about summary refs log tree commit diff
path: root/sysdeps/x86_64/fpu
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2012-05-05 19:37:39 +0000
committerJoseph Myers <joseph@codesourcery.com>2012-05-05 19:37:39 +0000
commit41498f4db1ebfeb2fb76b9137cba38c20000f1d3 (patch)
treee546d5a208020a4dc1598ea46d5c819e9a1a20c0 /sysdeps/x86_64/fpu
parent6698b8bf4365f09d5bb467e113068f210811b001 (diff)
downloadglibc-41498f4db1ebfeb2fb76b9137cba38c20000f1d3.tar.gz
glibc-41498f4db1ebfeb2fb76b9137cba38c20000f1d3.tar.xz
glibc-41498f4db1ebfeb2fb76b9137cba38c20000f1d3.zip
Fix missing exceptions from exp (bugs 13787, 13922, 14036).
Diffstat (limited to 'sysdeps/x86_64/fpu')
-rw-r--r--sysdeps/x86_64/fpu/e_expl.S19
1 files changed, 18 insertions, 1 deletions
diff --git a/sysdeps/x86_64/fpu/e_expl.S b/sysdeps/x86_64/fpu/e_expl.S
index c2d1d40ba5..d497b28973 100644
--- a/sysdeps/x86_64/fpu/e_expl.S
+++ b/sysdeps/x86_64/fpu/e_expl.S
@@ -35,6 +35,10 @@ c0:	.byte 0, 0, 0, 0, 0, 0, 0xaa, 0xb8, 0xff, 0x3f
 c1:	.byte 0x20, 0xfa, 0xee, 0xc2, 0x5f, 0x70, 0xa5, 0xec, 0xed, 0x3f
 	.byte 0, 0, 0, 0, 0, 0
 	ASM_SIZE_DIRECTIVE(c1)
+	ASM_TYPE_DIRECTIVE(csat,@object)
+csat:	.byte 0, 0, 0, 0, 0, 0, 0, 0x80, 0x0e, 0x40
+	.byte 0, 0, 0, 0, 0, 0
+	ASM_SIZE_DIRECTIVE(csat)
 
 #ifdef PIC
 # define MO(op) op##(%rip)
@@ -50,12 +54,25 @@ ENTRY(__ieee754_expl)
    For the i686 the code can be written better.
    -- drepper@cygnus.com.  */
 	fxam			/* Is NaN or +-Inf?  */
+	movzwl	8+8(%rsp), %eax
+	andl	$0x7fff, %eax
+	cmpl	$0x400d, %eax
+	jle	3f
+	/* Overflow, underflow or infinity or NaN as argument.  */
 	fstsw	%ax
 	movb	$0x45, %dh
 	andb	%ah, %dh
 	cmpb	$0x05, %dh
 	je	1f		/* Is +-Inf, jump.    */
-	fldl2e			/* 1  log2(e)         */
+	cmpb	$0x01, %dh
+	je	2f		/* Is +-NaN, jump.    */
+	/* Overflow or underflow; saturate.  */
+	fstp	%st
+	fldt	MO(csat)
+	andb	$2, %ah
+	jz	3f
+	fchs
+3:	fldl2e			/* 1  log2(e)         */
 	fmul	%st(1), %st	/* 1  x log2(e)       */
 	frndint			/* 1  i               */
 	fld	%st(1)		/* 2  x               */