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