375 lines
7.4 KiB
NASM
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
|