cpu.pp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  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. {$ifdef freebsd} // FreeBSD 7/8 have binutils version that don't support cmpxchg16b
  16. // Unless overridebinutils is defined (for ports usage), use db instead of the instruction
  17. {$ifndef overridebinutils}
  18. {$define oldbinutils}
  19. {$endif}
  20. {$endif}
  21. uses
  22. sysutils;
  23. function InterlockedCompareExchange128Support : boolean;inline;
  24. function AESSupport : boolean;inline;
  25. function AVXSupport : boolean;inline;
  26. function AVX2Support: boolean;inline;
  27. function FMASupport: boolean;inline;
  28. function POPCNTSupport: boolean;inline;
  29. var
  30. is_sse3_cpu : boolean = false;
  31. function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec;
  32. implementation
  33. {$asmmode att}
  34. var
  35. _AESSupport,
  36. _AVXSupport,
  37. _InterlockedCompareExchange128Support,
  38. _AVX2Support,
  39. _FMASupport,
  40. _POPCNTSupport: boolean;
  41. function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec; assembler;
  42. {
  43. win64:
  44. rcx ... pointer to result
  45. rdx ... target
  46. r8 ... NewValue
  47. r9 ... Comperand
  48. }
  49. {$ifdef win64}
  50. asm
  51. pushq %rbx
  52. { store result pointer for later use }
  53. pushq %rcx
  54. { load new value }
  55. movq (%r8),%rbx
  56. movq 8(%r8),%rcx
  57. { save target pointer for later use }
  58. movq %rdx,%r8
  59. { load comperand }
  60. movq (%r9),%rax
  61. movq 8(%r9),%rdx
  62. {$ifdef oldbinutils}
  63. .byte 0xF0,0x49,0x0F,0xC7,0x08
  64. {$else}
  65. lock cmpxchg16b (%r8)
  66. {$endif}
  67. { restore result pointer }
  68. popq %rcx
  69. { store result }
  70. movq %rax,(%rcx)
  71. movq %rdx,8(%rcx)
  72. popq %rbx
  73. end;
  74. {$else win64}
  75. {
  76. linux:
  77. rdi ... target
  78. [rsi:rdx] ... NewValue
  79. [rcx:r8] ... Comperand
  80. [rdx:rax] ... result
  81. }
  82. asm
  83. pushq %rbx
  84. movq %rsi,%rbx // new value low
  85. movq %rcx,%rax // comperand low
  86. movq %rdx,%rcx // new value high
  87. movq %r8,%rdx // comperand high
  88. {$ifdef oldbinutils}
  89. .byte 0xF0,0x48,0x0F,0xC7,0x0F
  90. {$else}
  91. lock cmpxchg16b (%rdi)
  92. {$endif}
  93. popq %rbx
  94. end;
  95. {$endif win64}
  96. function XGETBV(i : dword) : int64;assembler;
  97. asm
  98. {$ifndef win64}
  99. movq %rdi,%rcx
  100. {$endif win64}
  101. // older FPCs don't know the xgetbv opcode
  102. .byte 0x0f,0x01,0xd0
  103. andl $0xffffffff,%eax
  104. shlq $32,%rdx
  105. orq %rdx,%rax
  106. end;
  107. procedure SetupSupport;
  108. var
  109. _ecx,
  110. _ebx : longint;
  111. begin
  112. asm
  113. movl $0x00000001,%eax
  114. cpuid
  115. movl %ecx,_ecx
  116. end ['rax','rbx','rcx','rdx'];
  117. _InterlockedCompareExchange128Support:=(_ecx and $2000)<>0;
  118. _AESSupport:=(_ecx and $2000000)<>0;
  119. _POPCNTSupport:=(_ecx and $800000)<>0;
  120. _AVXSupport:=
  121. { XGETBV suspport? }
  122. ((_ecx and $08000000)<>0) and
  123. { xmm and ymm state enabled? }
  124. ((XGETBV(0) and %110)=%110) and
  125. { avx supported? }
  126. ((_ecx and $10000000)<>0);
  127. is_sse3_cpu:=(_ecx and $1)<>0;
  128. _FMASupport:=_AVXSupport and ((_ecx and $1000)<>0);
  129. asm
  130. movl $7,%eax
  131. movl $0,%ecx
  132. cpuid
  133. movl %ebx,_ebx
  134. end ['rax','rbx','rcx','rdx'];
  135. _AVX2Support:=_AVXSupport and ((_ebx and $20)<>0);
  136. end;
  137. function InterlockedCompareExchange128Support : boolean;inline;
  138. begin
  139. result:=_InterlockedCompareExchange128Support;
  140. end;
  141. function AESSupport : boolean;inline;
  142. begin
  143. result:=_AESSupport;
  144. end;
  145. function AVXSupport: boolean;inline;
  146. begin
  147. result:=_AVXSupport;
  148. end;
  149. function AVX2Support: boolean;inline;
  150. begin
  151. result:=_AVX2Support;
  152. end;
  153. function FMASupport: boolean;inline;
  154. begin
  155. result:=_FMASupport;
  156. end;
  157. function POPCNTSupport: boolean;inline;
  158. begin
  159. result:=_POPCNTSupport;
  160. end;
  161. begin
  162. SetupSupport;
  163. end.