cpu.pp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  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. {$IFNDEF FPC_DOTTEDUNITS}
  14. unit cpu;
  15. {$ENDIF FPC_DOTTEDUNITS}
  16. interface
  17. {$ifdef freebsd} // FreeBSD 7/8 have binutils version that don't support cmpxchg16b
  18. // Unless overridebinutils is defined (for ports usage), use db instead of the instruction
  19. {$ifndef overridebinutils}
  20. {$define oldbinutils}
  21. {$endif}
  22. {$endif}
  23. {$IFDEF FPC_DOTTEDUNITS}
  24. uses
  25. System.SysUtils;
  26. {$ELSE FPC_DOTTEDUNITS}
  27. uses
  28. sysutils;
  29. {$ENDIF FPC_DOTTEDUNITS}
  30. function InterlockedCompareExchange128Support : boolean;inline;
  31. function CMOVSupport : boolean;inline;
  32. function AESSupport : boolean;inline;
  33. function AVXSupport : boolean;inline;
  34. function AVX2Support: boolean;inline;
  35. function AVX512FSupport: boolean;inline;
  36. function AVX512DQSupport: boolean;inline;
  37. function AVX512IFMASupport: boolean;inline;
  38. function AVX512PFSupport: boolean;inline;
  39. function AVX512ERSupport: boolean;inline;
  40. function AVX512CDSupport: boolean;inline;
  41. function AVX512BWSupport: boolean;inline;
  42. function AVX512VLSupport: boolean;inline;
  43. function AVX512VBMISupport: boolean;inline;
  44. function AVX512VBMI2Support: boolean;inline;
  45. function AVX512VNNISupport: boolean;inline;
  46. function VAESSupport: boolean;inline;
  47. function VCLMULSupport: boolean;inline;
  48. function AVX512BITALGSupport: boolean;inline;
  49. function RDSEEDSupport: boolean;inline;
  50. function ADXSupport: boolean;inline;
  51. function SHASupport: boolean;inline;
  52. function FMASupport: boolean;inline;
  53. function POPCNTSupport: boolean;inline;
  54. function LZCNTSupport: boolean;inline;
  55. function SSE3Support: boolean;inline;
  56. function SSSE3Support: boolean;inline;
  57. function SSE41Support: boolean;inline;
  58. function SSE42Support: boolean;inline;
  59. function MOVBESupport: boolean;inline;
  60. function F16CSupport: boolean;inline;
  61. function RDRANDSupport: boolean;inline;
  62. function RTMSupport: boolean;inline;
  63. function BMI1Support: boolean;inline;
  64. function BMI2Support: boolean;inline;
  65. var
  66. is_sse3_cpu : boolean = false;
  67. function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec;
  68. implementation
  69. {$asmmode att}
  70. var
  71. _AESSupport,
  72. _AVXSupport,
  73. _InterlockedCompareExchange128Support,
  74. _AVX2Support,
  75. _AVX512FSupport,
  76. _AVX512DQSupport,
  77. _AVX512IFMASupport,
  78. _AVX512PFSupport,
  79. _AVX512ERSupport,
  80. _AVX512CDSupport,
  81. _AVX512BWSupport,
  82. _AVX512VLSupport,
  83. _AVX512VBMISupport,
  84. _AVX512VBMI2Support,
  85. _VAESSupport,
  86. _VCLMULSupport,
  87. _AVX512VNNISupport,
  88. _AVX512BITALGSupport,
  89. _RDSEEDSupport,
  90. _ADXSupport,
  91. _SHASupport,
  92. _FMASupport,
  93. _POPCNTSupport,
  94. _LZCNTSupport,
  95. _SSE3Support,
  96. _SSSE3Support,
  97. _SSE41Support,
  98. _SSE42Support,
  99. _MOVBESupport,
  100. _F16CSupport,
  101. _RDRANDSupport,
  102. _RTMSupport,
  103. _BMI1Support,
  104. _BMI2Support: boolean;
  105. function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec; assembler;
  106. {
  107. win64:
  108. rcx ... pointer to result
  109. rdx ... target
  110. r8 ... NewValue
  111. r9 ... Comperand
  112. }
  113. {$ifdef win64}
  114. asm
  115. pushq %rbx
  116. { store result pointer for later use }
  117. pushq %rcx
  118. { load new value }
  119. movq (%r8),%rbx
  120. movq 8(%r8),%rcx
  121. { save target pointer for later use }
  122. movq %rdx,%r8
  123. { load comperand }
  124. movq (%r9),%rax
  125. movq 8(%r9),%rdx
  126. {$ifdef oldbinutils}
  127. .byte 0xF0,0x49,0x0F,0xC7,0x08
  128. {$else}
  129. lock cmpxchg16b (%r8)
  130. {$endif}
  131. { restore result pointer }
  132. popq %rcx
  133. { store result }
  134. movq %rax,(%rcx)
  135. movq %rdx,8(%rcx)
  136. popq %rbx
  137. end;
  138. {$else win64}
  139. {
  140. linux:
  141. rdi ... target
  142. [rsi:rdx] ... NewValue
  143. [rcx:r8] ... Comperand
  144. [rdx:rax] ... result
  145. }
  146. asm
  147. pushq %rbx
  148. movq %rsi,%rbx // new value low
  149. movq %rcx,%rax // comperand low
  150. movq %rdx,%rcx // new value high
  151. movq %r8,%rdx // comperand high
  152. {$ifdef oldbinutils}
  153. .byte 0xF0,0x48,0x0F,0xC7,0x0F
  154. {$else}
  155. lock cmpxchg16b (%rdi)
  156. {$endif}
  157. popq %rbx
  158. end;
  159. {$endif win64}
  160. function XGETBV(i : dword) : int64;assembler;
  161. asm
  162. {$ifndef win64}
  163. movq %rdi,%rcx
  164. {$endif win64}
  165. // older FPCs don't know the xgetbv opcode
  166. .byte 0x0f,0x01,0xd0
  167. andl $0xffffffff,%eax
  168. shlq $32,%rdx
  169. orq %rdx,%rax
  170. end;
  171. procedure SetupSupport;
  172. var
  173. _edx,
  174. _ecx,
  175. _ebx,maxcpuidvalue : longint;
  176. begin
  177. asm
  178. movl $0x0,%eax
  179. cpuid
  180. movl %eax,maxcpuidvalue
  181. end ['rax','rbx','rcx','rdx'];
  182. asm
  183. movl $0x00000001,%eax
  184. cpuid
  185. movl %ecx,_ecx
  186. end ['rax','rbx','rcx','rdx'];
  187. _InterlockedCompareExchange128Support:=(_ecx and $2000)<>0;
  188. _AESSupport:=(_ecx and $2000000)<>0;
  189. _POPCNTSupport:=(_ecx and $800000)<>0;
  190. _SSE3Support:=(_ecx and $1)<>0;
  191. _SSSE3Support:=(_ecx and $200)<>0;
  192. _SSE41Support:=(_ecx and $80000)<>0;
  193. _SSE42Support:=(_ecx and $100000)<>0;
  194. _MOVBESupport:=(_ecx and $400000)<>0;
  195. _F16CSupport:=(_ecx and $20000000)<>0;
  196. _RDRANDSupport:=(_ecx and $40000000)<>0;
  197. _AVXSupport:=
  198. { XGETBV suspport? }
  199. ((_ecx and $08000000)<>0) and
  200. { xmm and ymm state enabled? }
  201. ((XGETBV(0) and %110)=%110) and
  202. { avx supported? }
  203. ((_ecx and $10000000)<>0);
  204. is_sse3_cpu:=(_ecx and $1)<>0;
  205. _FMASupport:=_AVXSupport and ((_ecx and $1000)<>0);
  206. asm
  207. movl $0x80000001,%eax
  208. cpuid
  209. movl %ecx,_ecx
  210. movl %edx,_edx
  211. end;
  212. _LZCNTSupport:=(_ecx and $20)<>0;
  213. { very early x86-64 CPUs might not support eax=7 }
  214. if maxcpuidvalue>=7 then
  215. begin
  216. asm
  217. movl $7,%eax
  218. movl $0,%ecx
  219. cpuid
  220. movl %ebx,_ebx
  221. movl %ecx,_ecx
  222. movl %edx,_edx
  223. end ['rax','rbx','rcx','rdx'];
  224. _AVX2Support:=_AVXSupport and ((_ebx and $20)<>0);
  225. _AVX512FSupport:=(_ebx and $10000)<>0;
  226. _AVX512DQSupport:=(_ebx and $20000)<>0;
  227. _RDSEEDSupport:=(_ebx and $40000)<>0;
  228. _ADXSupport:=(_ebx and $80000)<>0;
  229. _AVX512IFMASupport:=(_ebx and $200000)<>0;
  230. _AVX512PFSupport:=(_ebx and $4000000)<>0;
  231. _AVX512ERSupport:=(_ebx and $8000000)<>0;
  232. _AVX512CDSupport:=(_ebx and $10000000)<>0;
  233. _SHASupport:=(_ebx and $20000000)<>0;
  234. _AVX512BWSupport:=(_ebx and $40000000)<>0;
  235. _AVX512VLSupport:=(_ebx and $80000000)<>0;
  236. _AVX512VBMISupport:=(_ecx and $00000002)<>0;
  237. _AVX512VBMI2Support:=(_ecx and $00000040)<>0;
  238. _VAESSupport:=(_ecx and $00000200)<>0;
  239. _VCLMULSupport:=(_ecx and $00000400)<>0;
  240. _AVX512VNNISupport:=(_ecx and $00000800)<>0;
  241. _AVX512BITALGSupport:=(_ecx and $00001000)<>0;
  242. _BMI1Support:=(_ebx and $8)<>0;
  243. _BMI2Support:=(_ebx and $100)<>0;
  244. _RTMSupport:=(_ebx and $800)<>0;
  245. end;
  246. end;
  247. function InterlockedCompareExchange128Support : boolean;inline;
  248. begin
  249. result:=_InterlockedCompareExchange128Support;
  250. end;
  251. function CMOVSupport : boolean;
  252. begin
  253. result:=true;
  254. end;
  255. function AESSupport : boolean;inline;
  256. begin
  257. result:=_AESSupport;
  258. end;
  259. function AVXSupport: boolean;inline;
  260. begin
  261. result:=_AVXSupport;
  262. end;
  263. function AVX2Support: boolean;inline;
  264. begin
  265. result:=_AVX2Support;
  266. end;
  267. function AVX512FSupport: boolean;inline;
  268. begin
  269. result:=_AVX512FSupport;
  270. end;
  271. function AVX512DQSupport: boolean;inline;
  272. begin
  273. result:=_AVX512DQSupport;
  274. end;
  275. function AVX512IFMASupport: boolean;inline;
  276. begin
  277. result:=_AVX512IFMASupport;
  278. end;
  279. function AVX512PFSupport: boolean;inline;
  280. begin
  281. result:=_AVX512PFSupport;
  282. end;
  283. function AVX512ERSupport: boolean;inline;
  284. begin
  285. result:=_AVX512ERSupport;
  286. end;
  287. function AVX512CDSupport: boolean;inline;
  288. begin
  289. result:=_AVX512CDSupport;
  290. end;
  291. function AVX512BWSupport: boolean;inline;
  292. begin
  293. result:=_AVX512BWSupport;
  294. end;
  295. function AVX512VLSupport: boolean;inline;
  296. begin
  297. result:=_AVX512VLSupport;
  298. end;
  299. function AVX512VBMISupport: boolean;inline;
  300. begin
  301. result:=_AVX512VBMISupport;
  302. end;
  303. function AVX512VBMI2Support: boolean;inline;
  304. begin
  305. result:=_AVX512VBMI2Support;
  306. end;
  307. function VAESSupport: boolean;inline;
  308. begin
  309. result:=_VAESSupport;
  310. end;
  311. function VCLMULSupport: boolean;inline;
  312. begin
  313. result:=_VCLMULSupport;
  314. end;
  315. function AVX512VNNISupport: boolean;inline;
  316. begin
  317. result:=_AVX512VNNISupport;
  318. end;
  319. function AVX512BITALGSupport: boolean;inline;
  320. begin
  321. result:=_AVX512BITALGSupport;
  322. end;
  323. function RDSEEDSupport: boolean;inline;
  324. begin
  325. result:=_RDSEEDSupport;
  326. end;
  327. function ADXSupport: boolean;inline;
  328. begin
  329. result:=_ADXSupport;
  330. end;
  331. function SHASupport: boolean;inline;
  332. begin
  333. result:=_SHASupport;
  334. end;
  335. function FMASupport: boolean;inline;
  336. begin
  337. result:=_FMASupport;
  338. end;
  339. function POPCNTSupport: boolean;inline;
  340. begin
  341. result:=_POPCNTSupport;
  342. end;
  343. function LZCNTSupport: boolean;inline;
  344. begin
  345. result:=_LZCNTSupport;
  346. end;
  347. function SSE3Support: boolean;inline;
  348. begin
  349. result:=_SSE3Support;
  350. end;
  351. function SSSE3Support: boolean;inline;
  352. begin
  353. result:=_SSSE3Support;
  354. end;
  355. function SSE41Support: boolean;inline;
  356. begin
  357. result:=_SSE41Support;
  358. end;
  359. function SSE42Support: boolean;inline;
  360. begin
  361. result:=_SSE42Support;
  362. end;
  363. function MOVBESupport: boolean;inline;
  364. begin
  365. result:=_MOVBESupport;
  366. end;
  367. function F16CSupport: boolean;inline;
  368. begin
  369. result:=_F16CSupport;
  370. end;
  371. function RDRANDSupport: boolean;inline;
  372. begin
  373. result:=_RDRANDSupport;
  374. end;
  375. function RTMSupport: boolean;inline;
  376. begin
  377. result:=_RTMSupport;
  378. end;
  379. function BMI1Support: boolean;inline;
  380. begin
  381. result:=_BMI1Support;
  382. end;
  383. function BMI2Support: boolean;inline;
  384. begin
  385. result:=_BMI2Support;
  386. end;
  387. begin
  388. SetupSupport;
  389. end.