123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 |
- #ifndef ZEND_FLOAT_H
- #define ZEND_FLOAT_H
- BEGIN_EXTERN_C()
- extern ZEND_API void zend_init_fpu(void);
- extern ZEND_API void zend_shutdown_fpu(void);
- extern ZEND_API void zend_ensure_fpu_mode(void);
- END_EXTERN_C()
- #if defined(_MSC_VER) && !defined(_WIN64)
- # define HAVE__CONTROLFP_S
- #endif /* _MSC_VER */
- #if defined(HAVE__CONTROLFP_S) && !defined(__x86_64__)
- # include <float.h>
- # define XPFPA_HAVE_CW 1
- # define XPFPA_CW_DATATYPE \
- unsigned int
- # define XPFPA_STORE_CW(vptr) do { \
- _controlfp_s((unsigned int *)(vptr), 0, 0); \
- } while (0)
- # define XPFPA_RESTORE_CW(vptr) do { \
- unsigned int _xpfpa_fpu_cw; \
- _controlfp_s(&_xpfpa_fpu_cw, *((unsigned int *)(vptr)), _MCW_PC); \
- } while (0)
- # define XPFPA_DECLARE \
- unsigned int _xpfpa_fpu_oldcw, _xpfpa_fpu_cw;
- # define XPFPA_SWITCH_DOUBLE() do { \
- _controlfp_s(&_xpfpa_fpu_cw, 0, 0); \
- _xpfpa_fpu_oldcw = _xpfpa_fpu_cw; \
- _controlfp_s(&_xpfpa_fpu_cw, _PC_53, _MCW_PC); \
- } while (0)
- # define XPFPA_SWITCH_SINGLE() do { \
- _controlfp_s(&_xpfpa_fpu_cw, 0, 0); \
- _xpfpa_fpu_oldcw = _xpfpa_fpu_cw; \
- _controlfp_s(&_xpfpa_fpu_cw, _PC_24, _MCW_PC); \
- } while (0)
- # define XPFPA_SWITCH_DOUBLE_EXTENDED() do { \
- _controlfp_s(&_xpfpa_fpu_cw, 0, 0); \
- _xpfpa_fpu_oldcw = _xpfpa_fpu_cw; \
- _controlfp_s(&_xpfpa_fpu_cw, _PC_64, _MCW_PC); \
- } while (0)
- # define XPFPA_RESTORE() \
- _controlfp_s(&_xpfpa_fpu_cw, _xpfpa_fpu_oldcw, _MCW_PC)
- # define XPFPA_RETURN_DOUBLE(val) \
- do { \
- double _xpfpa_result = (val); \
- XPFPA_RESTORE(); \
- return _xpfpa_result; \
- } while (0)
- # define XPFPA_RETURN_SINGLE(val) \
- do { \
- float _xpfpa_result = (val); \
- XPFPA_RESTORE(); \
- return _xpfpa_result; \
- } while (0)
- # define XPFPA_RETURN_DOUBLE_EXTENDED(val) \
- do { \
- long double _xpfpa_result = (val); \
- XPFPA_RESTORE(); \
- return _xpfpa_result; \
- } while (0)
- #elif defined(HAVE__CONTROLFP) && !defined(__x86_64__)
- # include <float.h>
- # define XPFPA_DECLARE \
- unsigned int _xpfpa_fpu_oldcw;
- # define XPFPA_HAVE_CW 1
- # define XPFPA_CW_DATATYPE \
- unsigned int
- # define XPFPA_STORE_CW(vptr) do { \
- *((unsigned int *)(vptr)) = _controlfp(0, 0); \
- } while (0)
- # define XPFPA_RESTORE_CW(vptr) do { \
- _controlfp(*((unsigned int *)(vptr)), _MCW_PC); \
- } while (0)
- # define XPFPA_SWITCH_DOUBLE() do { \
- _xpfpa_fpu_oldcw = _controlfp(0, 0); \
- _controlfp(_PC_53, _MCW_PC); \
- } while (0)
- # define XPFPA_SWITCH_SINGLE() do { \
- _xpfpa_fpu_oldcw = _controlfp(0, 0); \
- _controlfp(_PC_24, _MCW_PC); \
- } while (0)
- # define XPFPA_SWITCH_DOUBLE_EXTENDED() do { \
- _xpfpa_fpu_oldcw = _controlfp(0, 0); \
- _controlfp(_PC_64, _MCW_PC); \
- } while (0)
- # define XPFPA_RESTORE() \
- _controlfp(_xpfpa_fpu_oldcw, _MCW_PC)
- # define XPFPA_RETURN_DOUBLE(val) \
- do { \
- double _xpfpa_result = (val); \
- XPFPA_RESTORE(); \
- return _xpfpa_result; \
- } while (0)
- # define XPFPA_RETURN_SINGLE(val) \
- do { \
- float _xpfpa_result = (val); \
- XPFPA_RESTORE(); \
- return _xpfpa_result; \
- } while (0)
- # define XPFPA_RETURN_DOUBLE_EXTENDED(val) \
- do { \
- long double _xpfpa_result = (val); \
- XPFPA_RESTORE(); \
- return _xpfpa_result; \
- } while (0)
- #elif defined(HAVE__FPU_SETCW) && !defined(__x86_64__) /* glibc systems */
- # include <fpu_control.h>
- # define XPFPA_DECLARE \
- fpu_control_t _xpfpa_fpu_oldcw, _xpfpa_fpu_cw;
- # define XPFPA_HAVE_CW 1
- # define XPFPA_CW_DATATYPE \
- fpu_control_t
- # define XPFPA_STORE_CW(vptr) do { \
- _FPU_GETCW((*((fpu_control_t *)(vptr)))); \
- } while (0)
- # define XPFPA_RESTORE_CW(vptr) do { \
- _FPU_SETCW((*((fpu_control_t *)(vptr)))); \
- } while (0)
- # define XPFPA_SWITCH_DOUBLE() do { \
- _FPU_GETCW(_xpfpa_fpu_oldcw); \
- _xpfpa_fpu_cw = (_xpfpa_fpu_oldcw & ~_FPU_EXTENDED & ~_FPU_SINGLE) | _FPU_DOUBLE; \
- _FPU_SETCW(_xpfpa_fpu_cw); \
- } while (0)
- # define XPFPA_SWITCH_SINGLE() do { \
- _FPU_GETCW(_xpfpa_fpu_oldcw); \
- _xpfpa_fpu_cw = (_xpfpa_fpu_oldcw & ~_FPU_EXTENDED & ~_FPU_DOUBLE) | _FPU_SINGLE; \
- _FPU_SETCW(_xpfpa_fpu_cw); \
- } while (0)
- # define XPFPA_SWITCH_DOUBLE_EXTENDED() do { \
- _FPU_GETCW(_xpfpa_fpu_oldcw); \
- _xpfpa_fpu_cw = (_xpfpa_fpu_oldcw & ~_FPU_SINGLE & ~_FPU_DOUBLE) | _FPU_EXTENDED; \
- _FPU_SETCW(_xpfpa_fpu_cw); \
- } while (0)
- # define XPFPA_RESTORE() \
- _FPU_SETCW(_xpfpa_fpu_oldcw)
- # define XPFPA_RETURN_DOUBLE(val) \
- do { \
- volatile double _xpfpa_result = (val); \
- XPFPA_RESTORE(); \
- return _xpfpa_result; \
- } while (0)
- # define XPFPA_RETURN_SINGLE(val) \
- do { \
- volatile float _xpfpa_result = (val); \
- XPFPA_RESTORE(); \
- return _xpfpa_result; \
- } while (0)
- # define XPFPA_RETURN_DOUBLE_EXTENDED(val) \
- do { \
- volatile long double _xpfpa_result = (val); \
- XPFPA_RESTORE(); \
- return _xpfpa_result; \
- } while (0)
- #elif defined(HAVE_FPSETPREC) && !defined(__x86_64__) /* FreeBSD */
- # include <machine/ieeefp.h>
- # define XPFPA_DECLARE \
- fp_prec_t _xpfpa_fpu_oldprec;
- # define XPFPA_HAVE_CW 1
- # define XPFPA_CW_DATATYPE \
- fp_prec_t
- # define XPFPA_STORE_CW(vptr) do { \
- *((fp_prec_t *)(vptr)) = fpgetprec(); \
- } while (0)
- # define XPFPA_RESTORE_CW(vptr) do { \
- fpsetprec(*((fp_prec_t *)(vptr))); \
- } while (0)
- # define XPFPA_SWITCH_DOUBLE() do { \
- _xpfpa_fpu_oldprec = fpgetprec(); \
- fpsetprec(FP_PD); \
- } while (0)
- # define XPFPA_SWITCH_SINGLE() do { \
- _xpfpa_fpu_oldprec = fpgetprec(); \
- fpsetprec(FP_PS); \
- } while (0)
- # define XPFPA_SWITCH_DOUBLE_EXTENDED() do { \
- _xpfpa_fpu_oldprec = fpgetprec(); \
- fpsetprec(FP_PE); \
- } while (0)
- # define XPFPA_RESTORE() \
- fpsetprec(_xpfpa_fpu_oldprec)
- # define XPFPA_RETURN_DOUBLE(val) \
- do { \
- volatile double _xpfpa_result = (val); \
- XPFPA_RESTORE(); \
- return _xpfpa_result; \
- } while (0)
- # define XPFPA_RETURN_SINGLE(val) \
- do { \
- volatile float _xpfpa_result = (val); \
- XPFPA_RESTORE(); \
- return _xpfpa_result; \
- } while (0)
- # define XPFPA_RETURN_DOUBLE_EXTENDED(val) \
- do { \
- volatile long double _xpfpa_result = (val); \
- XPFPA_RESTORE(); \
- return _xpfpa_result; \
- } while (0)
- #elif defined(HAVE_FPU_INLINE_ASM_X86) && !defined(__x86_64__)
- # define XPFPA_DECLARE \
- unsigned int _xpfpa_fpu_oldcw, _xpfpa_fpu_cw;
- # define XPFPA_HAVE_CW 1
- # define XPFPA_CW_DATATYPE \
- unsigned int
- # define XPFPA_STORE_CW(vptr) do { \
- __asm__ __volatile__ ("fnstcw %0" : "=m" (*((unsigned int *)(vptr)))); \
- } while (0)
- # define XPFPA_RESTORE_CW(vptr) do { \
- __asm__ __volatile__ ("fldcw %0" : : "m" (*((unsigned int *)(vptr)))); \
- } while (0)
- # define XPFPA_SWITCH_DOUBLE() do { \
- __asm__ __volatile__ ("fnstcw %0" : "=m" (*&_xpfpa_fpu_oldcw)); \
- _xpfpa_fpu_cw = (_xpfpa_fpu_oldcw & ~0x100) | 0x200; \
- __asm__ __volatile__ ("fldcw %0" : : "m" (*&_xpfpa_fpu_cw)); \
- } while (0)
- # define XPFPA_SWITCH_SINGLE() do { \
- __asm__ __volatile__ ("fnstcw %0" : "=m" (*&_xpfpa_fpu_oldcw)); \
- _xpfpa_fpu_cw = (_xpfpa_fpu_oldcw & ~0x300); \
- __asm__ __volatile__ ("fldcw %0" : : "m" (*&_xpfpa_fpu_cw)); \
- } while (0)
- # define XPFPA_SWITCH_DOUBLE_EXTENDED() do { \
- __asm__ __volatile__ ("fnstcw %0" : "=m" (*&_xpfpa_fpu_oldcw)); \
- _xpfpa_fpu_cw = _xpfpa_fpu_oldcw | 0x300; \
- __asm__ __volatile__ ("fldcw %0" : : "m" (*&_xpfpa_fpu_cw)); \
- } while (0)
- # define XPFPA_RESTORE() \
- __asm__ __volatile__ ("fldcw %0" : : "m" (*&_xpfpa_fpu_oldcw))
- # define XPFPA_RETURN_DOUBLE(val) \
- do { \
- volatile double _xpfpa_result = (val); \
- XPFPA_RESTORE(); \
- return _xpfpa_result; \
- } while (0)
- # define XPFPA_RETURN_SINGLE(val) \
- do { \
- volatile float _xpfpa_result = (val); \
- XPFPA_RESTORE(); \
- return _xpfpa_result; \
- } while (0)
- # define XPFPA_RETURN_DOUBLE_EXTENDED(val) \
- do { \
- volatile long double _xpfpa_result = (val); \
- XPFPA_RESTORE(); \
- return _xpfpa_result; \
- } while (0)
- #else /* FPU CONTROL */
- # define XPFPA_DECLARE /* NOP */
- # define XPFPA_HAVE_CW 0
- # define XPFPA_CW_DATATYPE unsigned int
- # define XPFPA_STORE_CW(variable) /* NOP */
- # define XPFPA_RESTORE_CW(variable) /* NOP */
- # define XPFPA_SWITCH_DOUBLE() /* NOP */
- # define XPFPA_SWITCH_SINGLE() /* NOP */
- # define XPFPA_SWITCH_DOUBLE_EXTENDED() /* NOP */
- # define XPFPA_RESTORE() /* NOP */
- # define XPFPA_RETURN_DOUBLE(val) return (val)
- # define XPFPA_RETURN_SINGLE(val) return (val)
- # define XPFPA_RETURN_DOUBLE_EXTENDED(val) return (val)
- #endif /* FPU CONTROL */
- #endif
|