cpu.pp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Florian Klaempfl
  4. This unit contains some routines to get informations about the
  5. processor
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {$mode objfpc}
  13. unit cpu;
  14. interface
  15. {$ifdef freebsd} // FreeBSD 7/8 have binutils version that don't support cmpxchg16b
  16. // Unless overridebinutils is defined (for ports usage), use db instead of the instruction
  17. {$ifndef overridebinutils}
  18. {$define oldbinutils}
  19. {$endif}
  20. {$endif}
  21. uses
  22. sysutils;
  23. function InterlockedCompareExchange128Support : boolean;inline;
  24. function AESSupport : boolean;inline;
  25. function AVXSupport : boolean;inline;
  26. function AVX2Support: boolean;inline;
  27. function FMASupport: boolean;inline;
  28. function POPCNTSupport: boolean;inline;
  29. function SSE41Support: boolean;inline;
  30. function SSE42Support: boolean;inline;
  31. function MOVBESupport: boolean;inline;
  32. function F16CSupport: boolean;inline;
  33. function RDRANDSupport: boolean;inline;
  34. function RTMSupport: boolean;inline;
  35. var
  36. is_sse3_cpu : boolean = false;
  37. function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec;
  38. implementation
  39. {$asmmode att}
  40. var
  41. _AESSupport,
  42. _AVXSupport,
  43. _InterlockedCompareExchange128Support,
  44. _AVX2Support,
  45. _FMASupport,
  46. _POPCNTSupport,
  47. _SSE41Support,
  48. _SSE42Support,
  49. _MOVBESupport,
  50. _F16CSupport,
  51. _RDRANDSupport,
  52. _RTMSupport: boolean;
  53. function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec; assembler;
  54. {
  55. win64:
  56. rcx ... pointer to result
  57. rdx ... target
  58. r8 ... NewValue
  59. r9 ... Comperand
  60. }
  61. {$ifdef win64}
  62. asm
  63. pushq %rbx
  64. { store result pointer for later use }
  65. pushq %rcx
  66. { load new value }
  67. movq (%r8),%rbx
  68. movq 8(%r8),%rcx
  69. { save target pointer for later use }
  70. movq %rdx,%r8
  71. { load comperand }
  72. movq (%r9),%rax
  73. movq 8(%r9),%rdx
  74. {$ifdef oldbinutils}
  75. .byte 0xF0,0x49,0x0F,0xC7,0x08
  76. {$else}
  77. lock cmpxchg16b (%r8)
  78. {$endif}
  79. { restore result pointer }
  80. popq %rcx
  81. { store result }
  82. movq %rax,(%rcx)
  83. movq %rdx,8(%rcx)
  84. popq %rbx
  85. end;
  86. {$else win64}
  87. {
  88. linux:
  89. rdi ... target
  90. [rsi:rdx] ... NewValue
  91. [rcx:r8] ... Comperand
  92. [rdx:rax] ... result
  93. }
  94. asm
  95. pushq %rbx
  96. movq %rsi,%rbx // new value low
  97. movq %rcx,%rax // comperand low
  98. movq %rdx,%rcx // new value high
  99. movq %r8,%rdx // comperand high
  100. {$ifdef oldbinutils}
  101. .byte 0xF0,0x48,0x0F,0xC7,0x0F
  102. {$else}
  103. lock cmpxchg16b (%rdi)
  104. {$endif}
  105. popq %rbx
  106. end;
  107. {$endif win64}
  108. function XGETBV(i : dword) : int64;assembler;
  109. asm
  110. {$ifndef win64}
  111. movq %rdi,%rcx
  112. {$endif win64}
  113. // older FPCs don't know the xgetbv opcode
  114. .byte 0x0f,0x01,0xd0
  115. andl $0xffffffff,%eax
  116. shlq $32,%rdx
  117. orq %rdx,%rax
  118. end;
  119. procedure SetupSupport;
  120. var
  121. _ecx,
  122. _ebx : longint;
  123. begin
  124. asm
  125. movl $0x00000001,%eax
  126. cpuid
  127. movl %ecx,_ecx
  128. end ['rax','rbx','rcx','rdx'];
  129. _InterlockedCompareExchange128Support:=(_ecx and $2000)<>0;
  130. _AESSupport:=(_ecx and $2000000)<>0;
  131. _POPCNTSupport:=(_ecx and $800000)<>0;
  132. _SSE41Support:=(_ecx and $80000)<>0;
  133. _SSE42Support:=(_ecx and $100000)<>0;
  134. _MOVBESupport:=(_ecx and $400000)<>0;
  135. _F16CSupport:=(_ecx and $20000000)<>0;
  136. _RDRANDSupport:=(_ecx and $40000000)<>0;
  137. _AVXSupport:=
  138. { XGETBV suspport? }
  139. ((_ecx and $08000000)<>0) and
  140. { xmm and ymm state enabled? }
  141. ((XGETBV(0) and %110)=%110) and
  142. { avx supported? }
  143. ((_ecx and $10000000)<>0);
  144. is_sse3_cpu:=(_ecx and $1)<>0;
  145. _FMASupport:=_AVXSupport and ((_ecx and $1000)<>0);
  146. asm
  147. movl $7,%eax
  148. movl $0,%ecx
  149. cpuid
  150. movl %ebx,_ebx
  151. end ['rax','rbx','rcx','rdx'];
  152. _AVX2Support:=_AVXSupport and ((_ebx and $20)<>0);
  153. _RTMSupport:=((_ebx and $800)<>0);
  154. end;
  155. function InterlockedCompareExchange128Support : boolean;inline;
  156. begin
  157. result:=_InterlockedCompareExchange128Support;
  158. end;
  159. function AESSupport : boolean;inline;
  160. begin
  161. result:=_AESSupport;
  162. end;
  163. function AVXSupport: boolean;inline;
  164. begin
  165. result:=_AVXSupport;
  166. end;
  167. function AVX2Support: boolean;inline;
  168. begin
  169. result:=_AVX2Support;
  170. end;
  171. function FMASupport: boolean;inline;
  172. begin
  173. result:=_FMASupport;
  174. end;
  175. function POPCNTSupport: boolean;inline;
  176. begin
  177. result:=_POPCNTSupport;
  178. end;
  179. function SSE41Support: boolean;inline;
  180. begin
  181. result:=_SSE41Support;
  182. end;
  183. function SSE42Support: boolean;inline;
  184. begin
  185. result:=_SSE42Support;
  186. end;
  187. function MOVBESupport: boolean;inline;
  188. begin
  189. result:=_MOVBESupport;
  190. end;
  191. function F16CSupport: boolean;inline;
  192. begin
  193. result:=_F16CSupport;
  194. end;
  195. function RDRANDSupport: boolean;inline;
  196. begin
  197. result:=_RDRANDSupport;
  198. end;
  199. function RTMSupport: boolean;inline;
  200. begin
  201. result:=_RTMSupport;
  202. end;
  203. begin
  204. SetupSupport;
  205. end.