417 lines
10 KiB
NASM
417 lines
10 KiB
NASM
subttl emload.asm - FLD and FILD instructions
|
|
page
|
|
;*******************************************************************************
|
|
;emload.asm - FLD and FILD instructions
|
|
;
|
|
; Microsoft Confidential
|
|
;
|
|
; Copyright (c) Microsoft Corporation 1991
|
|
; All Rights Reserved
|
|
;
|
|
;Purpose:
|
|
; FLD and FILD instructions
|
|
;Inputs:
|
|
; edi = [CURstk]
|
|
; dseg:esi = pointer to memory operand
|
|
;
|
|
;Revision History:
|
|
;
|
|
; [] 09/05/91 TP Initial 32-bit version.
|
|
;
|
|
;*******************************************************************************
|
|
|
|
|
|
PrevStackWrap edi,LdStk ;Tied to PrevStackElem below
|
|
|
|
;*******
|
|
EM_ENTRY eFLDreg
|
|
eFLDreg:
|
|
;*******
|
|
; edi = [CURstk]
|
|
; esi = pointer to st(i) from instruction field
|
|
|
|
PrevStackElem edi,LdStk ;Point to receiving location
|
|
cmp EMSEG:[edi].bTag,bTAG_EMPTY ;Is it empty?
|
|
jnz FldErr
|
|
mov ecx,EMSEG:[esi].ExpSgn
|
|
cmp cl,bTAG_EMPTY
|
|
jz FldErr
|
|
mov ebx,EMSEG:[esi].lManHi
|
|
mov esi,EMSEG:[esi].lManLo
|
|
mov EMSEG:[CURstk],edi
|
|
mov EMSEG:[edi].lManLo,esi
|
|
mov EMSEG:[edi].lManHi,ebx
|
|
mov EMSEG:[edi].ExpSgn,ecx
|
|
ret
|
|
|
|
|
|
;This is common code that stores a value into the stack after being loaded
|
|
;into registers by the appropriate routine.
|
|
|
|
PrevStackWrap edi,Load ;Tied to PrevStackElem below
|
|
|
|
FldCont:
|
|
;mantissa in ebx:esi, exp/sign in ecx
|
|
;edi = [CURstk]
|
|
PrevStackElem edi,Load ;Point to receiving location
|
|
cmp EMSEG:[edi].bTag,bTAG_EMPTY ;Is it empty?
|
|
jnz FldErr
|
|
cmp cl,bTAG_NAN ;Returning a NAN?
|
|
jz FldNAN
|
|
SaveStack:
|
|
mov EMSEG:[CURstk],edi
|
|
mov EMSEG:[edi].lManLo,esi
|
|
mov EMSEG:[edi].lManHi,ebx
|
|
mov EMSEG:[edi].ExpSgn,ecx
|
|
ret
|
|
|
|
FldErr:
|
|
or EMSEG:[SWcc],C1 ;Signal overflow
|
|
mov EMSEG:[CURerr],StackFlag;Kills possible denormal exception
|
|
Unsupported:
|
|
call ReturnIndefinite ;in emarith.asm
|
|
jz FldExit ;Unmasked, do nothing
|
|
mov EMSEG:[CURstk],edi ;Update top of stack
|
|
FldExit:
|
|
ret
|
|
|
|
FldNAN:
|
|
;Is it a signaling NAN?
|
|
test ebx,1 shl 30 ;Check for SNAN
|
|
jnz SaveStack ;If QNAN, just use it as result
|
|
or EMSEG:[CURerr],Invalid ;Flag the error
|
|
or ebx,1 shl 30 ;Make it into a QNAN
|
|
test EMSEG:[CWmask],Invalid ;Is it masked?
|
|
jnz SaveStack ;If so, update with masked response
|
|
ret
|
|
|
|
|
|
;****************
|
|
;Load Single Real
|
|
;****************
|
|
|
|
EM_ENTRY eFLD32
|
|
eFLD32:
|
|
push offset FldCont ;Return address
|
|
;Fall into Load32Real
|
|
Load32Real:
|
|
;dseg:esi points to IEEE 32-bit real number
|
|
;On exit:
|
|
; mantissa in ebx:esi, exponent in high ecx, sign in ch bit 7, tag in cl
|
|
;preserves edi.
|
|
|
|
mov EMSEG:[PrevDataOff],esi ;Save operand pointer
|
|
mov ecx,dseg:[esi] ;Get number
|
|
mov ebx,ecx ;Save copy of mantissa
|
|
shl ebx,8 ;Normalize
|
|
shr ecx,7 ;Bring exponent down
|
|
and ecx,0FFH shl 16 ;Look at just exponent
|
|
mov ch,dseg:[esi+3] ;Get sign again
|
|
jz short ZeroOrDenorm32 ;Exponent is zero
|
|
xor esi,esi ;Zero out the low bits
|
|
or ebx,1 shl 31 ;Set implied bit
|
|
cmp ecx,SexpMax shl 16
|
|
jge NANorInf ;Max exp., must be NAN or Infinity
|
|
add ecx,(TexpBias-SexpBias) shl 16 ;Change to extended format bias
|
|
mov cl,bTAG_SNGL
|
|
ret
|
|
|
|
ZeroOrDenorm32:
|
|
;Exponent is zero. Number is either zero or denormalized
|
|
xor esi,esi ;Zero out the low bits
|
|
and ebx,not (1 shl 31) ;Keep just mantissa
|
|
jnz Norm32
|
|
mov cl,bTAG_ZERO
|
|
ret
|
|
|
|
Norm32:
|
|
add ecx,(TexpBias-SexpBias+1-31) shl 16 ;Fix up bias
|
|
jmp FixDenorm
|
|
|
|
|
|
NANorInf:
|
|
;Shared by single and double real
|
|
and ecx,bSign shl 8 ;Save only sign in ch
|
|
or ecx,TexpMax shl 16 + bTAG_NAN ;Max exp.
|
|
cmp ebx,1 shl 31 ;Only 1 bit set means infinity
|
|
jnz @F
|
|
or esi,esi
|
|
jnz @F
|
|
mov cl,bTAG_INF
|
|
@@:
|
|
ret
|
|
|
|
;****************
|
|
;Load Double Real
|
|
;****************
|
|
|
|
EM_ENTRY eFLD64
|
|
eFLD64:
|
|
push offset FldCont ;Return address
|
|
;Fall into Load64Real
|
|
Load64Real:
|
|
;dseg:esi points to IEEE 64-bit real number
|
|
;On exit:
|
|
; mantissa in ebx:esi, exponent in high ecx, sign in ch bit 7, tag in cl
|
|
;preserves edi.
|
|
|
|
mov EMSEG:[PrevDataOff],esi ;Save operand pointer
|
|
mov ecx,dseg:[esi+4] ;Get sign, exp., and high mantissa
|
|
mov ebx,ecx ;Save copy of mantissa
|
|
shr ecx,4 ;Bring exponent down
|
|
and ecx,7FFH shl 16 ;Look at just exponent
|
|
mov ch,dseg:[esi+7] ;Get sign again
|
|
mov esi,dseg:[esi] ;Get low 32 bits of op
|
|
jz short ZeroOrDenorm64 ;Exponent is zero
|
|
shld ebx,esi,31-20
|
|
shl esi,31-20 ;Normalize
|
|
or ebx,1 shl 31 ;Set implied bit
|
|
cmp ecx,DexpMax shl 16
|
|
jge NANorInf ;Max exp., must be NAN or Infinity
|
|
add ecx,(TexpBias-DexpBias) shl 16 ;Change to extended format bias
|
|
SetNormTag:
|
|
or esi,esi ;Any bits in low half?
|
|
.erre bTAG_VALID eq 1
|
|
.erre bTAG_SNGL eq 0
|
|
setnz cl ;if low half==0 then cl=0 else cl=1
|
|
ret
|
|
|
|
ZeroOrDenorm64:
|
|
;Exponent is zero. Number is either zero or denormalized
|
|
and ebx,0FFFFFH ;Keep just mantissa
|
|
jnz ShortNorm64 ;Are top 20 bits zero?
|
|
or esi,esi ;Are low 32 bits zero too?
|
|
jnz LongNorm64
|
|
mov cl,bTAG_ZERO
|
|
ret
|
|
|
|
LongNorm64:
|
|
xchg ebx,esi ;Shift up 32 bits
|
|
sub ecx,32 shl 16 ;Correct exponent
|
|
ShortNorm64:
|
|
add ecx,(TexpBias-DexpBias+12-31) shl 16 ;Fix up bias
|
|
FixDenorm:
|
|
or EMSEG:[CURerr],Denormal ;Set Denormal Exception
|
|
bsr edx,ebx ;Scan for MSB
|
|
;Bit number in edx ranges from 0 to 31
|
|
mov cl,dl
|
|
not cl ;Convert bit number to shift count
|
|
shld ebx,esi,cl
|
|
shl esi,cl
|
|
shl edx,16 ;Move exp. adjustment to high end
|
|
add ecx,edx ;Adjust exponent
|
|
jmp SetNormTag
|
|
|
|
|
|
;******************
|
|
;Load Short Integer
|
|
;******************
|
|
|
|
EM_ENTRY eFILD16
|
|
eFILD16:
|
|
push offset FldCont ;Return address
|
|
;Fall into Load16Int
|
|
Load16Int:
|
|
;dseg:esi points to 16-bit integer
|
|
;On exit:
|
|
; mantissa in ebx:esi, exponent in high ecx, sign in ch bit 7, tag in cl
|
|
;preserves edi.
|
|
|
|
mov EMSEG:[PrevDataOff],esi ;Save operand pointer
|
|
mov ax,dseg:[esi]
|
|
NormInt16:
|
|
xor esi,esi ;Extend with zero
|
|
cwd ;extend sign through dx
|
|
xor ax,dx
|
|
sub ax,dx ;Take ABS() of integer
|
|
bsr cx,ax ;Find MSB
|
|
jz ZeroInt
|
|
;Bit number in cx ranges from 0 to 15
|
|
not ecx ;Convert to shift count
|
|
shl eax,cl ;Normalize
|
|
not ecx
|
|
.erre TexpBias eq 0
|
|
shl ecx,16 ;Move exponent to high half
|
|
mov ch,dh ;Set sign
|
|
mov ebx,eax ;Mantissa to ebx
|
|
mov cl,bTAG_SNGL
|
|
ret
|
|
|
|
ZeroInt:
|
|
xor ebx,ebx
|
|
mov ecx,ebx
|
|
mov cl,bTAG_ZERO
|
|
ret
|
|
|
|
|
|
;******************
|
|
;Load Long Integer
|
|
;******************
|
|
|
|
EM_ENTRY eFILD32
|
|
eFILD32:
|
|
push offset FldCont ;Return address
|
|
;Fall into Load32Int
|
|
Load32Int:
|
|
;dseg:esi points to 32-bit integer
|
|
;On exit:
|
|
; mantissa in ebx:esi, exponent in high ecx, sign in ch bit 7, tag in cl
|
|
;preserves edi.
|
|
|
|
mov EMSEG:[PrevDataOff],esi ;Save operand pointer
|
|
mov eax,dseg:[esi]
|
|
xor esi,esi ;Extend with zero
|
|
or eax,eax ;It it zero?
|
|
jz ZeroInt
|
|
cdq ;extend sign through edx
|
|
xor eax,edx
|
|
sub eax,edx ;Take ABS() of integer
|
|
mov ebx,eax ;Mantissa to ebx
|
|
;BSR uses 3 clocks/bit, so speed it up by checking the top half
|
|
;This saves 36 clocks on 386 (42 on 486sx)
|
|
;Cost is 13 clocks on 386 if high word isn't zero (5 on 486sx)
|
|
.erre TexpBias eq 0
|
|
xor eax,eax ;Initialize exponent
|
|
cmp ebx,0FFFFH ;Upper bits zero?
|
|
ja @F
|
|
shl ebx,16
|
|
sub eax,16
|
|
@@:
|
|
bsr ecx,ebx ;Find MSB
|
|
add eax,ecx ;Compute expoment
|
|
not cl ;Convert bit number to shift count
|
|
shl ebx,cl ;Normalize
|
|
shrd ecx,eax,16 ;Move exponent to high half of ecx
|
|
mov ch,dh ;Set sign
|
|
mov cl,bTAG_SNGL
|
|
ret
|
|
|
|
|
|
;*****************
|
|
;Load Quad Integer
|
|
;*****************
|
|
|
|
EM_ENTRY eFILD64
|
|
eFILD64:
|
|
mov EMSEG:[PrevDataOff],esi ;Save operand pointer
|
|
mov ebx,dseg:[esi+4] ;Get high 32 bits
|
|
mov eax,ebx ;Make copy of sign
|
|
mov esi,dseg:[esi] ;Get low 32 bits
|
|
mov ecx,ebx
|
|
or ecx,esi ;Is it zero?
|
|
jz ZeroQuad
|
|
NormQuadInt:
|
|
;Entry point from eFBLD
|
|
;eax bit 31 = sign
|
|
;ebx:esi = integer
|
|
;edi = [CURstk]
|
|
.erre TexpBias eq 0
|
|
mov ax,32 ;Initialize exponent
|
|
or ebx,ebx ;Check sign
|
|
jz LongNormInt
|
|
jns FindBit
|
|
not ebx
|
|
neg esi ;CY set if non-zero
|
|
sbb ebx,-1 ;Add one if esi == 0
|
|
jnz FindBit ;Check for high bits zero
|
|
LongNormInt:
|
|
xchg ebx,esi ;Normalize 32 bits
|
|
xor ax,ax ;Reduce exponent by 32
|
|
FindBit:
|
|
;BSR uses 3 clocks/bit, so speed it up by checking the top half
|
|
;This saves 35 clocks on 386 (41 on 486sx)
|
|
;Cost is 11 clocks on 386 if high word isn't zero (4 on 486sx)
|
|
cmp ebx,0FFFFH ;Upper bits zero?
|
|
ja @F
|
|
shld ebx,esi,16
|
|
shl esi,16
|
|
sub eax,16
|
|
@@:
|
|
bsr ecx,ebx ;Find MSB
|
|
add eax,ecx ;Compute expoment
|
|
not cl ;Convert bit number to shift count
|
|
shld ebx,esi,cl ;Normalize
|
|
shl esi,cl
|
|
mov ecx,eax ;Move sign and exponent to ecx
|
|
rol ecx,16 ;Swap sign and exponent halves
|
|
or esi,esi ;Any bits in low half?
|
|
.erre bTAG_VALID eq 1
|
|
.erre bTAG_SNGL eq 0
|
|
setnz cl ;if low half==0 then cl=0 else cl=1
|
|
jmp FldCont
|
|
|
|
ZeroQuad:
|
|
mov cl,bTAG_ZERO
|
|
jmp FldCont
|
|
|
|
|
|
;****************
|
|
;Load Temp Real
|
|
;****************
|
|
|
|
PrevStackWrap edi,Ld80 ;Tied to PrevStackElem below
|
|
|
|
EM_ENTRY eFLD80
|
|
eFLD80:
|
|
;This is not considered an "arithmetic" operation (like all the others are),
|
|
;so SNANs do NOT cause an exception. However, unsupported formats do.
|
|
mov EMSEG:[PrevDataOff],esi ;Save operand pointer
|
|
PrevStackElem edi,Ld80 ;Point to receiving location
|
|
cmp EMSEG:[edi].bTag,bTAG_EMPTY ;Is it empty?
|
|
jnz FldErr
|
|
LoadTempReal:
|
|
mov ebx,dseg:[esi+4] ;Get high half of mantissa
|
|
mov cx,dseg:[esi+8] ;Get exponent and sign
|
|
mov esi,dseg:[esi] ;Get low half of mantissa
|
|
mov eax,ecx
|
|
and ch,7FH ;Mask off sign bit
|
|
shl ecx,16 ;Move exponent to high end
|
|
mov ch,ah ;Restore sign
|
|
jz ZeroOrDenorm80
|
|
;Check for unsupported format: unnormals (MSB not set)
|
|
or ebx,ebx
|
|
jns Unsupported
|
|
sub ecx,(IexpBias-TexpBias) shl 16 ;Correct the bias
|
|
cmp ecx,TexpMax shl 16
|
|
jge NANorInf80
|
|
SetupTag:
|
|
or esi,esi ;Any bits in low half?
|
|
.erre bTAG_VALID eq 1
|
|
.erre bTAG_SNGL eq 0
|
|
setnz cl ;if low half==0 then cl=0 else cl=1
|
|
jmp SaveStack
|
|
|
|
NANorInf80:
|
|
mov cl,bTAG_NAN
|
|
cmp ebx,1 shl 31 ;Only 1 bit set means infinity
|
|
jnz SaveStack
|
|
or esi,esi
|
|
jnz SaveStack
|
|
mov cl,bTAG_INF
|
|
jmp SaveStack
|
|
|
|
ZeroOrDenorm80:
|
|
;Exponent is zero. Number is either zero or denormalized
|
|
or ebx,ebx
|
|
jnz ShortNorm80 ;Are top 32 bits zero?
|
|
or esi,esi ;Are low 32 bits zero too?
|
|
jnz LongNorm80
|
|
mov cl,bTAG_ZERO
|
|
jmp SaveStack
|
|
|
|
;This code accepts and works correctly with pseudo-denormals (MSB already set)
|
|
LongNorm80:
|
|
xchg ebx,esi ;Shift up 32 bits
|
|
sub ecx,32 shl 16 ;Correct exponent
|
|
ShortNorm80:
|
|
add ecx,(TexpBias-IexpBias+1-31) shl 16 ;Fix up bias
|
|
bsr edx,ebx ;Scan for MSB
|
|
;Bit number in edx ranges from 0 to 31
|
|
mov cl,dl
|
|
not cl ;Convert bit number to shift count
|
|
shld ebx,esi,cl
|
|
shl esi,cl
|
|
shl edx,16 ;Move exp. adjustment to high end
|
|
add ecx,edx ;Adjust exponent
|
|
jmp SetUpTag
|