summaryrefslogblamecommitdiffstats
path: root/private/mvdm/wow16/win87em/emlssng.asm
blob: a2db8e4de29c5fc7ae7353359af8907efb287ff3 (plain) (tree)












































































































































































































































































































































                                                                                       
	page	,132
	subttl	emlssng.asm - Load/Store Single Precision Numbers
;***
;emlssng.asm - Load/Store Single Precision Numbers
;
;	Copyright (c) 1984-89, Microsoft Corporation
;
;Purpose:
;	Load/Store Single Precision Numbers
;
;	This Module contains Proprietary Information of Microsoft
;	Corporation and should be treated as Confidential.
;
;Revision History:
;	See emulator.hst
;
;*******************************************************************************


ProfBegin LSSNG

;*********************************************************************;
;								      ;
;			 Load Single Real			      ;
;								      ;
;*********************************************************************;
;
; Subroutine converts single in regs to internal at ES:SI


pub	eFLDsr
	LDUS2AX 		;    get lower mantissa part
	MOV	DI,AX		;  2 keep lower mantissa in DX
	LDUS2AX 		;    get upper exponent/sign part
	MOV	DL,AL		;  2 copy most sig. mantissa byte
	ROL	AX,1		;  2 sign to AL, exponent to AH
	AND	AL,1		;  4 clear all flags except sign
	ROR	AL,1		;  2 get sign in right position
	XCHG	AL,AH

    ; AX, DI, DL: operand one

	PUSHST			; 64 allocate another register

pub	SingleToInternal

	OR	DL,80H		; Set leading bit of mantissa
	XOR	DH,DH		; Set Tag to valid non-zero
	CMP	AL,SexpMax	; Is Number NAN or Inf?
	JE	short SNANorInf
if	fastSP
	OR	AH,Single	; Set single Precision flag
endif
	CMP	AL,SexpMin	; Is Number Zero or Denormal
	JE	short SZeroOrDenorm
				; Otherwise number is valid non-zero
	MOV	Flag[esi],AH	 ; Store sign
	SUB	AL,SexpBias	; Unbias the exponent
	CBW

pub	SStoreExpnTag
	MOV	Expon[esi],AX	 ; Store Exponent
	MOV	Tag[esi],DH	 ; Store Tag
	MOV	MB7[esi],DL	 ; Store Mantissa
	MOV	MB5[esi],DI
ife	fastSP
	XOR	AX,AX		; Clear low order bytes of Mantissa
	MOV	MB4[esi],AL
	MOV	MB2[esi],AX
	MOV	MB0[esi],AX
endif
	RET

pub	SNANorInf
	MOV	Flag[esi],AH		; Store sign
	MOV	AX,IexpMax - IexpBias	; Set exponent to internal max
	MOV	DH,Special		; Set Tag to show NAN or Inf
	CMP	DL,80H			; If anything other than leading bit
	JNE	short SStoreExpnTag	;  is set number is NAN (not Inf)
	OR	DI,DI
	JNE	short SStoreExpnTag
	OR	DH,ZROorINF		; Set Tag to show Inf
	JMP	SStoreExpnTag

pub	SZeroorDenorm
	MOV	Flag[esi],AH		; Store sign
	CMP	DL,80H			; If anything other than leading bit
	JNE	short SDenormal 	;  is set number is Denormal
	OR	DI,DI
	JNE	short SDenormal
	MOV	AX,IexpMin - IexpBias	; Set exponent to internal min
	OR	DH,ZROorINF		; Set Tag to show 0
	JMP	SStoreExpnTag

pub	SDenormal
	OR	[CURerr],Denormal	; Set Denormal Exception
	SUB	AL,SexpBias		; unbias the Exponent
	CBW
	INC	AX

pub	SNormalize
	DEC	AX
	SHL	DI,1
	RCL	DL,1
	OR	DL,DL
	JNS	SNormalize

	JMP	SStoreExpnTag

page
;************************************************************;
;							     ;
;		 Store Single Real			     ;
;							     ;
;************************************************************;

pub	SSpecial		; number is NAN or INF or Zero
	TEST	CL,Special	; NAN or INF?
	JNE	short SSNANorINF
	XOR	AX,AX		; Number is Zero
	MOV	BX,AX
	JMP	STRUNC

pub	SSNANorINF
	TEST	CL,ZROorINF
	JNE	short SInf
	MOV	BX,MB5[esi]	 ; Number is a NAN
	MOV	AL,MB7[esi]
	MOV	AH,Flag[esi]	 ; Pick up Sign
	SHL	AX,1		; Destroy leading bit, Sign to CF
	MOV	AH,SexpMax
	RCR	AX,1
	JMP	STRUNC

 pub	SInf
	MOV	AH,Flag[esi]
	JMP	SSignedInfinity

pub	JMPSOver
	JMP	SOver

pub	JMPSUnder
	JMP	SUnder

; ES:SI: memory address of single
; stores and misc. operations;	first setup register values as follows:
; AX: TOS flags (for DOUB and SIGN flags)
; SI: TOS address (offset)

pub	eFSTsr
	mov	edi,esi 	; ES:DI = store address
	MOV	esi,[CURstk]	 ; 14 load TOS address
	MOV	AX,Flag[esi]	 ; 21 get TOS flags (sign, double)

; convert internal at DS:SI to single
; DS:SI = TOS, ES:DI = memory, CH = operation (POP), BP = old ES value

	MOV	CL,Tag[esi]	 ; See if number is NAN or Inf or Zero
	OR	CL,CL
	JNZ	short SSpecial
	MOV	CL,Flag[esi]	 ; Pick up sign & single precision flag

	MOV	AX,Expon[esi]
	CMP	AX,SexpMax - SexpBias
	JGE	short JMPSOver
	CMP	AX,SexpMin - SexpBias
	JLE	short JMPSUnder

	ADD	AL,SexpBias	; Bias the Exponent
	MOV	AH,MB7[esi]	 ; Pick up MSB of Mantissa
	XCHG	AH,AL
	SHL	AL,1		; Shift mantissa to destroy leading integer bit
	SHL	CL,1		; Get sign into CF
	RCR	AX,1		; Pack sign, exp, & MSB
if	fastSP
	TEST	CL,Single*2	; if number was single rounding is not needed
	JZ	SS1
	MOV	BX,MB5[esi]
	JMP	SHORT STRUNC
SS1:
endif
	MOV	DX,MB0[esi]	 ; DL Will be the sticky bit
	OR	DX,MB2[esi]	 ; DH will be round and the rest of sticky
	OR	DL,DH
	XOR	DH,DH
	MOV	BX,MB5[esi]
	OR	DX,MB3[esi]
	JZ	short STRUNC	; If no Round or Sticky result is exact
	OR	[CURerr],Precision

pub	SRound			; single in AX:BX:DX
	MOV	CL,[CWcntl]	; Need to know Rounding Control
	SHR	CL,1
	SHR	CL,1
	SHR	CL,1
	JC	short StDOWNorCHOP24
	SHR	CL,1
	JC	short StUP24

pub	StNEAR24
	CMP	DX,8000H	; How are round and sticky bits?
	JB	short STRUNC	; No round, so truncate
	JA	short SINC	; Round and sticky so round up
	TEST	BL,1		; Round and no sticky, is last bit even?
	JZ	short STRUNC	; Yes, so truncate.

pub	SINC
	MOV	DL,AL		; Increment mantissa
	ADD	BX,1
	ADC	AX,0
	XOR	DL,AL		; See if we overflowed a bit into the exponent
	JNS	short STRUNC	; If not number is now correct so go store
	MOV	DX,AX		; Exponent was incremented, see if it overflowed
	SHL	DX,1
	CMP	DH,SexpMax
	JE	short SOver

pub	StCHOP24
STRUNC:
	XCHG	AX,BX
	STAX2US
	MOV	AX,BX
	STAX2US

pub	SStoreExit
	RET

pub	StDOWNorCHOP24
	SHR	CL,1
	JC	short StCHOP24

pub	StDOWN24
	OR	AH,AH			; Test the sign
	JS	short SINC
	JMP	short STRUNC

pub	StUP24
	OR	AH,AH			; Test the sign
	JS	short STRUNC
	JMP	short SINC

pub	SOver				; Number overflowed Single Precision range.
					; Result returned depends upon rounding control
	OR	[CURerr],Overflow + Precision
	MOV	CL,[CWcntl]
	SHR	CL,1
	SHR	CL,1
	SHR	CL,1
	JC	short StMOvDNorCHP24

	SHR	CL,1
	JC	short StMOvUP24

StMOvNEAR24:				; Masked Overflow Near Rounding

pub	SSignedInfinity 		; Return signed infinity
	MOV	BX,[IEEEinfinityS + 2]
	AND	AH,Sign 		; Overstore the proper sign
	OR	BH,AH
	MOV	AX,[IEEEinfinityS]
	STAX2US
	MOV	AX,BX
	STAX2US
	JMP	SStoreExit

pub	StMOvDNorCHP24
	SHR	CL,1
	JC	short StMOvCHOP24

pub	StMOvDOWN24			; Masked Overflow Down Rounding
	TEST	AH,Sign 		; Positive goes to biggest
	JNZ	short SSignedInfinity

StMOvCHOP24:				; Masked Overflow Chop Rounding
pub	SSignedBiggest
	MOV	BX,[IEEEbiggestS + 2]
	AND	AH,Sign 		; Overstore the proper sign
	OR	AH,BH
	MOV	AL,BL
	STAX2US
	MOV	AX,[IEEEbiggestS]
	STAX2US
	JMP	SStoreExit

pub	StMOvUP24			; Masked Overflow Up Rounding
	TEST	AH,Sign 		; Negative goes to biggest
	JZ	short SSignedInfinity
	JMP	SSignedBiggest

pub	SUnder				; Masked Underflow - Try to denormalize
	OR	[CURerr],Underflow+Precision
	NEG	AX			; Convert exponent (which is too small)
	ADD	AX,SexpMin-SexpBias+1	; To a positive shift count
	CMP	AX,24			; Is shift more than mantissa precision
	JGE	short Szero
	XCHG	CX,AX
ifdef	i386
	movzx	ecx,cx			; (ecx) = zero-extended loop count
endif
	MOV	DX,MB0[esi]		; Pick up Insignif bytes for sticky bit
	OR	DX,MB2[esi]
	MOV	AL,DL
	OR	AL,DH
	MOV	DX,MB4[esi]
	MOV	BX,MB6[esi]
	OR	AL,AL
	JZ	short SSHIFTR
	OR	DL,1			; Set the sticky bit

pub	SSHIFTR
	SHR	BX,1
	RCR	DX,1
	JNC	short SSLOOP
	OR	DL,1
pub	SSLOOP
	LOOP	SSHIFTR

	XCHG	AH,CH			; Restore operation to CH
	MOV	AH,Flag[esi]		; Pick up sign
	AND	AH,Sign 		; Mask to sign only
	MOV	AL,BH			; Biased exponent for a denormal is 0
	MOV	BH,BL
	MOV	BL,DH
	MOV	DH,DL
	XOR	DL,DL
	JMP	SRound

pub	Szero
	XOR	AX,AX
	MOV	BX,AX
	JMP	STRUNC			; Go store single and exit

ProfEnd  LSSNG