summaryrefslogtreecommitdiff
path: root/sysdeps/i386/fpu/i386-math-asm.h
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/i386/fpu/i386-math-asm.h')
-rw-r--r--sysdeps/i386/fpu/i386-math-asm.h340
1 files changed, 340 insertions, 0 deletions
diff --git a/sysdeps/i386/fpu/i386-math-asm.h b/sysdeps/i386/fpu/i386-math-asm.h
new file mode 100644
index 0000000000..20307d3a4a
--- /dev/null
+++ b/sysdeps/i386/fpu/i386-math-asm.h
@@ -0,0 +1,340 @@
+/* Helper macros for x86 libm functions.
+ Copyright (C) 2015-2016 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 _I386_MATH_ASM_H
+#define _I386_MATH_ASM_H 1
+
+/* Remove excess range and precision by storing a value on the stack
+ and loading it back. */
+#define FLT_NARROW_EVAL \
+ subl $4, %esp; \
+ cfi_adjust_cfa_offset (4); \
+ fstps (%esp); \
+ flds (%esp); \
+ addl $4, %esp; \
+ cfi_adjust_cfa_offset (-4);
+#define DBL_NARROW_EVAL \
+ subl $8, %esp; \
+ cfi_adjust_cfa_offset (8); \
+ fstpl (%esp); \
+ fldl (%esp); \
+ 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. */