286 lines
6 KiB
NASM
286 lines
6 KiB
NASM
|
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
|