cpu.pp 13 KB

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