mmx.pp 6.4 KB

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