Refactor x86_64 libm code forcing underflow exceptions.
authorJoseph Myers <joseph@codesourcery.com>
Thu, 24 Sep 2015 22:25:30 +0000 (22:25 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Thu, 24 Sep 2015 22:25:30 +0000 (22:25 +0000)
This patch refactors code in sysdeps/x86_64/fpu that forces underflow
exceptions and closely follows corresponding i386 code to use common
macros in x86_64-math-asm.h for that purpose.  This is mainly about
keeping the code similar to the i386 code as far as possible, since
each macro apart from DEFINE_LDBL_MIN ends up used only once.  It
would be possible to do a further refactoring to share these macros
between i386 and x86_64 (with i386 using the fcomip / fucomip versions
when building for i686 and above), but I have no immediate plans to do
so.

Tested for x86_64.

* sysdeps/x86_64/fpu/x86_64-math-asm.h: New file.
* sysdeps/x86_64/fpu/e_exp2l.S: Include <x86_64-math-asm.h>.
(ldbl_min): Replace with use of DEFINE_LDBL_MIN.
(__ieee754_exp2l): Use LDBL_CHECK_FORCE_UFLOW_NONNEG_NAN.
* sysdeps/x86_64/fpu/e_expl.S: Include <x86_64-math-asm.h>.
[!USE_AS_EXPM1L] (cmin): Replace with use of DEFINE_LDBL_MIN.
(IEEE754_EXPL): Use LDBL_CHECK_FORCE_UFLOW_NONNEG.

ChangeLog
sysdeps/x86_64/fpu/e_exp2l.S
sysdeps/x86_64/fpu/e_expl.S
sysdeps/x86_64/fpu/x86_64-math-asm.h [new file with mode: 0644]

index 851dfc0..4105a9e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2015-09-24  Joseph Myers  <joseph@codesourcery.com>
 
+       * sysdeps/x86_64/fpu/x86_64-math-asm.h: New file.
+       * sysdeps/x86_64/fpu/e_exp2l.S: Include <x86_64-math-asm.h>.
+       (ldbl_min): Replace with use of DEFINE_LDBL_MIN.
+       (__ieee754_exp2l): Use LDBL_CHECK_FORCE_UFLOW_NONNEG_NAN.
+       * sysdeps/x86_64/fpu/e_expl.S: Include <x86_64-math-asm.h>.
+       [!USE_AS_EXPM1L] (cmin): Replace with use of DEFINE_LDBL_MIN.
+       (IEEE754_EXPL): Use LDBL_CHECK_FORCE_UFLOW_NONNEG.
+
        * sysdeps/i386/fpu/e_atanh.S (__ieee754_atanh) [PIC]: Use
        LOAD_PIC_REG.
 
index d634ad3..0e059b7 100644 (file)
@@ -6,13 +6,9 @@
  */
 
 #include <machine/asm.h>
+#include <x86_64-math-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)
+DEFINE_LDBL_MIN
 
 #ifdef PIC
 # define MO(op) op##(%rip)
@@ -50,16 +46,8 @@ ENTRY(__ieee754_exp2l)
        faddp                           /* 2^(fract(x)) */
        fscale                          /* e^x */
        fstp    %st(1)
-       /* 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
+       LDBL_CHECK_FORCE_UFLOW_NONNEG_NAN
+       ret
 
 1:     testl   $0x200, %eax            /* Test sign.  */
        jz      2f                      /* If positive, jump.  */
index 14dd29d..8b3ddae 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include <machine/asm.h>
+#include <x86_64-math-asm.h>
 
 #ifdef USE_AS_EXP10L
 # define IEEE754_EXPL __ieee754_exp10l
@@ -65,10 +66,7 @@ c1:  .byte 0x20, 0xfa, 0xee, 0xc2, 0x5f, 0x70, 0xa5, 0xec, 0xed, 0x3f
 csat:  .byte 0, 0, 0, 0, 0, 0, 0, 0x80, 0x0e, 0x40
        .byte 0, 0, 0, 0, 0, 0
        ASM_SIZE_DIRECTIVE(csat)
-       .type cmin,@object
-cmin:  .byte 0, 0, 0, 0, 0, 0, 0, 0x80, 0x1, 0
-       .byte 0, 0, 0, 0, 0, 0
-       ASM_SIZE_DIRECTIVE(cmin)
+DEFINE_LDBL_MIN
 #endif
 
 #ifdef PIC
@@ -192,17 +190,9 @@ ENTRY(IEEE754_EXPL)
        fstp    %st(1)          /* 2  */
        fscale                  /* 2 scale factor is st(1); base^x */
        fstp    %st(1)          /* 1  */
-       /* Ensure underflow for tiny result.  */
-       fldt    MO(cmin)        /* 2 cmin  */
-       fld     %st(1)          /* 3  */
-       fcomip  %st(1), %st     /* 2  */
-       fstp    %st             /* 1  */
-       jnc     6f
-       fld     %st
-       fmul    %st
-       fstp    %st
+       LDBL_CHECK_FORCE_UFLOW_NONNEG
 #endif
-6:     fstp    %st(1)          /* 0  */
+       fstp    %st(1)          /* 0  */
        jmp     2f
 1:
 #ifdef USE_AS_EXPM1L
diff --git a/sysdeps/x86_64/fpu/x86_64-math-asm.h b/sysdeps/x86_64/fpu/x86_64-math-asm.h
new file mode 100644 (file)
index 0000000..07eecf7
--- /dev/null
@@ -0,0 +1,61 @@
+/* Helper macros for x86_64 libm functions.
+   Copyright (C) 2015 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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _X86_64_MATH_ASM_H
+#define _X86_64_MATH_ASM_H 1
+
+/* Define constants for the minimum value of a floating-point
+   type.  */
+#define DEFINE_LDBL_MIN                                        \
+       .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;                         \
+       .size ldbl_min, .-ldbl_min;
+
+/* Force an underflow exception if the given value (nonnegative or
+   NaN) is subnormal.  The relevant constant for the minimum of the
+   type must have been defined, the MO macro must have been defined
+   for access to memory operands, and, if PIC, the PIC register must
+   have been loaded.  */
+#define LDBL_CHECK_FORCE_UFLOW_NONNEG_NAN      \
+       fldt    MO(ldbl_min);                   \
+       fld     %st(1);                         \
+       fucomip %st(1), %st(0);                 \
+       fstp    %st(0);                         \
+       jnc 6464f;                              \
+       fld     %st(0);                         \
+       fmul    %st(0);                         \
+       fstp    %st(0);                         \
+6464:
+
+/* Likewise, but the argument is nonnegative and not a NaN.  */
+#define LDBL_CHECK_FORCE_UFLOW_NONNEG          \
+       fldt    MO(ldbl_min);                   \
+       fld     %st(1);                         \
+       fcomip  %st(1), %st(0);                 \
+       fstp    %st(0);                         \
+       jnc 6464f;                              \
+       fld     %st(0);                         \
+       fmul    %st(0);                         \
+       fstp    %st(0);                         \
+6464:
+
+#endif /* x86_64-math-asm.h.  */