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