Mercurial > gnulib
annotate lib/fpucw.h @ 40186:8964917f9574
autoupdate
author | Karl Berry <karl@freefriends.org> |
---|---|
date | Mon, 18 Feb 2019 08:02:49 -0800 |
parents | b06060465f09 |
children |
rev | line source |
---|---|
18109
244355088b86
maint: add coding cookies to non-ASCII sources
Paul Eggert <eggert@cs.ucla.edu>
parents:
17848
diff
changeset
|
1 /* Manipulating the FPU control word. -*- coding: utf-8 -*- |
40057
b06060465f09
maint: Run 'make update-copyright'
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
2 Copyright (C) 2007-2019 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 | |
19190 | 16 along with this program. If not, see <https://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 | |
16573 | 33 only as 'double', i.e. lead to wrong results. Similarly on FreeBSD 6.4, at |
34 least for the division of 'long double' numbers. | |
8531 | 35 |
36 The FPU control word is under control of the application, i.e. it is | |
37 not required to be set either way by the ABI. (In fact, the i386 ABI | |
19192
d86e08b1f555
all: Replace many more http URLs by https URLs. Update stale URLs.
Bruno Haible <bruno@clisp.org>
parents:
19190
diff
changeset
|
38 https://www.linux-mips.org/pub/linux/mips/doc/ABI/abi386-4.pdf page 3-12 = page 38 |
8531 | 39 is not clear about it. But in any case, gcc treats the control word |
40 like a "preserved" register: it emits code that assumes that the control | |
41 word is preserved across calls, and it restores the control word at the | |
42 end of functions that modify it.) | |
43 | |
19192
d86e08b1f555
all: Replace many more http URLs by https URLs. Update stale URLs.
Bruno Haible <bruno@clisp.org>
parents:
19190
diff
changeset
|
44 See Vincent Lefèvre's page https://www.vinc17.net/research/extended.en.html |
8531 | 45 for a good explanation. |
46 See http://www.uwsg.iu.edu/hypermail/linux/kernel/0103.0/0453.html for | |
47 some argumentation which setting should be the default. */ | |
48 | |
49 /* This header file provides the following facilities: | |
50 fpucw_t integral type holding the value of 'fctrl' | |
51 FPU_PC_MASK bit mask denoting the precision control | |
52 FPU_PC_DOUBLE precision control for 53 bits mantissa | |
53 FPU_PC_EXTENDED precision control for 64 bits mantissa | |
54 GET_FPUCW () yields the current FPU control word | |
55 SET_FPUCW (word) sets the FPU control word | |
56 DECL_LONG_DOUBLE_ROUNDING variable declaration for | |
57 BEGIN/END_LONG_DOUBLE_ROUNDING | |
58 BEGIN_LONG_DOUBLE_ROUNDING () starts a sequence of instructions with | |
59 'long double' safe operation precision | |
60 END_LONG_DOUBLE_ROUNDING () ends a sequence of instructions with | |
61 'long double' safe operation precision | |
62 */ | |
63 | |
64 /* 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
|
65 #if (defined __i386__ || defined __x86_64__) && defined __GNUC__ |
8531 | 66 |
67 typedef unsigned short fpucw_t; /* glibc calls this fpu_control_t */ | |
68 | |
69 # define FPU_PC_MASK 0x0300 | |
70 # define FPU_PC_DOUBLE 0x200 /* glibc calls this _FPU_DOUBLE */ | |
71 # define FPU_PC_EXTENDED 0x300 /* glibc calls this _FPU_EXTENDED */ | |
72 | |
73 # define GET_FPUCW() \ | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9904
diff
changeset
|
74 ({ fpucw_t _cw; \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9904
diff
changeset
|
75 __asm__ __volatile__ ("fnstcw %0" : "=m" (*&_cw)); \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9904
diff
changeset
|
76 _cw; \ |
8531 | 77 }) |
78 # define SET_FPUCW(word) \ | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9904
diff
changeset
|
79 (void)({ fpucw_t _ncw = (word); \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9904
diff
changeset
|
80 __asm__ __volatile__ ("fldcw %0" : : "m" (*&_ncw)); \ |
8531 | 81 }) |
82 | |
83 # define DECL_LONG_DOUBLE_ROUNDING \ | |
84 fpucw_t oldcw; | |
85 # define BEGIN_LONG_DOUBLE_ROUNDING() \ | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9904
diff
changeset
|
86 (void)(oldcw = GET_FPUCW (), \ |
8531 | 87 SET_FPUCW ((oldcw & ~FPU_PC_MASK) | FPU_PC_EXTENDED)) |
88 # define END_LONG_DOUBLE_ROUNDING() \ | |
89 SET_FPUCW (oldcw) | |
90 | |
91 #else | |
92 | |
93 typedef unsigned int fpucw_t; | |
94 | |
95 # define FPU_PC_MASK 0 | |
96 # define FPU_PC_DOUBLE 0 | |
97 # define FPU_PC_EXTENDED 0 | |
98 | |
99 # define GET_FPUCW() 0 | |
100 # define SET_FPUCW(word) (void)(word) | |
101 | |
102 # define DECL_LONG_DOUBLE_ROUNDING | |
103 # define BEGIN_LONG_DOUBLE_ROUNDING() | |
104 # define END_LONG_DOUBLE_ROUNDING() | |
105 | |
106 #endif | |
107 | |
108 #endif /* _FPUCW_H */ |