1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #ifndef ZEND_FLOAT_H
22 #define ZEND_FLOAT_H
23
24 BEGIN_EXTERN_C()
25
26
27
28
29 extern ZEND_API void zend_init_fpu(TSRMLS_D);
30 extern ZEND_API void zend_shutdown_fpu(TSRMLS_D);
31 extern ZEND_API void zend_ensure_fpu_mode(TSRMLS_D);
32
33 END_EXTERN_C()
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78 #if defined(_MSC_VER) && !defined(_WIN64)
79 # if _MSC_VER >= 1500
80
81 # define HAVE__CONTROLFP_S
82 # else
83
84 # define HAVE__CONTROLFP
85 # endif
86
87 # if _MSC_VER >= 1500
88 # pragma fenv_access (on)
89 # endif
90 #endif
91
92 #ifdef HAVE__CONTROLFP_S
93
94
95 # include <float.h>
96
97 # define XPFPA_HAVE_CW 1
98 # define XPFPA_CW_DATATYPE \
99 unsigned int
100
101 # define XPFPA_STORE_CW(vptr) do { \
102 _controlfp_s((unsigned int *)(vptr), 0, 0); \
103 } while (0)
104
105 # define XPFPA_RESTORE_CW(vptr) do { \
106 unsigned int _xpfpa_fpu_cw; \
107 _controlfp_s(&_xpfpa_fpu_cw, *((unsigned int *)(vptr)), _MCW_PC); \
108 } while (0)
109
110 # define XPFPA_DECLARE \
111 unsigned int _xpfpa_fpu_oldcw, _xpfpa_fpu_cw;
112
113 # define XPFPA_SWITCH_DOUBLE() do { \
114 _controlfp_s(&_xpfpa_fpu_cw, 0, 0); \
115 _xpfpa_fpu_oldcw = _xpfpa_fpu_cw; \
116 _controlfp_s(&_xpfpa_fpu_cw, _PC_53, _MCW_PC); \
117 } while (0)
118 # define XPFPA_SWITCH_SINGLE() do { \
119 _controlfp_s(&_xpfpa_fpu_cw, 0, 0); \
120 _xpfpa_fpu_oldcw = _xpfpa_fpu_cw; \
121 _controlfp_s(&_xpfpa_fpu_cw, _PC_24, _MCW_PC); \
122 } while (0)
123
124
125 # define XPFPA_SWITCH_DOUBLE_EXTENDED() do { \
126 _controlfp_s(&_xpfpa_fpu_cw, 0, 0); \
127 _xpfpa_fpu_oldcw = _xpfpa_fpu_cw; \
128 _controlfp_s(&_xpfpa_fpu_cw, _PC_64, _MCW_PC); \
129 } while (0)
130 # define XPFPA_RESTORE() \
131 _controlfp_s(&_xpfpa_fpu_cw, _xpfpa_fpu_oldcw, _MCW_PC)
132
133
134
135
136 # define XPFPA_RETURN_DOUBLE(val) \
137 do { \
138 double _xpfpa_result = (val); \
139 XPFPA_RESTORE(); \
140 return _xpfpa_result; \
141 } while (0)
142 # define XPFPA_RETURN_SINGLE(val) \
143 do { \
144 float _xpfpa_result = (val); \
145 XPFPA_RESTORE(); \
146 return _xpfpa_result; \
147 } while (0)
148
149 # define XPFPA_RETURN_DOUBLE_EXTENDED(val) \
150 do { \
151 long double _xpfpa_result = (val); \
152 XPFPA_RESTORE(); \
153 return _xpfpa_result; \
154 } while (0)
155
156 #elif defined(HAVE__CONTROLFP)
157
158
159 # include <float.h>
160
161 # define XPFPA_DECLARE \
162 unsigned int _xpfpa_fpu_oldcw;
163
164 # define XPFPA_HAVE_CW 1
165 # define XPFPA_CW_DATATYPE \
166 unsigned int
167
168 # define XPFPA_STORE_CW(vptr) do { \
169 *((unsigned int *)(vptr)) = _controlfp(0, 0); \
170 } while (0)
171
172 # define XPFPA_RESTORE_CW(vptr) do { \
173 _controlfp(*((unsigned int *)(vptr)), _MCW_PC); \
174 } while (0)
175
176 # define XPFPA_SWITCH_DOUBLE() do { \
177 _xpfpa_fpu_oldcw = _controlfp(0, 0); \
178 _controlfp(_PC_53, _MCW_PC); \
179 } while (0)
180 # define XPFPA_SWITCH_SINGLE() do { \
181 _xpfpa_fpu_oldcw = _controlfp(0, 0); \
182 _controlfp(_PC_24, _MCW_PC); \
183 } while (0)
184
185 # define XPFPA_SWITCH_DOUBLE_EXTENDED() do { \
186 _xpfpa_fpu_oldcw = _controlfp(0, 0); \
187 _controlfp(_PC_64, _MCW_PC); \
188 } while (0)
189 # define XPFPA_RESTORE() \
190 _controlfp(_xpfpa_fpu_oldcw, _MCW_PC)
191
192
193
194
195 # define XPFPA_RETURN_DOUBLE(val) \
196 do { \
197 double _xpfpa_result = (val); \
198 XPFPA_RESTORE(); \
199 return _xpfpa_result; \
200 } while (0)
201 # define XPFPA_RETURN_SINGLE(val) \
202 do { \
203 float _xpfpa_result = (val); \
204 XPFPA_RESTORE(); \
205 return _xpfpa_result; \
206 } while (0)
207
208 # define XPFPA_RETURN_DOUBLE_EXTENDED(val) \
209 do { \
210 long double _xpfpa_result = (val); \
211 XPFPA_RESTORE(); \
212 return _xpfpa_result; \
213 } while (0)
214
215 #elif defined(HAVE__FPU_SETCW)
216
217
218 # include <fpu_control.h>
219
220 # define XPFPA_DECLARE \
221 fpu_control_t _xpfpa_fpu_oldcw, _xpfpa_fpu_cw;
222
223 # define XPFPA_HAVE_CW 1
224 # define XPFPA_CW_DATATYPE \
225 fpu_control_t
226
227 # define XPFPA_STORE_CW(vptr) do { \
228 _FPU_GETCW((*((fpu_control_t *)(vptr)))); \
229 } while (0)
230
231 # define XPFPA_RESTORE_CW(vptr) do { \
232 _FPU_SETCW((*((fpu_control_t *)(vptr)))); \
233 } while (0)
234
235 # define XPFPA_SWITCH_DOUBLE() do { \
236 _FPU_GETCW(_xpfpa_fpu_oldcw); \
237 _xpfpa_fpu_cw = (_xpfpa_fpu_oldcw & ~_FPU_EXTENDED & ~_FPU_SINGLE) | _FPU_DOUBLE; \
238 _FPU_SETCW(_xpfpa_fpu_cw); \
239 } while (0)
240 # define XPFPA_SWITCH_SINGLE() do { \
241 _FPU_GETCW(_xpfpa_fpu_oldcw); \
242 _xpfpa_fpu_cw = (_xpfpa_fpu_oldcw & ~_FPU_EXTENDED & ~_FPU_DOUBLE) | _FPU_SINGLE; \
243 _FPU_SETCW(_xpfpa_fpu_cw); \
244 } while (0)
245 # define XPFPA_SWITCH_DOUBLE_EXTENDED() do { \
246 _FPU_GETCW(_xpfpa_fpu_oldcw); \
247 _xpfpa_fpu_cw = (_xpfpa_fpu_oldcw & ~_FPU_SINGLE & ~_FPU_DOUBLE) | _FPU_EXTENDED; \
248 _FPU_SETCW(_xpfpa_fpu_cw); \
249 } while (0)
250 # define XPFPA_RESTORE() \
251 _FPU_SETCW(_xpfpa_fpu_oldcw)
252
253
254
255 # define XPFPA_RETURN_DOUBLE(val) \
256 do { \
257 volatile double _xpfpa_result = (val); \
258 XPFPA_RESTORE(); \
259 return _xpfpa_result; \
260 } while (0)
261 # define XPFPA_RETURN_SINGLE(val) \
262 do { \
263 volatile float _xpfpa_result = (val); \
264 XPFPA_RESTORE(); \
265 return _xpfpa_result; \
266 } while (0)
267 # define XPFPA_RETURN_DOUBLE_EXTENDED(val) \
268 do { \
269 volatile long double _xpfpa_result = (val); \
270 XPFPA_RESTORE(); \
271 return _xpfpa_result; \
272 } while (0)
273
274 #elif defined(HAVE_FPSETPREC)
275
276
277 # include <machine/ieeefp.h>
278
279 # define XPFPA_DECLARE \
280 fp_prec_t _xpfpa_fpu_oldprec;
281
282 # define XPFPA_HAVE_CW 1
283 # define XPFPA_CW_DATATYPE \
284 fp_prec_t
285
286 # define XPFPA_STORE_CW(vptr) do { \
287 *((fp_prec_t *)(vptr)) = fpgetprec(); \
288 } while (0)
289
290 # define XPFPA_RESTORE_CW(vptr) do { \
291 fpsetprec(*((fp_prec_t *)(vptr))); \
292 } while (0)
293
294 # define XPFPA_SWITCH_DOUBLE() do { \
295 _xpfpa_fpu_oldprec = fpgetprec(); \
296 fpsetprec(FP_PD); \
297 } while (0)
298 # define XPFPA_SWITCH_SINGLE() do { \
299 _xpfpa_fpu_oldprec = fpgetprec(); \
300 fpsetprec(FP_PS); \
301 } while (0)
302 # define XPFPA_SWITCH_DOUBLE_EXTENDED() do { \
303 _xpfpa_fpu_oldprec = fpgetprec(); \
304 fpsetprec(FP_PE); \
305 } while (0)
306 # define XPFPA_RESTORE() \
307 fpsetprec(_xpfpa_fpu_oldprec)
308
309
310
311 # define XPFPA_RETURN_DOUBLE(val) \
312 do { \
313 volatile double _xpfpa_result = (val); \
314 XPFPA_RESTORE(); \
315 return _xpfpa_result; \
316 } while (0)
317 # define XPFPA_RETURN_SINGLE(val) \
318 do { \
319 volatile float _xpfpa_result = (val); \
320 XPFPA_RESTORE(); \
321 return _xpfpa_result; \
322 } while (0)
323 # define XPFPA_RETURN_DOUBLE_EXTENDED(val) \
324 do { \
325 volatile long double _xpfpa_result = (val); \
326 XPFPA_RESTORE(); \
327 return _xpfpa_result; \
328 } while (0)
329
330 #elif defined(HAVE_FPU_INLINE_ASM_X86)
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354 # define XPFPA_DECLARE \
355 unsigned int _xpfpa_fpu_oldcw, _xpfpa_fpu_cw;
356
357 # define XPFPA_HAVE_CW 1
358 # define XPFPA_CW_DATATYPE \
359 unsigned int
360
361 # define XPFPA_STORE_CW(vptr) do { \
362 __asm__ __volatile__ ("fnstcw %0" : "=m" (*((unsigned int *)(vptr)))); \
363 } while (0)
364
365 # define XPFPA_RESTORE_CW(vptr) do { \
366 __asm__ __volatile__ ("fldcw %0" : : "m" (*((unsigned int *)(vptr)))); \
367 } while (0)
368
369 # define XPFPA_SWITCH_DOUBLE() do { \
370 __asm__ __volatile__ ("fnstcw %0" : "=m" (*&_xpfpa_fpu_oldcw)); \
371 _xpfpa_fpu_cw = (_xpfpa_fpu_oldcw & ~0x100) | 0x200; \
372 __asm__ __volatile__ ("fldcw %0" : : "m" (*&_xpfpa_fpu_cw)); \
373 } while (0)
374 # define XPFPA_SWITCH_SINGLE() do { \
375 __asm__ __volatile__ ("fnstcw %0" : "=m" (*&_xpfpa_fpu_oldcw)); \
376 _xpfpa_fpu_cw = (_xpfpa_fpu_oldcw & ~0x300); \
377 __asm__ __volatile__ ("fldcw %0" : : "m" (*&_xpfpa_fpu_cw)); \
378 } while (0)
379 # define XPFPA_SWITCH_DOUBLE_EXTENDED() do { \
380 __asm__ __volatile__ ("fnstcw %0" : "=m" (*&_xpfpa_fpu_oldcw)); \
381 _xpfpa_fpu_cw = _xpfpa_fpu_oldcw | 0x300; \
382 __asm__ __volatile__ ("fldcw %0" : : "m" (*&_xpfpa_fpu_cw)); \
383 } while (0)
384 # define XPFPA_RESTORE() \
385 __asm__ __volatile__ ("fldcw %0" : : "m" (*&_xpfpa_fpu_oldcw))
386
387
388
389 # define XPFPA_RETURN_DOUBLE(val) \
390 do { \
391 volatile double _xpfpa_result = (val); \
392 XPFPA_RESTORE(); \
393 return _xpfpa_result; \
394 } while (0)
395 # define XPFPA_RETURN_SINGLE(val) \
396 do { \
397 volatile float _xpfpa_result = (val); \
398 XPFPA_RESTORE(); \
399 return _xpfpa_result; \
400 } while (0)
401 # define XPFPA_RETURN_DOUBLE_EXTENDED(val) \
402 do { \
403 volatile long double _xpfpa_result = (val); \
404 XPFPA_RESTORE(); \
405 return _xpfpa_result; \
406 } while (0)
407
408 #else
409
410
411
412
413
414
415 # define XPFPA_DECLARE
416 # define XPFPA_HAVE_CW 0
417 # define XPFPA_CW_DATATYPE unsigned int
418 # define XPFPA_STORE_CW(variable)
419 # define XPFPA_RESTORE_CW(variable)
420 # define XPFPA_SWITCH_DOUBLE()
421 # define XPFPA_SWITCH_SINGLE()
422 # define XPFPA_SWITCH_DOUBLE_EXTENDED()
423 # define XPFPA_RESTORE()
424 # define XPFPA_RETURN_DOUBLE(val) return (val)
425 # define XPFPA_RETURN_SINGLE(val) return (val)
426 # define XPFPA_RETURN_DOUBLE_EXTENDED(val) return (val)
427
428 #endif
429
430 #endif