cpu.pp 8.6 KB

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