Mercurial > hg > octave-nkf > gnulib-hg
annotate lib/fpucw.h @ 16201:8250f2777afc
maint: update all copyright year number ranges
Run "make update-copyright".
author | Jim Meyering <meyering@redhat.com> |
---|---|
date | Sun, 01 Jan 2012 10:04:58 +0100 |
parents | 97fc9a21a8fb |
children | 99dddd1393e9 |
rev | line source |
---|---|
8531 | 1 /* Manipulating the FPU control word. |
16201
8250f2777afc
maint: update all copyright year number ranges
Jim Meyering <meyering@redhat.com>
parents:
14079
diff
changeset
|
2 Copyright (C) 2007-2012 Free Software Foundation, Inc. |
8531 | 3 Written by Bruno Haible <bruno@clisp.org>, 2007. |
4 | |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8531
diff
changeset
|
5 This program is free software: you can redistribute it and/or modify |
8531 | 6 it under the terms of the GNU General Public License as published by |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8531
diff
changeset
|
7 the Free Software Foundation; either version 3 of the License, or |
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8531
diff
changeset
|
8 (at your option) any later version. |
8531 | 9 |
10 This program is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 GNU General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU General Public License | |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8531
diff
changeset
|
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
8531 | 17 |
18 #ifndef _FPUCW_H | |
19 #define _FPUCW_H | |
20 | |
21 /* The i386 floating point hardware (the 387 compatible FPU, not the modern | |
22 SSE/SSE2 hardware) has a controllable rounding precision. It is specified | |
23 through the 'PC' bits in the FPU control word ('fctrl' register). (See | |
24 the GNU libc i386 <fpu_control.h> header for details.) | |
25 | |
26 On some platforms, such as Linux or Solaris, the default precision setting | |
27 is set to "extended precision". This means that 'long double' instructions | |
28 operate correctly, but 'double' computations often produce slightly | |
29 different results as on strictly IEEE 754 conforming systems. | |
30 | |
31 On some platforms, such as NetBSD, the default precision is set to | |
32 "double precision". This means that 'long double' instructions will operate | |
33 only as 'double', i.e. lead wrong results. | |
34 | |
35 The FPU control word is under control of the application, i.e. it is | |
36 not required to be set either way by the ABI. (In fact, the i386 ABI | |
37 http://refspecs.freestandards.org/elf/abi386-4.pdf page 3-12 = page 38 | |
38 is not clear about it. But in any case, gcc treats the control word | |
39 like a "preserved" register: it emits code that assumes that the control | |
40 word is preserved across calls, and it restores the control word at the | |
41 end of functions that modify it.) | |
42 | |
43 See Vincent Lefèvre's page http://www.vinc17.org/research/extended.en.html | |
44 for a good explanation. | |
45 See http://www.uwsg.iu.edu/hypermail/linux/kernel/0103.0/0453.html for | |
46 some argumentation which setting should be the default. */ | |
47 | |
48 /* This header file provides the following facilities: | |
49 fpucw_t integral type holding the value of 'fctrl' | |
50 FPU_PC_MASK bit mask denoting the precision control | |
51 FPU_PC_DOUBLE precision control for 53 bits mantissa | |
52 FPU_PC_EXTENDED precision control for 64 bits mantissa | |
53 GET_FPUCW () yields the current FPU control word | |
54 SET_FPUCW (word) sets the FPU control word | |
55 DECL_LONG_DOUBLE_ROUNDING variable declaration for | |
56 BEGIN/END_LONG_DOUBLE_ROUNDING | |
57 BEGIN_LONG_DOUBLE_ROUNDING () starts a sequence of instructions with | |
58 'long double' safe operation precision | |
59 END_LONG_DOUBLE_ROUNDING () ends a sequence of instructions with | |
60 'long double' safe operation precision | |
61 */ | |
62 | |
63 /* Inline assembler like this works only with GNU C. */ | |
9904
d4e2e7579bab
Enable the fpucw handling also for x86_64.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
64 #if (defined __i386__ || defined __x86_64__) && defined __GNUC__ |
8531 | 65 |
66 typedef unsigned short fpucw_t; /* glibc calls this fpu_control_t */ | |
67 | |
68 # define FPU_PC_MASK 0x0300 | |
69 # define FPU_PC_DOUBLE 0x200 /* glibc calls this _FPU_DOUBLE */ | |
70 # define FPU_PC_EXTENDED 0x300 /* glibc calls this _FPU_EXTENDED */ | |
71 | |
72 # define GET_FPUCW() \ | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9904
diff
changeset
|
73 ({ fpucw_t _cw; \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9904
diff
changeset
|
74 __asm__ __volatile__ ("fnstcw %0" : "=m" (*&_cw)); \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9904
diff
changeset
|
75 _cw; \ |
8531 | 76 }) |
77 # define SET_FPUCW(word) \ | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9904
diff
changeset
|
78 (void)({ fpucw_t _ncw = (word); \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9904
diff
changeset
|
79 __asm__ __volatile__ ("fldcw %0" : : "m" (*&_ncw)); \ |
8531 | 80 }) |
81 | |
82 # define DECL_LONG_DOUBLE_ROUNDING \ | |
83 fpucw_t oldcw; | |
84 # define BEGIN_LONG_DOUBLE_ROUNDING() \ | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9904
diff
changeset
|
85 (void)(oldcw = GET_FPUCW (), \ |
8531 | 86 SET_FPUCW ((oldcw & ~FPU_PC_MASK) | FPU_PC_EXTENDED)) |
87 # define END_LONG_DOUBLE_ROUNDING() \ | |
88 SET_FPUCW (oldcw) | |
89 | |
90 #else | |
91 | |
92 typedef unsigned int fpucw_t; | |
93 | |
94 # define FPU_PC_MASK 0 | |
95 # define FPU_PC_DOUBLE 0 | |
96 # define FPU_PC_EXTENDED 0 | |
97 | |
98 # define GET_FPUCW() 0 | |
99 # define SET_FPUCW(word) (void)(word) | |
100 | |
101 # define DECL_LONG_DOUBLE_ROUNDING | |
102 # define BEGIN_LONG_DOUBLE_ROUNDING() | |
103 # define END_LONG_DOUBLE_ROUNDING() | |
104 | |
105 #endif | |
106 | |
107 #endif /* _FPUCW_H */ |