subttl emfmul.asm - Multiplication page ;******************************************************************************* ; Copyright (c) Microsoft Corporation 1991 ; All Rights Reserved ; ;emfmul.asm - long double multiply ; by Tim Paterson ; ;Purpose: ; Long double multiplication. ;Inputs: ; ebx:esi = op1 mantissa ; ecx = op1 sign in bit 15, exponent in high half ; edi = pointer to op2 and result location ; [Result] = edi ; ; Exponents are unbiased. Denormals have been normalized using ; this expanded exponent range. Neither operand is allowed to be zero. ;Outputs: ; Jumps to [RoundMode] to round and store result. ; ;Revision History: ; ; [] 09/05/91 TP Initial 32-bit version. ; ;******************************************************************************* ;Dispatch table for multiply ; ;One operand has been loaded into ecx:ebx:esi ("source"), the other is ;pointed to by edi ("dest"). ; ;Tag of source is shifted. Tag values are as follows: .erre TAG_SNGL eq 0 ;SINGLE: low 32 bits are zero .erre TAG_VALID eq 1 .erre TAG_ZERO eq 2 .erre TAG_SPCL eq 3 ;NAN, Infinity, Denormal, Empty ;Any special case routines not found in this file are in emarith.asm tFmulDisp label dword ;Source (reg) Dest (*[di]) dd MulSingle ;single single dd MulDouble ;single double dd XorDestSign ;single zero dd MulSpclDest ;single special dd MulDouble ;double single dd MulDouble ;double double dd XorDestSign ;double zero dd MulSpclDest ;double special dd XorSourceSign ;zero single dd XorSourceSign ;zero double dd XorDestSign ;zero zero dd MulSpclDest ;zero special dd MulSpclSource ;special single dd MulSpclSource ;special double dd MulSpclSource ;special zero dd TwoOpBothSpcl ;special special dd XorDestSign ;Two infinities EM_ENTRY eFIMUL16 eFIMUL16: push offset MulSetResult jmp Load16Int ;Returns to MulSetResult EM_ENTRY eFIMUL32 eFIMUL32: push offset MulSetResult jmp Load32Int ;Returns to MulSetResult EM_ENTRY eFMUL32 eFMUL32: push offset MulSetResult jmp Load32Real ;Returns to MulSetResult EM_ENTRY eFMUL64 eFMUL64: push offset MulSetResult jmp Load64Real ;Returns to MulSetResult EM_ENTRY eFMULPreg eFMULPreg: push offset PopWhenDone EM_ENTRY eFMULreg eFMULreg: xchg esi,edi EM_ENTRY eFMULtop eFMULtop: mov ecx,EMSEG:[esi].ExpSgn mov ebx,EMSEG:[esi].lManHi mov esi,EMSEG:[esi].lManLo MulSetResult: mov ebp,offset tFmulDisp mov EMSEG:[Result],edi ;Save result pointer mov al,cl or al,EMSEG:[edi].bTag cmp al,bTAG_VALID .erre bTAG_VALID eq 1 .erre bTAG_SNGL eq 0 jz MulDouble ja TwoOpResultSet ;.erre MulSingle eq $ ;Fall into MulSingle ;********* MulSingle: ;********* mov edx,EMSEG:[edi].ExpSgn mov eax,EMSEG:[edi].lManHi ;op1 mantissa in ebx:esi, exponent in high ecx, sign in ch bit 7 ;op2 high mantissa in eax, exponent in high edx, sign in dh bit 7 xor ch,dh ;Compute result sign xor dx,dx ;Clear out sign and tag add ecx,edx ;Result exponent .erre TexpBias eq 0 ;Exponents not biased jo SMulBigUnderflow ;Multiplying two denormals ContSmul: ;Value in ecx is correct exponent if result is not normalized. ;If result comes out normalized, 1 will be added. mul ebx ;Compute product mov ebx,edx mov esi,eax xor eax,eax ;Extend with zero ;Result in ebx:esi:eax ;ecx = exponent minus one in high half, sign in ch or ebx,ebx ;Check for normalization jns ShiftOneBit ;In emfadd.asm add ecx,1 shl 16 ;Adjust exponent jmp EMSEG:[RoundMode] SMulBigUnderflow: or EMSEG:[CURerr],Underflow add ecx,Underbias shl 16 ;Fix up exponent test EMSEG:[CWmask],Underflow ;Is exception masked? jz ContSmul ;No, continue with multiply UnderflowZero: or EMSEG:[CURerr],Precision SignedZero: and ecx,bSign shl 8 ;Preserve sign bit xor ebx,ebx mov esi,ebx mov cl,bTAG_ZERO jmp EMSEG:[ZeroVector] ;******************************************************************************* DMulBigUnderflow: ;Overflow flag set could only occur with denormals (true exp < -32768) or EMSEG:[CURerr],Underflow test EMSEG:[CWmask],Underflow ;Is exception masked? jnz UnderflowZero ;Yes, return zero add ecx,Underbias shl 16 ;Fix up exponent jmp ContDmul ;Continue with multiply PolyMulToZero: ret ;Return the zero in registers PolyMulDouble: ;This entry point is used by polynomial evaluator. ;It checks the operand in registers for zero. cmp cl,bTAG_ZERO ;Adding to zero? jz PolyMulToZero ;********* MulDouble: ;********* mov eax,EMSEG:[edi].ExpSgn mov edx,EMSEG:[edi].lManHi mov edi,EMSEG:[edi].lManLo MulDoubleReg: ;Entry point used by transcendentals ;op1 mantissa in ebx:esi, exponent in high ecx, sign in ch bit 7 ;op2 mantissa in edx:edi, exponent in high eax, sign in ah bit 7 xor ch,ah ;Compute result sign xor ax,ax ;Clear out sign and tag add ecx,eax ;Result exponent .erre TexpBias eq 0 ;Exponents not biased jo DMulBigUnderflow ;Multiplying two denormals ContDmul: ;Value in ecx is correct exponent if result is not normalized. ;If result comes out normalized, 1 will be added. mov ebp,edx ;edx is used by MUL instruction ;Generate and sum partial products, from least to most significant mov eax,edi mul esi ;Lowest partial product add eax,-1 ;CY set IFF eax<>0 sbb cl,cl ;Sticky bit: 0 if zero, -1 if nz xchg edi,edx ;Save high result ;First product: cl reflects low dword non-zero (sticky bit), edi has high dword mov eax,ebx mul edx add edi,eax adc edx,0 ;Sum first results xchg edx,esi ;High result to esi ;Second product: accumulated in esi:edi:cl mov eax,ebp ;Next mult. to eax mul edx add edi,eax ;Sum low results adc esi,edx ;Sum high results mov eax,ebx mov ebx,0 ;Preserve CY flag adc ebx,ebx ;Keep carry out of high sum ;Third product: accumulated in ebx:esi:edi:cl mul ebp add esi,eax adc ebx,edx mov eax,edi or al,cl ;Collapse sticky bits into eax ;Result in ebx:esi:eax ;ecx = exponent minus one in high half, sign in ch MulDivNorm: or ebx,ebx ;Check for normalization jns ShiftOneBit ;In emfadd.asm add ecx,1 shl 16 ;Adjust exponent jmp EMSEG:[RoundMode]