cpu.pp 9.4 KB

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