aboutsummaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/i386/fpu/e_exp2.S34
-rw-r--r--sysdeps/i386/fpu/e_exp2f.S34
-rw-r--r--sysdeps/i386/fpu/e_exp2l.S29
-rw-r--r--sysdeps/ieee754/dbl-64/e_exp2.c10
-rw-r--r--sysdeps/ieee754/flt-32/e_exp2f.c10
-rw-r--r--sysdeps/x86_64/fpu/e_exp2l.S25
6 files changed, 136 insertions, 6 deletions
diff --git a/sysdeps/i386/fpu/e_exp2.S b/sysdeps/i386/fpu/e_exp2.S
index f802cf8b98..b75a63a0b3 100644
--- a/sysdeps/i386/fpu/e_exp2.S
+++ b/sysdeps/i386/fpu/e_exp2.S
@@ -6,7 +6,24 @@
#include <machine/asm.h>
+ .section .rodata.cst8,"aM",@progbits,8
+
+ .p2align 3
+ .type dbl_min,@object
+dbl_min: .byte 0, 0, 0, 0, 0, 0, 0x10, 0
+ ASM_SIZE_DIRECTIVE(dbl_min)
+
+#ifdef PIC
+# define MO(op) op##@GOTOFF(%ecx)
+#else
+# define MO(op) op
+#endif
+
+ .text
ENTRY(__ieee754_exp2)
+#ifdef PIC
+ LOAD_PIC_REG (cx)
+#endif
fldl 4(%esp)
/* I added the following ugly construct because exp(+-Inf) resulted
in NaN. The ugliness results from the bright minds at Intel.
@@ -27,7 +44,22 @@ ENTRY(__ieee754_exp2)
faddp /* 2^(fract(x)) */
fscale /* e^x */
fstp %st(1)
- ret
+ fldl MO(dbl_min)
+ fld %st(1)
+ fucompp
+ fnstsw
+ sahf
+ jnc 3f
+ subl $8, %esp
+ cfi_adjust_cfa_offset (8)
+ fld %st(0)
+ fmul %st(0)
+ fstpl (%esp)
+ fstpl (%esp)
+ fldl (%esp)
+ addl $8, %esp
+ cfi_adjust_cfa_offset (-8)
+3: ret
1: testl $0x200, %eax /* Test sign. */
jz 2f /* If positive, jump. */
diff --git a/sysdeps/i386/fpu/e_exp2f.S b/sysdeps/i386/fpu/e_exp2f.S
index f867d0d472..042c83b1ef 100644
--- a/sysdeps/i386/fpu/e_exp2f.S
+++ b/sysdeps/i386/fpu/e_exp2f.S
@@ -6,7 +6,24 @@
#include <machine/asm.h>
+ .section .rodata.cst4,"aM",@progbits,4
+
+ .p2align 2
+ .type flt_min,@object
+flt_min: .byte 0, 0, 0x80, 0
+ ASM_SIZE_DIRECTIVE(flt_min)
+
+#ifdef PIC
+# define MO(op) op##@GOTOFF(%ecx)
+#else
+# define MO(op) op
+#endif
+
+ .text
ENTRY(__ieee754_exp2f)
+#ifdef PIC
+ LOAD_PIC_REG (cx)
+#endif
flds 4(%esp)
/* I added the following ugly construct because exp(+-Inf) resulted
in NaN. The ugliness results from the bright minds at Intel.
@@ -27,7 +44,22 @@ ENTRY(__ieee754_exp2f)
faddp /* 2^(fract(x)) */
fscale /* e^x */
fstp %st(1)
- ret
+ flds MO(flt_min)
+ fld %st(1)
+ fucompp
+ fnstsw
+ sahf
+ jnc 3f
+ subl $4, %esp
+ cfi_adjust_cfa_offset (4)
+ fld %st(0)
+ fmul %st(0)
+ fstps (%esp)
+ fstps (%esp)
+ flds (%esp)
+ addl $4, %esp
+ cfi_adjust_cfa_offset (-4)
+3: ret
1: testl $0x200, %eax /* Test sign. */
jz 2f /* If positive, jump. */
diff --git a/sysdeps/i386/fpu/e_exp2l.S b/sysdeps/i386/fpu/e_exp2l.S
index 2bf9a25727..9a5ff95a6c 100644
--- a/sysdeps/i386/fpu/e_exp2l.S
+++ b/sysdeps/i386/fpu/e_exp2l.S
@@ -6,7 +6,24 @@
#include <machine/asm.h>
+ .section .rodata.cst16,"aM",@progbits,16
+ .p2align 4
+ .type ldbl_min,@object
+ldbl_min: .byte 0, 0, 0, 0, 0, 0, 0, 0x80, 0x1, 0
+ .byte 0, 0, 0, 0, 0, 0
+ ASM_SIZE_DIRECTIVE(ldbl_min)
+
+#ifdef PIC
+# define MO(op) op##@GOTOFF(%ecx)
+#else
+# define MO(op) op
+#endif
+
+ .text
ENTRY(__ieee754_exp2l)
+#ifdef PIC
+ LOAD_PIC_REG (cx)
+#endif
fldt 4(%esp)
/* I added the following ugly construct because exp(+-Inf) resulted
in NaN. The ugliness results from the bright minds at Intel.
@@ -35,7 +52,17 @@ ENTRY(__ieee754_exp2l)
faddp /* 2^(fract(x)) */
fscale /* e^x */
fstp %st(1)
- ret
+ /* Ensure underflow for tiny result. */
+ fldt MO(ldbl_min)
+ fld %st(1)
+ fucompp
+ fnstsw
+ sahf
+ jnc 4f
+ fld %st
+ fmul %st
+ fstp %st
+4: ret
1: testl $0x200, %eax /* Test sign. */
jz 2f /* If positive, jump. */
diff --git a/sysdeps/ieee754/dbl-64/e_exp2.c b/sysdeps/ieee754/dbl-64/e_exp2.c
index 30f0a8f529..01df62150d 100644
--- a/sysdeps/ieee754/dbl-64/e_exp2.c
+++ b/sysdeps/ieee754/dbl-64/e_exp2.c
@@ -120,7 +120,15 @@ __ieee754_exp2 (double x)
if (!unsafe)
return result;
else
- return result * scale_u.d;
+ {
+ result *= scale_u.d;
+ if (result < DBL_MIN)
+ {
+ double force_underflow = result * result;
+ math_force_eval (force_underflow);
+ }
+ return result;
+ }
}
else
/* Return x, if x is a NaN or Inf; or overflow, otherwise. */
diff --git a/sysdeps/ieee754/flt-32/e_exp2f.c b/sysdeps/ieee754/flt-32/e_exp2f.c
index 0b75a7ea2a..bc62042966 100644
--- a/sysdeps/ieee754/flt-32/e_exp2f.c
+++ b/sysdeps/ieee754/flt-32/e_exp2f.c
@@ -109,7 +109,15 @@ __ieee754_exp2f (float x)
if (!unsafe)
return result;
else
- return result * scale_u.f;
+ {
+ result *= scale_u.f;
+ if (result < FLT_MIN)
+ {
+ float force_underflow = result * result;
+ math_force_eval (force_underflow);
+ }
+ return result;
+ }
}
/* Exceptional cases: */
else if (isless (x, himark))
diff --git a/sysdeps/x86_64/fpu/e_exp2l.S b/sysdeps/x86_64/fpu/e_exp2l.S
index 7d42a932db..d634ad38f8 100644
--- a/sysdeps/x86_64/fpu/e_exp2l.S
+++ b/sysdeps/x86_64/fpu/e_exp2l.S
@@ -7,6 +7,20 @@
#include <machine/asm.h>
+ .section .rodata.cst16,"aM",@progbits,16
+ .p2align 4
+ .type ldbl_min,@object
+ldbl_min: .byte 0, 0, 0, 0, 0, 0, 0, 0x80, 0x1, 0
+ .byte 0, 0, 0, 0, 0, 0
+ ASM_SIZE_DIRECTIVE(ldbl_min)
+
+#ifdef PIC
+# define MO(op) op##(%rip)
+#else
+# define MO(op) op
+#endif
+
+ .text
ENTRY(__ieee754_exp2l)
fldt 8(%rsp)
/* I added the following ugly construct because exp(+-Inf) resulted
@@ -36,7 +50,16 @@ ENTRY(__ieee754_exp2l)
faddp /* 2^(fract(x)) */
fscale /* e^x */
fstp %st(1)
- ret
+ /* Ensure underflow for tiny result. */
+ fldt MO(ldbl_min)
+ fld %st(1)
+ fucomip %st(1), %st
+ fstp %st
+ jnc 4f
+ fld %st
+ fmul %st
+ fstp %st
+4: ret
1: testl $0x200, %eax /* Test sign. */
jz 2f /* If positive, jump. */