cpu.pp 6.4 KB

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