cpu.pp 10 KB

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