diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2012-06-06 10:13:19 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2012-06-06 10:13:19 -0700 |
commit | c08010c7cdea229bc3b27ecf42855d32daffd71e (patch) | |
tree | d72c9b4e9d966679ced05a0b2e922b3b3fbcc2a5 /sysdeps/x86/fpu/bits | |
parent | a728a38fb658f8b2f0acbea8a586db8bd054f3fe (diff) | |
download | glibc-c08010c7cdea229bc3b27ecf42855d32daffd71e.tar.gz glibc-c08010c7cdea229bc3b27ecf42855d32daffd71e.tar.xz glibc-c08010c7cdea229bc3b27ecf42855d32daffd71e.zip |
Use x86_64 fpu/bits/fenv.h for i386 and x86_64
Diffstat (limited to 'sysdeps/x86/fpu/bits')
-rw-r--r-- | sysdeps/x86/fpu/bits/fenv.h | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/sysdeps/x86/fpu/bits/fenv.h b/sysdeps/x86/fpu/bits/fenv.h new file mode 100644 index 0000000000..b2c01c403f --- /dev/null +++ b/sysdeps/x86/fpu/bits/fenv.h @@ -0,0 +1,141 @@ +/* Copyright (C) 1997-2012 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 _FENV_H +# error "Never use <bits/fenv.h> directly; include <fenv.h> instead." +#endif + +/* Define bits representing the exception. We use the bit positions + of the appropriate bits in the FPU control word. */ +enum + { + FE_INVALID = 0x01, +#define FE_INVALID FE_INVALID + __FE_DENORM = 0x02, + FE_DIVBYZERO = 0x04, +#define FE_DIVBYZERO FE_DIVBYZERO + FE_OVERFLOW = 0x08, +#define FE_OVERFLOW FE_OVERFLOW + FE_UNDERFLOW = 0x10, +#define FE_UNDERFLOW FE_UNDERFLOW + FE_INEXACT = 0x20 +#define FE_INEXACT FE_INEXACT + }; + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* The ix87 FPU supports all of the four defined rounding modes. We + use again the bit positions in the FPU control word as the values + for the appropriate macros. */ +enum + { + FE_TONEAREST = 0, +#define FE_TONEAREST FE_TONEAREST + FE_DOWNWARD = 0x400, +#define FE_DOWNWARD FE_DOWNWARD + FE_UPWARD = 0x800, +#define FE_UPWARD FE_UPWARD + FE_TOWARDZERO = 0xc00 +#define FE_TOWARDZERO FE_TOWARDZERO + }; + + +/* Type representing exception flags. */ +typedef unsigned short int fexcept_t; + + +/* Type representing floating-point environment. This structure + corresponds to the layout of the block written by the `fstenv' + instruction and has additional fields for the contents of the MXCSR + register as written by the `stmxcsr' instruction. */ +typedef struct + { + unsigned short int __control_word; + unsigned short int __unused1; + unsigned short int __status_word; + unsigned short int __unused2; + unsigned short int __tags; + unsigned short int __unused3; + unsigned int __eip; + unsigned short int __cs_selector; + unsigned int __opcode:11; + unsigned int __unused4:5; + unsigned int __data_offset; + unsigned short int __data_selector; + unsigned short int __unused5; +#ifdef __x86_64__ + unsigned int __mxcsr; +#endif + } +fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((const fenv_t *) -1) + +#ifdef __USE_GNU +/* Floating-point environment where none of the exception is masked. */ +# define FE_NOMASK_ENV ((const fenv_t *) -2) +#endif + + +#ifdef __USE_EXTERN_INLINES +__BEGIN_DECLS + +/* Optimized versions. */ +extern int __REDIRECT_NTH (__feraiseexcept_renamed, (int), feraiseexcept); +__extern_inline int +__NTH (feraiseexcept (int __excepts)) +{ + if (__builtin_constant_p (__excepts) + && (__excepts & ~(FE_INVALID | FE_DIVBYZERO)) == 0) + { + if ((FE_INVALID & __excepts) != 0) + { + /* One example of a invalid operation is 0.0 / 0.0. */ + float __f = 0.0; + +# ifdef __SSE_MATH__ + __asm__ __volatile__ ("divss %0, %0 " : : "x" (__f)); +# else + __asm__ __volatile__ ("fdiv %%st, %%st(0); fwait" + : "=t" (__f) : "0" (__f)); +# endif + (void) &__f; + } + if ((FE_DIVBYZERO & __excepts) != 0) + { + float __f = 1.0; + float __g = 0.0; + +# ifdef __SSE_MATH__ + __asm__ __volatile__ ("divss %1, %0" : : "x" (__f), "x" (__g)); +# else + __asm__ __volatile__ ("fdivp %%st, %%st(1); fwait" + : "=t" (__f) : "0" (__f), "u" (__g) : "st(1)"); +# endif + (void) &__f; + } + + return 0; + } + + return __feraiseexcept_renamed (__excepts); +} + +__END_DECLS +#endif |