cpu.pp 9.5 KB

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