windows-nt/Source/XPSP1/NT/base/ntdll/i386/emfmul.asm
2020-09-26 16:20:57 +08:00

239 lines
6 KiB
NASM

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]