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