225 lines
4.7 KiB
NASM
225 lines
4.7 KiB
NASM
|
page ,132
|
||
|
subttl emfrndi.asm - Round to INT
|
||
|
;***
|
||
|
;emfrndi.asm - Round to INT
|
||
|
;
|
||
|
; Copyright (c) 1986-89, Microsoft Corporation
|
||
|
;
|
||
|
;Purpose:
|
||
|
; Round to INT
|
||
|
;
|
||
|
; This Module contains Proprietary Information of Microsoft
|
||
|
; Corporation and should be treated as Confidential.
|
||
|
;
|
||
|
;Revision History:
|
||
|
; See emulator.hst
|
||
|
;
|
||
|
;*******************************************************************************
|
||
|
|
||
|
|
||
|
;*********************************************************************;
|
||
|
; ;
|
||
|
; Round TOS to Integer ;
|
||
|
; ;
|
||
|
;*********************************************************************;
|
||
|
|
||
|
ProfBegin FRNDI
|
||
|
|
||
|
|
||
|
pub eFRNDINT
|
||
|
MOV esi,[CURstk] ; Point to TOS
|
||
|
MOV CX,Expon[esi] ; Get exponent
|
||
|
CMP CX,63 ; See if we have very large integer
|
||
|
JGE short DONERNDINT
|
||
|
|
||
|
if fastSP
|
||
|
MOV BX,MB4[esi] ; Fetch mantissa to DI:BP:BX:DX
|
||
|
MOV DI,MB6[esi]
|
||
|
TEST byte ptr Flag[esi],Single
|
||
|
JZ RNDD
|
||
|
XOR BL,BL
|
||
|
MOV BP,BX
|
||
|
XOR BX,BX
|
||
|
MOV DX,BX
|
||
|
RND:
|
||
|
else
|
||
|
MOV BP,MB4[esi] ; Fetch mantissa to DI:BP:BX:DX
|
||
|
MOV DI,MB6[esi]
|
||
|
MOV DX,MB0[esi]
|
||
|
MOV BX,MB2[esi]
|
||
|
endif
|
||
|
CALL InternalToInteger
|
||
|
|
||
|
XOR AX,AX ; Test for zero
|
||
|
OR AX,DI
|
||
|
OR AX,BP
|
||
|
OR AX,BX
|
||
|
OR AX,DX
|
||
|
JZ short RoundIntToZero
|
||
|
|
||
|
MOV AX,63 ; What expon should be if no shifting
|
||
|
|
||
|
CALL IntegerToInternal
|
||
|
|
||
|
pub DONERNDINT
|
||
|
RET
|
||
|
|
||
|
if fastSP
|
||
|
RNDD:
|
||
|
MOV BP,BX
|
||
|
MOV DX,MB0[esi]
|
||
|
MOV BX,MB2[esi]
|
||
|
JMP RND
|
||
|
endif
|
||
|
|
||
|
pub RoundIntToZero
|
||
|
MOV Expon[esi],IexpMin - IexpBias
|
||
|
MOV MB0[esi],AX
|
||
|
MOV MB2[esi],AX
|
||
|
MOV MB4[esi],AX
|
||
|
MOV MB6[esi],AX
|
||
|
MOV byte ptr Tag[esi],ZROorINF
|
||
|
JMP DONERNDINT
|
||
|
PAGE
|
||
|
pub IntegerToInternal
|
||
|
; On entry DI:BP:BX:DX is the integer (unsigned i.e. no longer in 2's
|
||
|
; compliment) DS:SI points to TOS (the ultimate destination).
|
||
|
; AX contains the Exponent (assuming that the number will require
|
||
|
; no shifting. the routine will adjust it as it goes along)
|
||
|
; On exit the mantissa and exponent will be put in TOS.
|
||
|
; This routine is used to Load int16 and int32 also to round-to-int
|
||
|
|
||
|
XOR ecx,ecx
|
||
|
|
||
|
pub SHIFTLEFT
|
||
|
SHL DX,1 ; Left justify number
|
||
|
RCL BX,1
|
||
|
RCL BP,1
|
||
|
RCL DI,1
|
||
|
JC short DONESHIFT
|
||
|
LOOP SHIFTLEFT ; CX will count number of shifts done
|
||
|
|
||
|
pub DONESHIFT
|
||
|
RCR DI,1 ; We went one too far so reset
|
||
|
RCR BP,1
|
||
|
RCR BX,1
|
||
|
RCR DX,1
|
||
|
|
||
|
ADD AX,CX ; Adjust exponent
|
||
|
MOV Expon[esi],AX ; Store exponent
|
||
|
MOV MB0[esi],DX ; Store mantissa
|
||
|
MOV MB2[esi],BX
|
||
|
MOV MB4[esi],BP
|
||
|
MOV MB6[esi],DI
|
||
|
RET
|
||
|
PAGE
|
||
|
pub InternalToInteger
|
||
|
; On entry DI:BP:BX:DX is the mantissa, CX is the Exponent, and
|
||
|
; DS:SI points to TOS where the number came from. On exit
|
||
|
; DI:BP:BX:DX is an integer (unsigned i.e. needs to be jiggled to
|
||
|
; 2's compliment based upon the sign in TOS) rounded according to
|
||
|
; Round control. This routine used to Store int16 and int32 also
|
||
|
; by round-to-integer
|
||
|
|
||
|
ifdef i386
|
||
|
movsx ecx,cx ; (ecx) = sign-extended cx
|
||
|
endif
|
||
|
XOR AX,AX ; Clear Stickybit (AL) and roundbit (AH)
|
||
|
SUB ecx,63 ; Convert exponent to shift count
|
||
|
NEG ecx ; Shift will be done in 2 parts, 1st to get
|
||
|
DEC ecx ; sticky then 1 more to get round
|
||
|
ifdef i386
|
||
|
JGE short NOTRUNCATE; Shift count Neg means num was large int.
|
||
|
JMP TRUNCATE
|
||
|
NOTRUNCATE:
|
||
|
JE short GETROUND ; Zero shift means no sticky bit, only round
|
||
|
else
|
||
|
JL short TRUNCATE ; Shift count Neg means num was large int.
|
||
|
JE short GETROUND ; Zero shift means no sticky bit, only round
|
||
|
endif
|
||
|
CMP ecx,64 ; If big shift count then number is all sticky
|
||
|
JGE short STICKYNOROUND
|
||
|
|
||
|
cmp ecx,48 ; fast out for 16-bit ints
|
||
|
jle SHIFTRIGHT ; no
|
||
|
|
||
|
or dx,bx
|
||
|
or dx,bp ; dx = low 48 bits
|
||
|
jz nostick48 ; if 0 then no sticky bits
|
||
|
or al,1 ; set sticky bit
|
||
|
nostick48:
|
||
|
mov dx,di ; move upper 16 to lower 16
|
||
|
xor di,di ; zero upper 48 bits
|
||
|
mov bp,di
|
||
|
mov bx,di
|
||
|
sub ecx,48 ; just like looping 48 times
|
||
|
|
||
|
pub SHIFTRIGHT
|
||
|
SHR DI,1 ; Shift into sticky bit (lsb of AL)
|
||
|
RCR BP,1
|
||
|
RCR BX,1
|
||
|
RCR DX,1
|
||
|
JNC short LOOPEND
|
||
|
RCL AL,1
|
||
|
|
||
|
pub LOOPEND
|
||
|
LOOP SHIFTRIGHT
|
||
|
|
||
|
pub GETROUND
|
||
|
SHR DI,1 ; Shift into round
|
||
|
RCR BP,1
|
||
|
RCR BX,1
|
||
|
RCR DX,1
|
||
|
RCL AH,1 ; Shift round into lsb of AH
|
||
|
|
||
|
pub GOTROUNDANDSTICKY
|
||
|
OR AX,AX ; Was number exact?
|
||
|
JZ short TRUNCATE
|
||
|
OR [CURerr],Precision
|
||
|
TEST [CWcntl],RCdown ; True if down or chop
|
||
|
JNZ short INTDNorCHP
|
||
|
TEST [CWcntl],RCup ; True if UP (or CHOP)
|
||
|
JNZ short INTUP
|
||
|
|
||
|
pub INTNEAR
|
||
|
OR AL,DL ; In near mode inc if (sticky or lastbit) and Roundbit
|
||
|
AND AH,AL
|
||
|
SHR AH,1
|
||
|
JNC short TRUNCATE
|
||
|
|
||
|
pub INCREMENT
|
||
|
XOR AX,AX
|
||
|
ADD DX,1
|
||
|
ADC BX,AX
|
||
|
ADC BP,AX
|
||
|
ADC DI,AX
|
||
|
|
||
|
INTCHOP:
|
||
|
pub TRUNCATE
|
||
|
RET
|
||
|
|
||
|
pub STICKYNOROUND
|
||
|
MOV AL,1
|
||
|
XOR AH,AH
|
||
|
XOR DI,DI
|
||
|
MOV BP,DI
|
||
|
MOV BX,DI
|
||
|
MOV DX,DI
|
||
|
JMP GOTROUNDANDSTICKY
|
||
|
|
||
|
pub INTDNorCHP
|
||
|
TEST [CWcntl],RCup ; True if UP or CHOP
|
||
|
JNZ INTCHOP
|
||
|
|
||
|
pub INTDOWN
|
||
|
TEST byte ptr Flag[esi],Sign ; Truncate if round down and +
|
||
|
JNZ INCREMENT
|
||
|
JMP TRUNCATE
|
||
|
|
||
|
pub INTUP
|
||
|
TEST byte ptr Flag[esi],Sign ; Truncate if round up and -
|
||
|
JNZ TRUNCATE
|
||
|
JMP INCREMENT
|
||
|
|
||
|
ProfEnd FRNDI
|