* sysdeps/alpha/div.S: Save and restore FPCR around fp operations.

* sysdeps/alpha/divl.S, sysdeps/alpha/divq.S, sysdeps/alpha/divqu.S,
        sysdeps/alpha/ldiv.S, sysdeps/alpha/reml.S, sysdeps/alpha/remq.S,
        sysdeps/alpha/remqu.S: Likewise.
        * sysdeps/alpha/div_libc.h (FRAME): Increase to 64.
This commit is contained in:
Richard Henderson 2004-09-06 02:01:35 +00:00
parent df8419fe0a
commit a61c91b0ca
9 changed files with 130 additions and 29 deletions

View File

@ -48,6 +48,8 @@ div:
#endif #endif
beq $18, $divbyzero beq $18, $divbyzero
excb
mf_fpcr $f10
_ITOFT2 $17, $f0, 0, $18, $f1, 8 _ITOFT2 $17, $f0, 0, $18, $f1, 8
@ -55,7 +57,8 @@ div:
cvtqt $f1, $f1 cvtqt $f1, $f1
divt/c $f0, $f1, $f0 divt/c $f0, $f1, $f0
cvttq/c $f0, $f0 cvttq/c $f0, $f0
excb
mt_fpcr $f10
_FTOIT $f0, $0, 0 _FTOIT $f0, $0, 0
mull $0, $18, $1 mull $0, $18, $1

View File

@ -71,7 +71,7 @@
/* In order to make the below work, all top-level divide routines must /* In order to make the below work, all top-level divide routines must
use the same frame size. */ use the same frame size. */
#define FRAME 48 #define FRAME 64
/* Code fragment to generate an integer divide-by-zero fault. When /* Code fragment to generate an integer divide-by-zero fault. When
building libc.so, we arrange for there to be one copy of this code building libc.so, we arrange for there to be one copy of this code

View File

@ -22,7 +22,12 @@
registers are t10 and t11, the result goes in t12. Only t12 and AT may registers are t10 and t11, the result goes in t12. Only t12 and AT may
be clobbered. be clobbered.
The FPU can handle all input values except zero. Whee! */ The FPU can handle all input values except zero. Whee!
The FPCR save/restore is due to the fact that the EV6 _will_ set FPCR_INE
for cvttq/c even without /sui being set. It will not, however, properly
raise the exception, so we don't have to worry about FPCR_INED being clear
and so dying by SIGFPE. */
#ifndef EXTEND #ifndef EXTEND
#define EXTEND(S,D) sextl S, D #define EXTEND(S,D) sextl S, D
@ -41,25 +46,34 @@ __divl:
cfi_def_cfa_offset (FRAME) cfi_def_cfa_offset (FRAME)
CALL_MCOUNT CALL_MCOUNT
stt $f0, 0(sp) stt $f0, 0(sp)
stt $f1, 8(sp) excb
beq Y, DIVBYZERO beq Y, DIVBYZERO
stt $f1, 8(sp)
stt $f2, 16(sp)
cfi_rel_offset ($f0, 0) cfi_rel_offset ($f0, 0)
cfi_rel_offset ($f1, 8) cfi_rel_offset ($f1, 8)
cfi_rel_offset ($f2, 16)
mf_fpcr $f2
EXTEND (X, RV) EXTEND (X, RV)
EXTEND (Y, AT) EXTEND (Y, AT)
_ITOFT2 RV, $f0, 16, AT, $f1, 24 _ITOFT2 RV, $f0, 24, AT, $f1, 32
cvtqt $f0, $f0 cvtqt $f0, $f0
cvtqt $f1, $f1 cvtqt $f1, $f1
divt/c $f0, $f1, $f0 divt/c $f0, $f1, $f0
cvttq/c $f0, $f0 cvttq/c $f0, $f0
_FTOIT $f0, RV, 16 excb
mt_fpcr $f2
_FTOIT $f0, RV, 24
ldt $f0, 0(sp) ldt $f0, 0(sp)
ldt $f1, 8(sp) ldt $f1, 8(sp)
ldt $f2, 16(sp)
lda sp, FRAME(sp) lda sp, FRAME(sp)
cfi_restore ($f0) cfi_restore ($f0)
cfi_restore ($f1) cfi_restore ($f1)
cfi_restore ($f2)
cfi_def_cfa_offset (0) cfi_def_cfa_offset (0)
sextl RV, RV sextl RV, RV
ret $31, (RA), 1 ret $31, (RA), 1

View File

@ -33,7 +33,12 @@
When the dividend is outside the range for which we can compute exact When the dividend is outside the range for which we can compute exact
results, we use the fp quotent as an estimate from which we begin refining results, we use the fp quotent as an estimate from which we begin refining
an exact integral value. This reduces the number of iterations in the an exact integral value. This reduces the number of iterations in the
shift-and-subtract loop significantly. */ shift-and-subtract loop significantly.
The FPCR save/restore is due to the fact that the EV6 _will_ set FPCR_INE
for cvttq/c even without /sui being set. It will not, however, properly
raise the exception, so we don't have to worry about FPCR_INED being clear
and so dying by SIGFPE. */
.text .text
.align 4 .align 4
@ -53,10 +58,15 @@ __divq:
ready -- all the time in the world to figure out how we're ready -- all the time in the world to figure out how we're
going to use the results. */ going to use the results. */
stt $f0, 0(sp) stt $f0, 0(sp)
stt $f1, 8(sp) excb
beq Y, DIVBYZERO beq Y, DIVBYZERO
stt $f1, 8(sp)
stt $f3, 48(sp)
cfi_rel_offset ($f0, 0) cfi_rel_offset ($f0, 0)
cfi_rel_offset ($f1, 8) cfi_rel_offset ($f1, 8)
cfi_rel_offset ($f3, 48)
mf_fpcr $f3
_ITOFT2 X, $f0, 16, Y, $f1, 24 _ITOFT2 X, $f0, 16, Y, $f1, 24
cvtqt $f0, $f0 cvtqt $f0, $f0
@ -73,12 +83,16 @@ __divq:
/* If we get here, we're expecting exact results from the division. /* If we get here, we're expecting exact results from the division.
Do nothing else besides convert and clean up. */ Do nothing else besides convert and clean up. */
cvttq/c $f0, $f0 cvttq/c $f0, $f0
excb
mt_fpcr $f3
_FTOIT $f0, RV, 16 _FTOIT $f0, RV, 16
ldt $f0, 0(sp) ldt $f0, 0(sp)
ldt $f3, 48(sp)
cfi_restore ($f1) cfi_restore ($f1)
cfi_remember_state cfi_remember_state
cfi_restore ($f0) cfi_restore ($f0)
cfi_restore ($f3)
cfi_def_cfa_offset (0) cfi_def_cfa_offset (0)
lda sp, FRAME(sp) lda sp, FRAME(sp)
ret $31, (RA), 1 ret $31, (RA), 1
@ -121,9 +135,9 @@ $fix_sign_in_ret2:
cfi_rel_offset (t3, 0) cfi_rel_offset (t3, 0)
mulq Q, Y, QY mulq Q, Y, QY
unop excb
stq t4, 8(sp) stq t4, 8(sp)
unop mt_fpcr $f3
cfi_rel_offset (t4, 8) cfi_rel_offset (t4, 8)
subq QY, X, R subq QY, X, R
@ -147,6 +161,7 @@ $fix_sign_out_ret:
ldq t3, 0(sp) ldq t3, 0(sp)
ldq t4, 8(sp) ldq t4, 8(sp)
ldq t5, 40(sp) ldq t5, 40(sp)
ldt $f3, 48(sp)
lda sp, FRAME(sp) lda sp, FRAME(sp)
cfi_remember_state cfi_remember_state
cfi_restore (t0) cfi_restore (t0)
@ -155,6 +170,7 @@ $fix_sign_out_ret:
cfi_restore (t3) cfi_restore (t3)
cfi_restore (t4) cfi_restore (t4)
cfi_restore (t5) cfi_restore (t5)
cfi_restore ($f3)
cfi_def_cfa_offset (0) cfi_def_cfa_offset (0)
ret $31, (RA), 1 ret $31, (RA), 1

View File

@ -33,7 +33,12 @@
When the dividend is outside the range for which we can compute exact When the dividend is outside the range for which we can compute exact
results, we use the fp quotent as an estimate from which we begin refining results, we use the fp quotent as an estimate from which we begin refining
an exact integral value. This reduces the number of iterations in the an exact integral value. This reduces the number of iterations in the
shift-and-subtract loop significantly. */ shift-and-subtract loop significantly.
The FPCR save/restore is due to the fact that the EV6 _will_ set FPCR_INE
for cvttq/c even without /sui being set. It will not, however, properly
raise the exception, so we don't have to worry about FPCR_INED being clear
and so dying by SIGFPE. */
.text .text
.align 4 .align 4
@ -53,10 +58,15 @@ __divqu:
ready -- all the time in the world to figure out how we're ready -- all the time in the world to figure out how we're
going to use the results. */ going to use the results. */
stt $f0, 0(sp) stt $f0, 0(sp)
stt $f1, 8(sp) excb
beq Y, DIVBYZERO beq Y, DIVBYZERO
stt $f1, 8(sp)
stt $f3, 48(sp)
cfi_rel_offset ($f0, 0) cfi_rel_offset ($f0, 0)
cfi_rel_offset ($f1, 8) cfi_rel_offset ($f1, 8)
cfi_rel_offset ($f3, 48)
mf_fpcr $f3
_ITOFT2 X, $f0, 16, Y, $f1, 24 _ITOFT2 X, $f0, 16, Y, $f1, 24
cvtqt $f0, $f0 cvtqt $f0, $f0
@ -65,10 +75,7 @@ __divqu:
divt/c $f0, $f1, $f0 divt/c $f0, $f1, $f0
/* Check to see if Y was mis-converted as signed value. */ /* Check to see if Y was mis-converted as signed value. */
.align 4
ldt $f1, 8(sp) ldt $f1, 8(sp)
unop
nop
blt Y, $y_is_neg blt Y, $y_is_neg
/* Check to see if X fit in the double as an exact value. */ /* Check to see if X fit in the double as an exact value. */
@ -78,11 +85,16 @@ __divqu:
/* If we get here, we're expecting exact results from the division. /* If we get here, we're expecting exact results from the division.
Do nothing else besides convert and clean up. */ Do nothing else besides convert and clean up. */
cvttq/c $f0, $f0 cvttq/c $f0, $f0
excb
mt_fpcr $f3
_FTOIT $f0, RV, 16 _FTOIT $f0, RV, 16
ldt $f0, 0(sp) ldt $f0, 0(sp)
ldt $f3, 48(sp)
cfi_remember_state cfi_remember_state
cfi_restore ($f0) cfi_restore ($f0)
cfi_restore ($f1) cfi_restore ($f1)
cfi_restore ($f3)
cfi_def_cfa_offset (0) cfi_def_cfa_offset (0)
lda sp, FRAME(sp) lda sp, FRAME(sp)
ret $31, (RA), 1 ret $31, (RA), 1
@ -140,9 +152,9 @@ $x_big:
.align 4 .align 4
stq t4, 8(sp) stq t4, 8(sp)
unop excb
ldt $f0, 0(sp) ldt $f0, 0(sp)
unop mt_fpcr $f3
cfi_rel_offset (t4, 8) cfi_rel_offset (t4, 8)
cfi_restore ($f0) cfi_restore ($f0)
@ -164,6 +176,7 @@ $q_low_ret:
ldq t2, 32(sp) ldq t2, 32(sp)
ldq t3, 40(sp) ldq t3, 40(sp)
ldt $f3, 48(sp)
lda sp, FRAME(sp) lda sp, FRAME(sp)
cfi_remember_state cfi_remember_state
cfi_restore (t0) cfi_restore (t0)
@ -171,6 +184,7 @@ $q_low_ret:
cfi_restore (t2) cfi_restore (t2)
cfi_restore (t3) cfi_restore (t3)
cfi_restore (t4) cfi_restore (t4)
cfi_restore ($f3)
cfi_def_cfa_offset (0) cfi_def_cfa_offset (0)
ret $31, (RA), 1 ret $31, (RA), 1
@ -227,9 +241,13 @@ $y_is_neg:
from the divide will be completely wrong. Fortunately, the from the divide will be completely wrong. Fortunately, the
quotient must be either 0 or 1, so just compute it directly. */ quotient must be either 0 or 1, so just compute it directly. */
cmpult Y, X, RV cmpult Y, X, RV
excb
mt_fpcr $f3
ldt $f0, 0(sp) ldt $f0, 0(sp)
ldt $f3, 48(sp)
lda sp, FRAME(sp) lda sp, FRAME(sp)
cfi_restore ($f0) cfi_restore ($f0)
cfi_restore ($f3)
cfi_def_cfa_offset (0) cfi_def_cfa_offset (0)
ret $31, (RA), 1 ret $31, (RA), 1

View File

@ -53,6 +53,8 @@ ldiv:
#endif #endif
beq Y, $divbyzero beq Y, $divbyzero
excb
mf_fpcr $f10
_ITOFT2 X, $f0, 0, Y, $f1, 8 _ITOFT2 X, $f0, 0, Y, $f1, 8
@ -71,6 +73,8 @@ ldiv:
/* If we get here, we're expecting exact results from the division. /* If we get here, we're expecting exact results from the division.
Do nothing else besides convert and clean up. */ Do nothing else besides convert and clean up. */
cvttq/c $f0, $f0 cvttq/c $f0, $f0
excb
mt_fpcr $f10
_FTOIT $f0, $0, 0 _FTOIT $f0, $0, 0
$egress: $egress:
@ -107,9 +111,10 @@ $fix_sign_in_ret1:
cvttq/c $f0, $f0 cvttq/c $f0, $f0
_FTOIT $f0, Q, 8 _FTOIT $f0, Q, 8
.align 3
$fix_sign_in_ret2: $fix_sign_in_ret2:
mulq Q, Y, QY mulq Q, Y, QY
excb
mt_fpcr $f10
.align 4 .align 4
subq QY, X, R subq QY, X, R

View File

@ -24,7 +24,12 @@
be clobbered. be clobbered.
The FPU can handle the division for all input values except zero. The FPU can handle the division for all input values except zero.
All we have to do is compute the remainder via multiply-and-subtract. */ All we have to do is compute the remainder via multiply-and-subtract.
The FPCR save/restore is due to the fact that the EV6 _will_ set FPCR_INE
for cvttq/c even without /sui being set. It will not, however, properly
raise the exception, so we don't have to worry about FPCR_INED being clear
and so dying by SIGFPE. */
#ifndef EXTEND #ifndef EXTEND
#define EXTEND(S,D) sextl S, D #define EXTEND(S,D) sextl S, D
@ -43,26 +48,35 @@ __reml:
cfi_def_cfa_offset (FRAME) cfi_def_cfa_offset (FRAME)
CALL_MCOUNT CALL_MCOUNT
stt $f0, 0(sp) stt $f0, 0(sp)
stt $f1, 8(sp) excb
beq Y, DIVBYZERO beq Y, DIVBYZERO
stt $f1, 8(sp)
stt $f2, 16(sp)
cfi_rel_offset ($f0, 0) cfi_rel_offset ($f0, 0)
cfi_rel_offset ($f1, 8) cfi_rel_offset ($f1, 8)
cfi_rel_offset ($f2, 16)
mf_fpcr $f2
EXTEND (X, RV) EXTEND (X, RV)
EXTEND (Y, AT) EXTEND (Y, AT)
_ITOFT2 RV, $f0, 16, AT, $f1, 24 _ITOFT2 RV, $f0, 24, AT, $f1, 32
cvtqt $f0, $f0 cvtqt $f0, $f0
cvtqt $f1, $f1 cvtqt $f1, $f1
divt/c $f0, $f1, $f0 divt/c $f0, $f1, $f0
cvttq/c $f0, $f0 cvttq/c $f0, $f0
_FTOIT $f0, RV, 16 excb
mt_fpcr $f2
_FTOIT $f0, RV, 24
ldt $f0, 0(sp) ldt $f0, 0(sp)
mull RV, Y, RV mull RV, Y, RV
ldt $f1, 8(sp) ldt $f1, 8(sp)
ldt $f2, 16(sp)
lda sp, FRAME(sp) lda sp, FRAME(sp)
cfi_restore ($f0) cfi_restore ($f0)
cfi_restore ($f1) cfi_restore ($f1)
cfi_restore ($f2)
cfi_def_cfa_offset (0) cfi_def_cfa_offset (0)
subl X, RV, RV subl X, RV, RV
ret $31, (RA), 1 ret $31, (RA), 1

View File

@ -33,7 +33,12 @@
When the dividend is outside the range for which we can compute exact When the dividend is outside the range for which we can compute exact
results, we use the fp quotent as an estimate from which we begin refining results, we use the fp quotent as an estimate from which we begin refining
an exact integral value. This reduces the number of iterations in the an exact integral value. This reduces the number of iterations in the
shift-and-subtract loop significantly. */ shift-and-subtract loop significantly.
The FPCR save/restore is due to the fact that the EV6 _will_ set FPCR_INE
for cvttq/c even without /sui being set. It will not, however, properly
raise the exception, so we don't have to worry about FPCR_INED being clear
and so dying by SIGFPE. */
.text .text
.align 4 .align 4
@ -53,10 +58,15 @@ __remq:
ready -- all the time in the world to figure out how we're ready -- all the time in the world to figure out how we're
going to use the results. */ going to use the results. */
stt $f0, 0(sp) stt $f0, 0(sp)
stt $f1, 8(sp) excb
beq Y, DIVBYZERO beq Y, DIVBYZERO
stt $f1, 8(sp)
stt $f3, 48(sp)
cfi_rel_offset ($f0, 0) cfi_rel_offset ($f0, 0)
cfi_rel_offset ($f1, 8) cfi_rel_offset ($f1, 8)
cfi_rel_offset ($f3, 48)
mf_fpcr $f3
_ITOFT2 X, $f0, 16, Y, $f1, 24 _ITOFT2 X, $f0, 16, Y, $f1, 24
cvtqt $f0, $f0 cvtqt $f0, $f0
@ -73,12 +83,16 @@ __remq:
/* If we get here, we're expecting exact results from the division. /* If we get here, we're expecting exact results from the division.
Do nothing else besides convert, compute remainder, clean up. */ Do nothing else besides convert, compute remainder, clean up. */
cvttq/c $f0, $f0 cvttq/c $f0, $f0
excb
mt_fpcr $f3
_FTOIT $f0, AT, 16 _FTOIT $f0, AT, 16
mulq AT, Y, AT mulq AT, Y, AT
ldt $f0, 0(sp) ldt $f0, 0(sp)
ldt $f3, 48(sp)
cfi_restore ($f1) cfi_restore ($f1)
cfi_remember_state cfi_remember_state
cfi_restore ($f0) cfi_restore ($f0)
cfi_restore ($f3)
cfi_def_cfa_offset (0) cfi_def_cfa_offset (0)
lda sp, FRAME(sp) lda sp, FRAME(sp)
subq X, AT, RV subq X, AT, RV
@ -122,9 +136,9 @@ $fix_sign_in_ret2:
cfi_rel_offset (t3, 0) cfi_rel_offset (t3, 0)
mulq Q, Y, QY mulq Q, Y, QY
unop excb
stq t4, 8(sp) stq t4, 8(sp)
unop mt_fpcr $f3
cfi_rel_offset (t4, 8) cfi_rel_offset (t4, 8)
subq QY, X, R subq QY, X, R
@ -148,6 +162,7 @@ $fix_sign_out_ret:
ldq t3, 0(sp) ldq t3, 0(sp)
ldq t4, 8(sp) ldq t4, 8(sp)
ldq t5, 40(sp) ldq t5, 40(sp)
ldt $f3, 48(sp)
lda sp, FRAME(sp) lda sp, FRAME(sp)
cfi_remember_state cfi_remember_state
cfi_restore (t0) cfi_restore (t0)
@ -156,6 +171,7 @@ $fix_sign_out_ret:
cfi_restore (t3) cfi_restore (t3)
cfi_restore (t4) cfi_restore (t4)
cfi_restore (t5) cfi_restore (t5)
cfi_restore ($f3)
cfi_def_cfa_offset (0) cfi_def_cfa_offset (0)
ret $31, (RA), 1 ret $31, (RA), 1

View File

@ -33,7 +33,12 @@
When the dividend is outside the range for which we can compute exact When the dividend is outside the range for which we can compute exact
results, we use the fp quotent as an estimate from which we begin refining results, we use the fp quotent as an estimate from which we begin refining
an exact integral value. This reduces the number of iterations in the an exact integral value. This reduces the number of iterations in the
shift-and-subtract loop significantly. */ shift-and-subtract loop significantly.
The FPCR save/restore is due to the fact that the EV6 _will_ set FPCR_INE
for cvttq/c even without /sui being set. It will not, however, properly
raise the exception, so we don't have to worry about FPCR_INED being clear
and so dying by SIGFPE. */
.text .text
.align 4 .align 4
@ -57,11 +62,15 @@ __remqu:
and Y, AT, AT and Y, AT, AT
stt $f1, 8(sp) stt $f1, 8(sp)
excb
stt $f3, 48(sp)
beq AT, $powerof2 beq AT, $powerof2
cfi_rel_offset ($f0, 0) cfi_rel_offset ($f0, 0)
cfi_rel_offset ($f1, 8) cfi_rel_offset ($f1, 8)
cfi_rel_offset ($f3, 48)
_ITOFT2 X, $f0, 16, Y, $f1, 24 _ITOFT2 X, $f0, 16, Y, $f1, 24
mf_fpcr $f3
cvtqt $f0, $f0 cvtqt $f0, $f0
cvtqt $f1, $f1 cvtqt $f1, $f1
@ -79,14 +88,18 @@ __remqu:
/* If we get here, we're expecting exact results from the division. /* If we get here, we're expecting exact results from the division.
Do nothing else besides convert, compute remainder, clean up. */ Do nothing else besides convert, compute remainder, clean up. */
cvttq/c $f0, $f0 cvttq/c $f0, $f0
excb
mt_fpcr $f3
_FTOIT $f0, AT, 16 _FTOIT $f0, AT, 16
mulq AT, Y, AT mulq AT, Y, AT
ldt $f0, 0(sp) ldt $f0, 0(sp)
ldt $f3, 48(sp)
lda sp, FRAME(sp) lda sp, FRAME(sp)
cfi_remember_state cfi_remember_state
cfi_restore ($f0) cfi_restore ($f0)
cfi_restore ($f1) cfi_restore ($f1)
cfi_restore ($f3)
cfi_def_cfa_offset (0) cfi_def_cfa_offset (0)
.align 4 .align 4
@ -144,9 +157,9 @@ $x_big:
.align 4 .align 4
stq t4, 8(sp) stq t4, 8(sp)
unop excb
ldt $f0, 0(sp) ldt $f0, 0(sp)
unop mt_fpcr $f3
cfi_rel_offset (t4, 8) cfi_rel_offset (t4, 8)
cfi_restore ($f0) cfi_restore ($f0)
@ -168,6 +181,7 @@ $q_low_ret:
ldq t2, 32(sp) ldq t2, 32(sp)
ldq t3, 40(sp) ldq t3, 40(sp)
ldt $f3, 48(sp)
lda sp, FRAME(sp) lda sp, FRAME(sp)
cfi_remember_state cfi_remember_state
cfi_restore (t0) cfi_restore (t0)
@ -175,6 +189,7 @@ $q_low_ret:
cfi_restore (t2) cfi_restore (t2)
cfi_restore (t3) cfi_restore (t3)
cfi_restore (t4) cfi_restore (t4)
cfi_restore ($f3)
cfi_def_cfa_offset (0) cfi_def_cfa_offset (0)
ret $31, (RA), 1 ret $31, (RA), 1