]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Avoid "inexact" exceptions in i386/x86_64 floor functions (bug 15479).
authorJoseph Myers <joseph@codesourcery.com>
Mon, 27 Jun 2016 17:25:47 +0000 (17:25 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Mon, 27 Jun 2016 17:25:47 +0000 (17:25 +0000)
As discussed in
<https://sourceware.org/ml/libc-alpha/2016-05/msg00577.html>, TS
18661-1 disallows ceil, floor, round and trunc functions from raising
the "inexact" exception, in accordance with general IEEE 754 semantics
for when that exception is raised.  Fixing this for x87 floating point
is more complicated than for the other versions of these functions,
because they use the frndint instruction that raises "inexact" and
this can only be avoided by saving and restoring the whole
floating-point environment.

As I noted in
<https://sourceware.org/ml/libc-alpha/2016-06/msg00128.html>, I have
now implemented a GCC option -fno-fp-int-builtin-inexact for GCC 7,
such that GCC will inline these functions on x86, without caring about
"inexact", when the default -ffp-int-builtin-inexact is in effect.
This allows users to get optimized code depending on the options they
pass to the compiler, while making the out-of-line functions follow TS
18661-1 semantics and avoid "inexact".

This patch duly fixes the out-of-line floor function implementations
to avoid "inexact", in the same way as the nearbyint implementations.

I do not know how the performance of implementations such as these
based on saving the environment and changing the rounding mode
temporarily compares to that of the C versions or SSE 4.1 versions (of
course, for 32-bit x86 SSE implementations still need to get the
return value in an x87 register); it's entirely possible other
implementations could be faster in some cases.

Tested for x86_64 and x86.

[BZ #15479]
* sysdeps/i386/fpu/s_floor.S (__floor): Save and restore
floating-point environment rather than just control word.
* sysdeps/i386/fpu/s_floorf.S (__floorf): Likewise.
* sysdeps/i386/fpu/s_floorl.S (__floorl): Save and restore
floating-point environment, with "invalid" exceptions merged in,
rather than just control word.
* sysdeps/x86_64/fpu/s_floorl.S (__floorl): Likewise.
* math/libm-test.inc (floor_test_data): Do not allow spurious
"inexact" exceptions.

ChangeLog
math/libm-test.inc
sysdeps/i386/fpu/s_floor.S
sysdeps/i386/fpu/s_floorf.S
sysdeps/i386/fpu/s_floorl.S
sysdeps/x86_64/fpu/s_floorl.S

index d9d93edc02552ba1ac8bb072e30460c5a08cd1cd..a67e532b723201ef9657f561a6127cd5997708e7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2016-06-27  Joseph Myers  <joseph@codesourcery.com>
 
+       [BZ #15479]
+       * sysdeps/i386/fpu/s_floor.S (__floor): Save and restore
+       floating-point environment rather than just control word.
+       * sysdeps/i386/fpu/s_floorf.S (__floorf): Likewise.
+       * sysdeps/i386/fpu/s_floorl.S (__floorl): Save and restore
+       floating-point environment, with "invalid" exceptions merged in,
+       rather than just control word.
+       * sysdeps/x86_64/fpu/s_floorl.S (__floorl): Likewise.
+       * math/libm-test.inc (floor_test_data): Do not allow spurious
+       "inexact" exceptions.
+
        [BZ #15479]
        * sysdeps/i386/fpu/s_ceil.S (__ceil): Save and restore
        floating-point environment rather than just control word.
index ad97da1cc06debc4432f71438c4095d08e491e94..9f6e21da5b351375a624db0c8637024768db6576 100644 (file)
@@ -7308,14 +7308,13 @@ static const struct test_f_f_data floor_test_data[] =
     TEST_f_f (floor, snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
     TEST_f_f (floor, -snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
 
-    /* Bug 15479: spurious "inexact" exception may occur.  */
-    TEST_f_f (floor, lit_pi, 3.0, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -lit_pi, -4.0, ERRNO_UNCHANGED),
-    TEST_f_f (floor, min_subnorm_value, 0.0, ERRNO_UNCHANGED),
-    TEST_f_f (floor, min_value, 0.0, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 0.1, 0.0, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 0.25, 0.0, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 0.625, 0.0, ERRNO_UNCHANGED),
+    TEST_f_f (floor, lit_pi, 3.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -lit_pi, -4.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, min_subnorm_value, 0.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, min_value, 0.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 0.1, 0.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 0.25, 0.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 0.625, 0.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (floor, 1, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (floor, 2, 2, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (floor, 0x1p23, 0x1p23, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
@@ -7334,11 +7333,11 @@ static const struct test_f_f_data floor_test_data[] =
     TEST_f_f (floor, 0x1p113, 0x1p113, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (floor, 0x1p114, 0x1p114, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (floor, max_value, max_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
-    TEST_f_f (floor, -min_subnorm_value, -1.0, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -min_value, -1.0, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -0.1, -1.0, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -0.25, -1.0, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -0.625, -1.0, ERRNO_UNCHANGED),
+    TEST_f_f (floor, -min_subnorm_value, -1.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -min_value, -1.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -0.1, -1.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -0.25, -1.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -0.625, -1.0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (floor, -1, -1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (floor, -2, -2, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (floor, -0x1p23, -0x1p23, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
@@ -7360,78 +7359,78 @@ static const struct test_f_f_data floor_test_data[] =
 
 #if MANT_DIG >= 64
     /* The result can only be represented in long double.  */
-    TEST_f_f (floor, 4503599627370495.5L, 4503599627370495.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 4503599627370496.25L, 4503599627370496.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 4503599627370496.5L, 4503599627370496.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 4503599627370496.75L, 4503599627370496.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 4503599627370497.5L, 4503599627370497.0L, ERRNO_UNCHANGED),
+    TEST_f_f (floor, 4503599627370495.5L, 4503599627370495.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 4503599627370496.25L, 4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 4503599627370496.5L, 4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 4503599627370496.75L, 4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 4503599627370497.5L, 4503599627370497.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 # if MANT_DIG > 100
-    TEST_f_f (floor, 4503599627370494.5000000000001L, 4503599627370494.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 4503599627370495.5000000000001L, 4503599627370495.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 4503599627370496.5000000000001L, 4503599627370496.0L, ERRNO_UNCHANGED),
+    TEST_f_f (floor, 4503599627370494.5000000000001L, 4503599627370494.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 4503599627370495.5000000000001L, 4503599627370495.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 4503599627370496.5000000000001L, 4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 # endif
 
-    TEST_f_f (floor, -4503599627370495.5L, -4503599627370496.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -4503599627370496.25L, -4503599627370497.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -4503599627370496.5L, -4503599627370497.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -4503599627370496.75L, -4503599627370497.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -4503599627370497.5L, -4503599627370498.0L, ERRNO_UNCHANGED),
+    TEST_f_f (floor, -4503599627370495.5L, -4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -4503599627370496.25L, -4503599627370497.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -4503599627370496.5L, -4503599627370497.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -4503599627370496.75L, -4503599627370497.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -4503599627370497.5L, -4503599627370498.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 # if MANT_DIG > 100
-    TEST_f_f (floor, -4503599627370494.5000000000001L, -4503599627370495.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -4503599627370495.5000000000001L, -4503599627370496.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -4503599627370496.5000000000001L, -4503599627370497.0L, ERRNO_UNCHANGED),
+    TEST_f_f (floor, -4503599627370494.5000000000001L, -4503599627370495.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -4503599627370495.5000000000001L, -4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -4503599627370496.5000000000001L, -4503599627370497.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 # endif
 
-    TEST_f_f (floor, 9007199254740991.5L, 9007199254740991.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 9007199254740992.25L, 9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 9007199254740992.5L, 9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 9007199254740992.75L, 9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 9007199254740993.5L, 9007199254740993.0L, ERRNO_UNCHANGED),
+    TEST_f_f (floor, 9007199254740991.5L, 9007199254740991.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 9007199254740992.25L, 9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 9007199254740992.5L, 9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 9007199254740992.75L, 9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 9007199254740993.5L, 9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
 # if MANT_DIG > 100
-    TEST_f_f (floor, 9007199254740991.0000000000001L, 9007199254740991.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 9007199254740992.0000000000001L, 9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 9007199254740993.0000000000001L, 9007199254740993.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 9007199254740991.5000000000001L, 9007199254740991.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 9007199254740992.5000000000001L, 9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 9007199254740993.5000000000001L, 9007199254740993.0L, ERRNO_UNCHANGED),
+    TEST_f_f (floor, 9007199254740991.0000000000001L, 9007199254740991.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 9007199254740992.0000000000001L, 9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 9007199254740993.0000000000001L, 9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 9007199254740991.5000000000001L, 9007199254740991.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 9007199254740992.5000000000001L, 9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 9007199254740993.5000000000001L, 9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 # endif
 
-    TEST_f_f (floor, -9007199254740991.5L, -9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -9007199254740992.25L, -9007199254740993.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -9007199254740992.5L, -9007199254740993.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -9007199254740992.75L, -9007199254740993.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -9007199254740993.5L, -9007199254740994.0L, ERRNO_UNCHANGED),
+    TEST_f_f (floor, -9007199254740991.5L, -9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -9007199254740992.25L, -9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -9007199254740992.5L, -9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -9007199254740992.75L, -9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -9007199254740993.5L, -9007199254740994.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
 # if MANT_DIG > 100
-    TEST_f_f (floor, -9007199254740991.0000000000001L, -9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -9007199254740992.0000000000001L, -9007199254740993.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -9007199254740993.0000000000001L, -9007199254740994.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -9007199254740991.5000000000001L, -9007199254740992.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -9007199254740992.5000000000001L, -9007199254740993.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -9007199254740993.5000000000001L, -9007199254740994.0L, ERRNO_UNCHANGED),
+    TEST_f_f (floor, -9007199254740991.0000000000001L, -9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -9007199254740992.0000000000001L, -9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -9007199254740993.0000000000001L, -9007199254740994.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -9007199254740991.5000000000001L, -9007199254740992.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -9007199254740992.5000000000001L, -9007199254740993.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -9007199254740993.5000000000001L, -9007199254740994.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 # endif
 
-    TEST_f_f (floor, 72057594037927935.5L, 72057594037927935.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 72057594037927936.25L, 72057594037927936.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 72057594037927936.5L, 72057594037927936.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 72057594037927936.75L, 72057594037927936.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 72057594037927937.5L, 72057594037927937.0L, ERRNO_UNCHANGED),
-
-    TEST_f_f (floor, -72057594037927935.5L, -72057594037927936.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -72057594037927936.25L, -72057594037927937.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -72057594037927936.5L, -72057594037927937.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -72057594037927936.75L, -72057594037927937.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -72057594037927937.5L, -72057594037927938.0L, ERRNO_UNCHANGED),
-
-    TEST_f_f (floor, 10141204801825835211973625643007.5L, 10141204801825835211973625643007.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 10141204801825835211973625643008.25L, 10141204801825835211973625643008.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 10141204801825835211973625643008.5L, 10141204801825835211973625643008.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 10141204801825835211973625643008.75L, 10141204801825835211973625643008.0L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, 10141204801825835211973625643009.5L, 10141204801825835211973625643009.0L, ERRNO_UNCHANGED),
-
-    TEST_f_f (floor, 0xf.ffffffffffffff8p+47L, 0xf.fffffffffffep+47L, ERRNO_UNCHANGED),
-    TEST_f_f (floor, -0x8.000000000000004p+48L, -0x8.000000000001p+48L, ERRNO_UNCHANGED),
+    TEST_f_f (floor, 72057594037927935.5L, 72057594037927935.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 72057594037927936.25L, 72057594037927936.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 72057594037927936.5L, 72057594037927936.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 72057594037927936.75L, 72057594037927936.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 72057594037927937.5L, 72057594037927937.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_f_f (floor, -72057594037927935.5L, -72057594037927936.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -72057594037927936.25L, -72057594037927937.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -72057594037927936.5L, -72057594037927937.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -72057594037927936.75L, -72057594037927937.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -72057594037927937.5L, -72057594037927938.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_f_f (floor, 10141204801825835211973625643007.5L, 10141204801825835211973625643007.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 10141204801825835211973625643008.25L, 10141204801825835211973625643008.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 10141204801825835211973625643008.5L, 10141204801825835211973625643008.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 10141204801825835211973625643008.75L, 10141204801825835211973625643008.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, 10141204801825835211973625643009.5L, 10141204801825835211973625643009.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_f_f (floor, 0xf.ffffffffffffff8p+47L, 0xf.fffffffffffep+47L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (floor, -0x8.000000000000004p+48L, -0x8.000000000001p+48L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 #endif
   };
 
index 2d6287dc7998c5fea6d5daa262b6519c0059517c..ed837dae40fbf9f073883bcd90dd35aed513ae81 100644 (file)
@@ -9,10 +9,10 @@ RCSID("$NetBSD: s_floor.S,v 1.4 1995/05/09 00:01:59 jtc Exp $")
 
 ENTRY(__floor)
        fldl    4(%esp)
-       subl    $8,%esp
-       cfi_adjust_cfa_offset (8)
+       subl    $32,%esp
+       cfi_adjust_cfa_offset (32)
 
-       fstcw   4(%esp)                 /* store fpu control word */
+       fnstenv 4(%esp)                 /* store fpu environment */
 
        /* We use here %edx although only the low 1 bits are defined.
           But none of the operations should care and they are faster
@@ -25,10 +25,10 @@ ENTRY(__floor)
 
        frndint                         /* round */
 
-       fldcw   4(%esp)                 /* restore original control word */
+       fldenv  4(%esp)                 /* restore original environment */
 
-       addl    $8,%esp
-       cfi_adjust_cfa_offset (-8)
+       addl    $32,%esp
+       cfi_adjust_cfa_offset (-32)
        ret
 END (__floor)
 weak_alias (__floor, floor)
index e969fbe5877b9d7afb5be093626bf50c1422997f..84b6f7ed99cb0e74154828728cb0188304153994 100644 (file)
@@ -9,10 +9,10 @@ RCSID("$NetBSD: s_floorf.S,v 1.3 1995/05/09 00:04:32 jtc Exp $")
 
 ENTRY(__floorf)
        flds    4(%esp)
-       subl    $8,%esp
-       cfi_adjust_cfa_offset (8)
+       subl    $32,%esp
+       cfi_adjust_cfa_offset (32)
 
-       fstcw   4(%esp)                 /* store fpu control word */
+       fnstenv 4(%esp)                 /* store fpu environment */
 
        /* We use here %edx although only the low 1 bits are defined.
           But none of the operations should care and they are faster
@@ -25,10 +25,10 @@ ENTRY(__floorf)
 
        frndint                         /* round */
 
-       fldcw   4(%esp)                 /* restore original control word */
+       fldenv  4(%esp)                 /* restore original environment */
 
-       addl    $8,%esp
-       cfi_adjust_cfa_offset (-8)
+       addl    $32,%esp
+       cfi_adjust_cfa_offset (-32)
        ret
 END (__floorf)
 weak_alias (__floorf, floorf)
index 1206554c4a59f4be70d2de20b23fede67735583c..dc74a0c44682ef8f1b73d255d55cc3f003280941 100644 (file)
@@ -10,10 +10,10 @@ RCSID("$NetBSD: $")
 
 ENTRY(__floorl)
        fldt    4(%esp)
-       subl    $8,%esp
-       cfi_adjust_cfa_offset (8)
+       subl    $32,%esp
+       cfi_adjust_cfa_offset (32)
 
-       fstcw   4(%esp)                 /* store fpu control word */
+       fnstenv 4(%esp)                 /* store fpu environment */
 
        /* We use here %edx although only the low 1 bits are defined.
           But none of the operations should care and they are faster
@@ -26,10 +26,15 @@ ENTRY(__floorl)
 
        frndint                         /* round */
 
-       fldcw   4(%esp)                 /* restore original control word */
+       /* Preserve "invalid" exceptions from sNaN input.  */
+       fnstsw
+       andl    $0x1, %eax
+       orl     %eax, 8(%esp)
 
-       addl    $8,%esp
-       cfi_adjust_cfa_offset (-8)
+       fldenv  4(%esp)                 /* restore original environment */
+
+       addl    $32,%esp
+       cfi_adjust_cfa_offset (-32)
        ret
 END (__floorl)
 weak_alias (__floorl, floorl)
index f9ecc388dfa0333e8d6a824312cf0938968665fc..535fdd8571ce31a51e680ac04066203904d8d4af 100644 (file)
 ENTRY(__floorl)
        fldt    8(%rsp)
 
-       fstcw   -4(%rsp)                /* store fpu control word */
+       fnstenv -28(%rsp)               /* store fpu environment */
 
        /* We use here %edx although only the low 1 bits are defined.
           But none of the operations should care and they are faster
           than the 16 bit operations.  */
        movl    $0x400,%edx             /* round towards -oo */
-       orl     -4(%rsp),%edx
+       orl     -28(%rsp),%edx
        andl    $0xf7ff,%edx
-       movl    %edx,-8(%rsp)
-       fldcw   -8(%rsp)                /* load modified control word */
+       movl    %edx,-32(%rsp)
+       fldcw   -32(%rsp)               /* load modified control word */
 
        frndint                         /* round */
 
-       fldcw   -4(%rsp)                /* restore original control word */
+       /* Preserve "invalid" exceptions from sNaN input.  */
+       fnstsw
+       andl    $0x1, %eax
+       orl     %eax, -24(%rsp)
+
+       fldenv  -28(%rsp)               /* restore original environment */
 
        ret
 END (__floorl)