2
0

cpu.pp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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. {$IFNDEF FPC_DOTTEDUNITS}
  14. unit cpu;
  15. {$ENDIF FPC_DOTTEDUNITS}
  16. interface
  17. {$IFDEF FPC_DOTTEDUNITS}
  18. uses
  19. System.SysUtils;
  20. {$ELSE FPC_DOTTEDUNITS}
  21. uses
  22. sysutils;
  23. {$ENDIF FPC_DOTTEDUNITS}
  24. { returns true, if the processor supports the cpuid instruction }
  25. function cpuid_support : boolean;
  26. { returns true, if floating point is done by an emulator }
  27. function floating_point_emulation : boolean;
  28. { returns the contents of the cr0 register }
  29. function cr0 : longint;
  30. // function InterlockedCompareExchange128Support : boolean;
  31. // function AESSupport : boolean;inline;
  32. // function AVXSupport: boolean;inline;
  33. // function AVX2Support: boolean;inline;
  34. // function FMASupport: boolean;inline;
  35. // var
  36. // is_sse3_cpu : boolean = false;
  37. function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec;
  38. implementation
  39. {$ASMMODE INTEL}
  40. {$ASMCPU 80386}
  41. // var
  42. // _AVXSupport,
  43. // _AVX2Support,
  44. // _AESSupport,
  45. // _FMASupport : boolean;
  46. function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec;
  47. begin
  48. RunError(217);
  49. end;
  50. function cpuid_support : boolean;assembler;nostackframe;
  51. {
  52. Check if the ID-flag can be changed, if changed then CpuID is supported.
  53. }
  54. asm
  55. xor ax, ax
  56. {$IFDEF FPC_MM_HUGE}
  57. mov bx, SEG Test8086
  58. mov es, bx
  59. cmp byte ptr es:[Test8086], 2 { 2 = 80386 or later }
  60. {$ELSE FPC_MM_HUGE}
  61. cmp byte ptr [Test8086], 2 { 2 = 80386 or later }
  62. {$ENDIF FPC_MM_HUGE}
  63. jb @@Done { Test8086<2 means 80286 or earlier }
  64. pushfd
  65. pushfd
  66. pop bx
  67. pop cx
  68. mov dx, cx
  69. xor cx, 20h
  70. push cx
  71. push bx
  72. popfd
  73. pushfd
  74. pop bx
  75. pop cx
  76. popfd
  77. and cx, 20h
  78. and dx, 20h
  79. cmp cx, dx
  80. je @@Done
  81. inc ax
  82. @@Done:
  83. end;
  84. function cr0 : longint;assembler;nostackframe;
  85. asm
  86. int 3
  87. xor ax, ax
  88. xor dx, dx
  89. {$IFDEF FPC_MM_HUGE}
  90. mov bx, SEG Test8086
  91. mov es, bx
  92. mov al, byte ptr es:[Test8086]
  93. {$ELSE FPC_MM_HUGE}
  94. mov al, byte ptr [Test8086]
  95. {$ENDIF FPC_MM_HUGE}
  96. test al, al { 0 = 8086/8088/80186/80188/NEC v20/v30: no cr0/msw register; simply return 0 }
  97. jz @@Done
  98. cmp al, 1 { 1 = 80286 }
  99. jne @@386_or_later
  100. { on 80286 we use SMSW (high 16 bits are 0, because dx=0) }
  101. smsw ax
  102. jmp @@Done
  103. @@386_or_later:
  104. { use smsw first, to see if we are in real mode (mov eax, cr0 isn't supported in virtual 8086 mode) }
  105. smsw ax
  106. test al, 1
  107. jz @@386_read_cr0 { real mode: we can read cr0 }
  108. { 386 in protected mode; check the virtual 8086 mode flag }
  109. { unfortunately, this doesn't work, because pushfd never pushes the virtual 8086 mode flag as 1 }
  110. //pushfd
  111. //pop cx
  112. //pop cx
  113. //test cl, 2
  114. //jnz @@Done {if in virtual 8086 mode, we can't read cr0, so just return the SMSW result }
  115. { so, we must assume virtual 8086 mode and just return the SMSW result }
  116. { TODO: this can be updated for e.g. protected mode 286 targets, where we
  117. can safely assume the CPU is not in virtual 8086 mode, but proper protected mode
  118. and still try to read cr0 }
  119. jmp @@Done
  120. @@386_read_cr0:
  121. pushf { save the previous state of the interrupt flag }
  122. cli { disable interrupts, because some buggy TSR may destroy the high
  123. 16 bits of eax in an interrupt handler (BP7's 32-bit mul/div
  124. helpers do this, when they detect a 386 or later, so e.g. a BP7
  125. TSR that hooks the timer interrupt could do this) }
  126. { store eax, so that we preserve the high 16 bits of eax }
  127. push eax
  128. mov eax, cr0
  129. push eax
  130. pop cx
  131. pop dx
  132. pop eax { restore eax }
  133. mov ax, cx
  134. popf { restore interrupts to their previous state }
  135. @@Done:
  136. end;
  137. function floating_point_emulation : boolean;
  138. begin
  139. {!!!! I don't know currently the position of the EM flag }
  140. { $4 after Ralf Brown's list }
  141. floating_point_emulation:=(cr0 and $4)<>0;
  142. end;
  143. {$ASMMODE ATT}
  144. // function XGETBV(i : dword) : int64;assembler;
  145. // asm
  146. // movl %eax,%ecx
  147. // // older FPCs don't know the xgetbv opcode
  148. // .byte 0x0f,0x01,0xd0
  149. // end;
  150. // procedure SetupSupport;
  151. // var
  152. // _ecx,_ebx : longint;
  153. // begin
  154. // is_sse3_cpu:=false;
  155. // if cpuid_support then
  156. // begin
  157. // asm
  158. // pushl %ebx
  159. // movl $1,%eax
  160. // cpuid
  161. // movl %ecx,_ecx
  162. // popl %ebx
  163. // end;
  164. // _AESSupport:=(_ecx and $2000000)<>0;
  165. //
  166. // _AVXSupport:=
  167. // { XGETBV suspport? }
  168. // ((_ecx and $08000000)<>0) and
  169. // { xmm and ymm state enabled? }
  170. // ((XGETBV(0) and %110)=%110) and
  171. // { avx supported? }
  172. // ((_ecx and $10000000)<>0);
  173. //
  174. // is_sse3_cpu:=(_ecx and $1)<>0;
  175. //
  176. // _FMASupport:=_AVXSupport and ((_ecx and $1000)<>0);
  177. //
  178. // asm
  179. // pushl %ebx
  180. // movl $7,%eax
  181. // movl $0,%ecx
  182. // cpuid
  183. // movl %ebx,_ebx
  184. // popl %ebx
  185. // end;
  186. // _AVX2Support:=_AVXSupport and ((_ebx and $20)<>0);
  187. // end;
  188. // end;
  189. // function InterlockedCompareExchange128Support : boolean;
  190. // begin
  191. // { 32 Bit CPUs have no 128 Bit interlocked exchange support }
  192. // result:=false;
  193. // end;
  194. // function AESSupport : boolean;
  195. // begin
  196. // result:=_AESSupport;
  197. // end;
  198. // function AVXSupport: boolean;inline;
  199. // begin
  200. // result:=_AVXSupport;
  201. // end;
  202. // function AVX2Support: boolean;inline;
  203. // begin
  204. // result:=_AVX2Support;
  205. // end;
  206. // function FMASupport: boolean;inline;
  207. // begin
  208. // result:=_FMASupport;
  209. // end;
  210. begin
  211. // SetupSupport;
  212. end.