cpu.pp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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. xend
  80. end;
  81. end
  82. else
  83. {$endif FPC_PIC}
  84. {$endif FPC_FULLVERSION >= 30101}
  85. RunError(217);
  86. end;
  87. {$ASMMODE INTEL}
  88. function cpuid_support : boolean;assembler;
  89. {
  90. Check if the ID-flag can be changed, if changed then CpuID is supported.
  91. Tested under go32v1 and Linux on c6x86 with CpuID enabled and disabled (PFV)
  92. }
  93. asm
  94. push ebx
  95. pushfd
  96. pushfd
  97. pop eax
  98. mov ebx,eax
  99. xor eax,200000h
  100. push eax
  101. popfd
  102. pushfd
  103. pop eax
  104. popfd
  105. and eax,200000h
  106. and ebx,200000h
  107. cmp eax,ebx
  108. setnz al
  109. pop ebx
  110. end;
  111. function cr0 : longint;assembler;
  112. asm
  113. {$ifdef USE_REAL_INSTRUCTIONS}
  114. mov eax,cr0
  115. {$else}
  116. DB 0Fh,20h,0C0h
  117. {$endif}
  118. { mov eax,cr0
  119. special registers are not allowed in the assembler
  120. parsers }
  121. end;
  122. function floating_point_emulation : boolean;
  123. begin
  124. {!!!! I don't know currently the position of the EM flag }
  125. { $4 after Ralf Brown's list }
  126. floating_point_emulation:=(cr0 and $4)<>0;
  127. end;
  128. {$ASMMODE ATT}
  129. function XGETBV(i : dword) : int64;assembler;
  130. asm
  131. movl %eax,%ecx
  132. {$ifdef USE_REAL_INSTRUCTIONS}
  133. xgetbv
  134. {$else}
  135. // older FPCs don't know the xgetbv opcode
  136. .byte 0x0f,0x01,0xd0
  137. {$endif}
  138. end;
  139. procedure SetupSupport;
  140. var
  141. _ecx,_ebx : longint;
  142. begin
  143. is_sse3_cpu:=false;
  144. if cpuid_support then
  145. begin
  146. asm
  147. pushl %ebx
  148. movl $1,%eax
  149. cpuid
  150. movl %ecx,_ecx
  151. popl %ebx
  152. end;
  153. _AESSupport:=(_ecx and $2000000)<>0;
  154. _POPCNTSupport:=(_ecx and $800000)<>0;
  155. _SSE41Support:=(_ecx and $80000)<>0;
  156. _SSE42Support:=(_ecx and $100000)<>0;
  157. _MOVBESupport:=(_ecx and $400000)<>0;
  158. _F16CSupport:=(_ecx and $20000000)<>0;
  159. _RDRANDSupport:=(_ecx and $40000000)<>0;
  160. _AVXSupport:=
  161. { XGETBV suspport? }
  162. ((_ecx and $08000000)<>0) and
  163. { xmm and ymm state enabled? }
  164. ((XGETBV(0) and %110)=%110) and
  165. { avx supported? }
  166. ((_ecx and $10000000)<>0);
  167. is_sse3_cpu:=(_ecx and $1)<>0;
  168. _FMASupport:=_AVXSupport and ((_ecx and $1000)<>0);
  169. asm
  170. pushl %ebx
  171. movl $7,%eax
  172. movl $0,%ecx
  173. cpuid
  174. movl %ebx,_ebx
  175. popl %ebx
  176. end;
  177. _AVX2Support:=_AVXSupport and ((_ebx and $20)<>0);
  178. _RTMSupport:=((_ebx and $800)<>0);
  179. end;
  180. end;
  181. function InterlockedCompareExchange128Support : boolean;
  182. begin
  183. { 32 Bit CPUs have no 128 Bit interlocked exchange support,
  184. but it can simulated using RTM }
  185. result:=_RTMSupport;
  186. end;
  187. function AESSupport : boolean;
  188. begin
  189. result:=_AESSupport;
  190. end;
  191. function AVXSupport: boolean;inline;
  192. begin
  193. result:=_AVXSupport;
  194. end;
  195. function AVX2Support: boolean;inline;
  196. begin
  197. result:=_AVX2Support;
  198. end;
  199. function FMASupport: boolean;inline;
  200. begin
  201. result:=_FMASupport;
  202. end;
  203. function POPCNTSupport: boolean;inline;
  204. begin
  205. result:=_POPCNTSupport;
  206. end;
  207. function SSE41Support: boolean;inline;
  208. begin
  209. result:=_SSE41Support;
  210. end;
  211. function SSE42Support: boolean;inline;
  212. begin
  213. result:=_SSE42Support;
  214. end;
  215. function MOVBESupport: boolean;inline;
  216. begin
  217. result:=_MOVBESupport;
  218. end;
  219. function F16CSupport: boolean;inline;
  220. begin
  221. result:=_F16CSupport;
  222. end;
  223. function RDRANDSupport: boolean;inline;
  224. begin
  225. result:=_RDRANDSupport;
  226. end;
  227. function RTMSupport: boolean;inline;
  228. begin
  229. result:=_RTMSupport;
  230. end;
  231. begin
  232. SetupSupport;
  233. end.