Index: gdb/gnulib/import/fpucw.h |
diff --git a/gdb/gnulib/import/fpucw.h b/gdb/gnulib/import/fpucw.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..23e4c81411805b52a65a40a9de4c932f0727e06e |
--- /dev/null |
+++ b/gdb/gnulib/import/fpucw.h |
@@ -0,0 +1,108 @@ |
+/* Manipulating the FPU control word. |
+ Copyright (C) 2007-2012 Free Software Foundation, Inc. |
+ Written by Bruno Haible <bruno@clisp.org>, 2007. |
+ |
+ This program is free software: you can redistribute it and/or modify |
+ it under the terms of the GNU General Public License as published by |
+ the Free Software Foundation; either version 3 of the License, or |
+ (at your option) any later version. |
+ |
+ This program 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 General Public License for more details. |
+ |
+ You should have received a copy of the GNU General Public License |
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
+ |
+#ifndef _FPUCW_H |
+#define _FPUCW_H |
+ |
+/* The i386 floating point hardware (the 387 compatible FPU, not the modern |
+ SSE/SSE2 hardware) has a controllable rounding precision. It is specified |
+ through the 'PC' bits in the FPU control word ('fctrl' register). (See |
+ the GNU libc i386 <fpu_control.h> header for details.) |
+ |
+ On some platforms, such as Linux or Solaris, the default precision setting |
+ is set to "extended precision". This means that 'long double' instructions |
+ operate correctly, but 'double' computations often produce slightly |
+ different results as on strictly IEEE 754 conforming systems. |
+ |
+ On some platforms, such as NetBSD, the default precision is set to |
+ "double precision". This means that 'long double' instructions will operate |
+ only as 'double', i.e. lead to wrong results. Similarly on FreeBSD 6.4, at |
+ least for the division of 'long double' numbers. |
+ |
+ The FPU control word is under control of the application, i.e. it is |
+ not required to be set either way by the ABI. (In fact, the i386 ABI |
+ http://refspecs.freestandards.org/elf/abi386-4.pdf page 3-12 = page 38 |
+ is not clear about it. But in any case, gcc treats the control word |
+ like a "preserved" register: it emits code that assumes that the control |
+ word is preserved across calls, and it restores the control word at the |
+ end of functions that modify it.) |
+ |
+ See Vincent Lefèvre's page http://www.vinc17.org/research/extended.en.html |
+ for a good explanation. |
+ See http://www.uwsg.iu.edu/hypermail/linux/kernel/0103.0/0453.html for |
+ some argumentation which setting should be the default. */ |
+ |
+/* This header file provides the following facilities: |
+ fpucw_t integral type holding the value of 'fctrl' |
+ FPU_PC_MASK bit mask denoting the precision control |
+ FPU_PC_DOUBLE precision control for 53 bits mantissa |
+ FPU_PC_EXTENDED precision control for 64 bits mantissa |
+ GET_FPUCW () yields the current FPU control word |
+ SET_FPUCW (word) sets the FPU control word |
+ DECL_LONG_DOUBLE_ROUNDING variable declaration for |
+ BEGIN/END_LONG_DOUBLE_ROUNDING |
+ BEGIN_LONG_DOUBLE_ROUNDING () starts a sequence of instructions with |
+ 'long double' safe operation precision |
+ END_LONG_DOUBLE_ROUNDING () ends a sequence of instructions with |
+ 'long double' safe operation precision |
+ */ |
+ |
+/* Inline assembler like this works only with GNU C. */ |
+#if (defined __i386__ || defined __x86_64__) && defined __GNUC__ |
+ |
+typedef unsigned short fpucw_t; /* glibc calls this fpu_control_t */ |
+ |
+# define FPU_PC_MASK 0x0300 |
+# define FPU_PC_DOUBLE 0x200 /* glibc calls this _FPU_DOUBLE */ |
+# define FPU_PC_EXTENDED 0x300 /* glibc calls this _FPU_EXTENDED */ |
+ |
+# define GET_FPUCW() \ |
+ ({ fpucw_t _cw; \ |
+ __asm__ __volatile__ ("fnstcw %0" : "=m" (*&_cw)); \ |
+ _cw; \ |
+ }) |
+# define SET_FPUCW(word) \ |
+ (void)({ fpucw_t _ncw = (word); \ |
+ __asm__ __volatile__ ("fldcw %0" : : "m" (*&_ncw)); \ |
+ }) |
+ |
+# define DECL_LONG_DOUBLE_ROUNDING \ |
+ fpucw_t oldcw; |
+# define BEGIN_LONG_DOUBLE_ROUNDING() \ |
+ (void)(oldcw = GET_FPUCW (), \ |
+ SET_FPUCW ((oldcw & ~FPU_PC_MASK) | FPU_PC_EXTENDED)) |
+# define END_LONG_DOUBLE_ROUNDING() \ |
+ SET_FPUCW (oldcw) |
+ |
+#else |
+ |
+typedef unsigned int fpucw_t; |
+ |
+# define FPU_PC_MASK 0 |
+# define FPU_PC_DOUBLE 0 |
+# define FPU_PC_EXTENDED 0 |
+ |
+# define GET_FPUCW() 0 |
+# define SET_FPUCW(word) (void)(word) |
+ |
+# define DECL_LONG_DOUBLE_ROUNDING |
+# define BEGIN_LONG_DOUBLE_ROUNDING() |
+# define END_LONG_DOUBLE_ROUNDING() |
+ |
+#endif |
+ |
+#endif /* _FPUCW_H */ |