MMX.ASM 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  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. externdef C VendorID:byte
  46. ;*********************************************************************************************
  47. ;* Detect_MMX_Availability -- Detect the presence of MMX technology. *
  48. ;* *
  49. ;* *
  50. ;* INPUT: Nothing *
  51. ;* *
  52. ;* OUTPUT: True if MMX technology is available. *
  53. ;* *
  54. ;* Warnings: *
  55. ;* *
  56. ;* Note: Based in part on CPUID32.ASM by Intel *
  57. ;* *
  58. ;* HISTORY: *
  59. ;* 05/19/96 ST : Created. *
  60. ;*===========================================================================================*
  61. Detect_MMX_Availability proc C
  62. local idflag:byte
  63. local local_cputype:byte
  64. ; MMX always available now. ST - 1/3/2019 1:31PM
  65. mov [CPUType], 5
  66. mov eax, 1
  67. ret
  68. ;assume processor is at least 386
  69. ;
  70. ;check whether AC bit in eflags can be toggled.
  71. ;If not then processor is 386
  72. mov [idflag],0
  73. pushfd ;get Eflags in EAX
  74. pop eax
  75. mov ecx,eax ;save eflags
  76. xor eax,40000h ;toggle AC bit in eflags
  77. push eax ;new eflags on stack
  78. popfd ;move new value into eflags
  79. pushfd ;get new eflags back into eax
  80. pop eax
  81. xor eax,ecx ;if AC bit not toggled then CPU=386
  82. mov [local_cputype],3
  83. jz @@end_get_cpu ;cpu is 386
  84. push ecx
  85. popfd ;restore AC bit in eflags
  86. ;processor is at least 486
  87. ;
  88. ;Check for ability to set/clear ID flag in EFLAGS
  89. ;ID flag indicates ability of processor to execute the CPUID instruction.
  90. ;486 not guaranteed to have CPUID inst?
  91. ;
  92. mov [local_cputype],4
  93. mov eax,ecx ;original EFLAGS
  94. xor eax,200000h ;toggle ID bit
  95. push eax
  96. popfd
  97. pushfd
  98. pop eax
  99. xor eax,ecx ;check if still toggled
  100. jz @@end_get_cpu
  101. ; Execute CPUID instruction to determine vendor, family,
  102. ; model and stepping.
  103. ;
  104. mov [idflag],1 ;flag ID is available
  105. xor eax,eax
  106. cpuid
  107. mov dword ptr [VendorID],ebx
  108. mov dword ptr [VendorID+4],edx
  109. mov dword ptr [VendorID+8],ecx
  110. mov dword ptr [VendorID+12]," "
  111. cmp eax,1 ;check if 1 is valid
  112. jl @@end_get_cpu ;inp for cpuid inst.
  113. xor eax,eax
  114. inc eax
  115. cpuid ;get stepping, model and family
  116. and ax,0f00H
  117. shr ax,08H
  118. mov [local_cputype],al
  119. @@end_get_cpu: mov al,[local_cputype]
  120. mov [CPUType],al
  121. ;
  122. ; We have the CPU type in al now.
  123. ; If we arent on at least a pentium then we can assume there is no MMX
  124. ;
  125. cmp al,5
  126. jl @@no_mmx
  127. mov eax,1
  128. cpuid
  129. test edx,00800000h
  130. jz @@no_mmx
  131. ;
  132. ; MMX detected - return true
  133. ;
  134. mov eax,1
  135. ret
  136. @@no_mmx: xor eax,eax
  137. ret
  138. Detect_MMX_Availability endp
  139. ;*********************************************************************************************
  140. ;* Init_MMX -- Do any special inits required for MMX support *
  141. ;* *
  142. ;* *
  143. ;* INPUT: Nothing *
  144. ;* *
  145. ;* OUTPUT: None *
  146. ;* *
  147. ;* Warnings: *
  148. ;* *
  149. ;* HISTORY: *
  150. ;* 05/19/96 ST : Created. *
  151. ;*===========================================================================================*
  152. Init_MMX proc C
  153. mov edi,offset NewShapeJumpTable
  154. mov ecx,offset EndNewShapeJumpTable
  155. sub ecx,edi
  156. shr ecx,2
  157. mov eax,offset Single_Line_Trans
  158. mov ebx,offset MMX_Single_Line_Trans
  159. cld
  160. @@patch_loop: repnz scasd
  161. jnz @@done
  162. mov [edi-4],ebx
  163. test ecx,ecx
  164. jnz @@patch_loop
  165. @@done: ret
  166. Init_MMX endp
  167. ;*********************************************************************************************
  168. ;* MMX_Done -- Restores floating point capability after MMX usage *
  169. ;* *
  170. ;* *
  171. ;* INPUT: Nothing *
  172. ;* *
  173. ;* OUTPUT: None *
  174. ;* *
  175. ;* Warnings: *
  176. ;* *
  177. ;* HISTORY: *
  178. ;* 05/19/96 ST : Created. *
  179. ;*===========================================================================================*
  180. MMX_Done proc C
  181. emms
  182. ret
  183. MMX_Done endp
  184. code segment page public use32 'code' ; Need stricter segment alignment
  185. ; for pentium optimisations
  186. ;*********************************************************************************************
  187. ;* MMX_Single_Line_Trans -- draw a single line of transparent pixels using MMX technology *
  188. ;* *
  189. ;* *
  190. ;* INPUT: Esi - ptr to source data *
  191. ;* Edi - ptr to destination data *
  192. ;* Ecx - width to draw in bytes *
  193. ;* *
  194. ;* OUTPUT: None *
  195. ;* *
  196. ;* Warnings: *
  197. ;* *
  198. ;* HISTORY: *
  199. ;* 05/19/96 ST : Created. *
  200. ;*===========================================================================================*
  201. align 16
  202. MMX_Single_Line_Trans proc near
  203. ;
  204. ; If we are doing less than 8 bytes then dont use MMX
  205. ;
  206. cmp ecx,8
  207. jge @@mmx_loop
  208. push offset Single_Line_Trans_Entry
  209. ret
  210. ;
  211. ; Use MMX instructions to mask 8 bytes at once
  212. ;
  213. ; Creates a bitmask based on the source bytes equality with zero and then uses this to mask
  214. ; out the source bytes in the destination data. The advatage that MMX gives us is that there is
  215. ; no 'test for zero then jump' required to mask.
  216. ;
  217. align 64 ;MMX instructions like 64 byte alignment!
  218. @@mmx_loop:
  219. movq mm0,[esi] ; move 8 bytes of source into mm0
  220. pxor mm1,mm1 ; zero out mm1
  221. pcmpeqb mm1,mm0 ; compare mm0 with 0. Bits get set in mm1
  222. lea esi,[esi+8] ; adjust the source data pointer
  223. pand mm1,[edi] ; and in the destination data to throw away the bytes which arent zero in the source
  224. sub ecx,8 ; adjust the byte counter
  225. por mm1,mm0 ; or in the source with the destination data
  226. movq [edi],mm1 ; write back the destination data
  227. lea edi,[edi+8] ; adjust the destination pointer
  228. cmp ecx,8
  229. jg @@mmx_loop
  230. ;
  231. ; Jump to the approprite code for drawing the end of this line or going to the next one
  232. ;
  233. push offset Next_Line
  234. jcxz @@next_line
  235. push offset Single_Line_Trans_Entry
  236. @@next_line: ret
  237. MMX_Single_Line_Trans endp
  238. code ends
  239. .data
  240. CPUType db 0
  241. VendorID db "Not available",0,0,0,0,0,0
  242. end