2
0

cpu.pp 6.7 KB

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