diff options
Diffstat (limited to 'private/mvdm/wow16/win87em/emfrndi.asm')
-rw-r--r-- | private/mvdm/wow16/win87em/emfrndi.asm | 224 |
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 |