mmx.pp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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. {$IFNDEF FPC_DOTTEDUNITS}
  13. unit mmx;
  14. {$ENDIF FPC_DOTTEDUNITS}
  15. interface
  16. type
  17. tmmxshortint = array[0..7] of shortint;
  18. tmmxbyte = array[0..7] of byte;
  19. tmmxword = array[0..3] of word;
  20. tmmxinteger = array[0..3] of integer;
  21. tmmxlongint = array[0..1] of longint;
  22. tmmxcardinal = array[0..1] of cardinal;
  23. { for the AMD 3D }
  24. tmmxsingle = array[0..1] of single;
  25. pmmxshortint = ^tmmxshortint;
  26. pmmxbyte = ^tmmxbyte;
  27. pmmxword = ^tmmxword;
  28. pmmxinteger = ^tmmxinteger;
  29. {$ifdef HASFIXED}
  30. pmmxfixed = ^tmmxfixed;
  31. {$endif HASFIXED}
  32. pmmxlongint = ^tmmxlongint;
  33. pmmxcardinal = ^tmmxcardinal;
  34. { for the AMD 3D }
  35. pmmxsingle = ^tmmxsingle;
  36. const
  37. is_mmx_cpu : boolean = false;
  38. is_sse_cpu : boolean = false;
  39. is_sse2_cpu : boolean = false;
  40. is_amd_3d_cpu : boolean = false;
  41. is_amd_3d_dsp_cpu : boolean = false;
  42. is_amd_3d_mmx_cpu : boolean = false;
  43. { sets all floating point registers to empty
  44. (use this after mmx usage)
  45. }
  46. procedure emms;
  47. procedure femms;
  48. implementation
  49. {$IFDEF FPC_DOTTEDUNITS}
  50. uses
  51. System.CPU;
  52. {$ELSE FPC_DOTTEDUNITS}
  53. uses
  54. cpu;
  55. {$ENDIF FPC_DOTTEDUNITS}
  56. {$ASMMODE ATT}
  57. { return base type of processor: 0 - is Unknown, 10 - is AMD (AuthenticAMD), }
  58. { 20 - is Intel (GenuineIntel) }
  59. { 30 - is Hygon (HygonGenuine) }
  60. function getdevel:byte;
  61. var
  62. _ebx,_ecx,_edx : longint;
  63. begin
  64. getdevel:=0;
  65. if cpuid_support then
  66. begin
  67. asm
  68. pushl %ebx
  69. movl $0,%eax
  70. cpuid
  71. movl %ebx,_ebx
  72. movl %ecx,_ecx
  73. movl %edx,_edx
  74. popl %ebx
  75. end;
  76. if ((_ebx=$68747541) and (_ecx=$444D4163) and (_edx=$69746E65)) then getdevel:=10;
  77. if ((_ebx=$756E6547) and (_ecx=$6C65746E) and (_edx=$49656E69)) then getdevel:=20;
  78. if ((_ebx=$6f677948) and (_ecx=$656e6975) and (_edx=$6e65476e)) then getdevel:=30;
  79. end
  80. end;
  81. { returns true, if the processor supports the mmx instructions }
  82. function mmx_support : boolean;
  83. var
  84. _edx : longint;
  85. begin
  86. if cpuid_support then
  87. begin
  88. asm
  89. pushl %ebx
  90. movl $1,%eax
  91. cpuid
  92. movl %edx,_edx
  93. popl %ebx
  94. end;
  95. mmx_support:=(_edx and $800000)<>0;
  96. end
  97. else
  98. { a cpu with without cpuid instruction supports never mmx }
  99. mmx_support:=false;
  100. end;
  101. function amd_3d_support : boolean;
  102. var
  103. _edx : longint;
  104. begin
  105. { are there third party cpus supporting amd 3d instructions? }
  106. if cpuid_support and ((getdevel=10) or (getdevel=30)) then
  107. begin
  108. asm
  109. pushl %ebx
  110. movl $0x80000001,%eax
  111. cpuid
  112. movl %edx,_edx
  113. popl %ebx
  114. end;
  115. amd_3d_support:=(_edx and $80000000)<>0;
  116. end
  117. else
  118. { a cpu with without cpuid instruction supports never mmx }
  119. amd_3d_support:=false;
  120. end;
  121. function amd_3d_dsp_support : boolean;
  122. var
  123. _edx : longint;
  124. begin
  125. { are there third party cpus supporting amd dsp instructions? }
  126. if cpuid_support and ((getdevel=10) or (getdevel=30)) then
  127. begin
  128. asm
  129. pushl %ebx
  130. movl $0x80000001,%eax
  131. cpuid
  132. movl %edx,_edx
  133. popl %ebx
  134. end;
  135. amd_3d_dsp_support:=(_edx and $40000000)<>0;
  136. end
  137. else
  138. { a cpu with without cpuid instruction supports never mmx }
  139. amd_3d_dsp_support:=false;
  140. end;
  141. function amd_3d_mmx_support : boolean;
  142. var
  143. _edx : longint;
  144. begin
  145. { are there third party cpus supporting amd mmx instructions? }
  146. if cpuid_support and ((getdevel=10) or (getdevel=30)) then
  147. begin
  148. asm
  149. pushl %ebx
  150. movl $0x80000001,%eax
  151. cpuid
  152. movl %edx,_edx
  153. popl %ebx
  154. end;
  155. amd_3d_mmx_support:=(_edx and $400000)<>0;
  156. end
  157. else
  158. { a cpu with without cpuid instruction supports never mmx }
  159. amd_3d_mmx_support:=false;
  160. end;
  161. function sse_support : boolean;
  162. var
  163. _edx : longint;
  164. begin
  165. if cpuid_support then
  166. begin
  167. asm
  168. pushl %ebx
  169. movl $1,%eax
  170. cpuid
  171. movl %edx,_edx
  172. popl %ebx
  173. end;
  174. sse_support:=(_edx and $2000000)<>0;
  175. end
  176. else
  177. { a cpu with without cpuid instruction supports never sse }
  178. sse_support:=false;
  179. end;
  180. function sse2_support : boolean;
  181. var
  182. _edx : longint;
  183. begin
  184. if cpuid_support then
  185. begin
  186. asm
  187. pushl %ebx
  188. movl $1,%eax
  189. cpuid
  190. movl %edx,_edx
  191. popl %ebx
  192. end;
  193. sse2_support:=(_edx and $4000000)<>0;
  194. end
  195. else
  196. { a cpu with without cpuid instruction supports never sse2 }
  197. sse2_support:=false;
  198. end;
  199. procedure emms;assembler;
  200. asm
  201. { emms instruction not supported by older GNU as version,
  202. like 2.6 used by EMX target }
  203. // emms
  204. .byte 0x0f, 0x77
  205. end;
  206. procedure femms;assembler;
  207. asm
  208. { femms instruction not supported with older as versions }
  209. .byte 0x0f, 0x0e
  210. end;
  211. var
  212. oldexitproc : pointer;
  213. procedure mmxexitproc;
  214. begin
  215. exitproc:=oldexitproc;
  216. if is_amd_3d_cpu then femms else emms;
  217. end;
  218. begin
  219. if mmx_support then
  220. begin
  221. is_mmx_cpu:=true;
  222. if amd_3d_support then
  223. begin
  224. is_amd_3d_cpu:=true;
  225. is_amd_3d_dsp_cpu:=amd_3d_dsp_support;
  226. is_amd_3d_mmx_cpu:=amd_3d_mmx_support;
  227. end;
  228. is_sse_cpu:=sse_support;
  229. is_sse2_cpu:=sse2_support;
  230. { the exit code sets the fpu stack to empty }
  231. oldexitproc:=exitproc;
  232. exitproc:=@mmxexitproc;
  233. end;
  234. end.