patch-2.1.73 linux/arch/i386/math-emu/reg_round.S

Next file: linux/arch/i386/math-emu/reg_u_add.S
Previous file: linux/arch/i386/math-emu/reg_norm.S
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.72/linux/arch/i386/math-emu/reg_round.S linux/arch/i386/math-emu/reg_round.S
@@ -4,17 +4,20 @@
  |                                                                           |
  | Rounding/truncation/etc for FPU basic arithmetic functions.               |
  |                                                                           |
- | Copyright (C) 1993,1995                                                   |
+ | Copyright (C) 1993,1995,1997                                              |
  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
+ |                       Australia.  E-mail billm@suburbia.net               |
  |                                                                           |
  | This code has four possible entry points.                                 |
  | The following must be entered by a jmp instruction:                       |
  |   fpu_reg_round, fpu_reg_round_sqrt, and fpu_Arith_exit.                  |
  |                                                                           |
- | The _round_reg entry point is intended to be used by C code.              |
+ | The FPU_round entry point is intended to be used by C code.               |
  | From C, call as:                                                          |
- | void round_reg(FPU_REG *arg, unsigned int extent, unsigned int control_w) |
+ |  int FPU_round(FPU_REG *arg, unsigned int extent, unsigned int control_w) |
+ |                                                                           |
+ |    Return value is the tag of the answer, or-ed with FPU_Exception if     |
+ |    one was raised, or -1 on internal error.                               |
  |                                                                           |
  | For correct "up" and "down" rounding, the argument must have the correct  |
  | sign.                                                                     |
@@ -106,7 +109,7 @@
 .globl fpu_Arith_exit
 
 /* Entry point when called from C */
-ENTRY(round_reg)
+ENTRY(FPU_round)
 	pushl	%ebp
 	movl	%esp,%ebp
 	pushl	%esi
@@ -117,14 +120,10 @@
 	movl	SIGH(%edi),%eax
 	movl	SIGL(%edi),%ebx
 	movl	PARAM2,%edx
-	movl	PARAM3,%ecx
-	jmp	fpu_reg_round_sqrt
 
 fpu_reg_round:			/* Normal entry point */
 	movl	PARAM4,%ecx
 
-fpu_reg_round_sqrt:		/* Entry point from wm_sqrt.S */
-
 #ifndef NON_REENTRANT_FPU
 	pushl	%ebx		/* adjust the stack pointer */
 #endif NON_REENTRANT_FPU
@@ -135,12 +134,12 @@
 /*	jns	L_entry_bugged */
 #endif PARANOID
 
-	cmpl	EXP_UNDER,EXP(%edi)
-	jle	xMake_denorm			/* The number is a de-normal */
+	cmpw	EXP_UNDER,EXP(%edi)
+	jle	L_Make_denorm			/* The number is a de-normal */
 
 	movb	$0,FPU_denormal			/* 0 -> not a de-normal */
 
-xDenorm_done:
+Denorm_done:
 	movb	$0,FPU_bits_lost		/* No bits yet lost in rounding */
 
 	movl	%ecx,%esi
@@ -190,13 +189,13 @@
 #endif PARANOID
 
 LUp_24:
-	cmpb	SIGN_POS,SIGN(%edi)
+	cmpb	SIGN_POS,PARAM5
 	jne	LCheck_truncate_24	/* If negative then  up==truncate */
 
 	jmp	LCheck_24_round_up
 
 LDown_24:
-	cmpb	SIGN_POS,SIGN(%edi)
+	cmpb	SIGN_POS,PARAM5
 	je	LCheck_truncate_24	/* If positive then  down==truncate */
 
 LCheck_24_round_up:
@@ -205,7 +204,7 @@
 	orl	%ebx,%ecx
 	orl	%edx,%ecx
 	jnz	LDo_24_round_up
-	jmp	LRe_normalise
+	jmp	L_Re_normalise
 
 LRound_nearest_24:
 	/* Do rounding of the 24th bit if needed (nearest or even) */
@@ -240,13 +239,13 @@
 	andl	$0x000000ff,%ecx
 	orl	%ebx,%ecx
 	orl	%edx,%ecx
-	jz	LRe_normalise		/* No truncation needed */
+	jz	L_Re_normalise		/* No truncation needed */
 
 LDo_truncate_24:
 	andl	$0xffffff00,%eax	/* Truncate to 24 bits */
 	xorl	%ebx,%ebx
 	movb	LOST_DOWN,FPU_bits_lost
-	jmp	LRe_normalise
+	jmp	L_Re_normalise
 
 
 /* Round etc to 53 bit precision */
@@ -270,13 +269,13 @@
 #endif PARANOID
 
 LUp_53:
-	cmpb	SIGN_POS,SIGN(%edi)
+	cmpb	SIGN_POS,PARAM5
 	jne	LCheck_truncate_53	/* If negative then  up==truncate */
 
 	jmp	LCheck_53_round_up
 
 LDown_53:
-	cmpb	SIGN_POS,SIGN(%edi)
+	cmpb	SIGN_POS,PARAM5
 	je	LCheck_truncate_53	/* If positive then  down==truncate */
 
 LCheck_53_round_up:
@@ -284,7 +283,7 @@
 	andl	$0x000007ff,%ecx
 	orl	%edx,%ecx
 	jnz	LDo_53_round_up
-	jmp	LRe_normalise
+	jmp	L_Re_normalise
 
 LRound_nearest_53:
 	/* Do rounding of the 53rd bit if needed (nearest or even) */
@@ -315,12 +314,12 @@
 	movl	%ebx,%ecx
 	andl	$0x000007ff,%ecx
 	orl	%edx,%ecx
-	jz	LRe_normalise
+	jz	L_Re_normalise
 
 LTruncate_53:
 	movb	LOST_DOWN,FPU_bits_lost
 	andl	$0xfffff800,%ebx	/* Truncate to 53 bits */
-	jmp	LRe_normalise
+	jmp	L_Re_normalise
 
 
 /* Round etc to 64 bit precision */
@@ -344,20 +343,20 @@
 #endif PARANOID
 
 LUp_64:
-	cmpb	SIGN_POS,SIGN(%edi)
+	cmpb	SIGN_POS,PARAM5
 	jne	LCheck_truncate_64	/* If negative then  up==truncate */
 
 	orl	%edx,%edx
 	jnz	LDo_64_round_up
-	jmp	LRe_normalise
+	jmp	L_Re_normalise
 
 LDown_64:
-	cmpb	SIGN_POS,SIGN(%edi)
+	cmpb	SIGN_POS,PARAM5
 	je	LCheck_truncate_64	/* If positive then  down==truncate */
 
 	orl	%edx,%edx
 	jnz	LDo_64_round_up
-	jmp	LRe_normalise
+	jmp	L_Re_normalise
 
 LRound_nearest_64:
 	cmpl	$0x80000000,%edx
@@ -375,46 +374,60 @@
 	adcl	$0,%eax
 
 LCheck_Round_Overflow:
-	jnc	LRe_normalise
+	jnc	L_Re_normalise
 
 	/* Overflow, adjust the result (significand to 1.0) */
 	rcrl	$1,%eax
 	rcrl	$1,%ebx
-	incl	EXP(%edi)
-	jmp	LRe_normalise
+	incw	EXP(%edi)
+	jmp	L_Re_normalise
 
 LCheck_truncate_64:
 	orl	%edx,%edx
-	jz	LRe_normalise
+	jz	L_Re_normalise
 
 LTruncate_64:
 	movb	LOST_DOWN,FPU_bits_lost
 
-LRe_normalise:
+L_Re_normalise:
 	testb	$0xff,FPU_denormal
-	jnz	xNormalise_result
+	jnz	Normalise_result
+
+L_Normalised:
+	movl	TAG_Valid,%edx
 
-xL_Normalised:
+L_deNormalised:
 	cmpb	LOST_UP,FPU_bits_lost
-	je	xL_precision_lost_up
+	je	L_precision_lost_up
 
 	cmpb	LOST_DOWN,FPU_bits_lost
-	je	xL_precision_lost_down
+	je	L_precision_lost_down
 
-xL_no_precision_loss:
+L_no_precision_loss:
 	/* store the result */
-	movb	TW_Valid,TAG(%edi)
 
-xL_Store_significand:
+L_Store_significand:
 	movl	%eax,SIGH(%edi)
 	movl	%ebx,SIGL(%edi)
 
-	xorl	%eax,%eax	/* No errors detected. */
-
-	cmpl	EXP_OVER,EXP(%edi)
+	cmpw	EXP_OVER,EXP(%edi)
 	jge	L_overflow
 
-fpu_reg_round_exit:
+	movl	%edx,%eax
+
+	/* Convert the exponent to 80x87 form. */
+	addw	EXTENDED_Ebias,EXP(%edi)
+	andw	$0x7fff,EXP(%edi)
+
+fpu_reg_round_signed_special_exit:
+
+	cmpb	SIGN_POS,PARAM5
+	je	fpu_reg_round_special_exit
+
+	orw	$0x8000,EXP(%edi)	/* Negative sign for the result. */
+
+fpu_reg_round_special_exit:
+
 #ifndef NON_REENTRANT_FPU
 	popl	%ebx		/* adjust the stack pointer */
 #endif NON_REENTRANT_FPU
@@ -431,21 +444,25 @@
  * Set the FPU status flags to represent precision loss due to
  * round-up.
  */
-xL_precision_lost_up:
+L_precision_lost_up:
+	push	%edx
 	push	%eax
 	call	SYMBOL_NAME(set_precision_flag_up)
 	popl	%eax
-	jmp	xL_no_precision_loss
+	popl	%edx
+	jmp	L_no_precision_loss
 
 /*
  * Set the FPU status flags to represent precision loss due to
  * truncation.
  */
-xL_precision_lost_down:
+L_precision_lost_down:
+	push	%edx
 	push	%eax
 	call	SYMBOL_NAME(set_precision_flag_down)
 	popl	%eax
-	jmp	xL_no_precision_loss
+	popl	%edx
+	jmp	L_no_precision_loss
 
 
 /*
@@ -453,30 +470,30 @@
  * Shift the number right the required number of bits, which will
  * have to be undone later...
  */
-xMake_denorm:
+L_Make_denorm:
 	/* The action to be taken depends upon whether the underflow
 	   exception is masked */
 	testb	CW_Underflow,%cl		/* Underflow mask. */
-	jz	xUnmasked_underflow		/* Do not make a denormal. */
+	jz	Unmasked_underflow		/* Do not make a denormal. */
 
 	movb	DENORMAL,FPU_denormal
 
 	pushl	%ecx		/* Save */
-	movl	EXP_UNDER+1,%ecx
-	subl	EXP(%edi),%ecx
+	movw	EXP_UNDER+1,%cx
+	subw	EXP(%edi),%cx
 
-	cmpl	$64,%ecx	/* shrd only works for 0..31 bits */
-	jnc	xDenorm_shift_more_than_63
+	cmpw	$64,%cx	/* shrd only works for 0..31 bits */
+	jnc	Denorm_shift_more_than_63
 
-	cmpl	$32,%ecx	/* shrd only works for 0..31 bits */
-	jnc	xDenorm_shift_more_than_32
+	cmpw	$32,%cx	/* shrd only works for 0..31 bits */
+	jnc	Denorm_shift_more_than_32
 
 /*
  * We got here without jumps by assuming that the most common requirement
  *   is for a small de-normalising shift.
  * Shift by [1..31] bits
  */
-	addl	%ecx,EXP(%edi)
+	addw	%cx,EXP(%edi)
 	orl	%edx,%edx	/* extension */
 	setne	%ch		/* Save whether %edx is non-zero */
 	xorl	%edx,%edx
@@ -485,11 +502,11 @@
 	shr	%cl,%eax
 	orb	%ch,%dl
 	popl	%ecx
-	jmp	xDenorm_done
+	jmp	Denorm_done
 
 /* Shift by [32..63] bits */
-xDenorm_shift_more_than_32:
-	addl	%ecx,EXP(%edi)
+Denorm_shift_more_than_32:
+	addw	%cx,EXP(%edi)
 	subb	$32,%cl
 	orl	%edx,%edx
 	setne	%ch
@@ -506,15 +523,15 @@
 	movl	%eax,%ebx
 	xorl	%eax,%eax
 	popl	%ecx
-	jmp	xDenorm_done
+	jmp	Denorm_done
 
 /* Shift by [64..) bits */
-xDenorm_shift_more_than_63:
-	cmpl	$64,%ecx
-	jne	xDenorm_shift_more_than_64
+Denorm_shift_more_than_63:
+	cmpw	$64,%cx
+	jne	Denorm_shift_more_than_64
 
 /* Exactly 64 bit shift */
-	addl	%ecx,EXP(%edi)
+	addw	%cx,EXP(%edi)
 	xorl	%ecx,%ecx
 	orl	%edx,%edx
 	setne	%cl
@@ -526,32 +543,32 @@
 	xorl	%eax,%eax
 	xorl	%ebx,%ebx
 	popl	%ecx
-	jmp	xDenorm_done
+	jmp	Denorm_done
 
-xDenorm_shift_more_than_64:
-	movl	EXP_UNDER+1,EXP(%edi)
+Denorm_shift_more_than_64:
+	movw	EXP_UNDER+1,EXP(%edi)
 /* This is easy, %eax must be non-zero, so.. */
 	movl	$1,%edx
 	xorl	%eax,%eax
 	xorl	%ebx,%ebx
 	popl	%ecx
-	jmp	xDenorm_done
+	jmp	Denorm_done
 
 
-xUnmasked_underflow:
+Unmasked_underflow:
 	movb	UNMASKED_UNDERFLOW,FPU_denormal
-	jmp	xDenorm_done
+	jmp	Denorm_done
 
 
 /* Undo the de-normalisation. */
-xNormalise_result:
+Normalise_result:
 	cmpb	UNMASKED_UNDERFLOW,FPU_denormal
-	je	xSignal_underflow
+	je	Signal_underflow
 
 /* The number must be a denormal if we got here. */
 #ifdef PARANOID
 	/* But check it... just in case. */
-	cmpl	EXP_UNDER+1,EXP(%edi)
+	cmpw	EXP_UNDER+1,EXP(%edi)
 	jne	L_norm_bugged
 #endif PARANOID
 
@@ -565,41 +582,33 @@
 	 * Actual 80486 behaviour differs from this in some circumstances.
 	 */
 	orl	%eax,%eax		/* ms bits */
-	js	LNormalise_shift_done	/* Will be masked underflow */
-#endif PECULIAR_486
-
+	js	LPseudoDenormal		/* Will be masked underflow */
+#else
 	orl	%eax,%eax		/* ms bits */
-	js	xL_Normalised		/* No longer a denormal */
+	js	L_Normalised		/* No longer a denormal */
+#endif PECULIAR_486
 
-	jnz	LNormalise_shift_up_to_31	/* Shift left 0 - 31 bits */
+	jnz	LDenormal_adj_exponent
 
 	orl	%ebx,%ebx
 	jz	L_underflow_to_zero	/* The contents are zero */
 
-/* Shift left 32 - 63 bits */
-	movl	%ebx,%eax
-	xorl	%ebx,%ebx
-	subl	$32,EXP(%edi)
-
-LNormalise_shift_up_to_31:
-	bsrl	%eax,%ecx	/* get the required shift in %ecx */
-	subl	$31,%ecx
-	negl	%ecx
-	shld	%cl,%ebx,%eax
-	shl	%cl,%ebx
-	subl	%ecx,EXP(%edi)
+LDenormal_adj_exponent:
+	decw	EXP(%edi)
 
-LNormalise_shift_done:
+LPseudoDenormal:
 	testb	$0xff,FPU_bits_lost	/* bits lost == underflow */
-	jz	xL_Normalised
+	movl	TAG_Special,%edx
+	jz	L_deNormalised
 
 	/* There must be a masked underflow */
 	push	%eax
 	pushl	EX_Underflow
-	call	SYMBOL_NAME(FPU_exception)
+	call	EXCEPTION
 	popl	%eax
 	popl	%eax
-	jmp	xL_Normalised
+	movl	TAG_Special,%edx
+	jmp	L_deNormalised
 
 
 /*
@@ -613,41 +622,42 @@
 
 	push	%eax
 	pushl	EX_Underflow
-	call	SYMBOL_NAME(FPU_exception)
+	call	EXCEPTION
 	popl	%eax
 	popl	%eax
 
 /* Reduce the exponent to EXP_UNDER */
-	movl	EXP_UNDER,EXP(%edi)
-	movb	TW_Zero,TAG(%edi)
-	jmp	xL_Store_significand
+	movw	EXP_UNDER,EXP(%edi)
+	movl	TAG_Zero,%edx
+	jmp	L_Store_significand
 
 
 /* The operations resulted in a number too large to represent. */
 L_overflow:
+	addw	EXTENDED_Ebias,EXP(%edi)	/* Set for unmasked response. */
 	push	%edi
 	call	SYMBOL_NAME(arith_overflow)
 	pop	%edi
-	jmp	fpu_reg_round_exit
+	jmp	fpu_reg_round_signed_special_exit
 
 
-xSignal_underflow:
+Signal_underflow:
 	/* The number may have been changed to a non-denormal */
 	/* by the rounding operations. */
-	cmpl	EXP_UNDER,EXP(%edi)
-	jle	xDo_unmasked_underflow
+	cmpw	EXP_UNDER,EXP(%edi)
+	jle	Do_unmasked_underflow
 
-	jmp	xL_Normalised
+	jmp	L_Normalised
 
-xDo_unmasked_underflow:
+Do_unmasked_underflow:
 	/* Increase the exponent by the magic number */
-	addl	$(3*(1<<13)),EXP(%edi)
+	addw	$(3*(1<<13)),EXP(%edi)
 	push	%eax
 	pushl	EX_Underflow
 	call	EXCEPTION
 	popl	%eax
 	popl	%eax
-	jmp	xL_Normalised
+	jmp	L_Normalised
 
 
 #ifdef PARANOID
@@ -694,6 +704,6 @@
 	call	EXCEPTION
 	popl	%ebx
 L_exception_exit:
-	mov	$1,%eax
-	jmp	fpu_reg_round_exit
+	mov	$-1,%eax
+	jmp	fpu_reg_round_special_exit
 #endif PARANOID

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov