diff options
Diffstat (limited to 'sysdeps/i386/fpu/i386-math-asm.h')
-rw-r--r-- | sysdeps/i386/fpu/i386-math-asm.h | 340 |
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. */ |