windows-nt/Source/XPSP1/NT/base/mvdm/wow16/win87em/emnormal.asm
2020-09-26 16:20:57 +08:00

375 lines
7.4 KiB
NASM

page ,132
subttl emnormal.asm - Normalize and Round
;***
;emnormal.asm - Normalize and Round
;
; Copyright (c) 1986-89, Microsoft Corporation
;
;Purpose:
; Normalize and Round.
;
; This Module contains Proprietary Information of Microsoft
; Corporation and should be treated as Confidential.
;
;Revision History:
; See emulator.hst
;
;*******************************************************************************
ProfBegin NORMAL
;------------------------------------------;
; ;
; Double Precision Normalize and Round ;
; ;
;------------------------------------------;
even
pub NODRQQ
; Normalize the double precision number
; All arithmetic operations exit through NODRQQ or RNDR7Q
; Mantissa in DI:BX:CX:DX:BP, Exponent in SI, sign on Stack, old BP on Stack
MOV AL,4 ; Maximum of 4 word shifts, sign in AH(6)
pub DNOR
OR DI,DI ; See if any bits on in high word
JNZ short HIBYT ; If so, go check high byte for zero
SUB SI,16 ; Drop exponent by shift count
DEC AL ; Bump count
JZ short NORZERO
MOV DI,BX
MOV BX,CX
MOV CX,DX
MOV DX,BP
XOR BP,BP
JMP DNOR
pub NORZERO ; Here if result after normalization is zero
MOV esi,offset IEEEzero
MOV edi,[RESULT]
POP eax ; Throw out sign on stack
POP ebp ; Restore Old BP
JMP csMOVRQQ ; Move IEEE zero to TOS and return
even
pub HIBYT
TEST DI,0FF00H ; See if high byte is zero
JNZ short NORMSHF2
SUB SI,8 ; Drop exponent by shift amount
pub DN2
XCHG AX,DI
MOV AH,AL
MOV AL,BH
MOV BH,BL
MOV BL,CH
MOV CH,CL
MOV CL,DH
MOV DH,DL
XCHG AX,DI
XCHG AX,BP
MOV DL,AH
MOV AH,AL
XOR AL,AL
XCHG AX,BP
even
pub NORMSHF2
TEST DI,8000H ; Normalization complete?
JNZ ROUND ; Normalization complete
pub NORMLP ; Have to shift left
DEC SI ; Account for shift in exponent
SHL BP,1
RCL DX,1
RCL CX,1
RCL BX,1
RCL DI,1
TEST DI,8000H ; Check for normalized result
JZ NORMLP ; Bit will be set when normalized
JMP short ROUND
pub ROUND24 ; Round to 24 bits
OR DX,BP ; See if result fits exactly in 24 bits
OR CX,DX
OR CL,CH
MOV CH,BL
OR CX,CX
JZ short JEXACT
OR [CURerr],Precision ; Set flag on inexact result
SHR AL,1
JC short DOWNorCHOP24
SHR AL,1
JC short UP24
pub NEAR24 ; Round to nearest or Even
CMP CX,8000H
JA short INC24 ; Remainder Bigger then .5 so Bump up
JB short MSK24 ; Remainder Less then .5 so Mask off
TEST BH,1 ; Remainder = .5 so see if even
JZ short MSK24 ; When even Mask
JMP short INC24 ; When odd Bump up
pub UP24
POP eax ; Get the sign
PUSH eax
SHL AH,1
JC short MSK24 ; Trunc neg numbers to move toward + Inf
JMP short INC24
pub DOWNorCHOP24
SHR AL,1
JC short CHOP24
pub DOWN24
POP eax ; Get the sign
PUSH eax
SHL AH,1
JC short INC24
JMP short MSK24 ; Trunc Pos numbers to move toward - Inf
pub INC24
ADD BH,1
ADC DI,0
JNC short MSK24
MOV DI,8000H ; Number overflowed from 1,111... to 10,000...
INC SI ; Bump up Exponent
pub CHOP24
MSK24: ; Mask off insignificant bits
XOR BP,BP
MOV DX,BP
MOV CX,DX
MOV BL,CL
pub JEXACT
JMP EXACT
even
pub NORMSHF ; from multiply only
TEST DI,8000H ; Normalization complete?
JNZ ROUND ; Normalization complete
DEC SI ; Account for shift in exponent
SHL BP,1
RCL DX,1
RCL CX,1
RCL BX,1
RCL DI,1
even
; mantissa in DI:BX:CX:DX:BP
pub ROUND ; Drop into ROUND when normalized
MOV AL,[CWcntl] ; Pick up hi byte of control word
SHR AL,1 ; Which has Rounding & Precision Control
jnc short ROUND53
pub ROUND64 ; Round to 64 bits
SHR AL,1 ; Remove other bit of Precision control
OR BP,BP ; See if result fits exactly in 64 bits
JZ short EXACT
OR [CURerr],Precision ; Set flag on inexact result
SHR AL,1
JC short DOWNorCHOP64
SHR AL,1
JC short UP64
pub NEAR64 ; Round to nearest or Even
CMP BP,8000H
JA short INC64 ; Remainder Bigger then .5 so Bump up
JB short MSK64 ; Remainder Less then .5 so Mask off
TEST DL,1 ; Remainder = .5 so see if even
JZ short MSK64 ; When even Mask
pub INC64
XOR BP,BP ; Need a 0
ADD DX,1
ADC CX,BP
ADC BX,BP
ADC DI,BP
JNC short EXACT
MOV DI,8000H ; Number overflowed from 1,111... to 10,000...
INC SI ; Bump up Exponent
even
CHOP64:
MSK64: ; Mask off insignificant bits
pub EXACT
MOV eax,[RESULT]
XCHG eax,edi
MOV MB0[edi],DX ; Save Mantissa
MOV MB2[edi],CX
MOV MB4[edi],BX
MOV MB6[edi],AX
POP eax ; Fetch Sign
POP ebp ; Fetch Old BP
AND AH,Sign ; Mask off single precision
MOV Flag[edi],AH
CMP SI,IexpMax - IexpBias ; Test for overflow
JGE short jOVER
CMP SI,IexpMin - IexpBias ; Test for Underflow
JLE short UNDER
pub NORTAG
MOV Expon[edi],SI
MOV byte ptr Tag[edi],0 ; Number is in range and on TOS so ret
RET
jOVER: jmp OVER
pub UP64
POP eax ; Get the sign
PUSH eax
SHL AH,1
JC short MSK64 ; Trunc neg numbers to move toward + Inf
JMP short INC64
pub DOWNorCHOP64
SHR AL,1
JC short CHOP64
pub DOWN64
POP eax ; Get the sign
PUSH eax
SHL AH,1
JC short INC64
JMP short MSK64 ; Trunc Pos numbers to move toward - Inf
jROUND24:
jmp ROUND24
pub ROUND53 ; Round to 53 bits (or 24)
SHR AL,1
JNC short jROUND24
XCHG BP,AX ; See if result fits exactly in 53 bits
OR AL,AH
OR AL,DL
MOV AH,DH
AND AH,007H
AND DH,0F8H
XCHG BP,AX
OR BP,BP
JZ EXACT
OR [CURerr],Precision ; Set flag on inexact result
SHR AL,1
JC short DOWNorCHOP53
SHR AL,1
JC short UP53
pub NEAR53 ; Round to nearest or Even
CMP BP,0400H
JA short INC53 ; Remainder Bigger then .5 so Bump up
JB short MSK53 ; Remainder Less then .5 so Mask off
TEST DH,08H ; Remainder = .5 so see if even
JZ short MSK53 ; When even Mask
JMP short INC53 ; When odd Bump up
pub UNDER
MUNDER: ; Masked Underflow
MOV esi,offset IEEEzero
CALL csMOVRQQ
MOV Flag[edi],AH ; Overstore correct sign
RET
pub UP53
POP eax ; Get the sign
PUSH eax
SHL AH,1
JC short MSK53 ; Trunc neg numbers to move toward + Inf
JMP short INC53
pub DOWNorCHOP53
SHR AL,1
JC short CHOP53
pub DOWN53
POP eax ; Get the sign
PUSH eax
SHL AH,1
JC short INC53
JMP short MSK53 ; Trunc Pos numbers to move toward - Inf
pub INC53
XOR BP,BP ; Need a 0
ADD DH,08H
ADC CX,BP
ADC BX,BP
ADC DI,BP
JNC short MSK53
MOV DI,8000H ; Number overflowed from 1,111... to 10,000...
INC SI ; Bump up Exponent
pub CHOP53
MSK53: ; Mask off insignificant bits
XOR BP,BP
XOR DL,DL ; Note: The garbage in DH was masked off at ROUND53
JMP EXACT
PAGE
pub OVER ; Here if number overflowed
MOVER: ; The masked response to rounding depends on whether rounding
; is directed or not. If it is then Overflow flag is not set
; but precision is. Also the result is set to Inf or Biggest
; If rounding is not directed then Overflow is set and result
; is set to Inf.
OR [CURerr],Overflow
MOV AL,[CWcntl]
SHR AL,1
SHR AL,1
SHR AL,1
JC short MOvDNorCHP
SHR AL,1
JC short MOvUP
MOvNEAR: ; Masked Overflow Near Rounding
pub SignedInfinity ; Return signed infinity
MOV esi,offset IEEEinfinity
CALL csMOVRQQ
MOV Flag[edi],AH ; Overstore the proper sign
RET
pub MOvDNorCHP
SHR AL,1
JC short MOvCHOP
pub MOvDOWN ; Masked Overflow Down Rounding
OR [CURerr],Precision
TEST AH,Sign ; Positive goes to biggest
JNZ short SignedInfinity
MOvCHOP: ; Masked Overflow Chop Rounding
pub SignedBiggest
MOV esi,offset IEEEbiggest
CALL csMOVRQQ
MOV Flag[edi],AH ; Overstore the proper sign
RET
pub MOvUP ; Masked Overflow Up Rounding
OR [CURerr],Precision
TEST AH,Sign ; Negative goes to biggest
JZ short SignedInfinity
JMP SignedBiggest
ProfEnd NORMAL