summary refs log tree commit diff
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2015-06-21 18:43:10 +0000
committerJoseph Myers <joseph@codesourcery.com>2015-06-21 18:43:10 +0000
commitcb0937b299182e78307795081489ec1f148bdbd7 (patch)
tree32137f8b8dde65185697602763252a45e40e8472
parentfea1d8d67363c8b675a4c2533769ae12dc86efff (diff)
downloadglibc-cb0937b299182e78307795081489ec1f148bdbd7.tar.gz
glibc-cb0937b299182e78307795081489ec1f148bdbd7.tar.xz
glibc-cb0937b299182e78307795081489ec1f148bdbd7.zip
Fix x86_64 / x86 expm1l (-min_subnorm) result sign (bug 18569).
In the x86 / x86_64 implementations of expm1l, when expm1l's result
should underflow to 0 (argument minus the least subnormal, in some
rounding modes), it can be a zero of the wrong sign.  This patch fixes
this by returning the argument with underflow forced in that case
(this is a 1ulp error relative to the correctly rounded result of -0,
which is OK in terms of the documented accuracy goals, whereas a
result with the wrong sign never is).

Tested for x86_64 and x86.

	[BZ #18569]
	* sysdeps/i386/fpu/e_expl.S (IEEE754_EXPL) [USE_AS_EXPM1L]: Force
	underflow and return argument in case of subnormal argument.
	* sysdeps/x86_64/fpu/e_expl.S (IEEE754_EXPL) [USE_AS_EXPM1L]:
	Likewise.
	* math/auto-libm-test-in: Add more tests of expm1.
	* math/auto-libm-test-out: Regenerated.
-rw-r--r--ChangeLog8
-rw-r--r--NEWS2
-rw-r--r--math/auto-libm-test-in4
-rw-r--r--math/auto-libm-test-out316
-rw-r--r--sysdeps/i386/fpu/e_expl.S6
-rw-r--r--sysdeps/x86_64/fpu/e_expl.S6
6 files changed, 341 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index aee4136f66..98b3802e56 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2015-06-21  Joseph Myers  <joseph@codesourcery.com>
 
+	[BZ #18569]
+	* sysdeps/i386/fpu/e_expl.S (IEEE754_EXPL) [USE_AS_EXPM1L]: Force
+	underflow and return argument in case of subnormal argument.
+	* sysdeps/x86_64/fpu/e_expl.S (IEEE754_EXPL) [USE_AS_EXPM1L]:
+	Likewise.
+	* math/auto-libm-test-in: Add more tests of expm1.
+	* math/auto-libm-test-out: Regenerated.
+
 	[BZ #16361]
 	* sysdeps/i386/fpu/e_expl.S [!USE_AS_EXPM1L] (cmin): New object.
 	(IEEE754_EXPL) [!USE_AS_EXPM1L]: Force underflow exception for
diff --git a/NEWS b/NEWS
index e4a17c3b7e..90495e8e87 100644
--- a/NEWS
+++ b/NEWS
@@ -23,7 +23,7 @@ Version 2.22
   18422, 18434, 18444, 18468, 18469, 18470, 18479, 18483, 18495, 18496,
   18497, 18498, 18507, 18512, 18519, 18520, 18522, 18527, 18528, 18529,
   18530, 18532, 18533, 18534, 18536, 18539, 18540, 18542, 18544, 18545,
-  18546, 18547, 18553, 18558.
+  18546, 18547, 18553, 18558, 18569.
 
 * Cache information can be queried via sysconf() function on s390 e.g. with
   _SC_LEVEL1_ICACHE_SIZE as argument.
diff --git a/math/auto-libm-test-in b/math/auto-libm-test-in
index e8e4da62b8..6b054597f1 100644
--- a/math/auto-libm-test-in
+++ b/math/auto-libm-test-in
@@ -1364,6 +1364,10 @@ expm1 0x5.fb8dc64e91a74p-4
 expm1 0x3.735f497c4e67535cp-4
 # Bug 16353: underflow exception may be missing
 expm1 0x4.0000000000000028p-16384 missing-underflow
+expm1 min missing-underflow
+expm1 -min missing-underflow
+expm1 min_subnorm missing-underflow
+expm1 -min_subnorm missing-underflow
 
 fma 1.0 2.0 3.0
 fma 1.25 0.75 0.0625
diff --git a/math/auto-libm-test-out b/math/auto-libm-test-out
index bf067c42bf..2aecda11f7 100644
--- a/math/auto-libm-test-out
+++ b/math/auto-libm-test-out
@@ -109579,6 +109579,322 @@ expm1 0x4.0000000000000028p-16384 missing-underflow
 = expm1 tonearest ldbl-128 0x4.0000000000000028p-16384L : 0x4.0000000000000028p-16384L : inexact-ok
 = expm1 towardzero ldbl-128 0x4.0000000000000028p-16384L : 0x4.0000000000000028p-16384L : inexact-ok
 = expm1 upward ldbl-128 0x4.0000000000000028p-16384L : 0x4.0000000000000028000000000004p-16384L : inexact-ok
+expm1 min missing-underflow
+= expm1 downward flt-32 0x4p-128f : 0x4p-128f : inexact-ok underflow-ok errno-erange-ok
+= expm1 tonearest flt-32 0x4p-128f : 0x4p-128f : inexact-ok underflow-ok errno-erange-ok
+= expm1 towardzero flt-32 0x4p-128f : 0x4p-128f : inexact-ok underflow-ok errno-erange-ok
+= expm1 upward flt-32 0x4p-128f : 0x4.000008p-128f : inexact-ok underflow-ok errno-erange-ok
+= expm1 downward dbl-64 0x4p-128 : 0x4p-128 : inexact-ok
+= expm1 tonearest dbl-64 0x4p-128 : 0x4p-128 : inexact-ok
+= expm1 towardzero dbl-64 0x4p-128 : 0x4p-128 : inexact-ok
+= expm1 upward dbl-64 0x4p-128 : 0x4.0000000000004p-128 : inexact-ok
+= expm1 downward ldbl-96-intel 0x4p-128L : 0x4p-128L : inexact-ok
+= expm1 tonearest ldbl-96-intel 0x4p-128L : 0x4p-128L : inexact-ok
+= expm1 towardzero ldbl-96-intel 0x4p-128L : 0x4p-128L : inexact-ok
+= expm1 upward ldbl-96-intel 0x4p-128L : 0x4.0000000000000008p-128L : inexact-ok
+= expm1 downward ldbl-96-m68k 0x4p-128L : 0x4p-128L : inexact-ok
+= expm1 tonearest ldbl-96-m68k 0x4p-128L : 0x4p-128L : inexact-ok
+= expm1 towardzero ldbl-96-m68k 0x4p-128L : 0x4p-128L : inexact-ok
+= expm1 upward ldbl-96-m68k 0x4p-128L : 0x4.0000000000000008p-128L : inexact-ok
+= expm1 downward ldbl-128 0x4p-128L : 0x4p-128L : inexact-ok
+= expm1 tonearest ldbl-128 0x4p-128L : 0x4p-128L : inexact-ok
+= expm1 towardzero ldbl-128 0x4p-128L : 0x4p-128L : inexact-ok
+= expm1 upward ldbl-128 0x4p-128L : 0x4.0000000000000000000000000004p-128L : inexact-ok
+= expm1 downward ldbl-128ibm 0x4p-128L : 0x4p-128L : inexact-ok
+= expm1 tonearest ldbl-128ibm 0x4p-128L : 0x4p-128L : inexact-ok
+= expm1 towardzero ldbl-128ibm 0x4p-128L : 0x4p-128L : inexact-ok
+= expm1 upward ldbl-128ibm 0x4p-128L : 0x4.00000000000000000000000002p-128L : inexact-ok
+= expm1 downward dbl-64 0x4p-1024 : 0x4p-1024 : inexact-ok underflow-ok errno-erange-ok
+= expm1 tonearest dbl-64 0x4p-1024 : 0x4p-1024 : inexact-ok underflow-ok errno-erange-ok
+= expm1 towardzero dbl-64 0x4p-1024 : 0x4p-1024 : inexact-ok underflow-ok errno-erange-ok
+= expm1 upward dbl-64 0x4p-1024 : 0x4.0000000000004p-1024 : inexact-ok underflow-ok errno-erange-ok
+= expm1 downward ldbl-96-intel 0x4p-1024L : 0x4p-1024L : inexact-ok
+= expm1 tonearest ldbl-96-intel 0x4p-1024L : 0x4p-1024L : inexact-ok
+= expm1 towardzero ldbl-96-intel 0x4p-1024L : 0x4p-1024L : inexact-ok
+= expm1 upward ldbl-96-intel 0x4p-1024L : 0x4.0000000000000008p-1024L : inexact-ok
+= expm1 downward ldbl-96-m68k 0x4p-1024L : 0x4p-1024L : inexact-ok
+= expm1 tonearest ldbl-96-m68k 0x4p-1024L : 0x4p-1024L : inexact-ok
+= expm1 towardzero ldbl-96-m68k 0x4p-1024L : 0x4p-1024L : inexact-ok
+= expm1 upward ldbl-96-m68k 0x4p-1024L : 0x4.0000000000000008p-1024L : inexact-ok
+= expm1 downward ldbl-128 0x4p-1024L : 0x4p-1024L : inexact-ok
+= expm1 tonearest ldbl-128 0x4p-1024L : 0x4p-1024L : inexact-ok
+= expm1 towardzero ldbl-128 0x4p-1024L : 0x4p-1024L : inexact-ok
+= expm1 upward ldbl-128 0x4p-1024L : 0x4.0000000000000000000000000004p-1024L : inexact-ok
+= expm1 downward ldbl-128ibm 0x4p-1024L : 0x4p-1024L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-128ibm 0x4p-1024L : 0x4p-1024L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-128ibm 0x4p-1024L : 0x4p-1024L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward ldbl-128ibm 0x4p-1024L : 0x4.0000000000004p-1024L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 downward ldbl-96-intel 0x4p-16384L : 0x4p-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-96-intel 0x4p-16384L : 0x4p-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-96-intel 0x4p-16384L : 0x4p-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 upward ldbl-96-intel 0x4p-16384L : 0x4.0000000000000008p-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 downward ldbl-96-m68k 0x4p-16384L : 0x4p-16384L : inexact-ok
+= expm1 tonearest ldbl-96-m68k 0x4p-16384L : 0x4p-16384L : inexact-ok
+= expm1 towardzero ldbl-96-m68k 0x4p-16384L : 0x4p-16384L : inexact-ok
+= expm1 upward ldbl-96-m68k 0x4p-16384L : 0x4.0000000000000008p-16384L : inexact-ok
+= expm1 downward ldbl-128 0x4p-16384L : 0x4p-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-128 0x4p-16384L : 0x4p-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-128 0x4p-16384L : 0x4p-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 upward ldbl-128 0x4p-16384L : 0x4.0000000000000000000000000004p-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 downward ldbl-96-intel 0x2p-16384L : 0x2p-16384L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-96-intel 0x2p-16384L : 0x2p-16384L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-96-intel 0x2p-16384L : 0x2p-16384L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward ldbl-96-intel 0x2p-16384L : 0x2.0000000000000008p-16384L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 downward ldbl-96-m68k 0x2p-16384L : 0x2p-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-96-m68k 0x2p-16384L : 0x2p-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-96-m68k 0x2p-16384L : 0x2p-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 upward ldbl-96-m68k 0x2p-16384L : 0x2.0000000000000004p-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 downward ldbl-128 0x2p-16384L : 0x2p-16384L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-128 0x2p-16384L : 0x2p-16384L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-128 0x2p-16384L : 0x2p-16384L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward ldbl-128 0x2p-16384L : 0x2.0000000000000000000000000004p-16384L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 downward dbl-64 0x8p-972 : 0x8p-972 : inexact-ok
+= expm1 tonearest dbl-64 0x8p-972 : 0x8p-972 : inexact-ok
+= expm1 towardzero dbl-64 0x8p-972 : 0x8p-972 : inexact-ok
+= expm1 upward dbl-64 0x8p-972 : 0x8.0000000000008p-972 : inexact-ok
+= expm1 downward ldbl-96-intel 0x8p-972L : 0x8p-972L : inexact-ok
+= expm1 tonearest ldbl-96-intel 0x8p-972L : 0x8p-972L : inexact-ok
+= expm1 towardzero ldbl-96-intel 0x8p-972L : 0x8p-972L : inexact-ok
+= expm1 upward ldbl-96-intel 0x8p-972L : 0x8.000000000000001p-972L : inexact-ok
+= expm1 downward ldbl-96-m68k 0x8p-972L : 0x8p-972L : inexact-ok
+= expm1 tonearest ldbl-96-m68k 0x8p-972L : 0x8p-972L : inexact-ok
+= expm1 towardzero ldbl-96-m68k 0x8p-972L : 0x8p-972L : inexact-ok
+= expm1 upward ldbl-96-m68k 0x8p-972L : 0x8.000000000000001p-972L : inexact-ok
+= expm1 downward ldbl-128 0x8p-972L : 0x8p-972L : inexact-ok
+= expm1 tonearest ldbl-128 0x8p-972L : 0x8p-972L : inexact-ok
+= expm1 towardzero ldbl-128 0x8p-972L : 0x8p-972L : inexact-ok
+= expm1 upward ldbl-128 0x8p-972L : 0x8.0000000000000000000000000008p-972L : inexact-ok
+= expm1 downward ldbl-128ibm 0x8p-972L : 0x8p-972L : inexact-ok underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-128ibm 0x8p-972L : 0x8p-972L : inexact-ok underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-128ibm 0x8p-972L : 0x8p-972L : inexact-ok underflow-ok errno-erange-ok
+= expm1 upward ldbl-128ibm 0x8p-972L : 0x8.00000000000000000000000004p-972L : inexact-ok underflow-ok errno-erange-ok
+expm1 -min missing-underflow
+= expm1 downward flt-32 -0x4p-128f : -0x4p-128f : inexact-ok underflow-ok errno-erange-ok
+= expm1 tonearest flt-32 -0x4p-128f : -0x4p-128f : inexact-ok underflow-ok errno-erange-ok
+= expm1 towardzero flt-32 -0x4p-128f : -0x3.fffff8p-128f : inexact-ok underflow-ok errno-erange-ok
+= expm1 upward flt-32 -0x4p-128f : -0x3.fffff8p-128f : inexact-ok underflow-ok errno-erange-ok
+= expm1 downward dbl-64 -0x4p-128 : -0x4p-128 : inexact-ok
+= expm1 tonearest dbl-64 -0x4p-128 : -0x4p-128 : inexact-ok
+= expm1 towardzero dbl-64 -0x4p-128 : -0x3.ffffffffffffep-128 : inexact-ok
+= expm1 upward dbl-64 -0x4p-128 : -0x3.ffffffffffffep-128 : inexact-ok
+= expm1 downward ldbl-96-intel -0x4p-128L : -0x4p-128L : inexact-ok
+= expm1 tonearest ldbl-96-intel -0x4p-128L : -0x4p-128L : inexact-ok
+= expm1 towardzero ldbl-96-intel -0x4p-128L : -0x3.fffffffffffffffcp-128L : inexact-ok
+= expm1 upward ldbl-96-intel -0x4p-128L : -0x3.fffffffffffffffcp-128L : inexact-ok
+= expm1 downward ldbl-96-m68k -0x4p-128L : -0x4p-128L : inexact-ok
+= expm1 tonearest ldbl-96-m68k -0x4p-128L : -0x4p-128L : inexact-ok
+= expm1 towardzero ldbl-96-m68k -0x4p-128L : -0x3.fffffffffffffffcp-128L : inexact-ok
+= expm1 upward ldbl-96-m68k -0x4p-128L : -0x3.fffffffffffffffcp-128L : inexact-ok
+= expm1 downward ldbl-128 -0x4p-128L : -0x4p-128L : inexact-ok
+= expm1 tonearest ldbl-128 -0x4p-128L : -0x4p-128L : inexact-ok
+= expm1 towardzero ldbl-128 -0x4p-128L : -0x3.fffffffffffffffffffffffffffep-128L : inexact-ok
+= expm1 upward ldbl-128 -0x4p-128L : -0x3.fffffffffffffffffffffffffffep-128L : inexact-ok
+= expm1 downward ldbl-128ibm -0x4p-128L : -0x4p-128L : inexact-ok
+= expm1 tonearest ldbl-128ibm -0x4p-128L : -0x4p-128L : inexact-ok
+= expm1 towardzero ldbl-128ibm -0x4p-128L : -0x3.ffffffffffffffffffffffffffp-128L : inexact-ok
+= expm1 upward ldbl-128ibm -0x4p-128L : -0x3.ffffffffffffffffffffffffffp-128L : inexact-ok
+= expm1 downward dbl-64 -0x4p-1024 : -0x4p-1024 : inexact-ok underflow-ok errno-erange-ok
+= expm1 tonearest dbl-64 -0x4p-1024 : -0x4p-1024 : inexact-ok underflow-ok errno-erange-ok
+= expm1 towardzero dbl-64 -0x4p-1024 : -0x3.ffffffffffffcp-1024 : inexact-ok underflow-ok errno-erange-ok
+= expm1 upward dbl-64 -0x4p-1024 : -0x3.ffffffffffffcp-1024 : inexact-ok underflow-ok errno-erange-ok
+= expm1 downward ldbl-96-intel -0x4p-1024L : -0x4p-1024L : inexact-ok
+= expm1 tonearest ldbl-96-intel -0x4p-1024L : -0x4p-1024L : inexact-ok
+= expm1 towardzero ldbl-96-intel -0x4p-1024L : -0x3.fffffffffffffffcp-1024L : inexact-ok
+= expm1 upward ldbl-96-intel -0x4p-1024L : -0x3.fffffffffffffffcp-1024L : inexact-ok
+= expm1 downward ldbl-96-m68k -0x4p-1024L : -0x4p-1024L : inexact-ok
+= expm1 tonearest ldbl-96-m68k -0x4p-1024L : -0x4p-1024L : inexact-ok
+= expm1 towardzero ldbl-96-m68k -0x4p-1024L : -0x3.fffffffffffffffcp-1024L : inexact-ok
+= expm1 upward ldbl-96-m68k -0x4p-1024L : -0x3.fffffffffffffffcp-1024L : inexact-ok
+= expm1 downward ldbl-128 -0x4p-1024L : -0x4p-1024L : inexact-ok
+= expm1 tonearest ldbl-128 -0x4p-1024L : -0x4p-1024L : inexact-ok
+= expm1 towardzero ldbl-128 -0x4p-1024L : -0x3.fffffffffffffffffffffffffffep-1024L : inexact-ok
+= expm1 upward ldbl-128 -0x4p-1024L : -0x3.fffffffffffffffffffffffffffep-1024L : inexact-ok
+= expm1 downward ldbl-128ibm -0x4p-1024L : -0x4p-1024L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-128ibm -0x4p-1024L : -0x4p-1024L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-128ibm -0x4p-1024L : -0x3.ffffffffffffcp-1024L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward ldbl-128ibm -0x4p-1024L : -0x3.ffffffffffffcp-1024L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 downward ldbl-96-intel -0x4p-16384L : -0x4p-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-96-intel -0x4p-16384L : -0x4p-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-96-intel -0x4p-16384L : -0x3.fffffffffffffff8p-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 upward ldbl-96-intel -0x4p-16384L : -0x3.fffffffffffffff8p-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 downward ldbl-96-m68k -0x4p-16384L : -0x4p-16384L : inexact-ok
+= expm1 tonearest ldbl-96-m68k -0x4p-16384L : -0x4p-16384L : inexact-ok
+= expm1 towardzero ldbl-96-m68k -0x4p-16384L : -0x3.fffffffffffffffcp-16384L : inexact-ok
+= expm1 upward ldbl-96-m68k -0x4p-16384L : -0x3.fffffffffffffffcp-16384L : inexact-ok
+= expm1 downward ldbl-128 -0x4p-16384L : -0x4p-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-128 -0x4p-16384L : -0x4p-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-128 -0x4p-16384L : -0x3.fffffffffffffffffffffffffffcp-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 upward ldbl-128 -0x4p-16384L : -0x3.fffffffffffffffffffffffffffcp-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 downward ldbl-96-intel -0x2p-16384L : -0x2p-16384L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-96-intel -0x2p-16384L : -0x2p-16384L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-96-intel -0x2p-16384L : -0x1.fffffffffffffff8p-16384L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward ldbl-96-intel -0x2p-16384L : -0x1.fffffffffffffff8p-16384L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 downward ldbl-96-m68k -0x2p-16384L : -0x2p-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-96-m68k -0x2p-16384L : -0x2p-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-96-m68k -0x2p-16384L : -0x1.fffffffffffffffcp-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 upward ldbl-96-m68k -0x2p-16384L : -0x1.fffffffffffffffcp-16384L : inexact-ok underflow-ok errno-erange-ok
+= expm1 downward ldbl-128 -0x2p-16384L : -0x2p-16384L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-128 -0x2p-16384L : -0x2p-16384L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-128 -0x2p-16384L : -0x1.fffffffffffffffffffffffffffcp-16384L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward ldbl-128 -0x2p-16384L : -0x1.fffffffffffffffffffffffffffcp-16384L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 downward dbl-64 -0x8p-972 : -0x8p-972 : inexact-ok
+= expm1 tonearest dbl-64 -0x8p-972 : -0x8p-972 : inexact-ok
+= expm1 towardzero dbl-64 -0x8p-972 : -0x7.ffffffffffffcp-972 : inexact-ok
+= expm1 upward dbl-64 -0x8p-972 : -0x7.ffffffffffffcp-972 : inexact-ok
+= expm1 downward ldbl-96-intel -0x8p-972L : -0x8p-972L : inexact-ok
+= expm1 tonearest ldbl-96-intel -0x8p-972L : -0x8p-972L : inexact-ok
+= expm1 towardzero ldbl-96-intel -0x8p-972L : -0x7.fffffffffffffff8p-972L : inexact-ok
+= expm1 upward ldbl-96-intel -0x8p-972L : -0x7.fffffffffffffff8p-972L : inexact-ok
+= expm1 downward ldbl-96-m68k -0x8p-972L : -0x8p-972L : inexact-ok
+= expm1 tonearest ldbl-96-m68k -0x8p-972L : -0x8p-972L : inexact-ok
+= expm1 towardzero ldbl-96-m68k -0x8p-972L : -0x7.fffffffffffffff8p-972L : inexact-ok
+= expm1 upward ldbl-96-m68k -0x8p-972L : -0x7.fffffffffffffff8p-972L : inexact-ok
+= expm1 downward ldbl-128 -0x8p-972L : -0x8p-972L : inexact-ok
+= expm1 tonearest ldbl-128 -0x8p-972L : -0x8p-972L : inexact-ok
+= expm1 towardzero ldbl-128 -0x8p-972L : -0x7.fffffffffffffffffffffffffffcp-972L : inexact-ok
+= expm1 upward ldbl-128 -0x8p-972L : -0x7.fffffffffffffffffffffffffffcp-972L : inexact-ok
+= expm1 downward ldbl-128ibm -0x8p-972L : -0x8p-972L : inexact-ok underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-128ibm -0x8p-972L : -0x8p-972L : inexact-ok underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-128ibm -0x8p-972L : -0x7.fffffffffffffffffffffffffcp-972L : inexact-ok underflow-ok errno-erange-ok
+= expm1 upward ldbl-128ibm -0x8p-972L : -0x7.fffffffffffffffffffffffffcp-972L : inexact-ok underflow-ok errno-erange-ok
+expm1 min_subnorm missing-underflow
+= expm1 downward flt-32 0x8p-152f : 0x8p-152f : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest flt-32 0x8p-152f : 0x8p-152f : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero flt-32 0x8p-152f : 0x8p-152f : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward flt-32 0x8p-152f : 0x1p-148f : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 downward dbl-64 0x8p-152 : 0x8p-152 : inexact-ok
+= expm1 tonearest dbl-64 0x8p-152 : 0x8p-152 : inexact-ok
+= expm1 towardzero dbl-64 0x8p-152 : 0x8p-152 : inexact-ok
+= expm1 upward dbl-64 0x8p-152 : 0x8.0000000000008p-152 : inexact-ok
+= expm1 downward ldbl-96-intel 0x8p-152L : 0x8p-152L : inexact-ok
+= expm1 tonearest ldbl-96-intel 0x8p-152L : 0x8p-152L : inexact-ok
+= expm1 towardzero ldbl-96-intel 0x8p-152L : 0x8p-152L : inexact-ok
+= expm1 upward ldbl-96-intel 0x8p-152L : 0x8.000000000000001p-152L : inexact-ok
+= expm1 downward ldbl-96-m68k 0x8p-152L : 0x8p-152L : inexact-ok
+= expm1 tonearest ldbl-96-m68k 0x8p-152L : 0x8p-152L : inexact-ok
+= expm1 towardzero ldbl-96-m68k 0x8p-152L : 0x8p-152L : inexact-ok
+= expm1 upward ldbl-96-m68k 0x8p-152L : 0x8.000000000000001p-152L : inexact-ok
+= expm1 downward ldbl-128 0x8p-152L : 0x8p-152L : inexact-ok
+= expm1 tonearest ldbl-128 0x8p-152L : 0x8p-152L : inexact-ok
+= expm1 towardzero ldbl-128 0x8p-152L : 0x8p-152L : inexact-ok
+= expm1 upward ldbl-128 0x8p-152L : 0x8.0000000000000000000000000008p-152L : inexact-ok
+= expm1 downward ldbl-128ibm 0x8p-152L : 0x8p-152L : inexact-ok
+= expm1 tonearest ldbl-128ibm 0x8p-152L : 0x8p-152L : inexact-ok
+= expm1 towardzero ldbl-128ibm 0x8p-152L : 0x8p-152L : inexact-ok
+= expm1 upward ldbl-128ibm 0x8p-152L : 0x8.00000000000000000000000004p-152L : inexact-ok
+= expm1 downward dbl-64 0x4p-1076 : 0x4p-1076 : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest dbl-64 0x4p-1076 : 0x4p-1076 : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero dbl-64 0x4p-1076 : 0x4p-1076 : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward dbl-64 0x4p-1076 : 0x8p-1076 : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 downward ldbl-96-intel 0x4p-1076L : 0x4p-1076L : inexact-ok
+= expm1 tonearest ldbl-96-intel 0x4p-1076L : 0x4p-1076L : inexact-ok
+= expm1 towardzero ldbl-96-intel 0x4p-1076L : 0x4p-1076L : inexact-ok
+= expm1 upward ldbl-96-intel 0x4p-1076L : 0x4.0000000000000008p-1076L : inexact-ok
+= expm1 downward ldbl-96-m68k 0x4p-1076L : 0x4p-1076L : inexact-ok
+= expm1 tonearest ldbl-96-m68k 0x4p-1076L : 0x4p-1076L : inexact-ok
+= expm1 towardzero ldbl-96-m68k 0x4p-1076L : 0x4p-1076L : inexact-ok
+= expm1 upward ldbl-96-m68k 0x4p-1076L : 0x4.0000000000000008p-1076L : inexact-ok
+= expm1 downward ldbl-128 0x4p-1076L : 0x4p-1076L : inexact-ok
+= expm1 tonearest ldbl-128 0x4p-1076L : 0x4p-1076L : inexact-ok
+= expm1 towardzero ldbl-128 0x4p-1076L : 0x4p-1076L : inexact-ok
+= expm1 upward ldbl-128 0x4p-1076L : 0x4.0000000000000000000000000004p-1076L : inexact-ok
+= expm1 downward ldbl-128ibm 0x4p-1076L : 0x4p-1076L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-128ibm 0x4p-1076L : 0x4p-1076L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-128ibm 0x4p-1076L : 0x4p-1076L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward ldbl-128ibm 0x4p-1076L : 0x8p-1076L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 downward ldbl-96-intel 0x8p-16448L : 0x8p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-96-intel 0x8p-16448L : 0x8p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-96-intel 0x8p-16448L : 0x8p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward ldbl-96-intel 0x8p-16448L : 0x1p-16444L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 downward ldbl-96-m68k 0x8p-16448L : 0x8p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-96-m68k 0x8p-16448L : 0x8p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-96-m68k 0x8p-16448L : 0x8p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward ldbl-96-m68k 0x8p-16448L : 0xcp-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 downward ldbl-128 0x8p-16448L : 0x8p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-128 0x8p-16448L : 0x8p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-128 0x8p-16448L : 0x8p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward ldbl-128 0x8p-16448L : 0x8.000000000004p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 downward ldbl-96-m68k 0x4p-16448L : 0x4p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-96-m68k 0x4p-16448L : 0x4p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-96-m68k 0x4p-16448L : 0x4p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward ldbl-96-m68k 0x4p-16448L : 0x8p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 downward ldbl-128 0x4p-16448L : 0x4p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-128 0x4p-16448L : 0x4p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-128 0x4p-16448L : 0x4p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward ldbl-128 0x4p-16448L : 0x4.000000000004p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 downward ldbl-128 0x4p-16496L : 0x4p-16496L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-128 0x4p-16496L : 0x4p-16496L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-128 0x4p-16496L : 0x4p-16496L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward ldbl-128 0x4p-16496L : 0x8p-16496L : inexact-ok underflow underflow-ok errno-erange-ok
+expm1 -min_subnorm missing-underflow
+= expm1 downward flt-32 -0x8p-152f : -0x8p-152f : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest flt-32 -0x8p-152f : -0x8p-152f : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero flt-32 -0x8p-152f : -0x0p+0f : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward flt-32 -0x8p-152f : -0x0p+0f : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 downward dbl-64 -0x8p-152 : -0x8p-152 : inexact-ok
+= expm1 tonearest dbl-64 -0x8p-152 : -0x8p-152 : inexact-ok
+= expm1 towardzero dbl-64 -0x8p-152 : -0x7.ffffffffffffcp-152 : inexact-ok
+= expm1 upward dbl-64 -0x8p-152 : -0x7.ffffffffffffcp-152 : inexact-ok
+= expm1 downward ldbl-96-intel -0x8p-152L : -0x8p-152L : inexact-ok
+= expm1 tonearest ldbl-96-intel -0x8p-152L : -0x8p-152L : inexact-ok
+= expm1 towardzero ldbl-96-intel -0x8p-152L : -0x7.fffffffffffffff8p-152L : inexact-ok
+= expm1 upward ldbl-96-intel -0x8p-152L : -0x7.fffffffffffffff8p-152L : inexact-ok
+= expm1 downward ldbl-96-m68k -0x8p-152L : -0x8p-152L : inexact-ok
+= expm1 tonearest ldbl-96-m68k -0x8p-152L : -0x8p-152L : inexact-ok
+= expm1 towardzero ldbl-96-m68k -0x8p-152L : -0x7.fffffffffffffff8p-152L : inexact-ok
+= expm1 upward ldbl-96-m68k -0x8p-152L : -0x7.fffffffffffffff8p-152L : inexact-ok
+= expm1 downward ldbl-128 -0x8p-152L : -0x8p-152L : inexact-ok
+= expm1 tonearest ldbl-128 -0x8p-152L : -0x8p-152L : inexact-ok
+= expm1 towardzero ldbl-128 -0x8p-152L : -0x7.fffffffffffffffffffffffffffcp-152L : inexact-ok
+= expm1 upward ldbl-128 -0x8p-152L : -0x7.fffffffffffffffffffffffffffcp-152L : inexact-ok
+= expm1 downward ldbl-128ibm -0x8p-152L : -0x8p-152L : inexact-ok
+= expm1 tonearest ldbl-128ibm -0x8p-152L : -0x8p-152L : inexact-ok
+= expm1 towardzero ldbl-128ibm -0x8p-152L : -0x7.fffffffffffffffffffffffffep-152L : inexact-ok
+= expm1 upward ldbl-128ibm -0x8p-152L : -0x7.fffffffffffffffffffffffffep-152L : inexact-ok
+= expm1 downward dbl-64 -0x4p-1076 : -0x4p-1076 : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest dbl-64 -0x4p-1076 : -0x4p-1076 : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero dbl-64 -0x4p-1076 : -0x0p+0 : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward dbl-64 -0x4p-1076 : -0x0p+0 : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 downward ldbl-96-intel -0x4p-1076L : -0x4p-1076L : inexact-ok
+= expm1 tonearest ldbl-96-intel -0x4p-1076L : -0x4p-1076L : inexact-ok
+= expm1 towardzero ldbl-96-intel -0x4p-1076L : -0x3.fffffffffffffffcp-1076L : inexact-ok
+= expm1 upward ldbl-96-intel -0x4p-1076L : -0x3.fffffffffffffffcp-1076L : inexact-ok
+= expm1 downward ldbl-96-m68k -0x4p-1076L : -0x4p-1076L : inexact-ok
+= expm1 tonearest ldbl-96-m68k -0x4p-1076L : -0x4p-1076L : inexact-ok
+= expm1 towardzero ldbl-96-m68k -0x4p-1076L : -0x3.fffffffffffffffcp-1076L : inexact-ok
+= expm1 upward ldbl-96-m68k -0x4p-1076L : -0x3.fffffffffffffffcp-1076L : inexact-ok
+= expm1 downward ldbl-128 -0x4p-1076L : -0x4p-1076L : inexact-ok
+= expm1 tonearest ldbl-128 -0x4p-1076L : -0x4p-1076L : inexact-ok
+= expm1 towardzero ldbl-128 -0x4p-1076L : -0x3.fffffffffffffffffffffffffffep-1076L : inexact-ok
+= expm1 upward ldbl-128 -0x4p-1076L : -0x3.fffffffffffffffffffffffffffep-1076L : inexact-ok
+= expm1 downward ldbl-128ibm -0x4p-1076L : -0x4p-1076L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-128ibm -0x4p-1076L : -0x4p-1076L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-128ibm -0x4p-1076L : -0x0p+0L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward ldbl-128ibm -0x4p-1076L : -0x0p+0L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 downward ldbl-96-intel -0x8p-16448L : -0x8p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-96-intel -0x8p-16448L : -0x8p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-96-intel -0x8p-16448L : -0x0p+0L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward ldbl-96-intel -0x8p-16448L : -0x0p+0L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 downward ldbl-96-m68k -0x8p-16448L : -0x8p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-96-m68k -0x8p-16448L : -0x8p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-96-m68k -0x8p-16448L : -0x4p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward ldbl-96-m68k -0x8p-16448L : -0x4p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 downward ldbl-128 -0x8p-16448L : -0x8p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-128 -0x8p-16448L : -0x8p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-128 -0x8p-16448L : -0x7.fffffffffffcp-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward ldbl-128 -0x8p-16448L : -0x7.fffffffffffcp-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 downward ldbl-96-m68k -0x4p-16448L : -0x4p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-96-m68k -0x4p-16448L : -0x4p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-96-m68k -0x4p-16448L : -0x0p+0L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward ldbl-96-m68k -0x4p-16448L : -0x0p+0L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 downward ldbl-128 -0x4p-16448L : -0x4p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-128 -0x4p-16448L : -0x4p-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-128 -0x4p-16448L : -0x3.fffffffffffcp-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward ldbl-128 -0x4p-16448L : -0x3.fffffffffffcp-16448L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 downward ldbl-128 -0x4p-16496L : -0x4p-16496L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 tonearest ldbl-128 -0x4p-16496L : -0x4p-16496L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 towardzero ldbl-128 -0x4p-16496L : -0x0p+0L : inexact-ok underflow underflow-ok errno-erange-ok
+= expm1 upward ldbl-128 -0x4p-16496L : -0x0p+0L : inexact-ok underflow underflow-ok errno-erange-ok
 fma 1.0 2.0 3.0
 = fma downward flt-32 0x1p+0f 0x2p+0f 0x3p+0f : 0x5p+0f :
 = fma tonearest flt-32 0x1p+0f 0x2p+0f 0x3p+0f : 0x5p+0f :
diff --git a/sysdeps/i386/fpu/e_expl.S b/sysdeps/i386/fpu/e_expl.S
index 74968bbc2b..711c86a6e8 100644
--- a/sysdeps/i386/fpu/e_expl.S
+++ b/sysdeps/i386/fpu/e_expl.S
@@ -122,6 +122,12 @@ ENTRY(IEEE754_EXPL)
 	   normal.  */
 	cmpl	$0x0001, %eax
 	jge	2f
+	/* Force underflow and return the argument, to avoid wrong signs
+	   of zero results from the code below in some rounding modes.  */
+	fld	%st
+	fmul	%st
+	fstp	%st
+	jmp	2f
 #else
 	movzwl	4+8(%esp), %eax
 	andl	$0x7fff, %eax
diff --git a/sysdeps/x86_64/fpu/e_expl.S b/sysdeps/x86_64/fpu/e_expl.S
index 866bad2c6e..14dd29dcad 100644
--- a/sysdeps/x86_64/fpu/e_expl.S
+++ b/sysdeps/x86_64/fpu/e_expl.S
@@ -119,6 +119,12 @@ ENTRY(IEEE754_EXPL)
 	   normal.  */
 	cmpl	$0x0001, %eax
 	jge	2f
+	/* Force underflow and return the argument, to avoid wrong signs
+	   of zero results from the code below in some rounding modes.  */
+	fld	%st
+	fmul	%st
+	fstp	%st
+	jmp	2f
 #else
 	movzwl	8+8(%rsp), %eax
 	andl	$0x7fff, %eax