cpu.pp 11 KB

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