cpu.pp 12 KB

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