cpu.pp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  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. {$goto on}
  14. unit cpu;
  15. interface
  16. uses
  17. sysutils;
  18. { returns true, if the processor supports the cpuid instruction }
  19. function cpuid_support : boolean;
  20. { returns true, if floating point is done by an emulator }
  21. function floating_point_emulation : boolean;
  22. { returns the contents of the cr0 register }
  23. function cr0 : longint;
  24. function InterlockedCompareExchange128Support : boolean;
  25. function AESSupport : boolean;inline;
  26. function AVXSupport: boolean;inline;
  27. function AVX2Support: boolean;inline;
  28. function FMASupport: boolean;inline;
  29. function POPCNTSupport: boolean;inline;
  30. function SSE41Support: boolean;inline;
  31. function SSE42Support: boolean;inline;
  32. function MOVBESupport: boolean;inline;
  33. function F16CSupport: boolean;inline;
  34. function RDRANDSupport: boolean;inline;
  35. function RTMSupport: boolean;inline;
  36. var
  37. is_sse3_cpu : boolean = false;
  38. function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec;
  39. implementation
  40. {$ASMMODE INTEL}
  41. var
  42. _AVXSupport,
  43. _AVX2Support,
  44. _AESSupport,
  45. _FMASupport,
  46. _POPCNTSupport,
  47. _SSE41Support,
  48. _SSE42Support,
  49. _MOVBESupport,
  50. _F16CSupport,
  51. _RDRANDSupport,
  52. _RTMSupport: boolean;
  53. {$ASMMODE ATT}
  54. function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec;
  55. begin
  56. {$if FPC_FULLVERSION >= 30101}
  57. {$ifndef FPC_PIC}
  58. if _RTMSupport then
  59. begin
  60. asm
  61. {$ifdef USE_REAL_INSTRUCTIONS}
  62. .Lretry:
  63. xbegin .Lretry
  64. {$else}
  65. { 3d: c7 f8 fa ff ff ff xbegin }
  66. .byte 0xc7,0xf8, 0xfa, 0xff, 0xff, 0xff
  67. {$endif}
  68. end;
  69. Result:=Target;
  70. if (Result.Lo=Comperand.Lo) and (Result.Hi=Comperand.Hi) then
  71. Target:=NewValue;
  72. asm
  73. {$ifdef USE_REAL_INSTRUCTIONS}
  74. xend
  75. {$else}
  76. { 8a: 0f 01 d5 xend }
  77. .byte 0x0f, 0x01, 0xd5
  78. {$endif}
  79. end;
  80. end
  81. else
  82. {$endif FPC_PIC}
  83. {$endif FPC_FULLVERSION >= 30101}
  84. RunError(217);
  85. end;
  86. {$ASMMODE INTEL}
  87. function cpuid_support : boolean;assembler;
  88. {
  89. Check if the ID-flag can be changed, if changed then CpuID is supported.
  90. Tested under go32v1 and Linux on c6x86 with CpuID enabled and disabled (PFV)
  91. }
  92. asm
  93. push ebx
  94. pushfd
  95. pushfd
  96. pop eax
  97. mov ebx,eax
  98. xor eax,200000h
  99. push eax
  100. popfd
  101. pushfd
  102. pop eax
  103. popfd
  104. and eax,200000h
  105. and ebx,200000h
  106. cmp eax,ebx
  107. setnz al
  108. pop ebx
  109. end;
  110. function cr0 : longint;assembler;
  111. asm
  112. {$ifdef USE_REAL_INSTRUCTIONS}
  113. mov eax,cr0
  114. {$else}
  115. DB 0Fh,20h,0C0h
  116. {$endif}
  117. { mov eax,cr0
  118. special registers are not allowed in the assembler
  119. parsers }
  120. end;
  121. function floating_point_emulation : boolean;
  122. begin
  123. {!!!! I don't know currently the position of the EM flag }
  124. { $4 after Ralf Brown's list }
  125. floating_point_emulation:=(cr0 and $4)<>0;
  126. end;
  127. {$ASMMODE ATT}
  128. function XGETBV(i : dword) : int64;assembler;
  129. asm
  130. movl %eax,%ecx
  131. {$ifdef USE_REAL_INSTRUCTIONS}
  132. xgetbv
  133. {$else}
  134. // older FPCs don't know the xgetbv opcode
  135. .byte 0x0f,0x01,0xd0
  136. {$endif}
  137. end;
  138. procedure SetupSupport;
  139. var
  140. _ecx,_ebx : longint;
  141. begin
  142. is_sse3_cpu:=false;
  143. if cpuid_support then
  144. begin
  145. asm
  146. pushl %ebx
  147. movl $1,%eax
  148. cpuid
  149. movl %ecx,_ecx
  150. popl %ebx
  151. end;
  152. _AESSupport:=(_ecx and $2000000)<>0;
  153. _POPCNTSupport:=(_ecx and $800000)<>0;
  154. _SSE41Support:=(_ecx and $80000)<>0;
  155. _SSE42Support:=(_ecx and $100000)<>0;
  156. _MOVBESupport:=(_ecx and $400000)<>0;
  157. _F16CSupport:=(_ecx and $20000000)<>0;
  158. _RDRANDSupport:=(_ecx and $40000000)<>0;
  159. _AVXSupport:=
  160. { XGETBV suspport? }
  161. ((_ecx and $08000000)<>0) and
  162. { xmm and ymm state enabled? }
  163. ((XGETBV(0) and %110)=%110) and
  164. { avx supported? }
  165. ((_ecx and $10000000)<>0);
  166. is_sse3_cpu:=(_ecx and $1)<>0;
  167. _FMASupport:=_AVXSupport and ((_ecx and $1000)<>0);
  168. asm
  169. pushl %ebx
  170. movl $7,%eax
  171. movl $0,%ecx
  172. cpuid
  173. movl %ebx,_ebx
  174. popl %ebx
  175. end;
  176. _AVX2Support:=_AVXSupport and ((_ebx and $20)<>0);
  177. _RTMSupport:=((_ebx and $800)<>0);
  178. end;
  179. end;
  180. function InterlockedCompareExchange128Support : boolean;
  181. begin
  182. { 32 Bit CPUs have no 128 Bit interlocked exchange support,
  183. but it can simulated using RTM }
  184. result:=_RTMSupport;
  185. end;
  186. function AESSupport : boolean;
  187. begin
  188. result:=_AESSupport;
  189. end;
  190. function AVXSupport: boolean;inline;
  191. begin
  192. result:=_AVXSupport;
  193. end;
  194. function AVX2Support: boolean;inline;
  195. begin
  196. result:=_AVX2Support;
  197. end;
  198. function FMASupport: boolean;inline;
  199. begin
  200. result:=_FMASupport;
  201. end;
  202. function POPCNTSupport: boolean;inline;
  203. begin
  204. result:=_POPCNTSupport;
  205. end;
  206. function SSE41Support: boolean;inline;
  207. begin
  208. result:=_SSE41Support;
  209. end;
  210. function SSE42Support: boolean;inline;
  211. begin
  212. result:=_SSE42Support;
  213. end;
  214. function MOVBESupport: boolean;inline;
  215. begin
  216. result:=_MOVBESupport;
  217. end;
  218. function F16CSupport: boolean;inline;
  219. begin
  220. result:=_F16CSupport;
  221. end;
  222. function RDRANDSupport: boolean;inline;
  223. begin
  224. result:=_RDRANDSupport;
  225. end;
  226. function RTMSupport: boolean;inline;
  227. begin
  228. result:=_RTMSupport;
  229. end;
  230. begin
  231. SetupSupport;
  232. end.