windows-nt/Source/XPSP1/NT/base/mvdm/wow16/win87em/emarith.asm

286 lines
6 KiB
NASM
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
page ,132
subttl emarith.asm - Arithmetic Operations
;***
;emarith.asm -
;
; Copyright (c) 1986-89, Microsoft Corporation
;
;Purpose:
; Arithmetic Operations
;
; This Module contains Proprietary Information of Microsoft
; Corporation and should be treated as Confidential.
;
;Revision History: (Also see emulator.hst)
;
; 12/19/89 WAJ XORSIGN was not masking the sign bit correctly.
;
;*******************************************************************************
;-----------------------------------------------;
; ;
; Double precision arithmetic ;
; ;
;-----------------------------------------------;
; Inputs:
; DI = (op1) NOS (Next on stack)
; SI = (op2) TOS (Top of stack)
;
; Functions:
; ADDRQQ - Addition RESULT <-- [DI] + [SI]
; SUDRQQ - Subtract RESULT <-- [DI] - [SI]
; MUDRQQ - Multiply RESULT <-- [DI] * [SI]
; DIDRQQ - Division RESULT <-- [DI] / [SI]
; SVDRQQ - Subtract Reversed RESULT <-- [SI] - [DI]
; DRDRQQ - Division Reversed RESULT <-- [SI] / [DI]
; Outputs:
; Destination of result is in RESULT
; Registers:
; All except BP destroyed.
; Understanding this code:
;
; Assign the symbol S to SI, assign the symbol D to DI.
;
; Upon entry: SI <-- S, DI <-- D , Performing D - S
ProfBegin ARITH
even
lab SVDRQQ ; Reverse Subtract
MOV DX,Sign*256 ; DH will be flag[SI], prepare to switch sign
JMP short DOADD
even
lab SUDRQQ ; Normal Subtract
MOV DX,Sign ; DL will be flag[DI], prepare to switch sign
JMP short DOADD
even
lab MUDRQQ ; Multiplication
xor idx,idx ; Do not change signs on entry
MOV ibx,offset MULJMPTAB
JMP short INITIL
even
lab DIDRQQ ; Normal Division
xor idx,idx
XCHG isi,idi ; Make SI - Numerator, DI - Denominator
MOV ibx,offset DIVJMPTAB
JMP short INITIL
even
lab DRDRQQ ; Reverse Division
xor idx,idx
MOV ibx,offset DIVJMPTAB
JMP short INITIL
even
lab ADDRQQ ; Double Precision Add
xor idx,idx ; No signs get switched
lab DOADD
MOV ibx,offset ADDJMPTAB
lab INITIL
MOV AL,Tag[idi] ; Get tags to determine special cases.
SHL AL,1
SHL AL,1
OR AL,Tag[isi]
CBI
ifdef i386
SHL iax,2
else
SHL iax,1
endif
ADD ibx,iax ; BX now points to address of proper routine.
XOR DH,Flag[idi] ; Sign A
XOR DL,Flag[isi] ; Sign B
MOV CX,Expon[idi] ; Exponent of operand A
MOV AX,Expon[isi] ; Exponent of operand B
JMP cs:[ibx] ; Go to appropriate routine.
page
;-----------------------------------------------------------;
; ;
; Special Case Routines for Arithmetic Functions ;
; ;
;-----------------------------------------------------------;
lab DDD
mov isi,idi ;return DI with sign from Add/Subtract
mov dl,dh
lab SSS ;Return SI with sign from Add/Subtract
call MOVresult
MOV Flag[idi],dl ;Overstore correct Sign from Add/Subtract
ret
lab D0SSINV ;Return SI, set both Invalid and Zerodivide
OR [CURerr],ZeroDivide
JMP short SSINV
lab DDINV ;Return DI and set Invalid exception
MOV isi,idi
lab SSINV ;Return SI and set INVALID exception
OR [CURerr],Invalid
jmp short MOVresult
lab ZEROS ;Return 0 with xor of signs
MOV isi,offset IEEEzero
lab XORSIGN
XOR DH,DL
AND DH,80h ; Mask to just the sign.
CALL csMOVresult
OR Flag[idi],DH
RET
lab DIV0 ;Set exception, Return Infinity signed
OR [CURerr],ZeroDivide
lab INFS ;Return signed infinity
MOV isi,offset IEEEinfinity
JMP XORSIGN
lab D0INDINV ;Set div 0 exception, Return Indefinate and Invalid
OR [CURerr],ZeroDivide
lab INDINV
MOV isi,offset IEEEindefinite
OR [CURerr],Invalid
lab csMOVresult
mov idi,[RESULT]
lab csMOVRQQ ; as above for constants in CS
ifdef i386
MOVS dword ptr es:[idi],dword ptr cs:[isi]
MOVS dword ptr es:[idi],dword ptr cs:[isi]
MOVS dword ptr es:[idi],dword ptr cs:[isi]
else
MOVS word ptr es:[idi],word ptr cs:[isi]
MOVS word ptr es:[idi],word ptr cs:[isi]
MOVS word ptr es:[idi],word ptr cs:[isi]
MOVS word ptr es:[idi],word ptr cs:[isi]
MOVS word ptr es:[idi],word ptr cs:[isi]
MOVS word ptr es:[idi],word ptr cs:[isi]
endif
SUB idi,Reg87Len
SUB isi,Reg87Len
RET
lab MOVresult
mov idi,[RESULT] ; move to result
cmp isi,idi
je short MOVret ; unless the same
lab MOVRQQ
ifdef i386
MOVS dword ptr es:[idi],dword ptr ds:[isi]
MOVS dword ptr es:[idi],dword ptr ds:[isi]
MOVS dword ptr es:[idi],dword ptr ds:[isi]
else
MOVS word ptr es:[idi],word ptr ds:[isi]
MOVS word ptr es:[idi],word ptr ds:[isi]
MOVS word ptr es:[idi],word ptr ds:[isi]
MOVS word ptr es:[idi],word ptr ds:[isi]
MOVS word ptr es:[idi],word ptr ds:[isi]
MOVS word ptr es:[idi],word ptr ds:[isi]
endif
SUB idi,Reg87Len
SUB isi,Reg87Len
lab MOVret
RET
lab INFINF ; Addition of two infinities was attempted
TEST [CWcntl],InfinityControl ; Invalid if projective closure
JSZ INDINV
XOR DL,DH ; Invalid if signs are different
JSS INDINV
JMP DDD ; Otherwise Inf is the answer, already at DI
lab BIGNAN ; Return the NAN with the Bigger mantissa
mov iax, isi
mov ibx, idi
add isi, MantissaByteCnt-2 ; UNDONE387: Convert SNAN to QNAN
add idi, MantissaByteCnt-2
mov icx, MantissaByteCnt/2
std
repe cmps word ptr ds:[isi], word ptr es:[idi]
cld
JSB DDNAN
mov isi, iax ; Greater NAN was in si
jmp SSINV
lab DDNAN
mov isi, ibx ; Greater NAN was in di
jmp SSINV
page
if fastSP
ifdef i386
BUG ; fastsp and i386 do not work together
endif
;Assumes DL = Flag[SI], DH = Flag[DI]. Will convert the mantissa on
;stack to double if necessary by appending zeros.
;Must not change AX, DX, SI, DI.
lab CoerceToDouble
MOV BX,DX ; get to work reg
AND BX,Single + 256*Single ; mask to single flags only
JSNZ CheckDI
lab CoerceToDoubleReturn
RET
lab CheckDI
XOR BX,BX ; Prepare to zero out mantissa
XCHG AX,BX
TEST DH,Single
JSZ CheckSI
STOSW ; Zero out lower five bytes
STOSW
STOSB
SUB DI,5 ; Reset DI
lab CheckSI
TEST DL,Single
JZ short ExitCoerceToDouble
XCHG DI,SI
STOSW ; Zero out lower five bytes
STOSW
STOSB
SUB DI,5 ; Reset DI
XCHG DI,SI
lab ExitCoerceToDouble
XCHG AX,BX ; Reset AX
XOR BX,BX ; Set zero flag to indicate results now double
RET
endif ;fastSP
ProfEnd ARITH