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