cpu.pp 11 KB

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