mmx.pp 6.5 KB

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