~ubuntu-branches/ubuntu/vivid/gzip/vivid

« back to all changes in this revision

Viewing changes to lib/fpucw.h

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-10-19 11:42:42 UTC
  • mfrom: (4.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20111019114242-d8wiiu8kbvdtgmgj
Tags: 1.4-1ubuntu1
* Merge with Debian testing.  Remaining Ubuntu changes:
  - debian/{control,rules}: Remove the Win32 build and mingw64
    build-dependency, since mingw is in universe, and will remain so for
    the forseeable future.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Manipulating the FPU control word.
 
2
   Copyright (C) 2007-2010 Free Software Foundation, Inc.
 
3
   Written by Bruno Haible <bruno@clisp.org>, 2007.
 
4
 
 
5
   This program is free software: you can redistribute it and/or modify
 
6
   it under the terms of the GNU General Public License as published by
 
7
   the Free Software Foundation; either version 3 of the License, or
 
8
   (at your option) any later version.
 
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
 
16
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
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.  */
 
64
#if (defined __i386__ || defined __x86_64__) && defined __GNUC__
 
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() \
 
73
  ({ fpucw_t _cw;                                               \
 
74
     __asm__ __volatile__ ("fnstcw %0" : "=m" (*&_cw));         \
 
75
     _cw;                                                       \
 
76
   })
 
77
# define SET_FPUCW(word) \
 
78
  (void)({ fpucw_t _ncw = (word);                               \
 
79
           __asm__ __volatile__ ("fldcw %0" : : "m" (*&_ncw));  \
 
80
         })
 
81
 
 
82
# define DECL_LONG_DOUBLE_ROUNDING \
 
83
  fpucw_t oldcw;
 
84
# define BEGIN_LONG_DOUBLE_ROUNDING() \
 
85
  (void)(oldcw = GET_FPUCW (),                                  \
 
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 */