239 lines
6 KiB
NASM
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]
|