mmx.pp 6.7 KB

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