about summary refs log tree commit diff
path: root/sysdeps/alpha/divqu.S
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2004-09-06 02:01:35 +0000
committerRichard Henderson <rth@redhat.com>2004-09-06 02:01:35 +0000
commitfebcd83655138bcb01b2680e170e6773a1ec813c (patch)
tree28ede43c995a57e82b29bd5fc3fef7112d5a4c20 /sysdeps/alpha/divqu.S
parent42d86dd6c0a12373cb1d10b49f7ad2fb6488d364 (diff)
downloadglibc-febcd83655138bcb01b2680e170e6773a1ec813c.tar.gz
glibc-febcd83655138bcb01b2680e170e6773a1ec813c.tar.xz
glibc-febcd83655138bcb01b2680e170e6773a1ec813c.zip
* 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.
2004-09-05  Richard Henderson  <rth@redhat.com>

	* 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.
Diffstat (limited to 'sysdeps/alpha/divqu.S')
-rw-r--r--sysdeps/alpha/divqu.S32
1 files changed, 25 insertions, 7 deletions
diff --git a/sysdeps/alpha/divqu.S b/sysdeps/alpha/divqu.S
index 63b575faa7..fc00fa133c 100644
--- a/sysdeps/alpha/divqu.S
+++ b/sysdeps/alpha/divqu.S
@@ -33,7 +33,12 @@
    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
    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
 	.align	4
@@ -53,10 +58,15 @@ __divqu:
 	   ready -- all the time in the world to figure out how we're
 	   going to use the results.  */
 	stt	$f0, 0(sp)
-	stt	$f1, 8(sp)
+	excb
 	beq	Y, DIVBYZERO
+
+	stt	$f1, 8(sp)
+	stt	$f3, 48(sp)
 	cfi_rel_offset ($f0, 0)
 	cfi_rel_offset ($f1, 8)
+	cfi_rel_offset ($f3, 48)
+	mf_fpcr	$f3
 
 	_ITOFT2	X, $f0, 16, Y, $f1, 24
 	cvtqt	$f0, $f0
@@ -65,10 +75,7 @@ __divqu:
 	divt/c	$f0, $f1, $f0
 
 	/* Check to see if Y was mis-converted as signed value.  */
-	.align	4
 	ldt	$f1, 8(sp)
-	unop
-	nop
 	blt	Y, $y_is_neg
 
 	/* 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.
 	   Do nothing else besides convert and clean up.  */
 	cvttq/c	$f0, $f0
+	excb
+	mt_fpcr	$f3
 	_FTOIT	$f0, RV, 16
+
 	ldt	$f0, 0(sp)
+	ldt	$f3, 48(sp)
 	cfi_remember_state
 	cfi_restore ($f0)
 	cfi_restore ($f1)
+	cfi_restore ($f3)
 	cfi_def_cfa_offset (0)
 	lda	sp, FRAME(sp)
 	ret	$31, (RA), 1
@@ -140,9 +152,9 @@ $x_big:
 
 	.align	4
 	stq	t4, 8(sp)
-	unop
+	excb
 	ldt	$f0, 0(sp)
-	unop
+	mt_fpcr	$f3
 	cfi_rel_offset (t4, 8)
 	cfi_restore ($f0)
 
@@ -164,6 +176,7 @@ $q_low_ret:
 	ldq	t2, 32(sp)
 
 	ldq	t3, 40(sp)
+	ldt	$f3, 48(sp)
 	lda	sp, FRAME(sp)
 	cfi_remember_state
 	cfi_restore (t0)
@@ -171,6 +184,7 @@ $q_low_ret:
 	cfi_restore (t2)
 	cfi_restore (t3)
 	cfi_restore (t4)
+	cfi_restore ($f3)
 	cfi_def_cfa_offset (0)
 	ret	$31, (RA), 1
 
@@ -227,9 +241,13 @@ $y_is_neg:
 	   from the divide will be completely wrong.  Fortunately, the
 	   quotient must be either 0 or 1, so just compute it directly.  */
 	cmpult	Y, X, RV
+	excb
+	mt_fpcr	$f3
 	ldt	$f0, 0(sp)
+	ldt	$f3, 48(sp)
 	lda	sp, FRAME(sp)
 	cfi_restore ($f0)
+	cfi_restore ($f3)
 	cfi_def_cfa_offset (0)
 	ret	$31, (RA), 1