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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3 Written by Bruno Haible <bruno@clisp.org>, 2007.
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
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
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
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
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
9
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
10 This program is distributed in the hope that it will be useful,
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
13 GNU General Public License for more details.
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
14
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
15 You should have received a copy of the GNU General Public License
19190
9759915b2aca all: prefer https: URLs
Paul Eggert <eggert@cs.ucla.edu>
parents: 18626
diff changeset
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
8531
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
17
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
18 #ifndef _FPUCW_H
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
19 #define _FPUCW_H
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
20
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
21 /* The i386 floating point hardware (the 387 compatible FPU, not the modern
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
22 SSE/SSE2 hardware) has a controllable rounding precision. It is specified
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
23 through the 'PC' bits in the FPU control word ('fctrl' register). (See
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
24 the GNU libc i386 <fpu_control.h> header for details.)
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
25
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
26 On some platforms, such as Linux or Solaris, the default precision setting
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
27 is set to "extended precision". This means that 'long double' instructions
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
28 operate correctly, but 'double' computations often produce slightly
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
29 different results as on strictly IEEE 754 conforming systems.
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
30
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
31 On some platforms, such as NetBSD, the default precision is set to
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
32 "double precision". This means that 'long double' instructions will operate
16573
99dddd1393e9 fpucw: Doc about FreeBSD.
Bruno Haible <bruno@clisp.org>
parents: 16201
diff changeset
33 only as 'double', i.e. lead to wrong results. Similarly on FreeBSD 6.4, at
99dddd1393e9 fpucw: Doc about FreeBSD.
Bruno Haible <bruno@clisp.org>
parents: 16201
diff changeset
34 least for the division of 'long double' numbers.
8531
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
35
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
36 The FPU control word is under control of the application, i.e. it is
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
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
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
39 is not clear about it. But in any case, gcc treats the control word
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
40 like a "preserved" register: it emits code that assumes that the control
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
41 word is preserved across calls, and it restores the control word at the
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
42 end of functions that modify it.)
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
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
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
45 for a good explanation.
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
46 See http://www.uwsg.iu.edu/hypermail/linux/kernel/0103.0/0453.html for
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
47 some argumentation which setting should be the default. */
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
48
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
49 /* This header file provides the following facilities:
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
50 fpucw_t integral type holding the value of 'fctrl'
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
51 FPU_PC_MASK bit mask denoting the precision control
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
52 FPU_PC_DOUBLE precision control for 53 bits mantissa
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
53 FPU_PC_EXTENDED precision control for 64 bits mantissa
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
54 GET_FPUCW () yields the current FPU control word
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
55 SET_FPUCW (word) sets the FPU control word
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
56 DECL_LONG_DOUBLE_ROUNDING variable declaration for
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
57 BEGIN/END_LONG_DOUBLE_ROUNDING
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
58 BEGIN_LONG_DOUBLE_ROUNDING () starts a sequence of instructions with
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
59 'long double' safe operation precision
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
60 END_LONG_DOUBLE_ROUNDING () ends a sequence of instructions with
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
61 'long double' safe operation precision
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
62 */
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
63
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
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
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
66
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
67 typedef unsigned short fpucw_t; /* glibc calls this fpu_control_t */
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
68
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
69 # define FPU_PC_MASK 0x0300
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
70 # define FPU_PC_DOUBLE 0x200 /* glibc calls this _FPU_DOUBLE */
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
71 # define FPU_PC_EXTENDED 0x300 /* glibc calls this _FPU_EXTENDED */
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
72
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
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
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
77 })
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
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
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
81 })
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
82
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
83 # define DECL_LONG_DOUBLE_ROUNDING \
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
84 fpucw_t oldcw;
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
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
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
87 SET_FPUCW ((oldcw & ~FPU_PC_MASK) | FPU_PC_EXTENDED))
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
88 # define END_LONG_DOUBLE_ROUNDING() \
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
89 SET_FPUCW (oldcw)
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
90
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
91 #else
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
92
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
93 typedef unsigned int fpucw_t;
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
94
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
95 # define FPU_PC_MASK 0
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
96 # define FPU_PC_DOUBLE 0
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
97 # define FPU_PC_EXTENDED 0
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
98
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
99 # define GET_FPUCW() 0
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
100 # define SET_FPUCW(word) (void)(word)
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
101
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
102 # define DECL_LONG_DOUBLE_ROUNDING
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
103 # define BEGIN_LONG_DOUBLE_ROUNDING()
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
104 # define END_LONG_DOUBLE_ROUNDING()
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
105
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
106 #endif
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
107
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
108 #endif /* _FPUCW_H */