about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2013-12-19 13:36:10 +0000
committerJoseph Myers <joseph@codesourcery.com>2013-12-19 13:36:10 +0000
commitf88acd39da2a509081e541b84ecbf204ef20f9e8 (patch)
tree383c0bcce4b3e74c9150d01550e7c412e47981bd
parentc688b4196014e0162a1ff11120f6c9516be0c6cb (diff)
downloadglibc-f88acd39da2a509081e541b84ecbf204ef20f9e8.tar.gz
glibc-f88acd39da2a509081e541b84ecbf204ef20f9e8.tar.xz
glibc-f88acd39da2a509081e541b84ecbf204ef20f9e8.zip
Fix x86/x86_64 expm1 inaccuracy near 0 in directed rounding modes (bug 16293).
Bug 16293 is inaccuracy of x86/x86_64 versions of expm1, near 0 in
directed rounding modes, that arises from frndint rounding the
exponent to 1 or -1 instead of 0, resulting in large cancellation
error.  This inaccuracy in turn affects other functions such as sinh
that use expm1.  This patch fixes the problem by setting
round-to-nearest mode temporarily around the affected calls to
frndint.  I don't think this is needed for other uses of frndint, such
as in exp itself, as only for expm1 is the cancellation error
significant.

Tested x86_64 and x86 and ulps updated accordingly.

	* sysdeps/i386/fpu/e_expl.S (IEEE754_EXPL) [USE_AS_EXPM1L]: Set
	round-to-nearest mode when using frndint.
	* sysdeps/i386/fpu/s_expm1.S (__expm1): Likewise.
	* sysdeps/i386/fpu/s_expm1f.S (__expm1f): Likewise.
	* sysdeps/x86_64/fpu/e_expl.S (IEEE754_EXPL) [USE_AS_EXPM1L]:
	Likewise.
	* math/auto-libm-test-in: Add more tests of expm1.  Do not expect
	sinh test to fail.
	* math/auto-libm-test-out: Regenerated.
	* math/libm-test.inc (TEST_COND_x86_64): Remove macro.
	(TEST_COND_x86): Likewise.
	(expm1_tonearest_test_data): New array.
	(expm1_test_tonearest): New function.
	(expm1_towardzero_test_data): New array.
	(expm1_test_towardzero): New function.
	(expm1_downward_test_data): New array.
	(expm1_test_downward): New function.
	(expm1_upward_test_data): New array.
	(expm1_test_upward): New function.
	(main): Run the new test functions.
	* sysdeps/i386/fpu/libm-test-ulps: Update.
	* sysdeps/x86_64/fpu/libm-test-ulps: Likewise.
-rw-r--r--ChangeLog24
-rw-r--r--NEWS2
-rw-r--r--math/auto-libm-test-in19
-rw-r--r--math/auto-libm-test-out450
-rw-r--r--math/libm-test.inc72
-rw-r--r--sysdeps/i386/fpu/e_expl.S15
-rw-r--r--sysdeps/i386/fpu/libm-test-ulps375
-rw-r--r--sysdeps/i386/fpu/s_expm1.S11
-rw-r--r--sysdeps/i386/fpu/s_expm1f.S11
-rw-r--r--sysdeps/x86_64/fpu/e_expl.S11
-rw-r--r--sysdeps/x86_64/fpu/libm-test-ulps319
11 files changed, 1269 insertions, 40 deletions
diff --git a/ChangeLog b/ChangeLog
index 727688e124..e8b90876d6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,29 @@
 2013-12-19  Joseph Myers  <joseph@codesourcery.com>
 
+	[BZ #16293]
+	* sysdeps/i386/fpu/e_expl.S (IEEE754_EXPL) [USE_AS_EXPM1L]: Set
+	round-to-nearest mode when using frndint.
+	* sysdeps/i386/fpu/s_expm1.S (__expm1): Likewise.
+	* sysdeps/i386/fpu/s_expm1f.S (__expm1f): Likewise.
+	* sysdeps/x86_64/fpu/e_expl.S (IEEE754_EXPL) [USE_AS_EXPM1L]:
+	Likewise.
+	* math/auto-libm-test-in: Add more tests of expm1.  Do not expect
+	sinh test to fail.
+	* math/auto-libm-test-out: Regenerated.
+	* math/libm-test.inc (TEST_COND_x86_64): Remove macro.
+	(TEST_COND_x86): Likewise.
+	(expm1_tonearest_test_data): New array.
+	(expm1_test_tonearest): New function.
+	(expm1_towardzero_test_data): New array.
+	(expm1_test_towardzero): New function.
+	(expm1_downward_test_data): New array.
+	(expm1_test_downward): New function.
+	(expm1_upward_test_data): New array.
+	(expm1_test_upward): New function.
+	(main): Run the new test functions.
+	* sysdeps/i386/fpu/libm-test-ulps: Update.
+	* sysdeps/x86_64/fpu/libm-test-ulps: Likewise.
+
 	* include/features.h: Update comment documenting feature test
 	macros.  Mention _DEFAULT_SOURCE in comment.
 	[_GNU_SOURCE] (_DEFAULT_SOURCE): Undefine and redefine.
diff --git a/NEWS b/NEWS
index d82cf9592b..b8ff649e2c 100644
--- a/NEWS
+++ b/NEWS
@@ -22,7 +22,7 @@ Version 2.19
   15966, 15985, 15988, 15997, 16032, 16034, 16036, 16037, 16038, 16041,
   16055, 16071, 16072, 16074, 16077, 16078, 16103, 16112, 16143, 16144,
   16146, 16150, 16151, 16153, 16167, 16172, 16195, 16214, 16245, 16271,
-  16274, 16283, 16289, 16314, 16316, 16330, 16338.
+  16274, 16283, 16289, 16293, 16314, 16316, 16330, 16338.
 
 * The public headers no longer use __unused nor __block.  This change is to
   support compiling programs that are derived from BSD sources and use
diff --git a/math/auto-libm-test-in b/math/auto-libm-test-in
index 50e0e6b628..28e9d455b6 100644
--- a/math/auto-libm-test-in
+++ b/math/auto-libm-test-in
@@ -281,6 +281,22 @@ expm1 -100000.0
 expm1 100000.0
 expm1 max
 expm1 -max
+expm1 0x1p-2
+expm1 -0x1p-2
+expm1 0x1p-10
+expm1 -0x1p-10
+expm1 0x1p-20
+expm1 -0x1p-20
+expm1 0x1p-29
+expm1 -0x1p-29
+expm1 0x1p-32
+expm1 -0x1p-32
+expm1 0x1p-50
+expm1 -0x1p-50
+expm1 0x1p-64
+expm1 -0x1p-64
+expm1 0x1p-100
+expm1 -0x1p-100
 
 hypot 0 0
 hypot 0 -0
@@ -835,8 +851,7 @@ sin 10
 sinh 0
 sinh -0
 sinh 0.75
-# Bug 16293: expm1 inaccurate in directed rounding modes.
-sinh 0x8p-32 xfail:x86_64:ldbl-96-intel xfail:x86
+sinh 0x8p-32
 sinh 22
 sinh 23
 sinh 24
diff --git a/math/auto-libm-test-out b/math/auto-libm-test-out
index e80e363380..06a7591b90 100644
--- a/math/auto-libm-test-out
+++ b/math/auto-libm-test-out
@@ -10893,6 +10893,406 @@ expm1 -max
 = expm1 tonearest ldbl-128ibm -0xf.ffffffffffffbffffffffffffcp+1020L : -0x1p+0L : inexact-ok
 = expm1 towardzero ldbl-128ibm -0xf.ffffffffffffbffffffffffffcp+1020L : -0xf.fffffffffffffffffffffffffcp-4L : inexact-ok
 = expm1 upward ldbl-128ibm -0xf.ffffffffffffbffffffffffffcp+1020L : -0xf.fffffffffffffffffffffffffcp-4L : inexact-ok
+expm1 0x1p-2
+= expm1 downward flt-32 0x4p-4f : 0x4.8b5e38p-4f : inexact-ok
+= expm1 tonearest flt-32 0x4p-4f : 0x4.8b5e4p-4f : inexact-ok
+= expm1 towardzero flt-32 0x4p-4f : 0x4.8b5e38p-4f : inexact-ok
+= expm1 upward flt-32 0x4p-4f : 0x4.8b5e4p-4f : inexact-ok
+= expm1 downward dbl-64 0x4p-4 : 0x4.8b5e3c3e81864p-4 : inexact-ok
+= expm1 tonearest dbl-64 0x4p-4 : 0x4.8b5e3c3e81868p-4 : inexact-ok
+= expm1 towardzero dbl-64 0x4p-4 : 0x4.8b5e3c3e81864p-4 : inexact-ok
+= expm1 upward dbl-64 0x4p-4 : 0x4.8b5e3c3e81868p-4 : inexact-ok
+= expm1 downward ldbl-96-intel 0x4p-4L : 0x4.8b5e3c3e8186676p-4L : inexact-ok
+= expm1 tonearest ldbl-96-intel 0x4p-4L : 0x4.8b5e3c3e81866768p-4L : inexact-ok
+= expm1 towardzero ldbl-96-intel 0x4p-4L : 0x4.8b5e3c3e8186676p-4L : inexact-ok
+= expm1 upward ldbl-96-intel 0x4p-4L : 0x4.8b5e3c3e81866768p-4L : inexact-ok
+= expm1 downward ldbl-96-m68k 0x4p-4L : 0x4.8b5e3c3e8186676p-4L : inexact-ok
+= expm1 tonearest ldbl-96-m68k 0x4p-4L : 0x4.8b5e3c3e81866768p-4L : inexact-ok
+= expm1 towardzero ldbl-96-m68k 0x4p-4L : 0x4.8b5e3c3e8186676p-4L : inexact-ok
+= expm1 upward ldbl-96-m68k 0x4p-4L : 0x4.8b5e3c3e81866768p-4L : inexact-ok
+= expm1 downward ldbl-128 0x4p-4L : 0x4.8b5e3c3e81866767bc3b69baabe4p-4L : inexact-ok
+= expm1 tonearest ldbl-128 0x4p-4L : 0x4.8b5e3c3e81866767bc3b69baabe4p-4L : inexact-ok
+= expm1 towardzero ldbl-128 0x4p-4L : 0x4.8b5e3c3e81866767bc3b69baabe4p-4L : inexact-ok
+= expm1 upward ldbl-128 0x4p-4L : 0x4.8b5e3c3e81866767bc3b69baabe8p-4L : inexact-ok
+= expm1 downward ldbl-128ibm 0x4p-4L : 0x4.8b5e3c3e81866767bc3b69baaap-4L : inexact-ok
+= expm1 tonearest ldbl-128ibm 0x4p-4L : 0x4.8b5e3c3e81866767bc3b69baacp-4L : inexact-ok
+= expm1 towardzero ldbl-128ibm 0x4p-4L : 0x4.8b5e3c3e81866767bc3b69baaap-4L : inexact-ok
+= expm1 upward ldbl-128ibm 0x4p-4L : 0x4.8b5e3c3e81866767bc3b69baacp-4L : inexact-ok
+expm1 -0x1p-2
+= expm1 downward flt-32 -0x4p-4f : -0x3.8a0834p-4f : inexact-ok
+= expm1 tonearest flt-32 -0x4p-4f : -0x3.8a083p-4f : inexact-ok
+= expm1 towardzero flt-32 -0x4p-4f : -0x3.8a083p-4f : inexact-ok
+= expm1 upward flt-32 -0x4p-4f : -0x3.8a083p-4f : inexact-ok
+= expm1 downward dbl-64 -0x4p-4 : -0x3.8a0830a9befaap-4 : inexact-ok
+= expm1 tonearest dbl-64 -0x4p-4 : -0x3.8a0830a9befa8p-4 : inexact-ok
+= expm1 towardzero dbl-64 -0x4p-4 : -0x3.8a0830a9befa8p-4 : inexact-ok
+= expm1 upward dbl-64 -0x4p-4 : -0x3.8a0830a9befa8p-4 : inexact-ok
+= expm1 downward ldbl-96-intel -0x4p-4L : -0x3.8a0830a9befa8bccp-4L : inexact-ok
+= expm1 tonearest ldbl-96-intel -0x4p-4L : -0x3.8a0830a9befa8bccp-4L : inexact-ok
+= expm1 towardzero ldbl-96-intel -0x4p-4L : -0x3.8a0830a9befa8bc8p-4L : inexact-ok
+= expm1 upward ldbl-96-intel -0x4p-4L : -0x3.8a0830a9befa8bc8p-4L : inexact-ok
+= expm1 downward ldbl-96-m68k -0x4p-4L : -0x3.8a0830a9befa8bccp-4L : inexact-ok
+= expm1 tonearest ldbl-96-m68k -0x4p-4L : -0x3.8a0830a9befa8bccp-4L : inexact-ok
+= expm1 towardzero ldbl-96-m68k -0x4p-4L : -0x3.8a0830a9befa8bc8p-4L : inexact-ok
+= expm1 upward ldbl-96-m68k -0x4p-4L : -0x3.8a0830a9befa8bc8p-4L : inexact-ok
+= expm1 downward ldbl-128 -0x4p-4L : -0x3.8a0830a9befa8bcbea343629c972p-4L : inexact-ok
+= expm1 tonearest ldbl-128 -0x4p-4L : -0x3.8a0830a9befa8bcbea343629c97p-4L : inexact-ok
+= expm1 towardzero ldbl-128 -0x4p-4L : -0x3.8a0830a9befa8bcbea343629c97p-4L : inexact-ok
+= expm1 upward ldbl-128 -0x4p-4L : -0x3.8a0830a9befa8bcbea343629c97p-4L : inexact-ok
+= expm1 downward ldbl-128ibm -0x4p-4L : -0x3.8a0830a9befa8bcbea343629cap-4L : inexact-ok
+= expm1 tonearest ldbl-128ibm -0x4p-4L : -0x3.8a0830a9befa8bcbea343629c9p-4L : inexact-ok
+= expm1 towardzero ldbl-128ibm -0x4p-4L : -0x3.8a0830a9befa8bcbea343629c9p-4L : inexact-ok
+= expm1 upward ldbl-128ibm -0x4p-4L : -0x3.8a0830a9befa8bcbea343629c9p-4L : inexact-ok
+expm1 0x1p-10
+= expm1 downward flt-32 0x4p-12f : 0x4.008008p-12f : inexact-ok
+= expm1 tonearest flt-32 0x4p-12f : 0x4.008008p-12f : inexact-ok
+= expm1 towardzero flt-32 0x4p-12f : 0x4.008008p-12f : inexact-ok
+= expm1 upward flt-32 0x4p-12f : 0x4.00801p-12f : inexact-ok
+= expm1 downward dbl-64 0x4p-12 : 0x4.00800aab555dcp-12 : inexact-ok
+= expm1 tonearest dbl-64 0x4p-12 : 0x4.00800aab555dcp-12 : inexact-ok
+= expm1 towardzero dbl-64 0x4p-12 : 0x4.00800aab555dcp-12 : inexact-ok
+= expm1 upward dbl-64 0x4p-12 : 0x4.00800aab555ep-12 : inexact-ok
+= expm1 downward ldbl-96-intel 0x4p-12L : 0x4.00800aab555dde38p-12L : inexact-ok
+= expm1 tonearest ldbl-96-intel 0x4p-12L : 0x4.00800aab555dde38p-12L : inexact-ok
+= expm1 towardzero ldbl-96-intel 0x4p-12L : 0x4.00800aab555dde38p-12L : inexact-ok
+= expm1 upward ldbl-96-intel 0x4p-12L : 0x4.00800aab555dde4p-12L : inexact-ok
+= expm1 downward ldbl-96-m68k 0x4p-12L : 0x4.00800aab555dde38p-12L : inexact-ok
+= expm1 tonearest ldbl-96-m68k 0x4p-12L : 0x4.00800aab555dde38p-12L : inexact-ok
+= expm1 towardzero ldbl-96-m68k 0x4p-12L : 0x4.00800aab555dde38p-12L : inexact-ok
+= expm1 upward ldbl-96-m68k 0x4p-12L : 0x4.00800aab555dde4p-12L : inexact-ok
+= expm1 downward ldbl-128 0x4p-12L : 0x4.00800aab555dde38e6ce86e92778p-12L : inexact-ok
+= expm1 tonearest ldbl-128 0x4p-12L : 0x4.00800aab555dde38e6ce86e9277cp-12L : inexact-ok
+= expm1 towardzero ldbl-128 0x4p-12L : 0x4.00800aab555dde38e6ce86e92778p-12L : inexact-ok
+= expm1 upward ldbl-128 0x4p-12L : 0x4.00800aab555dde38e6ce86e9277cp-12L : inexact-ok
+= expm1 downward ldbl-128ibm 0x4p-12L : 0x4.00800aab555dde38e6ce86e926p-12L : inexact-ok
+= expm1 tonearest ldbl-128ibm 0x4p-12L : 0x4.00800aab555dde38e6ce86e928p-12L : inexact-ok
+= expm1 towardzero ldbl-128ibm 0x4p-12L : 0x4.00800aab555dde38e6ce86e926p-12L : inexact-ok
+= expm1 upward ldbl-128ibm 0x4p-12L : 0x4.00800aab555dde38e6ce86e928p-12L : inexact-ok
+expm1 -0x1p-10
+= expm1 downward flt-32 -0x4p-12f : -0x3.ff800cp-12f : inexact-ok
+= expm1 tonearest flt-32 -0x4p-12f : -0x3.ff800cp-12f : inexact-ok
+= expm1 towardzero flt-32 -0x4p-12f : -0x3.ff8008p-12f : inexact-ok
+= expm1 upward flt-32 -0x4p-12f : -0x3.ff8008p-12f : inexact-ok
+= expm1 downward dbl-64 -0x4p-12 : -0x3.ff800aaa0008ap-12 : inexact-ok
+= expm1 tonearest dbl-64 -0x4p-12 : -0x3.ff800aaa00088p-12 : inexact-ok
+= expm1 towardzero dbl-64 -0x4p-12 : -0x3.ff800aaa00088p-12 : inexact-ok
+= expm1 upward dbl-64 -0x4p-12 : -0x3.ff800aaa00088p-12 : inexact-ok
+= expm1 downward ldbl-96-intel -0x4p-12L : -0x3.ff800aaa0008883p-12L : inexact-ok
+= expm1 tonearest ldbl-96-intel -0x4p-12L : -0x3.ff800aaa0008882cp-12L : inexact-ok
+= expm1 towardzero ldbl-96-intel -0x4p-12L : -0x3.ff800aaa0008882cp-12L : inexact-ok
+= expm1 upward ldbl-96-intel -0x4p-12L : -0x3.ff800aaa0008882cp-12L : inexact-ok
+= expm1 downward ldbl-96-m68k -0x4p-12L : -0x3.ff800aaa0008883p-12L : inexact-ok
+= expm1 tonearest ldbl-96-m68k -0x4p-12L : -0x3.ff800aaa0008882cp-12L : inexact-ok
+= expm1 towardzero ldbl-96-m68k -0x4p-12L : -0x3.ff800aaa0008882cp-12L : inexact-ok
+= expm1 upward ldbl-96-m68k -0x4p-12L : -0x3.ff800aaa0008882cp-12L : inexact-ok
+= expm1 downward ldbl-128 -0x4p-12L : -0x3.ff800aaa0008882d861847853132p-12L : inexact-ok
+= expm1 tonearest ldbl-128 -0x4p-12L : -0x3.ff800aaa0008882d861847853132p-12L : inexact-ok
+= expm1 towardzero ldbl-128 -0x4p-12L : -0x3.ff800aaa0008882d86184785313p-12L : inexact-ok
+= expm1 upward ldbl-128 -0x4p-12L : -0x3.ff800aaa0008882d86184785313p-12L : inexact-ok
+= expm1 downward ldbl-128ibm -0x4p-12L : -0x3.ff800aaa0008882d8618478532p-12L : inexact-ok
+= expm1 tonearest ldbl-128ibm -0x4p-12L : -0x3.ff800aaa0008882d8618478531p-12L : inexact-ok
+= expm1 towardzero ldbl-128ibm -0x4p-12L : -0x3.ff800aaa0008882d8618478531p-12L : inexact-ok
+= expm1 upward ldbl-128ibm -0x4p-12L : -0x3.ff800aaa0008882d8618478531p-12L : inexact-ok
+expm1 0x1p-20
+= expm1 downward flt-32 0x1p-20f : 0x1.000008p-20f : inexact-ok
+= expm1 tonearest flt-32 0x1p-20f : 0x1.000008p-20f : inexact-ok
+= expm1 towardzero flt-32 0x1p-20f : 0x1.000008p-20f : inexact-ok
+= expm1 upward flt-32 0x1p-20f : 0x1.00000ap-20f : inexact-ok
+= expm1 downward dbl-64 0x1p-20 : 0x1.00000800002aap-20 : inexact-ok
+= expm1 tonearest dbl-64 0x1p-20 : 0x1.00000800002abp-20 : inexact-ok
+= expm1 towardzero dbl-64 0x1p-20 : 0x1.00000800002aap-20 : inexact-ok
+= expm1 upward dbl-64 0x1p-20 : 0x1.00000800002abp-20 : inexact-ok
+= expm1 downward ldbl-96-intel 0x1p-20L : 0x1.00000800002aaaaap-20L : inexact-ok
+= expm1 tonearest ldbl-96-intel 0x1p-20L : 0x1.00000800002aaaacp-20L : inexact-ok
+= expm1 towardzero ldbl-96-intel 0x1p-20L : 0x1.00000800002aaaaap-20L : inexact-ok
+= expm1 upward ldbl-96-intel 0x1p-20L : 0x1.00000800002aaaacp-20L : inexact-ok
+= expm1 downward ldbl-96-m68k 0x1p-20L : 0x1.00000800002aaaaap-20L : inexact-ok
+= expm1 tonearest ldbl-96-m68k 0x1p-20L : 0x1.00000800002aaaacp-20L : inexact-ok
+= expm1 towardzero ldbl-96-m68k 0x1p-20L : 0x1.00000800002aaaaap-20L : inexact-ok
+= expm1 upward ldbl-96-m68k 0x1p-20L : 0x1.00000800002aaaacp-20L : inexact-ok
+= expm1 downward ldbl-128 0x1p-20L : 0x1.00000800002aaaab55555777777dp-20L : inexact-ok
+= expm1 tonearest ldbl-128 0x1p-20L : 0x1.00000800002aaaab55555777777dp-20L : inexact-ok
+= expm1 towardzero ldbl-128 0x1p-20L : 0x1.00000800002aaaab55555777777dp-20L : inexact-ok
+= expm1 upward ldbl-128 0x1p-20L : 0x1.00000800002aaaab55555777777ep-20L : inexact-ok
+= expm1 downward ldbl-128ibm 0x1p-20L : 0x1.00000800002aaaab5555577777p-20L : inexact-ok
+= expm1 tonearest ldbl-128ibm 0x1p-20L : 0x1.00000800002aaaab55555777778p-20L : inexact-ok
+= expm1 towardzero ldbl-128ibm 0x1p-20L : 0x1.00000800002aaaab5555577777p-20L : inexact-ok
+= expm1 upward ldbl-128ibm 0x1p-20L : 0x1.00000800002aaaab55555777778p-20L : inexact-ok
+expm1 -0x1p-20
+= expm1 downward flt-32 -0x1p-20f : -0xf.ffff9p-24f : inexact-ok
+= expm1 tonearest flt-32 -0x1p-20f : -0xf.ffff8p-24f : inexact-ok
+= expm1 towardzero flt-32 -0x1p-20f : -0xf.ffff8p-24f : inexact-ok
+= expm1 upward flt-32 -0x1p-20f : -0xf.ffff8p-24f : inexact-ok
+= expm1 downward dbl-64 -0x1p-20 : -0xf.ffff800002abp-24 : inexact-ok
+= expm1 tonearest dbl-64 -0x1p-20 : -0xf.ffff800002aa8p-24 : inexact-ok
+= expm1 towardzero dbl-64 -0x1p-20 : -0xf.ffff800002aa8p-24 : inexact-ok
+= expm1 upward dbl-64 -0x1p-20 : -0xf.ffff800002aa8p-24 : inexact-ok
+= expm1 downward ldbl-96-intel -0x1p-20L : -0xf.ffff800002aaaabp-24L : inexact-ok
+= expm1 tonearest ldbl-96-intel -0x1p-20L : -0xf.ffff800002aaaaap-24L : inexact-ok
+= expm1 towardzero ldbl-96-intel -0x1p-20L : -0xf.ffff800002aaaaap-24L : inexact-ok
+= expm1 upward ldbl-96-intel -0x1p-20L : -0xf.ffff800002aaaaap-24L : inexact-ok
+= expm1 downward ldbl-96-m68k -0x1p-20L : -0xf.ffff800002aaaabp-24L : inexact-ok
+= expm1 tonearest ldbl-96-m68k -0x1p-20L : -0xf.ffff800002aaaaap-24L : inexact-ok
+= expm1 towardzero ldbl-96-m68k -0x1p-20L : -0xf.ffff800002aaaaap-24L : inexact-ok
+= expm1 upward ldbl-96-m68k -0x1p-20L : -0xf.ffff800002aaaaap-24L : inexact-ok
+= expm1 downward ldbl-128 -0x1p-20L : -0xf.ffff800002aaaaa00000222221c8p-24L : inexact-ok
+= expm1 tonearest ldbl-128 -0x1p-20L : -0xf.ffff800002aaaaa00000222221c8p-24L : inexact-ok
+= expm1 towardzero ldbl-128 -0x1p-20L : -0xf.ffff800002aaaaa00000222221cp-24L : inexact-ok
+= expm1 upward ldbl-128 -0x1p-20L : -0xf.ffff800002aaaaa00000222221cp-24L : inexact-ok
+= expm1 downward ldbl-128ibm -0x1p-20L : -0xf.ffff800002aaaaa00000222224p-24L : inexact-ok
+= expm1 tonearest ldbl-128ibm -0x1p-20L : -0xf.ffff800002aaaaa0000022222p-24L : inexact-ok
+= expm1 towardzero ldbl-128ibm -0x1p-20L : -0xf.ffff800002aaaaa0000022222p-24L : inexact-ok
+= expm1 upward ldbl-128ibm -0x1p-20L : -0xf.ffff800002aaaaa0000022222p-24L : inexact-ok
+expm1 0x1p-29
+= expm1 downward flt-32 0x8p-32f : 0x8p-32f : inexact-ok
+= expm1 tonearest flt-32 0x8p-32f : 0x8p-32f : inexact-ok
+= expm1 towardzero flt-32 0x8p-32f : 0x8p-32f : inexact-ok
+= expm1 upward flt-32 0x8p-32f : 0x8.00001p-32f : inexact-ok
+= expm1 downward dbl-64 0x8p-32 : 0x8.0000002p-32 : inexact-ok
+= expm1 tonearest dbl-64 0x8p-32 : 0x8.0000002p-32 : inexact-ok
+= expm1 towardzero dbl-64 0x8p-32 : 0x8.0000002p-32 : inexact-ok
+= expm1 upward dbl-64 0x8p-32 : 0x8.0000002000008p-32 : inexact-ok
+= expm1 downward ldbl-96-intel 0x8p-32L : 0x8.000000200000005p-32L : inexact-ok
+= expm1 tonearest ldbl-96-intel 0x8p-32L : 0x8.000000200000005p-32L : inexact-ok
+= expm1 towardzero ldbl-96-intel 0x8p-32L : 0x8.000000200000005p-32L : inexact-ok
+= expm1 upward ldbl-96-intel 0x8p-32L : 0x8.000000200000006p-32L : inexact-ok
+= expm1 downward ldbl-96-m68k 0x8p-32L : 0x8.000000200000005p-32L : inexact-ok
+= expm1 tonearest ldbl-96-m68k 0x8p-32L : 0x8.000000200000005p-32L : inexact-ok
+= expm1 towardzero ldbl-96-m68k 0x8p-32L : 0x8.000000200000005p-32L : inexact-ok
+= expm1 upward ldbl-96-m68k 0x8p-32L : 0x8.000000200000006p-32L : inexact-ok
+= expm1 downward ldbl-128 0x8p-32L : 0x8.0000002000000055555556p-32L : inexact-ok
+= expm1 tonearest ldbl-128 0x8p-32L : 0x8.0000002000000055555556p-32L : inexact-ok
+= expm1 towardzero ldbl-128 0x8p-32L : 0x8.0000002000000055555556p-32L : inexact-ok
+= expm1 upward ldbl-128 0x8p-32L : 0x8.0000002000000055555556000008p-32L : inexact-ok
+= expm1 downward ldbl-128ibm 0x8p-32L : 0x8.0000002000000055555556p-32L : inexact-ok
+= expm1 tonearest ldbl-128ibm 0x8p-32L : 0x8.0000002000000055555556p-32L : inexact-ok
+= expm1 towardzero ldbl-128ibm 0x8p-32L : 0x8.0000002000000055555556p-32L : inexact-ok
+= expm1 upward ldbl-128ibm 0x8p-32L : 0x8.00000020000000555555560004p-32L : inexact-ok
+expm1 -0x1p-29
+= expm1 downward flt-32 -0x8p-32f : -0x8p-32f : inexact-ok
+= expm1 tonearest flt-32 -0x8p-32f : -0x8p-32f : inexact-ok
+= expm1 towardzero flt-32 -0x8p-32f : -0x7.fffff8p-32f : inexact-ok
+= expm1 upward flt-32 -0x8p-32f : -0x7.fffff8p-32f : inexact-ok
+= expm1 downward dbl-64 -0x8p-32 : -0x7.ffffffe000004p-32 : inexact-ok
+= expm1 tonearest dbl-64 -0x8p-32 : -0x7.ffffffep-32 : inexact-ok
+= expm1 towardzero dbl-64 -0x8p-32 : -0x7.ffffffep-32 : inexact-ok
+= expm1 upward dbl-64 -0x8p-32 : -0x7.ffffffep-32 : inexact-ok
+= expm1 downward ldbl-96-intel -0x8p-32L : -0x7.ffffffe000000058p-32L : inexact-ok
+= expm1 tonearest ldbl-96-intel -0x8p-32L : -0x7.ffffffe000000058p-32L : inexact-ok
+= expm1 towardzero ldbl-96-intel -0x8p-32L : -0x7.ffffffe00000005p-32L : inexact-ok
+= expm1 upward ldbl-96-intel -0x8p-32L : -0x7.ffffffe00000005p-32L : inexact-ok
+= expm1 downward ldbl-96-m68k -0x8p-32L : -0x7.ffffffe000000058p-32L : inexact-ok
+= expm1 tonearest ldbl-96-m68k -0x8p-32L : -0x7.ffffffe000000058p-32L : inexact-ok
+= expm1 towardzero ldbl-96-m68k -0x8p-32L : -0x7.ffffffe00000005p-32L : inexact-ok
+= expm1 upward ldbl-96-m68k -0x8p-32L : -0x7.ffffffe00000005p-32L : inexact-ok
+= expm1 downward ldbl-128 -0x8p-32L : -0x7.ffffffe000000055555554aaaaacp-32L : inexact-ok
+= expm1 tonearest ldbl-128 -0x8p-32L : -0x7.ffffffe000000055555554aaaaa8p-32L : inexact-ok
+= expm1 towardzero ldbl-128 -0x8p-32L : -0x7.ffffffe000000055555554aaaaa8p-32L : inexact-ok
+= expm1 upward ldbl-128 -0x8p-32L : -0x7.ffffffe000000055555554aaaaa8p-32L : inexact-ok
+= expm1 downward ldbl-128ibm -0x8p-32L : -0x7.ffffffe000000055555554aaacp-32L : inexact-ok
+= expm1 tonearest ldbl-128ibm -0x8p-32L : -0x7.ffffffe000000055555554aaaap-32L : inexact-ok
+= expm1 towardzero ldbl-128ibm -0x8p-32L : -0x7.ffffffe000000055555554aaaap-32L : inexact-ok
+= expm1 upward ldbl-128ibm -0x8p-32L : -0x7.ffffffe000000055555554aaaap-32L : inexact-ok
+expm1 0x1p-32
+= expm1 downward flt-32 0x1p-32f : 0x1p-32f : inexact-ok
+= expm1 tonearest flt-32 0x1p-32f : 0x1p-32f : inexact-ok
+= expm1 towardzero flt-32 0x1p-32f : 0x1p-32f : inexact-ok
+= expm1 upward flt-32 0x1p-32f : 0x1.000002p-32f : inexact-ok
+= expm1 downward dbl-64 0x1p-32 : 0x1.000000008p-32 : inexact-ok
+= expm1 tonearest dbl-64 0x1p-32 : 0x1.000000008p-32 : inexact-ok
+= expm1 towardzero dbl-64 0x1p-32 : 0x1.000000008p-32 : inexact-ok
+= expm1 upward dbl-64 0x1p-32 : 0x1.0000000080001p-32 : inexact-ok
+= expm1 downward ldbl-96-intel 0x1p-32L : 0x1.000000008p-32L : inexact-ok
+= expm1 tonearest ldbl-96-intel 0x1p-32L : 0x1.000000008p-32L : inexact-ok
+= expm1 towardzero ldbl-96-intel 0x1p-32L : 0x1.000000008p-32L : inexact-ok
+= expm1 upward ldbl-96-intel 0x1p-32L : 0x1.0000000080000002p-32L : inexact-ok
+= expm1 downward ldbl-96-m68k 0x1p-32L : 0x1.000000008p-32L : inexact-ok
+= expm1 tonearest ldbl-96-m68k 0x1p-32L : 0x1.000000008p-32L : inexact-ok
+= expm1 towardzero ldbl-96-m68k 0x1p-32L : 0x1.000000008p-32L : inexact-ok
+= expm1 upward ldbl-96-m68k 0x1p-32L : 0x1.0000000080000002p-32L : inexact-ok
+= expm1 downward ldbl-128 0x1p-32L : 0x1.00000000800000002aaaaaaab555p-32L : inexact-ok
+= expm1 tonearest ldbl-128 0x1p-32L : 0x1.00000000800000002aaaaaaab555p-32L : inexact-ok
+= expm1 towardzero ldbl-128 0x1p-32L : 0x1.00000000800000002aaaaaaab555p-32L : inexact-ok
+= expm1 upward ldbl-128 0x1p-32L : 0x1.00000000800000002aaaaaaab556p-32L : inexact-ok
+= expm1 downward ldbl-128ibm 0x1p-32L : 0x1.00000000800000002aaaaaaab5p-32L : inexact-ok
+= expm1 tonearest ldbl-128ibm 0x1p-32L : 0x1.00000000800000002aaaaaaab58p-32L : inexact-ok
+= expm1 towardzero ldbl-128ibm 0x1p-32L : 0x1.00000000800000002aaaaaaab5p-32L : inexact-ok
+= expm1 upward ldbl-128ibm 0x1p-32L : 0x1.00000000800000002aaaaaaab58p-32L : inexact-ok
+expm1 -0x1p-32
+= expm1 downward flt-32 -0x1p-32f : -0x1p-32f : inexact-ok
+= expm1 tonearest flt-32 -0x1p-32f : -0x1p-32f : inexact-ok
+= expm1 towardzero flt-32 -0x1p-32f : -0xf.fffffp-36f : inexact-ok
+= expm1 upward flt-32 -0x1p-32f : -0xf.fffffp-36f : inexact-ok
+= expm1 downward dbl-64 -0x1p-32 : -0xf.fffffff800008p-36 : inexact-ok
+= expm1 tonearest dbl-64 -0x1p-32 : -0xf.fffffff8p-36 : inexact-ok
+= expm1 towardzero dbl-64 -0x1p-32 : -0xf.fffffff8p-36 : inexact-ok
+= expm1 upward dbl-64 -0x1p-32 : -0xf.fffffff8p-36 : inexact-ok
+= expm1 downward ldbl-96-intel -0x1p-32L : -0xf.fffffff80000001p-36L : inexact-ok
+= expm1 tonearest ldbl-96-intel -0x1p-32L : -0xf.fffffff8p-36L : inexact-ok
+= expm1 towardzero ldbl-96-intel -0x1p-32L : -0xf.fffffff8p-36L : inexact-ok
+= expm1 upward ldbl-96-intel -0x1p-32L : -0xf.fffffff8p-36L : inexact-ok
+= expm1 downward ldbl-96-m68k -0x1p-32L : -0xf.fffffff80000001p-36L : inexact-ok
+= expm1 tonearest ldbl-96-m68k -0x1p-32L : -0xf.fffffff8p-36L : inexact-ok
+= expm1 towardzero ldbl-96-m68k -0x1p-32L : -0xf.fffffff8p-36L : inexact-ok
+= expm1 upward ldbl-96-m68k -0x1p-32L : -0xf.fffffff8p-36L : inexact-ok
+= expm1 downward ldbl-128 -0x1p-32L : -0xf.fffffff800000002aaaaaaaap-36L : inexact-ok
+= expm1 tonearest ldbl-128 -0x1p-32L : -0xf.fffffff800000002aaaaaaaap-36L : inexact-ok
+= expm1 towardzero ldbl-128 -0x1p-32L : -0xf.fffffff800000002aaaaaaa9fff8p-36L : inexact-ok
+= expm1 upward ldbl-128 -0x1p-32L : -0xf.fffffff800000002aaaaaaa9fff8p-36L : inexact-ok
+= expm1 downward ldbl-128ibm -0x1p-32L : -0xf.fffffff800000002aaaaaaaap-36L : inexact-ok
+= expm1 tonearest ldbl-128ibm -0x1p-32L : -0xf.fffffff800000002aaaaaaaap-36L : inexact-ok
+= expm1 towardzero ldbl-128ibm -0x1p-32L : -0xf.fffffff800000002aaaaaaa9fcp-36L : inexact-ok
+= expm1 upward ldbl-128ibm -0x1p-32L : -0xf.fffffff800000002aaaaaaa9fcp-36L : inexact-ok
+expm1 0x1p-50
+= expm1 downward flt-32 0x4p-52f : 0x4p-52f : inexact-ok
+= expm1 tonearest flt-32 0x4p-52f : 0x4p-52f : inexact-ok
+= expm1 towardzero flt-32 0x4p-52f : 0x4p-52f : inexact-ok
+= expm1 upward flt-32 0x4p-52f : 0x4.000008p-52f : inexact-ok
+= expm1 downward dbl-64 0x4p-52 : 0x4.0000000000008p-52 : inexact-ok
+= expm1 tonearest dbl-64 0x4p-52 : 0x4.0000000000008p-52 : inexact-ok
+= expm1 towardzero dbl-64 0x4p-52 : 0x4.0000000000008p-52 : inexact-ok
+= expm1 upward dbl-64 0x4p-52 : 0x4.000000000000cp-52 : inexact-ok
+= expm1 downward ldbl-96-intel 0x4p-52L : 0x4.0000000000008p-52L : inexact-ok
+= expm1 tonearest ldbl-96-intel 0x4p-52L : 0x4.0000000000008p-52L : inexact-ok
+= expm1 towardzero ldbl-96-intel 0x4p-52L : 0x4.0000000000008p-52L : inexact-ok
+= expm1 upward ldbl-96-intel 0x4p-52L : 0x4.0000000000008008p-52L : inexact-ok
+= expm1 downward ldbl-96-m68k 0x4p-52L : 0x4.0000000000008p-52L : inexact-ok
+= expm1 tonearest ldbl-96-m68k 0x4p-52L : 0x4.0000000000008p-52L : inexact-ok
+= expm1 towardzero ldbl-96-m68k 0x4p-52L : 0x4.0000000000008p-52L : inexact-ok
+= expm1 upward ldbl-96-m68k 0x4p-52L : 0x4.0000000000008008p-52L : inexact-ok
+= expm1 downward ldbl-128 0x4p-52L : 0x4.0000000000008000000000000aa8p-52L : inexact-ok
+= expm1 tonearest ldbl-128 0x4p-52L : 0x4.0000000000008000000000000aacp-52L : inexact-ok
+= expm1 towardzero ldbl-128 0x4p-52L : 0x4.0000000000008000000000000aa8p-52L : inexact-ok
+= expm1 upward ldbl-128 0x4p-52L : 0x4.0000000000008000000000000aacp-52L : inexact-ok
+= expm1 downward ldbl-128ibm 0x4p-52L : 0x4.0000000000008000000000000ap-52L : inexact-ok
+= expm1 tonearest ldbl-128ibm 0x4p-52L : 0x4.0000000000008000000000000ap-52L : inexact-ok
+= expm1 towardzero ldbl-128ibm 0x4p-52L : 0x4.0000000000008000000000000ap-52L : inexact-ok
+= expm1 upward ldbl-128ibm 0x4p-52L : 0x4.0000000000008000000000000cp-52L : inexact-ok
+expm1 -0x1p-50
+= expm1 downward flt-32 -0x4p-52f : -0x4p-52f : inexact-ok
+= expm1 tonearest flt-32 -0x4p-52f : -0x4p-52f : inexact-ok
+= expm1 towardzero flt-32 -0x4p-52f : -0x3.fffffcp-52f : inexact-ok
+= expm1 upward flt-32 -0x4p-52f : -0x3.fffffcp-52f : inexact-ok
+= expm1 downward dbl-64 -0x4p-52 : -0x3.ffffffffffffap-52 : inexact-ok
+= expm1 tonearest dbl-64 -0x4p-52 : -0x3.ffffffffffff8p-52 : inexact-ok
+= expm1 towardzero dbl-64 -0x4p-52 : -0x3.ffffffffffff8p-52 : inexact-ok
+= expm1 upward dbl-64 -0x4p-52 : -0x3.ffffffffffff8p-52 : inexact-ok
+= expm1 downward ldbl-96-intel -0x4p-52L : -0x3.ffffffffffff8004p-52L : inexact-ok
+= expm1 tonearest ldbl-96-intel -0x4p-52L : -0x3.ffffffffffff8p-52L : inexact-ok
+= expm1 towardzero ldbl-96-intel -0x4p-52L : -0x3.ffffffffffff8p-52L : inexact-ok
+= expm1 upward ldbl-96-intel -0x4p-52L : -0x3.ffffffffffff8p-52L : inexact-ok
+= expm1 downward ldbl-96-m68k -0x4p-52L : -0x3.ffffffffffff8004p-52L : inexact-ok
+= expm1 tonearest ldbl-96-m68k -0x4p-52L : -0x3.ffffffffffff8p-52L : inexact-ok
+= expm1 towardzero ldbl-96-m68k -0x4p-52L : -0x3.ffffffffffff8p-52L : inexact-ok
+= expm1 upward ldbl-96-m68k -0x4p-52L : -0x3.ffffffffffff8p-52L : inexact-ok
+= expm1 downward ldbl-128 -0x4p-52L : -0x3.ffffffffffff8000000000000aacp-52L : inexact-ok
+= expm1 tonearest ldbl-128 -0x4p-52L : -0x3.ffffffffffff8000000000000aaap-52L : inexact-ok
+= expm1 towardzero ldbl-128 -0x4p-52L : -0x3.ffffffffffff8000000000000aaap-52L : inexact-ok
+= expm1 upward ldbl-128 -0x4p-52L : -0x3.ffffffffffff8000000000000aaap-52L : inexact-ok
+= expm1 downward ldbl-128ibm -0x4p-52L : -0x3.ffffffffffff8000000000000bp-52L : inexact-ok
+= expm1 tonearest ldbl-128ibm -0x4p-52L : -0x3.ffffffffffff8000000000000bp-52L : inexact-ok
+= expm1 towardzero ldbl-128ibm -0x4p-52L : -0x3.ffffffffffff8000000000000ap-52L : inexact-ok
+= expm1 upward ldbl-128ibm -0x4p-52L : -0x3.ffffffffffff8000000000000ap-52L : inexact-ok
+expm1 0x1p-64
+= expm1 downward flt-32 0x1p-64f : 0x1p-64f : inexact-ok
+= expm1 tonearest flt-32 0x1p-64f : 0x1p-64f : inexact-ok
+= expm1 towardzero flt-32 0x1p-64f : 0x1p-64f : inexact-ok
+= expm1 upward flt-32 0x1p-64f : 0x1.000002p-64f : inexact-ok
+= expm1 downward dbl-64 0x1p-64 : 0x1p-64 : inexact-ok
+= expm1 tonearest dbl-64 0x1p-64 : 0x1p-64 : inexact-ok
+= expm1 towardzero dbl-64 0x1p-64 : 0x1p-64 : inexact-ok
+= expm1 upward dbl-64 0x1p-64 : 0x1.0000000000001p-64 : inexact-ok
+= expm1 downward ldbl-96-intel 0x1p-64L : 0x1p-64L : inexact-ok
+= expm1 tonearest ldbl-96-intel 0x1p-64L : 0x1p-64L : inexact-ok
+= expm1 towardzero ldbl-96-intel 0x1p-64L : 0x1p-64L : inexact-ok
+= expm1 upward ldbl-96-intel 0x1p-64L : 0x1.0000000000000002p-64L : inexact-ok
+= expm1 downward ldbl-96-m68k 0x1p-64L : 0x1p-64L : inexact-ok
+= expm1 tonearest ldbl-96-m68k 0x1p-64L : 0x1p-64L : inexact-ok
+= expm1 towardzero ldbl-96-m68k 0x1p-64L : 0x1p-64L : inexact-ok
+= expm1 upward ldbl-96-m68k 0x1p-64L : 0x1.0000000000000002p-64L : inexact-ok
+= expm1 downward ldbl-128 0x1p-64L : 0x1.00000000000000008p-64L : inexact-ok
+= expm1 tonearest ldbl-128 0x1p-64L : 0x1.00000000000000008p-64L : inexact-ok
+= expm1 towardzero ldbl-128 0x1p-64L : 0x1.00000000000000008p-64L : inexact-ok
+= expm1 upward ldbl-128 0x1p-64L : 0x1.0000000000000000800000000001p-64L : inexact-ok
+= expm1 downward ldbl-128ibm 0x1p-64L : 0x1.00000000000000008p-64L : inexact-ok
+= expm1 tonearest ldbl-128ibm 0x1p-64L : 0x1.00000000000000008p-64L : inexact-ok
+= expm1 towardzero ldbl-128ibm 0x1p-64L : 0x1.00000000000000008p-64L : inexact-ok
+= expm1 upward ldbl-128ibm 0x1p-64L : 0x1.000000000000000080000000008p-64L : inexact-ok
+expm1 -0x1p-64
+= expm1 downward flt-32 -0x1p-64f : -0x1p-64f : inexact-ok
+= expm1 tonearest flt-32 -0x1p-64f : -0x1p-64f : inexact-ok
+= expm1 towardzero flt-32 -0x1p-64f : -0xf.fffffp-68f : inexact-ok
+= expm1 upward flt-32 -0x1p-64f : -0xf.fffffp-68f : inexact-ok
+= expm1 downward dbl-64 -0x1p-64 : -0x1p-64 : inexact-ok
+= expm1 tonearest dbl-64 -0x1p-64 : -0x1p-64 : inexact-ok
+= expm1 towardzero dbl-64 -0x1p-64 : -0xf.ffffffffffff8p-68 : inexact-ok
+= expm1 upward dbl-64 -0x1p-64 : -0xf.ffffffffffff8p-68 : inexact-ok
+= expm1 downward ldbl-96-intel -0x1p-64L : -0x1p-64L : inexact-ok
+= expm1 tonearest ldbl-96-intel -0x1p-64L : -0xf.fffffffffffffffp-68L : inexact-ok
+= expm1 towardzero ldbl-96-intel -0x1p-64L : -0xf.fffffffffffffffp-68L : inexact-ok
+= expm1 upward ldbl-96-intel -0x1p-64L : -0xf.fffffffffffffffp-68L : inexact-ok
+= expm1 downward ldbl-96-m68k -0x1p-64L : -0x1p-64L : inexact-ok
+= expm1 tonearest ldbl-96-m68k -0x1p-64L : -0xf.fffffffffffffffp-68L : inexact-ok
+= expm1 towardzero ldbl-96-m68k -0x1p-64L : -0xf.fffffffffffffffp-68L : inexact-ok
+= expm1 upward ldbl-96-m68k -0x1p-64L : -0xf.fffffffffffffffp-68L : inexact-ok
+= expm1 downward ldbl-128 -0x1p-64L : -0xf.fffffffffffffff8p-68L : inexact-ok
+= expm1 tonearest ldbl-128 -0x1p-64L : -0xf.fffffffffffffff8p-68L : inexact-ok
+= expm1 towardzero ldbl-128 -0x1p-64L : -0xf.fffffffffffffff7fffffffffff8p-68L : inexact-ok
+= expm1 upward ldbl-128 -0x1p-64L : -0xf.fffffffffffffff7fffffffffff8p-68L : inexact-ok
+= expm1 downward ldbl-128ibm -0x1p-64L : -0xf.fffffffffffffff8p-68L : inexact-ok
+= expm1 tonearest ldbl-128ibm -0x1p-64L : -0xf.fffffffffffffff8p-68L : inexact-ok
+= expm1 towardzero ldbl-128ibm -0x1p-64L : -0xf.fffffffffffffff7fffffffffcp-68L : inexact-ok
+= expm1 upward ldbl-128ibm -0x1p-64L : -0xf.fffffffffffffff7fffffffffcp-68L : inexact-ok
+expm1 0x1p-100
+= expm1 downward flt-32 0x1p-100f : 0x1p-100f : inexact-ok
+= expm1 tonearest flt-32 0x1p-100f : 0x1p-100f : inexact-ok
+= expm1 towardzero flt-32 0x1p-100f : 0x1p-100f : inexact-ok
+= expm1 upward flt-32 0x1p-100f : 0x1.000002p-100f : inexact-ok
+= expm1 downward dbl-64 0x1p-100 : 0x1p-100 : inexact-ok
+= expm1 tonearest dbl-64 0x1p-100 : 0x1p-100 : inexact-ok
+= expm1 towardzero dbl-64 0x1p-100 : 0x1p-100 : inexact-ok
+= expm1 upward dbl-64 0x1p-100 : 0x1.0000000000001p-100 : inexact-ok
+= expm1 downward ldbl-96-intel 0x1p-100L : 0x1p-100L : inexact-ok
+= expm1 tonearest ldbl-96-intel 0x1p-100L : 0x1p-100L : inexact-ok
+= expm1 towardzero ldbl-96-intel 0x1p-100L : 0x1p-100L : inexact-ok
+= expm1 upward ldbl-96-intel 0x1p-100L : 0x1.0000000000000002p-100L : inexact-ok
+= expm1 downward ldbl-96-m68k 0x1p-100L : 0x1p-100L : inexact-ok
+= expm1 tonearest ldbl-96-m68k 0x1p-100L : 0x1p-100L : inexact-ok
+= expm1 towardzero ldbl-96-m68k 0x1p-100L : 0x1p-100L : inexact-ok
+= expm1 upward ldbl-96-m68k 0x1p-100L : 0x1.0000000000000002p-100L : inexact-ok
+= expm1 downward ldbl-128 0x1p-100L : 0x1.00000000000000000000000008p-100L : inexact-ok
+= expm1 tonearest ldbl-128 0x1p-100L : 0x1.00000000000000000000000008p-100L : inexact-ok
+= expm1 towardzero ldbl-128 0x1p-100L : 0x1.00000000000000000000000008p-100L : inexact-ok
+= expm1 upward ldbl-128 0x1p-100L : 0x1.0000000000000000000000000801p-100L : inexact-ok
+= expm1 downward ldbl-128ibm 0x1p-100L : 0x1.00000000000000000000000008p-100L : inexact-ok
+= expm1 tonearest ldbl-128ibm 0x1p-100L : 0x1.00000000000000000000000008p-100L : inexact-ok
+= expm1 towardzero ldbl-128ibm 0x1p-100L : 0x1.00000000000000000000000008p-100L : inexact-ok
+= expm1 upward ldbl-128ibm 0x1p-100L : 0x1.000000000000000000000000088p-100L : inexact-ok
+expm1 -0x1p-100
+= expm1 downward flt-32 -0x1p-100f : -0x1p-100f : inexact-ok
+= expm1 tonearest flt-32 -0x1p-100f : -0x1p-100f : inexact-ok
+= expm1 towardzero flt-32 -0x1p-100f : -0xf.fffffp-104f : inexact-ok
+= expm1 upward flt-32 -0x1p-100f : -0xf.fffffp-104f : inexact-ok
+= expm1 downward dbl-64 -0x1p-100 : -0x1p-100 : inexact-ok
+= expm1 tonearest dbl-64 -0x1p-100 : -0x1p-100 : inexact-ok
+= expm1 towardzero dbl-64 -0x1p-100 : -0xf.ffffffffffff8p-104 : inexact-ok
+= expm1 upward dbl-64 -0x1p-100 : -0xf.ffffffffffff8p-104 : inexact-ok
+= expm1 downward ldbl-96-intel -0x1p-100L : -0x1p-100L : inexact-ok
+= expm1 tonearest ldbl-96-intel -0x1p-100L : -0x1p-100L : inexact-ok
+= expm1 towardzero ldbl-96-intel -0x1p-100L : -0xf.fffffffffffffffp-104L : inexact-ok
+= expm1 upward ldbl-96-intel -0x1p-100L : -0xf.fffffffffffffffp-104L : inexact-ok
+= expm1 downward ldbl-96-m68k -0x1p-100L : -0x1p-100L : inexact-ok
+= expm1 tonearest ldbl-96-m68k -0x1p-100L : -0x1p-100L : inexact-ok
+= expm1 towardzero ldbl-96-m68k -0x1p-100L : -0xf.fffffffffffffffp-104L : inexact-ok
+= expm1 upward ldbl-96-m68k -0x1p-100L : -0xf.fffffffffffffffp-104L : inexact-ok
+= expm1 downward ldbl-128 -0x1p-100L : -0xf.ffffffffffffffffffffffff8p-104L : inexact-ok
+= expm1 tonearest ldbl-128 -0x1p-100L : -0xf.ffffffffffffffffffffffff8p-104L : inexact-ok
+= expm1 towardzero ldbl-128 -0x1p-100L : -0xf.ffffffffffffffffffffffff7ff8p-104L : inexact-ok
+= expm1 upward ldbl-128 -0x1p-100L : -0xf.ffffffffffffffffffffffff7ff8p-104L : inexact-ok
+= expm1 downward ldbl-128ibm -0x1p-100L : -0xf.ffffffffffffffffffffffff8p-104L : inexact-ok
+= expm1 tonearest ldbl-128ibm -0x1p-100L : -0xf.ffffffffffffffffffffffff8p-104L : inexact-ok
+= expm1 towardzero ldbl-128ibm -0x1p-100L : -0xf.ffffffffffffffffffffffff7cp-104L : inexact-ok
+= expm1 upward ldbl-128ibm -0x1p-100L : -0xf.ffffffffffffffffffffffff7cp-104L : inexact-ok
 hypot 0 0
 = hypot downward flt-32 0x0p+0f 0x0p+0f : 0x0p+0f : inexact-ok
 = hypot tonearest flt-32 0x0p+0f 0x0p+0f : 0x0p+0f : inexact-ok
@@ -61939,31 +62339,31 @@ sinh 0.75
 = sinh tonearest ldbl-128ibm 0xcp-4L : 0xd.283596e9e347f2ee3cf47bf04cp-4L : inexact-ok
 = sinh towardzero ldbl-128ibm 0xcp-4L : 0xd.283596e9e347f2ee3cf47bf048p-4L : inexact-ok
 = sinh upward ldbl-128ibm 0xcp-4L : 0xd.283596e9e347f2ee3cf47bf04cp-4L : inexact-ok
-sinh 0x8p-32 xfail:x86_64:ldbl-96-intel xfail:x86
-= sinh downward flt-32 0x8p-32f : 0x8p-32f : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh tonearest flt-32 0x8p-32f : 0x8p-32f : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh towardzero flt-32 0x8p-32f : 0x8p-32f : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh upward flt-32 0x8p-32f : 0x8.00001p-32f : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh downward dbl-64 0x8p-32 : 0x8p-32 : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh tonearest dbl-64 0x8p-32 : 0x8p-32 : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh towardzero dbl-64 0x8p-32 : 0x8p-32 : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh upward dbl-64 0x8p-32 : 0x8.0000000000008p-32 : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh downward ldbl-96-intel 0x8p-32L : 0x8.000000000000005p-32L : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh tonearest ldbl-96-intel 0x8p-32L : 0x8.000000000000005p-32L : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh towardzero ldbl-96-intel 0x8p-32L : 0x8.000000000000005p-32L : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh upward ldbl-96-intel 0x8p-32L : 0x8.000000000000006p-32L : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh downward ldbl-96-m68k 0x8p-32L : 0x8.000000000000005p-32L : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh tonearest ldbl-96-m68k 0x8p-32L : 0x8.000000000000005p-32L : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh towardzero ldbl-96-m68k 0x8p-32L : 0x8.000000000000005p-32L : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh upward ldbl-96-m68k 0x8p-32L : 0x8.000000000000006p-32L : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh downward ldbl-128 0x8p-32L : 0x8.000000000000005555555555555p-32L : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh tonearest ldbl-128 0x8p-32L : 0x8.0000000000000055555555555558p-32L : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh towardzero ldbl-128 0x8p-32L : 0x8.000000000000005555555555555p-32L : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh upward ldbl-128 0x8p-32L : 0x8.0000000000000055555555555558p-32L : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh downward ldbl-128ibm 0x8p-32L : 0x8.00000000000000555555555554p-32L : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh tonearest ldbl-128ibm 0x8p-32L : 0x8.00000000000000555555555554p-32L : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh towardzero ldbl-128ibm 0x8p-32L : 0x8.00000000000000555555555554p-32L : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
-= sinh upward ldbl-128ibm 0x8p-32L : 0x8.00000000000000555555555558p-32L : xfail:x86_64:ldbl-96-intel xfail:x86 inexact-ok
+sinh 0x8p-32
+= sinh downward flt-32 0x8p-32f : 0x8p-32f : inexact-ok
+= sinh tonearest flt-32 0x8p-32f : 0x8p-32f : inexact-ok
+= sinh towardzero flt-32 0x8p-32f : 0x8p-32f : inexact-ok
+= sinh upward flt-32 0x8p-32f : 0x8.00001p-32f : inexact-ok
+= sinh downward dbl-64 0x8p-32 : 0x8p-32 : inexact-ok
+= sinh tonearest dbl-64 0x8p-32 : 0x8p-32 : inexact-ok
+= sinh towardzero dbl-64 0x8p-32 : 0x8p-32 : inexact-ok
+= sinh upward dbl-64 0x8p-32 : 0x8.0000000000008p-32 : inexact-ok
+= sinh downward ldbl-96-intel 0x8p-32L : 0x8.000000000000005p-32L : inexact-ok
+= sinh tonearest ldbl-96-intel 0x8p-32L : 0x8.000000000000005p-32L : inexact-ok
+= sinh towardzero ldbl-96-intel 0x8p-32L : 0x8.000000000000005p-32L : inexact-ok
+= sinh upward ldbl-96-intel 0x8p-32L : 0x8.000000000000006p-32L : inexact-ok
+= sinh downward ldbl-96-m68k 0x8p-32L : 0x8.000000000000005p-32L : inexact-ok
+= sinh tonearest ldbl-96-m68k 0x8p-32L : 0x8.000000000000005p-32L : inexact-ok
+= sinh towardzero ldbl-96-m68k 0x8p-32L : 0x8.000000000000005p-32L : inexact-ok
+= sinh upward ldbl-96-m68k 0x8p-32L : 0x8.000000000000006p-32L : inexact-ok
+= sinh downward ldbl-128 0x8p-32L : 0x8.000000000000005555555555555p-32L : inexact-ok
+= sinh tonearest ldbl-128 0x8p-32L : 0x8.0000000000000055555555555558p-32L : inexact-ok
+= sinh towardzero ldbl-128 0x8p-32L : 0x8.000000000000005555555555555p-32L : inexact-ok
+= sinh upward ldbl-128 0x8p-32L : 0x8.0000000000000055555555555558p-32L : inexact-ok
+= sinh downward ldbl-128ibm 0x8p-32L : 0x8.00000000000000555555555554p-32L : inexact-ok
+= sinh tonearest ldbl-128ibm 0x8p-32L : 0x8.00000000000000555555555554p-32L : inexact-ok
+= sinh towardzero ldbl-128ibm 0x8p-32L : 0x8.00000000000000555555555554p-32L : inexact-ok
+= sinh upward ldbl-128ibm 0x8p-32L : 0x8.00000000000000555555555558p-32L : inexact-ok
 sinh 22
 = sinh downward flt-32 0x1.6p+4f : 0x6.ad6b68p+28f : inexact-ok
 = sinh tonearest flt-32 0x1.6p+4f : 0x6.ad6b7p+28f : inexact-ok
diff --git a/math/libm-test.inc b/math/libm-test.inc
index dea6c8b7ce..aab3ed2987 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -267,18 +267,6 @@ struct ulp_data
 #define TEST_COND_before_rounding	(!TININESS_AFTER_ROUNDING)
 #define TEST_COND_after_rounding	TININESS_AFTER_ROUNDING
 
-#ifdef __x86_64__
-# define TEST_COND_x86_64	1
-#else
-# define TEST_COND_x86_64	0
-#endif
-
-#ifdef __i386__
-# define TEST_COND_x86		1
-#else
-# define TEST_COND_x86		0
-#endif
-
 /* Various constants (we must supply them precalculated for accuracy).  */
 #define M_PI_6l			.52359877559829887307710723054658383L
 #define M_PI_34l		2.356194490192344928846982537459627163L	/* 3*pi/4 */
@@ -7845,6 +7833,62 @@ expm1_test (void)
 }
 
 
+static const struct test_f_f_data expm1_tonearest_test_data[] =
+  {
+    AUTO_TESTS_f_f (expm1, tonearest),
+  };
+
+static void
+expm1_test_tonearest (void)
+{
+  START (expm1_tonearest);
+  RUN_TEST_LOOP_f_f (expm1, expm1_tonearest_test_data, FE_TONEAREST);
+  END;
+}
+
+
+static const struct test_f_f_data expm1_towardzero_test_data[] =
+  {
+    AUTO_TESTS_f_f (expm1, towardzero),
+  };
+
+static void
+expm1_test_towardzero (void)
+{
+  START (expm1_towardzero);
+  RUN_TEST_LOOP_f_f (expm1, expm1_towardzero_test_data, FE_TOWARDZERO);
+  END;
+}
+
+
+static const struct test_f_f_data expm1_downward_test_data[] =
+  {
+    AUTO_TESTS_f_f (expm1, downward),
+  };
+
+static void
+expm1_test_downward (void)
+{
+  START (expm1_downward);
+  RUN_TEST_LOOP_f_f (expm1, expm1_downward_test_data, FE_DOWNWARD);
+  END;
+}
+
+
+static const struct test_f_f_data expm1_upward_test_data[] =
+  {
+    AUTO_TESTS_f_f (expm1, upward),
+  };
+
+static void
+expm1_test_upward (void)
+{
+  START (expm1_upward);
+  RUN_TEST_LOOP_f_f (expm1, expm1_upward_test_data, FE_UPWARD);
+  END;
+}
+
+
 static const struct test_f_f_data fabs_test_data[] =
   {
     TEST_f_f (fabs, 0, 0, NO_INEXACT_EXCEPTION),
@@ -13337,6 +13381,10 @@ main (int argc, char **argv)
   exp10_test ();
   exp2_test ();
   expm1_test ();
+  expm1_test_tonearest ();
+  expm1_test_towardzero ();
+  expm1_test_downward ();
+  expm1_test_upward ();
   frexp_test ();
   ldexp_test ();
   log_test ();
diff --git a/sysdeps/i386/fpu/e_expl.S b/sysdeps/i386/fpu/e_expl.S
index af339f0ff4..a8a5e70b07 100644
--- a/sysdeps/i386/fpu/e_expl.S
+++ b/sysdeps/i386/fpu/e_expl.S
@@ -130,9 +130,24 @@ ENTRY(IEEE754_EXPL)
 #endif
 3:	FLDLOG			/* 1  log2(base)      */
 	fmul	%st(1), %st	/* 1  x log2(base)    */
+#ifdef USE_AS_EXPM1L
+	/* Set round-to-nearest temporarily.  */
+	subl	$8, %esp
+	cfi_adjust_cfa_offset (8)
+	fstcw	4(%esp)
+	movl	$0xf3ff, %edx
+	andl	4(%esp), %edx
+	movl	%edx, (%esp)
+	fldcw	(%esp)
+#endif
 	frndint			/* 1  i               */
 	fld	%st(1)		/* 2  x               */
 	frndint			/* 2  xi              */
+#ifdef USE_AS_EXPM1L
+	fldcw	4(%esp)
+	addl	$8, %esp
+	cfi_adjust_cfa_offset (-8)
+#endif
 	fld	%st(1)		/* 3  i               */
 	fldt	MO(c0)		/* 4  c0              */
 	fld	%st(2)		/* 5  xi              */
diff --git a/sysdeps/i386/fpu/libm-test-ulps b/sysdeps/i386/fpu/libm-test-ulps
index a471e5fe9f..bb3adcbd67 100644
--- a/sysdeps/i386/fpu/libm-test-ulps
+++ b/sysdeps/i386/fpu/libm-test-ulps
@@ -6092,9 +6092,15 @@ idouble: 1
 ifloat: 1
 
 # expm1
+Test "expm1 (-0x1p-64)":
+ildouble: 1
+ldouble: 1
 Test "expm1 (-0x2.dp+4)":
 ildouble: 1
 ldouble: 1
+Test "expm1 (-0x4p-12)":
+ildouble: 1
+ldouble: 1
 Test "expm1 (-45.0)":
 ildouble: 1
 ldouble: 1
@@ -6108,6 +6114,338 @@ Test "expm1 (11356.25)":
 ildouble: 1
 ldouble: 1
 
+# expm1_downward
+Test "expm1_downward (-0x1p-100)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (-0x2.ep+4)":
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (-0x4.9p+4)":
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (-0x4.bp+4)":
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (-0x4p-4)":
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (-0x5p+4)":
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (-0x6.4p+4)":
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (0x1p+0)":
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (0x1p-100)":
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (0x1p-32)":
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (0x3.2p+4)":
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (0x4p-12)":
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (0x4p-52)":
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (0x7.fp+4)":
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (0x8p-32)":
+ildouble: 1
+ldouble: 1
+
+# expm1_tonearest
+Test "expm1_tonearest (-0x1p-64)":
+ildouble: 1
+ldouble: 1
+Test "expm1_tonearest (-0x2.dp+4)":
+ildouble: 1
+ldouble: 1
+Test "expm1_tonearest (-0x4p-12)":
+ildouble: 1
+ldouble: 1
+Test "expm1_tonearest (0x1p+0)":
+ildouble: 1
+ldouble: 1
+Test "expm1_tonearest (0x2.c5c4p+12)":
+ildouble: 1
+ldouble: 1
+
+# expm1_towardzero
+Test "expm1_towardzero (-0x1.2p+4)":
+float: 1
+Test "expm1_towardzero (-0x1.86ap+16)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0x1p-100)":
+double: 1
+float: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0x1p-20)":
+ildouble: 2
+ldouble: 2
+Test "expm1_towardzero (-0x1p-32)":
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0x1p-64)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0x2.4p+4)":
+float: 1
+Test "expm1_towardzero (-0x2.5p+4)":
+float: 1
+Test "expm1_towardzero (-0x2.6p+4)":
+double: 1
+float: 1
+Test "expm1_towardzero (-0x2.71p+12)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0x2.cp+4)":
+double: 1
+float: 1
+Test "expm1_towardzero (-0x2.dp+4)":
+double: 1
+float: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0x2.ep+4)":
+double: 1
+float: 1
+Test "expm1_towardzero (-0x3.e8p+8)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0x4.9p+4)":
+double: 1
+float: 1
+Test "expm1_towardzero (-0x4.ap+4)":
+double: 1
+float: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0x4.bp+4)":
+double: 1
+float: 1
+Test "expm1_towardzero (-0x4.ep+4)":
+double: 1
+float: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0x4.fp+4)":
+double: 1
+float: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0x4p-12)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0x4p-52)":
+idouble: 1
+ildouble: 2
+ldouble: 2
+Test "expm1_towardzero (-0x5p+4)":
+double: 1
+float: 1
+Test "expm1_towardzero (-0x6.4p+4)":
+double: 1
+float: 1
+Test "expm1_towardzero (-0x8p-32)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0xf.ffffffffffff8p+1020)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0xf.fffffffffffffffp+16380)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0xf.fffffp+124)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (0x1p+0)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (0x1p-100)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (0x1p-32)":
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (0x3.2p+4)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (0x4p-12)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (0x4p-52)":
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (0x7.fp+4)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (0x8p-32)":
+ildouble: 1
+ldouble: 1
+
+# expm1_upward
+Test "expm1_upward (-0x1.2p+4)":
+float: 1
+Test "expm1_upward (-0x1.86ap+16)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0x1p-100)":
+double: 1
+float: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0x1p-20)":
+ildouble: 2
+ldouble: 2
+Test "expm1_upward (-0x1p-32)":
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0x1p-64)":
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0x2.4p+4)":
+float: 1
+Test "expm1_upward (-0x2.5p+4)":
+float: 1
+Test "expm1_upward (-0x2.6p+4)":
+double: 1
+float: 1
+Test "expm1_upward (-0x2.71p+12)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0x2.cp+4)":
+double: 1
+float: 1
+Test "expm1_upward (-0x2.dp+4)":
+double: 1
+float: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0x2.ep+4)":
+double: 1
+float: 1
+Test "expm1_upward (-0x3.e8p+8)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0x4.9p+4)":
+double: 1
+float: 1
+Test "expm1_upward (-0x4.ap+4)":
+double: 1
+float: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0x4.bp+4)":
+double: 1
+float: 1
+Test "expm1_upward (-0x4.ep+4)":
+double: 1
+float: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0x4.fp+4)":
+double: 1
+float: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0x4p-12)":
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0x4p-52)":
+idouble: 1
+ildouble: 2
+ldouble: 2
+Test "expm1_upward (-0x5p+4)":
+double: 1
+float: 1
+Test "expm1_upward (-0x6.4p+4)":
+double: 1
+float: 1
+Test "expm1_upward (-0x8p-32)":
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0xf.ffffffffffff8p+1020)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0xf.fffffffffffffffp+16380)":
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0xf.fffffp+124)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (0x1.f4p+8)":
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (0x4p-4)":
+ildouble: 1
+ldouble: 1
+
 # gamma
 Test "gamma (-0.5)":
 double: 1
@@ -7773,6 +8111,9 @@ ldouble: 1
 Test "sinh_downward (0x1.8p+4)":
 ildouble: 1
 ldouble: 1
+Test "sinh_downward (0x8p-32)":
+ildouble: 1
+ldouble: 1
 Test "sinh_downward (0xcp-4)":
 float: 1
 ildouble: 1
@@ -7810,6 +8151,9 @@ ldouble: 1
 Test "sinh_towardzero (0x1.8p+4)":
 ildouble: 1
 ldouble: 1
+Test "sinh_towardzero (0x8p-32)":
+ildouble: 1
+ldouble: 1
 Test "sinh_towardzero (0xcp-4)":
 float: 1
 ildouble: 1
@@ -7840,6 +8184,9 @@ ldouble: 1
 Test "sinh_upward (0x1.7p+4)":
 ildouble: 1
 ldouble: 1
+Test "sinh_upward (0x8p-32)":
+double: 1
+float: 1
 Test "sinh_upward (0xcp-4)":
 float: 1
 ildouble: 2
@@ -10663,6 +11010,34 @@ Function: "expm1":
 ildouble: 1
 ldouble: 1
 
+Function: "expm1_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "expm1_tonearest":
+ildouble: 1
+ldouble: 1
+
+Function: "expm1_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: "expm1_upward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
 Function: "gamma":
 double: 1
 float: 2
diff --git a/sysdeps/i386/fpu/s_expm1.S b/sysdeps/i386/fpu/s_expm1.S
index 91617eb74c..398055276e 100644
--- a/sysdeps/i386/fpu/s_expm1.S
+++ b/sysdeps/i386/fpu/s_expm1.S
@@ -78,7 +78,18 @@ ENTRY(__expm1)
 5:	fldt	MO(l2e)		// log2(e) : x
 	fmulp			// log2(e)*x
 	fld	%st		// log2(e)*x : log2(e)*x
+	// Set round-to-nearest temporarily.
+	subl	$8, %esp
+	cfi_adjust_cfa_offset (8)
+	fstcw	4(%esp)
+	movl	$0xf3ff, %ecx
+	andl	4(%esp), %ecx
+	movl	%ecx, (%esp)
+	fldcw	(%esp)
 	frndint			// int(log2(e)*x) : log2(e)*x
+	fldcw	4(%esp)
+	addl	$8, %esp
+	cfi_adjust_cfa_offset (-8)
 	fsubr	%st, %st(1)	// int(log2(e)*x) : fract(log2(e)*x)
 	fxch			// fract(log2(e)*x) : int(log2(e)*x)
 	f2xm1			// 2^fract(log2(e)*x)-1 : int(log2(e)*x)
diff --git a/sysdeps/i386/fpu/s_expm1f.S b/sysdeps/i386/fpu/s_expm1f.S
index 2f1b6f69fc..e5e52a08f3 100644
--- a/sysdeps/i386/fpu/s_expm1f.S
+++ b/sysdeps/i386/fpu/s_expm1f.S
@@ -78,7 +78,18 @@ ENTRY(__expm1f)
 5:	fldt	MO(l2e)		// log2(e) : x
 	fmulp			// log2(e)*x
 	fld	%st		// log2(e)*x : log2(e)*x
+	// Set round-to-nearest temporarily.
+	subl	$8, %esp
+	cfi_adjust_cfa_offset (8)
+	fstcw	4(%esp)
+	movl	$0xf3ff, %ecx
+	andl	4(%esp), %ecx
+	movl	%ecx, (%esp)
+	fldcw	(%esp)
 	frndint			// int(log2(e)*x) : log2(e)*x
+	fldcw	4(%esp)
+	addl	$8, %esp
+	cfi_adjust_cfa_offset (-8)
 	fsubr	%st, %st(1)	// int(log2(e)*x) : fract(log2(e)*x)
 	fxch			// fract(log2(e)*x) : int(log2(e)*x)
 	f2xm1			// 2^fract(log2(e)*x)-1 : int(log2(e)*x)
diff --git a/sysdeps/x86_64/fpu/e_expl.S b/sysdeps/x86_64/fpu/e_expl.S
index a919780390..1c21f03ddc 100644
--- a/sysdeps/x86_64/fpu/e_expl.S
+++ b/sysdeps/x86_64/fpu/e_expl.S
@@ -127,9 +127,20 @@ ENTRY(IEEE754_EXPL)
 #endif
 3:	FLDLOG			/* 1  log2(base)      */
 	fmul	%st(1), %st	/* 1  x log2(base)    */
+#ifdef USE_AS_EXPM1L
+	/* Set round-to-nearest temporarily.  */
+	fstcw	-4(%rsp)
+	movl	$0xf3ff, %edx
+	andl	-4(%rsp), %edx
+	movl	%edx, -8(%rsp)
+	fldcw	-8(%rsp)
+#endif
 	frndint			/* 1  i               */
 	fld	%st(1)		/* 2  x               */
 	frndint			/* 2  xi              */
+#ifdef USE_AS_EXPM1L
+	fldcw	-4(%rsp)
+#endif
 	fld	%st(1)		/* 3  i               */
 	fldt	MO(c0)		/* 4  c0              */
 	fld	%st(2)		/* 5  xi              */
diff --git a/sysdeps/x86_64/fpu/libm-test-ulps b/sysdeps/x86_64/fpu/libm-test-ulps
index b45ce1dfcd..89b4bc8289 100644
--- a/sysdeps/x86_64/fpu/libm-test-ulps
+++ b/sysdeps/x86_64/fpu/libm-test-ulps
@@ -7011,9 +7011,15 @@ float: 1
 ifloat: 1
 
 # expm1
+Test "expm1 (-0x1p-64)":
+ildouble: 1
+ldouble: 1
 Test "expm1 (-0x2.dp+4)":
 ildouble: 1
 ldouble: 1
+Test "expm1 (-0x4p-12)":
+ildouble: 1
+ldouble: 1
 Test "expm1 (-45.0)":
 ildouble: 1
 ldouble: 1
@@ -7048,6 +7054,281 @@ Test "expm1 (500.0)":
 double: 1
 idouble: 1
 
+# expm1_downward
+Test "expm1_downward (-0x1p-100)":
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (-0x2.ep+4)":
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (-0x4.9p+4)":
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (-0x4.bp+4)":
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (-0x4p-4)":
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (-0x5p+4)":
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (-0x6.4p+4)":
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (0x1.f4p+8)":
+double: 1
+idouble: 1
+Test "expm1_downward (0x1p+0)":
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (0x1p-100)":
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (0x1p-32)":
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (0x3.2p+4)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (0x4p-12)":
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (0x4p-52)":
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (0x7.fp+4)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_downward (0x8p-32)":
+ildouble: 1
+ldouble: 1
+
+# expm1_tonearest
+Test "expm1_tonearest (-0x1p-64)":
+ildouble: 1
+ldouble: 1
+Test "expm1_tonearest (-0x2.dp+4)":
+ildouble: 1
+ldouble: 1
+Test "expm1_tonearest (-0x4p-12)":
+ildouble: 1
+ldouble: 1
+Test "expm1_tonearest (0x1.f4p+8)":
+double: 1
+idouble: 1
+Test "expm1_tonearest (0x1p+0)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_tonearest (0x2.c5c4p+12)":
+ildouble: 1
+ldouble: 1
+Test "expm1_tonearest (0xcp-4)":
+double: 1
+idouble: 1
+
+# expm1_towardzero
+Test "expm1_towardzero (-0x1.86ap+16)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0x1p-100)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0x1p-20)":
+ildouble: 2
+ldouble: 2
+Test "expm1_towardzero (-0x1p-32)":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0x1p-64)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0x2.71p+12)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0x2.dp+4)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0x3.e8p+8)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0x4.ap+4)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0x4.ep+4)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0x4.fp+4)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0x4p-12)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0x4p-52)":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "expm1_towardzero (-0x8p-32)":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0xf.ffffffffffff8p+1020)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0xf.fffffffffffffffp+16380)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (-0xf.fffffp+124)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (0x1.f4p+8)":
+double: 1
+idouble: 1
+Test "expm1_towardzero (0x1p+0)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (0x1p-100)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (0x1p-32)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (0x3.2p+4)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (0x4p-12)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (0x4p-52)":
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (0x7.fp+4)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_towardzero (0x8p-32)":
+ildouble: 1
+ldouble: 1
+
+# expm1_upward
+Test "expm1_upward (-0x1.86ap+16)":
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0x1p-100)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0x1p-20)":
+ildouble: 2
+ldouble: 2
+Test "expm1_upward (-0x1p-32)":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0x1p-64)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0x2.71p+12)":
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0x2.dp+4)":
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0x3.e8p+8)":
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0x4.ap+4)":
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0x4.ep+4)":
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0x4.fp+4)":
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0x4p-12)":
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0x4p-52)":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "expm1_upward (-0x8p-32)":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0xf.ffffffffffff8p+1020)":
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0xf.fffffffffffffffp+16380)":
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (-0xf.fffffp+124)":
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (0x1.f4p+8)":
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (0x1p-100)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "expm1_upward (0x1p-32)":
+float: 1
+ifloat: 1
+Test "expm1_upward (0x1p-64)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "expm1_upward (0x4p-4)":
+ildouble: 1
+ldouble: 1
+Test "expm1_upward (0x4p-52)":
+float: 1
+ifloat: 1
+Test "expm1_upward (0x8p-32)":
+float: 1
+ifloat: 1
+
 # gamma
 Test "gamma (-0.5)":
 ildouble: 1
@@ -8864,6 +9145,9 @@ ldouble: 1
 Test "sinh_downward (0x1.8p+4)":
 ildouble: 1
 ldouble: 1
+Test "sinh_downward (0x8p-32)":
+ildouble: 1
+ldouble: 1
 Test "sinh_downward (22)":
 float: 1
 ifloat: 1
@@ -8894,6 +9178,9 @@ ldouble: 1
 Test "sinh_towardzero (0x1.8p+4)":
 ildouble: 1
 ldouble: 1
+Test "sinh_towardzero (0x8p-32)":
+ildouble: 1
+ldouble: 1
 Test "sinh_towardzero (22)":
 float: 1
 ifloat: 1
@@ -12014,6 +12301,38 @@ ifloat: 1
 ildouble: 1
 ldouble: 1
 
+Function: "expm1_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "expm1_tonearest":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "expm1_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: "expm1_upward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
 Function: "gamma":
 double: 1
 float: 2