cpu.pp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  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 AVX512FSupport: boolean;inline;
  28. function AVX512DQSupport: boolean;inline;
  29. function AVX512IFMASupport: boolean;inline;
  30. function AVX512PFSupport: boolean;inline;
  31. function AVX512ERSupport: boolean;inline;
  32. function AVX512CDSupport: boolean;inline;
  33. function AVX512BWSupport: boolean;inline;
  34. function AVX512VLSupport: boolean;inline;
  35. function SHASupport: boolean;inline;
  36. function FMASupport: boolean;inline;
  37. function POPCNTSupport: boolean;inline;
  38. function SSE41Support: boolean;inline;
  39. function SSE42Support: boolean;inline;
  40. function MOVBESupport: boolean;inline;
  41. function F16CSupport: boolean;inline;
  42. function RDRANDSupport: boolean;inline;
  43. function RTMSupport: boolean;inline;
  44. function BMI1Support: boolean;inline;
  45. function BMI2Support: boolean;inline;
  46. var
  47. is_sse3_cpu : boolean = false;
  48. function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec;
  49. implementation
  50. {$asmmode att}
  51. var
  52. _AESSupport,
  53. _AVXSupport,
  54. _InterlockedCompareExchange128Support,
  55. _AVX2Support,
  56. _AVX512FSupport,
  57. _AVX512DQSupport,
  58. _AVX512IFMASupport,
  59. _AVX512PFSupport,
  60. _AVX512ERSupport,
  61. _AVX512CDSupport,
  62. _AVX512BWSupport,
  63. _AVX512VLSupport,
  64. _SHASupport,
  65. _FMASupport,
  66. _POPCNTSupport,
  67. _SSE41Support,
  68. _SSE42Support,
  69. _MOVBESupport,
  70. _F16CSupport,
  71. _RDRANDSupport,
  72. _RTMSupport,
  73. _BMI1Support,
  74. _BMI2Support: boolean;
  75. function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec; assembler;
  76. {
  77. win64:
  78. rcx ... pointer to result
  79. rdx ... target
  80. r8 ... NewValue
  81. r9 ... Comperand
  82. }
  83. {$ifdef win64}
  84. asm
  85. pushq %rbx
  86. { store result pointer for later use }
  87. pushq %rcx
  88. { load new value }
  89. movq (%r8),%rbx
  90. movq 8(%r8),%rcx
  91. { save target pointer for later use }
  92. movq %rdx,%r8
  93. { load comperand }
  94. movq (%r9),%rax
  95. movq 8(%r9),%rdx
  96. {$ifdef oldbinutils}
  97. .byte 0xF0,0x49,0x0F,0xC7,0x08
  98. {$else}
  99. lock cmpxchg16b (%r8)
  100. {$endif}
  101. { restore result pointer }
  102. popq %rcx
  103. { store result }
  104. movq %rax,(%rcx)
  105. movq %rdx,8(%rcx)
  106. popq %rbx
  107. end;
  108. {$else win64}
  109. {
  110. linux:
  111. rdi ... target
  112. [rsi:rdx] ... NewValue
  113. [rcx:r8] ... Comperand
  114. [rdx:rax] ... result
  115. }
  116. asm
  117. pushq %rbx
  118. movq %rsi,%rbx // new value low
  119. movq %rcx,%rax // comperand low
  120. movq %rdx,%rcx // new value high
  121. movq %r8,%rdx // comperand high
  122. {$ifdef oldbinutils}
  123. .byte 0xF0,0x48,0x0F,0xC7,0x0F
  124. {$else}
  125. lock cmpxchg16b (%rdi)
  126. {$endif}
  127. popq %rbx
  128. end;
  129. {$endif win64}
  130. function XGETBV(i : dword) : int64;assembler;
  131. asm
  132. {$ifndef win64}
  133. movq %rdi,%rcx
  134. {$endif win64}
  135. // older FPCs don't know the xgetbv opcode
  136. .byte 0x0f,0x01,0xd0
  137. andl $0xffffffff,%eax
  138. shlq $32,%rdx
  139. orq %rdx,%rax
  140. end;
  141. procedure SetupSupport;
  142. var
  143. _ecx,
  144. _ebx,maxcpuidvalue : longint;
  145. begin
  146. asm
  147. movl $0x0,%eax
  148. cpuid
  149. movl %eax,maxcpuidvalue
  150. end ['rax','rbx','rcx','rdx'];
  151. asm
  152. movl $0x00000001,%eax
  153. cpuid
  154. movl %ecx,_ecx
  155. end ['rax','rbx','rcx','rdx'];
  156. _InterlockedCompareExchange128Support:=(_ecx and $2000)<>0;
  157. _AESSupport:=(_ecx and $2000000)<>0;
  158. _POPCNTSupport:=(_ecx and $800000)<>0;
  159. _SSE41Support:=(_ecx and $80000)<>0;
  160. _SSE42Support:=(_ecx and $100000)<>0;
  161. _MOVBESupport:=(_ecx and $400000)<>0;
  162. _F16CSupport:=(_ecx and $20000000)<>0;
  163. _RDRANDSupport:=(_ecx and $40000000)<>0;
  164. _AVXSupport:=
  165. { XGETBV suspport? }
  166. ((_ecx and $08000000)<>0) and
  167. { xmm and ymm state enabled? }
  168. ((XGETBV(0) and %110)=%110) and
  169. { avx supported? }
  170. ((_ecx and $10000000)<>0);
  171. is_sse3_cpu:=(_ecx and $1)<>0;
  172. _FMASupport:=_AVXSupport and ((_ecx and $1000)<>0);
  173. { very early x86-64 CPUs might not support eax=7 }
  174. if maxcpuidvalue>=7 then
  175. begin
  176. asm
  177. movl $7,%eax
  178. movl $0,%ecx
  179. cpuid
  180. movl %ebx,_ebx
  181. end ['rax','rbx','rcx','rdx'];
  182. _AVX2Support:=_AVXSupport and ((_ebx and $20)<>0);
  183. _AVX512FSupport:=(_ebx and $10000)<>0;
  184. _AVX512DQSupport:=(_ebx and $20000)<>0;
  185. _AVX512IFMASupport:=(_ebx and $200000)<>0;
  186. _AVX512PFSupport:=(_ebx and $4000000)<>0;
  187. _AVX512ERSupport:=(_ebx and $8000000)<>0;
  188. _AVX512CDSupport:=(_ebx and $10000000)<>0;
  189. _SHASupport:=(_ebx and $20000000)<>0;
  190. _AVX512BWSupport:=(_ebx and $40000000)<>0;
  191. _AVX512VLSupport:=(_ebx and $80000000)<>0;
  192. _BMI1Support:=(_ebx and $8)<>0;
  193. _BMI2Support:=(_ebx and $100)<>0;
  194. _RTMSupport:=(_ebx and $800)<>0;
  195. end;
  196. end;
  197. function InterlockedCompareExchange128Support : boolean;inline;
  198. begin
  199. result:=_InterlockedCompareExchange128Support;
  200. end;
  201. function AESSupport : boolean;inline;
  202. begin
  203. result:=_AESSupport;
  204. end;
  205. function AVXSupport: boolean;inline;
  206. begin
  207. result:=_AVXSupport;
  208. end;
  209. function AVX2Support: boolean;inline;
  210. begin
  211. result:=_AVX2Support;
  212. end;
  213. function AVX512FSupport: boolean;inline;
  214. begin
  215. result:=_AVX512FSupport;
  216. end;
  217. function AVX512DQSupport: boolean;inline;
  218. begin
  219. result:=_AVX512DQSupport;
  220. end;
  221. function AVX512IFMASupport: boolean;inline;
  222. begin
  223. result:=_AVX512IFMASupport;
  224. end;
  225. function AVX512PFSupport: boolean;inline;
  226. begin
  227. result:=_AVX512PFSupport;
  228. end;
  229. function AVX512ERSupport: boolean;inline;
  230. begin
  231. result:=_AVX512ERSupport;
  232. end;
  233. function AVX512CDSupport: boolean;inline;
  234. begin
  235. result:=_AVX512CDSupport;
  236. end;
  237. function AVX512BWSupport: boolean;inline;
  238. begin
  239. result:=_AVX512BWSupport;
  240. end;
  241. function AVX512VLSupport: boolean;inline;
  242. begin
  243. result:=_AVX512VLSupport;
  244. end;
  245. function SHASupport: boolean;inline;
  246. begin
  247. result:=_SHASupport;
  248. end;
  249. function FMASupport: boolean;inline;
  250. begin
  251. result:=_FMASupport;
  252. end;
  253. function POPCNTSupport: boolean;inline;
  254. begin
  255. result:=_POPCNTSupport;
  256. end;
  257. function SSE41Support: boolean;inline;
  258. begin
  259. result:=_SSE41Support;
  260. end;
  261. function SSE42Support: boolean;inline;
  262. begin
  263. result:=_SSE42Support;
  264. end;
  265. function MOVBESupport: boolean;inline;
  266. begin
  267. result:=_MOVBESupport;
  268. end;
  269. function F16CSupport: boolean;inline;
  270. begin
  271. result:=_F16CSupport;
  272. end;
  273. function RDRANDSupport: boolean;inline;
  274. begin
  275. result:=_RDRANDSupport;
  276. end;
  277. function RTMSupport: boolean;inline;
  278. begin
  279. result:=_RTMSupport;
  280. end;
  281. function BMI1Support: boolean;inline;
  282. begin
  283. result:=_BMI1Support;
  284. end;
  285. function BMI2Support: boolean;inline;
  286. begin
  287. result:=_BMI2Support;
  288. end;
  289. begin
  290. SetupSupport;
  291. end.