cpu.pp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  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 CMOVSupport : boolean;inline;
  25. function AESSupport : boolean;inline;
  26. function AVXSupport : boolean;inline;
  27. function AVX2Support: boolean;inline;
  28. function AVX512FSupport: boolean;inline;
  29. function AVX512DQSupport: boolean;inline;
  30. function AVX512IFMASupport: boolean;inline;
  31. function AVX512PFSupport: boolean;inline;
  32. function AVX512ERSupport: boolean;inline;
  33. function AVX512CDSupport: boolean;inline;
  34. function AVX512BWSupport: boolean;inline;
  35. function AVX512VLSupport: boolean;inline;
  36. function AVX512VBMISupport: boolean;inline;
  37. function AVX512VBMI2Support: boolean;inline;
  38. function AVX512VNNISupport: boolean;inline;
  39. function VAESSupport: boolean;inline;
  40. function VCLMULSupport: boolean;inline;
  41. function AVX512BITALGSupport: boolean;inline;
  42. function RDSEEDSupport: boolean;inline;
  43. function ADXSupport: boolean;inline;
  44. function SHASupport: boolean;inline;
  45. function FMASupport: boolean;inline;
  46. function POPCNTSupport: boolean;inline;
  47. function LZCNTSupport: boolean;inline;
  48. function SSE3Support: boolean;inline;
  49. function SSSE3Support: boolean;inline;
  50. function SSE41Support: boolean;inline;
  51. function SSE42Support: boolean;inline;
  52. function MOVBESupport: boolean;inline;
  53. function F16CSupport: boolean;inline;
  54. function RDRANDSupport: boolean;inline;
  55. function RTMSupport: boolean;inline;
  56. function BMI1Support: boolean;inline;
  57. function BMI2Support: boolean;inline;
  58. var
  59. is_sse3_cpu : boolean = false;
  60. function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec;
  61. implementation
  62. {$asmmode att}
  63. var
  64. _AESSupport,
  65. _AVXSupport,
  66. _InterlockedCompareExchange128Support,
  67. _AVX2Support,
  68. _AVX512FSupport,
  69. _AVX512DQSupport,
  70. _AVX512IFMASupport,
  71. _AVX512PFSupport,
  72. _AVX512ERSupport,
  73. _AVX512CDSupport,
  74. _AVX512BWSupport,
  75. _AVX512VLSupport,
  76. _AVX512VBMISupport,
  77. _AVX512VBMI2Support,
  78. _VAESSupport,
  79. _VCLMULSupport,
  80. _AVX512VNNISupport,
  81. _AVX512BITALGSupport,
  82. _RDSEEDSupport,
  83. _ADXSupport,
  84. _SHASupport,
  85. _FMASupport,
  86. _POPCNTSupport,
  87. _LZCNTSupport,
  88. _SSE3Support,
  89. _SSSE3Support,
  90. _SSE41Support,
  91. _SSE42Support,
  92. _MOVBESupport,
  93. _F16CSupport,
  94. _RDRANDSupport,
  95. _RTMSupport,
  96. _BMI1Support,
  97. _BMI2Support: boolean;
  98. function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec; assembler;
  99. {
  100. win64:
  101. rcx ... pointer to result
  102. rdx ... target
  103. r8 ... NewValue
  104. r9 ... Comperand
  105. }
  106. {$ifdef win64}
  107. asm
  108. pushq %rbx
  109. { store result pointer for later use }
  110. pushq %rcx
  111. { load new value }
  112. movq (%r8),%rbx
  113. movq 8(%r8),%rcx
  114. { save target pointer for later use }
  115. movq %rdx,%r8
  116. { load comperand }
  117. movq (%r9),%rax
  118. movq 8(%r9),%rdx
  119. {$ifdef oldbinutils}
  120. .byte 0xF0,0x49,0x0F,0xC7,0x08
  121. {$else}
  122. lock cmpxchg16b (%r8)
  123. {$endif}
  124. { restore result pointer }
  125. popq %rcx
  126. { store result }
  127. movq %rax,(%rcx)
  128. movq %rdx,8(%rcx)
  129. popq %rbx
  130. end;
  131. {$else win64}
  132. {
  133. linux:
  134. rdi ... target
  135. [rsi:rdx] ... NewValue
  136. [rcx:r8] ... Comperand
  137. [rdx:rax] ... result
  138. }
  139. asm
  140. pushq %rbx
  141. movq %rsi,%rbx // new value low
  142. movq %rcx,%rax // comperand low
  143. movq %rdx,%rcx // new value high
  144. movq %r8,%rdx // comperand high
  145. {$ifdef oldbinutils}
  146. .byte 0xF0,0x48,0x0F,0xC7,0x0F
  147. {$else}
  148. lock cmpxchg16b (%rdi)
  149. {$endif}
  150. popq %rbx
  151. end;
  152. {$endif win64}
  153. function XGETBV(i : dword) : int64;assembler;
  154. asm
  155. {$ifndef win64}
  156. movq %rdi,%rcx
  157. {$endif win64}
  158. // older FPCs don't know the xgetbv opcode
  159. .byte 0x0f,0x01,0xd0
  160. andl $0xffffffff,%eax
  161. shlq $32,%rdx
  162. orq %rdx,%rax
  163. end;
  164. procedure SetupSupport;
  165. var
  166. _edx,
  167. _ecx,
  168. _ebx,maxcpuidvalue : longint;
  169. begin
  170. asm
  171. movl $0x0,%eax
  172. cpuid
  173. movl %eax,maxcpuidvalue
  174. end ['rax','rbx','rcx','rdx'];
  175. asm
  176. movl $0x00000001,%eax
  177. cpuid
  178. movl %ecx,_ecx
  179. end ['rax','rbx','rcx','rdx'];
  180. _InterlockedCompareExchange128Support:=(_ecx and $2000)<>0;
  181. _AESSupport:=(_ecx and $2000000)<>0;
  182. _POPCNTSupport:=(_ecx and $800000)<>0;
  183. _SSE3Support:=(_ecx and $1)<>0;
  184. _SSSE3Support:=(_ecx and $200)<>0;
  185. _SSE41Support:=(_ecx and $80000)<>0;
  186. _SSE42Support:=(_ecx and $100000)<>0;
  187. _MOVBESupport:=(_ecx and $400000)<>0;
  188. _F16CSupport:=(_ecx and $20000000)<>0;
  189. _RDRANDSupport:=(_ecx and $40000000)<>0;
  190. _AVXSupport:=
  191. { XGETBV suspport? }
  192. ((_ecx and $08000000)<>0) and
  193. { xmm and ymm state enabled? }
  194. ((XGETBV(0) and %110)=%110) and
  195. { avx supported? }
  196. ((_ecx and $10000000)<>0);
  197. is_sse3_cpu:=(_ecx and $1)<>0;
  198. _FMASupport:=_AVXSupport and ((_ecx and $1000)<>0);
  199. asm
  200. movl $0x80000001,%eax
  201. cpuid
  202. movl %ecx,_ecx
  203. movl %edx,_edx
  204. end;
  205. _LZCNTSupport:=(_ecx and $20)<>0;
  206. { very early x86-64 CPUs might not support eax=7 }
  207. if maxcpuidvalue>=7 then
  208. begin
  209. asm
  210. movl $7,%eax
  211. movl $0,%ecx
  212. cpuid
  213. movl %ebx,_ebx
  214. movl %ecx,_ecx
  215. movl %edx,_edx
  216. end ['rax','rbx','rcx','rdx'];
  217. _AVX2Support:=_AVXSupport and ((_ebx and $20)<>0);
  218. _AVX512FSupport:=(_ebx and $10000)<>0;
  219. _AVX512DQSupport:=(_ebx and $20000)<>0;
  220. _RDSEEDSupport:=(_ebx and $40000)<>0;
  221. _ADXSupport:=(_ebx and $80000)<>0;
  222. _AVX512IFMASupport:=(_ebx and $200000)<>0;
  223. _AVX512PFSupport:=(_ebx and $4000000)<>0;
  224. _AVX512ERSupport:=(_ebx and $8000000)<>0;
  225. _AVX512CDSupport:=(_ebx and $10000000)<>0;
  226. _SHASupport:=(_ebx and $20000000)<>0;
  227. _AVX512BWSupport:=(_ebx and $40000000)<>0;
  228. _AVX512VLSupport:=(_ebx and $80000000)<>0;
  229. _AVX512VBMISupport:=(_ecx and $00000002)<>0;
  230. _AVX512VBMI2Support:=(_ecx and $00000040)<>0;
  231. _VAESSupport:=(_ecx and $00000200)<>0;
  232. _VCLMULSupport:=(_ecx and $00000400)<>0;
  233. _AVX512VNNISupport:=(_ecx and $00000800)<>0;
  234. _AVX512BITALGSupport:=(_ecx and $00001000)<>0;
  235. _BMI1Support:=(_ebx and $8)<>0;
  236. _BMI2Support:=(_ebx and $100)<>0;
  237. _RTMSupport:=(_ebx and $800)<>0;
  238. end;
  239. end;
  240. function InterlockedCompareExchange128Support : boolean;inline;
  241. begin
  242. result:=_InterlockedCompareExchange128Support;
  243. end;
  244. function CMOVSupport : boolean;
  245. begin
  246. result:=true;
  247. end;
  248. function AESSupport : boolean;inline;
  249. begin
  250. result:=_AESSupport;
  251. end;
  252. function AVXSupport: boolean;inline;
  253. begin
  254. result:=_AVXSupport;
  255. end;
  256. function AVX2Support: boolean;inline;
  257. begin
  258. result:=_AVX2Support;
  259. end;
  260. function AVX512FSupport: boolean;inline;
  261. begin
  262. result:=_AVX512FSupport;
  263. end;
  264. function AVX512DQSupport: boolean;inline;
  265. begin
  266. result:=_AVX512DQSupport;
  267. end;
  268. function AVX512IFMASupport: boolean;inline;
  269. begin
  270. result:=_AVX512IFMASupport;
  271. end;
  272. function AVX512PFSupport: boolean;inline;
  273. begin
  274. result:=_AVX512PFSupport;
  275. end;
  276. function AVX512ERSupport: boolean;inline;
  277. begin
  278. result:=_AVX512ERSupport;
  279. end;
  280. function AVX512CDSupport: boolean;inline;
  281. begin
  282. result:=_AVX512CDSupport;
  283. end;
  284. function AVX512BWSupport: boolean;inline;
  285. begin
  286. result:=_AVX512BWSupport;
  287. end;
  288. function AVX512VLSupport: boolean;inline;
  289. begin
  290. result:=_AVX512VLSupport;
  291. end;
  292. function AVX512VBMISupport: boolean;inline;
  293. begin
  294. result:=_AVX512VBMISupport;
  295. end;
  296. function AVX512VBMI2Support: boolean;inline;
  297. begin
  298. result:=_AVX512VBMI2Support;
  299. end;
  300. function VAESSupport: boolean;inline;
  301. begin
  302. result:=_VAESSupport;
  303. end;
  304. function VCLMULSupport: boolean;inline;
  305. begin
  306. result:=_VCLMULSupport;
  307. end;
  308. function AVX512VNNISupport: boolean;inline;
  309. begin
  310. result:=_AVX512VNNISupport;
  311. end;
  312. function AVX512BITALGSupport: boolean;inline;
  313. begin
  314. result:=_AVX512BITALGSupport;
  315. end;
  316. function RDSEEDSupport: boolean;inline;
  317. begin
  318. result:=_RDSEEDSupport;
  319. end;
  320. function ADXSupport: boolean;inline;
  321. begin
  322. result:=_ADXSupport;
  323. end;
  324. function SHASupport: boolean;inline;
  325. begin
  326. result:=_SHASupport;
  327. end;
  328. function FMASupport: boolean;inline;
  329. begin
  330. result:=_FMASupport;
  331. end;
  332. function POPCNTSupport: boolean;inline;
  333. begin
  334. result:=_POPCNTSupport;
  335. end;
  336. function LZCNTSupport: boolean;inline;
  337. begin
  338. result:=_LZCNTSupport;
  339. end;
  340. function SSE3Support: boolean;inline;
  341. begin
  342. result:=_SSE3Support;
  343. end;
  344. function SSSE3Support: boolean;inline;
  345. begin
  346. result:=_SSSE3Support;
  347. end;
  348. function SSE41Support: boolean;inline;
  349. begin
  350. result:=_SSE41Support;
  351. end;
  352. function SSE42Support: boolean;inline;
  353. begin
  354. result:=_SSE42Support;
  355. end;
  356. function MOVBESupport: boolean;inline;
  357. begin
  358. result:=_MOVBESupport;
  359. end;
  360. function F16CSupport: boolean;inline;
  361. begin
  362. result:=_F16CSupport;
  363. end;
  364. function RDRANDSupport: boolean;inline;
  365. begin
  366. result:=_RDRANDSupport;
  367. end;
  368. function RTMSupport: boolean;inline;
  369. begin
  370. result:=_RTMSupport;
  371. end;
  372. function BMI1Support: boolean;inline;
  373. begin
  374. result:=_BMI1Support;
  375. end;
  376. function BMI2Support: boolean;inline;
  377. begin
  378. result:=_BMI2Support;
  379. end;
  380. begin
  381. SetupSupport;
  382. end.