cpu.pp 11 KB

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