mmx.pp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  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. { 30 - is Hygon (HygonGenuine) }
  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. pushl %ebx
  62. movl $0,%eax
  63. cpuid
  64. movl %ebx,_ebx
  65. movl %ecx,_ecx
  66. movl %edx,_edx
  67. popl %ebx
  68. end;
  69. if ((_ebx=$68747541) and (_ecx=$444D4163) and (_edx=$69746E65)) then getdevel:=10;
  70. if ((_ebx=$756E6547) and (_ecx=$6C65746E) and (_edx=$49656E69)) then getdevel:=20;
  71. if ((_ebx=$6f677948) and (_ecx=$656e6975) and (_edx=$6e65476e)) then getdevel:=30;
  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. pushl %ebx
  83. movl $1,%eax
  84. cpuid
  85. movl %edx,_edx
  86. popl %ebx
  87. end;
  88. mmx_support:=(_edx and $800000)<>0;
  89. end
  90. else
  91. { a cpu with without cpuid instruction supports never mmx }
  92. mmx_support:=false;
  93. end;
  94. function amd_3d_support : boolean;
  95. var
  96. _edx : longint;
  97. begin
  98. { are there third party cpus supporting amd 3d instructions? }
  99. if cpuid_support and ((getdevel=10) or (getdevel=30)) then
  100. begin
  101. asm
  102. pushl %ebx
  103. movl $0x80000001,%eax
  104. cpuid
  105. movl %edx,_edx
  106. popl %ebx
  107. end;
  108. amd_3d_support:=(_edx and $80000000)<>0;
  109. end
  110. else
  111. { a cpu with without cpuid instruction supports never mmx }
  112. amd_3d_support:=false;
  113. end;
  114. function amd_3d_dsp_support : boolean;
  115. var
  116. _edx : longint;
  117. begin
  118. { are there third party cpus supporting amd dsp instructions? }
  119. if cpuid_support and ((getdevel=10) or (getdevel=30)) then
  120. begin
  121. asm
  122. pushl %ebx
  123. movl $0x80000001,%eax
  124. cpuid
  125. movl %edx,_edx
  126. popl %ebx
  127. end;
  128. amd_3d_dsp_support:=(_edx and $40000000)<>0;
  129. end
  130. else
  131. { a cpu with without cpuid instruction supports never mmx }
  132. amd_3d_dsp_support:=false;
  133. end;
  134. function amd_3d_mmx_support : boolean;
  135. var
  136. _edx : longint;
  137. begin
  138. { are there third party cpus supporting amd mmx instructions? }
  139. if cpuid_support and ((getdevel=10) or (getdevel=30)) then
  140. begin
  141. asm
  142. pushl %ebx
  143. movl $0x80000001,%eax
  144. cpuid
  145. movl %edx,_edx
  146. popl %ebx
  147. end;
  148. amd_3d_mmx_support:=(_edx and $400000)<>0;
  149. end
  150. else
  151. { a cpu with without cpuid instruction supports never mmx }
  152. amd_3d_mmx_support:=false;
  153. end;
  154. function sse_support : boolean;
  155. var
  156. _edx : longint;
  157. begin
  158. if cpuid_support then
  159. begin
  160. asm
  161. pushl %ebx
  162. movl $1,%eax
  163. cpuid
  164. movl %edx,_edx
  165. popl %ebx
  166. end;
  167. sse_support:=(_edx and $2000000)<>0;
  168. end
  169. else
  170. { a cpu with without cpuid instruction supports never sse }
  171. sse_support:=false;
  172. end;
  173. function sse2_support : boolean;
  174. var
  175. _edx : longint;
  176. begin
  177. if cpuid_support then
  178. begin
  179. asm
  180. pushl %ebx
  181. movl $1,%eax
  182. cpuid
  183. movl %edx,_edx
  184. popl %ebx
  185. end;
  186. sse2_support:=(_edx and $4000000)<>0;
  187. end
  188. else
  189. { a cpu with without cpuid instruction supports never sse2 }
  190. sse2_support:=false;
  191. end;
  192. procedure emms;assembler;
  193. asm
  194. { emms instruction not supported by older GNU as version,
  195. like 2.6 used by EMX target }
  196. // emms
  197. .byte 0x0f, 0x77
  198. end;
  199. procedure femms;assembler;
  200. asm
  201. { femms instruction not supported with older as versions }
  202. .byte 0x0f, 0x0e
  203. end;
  204. var
  205. oldexitproc : pointer;
  206. procedure mmxexitproc;
  207. begin
  208. exitproc:=oldexitproc;
  209. if is_amd_3d_cpu then femms else emms;
  210. end;
  211. begin
  212. if mmx_support then
  213. begin
  214. is_mmx_cpu:=true;
  215. if amd_3d_support then
  216. begin
  217. is_amd_3d_cpu:=true;
  218. is_amd_3d_dsp_cpu:=amd_3d_dsp_support;
  219. is_amd_3d_mmx_cpu:=amd_3d_mmx_support;
  220. end;
  221. is_sse_cpu:=sse_support;
  222. is_sse2_cpu:=sse2_support;
  223. { the exit code sets the fpu stack to empty }
  224. oldexitproc:=exitproc;
  225. exitproc:=@mmxexitproc;
  226. end;
  227. end.