MMX.ASM 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. ;
  2. ; Copyright 2020 Electronic Arts Inc.
  3. ;
  4. ; TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
  5. ; software: you can redistribute it and/or modify it under the terms of
  6. ; the GNU General Public License as published by the Free Software Foundation,
  7. ; either version 3 of the License, or (at your option) any later version.
  8. ; TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
  9. ; in the hope that it will be useful, but with permitted additional restrictions
  10. ; under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
  11. ; distributed with this program. You should have received a copy of the
  12. ; GNU General Public License along with permitted additional restrictions
  13. ; with this program. If not, see [https://github.com/electronicarts/CnC_Remastered_Collection]>.
  14. ;***************************************************************************
  15. ;** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S I N C **
  16. ;***************************************************************************
  17. ;* *
  18. ;* Project Name : Command & Conquer *
  19. ;* *
  20. ;* File Name : MMX.ASM *
  21. ;* *
  22. ;* Programmer : Steve Tall *
  23. ;* *
  24. ;* Start Date : May 19th, 1996 *
  25. ;* *
  26. ;* Last Update : May 19th 1996 [ST] *
  27. ;* *
  28. ;*-------------------------------------------------------------------------*
  29. ;* Functions: *
  30. ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
  31. ; include <mmx.inc>
  32. .model flat
  33. ;.686
  34. externdef C Detect_MMX_Availability:near
  35. externdef C Single_Line_Trans_Entry:near
  36. externdef C Next_Line:near
  37. externdef C Init_MMX:near
  38. externdef C MMX_Done:near
  39. externdef EndNewShapeJumpTable:byte
  40. externdef NewShapeJumpTable:dword
  41. externdef C Single_Line_Trans:near
  42. externdef MMX_Single_Line_Trans:near
  43. .code
  44. externdef C CPUType:byte
  45. ;*********************************************************************************************
  46. ;* Detect_MMX_Availability -- Detect the presence of MMX technology. *
  47. ;* *
  48. ;* *
  49. ;* INPUT: Nothing *
  50. ;* *
  51. ;* OUTPUT: True if MMX technology is available. *
  52. ;* *
  53. ;* Warnings: *
  54. ;* *
  55. ;* Note: Based in part on CPUID32.ASM by Intel *
  56. ;* *
  57. ;* HISTORY: *
  58. ;* 05/19/96 ST : Created. *
  59. ;*===========================================================================================*
  60. Detect_MMX_Availability proc C
  61. local idflag:byte
  62. local local_cputype:byte
  63. ; MMX always available now. ST - 1/3/2019 1:31PM
  64. mov [CPUType], 5
  65. mov eax, 1
  66. ret
  67. ;assume processor is at least 386
  68. ;
  69. ;check whether AC bit in eflags can be toggled.
  70. ;If not then processor is 386
  71. mov [idflag],0
  72. pushfd ;get Eflags in EAX
  73. pop eax
  74. mov ecx,eax ;save eflags
  75. xor eax,40000h ;toggle AC bit in eflags
  76. push eax ;new eflags on stack
  77. popfd ;move new value into eflags
  78. pushfd ;get new eflags back into eax
  79. pop eax
  80. xor eax,ecx ;if AC bit not toggled then CPU=386
  81. mov [local_cputype],3
  82. jz @@end_get_cpu ;cpu is 386
  83. push ecx
  84. popfd ;restore AC bit in eflags
  85. ;processor is at least 486
  86. ;
  87. ;Check for ability to set/clear ID flag in EFLAGS
  88. ;ID flag indicates ability of processor to execute the CPUID instruction.
  89. ;486 not guaranteed to have CPUID inst?
  90. ;
  91. mov [local_cputype],4
  92. mov eax,ecx ;original EFLAGS
  93. xor eax,200000h ;toggle ID bit
  94. push eax
  95. popfd
  96. pushfd
  97. pop eax
  98. xor eax,ecx ;check if still toggled
  99. jz @@end_get_cpu
  100. ; Execute CPUID instruction to determine vendor, family,
  101. ; model and stepping.
  102. ;
  103. mov [idflag],1 ;flag ID is available
  104. xor eax,eax
  105. cpuid
  106. mov dword ptr [VendorID],ebx
  107. mov dword ptr [VendorID+4],edx
  108. mov dword ptr [VendorID+8],ecx
  109. mov dword ptr [VendorID+12]," "
  110. cmp eax,1 ;check if 1 is valid
  111. jl @@end_get_cpu ;inp for cpuid inst.
  112. xor eax,eax
  113. inc eax
  114. cpuid ;get stepping, model and family
  115. and ax,0f00H
  116. shr ax,08H
  117. mov [local_cputype],al
  118. @@end_get_cpu: mov al,[local_cputype]
  119. mov [CPUType],al
  120. ;
  121. ; We have the CPU type in al now.
  122. ; If we arent on at least a pentium then we can assume there is no MMX
  123. ;
  124. cmp al,5
  125. jl @@no_mmx
  126. mov eax,1
  127. cpuid
  128. test edx,00800000h
  129. jz @@no_mmx
  130. ;
  131. ; MMX detected - return true
  132. ;
  133. mov eax,1
  134. ret
  135. @@no_mmx: xor eax,eax
  136. ret
  137. Detect_MMX_Availability endp
  138. ;*********************************************************************************************
  139. ;* Init_MMX -- Do any special inits required for MMX support *
  140. ;* *
  141. ;* *
  142. ;* INPUT: Nothing *
  143. ;* *
  144. ;* OUTPUT: None *
  145. ;* *
  146. ;* Warnings: *
  147. ;* *
  148. ;* HISTORY: *
  149. ;* 05/19/96 ST : Created. *
  150. ;*===========================================================================================*
  151. Init_MMX proc C
  152. mov edi,offset NewShapeJumpTable
  153. mov ecx,offset EndNewShapeJumpTable
  154. sub ecx,edi
  155. shr ecx,2
  156. mov eax,offset Single_Line_Trans
  157. mov ebx,offset MMX_Single_Line_Trans
  158. cld
  159. @@patch_loop: repnz scasd
  160. jnz @@done
  161. mov [edi-4],ebx
  162. test ecx,ecx
  163. jnz @@patch_loop
  164. @@done: ret
  165. Init_MMX endp
  166. ;*********************************************************************************************
  167. ;* MMX_Done -- Restores floating point capability after MMX usage *
  168. ;* *
  169. ;* *
  170. ;* INPUT: Nothing *
  171. ;* *
  172. ;* OUTPUT: None *
  173. ;* *
  174. ;* Warnings: *
  175. ;* *
  176. ;* HISTORY: *
  177. ;* 05/19/96 ST : Created. *
  178. ;*===========================================================================================*
  179. MMX_Done proc C
  180. emms
  181. ret
  182. MMX_Done endp
  183. code segment page public use32 'code' ; Need stricter segment alignment
  184. ; for pentium optimisations
  185. ;*********************************************************************************************
  186. ;* MMX_Single_Line_Trans -- draw a single line of transparent pixels using MMX technology *
  187. ;* *
  188. ;* *
  189. ;* INPUT: Esi - ptr to source data *
  190. ;* Edi - ptr to destination data *
  191. ;* Ecx - width to draw in bytes *
  192. ;* *
  193. ;* OUTPUT: None *
  194. ;* *
  195. ;* Warnings: *
  196. ;* *
  197. ;* HISTORY: *
  198. ;* 05/19/96 ST : Created. *
  199. ;*===========================================================================================*
  200. align 16
  201. MMX_Single_Line_Trans proc near
  202. ;
  203. ; If we are doing less than 8 bytes then dont use MMX
  204. ;
  205. cmp ecx,8
  206. jge @@mmx_loop
  207. push offset Single_Line_Trans_Entry
  208. ret
  209. ;
  210. ; Use MMX instructions to mask 8 bytes at once
  211. ;
  212. ; Creates a bitmask based on the source bytes equality with zero and then uses this to mask
  213. ; out the source bytes in the destination data. The advatage that MMX gives us is that there is
  214. ; no 'test for zero then jump' required to mask.
  215. ;
  216. align 64 ;MMX instructions like 64 byte alignment!
  217. @@mmx_loop:
  218. movq mm0,[esi] ; move 8 bytes of source into mm0
  219. pxor mm1,mm1 ; zero out mm1
  220. pcmpeqb mm1,mm0 ; compare mm0 with 0. Bits get set in mm1
  221. lea esi,[esi+8] ; adjust the source data pointer
  222. pand mm1,[edi] ; and in the destination data to throw away the bytes which arent zero in the source
  223. sub ecx,8 ; adjust the byte counter
  224. por mm1,mm0 ; or in the source with the destination data
  225. movq [edi],mm1 ; write back the destination data
  226. lea edi,[edi+8] ; adjust the destination pointer
  227. cmp ecx,8
  228. jg @@mmx_loop
  229. ;
  230. ; Jump to the approprite code for drawing the end of this line or going to the next one
  231. ;
  232. push offset Next_Line
  233. jcxz @@next_line
  234. push offset Single_Line_Trans_Entry
  235. @@next_line: ret
  236. MMX_Single_Line_Trans endp
  237. code ends
  238. .data
  239. CPUType db 0
  240. VendorID db "Not available",0,0,0,0,0,0
  241. end