cpu.pp 10 KB

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