cpu.pp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  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. {$goto on}
  14. unit cpu;
  15. interface
  16. uses
  17. sysutils;
  18. { returns true, if the processor supports the cpuid instruction }
  19. function cpuid_support : boolean;
  20. { returns true, if floating point is done by an emulator }
  21. function floating_point_emulation : boolean;
  22. { returns the contents of the cr0 register }
  23. function cr0 : longint;
  24. function CMOVSupport : boolean;inline;
  25. function InterlockedCompareExchange128Support : boolean;
  26. function AESSupport : boolean;inline;
  27. function AVXSupport: boolean;inline;
  28. function AVX2Support: boolean;inline;
  29. function AVX512FSupport: boolean;inline;
  30. function AVX512DQSupport: boolean;inline;
  31. function AVX512IFMASupport: boolean;inline;
  32. function AVX512PFSupport: boolean;inline;
  33. function AVX512ERSupport: boolean;inline;
  34. function AVX512CDSupport: boolean;inline;
  35. function AVX512BWSupport: boolean;inline;
  36. function AVX512VLSupport: boolean;inline;
  37. function AVX512VBMISupport: boolean;inline;
  38. function AVX512VBMI2Support: boolean;inline;
  39. function AVX512VNNISupport: boolean;inline;
  40. function VAESSupport: boolean;inline;
  41. function VCLMULSupport: boolean;inline;
  42. function AVX512BITALGSupport: boolean;inline;
  43. function RDSEEDSupport: boolean;inline;
  44. function ADXSupport: boolean;inline;
  45. function SHASupport: boolean;inline;
  46. function FMASupport: boolean;inline;
  47. function POPCNTSupport: boolean;inline;
  48. function LZCNTSupport: boolean;inline;
  49. function SSE3Support: boolean;inline;
  50. function SSSE3Support: boolean;inline;
  51. function SSE41Support: boolean;inline;
  52. function SSE42Support: boolean;inline;
  53. function MOVBESupport: boolean;inline;
  54. function F16CSupport: boolean;inline;
  55. function RDRANDSupport: boolean;inline;
  56. function RTMSupport: boolean;inline;
  57. function BMI1Support: boolean;inline;
  58. function BMI2Support: boolean;inline;
  59. var
  60. is_sse3_cpu : boolean = false;
  61. function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec;
  62. implementation
  63. {$ASMMODE INTEL}
  64. var
  65. _CMOVSupport,
  66. _AESSupport,
  67. _AVXSupport,
  68. _AVX2Support,
  69. _AVX512FSupport,
  70. _AVX512DQSupport,
  71. _AVX512IFMASupport,
  72. _AVX512PFSupport,
  73. _AVX512ERSupport,
  74. _AVX512CDSupport,
  75. _AVX512BWSupport,
  76. _AVX512VLSupport,
  77. _AVX512VBMISupport,
  78. _AVX512VBMI2Support,
  79. _VAESSupport,
  80. _VCLMULSupport,
  81. _AVX512VNNISupport,
  82. _AVX512BITALGSupport,
  83. _RDSEEDSupport,
  84. _ADXSupport,
  85. _SHASupport,
  86. _FMASupport,
  87. _POPCNTSupport,
  88. _LZCNTSupport,
  89. _SSE3Support,
  90. _SSSE3Support,
  91. _SSE41Support,
  92. _SSE42Support,
  93. _MOVBESupport,
  94. _F16CSupport,
  95. _RDRANDSupport,
  96. _RTMSupport,
  97. _BMI1Support,
  98. _BMI2Support: boolean;
  99. {$ASMMODE ATT}
  100. function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec;
  101. begin
  102. {$if FPC_FULLVERSION >= 30101}
  103. {$ifndef FPC_PIC}
  104. if _RTMSupport then
  105. begin
  106. asm
  107. {$ifdef USE_REAL_INSTRUCTIONS}
  108. .Lretry:
  109. xbegin .Lretry
  110. {$else}
  111. { 3d: c7 f8 fa ff ff ff xbegin }
  112. .byte 0xc7,0xf8, 0xfa, 0xff, 0xff, 0xff
  113. {$endif}
  114. end;
  115. Result:=Target;
  116. if (Result.Lo=Comperand.Lo) and (Result.Hi=Comperand.Hi) then
  117. Target:=NewValue;
  118. asm
  119. {$ifdef USE_REAL_INSTRUCTIONS}
  120. xend
  121. {$else}
  122. { 8a: 0f 01 d5 xend }
  123. .byte 0x0f, 0x01, 0xd5
  124. {$endif}
  125. end;
  126. end
  127. else
  128. {$endif FPC_PIC}
  129. {$endif FPC_FULLVERSION >= 30101}
  130. RunError(217);
  131. end;
  132. {$ASMMODE INTEL}
  133. function cpuid_support : boolean;assembler;
  134. {
  135. Check if the ID-flag can be changed, if changed then CpuID is supported.
  136. Tested under go32v1 and Linux on c6x86 with CpuID enabled and disabled (PFV)
  137. }
  138. asm
  139. push ebx
  140. pushfd
  141. pushfd
  142. pop eax
  143. mov ebx,eax
  144. xor eax,200000h
  145. push eax
  146. popfd
  147. pushfd
  148. pop eax
  149. popfd
  150. and eax,200000h
  151. and ebx,200000h
  152. cmp eax,ebx
  153. setnz al
  154. pop ebx
  155. end;
  156. function cr0 : longint;assembler;
  157. asm
  158. {$ifdef USE_REAL_INSTRUCTIONS}
  159. mov eax,cr0
  160. {$else}
  161. DB 0Fh,20h,0C0h
  162. {$endif}
  163. { mov eax,cr0
  164. special registers are not allowed in the assembler
  165. parsers }
  166. end;
  167. function floating_point_emulation : boolean;
  168. begin
  169. {!!!! I don't know currently the position of the EM flag }
  170. { $4 after Ralf Brown's list }
  171. floating_point_emulation:=(cr0 and $4)<>0;
  172. end;
  173. {$ASMMODE ATT}
  174. function XGETBV(i : dword) : int64;assembler;
  175. asm
  176. movl %eax,%ecx
  177. {$ifdef USE_REAL_INSTRUCTIONS}
  178. xgetbv
  179. {$else}
  180. // older FPCs don't know the xgetbv opcode
  181. .byte 0x0f,0x01,0xd0
  182. {$endif}
  183. end;
  184. procedure SetupSupport;
  185. var
  186. _edx,_ecx,_ebx,maxcpuidvalue : longint;
  187. begin
  188. is_sse3_cpu:=false;
  189. if cpuid_support then
  190. begin
  191. asm
  192. pushl %ebx
  193. movl $0,%eax
  194. cpuid
  195. movl %eax,maxcpuidvalue
  196. popl %ebx
  197. end;
  198. asm
  199. pushl %ebx
  200. movl $1,%eax
  201. cpuid
  202. movl %edx,_edx
  203. movl %ecx,_ecx
  204. popl %ebx
  205. end;
  206. _CMOVSupport:=(_edx and $8000)<>0;
  207. _AESSupport:=(_ecx and $2000000)<>0;
  208. _POPCNTSupport:=(_ecx and $800000)<>0;
  209. _SSE3Support:=(_ecx and $1)<>0;
  210. _SSSE3Support:=(_ecx and $200)<>0;
  211. _SSE41Support:=(_ecx and $80000)<>0;
  212. _SSE42Support:=(_ecx and $100000)<>0;
  213. _MOVBESupport:=(_ecx and $400000)<>0;
  214. _F16CSupport:=(_ecx and $20000000)<>0;
  215. _RDRANDSupport:=(_ecx and $40000000)<>0;
  216. _AVXSupport:=
  217. { XGETBV suspport? }
  218. ((_ecx and $08000000)<>0) and
  219. { xmm and ymm state enabled? }
  220. ((XGETBV(0) and %110)=%110) and
  221. { avx supported? }
  222. ((_ecx and $10000000)<>0);
  223. is_sse3_cpu:=(_ecx and $1)<>0;
  224. _FMASupport:=_AVXSupport and ((_ecx and $1000)<>0);
  225. asm
  226. pushl %ebx
  227. movl $0x80000001,%eax
  228. cpuid
  229. movl %ecx,_ecx
  230. movl %edx,_edx
  231. popl %ebx
  232. end;
  233. _LZCNTSupport:=(_ecx and $20)<>0;
  234. if maxcpuidvalue>=7 then
  235. begin
  236. asm
  237. pushl %ebx
  238. movl $7,%eax
  239. movl $0,%ecx
  240. cpuid
  241. movl %ebx,_ebx
  242. movl %ecx,_ecx
  243. movl %edx,_edx
  244. popl %ebx
  245. end;
  246. _AVX2Support:=_AVXSupport and ((_ebx and $20)<>0);
  247. _AVX512FSupport:=(_ebx and $10000)<>0;
  248. _AVX512DQSupport:=(_ebx and $20000)<>0;
  249. _RDSEEDSupport:=(_ebx and $40000)<>0;
  250. _ADXSupport:=(_ebx and $80000)<>0;
  251. _AVX512IFMASupport:=(_ebx and $200000)<>0;
  252. _AVX512PFSupport:=(_ebx and $4000000)<>0;
  253. _AVX512ERSupport:=(_ebx and $8000000)<>0;
  254. _AVX512CDSupport:=(_ebx and $10000000)<>0;
  255. _AVX512BWSupport:=(_ebx and $40000000)<>0;
  256. _AVX512VBMISupport:=(_ecx and $00000002)<>0;
  257. _AVX512VBMI2Support:=(_ecx and $00000040)<>0;
  258. _VAESSupport:=(_ecx and $00000200)<>0;
  259. _VCLMULSupport:=(_ecx and $00000400)<>0;
  260. _AVX512VNNISupport:=(_ecx and $00000800)<>0;
  261. _AVX512BITALGSupport:=(_ecx and $00001000)<>0;
  262. _SHASupport:=(_ebx and $20000000)<>0;
  263. _AVX512VLSupport:=(_ebx and $80000000)<>0;
  264. _BMI1Support:=(_ebx and $8)<>0;
  265. _BMI2Support:=(_ebx and $100)<>0;
  266. _RTMSupport:=((_ebx and $800)<>0);
  267. end;
  268. end;
  269. end;
  270. function InterlockedCompareExchange128Support : boolean;
  271. begin
  272. { 32 Bit CPUs have no 128 Bit interlocked exchange support,
  273. but it can simulated using RTM }
  274. result:=_RTMSupport;
  275. end;
  276. function CMOVSupport : boolean;
  277. begin
  278. result:=_CMOVSupport;
  279. end;
  280. function AESSupport : boolean;
  281. begin
  282. result:=_AESSupport;
  283. end;
  284. function AVXSupport: boolean;inline;
  285. begin
  286. result:=_AVXSupport;
  287. end;
  288. function AVX2Support: boolean;inline;
  289. begin
  290. result:=_AVX2Support;
  291. end;
  292. function AVX512FSupport: boolean;inline;
  293. begin
  294. result:=_AVX512FSupport;
  295. end;
  296. function AVX512DQSupport: boolean;inline;
  297. begin
  298. result:=_AVX512DQSupport;
  299. end;
  300. function AVX512IFMASupport: boolean;inline;
  301. begin
  302. result:=_AVX512IFMASupport;
  303. end;
  304. function AVX512PFSupport: boolean;inline;
  305. begin
  306. result:=_AVX512PFSupport;
  307. end;
  308. function AVX512ERSupport: boolean;inline;
  309. begin
  310. result:=_AVX512ERSupport;
  311. end;
  312. function AVX512CDSupport: boolean;inline;
  313. begin
  314. result:=_AVX512CDSupport;
  315. end;
  316. function AVX512BWSupport: boolean;inline;
  317. begin
  318. result:=_AVX512BWSupport;
  319. end;
  320. function AVX512VLSupport: boolean;inline;
  321. begin
  322. result:=_AVX512VLSupport;
  323. end;
  324. function AVX512VBMISupport: boolean;inline;
  325. begin
  326. result:=_AVX512VBMISupport;
  327. end;
  328. function AVX512VBMI2Support: boolean;inline;
  329. begin
  330. result:=_AVX512VBMI2Support;
  331. end;
  332. function VAESSupport: boolean;inline;
  333. begin
  334. result:=_VAESSupport;
  335. end;
  336. function VCLMULSupport: boolean;inline;
  337. begin
  338. result:=_VCLMULSupport;
  339. end;
  340. function AVX512VNNISupport: boolean;inline;
  341. begin
  342. result:=_AVX512VNNISupport;
  343. end;
  344. function AVX512BITALGSupport: boolean;inline;
  345. begin
  346. result:=_AVX512BITALGSupport;
  347. end;
  348. function RDSEEDSupport: boolean;inline;
  349. begin
  350. result:=_RDSEEDSupport;
  351. end;
  352. function ADXSupport: boolean;inline;
  353. begin
  354. result:=_ADXSupport;
  355. end;
  356. function SHASupport: boolean;inline;
  357. begin
  358. result:=_SHASupport;
  359. end;
  360. function FMASupport: boolean;inline;
  361. begin
  362. result:=_FMASupport;
  363. end;
  364. function POPCNTSupport: boolean;inline;
  365. begin
  366. result:=_POPCNTSupport;
  367. end;
  368. function LZCNTSupport: boolean;inline;
  369. begin
  370. result:=_LZCNTSupport;
  371. end;
  372. function SSE3Support: boolean;inline;
  373. begin
  374. result:=_SSE3Support;
  375. end;
  376. function SSSE3Support: boolean;inline;
  377. begin
  378. result:=_SSSE3Support;
  379. end;
  380. function SSE41Support: boolean;inline;
  381. begin
  382. result:=_SSE41Support;
  383. end;
  384. function SSE42Support: boolean;inline;
  385. begin
  386. result:=_SSE42Support;
  387. end;
  388. function MOVBESupport: boolean;inline;
  389. begin
  390. result:=_MOVBESupport;
  391. end;
  392. function F16CSupport: boolean;inline;
  393. begin
  394. result:=_F16CSupport;
  395. end;
  396. function RDRANDSupport: boolean;inline;
  397. begin
  398. result:=_RDRANDSupport;
  399. end;
  400. function RTMSupport: boolean;inline;
  401. begin
  402. result:=_RTMSupport;
  403. end;
  404. function BMI1Support: boolean;inline;
  405. begin
  406. result:=_BMI1Support;
  407. end;
  408. function BMI2Support: boolean;inline;
  409. begin
  410. result:=_BMI2Support;
  411. end;
  412. begin
  413. SetupSupport;
  414. end.