cpu.pp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  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 FMASupport: boolean;inline;
  28. function POPCNTSupport: boolean;inline;
  29. function SSE41Support: boolean;inline;
  30. function SSE42Support: boolean;inline;
  31. function MOVBESupport: boolean;inline;
  32. function F16CSupport: boolean;inline;
  33. function RDRANDSupport: boolean;inline;
  34. var
  35. is_sse3_cpu : boolean = false;
  36. function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec;
  37. implementation
  38. {$asmmode att}
  39. var
  40. _AESSupport,
  41. _AVXSupport,
  42. _InterlockedCompareExchange128Support,
  43. _AVX2Support,
  44. _FMASupport,
  45. _POPCNTSupport,
  46. _SSE41Support,
  47. _SSE42Support,
  48. _MOVBESupport,
  49. _F16CSupport,
  50. _RDRANDSupport: boolean;
  51. function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec; assembler;
  52. {
  53. win64:
  54. rcx ... pointer to result
  55. rdx ... target
  56. r8 ... NewValue
  57. r9 ... Comperand
  58. }
  59. {$ifdef win64}
  60. asm
  61. pushq %rbx
  62. { store result pointer for later use }
  63. pushq %rcx
  64. { load new value }
  65. movq (%r8),%rbx
  66. movq 8(%r8),%rcx
  67. { save target pointer for later use }
  68. movq %rdx,%r8
  69. { load comperand }
  70. movq (%r9),%rax
  71. movq 8(%r9),%rdx
  72. {$ifdef oldbinutils}
  73. .byte 0xF0,0x49,0x0F,0xC7,0x08
  74. {$else}
  75. lock cmpxchg16b (%r8)
  76. {$endif}
  77. { restore result pointer }
  78. popq %rcx
  79. { store result }
  80. movq %rax,(%rcx)
  81. movq %rdx,8(%rcx)
  82. popq %rbx
  83. end;
  84. {$else win64}
  85. {
  86. linux:
  87. rdi ... target
  88. [rsi:rdx] ... NewValue
  89. [rcx:r8] ... Comperand
  90. [rdx:rax] ... result
  91. }
  92. asm
  93. pushq %rbx
  94. movq %rsi,%rbx // new value low
  95. movq %rcx,%rax // comperand low
  96. movq %rdx,%rcx // new value high
  97. movq %r8,%rdx // comperand high
  98. {$ifdef oldbinutils}
  99. .byte 0xF0,0x48,0x0F,0xC7,0x0F
  100. {$else}
  101. lock cmpxchg16b (%rdi)
  102. {$endif}
  103. popq %rbx
  104. end;
  105. {$endif win64}
  106. function XGETBV(i : dword) : int64;assembler;
  107. asm
  108. {$ifndef win64}
  109. movq %rdi,%rcx
  110. {$endif win64}
  111. // older FPCs don't know the xgetbv opcode
  112. .byte 0x0f,0x01,0xd0
  113. andl $0xffffffff,%eax
  114. shlq $32,%rdx
  115. orq %rdx,%rax
  116. end;
  117. procedure SetupSupport;
  118. var
  119. _ecx,
  120. _ebx : longint;
  121. begin
  122. asm
  123. movl $0x00000001,%eax
  124. cpuid
  125. movl %ecx,_ecx
  126. end ['rax','rbx','rcx','rdx'];
  127. _InterlockedCompareExchange128Support:=(_ecx and $2000)<>0;
  128. _AESSupport:=(_ecx and $2000000)<>0;
  129. _POPCNTSupport:=(_ecx and $800000)<>0;
  130. _SSE41Support:=(_ecx and $80000)<>0;
  131. _SSE42Support:=(_ecx and $100000)<>0;
  132. _MOVBESupport:=(_ecx and $400000)<>0;
  133. _F16CSupport:=(_ecx and $20000000)<>0;
  134. _RDRANDSupport:=(_ecx and $40000000)<>0;
  135. _AVXSupport:=
  136. { XGETBV suspport? }
  137. ((_ecx and $08000000)<>0) and
  138. { xmm and ymm state enabled? }
  139. ((XGETBV(0) and %110)=%110) and
  140. { avx supported? }
  141. ((_ecx and $10000000)<>0);
  142. is_sse3_cpu:=(_ecx and $1)<>0;
  143. _FMASupport:=_AVXSupport and ((_ecx and $1000)<>0);
  144. asm
  145. movl $7,%eax
  146. movl $0,%ecx
  147. cpuid
  148. movl %ebx,_ebx
  149. end ['rax','rbx','rcx','rdx'];
  150. _AVX2Support:=_AVXSupport and ((_ebx and $20)<>0);
  151. end;
  152. function InterlockedCompareExchange128Support : boolean;inline;
  153. begin
  154. result:=_InterlockedCompareExchange128Support;
  155. end;
  156. function AESSupport : boolean;inline;
  157. begin
  158. result:=_AESSupport;
  159. end;
  160. function AVXSupport: boolean;inline;
  161. begin
  162. result:=_AVXSupport;
  163. end;
  164. function AVX2Support: boolean;inline;
  165. begin
  166. result:=_AVX2Support;
  167. end;
  168. function FMASupport: boolean;inline;
  169. begin
  170. result:=_FMASupport;
  171. end;
  172. function POPCNTSupport: boolean;inline;
  173. begin
  174. result:=_POPCNTSupport;
  175. end;
  176. function SSE41Support: boolean;inline;
  177. begin
  178. result:=_SSE41Support;
  179. end;
  180. function SSE42Support: boolean;inline;
  181. begin
  182. result:=_SSE42Support;
  183. end;
  184. function MOVBESupport: boolean;inline;
  185. begin
  186. result:=_MOVBESupport;
  187. end;
  188. function F16CSupport: boolean;inline;
  189. begin
  190. result:=_F16CSupport;
  191. end;
  192. function RDRANDSupport: boolean;inline;
  193. begin
  194. result:=_RDRANDSupport;
  195. end;
  196. begin
  197. SetupSupport;
  198. end.