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
- Lines: 515
- Date:
Tue Dec 9 17:57:09 1997
- Orig file:
v2.1.72/linux/arch/i386/math-emu/reg_round.S
- Orig date:
Thu Oct 10 06:01:12 1996
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