]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - sysdeps/i386/fpu/i386-math-asm.h
Prefer https to http for gnu.org and fsf.org URLs
[thirdparty/glibc.git] / sysdeps / i386 / fpu / i386-math-asm.h
index fd4313016cd80fa257fadfc0a3aa1b9607cad373..0e98562d5208d802bf7b4d973155c61765b9ebf7 100644 (file)
@@ -1,5 +1,5 @@
 /* Helper macros for x86 libm functions.
-   Copyright (C) 2015 Free Software Foundation, Inc.
+   Copyright (C) 2015-2019 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
@@ -14,7 +14,7 @@
 
    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/>.  */
+   <https://www.gnu.org/licenses/>.  */
 
 #ifndef _I386_MATH_ASM_H
 #define _I386_MATH_ASM_H 1
        addl    $8, %esp;                       \
        cfi_adjust_cfa_offset (-8);
 
+/* Define constants for the minimum value of a floating-point
+   type.  */
+#define DEFINE_FLT_MIN                         \
+       .section .rodata.cst4,"aM",@progbits,4; \
+       .p2align 2;                             \
+       .type flt_min,@object;                  \
+flt_min:                                       \
+       .byte 0, 0, 0x80, 0;                    \
+       .size flt_min, .-flt_min;
+#define DEFINE_DBL_MIN                         \
+       .section .rodata.cst8,"aM",@progbits,8; \
+       .p2align 3;                             \
+       .type dbl_min,@object;                  \
+dbl_min:                                       \
+       .byte 0, 0, 0, 0, 0, 0, 0x10, 0;        \
+       .size dbl_min, .-dbl_min;
+#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;
+
+/* Remove excess range and precision by storing a value on the stack
+   and loading it back.  The value is given to be nonnegative or NaN;
+   if it is subnormal, also force an underflow exception.  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 FLT_NARROW_EVAL_UFLOW_NONNEG_NAN       \
+       subl    $4, %esp;                       \
+       cfi_adjust_cfa_offset (4);              \
+       flds    MO(flt_min);                    \
+       fld     %st(1);                         \
+       fucompp;                                \
+       fnstsw;                                 \
+       sahf;                                   \
+       jnc 6424f;                              \
+       fld     %st(0);                         \
+       fmul    %st(0);                         \
+       fstps   (%esp);                         \
+6424:  fstps   (%esp);                         \
+       flds    (%esp);                         \
+       addl    $4, %esp;                       \
+       cfi_adjust_cfa_offset (-4);
+#define DBL_NARROW_EVAL_UFLOW_NONNEG_NAN       \
+       subl    $8, %esp;                       \
+       cfi_adjust_cfa_offset (8);              \
+       fldl    MO(dbl_min);                    \
+       fld     %st(1);                         \
+       fucompp;                                \
+       fnstsw;                                 \
+       sahf;                                   \
+       jnc 6453f;                              \
+       fld     %st(0);                         \
+       fmul    %st(0);                         \
+       fstpl   (%esp);                         \
+6453:  fstpl   (%esp);                         \
+       fldl    (%esp);                         \
+       addl    $8, %esp;                       \
+       cfi_adjust_cfa_offset (-8);
+
+/* Likewise, but the argument is not a NaN (so fcom instructions,
+   which support memory operands, can be used).  */
+#define FLT_NARROW_EVAL_UFLOW_NONNEG           \
+       subl    $4, %esp;                       \
+       cfi_adjust_cfa_offset (4);              \
+       fcoms   MO(flt_min);                    \
+       fnstsw;                                 \
+       sahf;                                   \
+       jnc 6424f;                              \
+       fld     %st(0);                         \
+       fmul    %st(0);                         \
+       fstps   (%esp);                         \
+6424:  fstps   (%esp);                         \
+       flds    (%esp);                         \
+       addl    $4, %esp;                       \
+       cfi_adjust_cfa_offset (-4);
+#define DBL_NARROW_EVAL_UFLOW_NONNEG           \
+       subl    $8, %esp;                       \
+       cfi_adjust_cfa_offset (8);              \
+       fcoml   MO(dbl_min);                    \
+       fnstsw;                                 \
+       sahf;                                   \
+       jnc 6453f;                              \
+       fld     %st(0);                         \
+       fmul    %st(0);                         \
+       fstpl   (%esp);                         \
+6453:  fstpl   (%esp);                         \
+       fldl    (%esp);                         \
+       addl    $8, %esp;                       \
+       cfi_adjust_cfa_offset (-8);
+
+/* Likewise, but the non-NaN argument may be negative.  */
+#define FLT_NARROW_EVAL_UFLOW_NONNAN           \
+       subl    $4, %esp;                       \
+       cfi_adjust_cfa_offset (4);              \
+       fld     %st(0);                         \
+       fabs;                                   \
+       fcomps  MO(flt_min);                    \
+       fnstsw;                                 \
+       sahf;                                   \
+       jnc 6424f;                              \
+       fld     %st(0);                         \
+       fmul    %st(0);                         \
+       fstps   (%esp);                         \
+6424:  fstps   (%esp);                         \
+       flds    (%esp);                         \
+       addl    $4, %esp;                       \
+       cfi_adjust_cfa_offset (-4);
+#define DBL_NARROW_EVAL_UFLOW_NONNAN           \
+       subl    $8, %esp;                       \
+       cfi_adjust_cfa_offset (8);              \
+       fld     %st(0);                         \
+       fabs;                                   \
+       fcompl  MO(dbl_min);                    \
+       fnstsw;                                 \
+       sahf;                                   \
+       jnc 6453f;                              \
+       fld     %st(0);                         \
+       fmul    %st(0);                         \
+       fstpl   (%esp);                         \
+6453:  fstpl   (%esp);                         \
+       fldl    (%esp);                         \
+       addl    $8, %esp;                       \
+       cfi_adjust_cfa_offset (-8);
+
+/* Force an underflow exception if the given value 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 FLT_CHECK_FORCE_UFLOW                  \
+       flds    MO(flt_min);                    \
+       fld     %st(1);                         \
+       fabs;                                   \
+       fucompp;                                \
+       fnstsw;                                 \
+       sahf;                                   \
+       jnc 6424f;                              \
+       subl    $4, %esp;                       \
+       cfi_adjust_cfa_offset (4);              \
+       fld     %st(0);                         \
+       fmul    %st(0);                         \
+       fstps   (%esp);                         \
+       addl    $4, %esp;                       \
+       cfi_adjust_cfa_offset (-4);             \
+6424:
+#define DBL_CHECK_FORCE_UFLOW                  \
+       fldl    MO(dbl_min);                    \
+       fld     %st(1);                         \
+       fabs;                                   \
+       fucompp;                                \
+       fnstsw;                                 \
+       sahf;                                   \
+       jnc 6453f;                              \
+       subl    $8, %esp;                       \
+       cfi_adjust_cfa_offset (8);              \
+       fld     %st(0);                         \
+       fmul    %st(0);                         \
+       fstpl   (%esp);                         \
+       addl    $8, %esp;                       \
+       cfi_adjust_cfa_offset (-8);             \
+6453:
+
+/* Likewise, but also remove excess range and precision if the value
+   is subnormal.  */
+#define FLT_CHECK_FORCE_UFLOW_NARROW           \
+       flds    MO(flt_min);                    \
+       fld     %st(1);                         \
+       fabs;                                   \
+       fucompp;                                \
+       fnstsw;                                 \
+       sahf;                                   \
+       jnc 6424f;                              \
+       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);             \
+6424:
+#define DBL_CHECK_FORCE_UFLOW_NARROW           \
+       fldl    MO(dbl_min);                    \
+       fld     %st(1);                         \
+       fabs;                                   \
+       fucompp;                                \
+       fnstsw;                                 \
+       sahf;                                   \
+       jnc 6453f;                              \
+       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);             \
+6453:
+
+/* Likewise, but the argument is nonnegative or NaN.  */
+#define LDBL_CHECK_FORCE_UFLOW_NONNEG_NAN      \
+       fldt    MO(ldbl_min);                   \
+       fld     %st(1);                         \
+       fucompp;                                \
+       fnstsw;                                 \
+       sahf;                                   \
+       jnc 6464f;                              \
+       fld     %st(0);                         \
+       fmul    %st(0);                         \
+       fstp    %st(0);                         \
+6464:
+
+/* Likewise, but the argument is not a NaN.  */
+#define FLT_CHECK_FORCE_UFLOW_NONNAN           \
+       fld %st(0);                             \
+       fabs;                                   \
+       fcomps  MO(flt_min);                    \
+       fnstsw;                                 \
+       sahf;                                   \
+       jnc 6424f;                              \
+       subl    $4, %esp;                       \
+       cfi_adjust_cfa_offset (4);              \
+       fld     %st(0);                         \
+       fmul    %st(0);                         \
+       fstps   (%esp);                         \
+       addl    $4, %esp;                       \
+       cfi_adjust_cfa_offset (-4);             \
+6424:
+#define DBL_CHECK_FORCE_UFLOW_NONNAN           \
+       fld %st(0);                             \
+       fabs;                                   \
+       fcompl  MO(dbl_min);                    \
+       fnstsw;                                 \
+       sahf;                                   \
+       jnc 6453f;                              \
+       subl    $8, %esp;                       \
+       cfi_adjust_cfa_offset (8);              \
+       fld     %st(0);                         \
+       fmul    %st(0);                         \
+       fstpl   (%esp);                         \
+       addl    $8, %esp;                       \
+       cfi_adjust_cfa_offset (-8);             \
+6453:
+#define LDBL_CHECK_FORCE_UFLOW_NONNAN          \
+       fldt    MO(ldbl_min);                   \
+       fld     %st(1);                         \
+       fabs;                                   \
+       fcompp;                                 \
+       fnstsw;                                 \
+       sahf;                                   \
+       jnc 6464f;                              \
+       fld     %st(0);                         \
+       fmul    %st(0);                         \
+       fstp    %st(0);                         \
+6464:
+
+/* Likewise, but the argument is nonnegative and not a NaN.  */
+#define FLT_CHECK_FORCE_UFLOW_NONNEG           \
+       fcoms   MO(flt_min);                    \
+       fnstsw;                                 \
+       sahf;                                   \
+       jnc 6424f;                              \
+       subl    $4, %esp;                       \
+       cfi_adjust_cfa_offset (4);              \
+       fld     %st(0);                         \
+       fmul    %st(0);                         \
+       fstps   (%esp);                         \
+       addl    $4, %esp;                       \
+       cfi_adjust_cfa_offset (-4);             \
+6424:
+#define DBL_CHECK_FORCE_UFLOW_NONNEG           \
+       fcoml   MO(dbl_min);                    \
+       fnstsw;                                 \
+       sahf;                                   \
+       jnc 6453f;                              \
+       subl    $8, %esp;                       \
+       cfi_adjust_cfa_offset (8);              \
+       fld     %st(0);                         \
+       fmul    %st(0);                         \
+       fstpl   (%esp);                         \
+       addl    $8, %esp;                       \
+       cfi_adjust_cfa_offset (-8);             \
+6453:
+#define LDBL_CHECK_FORCE_UFLOW_NONNEG          \
+       fldt    MO(ldbl_min);                   \
+       fld     %st(1);                         \
+       fcompp;                                 \
+       fnstsw;                                 \
+       sahf;                                   \
+       jnc 6464f;                              \
+       fld     %st(0);                         \
+       fmul    %st(0);                         \
+       fstp    %st(0);                         \
+6464:
+
 #endif /* i386-math-asm.h.  */