PPL  1.2
fpu-ia32_inlines.hh
Go to the documentation of this file.
1 /* IA-32 floating point unit inline related functions.
2  Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3  Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4 
5 This file is part of the Parma Polyhedra Library (PPL).
6 
7 The PPL is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 The PPL is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20 
21 For the most up-to-date information see the Parma Polyhedra Library
22 site: http://bugseng.com/products/ppl/ . */
23 
24 #ifndef PPL_fpu_ia32_inlines_hh
25 #define PPL_fpu_ia32_inlines_hh 1
26 
27 #include <csetjmp>
28 #include <csignal>
29 
30 #define FPU_INVALID 0x01
31 #define FPU_DIVBYZERO 0x04
32 #define FPU_OVERFLOW 0x08
33 #define FPU_UNDERFLOW 0x10
34 #define FPU_INEXACT 0x20
35 
36 #define FPU_ALL_EXCEPT \
37  (FPU_INEXACT | FPU_DIVBYZERO | FPU_UNDERFLOW | FPU_OVERFLOW | FPU_INVALID)
38 
39 #define PPL_FPU_TONEAREST 0
40 #define PPL_FPU_DOWNWARD 0x400
41 #define PPL_FPU_UPWARD 0x800
42 #define PPL_FPU_TOWARDZERO 0xc00
43 
44 #define FPU_ROUNDING_MASK 0xc00
45 
46 #define SSE_INEXACT 0x20
47 
48 #define PPL_FPU_CONTROL_DEFAULT_BASE 0x37f
49 #define PPL_SSE_CONTROL_DEFAULT_BASE 0x1f80
50 
51 // This MUST be congruent with the definition of ROUND_DIRECT
52 #define PPL_FPU_CONTROL_DEFAULT \
53  (PPL_FPU_CONTROL_DEFAULT_BASE | PPL_FPU_UPWARD)
54 #define PPL_SSE_CONTROL_DEFAULT \
55  (PPL_SSE_CONTROL_DEFAULT_BASE | (PPL_FPU_UPWARD << 3))
56 
57 namespace Parma_Polyhedra_Library {
58 
59 typedef struct {
60  unsigned short control_word;
61  unsigned short unused1;
62  unsigned short status_word;
63  unsigned short unused2;
64  unsigned short tags;
65  unsigned short unused3;
66  unsigned int eip;
67  unsigned short cs_selector;
68  unsigned int opcode:11;
69  unsigned int unused4:5;
70  unsigned int data_offset;
71  unsigned short data_selector;
72  unsigned short unused5;
73 } ia32_fenv_t;
74 
75 inline int
77  unsigned short cw;
78  __asm__ __volatile__ ("fnstcw %0" : "=m" (*&cw) : : "memory");
79  return cw;
80 }
81 
82 inline void
84  unsigned short cw = static_cast<unsigned short>(c);
85  __asm__ __volatile__ ("fldcw %0" : : "m" (*&cw) : "memory");
86 }
87 
88 inline int
90  unsigned short sw;
91  __asm__ __volatile__ ("fnstsw %0" : "=a" (sw) : : "memory");
92  return sw;
93 }
94 
95 inline void
96 fpu_clear_status(unsigned short bits) {
97  /* There is no fldsw instruction */
98  ia32_fenv_t env;
99  __asm__ __volatile__ ("fnstenv %0" : "=m" (env));
100  env.status_word = static_cast<unsigned short>(env.status_word & ~bits);
101  __asm__ __volatile__ ("fldenv %0" : : "m" (env) : "memory");
102 }
103 
104 inline void
106  __asm__ __volatile__ ("fnclex" : /* No outputs. */ : : "memory");
107 }
108 
109 #ifdef PPL_FPMATH_MAY_USE_SSE
110 inline void
111 sse_set_control(unsigned int cw) {
112  __asm__ __volatile__ ("ldmxcsr %0" : : "m" (*&cw) : "memory");
113 }
114 
115 inline unsigned int
116 sse_get_control() {
117  unsigned int cw;
118  __asm__ __volatile__ ("stmxcsr %0" : "=m" (*&cw) : : "memory");
119  return cw;
120 }
121 #endif
122 
123 inline void
125 #ifdef PPL_FPMATH_MAY_USE_SSE
126  extern void detect_sse_unit();
127  detect_sse_unit();
128 #endif
129 }
130 
134 }
135 
136 inline void
138 #ifdef PPL_FPMATH_MAY_USE_387
140 #endif
141 #ifdef PPL_FPMATH_MAY_USE_SSE
142  extern bool have_sse_unit;
143  if (have_sse_unit)
144  sse_set_control(PPL_SSE_CONTROL_DEFAULT_BASE | (dir << 3));
145 #endif
146 }
147 
150 #ifdef PPL_FPMATH_MAY_USE_387
152 #endif
153 #ifdef PPL_FPMATH_MAY_USE_SSE
154  extern bool have_sse_unit;
155  if (have_sse_unit)
156  sse_set_control(PPL_SSE_CONTROL_DEFAULT_BASE | (dir << 3));
157 #endif
158  return static_cast<fpu_rounding_control_word_type>(0);
159 }
160 
161 inline void
163 #ifdef PPL_FPMATH_MAY_USE_387
165 #endif
166 #ifdef PPL_FPMATH_MAY_USE_SSE
167  // NOTE: on entry to this function the current rounding mode
168  // has to be the default one.
169  extern bool have_sse_unit;
170  if (have_sse_unit) {
171  sse_set_control(PPL_SSE_CONTROL_DEFAULT);
172  }
173 #endif
174 }
175 
176 inline void
178 #ifdef PPL_FPMATH_MAY_USE_387
180 #endif
181 #ifdef PPL_FPMATH_MAY_USE_SSE
182  extern bool have_sse_unit;
183  if (have_sse_unit) {
184  sse_set_control(PPL_SSE_CONTROL_DEFAULT);
185  }
186 #endif
187 }
188 
189 inline int
191 #ifdef PPL_FPMATH_MAY_USE_387
192  if (fpu_get_status() & FPU_INEXACT) {
193  return 1;
194  }
195 #endif
196 #ifdef PPL_FPMATH_MAY_USE_SSE
197  extern bool have_sse_unit;
198  if (have_sse_unit && (sse_get_control() & SSE_INEXACT)) {
199  return 1;
200  }
201 #endif
202  return 0;
203 }
204 
205 } // namespace Parma_Polyhedra_Library
206 
207 #endif // !defined(PPL_fpu_ia32_inlines_hh)
#define PPL_FPU_CONTROL_DEFAULT_BASE
fpu_rounding_control_word_type fpu_save_rounding_direction(fpu_rounding_direction_type dir)
Sets the FPU rounding direction to dir and returns the rounding control word previously in use...
int fpu_check_inexact()
Queries the inexact computation status.
fpu_rounding_direction_type fpu_get_rounding_direction()
Returns the current FPU rounding direction.
#define FPU_ROUNDING_MASK
void fpu_reset_inexact()
Clears the inexact computation status.
#define PPL_FPU_CONTROL_DEFAULT
#define PPL_SSE_CONTROL_DEFAULT_BASE
void fpu_restore_rounding_direction(fpu_rounding_control_word_type)
Restores the FPU rounding rounding control word to cw.
#define PPL_SSE_CONTROL_DEFAULT
#define SSE_INEXACT
The entire library is confined to this namespace.
Definition: version.hh:61
void fpu_initialize_control_functions()
Initializes the FPU control functions.
#define FPU_INEXACT
Coefficient c
Definition: PIP_Tree.cc:64
void fpu_set_rounding_direction(fpu_rounding_direction_type dir)
Sets the FPU rounding direction to dir.
void fpu_clear_status(unsigned short bits)