mmx.pp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Florian Klaempfl
  4. member of the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. { This unit contains some helpful stuff to deal with the mmx extensions }
  12. unit mmx;
  13. interface
  14. type
  15. tmmxshortint = array[0..7] of shortint;
  16. tmmxbyte = array[0..7] of byte;
  17. tmmxword = array[0..3] of word;
  18. tmmxinteger = array[0..3] of integer;
  19. tmmxlongint = array[0..1] of longint;
  20. tmmxcardinal = array[0..1] of cardinal;
  21. { for the AMD 3D }
  22. tmmxsingle = array[0..1] of single;
  23. pmmxshortint = ^tmmxshortint;
  24. pmmxbyte = ^tmmxbyte;
  25. pmmxword = ^tmmxword;
  26. pmmxinteger = ^tmmxinteger;
  27. {$ifdef HASFIXED}
  28. pmmxfixed = ^tmmxfixed;
  29. {$endif HASFIXED}
  30. pmmxlongint = ^tmmxlongint;
  31. pmmxcardinal = ^tmmxcardinal;
  32. { for the AMD 3D }
  33. pmmxsingle = ^tmmxsingle;
  34. const
  35. is_mmx_cpu : boolean = false;
  36. is_sse_cpu : boolean = false;
  37. is_sse2_cpu : boolean = false;
  38. is_amd_3d_cpu : boolean = false;
  39. is_amd_3d_dsp_cpu : boolean = false;
  40. is_amd_3d_mmx_cpu : boolean = false;
  41. { sets all floating point registers to empty
  42. (use this after mmx usage)
  43. }
  44. procedure emms;
  45. procedure femms;
  46. implementation
  47. uses
  48. cpu;
  49. {$ASMMODE ATT}
  50. { return base type of processor: 0 - is Unknown, 10 - is AMD (AuthenticAMD), }
  51. { 20 - is Intel (GenuineIntel) }
  52. function getdevel:byte;
  53. var
  54. _ebx,_ecx,_edx : longint;
  55. begin
  56. getdevel:=0;
  57. if cpuid_support then
  58. begin
  59. asm
  60. movl $0,%eax
  61. cpuid
  62. movl %ebx,_ebx
  63. movl %ecx,_ecx
  64. movl %edx,_edx
  65. end;
  66. if ((_ebx=$68747541) and (_ecx=$444D4163) and (_edx=$69746E65)) then getdevel:=10;
  67. if ((_ebx=$756E6547) and (_ecx=$6C65746E) and (_edx=$49656E69)) then getdevel:=20;
  68. end
  69. end;
  70. { returns true, if the processor supports the mmx instructions }
  71. function mmx_support : boolean;
  72. var
  73. _edx : longint;
  74. begin
  75. if cpuid_support then
  76. begin
  77. asm
  78. movl $1,%eax
  79. cpuid
  80. movl %edx,_edx
  81. end;
  82. mmx_support:=(_edx and $800000)<>0;
  83. end
  84. else
  85. { a cpu with without cpuid instruction supports never mmx }
  86. mmx_support:=false;
  87. end;
  88. function amd_3d_support : boolean;
  89. var
  90. _edx : longint;
  91. begin
  92. if cpuid_support then
  93. begin
  94. asm
  95. movl $0x80000001,%eax
  96. cpuid
  97. movl %edx,_edx
  98. end;
  99. amd_3d_support:=(_edx and $80000000)<>0;
  100. end
  101. else
  102. { a cpu with without cpuid instruction supports never mmx }
  103. amd_3d_support:=false;
  104. end;
  105. function amd_3d_dsp_support : boolean;
  106. var
  107. _edx : longint;
  108. begin
  109. if cpuid_support then
  110. begin
  111. asm
  112. movl $0x80000001,%eax
  113. cpuid
  114. movl %edx,_edx
  115. end;
  116. amd_3d_dsp_support:=(_edx and $40000000)<>0;
  117. end
  118. else
  119. { a cpu with without cpuid instruction supports never mmx }
  120. amd_3d_dsp_support:=false;
  121. end;
  122. function amd_3d_mmx_support : boolean;
  123. var
  124. _edx : longint;
  125. begin
  126. if cpuid_support then
  127. begin
  128. asm
  129. movl $0x80000001,%eax
  130. cpuid
  131. movl %edx,_edx
  132. end;
  133. amd_3d_mmx_support:=(_edx and $400000)<>0;
  134. end
  135. else
  136. { a cpu with without cpuid instruction supports never mmx }
  137. amd_3d_mmx_support:=false;
  138. end;
  139. function sse_support : boolean;
  140. var
  141. _edx : longint;
  142. begin
  143. if cpuid_support then
  144. begin
  145. asm
  146. movl $1,%eax
  147. cpuid
  148. movl %edx,_edx
  149. end;
  150. sse_support:=(_edx and $2000000)<>0;
  151. end
  152. else
  153. { a cpu with without cpuid instruction supports never sse }
  154. sse_support:=false;
  155. end;
  156. function sse2_support : boolean;
  157. var
  158. _edx : longint;
  159. begin
  160. if cpuid_support then
  161. begin
  162. asm
  163. movl $1,%eax
  164. cpuid
  165. movl %edx,_edx
  166. end;
  167. sse2_support:=(_edx and $4000000)<>0;
  168. end
  169. else
  170. { a cpu with without cpuid instruction supports never sse2 }
  171. sse2_support:=false;
  172. end;
  173. procedure emms;assembler;
  174. asm
  175. emms
  176. end;
  177. procedure femms;assembler;
  178. asm
  179. .byte 0x0f, 0x0e
  180. { femms instruction not supported with older as versions }
  181. end;
  182. var
  183. oldexitproc : pointer;
  184. procedure mmxexitproc;
  185. begin
  186. exitproc:=oldexitproc;
  187. if is_amd_3d_cpu then femms else emms;
  188. end;
  189. begin
  190. if mmx_support then
  191. begin
  192. is_mmx_cpu:=true;
  193. if amd_3d_support then
  194. begin
  195. is_amd_3d_cpu:=true;
  196. is_amd_3d_dsp_cpu:=amd_3d_dsp_support;
  197. is_amd_3d_mmx_cpu:=amd_3d_mmx_support;
  198. end;
  199. is_sse_cpu:=sse_support;
  200. is_sse2_cpu:=sse2_support;
  201. { the exit code sets the fpu stack to empty }
  202. oldexitproc:=exitproc;
  203. exitproc:=@mmxexitproc;
  204. end;
  205. end.