aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/i386
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2024-04-03 16:39:17 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2024-04-04 14:29:28 -0300
commit637bfc392f406c6c77f59494ed34949a6161bceb (patch)
tree5a34cc9cca8f4f0670e1be613bf5bc66f9e80cb0 /sysdeps/i386
parent87cb1dfcd6d1acbcd695279d7abd9163a0cc64fc (diff)
downloadglibc-637bfc392f406c6c77f59494ed34949a6161bceb.zip
glibc-637bfc392f406c6c77f59494ed34949a6161bceb.tar.gz
glibc-637bfc392f406c6c77f59494ed34949a6161bceb.tar.bz2
math: x86 ceill traps when FE_INEXACT is enabled (BZ 31600)
The implementations of ceil functions using x87 floating point (i386 and x86_64 long double only) traps when FE_INEXACT is enabled. Although this is a GNU extension outside the scope of the C standard, other architectures that also support traps do not show this behavior. The fix moves the implementation to a common one that holds any exceptions with a 'fnclex' (libc_feholdexcept_setround_387). Checked on x86_64-linux-gnu and i686-linux-gnu. Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
Diffstat (limited to 'sysdeps/i386')
-rw-r--r--sysdeps/i386/fpu/s_ceil.S34
-rw-r--r--sysdeps/i386/fpu/s_ceil.c25
-rw-r--r--sysdeps/i386/fpu/s_ceilf.S34
-rw-r--r--sysdeps/i386/fpu/s_ceilf.c25
-rw-r--r--sysdeps/i386/fpu/s_ceill.S39
5 files changed, 50 insertions, 107 deletions
diff --git a/sysdeps/i386/fpu/s_ceil.S b/sysdeps/i386/fpu/s_ceil.S
deleted file mode 100644
index 99984f9..0000000
--- a/sysdeps/i386/fpu/s_ceil.S
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Public domain.
- */
-
-#include <machine/asm.h>
-#include <libm-alias-double.h>
-
-RCSID("$NetBSD: s_ceil.S,v 1.4 1995/05/08 23:52:13 jtc Exp $")
-
-ENTRY(__ceil)
- fldl 4(%esp)
- subl $32,%esp
- cfi_adjust_cfa_offset (32)
-
- 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
- than the 16 bit operations. */
- movl $0x0800,%edx /* round towards +oo */
- orl 4(%esp),%edx
- andl $0xfbff,%edx
- movl %edx,(%esp)
- fldcw (%esp) /* load modified control word */
-
- frndint /* round */
-
- fldenv 4(%esp) /* restore original environment */
-
- addl $32,%esp
- cfi_adjust_cfa_offset (-32)
- ret
-END (__ceil)
-libm_alias_double (__ceil, ceil)
diff --git a/sysdeps/i386/fpu/s_ceil.c b/sysdeps/i386/fpu/s_ceil.c
new file mode 100644
index 0000000..349135c
--- /dev/null
+++ b/sysdeps/i386/fpu/s_ceil.c
@@ -0,0 +1,25 @@
+/* Return smallest integral value not less than argument. i386 version.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <libm-alias-double.h>
+
+#define FUNC __ceil
+#define TYPE double
+#define FE_OPTION FE_UPWARD
+#include "s_nearestint_387_template.c"
+libm_alias_double (__ceil, ceil)
diff --git a/sysdeps/i386/fpu/s_ceilf.S b/sysdeps/i386/fpu/s_ceilf.S
deleted file mode 100644
index 03e8e22..0000000
--- a/sysdeps/i386/fpu/s_ceilf.S
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Public domain.
- */
-
-#include <machine/asm.h>
-#include <libm-alias-float.h>
-
-RCSID("$NetBSD: s_ceilf.S,v 1.3 1995/05/08 23:52:44 jtc Exp $")
-
-ENTRY(__ceilf)
- flds 4(%esp)
- subl $32,%esp
- cfi_adjust_cfa_offset (32)
-
- 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
- than the 16 bit operations. */
- movl $0x0800,%edx /* round towards +oo */
- orl 4(%esp),%edx
- andl $0xfbff,%edx
- movl %edx,(%esp)
- fldcw (%esp) /* load modified control word */
-
- frndint /* round */
-
- fldenv 4(%esp) /* restore original environment */
-
- addl $32,%esp
- cfi_adjust_cfa_offset (-32)
- ret
-END (__ceilf)
-libm_alias_float (__ceil, ceil)
diff --git a/sysdeps/i386/fpu/s_ceilf.c b/sysdeps/i386/fpu/s_ceilf.c
new file mode 100644
index 0000000..e73a20f
--- /dev/null
+++ b/sysdeps/i386/fpu/s_ceilf.c
@@ -0,0 +1,25 @@
+/* Return largest integral value not less than argument. i386 version.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <libm-alias-float.h>
+
+#define FUNC __ceilf
+#define TYPE float
+#define FE_OPTION FE_UPWARD
+#include "s_nearestint_387_template.c"
+libm_alias_float (__ceil, ceil)
diff --git a/sysdeps/i386/fpu/s_ceill.S b/sysdeps/i386/fpu/s_ceill.S
deleted file mode 100644
index a551fce..0000000
--- a/sysdeps/i386/fpu/s_ceill.S
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Public domain.
- */
-
-#include <libm-alias-ldouble.h>
-#include <machine/asm.h>
-
-RCSID("$NetBSD: $")
-
-ENTRY(__ceill)
- fldt 4(%esp)
- subl $32,%esp
- cfi_adjust_cfa_offset (32)
-
- 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
- than the 16 bit operations. */
- movl $0x0800,%edx /* round towards +oo */
- orl 4(%esp),%edx
- andl $0xfbff,%edx
- movl %edx,(%esp)
- fldcw (%esp) /* load modified control word */
-
- frndint /* round */
-
- /* Preserve "invalid" exceptions from sNaN input. */
- fnstsw
- andl $0x1, %eax
- orl %eax, 8(%esp)
-
- fldenv 4(%esp) /* restore original environment */
-
- addl $32,%esp
- cfi_adjust_cfa_offset (-32)
- ret
-END (__ceill)
-libm_alias_ldouble (__ceil, ceil)