summaryrefslogtreecommitdiffstats
path: root/private/mvdm/wow16/win87em/emfrndi.asm
diff options
context:
space:
mode:
Diffstat (limited to 'private/mvdm/wow16/win87em/emfrndi.asm')
-rw-r--r--private/mvdm/wow16/win87em/emfrndi.asm224
1 files changed, 224 insertions, 0 deletions
diff --git a/private/mvdm/wow16/win87em/emfrndi.asm b/private/mvdm/wow16/win87em/emfrndi.asm
new file mode 100644
index 000000000..2766ed8f4
--- /dev/null
+++ b/private/mvdm/wow16/win87em/emfrndi.asm
@@ -0,0 +1,224 @@
+ 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