📄 fpusettings.h
字号:
STREFLOP_STMXCSR(sse_mode);
sse_mode &= ~( excepts << 7 ); // generate error for selection
STREFLOP_LDMXCSR(sse_mode);
return 0;
}
/// Clear exceptions for these flags
inline int feclearexcept(int excepts) {
// Just in case the compiler would store a value on the st(x) registers
unsigned short x87_mode;
STREFLOP_FSTCW(x87_mode);
x87_mode |= excepts;
STREFLOP_FLDCW(x87_mode);
int sse_mode;
STREFLOP_STMXCSR(sse_mode);
sse_mode |= excepts << 7;
STREFLOP_LDMXCSR(sse_mode);
return 0;
}
/// Get current rounding mode
inline int fegetround() {
int sse_mode;
STREFLOP_STMXCSR(sse_mode);
return (sse_mode>>3) & 0x00000C00;
}
/// Set a new rounding mode
inline int fesetround(FPU_RoundMode roundMode) {
int sse_mode;
STREFLOP_STMXCSR(sse_mode);
sse_mode &= 0xFFFF9FFF; // clear current mode
sse_mode |= roundMode<<3; // sets new mode
STREFLOP_LDMXCSR(sse_mode);
return 0;
}
/// stores both x87 and SSE words
struct fenv_t {
int sse_mode;
short int x87_mode;
};
/// Default env. Defined in Math.cpp, structs are initialized to 0
extern fenv_t FE_DFL_ENV;
/// Get FP env into the given structure
inline int fegetenv(fenv_t *envp) {
// check that default env exists, otherwise save it now
if (!FE_DFL_ENV.x87_mode) STREFLOP_FSTCW(FE_DFL_ENV.x87_mode);
// Now store env into argument
STREFLOP_FSTCW(envp->x87_mode);
// For SSE
if (!FE_DFL_ENV.sse_mode) STREFLOP_STMXCSR(FE_DFL_ENV.sse_mode);
// Now store env into argument
STREFLOP_STMXCSR(envp->sse_mode);
return 0;
}
/// Sets FP env from the given structure
inline int fesetenv(const fenv_t *envp) {
// check that default env exists, otherwise save it now
if (!FE_DFL_ENV.x87_mode) STREFLOP_FSTCW(FE_DFL_ENV.x87_mode);
// Now overwrite current env by argument
STREFLOP_FLDCW(envp->x87_mode);
// For SSE
if (!FE_DFL_ENV.sse_mode) STREFLOP_STMXCSR(FE_DFL_ENV.sse_mode);
// Now overwrite current env by argument
STREFLOP_LDMXCSR(envp->sse_mode);
return 0;
}
/// get env and clear exceptions
inline int feholdexcept(fenv_t *envp) {
fegetenv(envp);
feclearexcept(FE_ALL_EXCEPT);
return 0;
}
template<typename T> inline void streflop_init() {
// Do nothing by default, or for unknown types
}
/// Initialize the FPU for the different types
/// this may also be called to switch between code sections using
/// different precisions
template<> inline void streflop_init<Simple>() {
// Just in case the compiler would store a value on the st(x) registers
unsigned short x87_mode;
STREFLOP_FSTCW(x87_mode);
x87_mode &= 0xFCFF; // 32 bits internal operations
STREFLOP_FLDCW(x87_mode);
int sse_mode;
STREFLOP_STMXCSR(sse_mode);
#if defined(STREFLOP_NO_DENORMALS)
sse_mode |= 0x8040; // set DAZ and FTZ
#else
sse_mode &= 0xFFFF7FBF; // clear DAZ and FTZ
#endif
STREFLOP_LDMXCSR(sse_mode);
}
template<> inline void streflop_init<Double>() {
// Just in case the compiler would store a value on the st(x) registers
unsigned short x87_mode;
STREFLOP_FSTCW(x87_mode);
x87_mode &= 0xFCFF;
x87_mode |= 0x0200; // 64 bits internal operations
STREFLOP_FLDCW(x87_mode);
int sse_mode;
STREFLOP_STMXCSR(sse_mode);
#if defined(STREFLOP_NO_DENORMALS)
sse_mode |= 0x8040; // set DAZ and FTZ
#else
sse_mode &= 0xFFFF7FBF; // clear DAZ and FTZ
#endif
STREFLOP_LDMXCSR(sse_mode);
}
#ifdef Extended
template<> inline void streflop_init<Extended>() {
// Just in case the compiler would store a value on the st(x) registers
unsigned short x87_mode;
STREFLOP_FSTCW(x87_mode);
x87_mode &= 0xFCFF;
x87_mode |= 0x0300; // 80 bits internal operations
STREFLOP_FLDCW(x87_mode);
int sse_mode;
STREFLOP_STMXCSR(sse_mode);
#if defined(STREFLOP_NO_DENORMALS)
sse_mode |= 0x8040; // set DAZ and FTZ
#else
sse_mode &= 0xFFFF7FBF; // clear DAZ and FTZ
#endif
STREFLOP_LDMXCSR(sse_mode);
}
#endif
#elif defined(STREFLOP_SOFT)
/// Raise exception for these flags
inline int feraiseexcept(FPU_Exceptions excepts) {
// Use positive logic
SoftFloat::float_exception_realtraps |= excepts;
return 0;
}
/// Clear exceptions for these flags
inline int feclearexcept(int excepts) {
// Use positive logic
SoftFloat::float_exception_realtraps &= ~( excepts );
return 0;
}
/// Get current rounding mode
inline int fegetround() {
// see softfloat.h for the definition
switch (SoftFloat::float_rounding_mode) {
case SoftFloat::float_round_down: return FE_DOWNWARD;
case SoftFloat::float_round_up: return FE_UPWARD;
case SoftFloat::float_round_to_zero: return FE_TOWARDZERO;
default:; // is also initial mode
}
// case SoftFloat::float_round_nearest_even:
return FE_TONEAREST;
}
/// Set a new rounding mode
inline int fesetround(FPU_RoundMode roundMode) {
// see softfloat.h for the definition
switch (roundMode) {
case FE_DOWNWARD: SoftFloat::float_rounding_mode = SoftFloat::float_round_down; return 0;
case FE_UPWARD: SoftFloat::float_rounding_mode = SoftFloat::float_round_up; return 0;
case FE_TOWARDZERO: SoftFloat::float_rounding_mode = SoftFloat::float_round_to_zero; return 0;
case FE_TONEAREST: SoftFloat::float_rounding_mode = SoftFloat::float_round_nearest_even; return 0;
}
// Error, invalid mode
return 1;
}
/// SoftFloat environment comprises non-volatile state variables
struct fenv_t {
char tininess;
char rounding_mode;
int exception_realtraps;
};
/// Default env. Defined in Math.cpp, initialized to some invalid value for detection
extern fenv_t FE_DFL_ENV;
/// Get FP env into the given structure
inline int fegetenv(fenv_t *envp) {
// check that default env exists, otherwise save it now
if (FE_DFL_ENV.tininess==42) {
// First use: save default environment now
FE_DFL_ENV.tininess = SoftFloat::float_detect_tininess;
FE_DFL_ENV.rounding_mode = SoftFloat::float_rounding_mode;
FE_DFL_ENV.exception_realtraps = SoftFloat::float_exception_realtraps;
}
// Now get the current env in the given argument
envp->tininess = SoftFloat::float_detect_tininess;
envp->rounding_mode = SoftFloat::float_rounding_mode;
envp->exception_realtraps = SoftFloat::float_exception_realtraps;
return 0;
}
/// Sets FP env from the given structure
inline int fesetenv(const fenv_t *envp) {
// check that default env exists, otherwise save it now
if (FE_DFL_ENV.tininess==42) {
// First use: save default environment now
FE_DFL_ENV.tininess = SoftFloat::float_detect_tininess;
FE_DFL_ENV.rounding_mode = SoftFloat::float_rounding_mode;
FE_DFL_ENV.exception_realtraps = SoftFloat::float_exception_realtraps;
}
// Now get the current env in the given argument
SoftFloat::float_detect_tininess = envp->tininess;
SoftFloat::float_rounding_mode = envp->rounding_mode;
SoftFloat::float_exception_realtraps = envp->exception_realtraps;
return 0;
}
/// get env and clear exceptions
inline int feholdexcept(fenv_t *envp) {
fegetenv(envp);
feclearexcept(FE_ALL_EXCEPT);
return 0;
}
template<typename T> inline void streflop_init() {
// Do nothing by default, or for unknown types
}
/// Initialize the FPU for the different types
/// this may also be called to switch between code sections using
/// different precisions
template<> inline void streflop_init<Simple>() {
}
template<> inline void streflop_init<Double>() {
}
template<> inline void streflop_init<Extended>() {
}
#else
#error STREFLOP: Invalid combination or unknown FPU type.
#endif
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -