334 lines
7.4 KiB
NASM
334 lines
7.4 KiB
NASM
page ,132
|
|
subttl emlssng.asm - Load/Store Single Precision Numbers
|
|
;***
|
|
;emlssng.asm - Load/Store Single Precision Numbers
|
|
;
|
|
; Copyright (c) 1984-89, Microsoft Corporation
|
|
;
|
|
;Purpose:
|
|
; Load/Store Single Precision Numbers
|
|
;
|
|
; This Module contains Proprietary Information of Microsoft
|
|
; Corporation and should be treated as Confidential.
|
|
;
|
|
;Revision History:
|
|
; See emulator.hst
|
|
;
|
|
;*******************************************************************************
|
|
|
|
|
|
ProfBegin LSSNG
|
|
|
|
;*********************************************************************;
|
|
; ;
|
|
; Load Single Real ;
|
|
; ;
|
|
;*********************************************************************;
|
|
;
|
|
; Subroutine converts single in regs to internal at ES:SI
|
|
|
|
|
|
pub eFLDsr
|
|
LDUS2AX ; get lower mantissa part
|
|
MOV DI,AX ; 2 keep lower mantissa in DX
|
|
LDUS2AX ; get upper exponent/sign part
|
|
MOV DL,AL ; 2 copy most sig. mantissa byte
|
|
ROL AX,1 ; 2 sign to AL, exponent to AH
|
|
AND AL,1 ; 4 clear all flags except sign
|
|
ROR AL,1 ; 2 get sign in right position
|
|
XCHG AL,AH
|
|
|
|
; AX, DI, DL: operand one
|
|
|
|
PUSHST ; 64 allocate another register
|
|
|
|
pub SingleToInternal
|
|
|
|
OR DL,80H ; Set leading bit of mantissa
|
|
XOR DH,DH ; Set Tag to valid non-zero
|
|
CMP AL,SexpMax ; Is Number NAN or Inf?
|
|
JE short SNANorInf
|
|
if fastSP
|
|
OR AH,Single ; Set single Precision flag
|
|
endif
|
|
CMP AL,SexpMin ; Is Number Zero or Denormal
|
|
JE short SZeroOrDenorm
|
|
; Otherwise number is valid non-zero
|
|
MOV Flag[esi],AH ; Store sign
|
|
SUB AL,SexpBias ; Unbias the exponent
|
|
CBW
|
|
|
|
pub SStoreExpnTag
|
|
MOV Expon[esi],AX ; Store Exponent
|
|
MOV Tag[esi],DH ; Store Tag
|
|
MOV MB7[esi],DL ; Store Mantissa
|
|
MOV MB5[esi],DI
|
|
ife fastSP
|
|
XOR AX,AX ; Clear low order bytes of Mantissa
|
|
MOV MB4[esi],AL
|
|
MOV MB2[esi],AX
|
|
MOV MB0[esi],AX
|
|
endif
|
|
RET
|
|
|
|
pub SNANorInf
|
|
MOV Flag[esi],AH ; Store sign
|
|
MOV AX,IexpMax - IexpBias ; Set exponent to internal max
|
|
MOV DH,Special ; Set Tag to show NAN or Inf
|
|
CMP DL,80H ; If anything other than leading bit
|
|
JNE short SStoreExpnTag ; is set number is NAN (not Inf)
|
|
OR DI,DI
|
|
JNE short SStoreExpnTag
|
|
OR DH,ZROorINF ; Set Tag to show Inf
|
|
JMP SStoreExpnTag
|
|
|
|
pub SZeroorDenorm
|
|
MOV Flag[esi],AH ; Store sign
|
|
CMP DL,80H ; If anything other than leading bit
|
|
JNE short SDenormal ; is set number is Denormal
|
|
OR DI,DI
|
|
JNE short SDenormal
|
|
MOV AX,IexpMin - IexpBias ; Set exponent to internal min
|
|
OR DH,ZROorINF ; Set Tag to show 0
|
|
JMP SStoreExpnTag
|
|
|
|
pub SDenormal
|
|
OR [CURerr],Denormal ; Set Denormal Exception
|
|
SUB AL,SexpBias ; unbias the Exponent
|
|
CBW
|
|
INC AX
|
|
|
|
pub SNormalize
|
|
DEC AX
|
|
SHL DI,1
|
|
RCL DL,1
|
|
OR DL,DL
|
|
JNS SNormalize
|
|
|
|
JMP SStoreExpnTag
|
|
|
|
page
|
|
;************************************************************;
|
|
; ;
|
|
; Store Single Real ;
|
|
; ;
|
|
;************************************************************;
|
|
|
|
pub SSpecial ; number is NAN or INF or Zero
|
|
TEST CL,Special ; NAN or INF?
|
|
JNE short SSNANorINF
|
|
XOR AX,AX ; Number is Zero
|
|
MOV BX,AX
|
|
JMP STRUNC
|
|
|
|
pub SSNANorINF
|
|
TEST CL,ZROorINF
|
|
JNE short SInf
|
|
MOV BX,MB5[esi] ; Number is a NAN
|
|
MOV AL,MB7[esi]
|
|
MOV AH,Flag[esi] ; Pick up Sign
|
|
SHL AX,1 ; Destroy leading bit, Sign to CF
|
|
MOV AH,SexpMax
|
|
RCR AX,1
|
|
JMP STRUNC
|
|
|
|
pub SInf
|
|
MOV AH,Flag[esi]
|
|
JMP SSignedInfinity
|
|
|
|
pub JMPSOver
|
|
JMP SOver
|
|
|
|
pub JMPSUnder
|
|
JMP SUnder
|
|
|
|
; ES:SI: memory address of single
|
|
; stores and misc. operations; first setup register values as follows:
|
|
; AX: TOS flags (for DOUB and SIGN flags)
|
|
; SI: TOS address (offset)
|
|
|
|
pub eFSTsr
|
|
mov edi,esi ; ES:DI = store address
|
|
MOV esi,[CURstk] ; 14 load TOS address
|
|
MOV AX,Flag[esi] ; 21 get TOS flags (sign, double)
|
|
|
|
; convert internal at DS:SI to single
|
|
; DS:SI = TOS, ES:DI = memory, CH = operation (POP), BP = old ES value
|
|
|
|
MOV CL,Tag[esi] ; See if number is NAN or Inf or Zero
|
|
OR CL,CL
|
|
JNZ short SSpecial
|
|
MOV CL,Flag[esi] ; Pick up sign & single precision flag
|
|
|
|
MOV AX,Expon[esi]
|
|
CMP AX,SexpMax - SexpBias
|
|
JGE short JMPSOver
|
|
CMP AX,SexpMin - SexpBias
|
|
JLE short JMPSUnder
|
|
|
|
ADD AL,SexpBias ; Bias the Exponent
|
|
MOV AH,MB7[esi] ; Pick up MSB of Mantissa
|
|
XCHG AH,AL
|
|
SHL AL,1 ; Shift mantissa to destroy leading integer bit
|
|
SHL CL,1 ; Get sign into CF
|
|
RCR AX,1 ; Pack sign, exp, & MSB
|
|
if fastSP
|
|
TEST CL,Single*2 ; if number was single rounding is not needed
|
|
JZ SS1
|
|
MOV BX,MB5[esi]
|
|
JMP SHORT STRUNC
|
|
SS1:
|
|
endif
|
|
MOV DX,MB0[esi] ; DL Will be the sticky bit
|
|
OR DX,MB2[esi] ; DH will be round and the rest of sticky
|
|
OR DL,DH
|
|
XOR DH,DH
|
|
MOV BX,MB5[esi]
|
|
OR DX,MB3[esi]
|
|
JZ short STRUNC ; If no Round or Sticky result is exact
|
|
OR [CURerr],Precision
|
|
|
|
pub SRound ; single in AX:BX:DX
|
|
MOV CL,[CWcntl] ; Need to know Rounding Control
|
|
SHR CL,1
|
|
SHR CL,1
|
|
SHR CL,1
|
|
JC short StDOWNorCHOP24
|
|
SHR CL,1
|
|
JC short StUP24
|
|
|
|
pub StNEAR24
|
|
CMP DX,8000H ; How are round and sticky bits?
|
|
JB short STRUNC ; No round, so truncate
|
|
JA short SINC ; Round and sticky so round up
|
|
TEST BL,1 ; Round and no sticky, is last bit even?
|
|
JZ short STRUNC ; Yes, so truncate.
|
|
|
|
pub SINC
|
|
MOV DL,AL ; Increment mantissa
|
|
ADD BX,1
|
|
ADC AX,0
|
|
XOR DL,AL ; See if we overflowed a bit into the exponent
|
|
JNS short STRUNC ; If not number is now correct so go store
|
|
MOV DX,AX ; Exponent was incremented, see if it overflowed
|
|
SHL DX,1
|
|
CMP DH,SexpMax
|
|
JE short SOver
|
|
|
|
pub StCHOP24
|
|
STRUNC:
|
|
XCHG AX,BX
|
|
STAX2US
|
|
MOV AX,BX
|
|
STAX2US
|
|
|
|
pub SStoreExit
|
|
RET
|
|
|
|
pub StDOWNorCHOP24
|
|
SHR CL,1
|
|
JC short StCHOP24
|
|
|
|
pub StDOWN24
|
|
OR AH,AH ; Test the sign
|
|
JS short SINC
|
|
JMP short STRUNC
|
|
|
|
pub StUP24
|
|
OR AH,AH ; Test the sign
|
|
JS short STRUNC
|
|
JMP short SINC
|
|
|
|
pub SOver ; Number overflowed Single Precision range.
|
|
; Result returned depends upon rounding control
|
|
OR [CURerr],Overflow + Precision
|
|
MOV CL,[CWcntl]
|
|
SHR CL,1
|
|
SHR CL,1
|
|
SHR CL,1
|
|
JC short StMOvDNorCHP24
|
|
|
|
SHR CL,1
|
|
JC short StMOvUP24
|
|
|
|
StMOvNEAR24: ; Masked Overflow Near Rounding
|
|
|
|
pub SSignedInfinity ; Return signed infinity
|
|
MOV BX,[IEEEinfinityS + 2]
|
|
AND AH,Sign ; Overstore the proper sign
|
|
OR BH,AH
|
|
MOV AX,[IEEEinfinityS]
|
|
STAX2US
|
|
MOV AX,BX
|
|
STAX2US
|
|
JMP SStoreExit
|
|
|
|
pub StMOvDNorCHP24
|
|
SHR CL,1
|
|
JC short StMOvCHOP24
|
|
|
|
pub StMOvDOWN24 ; Masked Overflow Down Rounding
|
|
TEST AH,Sign ; Positive goes to biggest
|
|
JNZ short SSignedInfinity
|
|
|
|
StMOvCHOP24: ; Masked Overflow Chop Rounding
|
|
pub SSignedBiggest
|
|
MOV BX,[IEEEbiggestS + 2]
|
|
AND AH,Sign ; Overstore the proper sign
|
|
OR AH,BH
|
|
MOV AL,BL
|
|
STAX2US
|
|
MOV AX,[IEEEbiggestS]
|
|
STAX2US
|
|
JMP SStoreExit
|
|
|
|
pub StMOvUP24 ; Masked Overflow Up Rounding
|
|
TEST AH,Sign ; Negative goes to biggest
|
|
JZ short SSignedInfinity
|
|
JMP SSignedBiggest
|
|
|
|
pub SUnder ; Masked Underflow - Try to denormalize
|
|
OR [CURerr],Underflow+Precision
|
|
NEG AX ; Convert exponent (which is too small)
|
|
ADD AX,SexpMin-SexpBias+1 ; To a positive shift count
|
|
CMP AX,24 ; Is shift more than mantissa precision
|
|
JGE short Szero
|
|
XCHG CX,AX
|
|
ifdef i386
|
|
movzx ecx,cx ; (ecx) = zero-extended loop count
|
|
endif
|
|
MOV DX,MB0[esi] ; Pick up Insignif bytes for sticky bit
|
|
OR DX,MB2[esi]
|
|
MOV AL,DL
|
|
OR AL,DH
|
|
MOV DX,MB4[esi]
|
|
MOV BX,MB6[esi]
|
|
OR AL,AL
|
|
JZ short SSHIFTR
|
|
OR DL,1 ; Set the sticky bit
|
|
|
|
pub SSHIFTR
|
|
SHR BX,1
|
|
RCR DX,1
|
|
JNC short SSLOOP
|
|
OR DL,1
|
|
pub SSLOOP
|
|
LOOP SSHIFTR
|
|
|
|
XCHG AH,CH ; Restore operation to CH
|
|
MOV AH,Flag[esi] ; Pick up sign
|
|
AND AH,Sign ; Mask to sign only
|
|
MOV AL,BH ; Biased exponent for a denormal is 0
|
|
MOV BH,BL
|
|
MOV BL,DH
|
|
MOV DH,DL
|
|
XOR DL,DL
|
|
JMP SRound
|
|
|
|
pub Szero
|
|
XOR AX,AX
|
|
MOV BX,AX
|
|
JMP STRUNC ; Go store single and exit
|
|
|
|
ProfEnd LSSNG
|