mirror of
https://github.com/Rosalie241/RMG.git
synced 2026-07-11 01:24:01 +02:00
a
This commit is contained in:
@@ -736,16 +736,6 @@ endif
|
||||
|
||||
ifeq ($(ACCURATE_FPU), 1)
|
||||
CFLAGS += -DACCURATE_FPU_BEHAVIOR
|
||||
# -O2 & -O3 enable -ftree-pre in GCC
|
||||
# which break some FPU functions and cause
|
||||
# a lot of test failures in n64-systemtest,
|
||||
# so fix that by disabling -ftree-pre
|
||||
# TODO: test with different GCC versions
|
||||
# NOTE: tested with GCC 13.2.1
|
||||
CC_VERSION := $(shell $(CC) --version)
|
||||
ifneq ($(findstring GCC,$(CC_VERSION)), )
|
||||
CFLAGS += -fno-tree-pre
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUGGER), 1)
|
||||
|
||||
+53
-47
@@ -44,6 +44,7 @@ static __inline float truncf(float x) { return (float)(int)x; }
|
||||
|
||||
#else
|
||||
#define M64P_FPU_INLINE static inline
|
||||
#define M64P_FPU_LOCAL static
|
||||
#include <fenv.h>
|
||||
#endif
|
||||
|
||||
@@ -90,26 +91,26 @@ M64P_FPU_INLINE void set_rounding(uint32_t fcr31)
|
||||
}
|
||||
|
||||
#ifdef ACCURATE_FPU_BEHAVIOR
|
||||
M64P_FPU_INLINE int is_qnan_float(const float* value)
|
||||
M64P_FPU_LOCAL int is_qnan_float(const float* value)
|
||||
{
|
||||
uint32_t v;
|
||||
memcpy(&v, value, 4);
|
||||
return (v & (1 << 22)) != 0;
|
||||
}
|
||||
|
||||
M64P_FPU_INLINE int is_qnan_double(const double* value)
|
||||
M64P_FPU_LOCAL int is_qnan_double(const double* value)
|
||||
{
|
||||
uint64_t v;
|
||||
memcpy(&v, value, 8);
|
||||
return (v & (1L << 51)) != 0;
|
||||
}
|
||||
|
||||
M64P_FPU_INLINE void fpu_reset_cause(uint32_t* fcr31)
|
||||
M64P_FPU_LOCAL void fpu_reset_cause(uint32_t* fcr31)
|
||||
{
|
||||
(*fcr31) &= ~FCR31_CAUSE_BITS;
|
||||
}
|
||||
|
||||
M64P_FPU_INLINE int fpu_throw_exception(uint32_t* fcr31)
|
||||
M64P_FPU_LOCAL int fpu_throw_exception(uint32_t* fcr31)
|
||||
{
|
||||
if ((*fcr31) & FCR31_ENABLE_DIVBYZERO_BIT &&
|
||||
(*fcr31) & FCR31_CAUSE_DIVBYZERO_BIT)
|
||||
@@ -155,16 +156,18 @@ M64P_FPU_INLINE int fpu_throw_exception(uint32_t* fcr31)
|
||||
return 0;
|
||||
}
|
||||
|
||||
M64P_FPU_INLINE void fpu_reset_exceptions()
|
||||
M64P_FPU_LOCAL void fpu_reset_exceptions()
|
||||
{
|
||||
feclearexcept(FE_ALL_EXCEPT);
|
||||
}
|
||||
|
||||
M64P_FPU_INLINE int fpu_check_exceptions(uint32_t* fcr31)
|
||||
M64P_FPU_LOCAL int fpu_check_exceptions(uint32_t* fcr31, uint8_t checkInvalidOp)
|
||||
{
|
||||
int fexceptions;
|
||||
|
||||
fexceptions = fetestexcept(FE_ALL_EXCEPT) & FE_ALL_EXCEPT;
|
||||
int fexceptions = fetestexcept(FE_ALL_EXCEPT) & FE_ALL_EXCEPT;
|
||||
if (!fexceptions)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int divByZeroEnabled = (*fcr31) & FCR31_ENABLE_DIVBYZERO_BIT;
|
||||
const int inexactEnabled = (*fcr31) & FCR31_ENABLE_INEXACT_BIT;
|
||||
@@ -176,17 +179,14 @@ M64P_FPU_INLINE int fpu_check_exceptions(uint32_t* fcr31)
|
||||
if (fexceptions & FE_UNDERFLOW)
|
||||
{
|
||||
if (!((*fcr31) & FCR31_FS_BIT) ||
|
||||
(*fcr31) & FCR31_ENABLE_UNDERFLOW_BIT ||
|
||||
(*fcr31) & FCR31_ENABLE_INEXACT_BIT)
|
||||
((*fcr31) & FCR31_ENABLE_UNDERFLOW_BIT) ||
|
||||
((*fcr31) & FCR31_ENABLE_INEXACT_BIT))
|
||||
{
|
||||
(*fcr31) |= FCR31_CAUSE_UNIMPLOP_BIT;
|
||||
return 1;
|
||||
}
|
||||
|
||||
(*fcr31) |= FCR31_CAUSE_UNDERFLOW_BIT;
|
||||
if (!underflowEnabled) (*fcr31) |= FCR31_FLAG_UNDERFLOW_BIT;
|
||||
else throw_exception |= 1;
|
||||
}
|
||||
|
||||
if (fexceptions & FE_DIVBYZERO)
|
||||
{
|
||||
(*fcr31) |= FCR31_CAUSE_DIVBYZERO_BIT;
|
||||
@@ -199,6 +199,12 @@ M64P_FPU_INLINE int fpu_check_exceptions(uint32_t* fcr31)
|
||||
if (!inexactEnabled) (*fcr31) |= FCR31_FLAG_INEXACT_BIT;
|
||||
else throw_exception |= 1;
|
||||
}
|
||||
if (fexceptions & FE_UNDERFLOW)
|
||||
{
|
||||
(*fcr31) |= FCR31_CAUSE_UNDERFLOW_BIT;
|
||||
if (!underflowEnabled) (*fcr31) |= FCR31_FLAG_UNDERFLOW_BIT;
|
||||
else throw_exception |= 1;
|
||||
}
|
||||
if (fexceptions & FE_OVERFLOW)
|
||||
{
|
||||
(*fcr31) |= FCR31_CAUSE_OVERFLOW_BIT;
|
||||
@@ -215,7 +221,7 @@ M64P_FPU_INLINE int fpu_check_exceptions(uint32_t* fcr31)
|
||||
return throw_exception;
|
||||
}
|
||||
|
||||
M64P_FPU_INLINE int fpu_check_input_float(uint32_t* fcr31, const float* value)
|
||||
M64P_FPU_LOCAL int fpu_check_input_float(uint32_t* fcr31, const float* value)
|
||||
{
|
||||
switch (fpclassify(*value))
|
||||
{
|
||||
@@ -242,7 +248,7 @@ M64P_FPU_INLINE int fpu_check_input_float(uint32_t* fcr31, const float* value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
M64P_FPU_INLINE int fpu_check_input_double(uint32_t* fcr31, const double* value)
|
||||
M64P_FPU_LOCAL int fpu_check_input_double(uint32_t* fcr31, const double* value)
|
||||
{
|
||||
switch (fpclassify(*value))
|
||||
{
|
||||
@@ -269,7 +275,7 @@ M64P_FPU_INLINE int fpu_check_input_double(uint32_t* fcr31, const double* value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
M64P_FPU_INLINE int fpu_check_input_float_conv_int32(uint32_t* fcr31, const float* source)
|
||||
M64P_FPU_LOCAL int fpu_check_input_float_conv_int32(uint32_t* fcr31, const float* source)
|
||||
{
|
||||
switch (fpclassify(*source))
|
||||
{
|
||||
@@ -292,7 +298,7 @@ M64P_FPU_INLINE int fpu_check_input_float_conv_int32(uint32_t* fcr31, const floa
|
||||
return 0;
|
||||
}
|
||||
|
||||
M64P_FPU_INLINE int fpu_check_input_double_conv_int32(uint32_t* fcr31, const double* source)
|
||||
M64P_FPU_LOCAL int fpu_check_input_double_conv_int32(uint32_t* fcr31, const double* source)
|
||||
{
|
||||
switch (fpclassify(*source))
|
||||
{
|
||||
@@ -315,7 +321,7 @@ M64P_FPU_INLINE int fpu_check_input_double_conv_int32(uint32_t* fcr31, const dou
|
||||
return 0;
|
||||
}
|
||||
|
||||
M64P_FPU_INLINE void fpu_flush_output_float(uint32_t* fcr31, float* value)
|
||||
M64P_FPU_LOCAL void fpu_flush_output_float(uint32_t* fcr31, float* value)
|
||||
{
|
||||
switch (fegetround())
|
||||
{
|
||||
@@ -334,7 +340,7 @@ M64P_FPU_INLINE void fpu_flush_output_float(uint32_t* fcr31, float* value)
|
||||
}
|
||||
}
|
||||
|
||||
M64P_FPU_INLINE void fpu_flush_output_double(uint32_t* fcr31, double* value)
|
||||
M64P_FPU_LOCAL void fpu_flush_output_double(uint32_t* fcr31, double* value)
|
||||
{
|
||||
switch (fegetround())
|
||||
{
|
||||
@@ -353,7 +359,7 @@ M64P_FPU_INLINE void fpu_flush_output_double(uint32_t* fcr31, double* value)
|
||||
}
|
||||
}
|
||||
|
||||
M64P_FPU_INLINE int fpu_check_output_float(uint32_t* fcr31, float* value)
|
||||
M64P_FPU_LOCAL int fpu_check_output_float(uint32_t* fcr31, float* value)
|
||||
{
|
||||
switch (fpclassify(*value))
|
||||
{
|
||||
@@ -384,7 +390,7 @@ M64P_FPU_INLINE int fpu_check_output_float(uint32_t* fcr31, float* value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
M64P_FPU_INLINE int fpu_check_output_double(uint32_t* fcr31, double* value)
|
||||
M64P_FPU_LOCAL int fpu_check_output_double(uint32_t* fcr31, double* value)
|
||||
{
|
||||
switch (fpclassify(*value))
|
||||
{
|
||||
@@ -430,7 +436,7 @@ M64P_FPU_INLINE void fpu_reset_exceptions()
|
||||
{
|
||||
}
|
||||
|
||||
M64P_FPU_INLINE int fpu_check_exceptions(uint32_t* fcr31)
|
||||
M64P_FPU_INLINE int fpu_check_exceptions(uint32_t* fcr31, uint8_t checkInvalidOp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -475,7 +481,7 @@ M64P_FPU_INLINE int cvt_s_w(uint32_t* fcr31, const int32_t* source, float* dest)
|
||||
|
||||
float value = (float)*source;
|
||||
|
||||
if (fpu_check_exceptions(fcr31)) return 1;
|
||||
if (fpu_check_exceptions(fcr31, 0)) return 1;
|
||||
if (fpu_check_output_float(fcr31, &value)) return 1;
|
||||
|
||||
*dest = value;
|
||||
@@ -490,7 +496,7 @@ M64P_FPU_INLINE int cvt_d_w(uint32_t* fcr31, const int32_t* source, double* dest
|
||||
|
||||
double value = (double)*source;
|
||||
|
||||
if (fpu_check_exceptions(fcr31)) return 1;
|
||||
if (fpu_check_exceptions(fcr31, 0)) return 1;
|
||||
if (fpu_check_output_double(fcr31, &value)) return 1;
|
||||
|
||||
*dest = value;
|
||||
@@ -512,7 +518,7 @@ M64P_FPU_INLINE int cvt_s_l(uint32_t* fcr31, const int64_t* source, float* dest)
|
||||
|
||||
float value = (float)*source;
|
||||
|
||||
if (fpu_check_exceptions(fcr31)) return 1;
|
||||
if (fpu_check_exceptions(fcr31, 0)) return 1;
|
||||
if (fpu_check_output_float(fcr31, &value)) return 1;
|
||||
|
||||
*dest = value;
|
||||
@@ -534,7 +540,7 @@ M64P_FPU_INLINE int cvt_d_l(uint32_t* fcr31, const int64_t* source, double* dest
|
||||
|
||||
double value = (double)*source;
|
||||
|
||||
if (fpu_check_exceptions(fcr31)) return 1;
|
||||
if (fpu_check_exceptions(fcr31, 0)) return 1;
|
||||
if (fpu_check_output_double(fcr31, &value)) return 1;
|
||||
|
||||
*dest = value;
|
||||
@@ -551,7 +557,7 @@ M64P_FPU_INLINE int cvt_d_s(uint32_t* fcr31, const float* source, double* dest)
|
||||
|
||||
double value = (double)*source;
|
||||
|
||||
if (fpu_check_exceptions(fcr31)) return 1;
|
||||
if (fpu_check_exceptions(fcr31, 0)) return 1;
|
||||
if (fpu_check_output_double(fcr31, &value)) return 1;
|
||||
|
||||
*dest = value;
|
||||
@@ -568,7 +574,7 @@ M64P_FPU_INLINE int cvt_s_d(uint32_t* fcr31, const double* source, float* dest)
|
||||
|
||||
float value = (float)*source;
|
||||
|
||||
if (fpu_check_exceptions(fcr31)) return 1;
|
||||
if (fpu_check_exceptions(fcr31, 0)) return 1;
|
||||
if (fpu_check_output_float(fcr31, &value)) return 1;
|
||||
|
||||
*dest = value;
|
||||
@@ -605,7 +611,7 @@ M64P_FPU_INLINE int round_w_s(uint32_t* fcr31, const float* source, int32_t* des
|
||||
|
||||
int32_t value = (int32_t)roundf(*source);
|
||||
|
||||
if (fpu_check_exceptions(fcr31)) return 1;
|
||||
if (fpu_check_exceptions(fcr31, 0)) return 1;
|
||||
|
||||
if (*source != value)
|
||||
{
|
||||
@@ -632,7 +638,7 @@ M64P_FPU_INLINE int trunc_w_s(uint32_t* fcr31, const float* source, int32_t* des
|
||||
|
||||
int32_t value = (int32_t)truncf(*source);
|
||||
|
||||
if (fpu_check_exceptions(fcr31)) return 1;
|
||||
if (fpu_check_exceptions(fcr31, 0)) return 1;
|
||||
|
||||
if (*source != value)
|
||||
{
|
||||
@@ -659,7 +665,7 @@ M64P_FPU_INLINE int ceil_w_s(uint32_t* fcr31, const float* source, int32_t* dest
|
||||
|
||||
int32_t value = (int32_t)ceilf(*source);
|
||||
|
||||
if (fpu_check_exceptions(fcr31)) return 1;
|
||||
if (fpu_check_exceptions(fcr31, 0)) return 1;
|
||||
|
||||
*dest = value;
|
||||
return 0;
|
||||
@@ -748,7 +754,7 @@ M64P_FPU_INLINE int cvt_w_s(uint32_t* fcr31, const float* source, int32_t* dest)
|
||||
|
||||
int32_t value = rintf(*source);
|
||||
|
||||
if (fpu_check_exceptions(fcr31)) return 1;
|
||||
if (fpu_check_exceptions(fcr31, 0)) return 1;
|
||||
|
||||
*dest = value;
|
||||
return 0;
|
||||
@@ -764,7 +770,7 @@ M64P_FPU_INLINE int cvt_w_d(uint32_t* fcr31, const double* source, int32_t* dest
|
||||
|
||||
int32_t value = rint(*source);
|
||||
|
||||
if (fpu_check_exceptions(fcr31)) return 1;
|
||||
if (fpu_check_exceptions(fcr31, 0)) return 1;
|
||||
|
||||
*dest = value;
|
||||
return 0;
|
||||
@@ -783,7 +789,7 @@ M64P_FPU_INLINE void cvt_l_s(uint32_t* fcr31, const float* source, int64_t* dest
|
||||
case 3: floor_l_s(source, dest); return;
|
||||
}
|
||||
|
||||
fpu_check_exceptions(fcr31);
|
||||
fpu_check_exceptions(fcr31, 0);
|
||||
}
|
||||
M64P_FPU_INLINE void cvt_l_d(uint32_t* fcr31, const double* source, int64_t* dest)
|
||||
{
|
||||
@@ -798,7 +804,7 @@ M64P_FPU_INLINE void cvt_l_d(uint32_t* fcr31, const double* source, int64_t* des
|
||||
case 3: floor_l_d(source, dest); return;
|
||||
}
|
||||
|
||||
fpu_check_exceptions(fcr31);
|
||||
fpu_check_exceptions(fcr31, 0);
|
||||
}
|
||||
|
||||
M64P_FPU_INLINE void c_f_s(uint32_t* fcr31, const float* source, const float* target)
|
||||
@@ -1295,7 +1301,7 @@ M64P_FPU_INLINE int add_s(uint32_t* fcr31, const float* source1, const float* so
|
||||
|
||||
float value = *source1 + *source2;
|
||||
|
||||
if (fpu_check_exceptions(fcr31)) return 1;
|
||||
if (fpu_check_exceptions(fcr31, 0)) return 1;
|
||||
if (fpu_check_output_float(fcr31, &value)) return 1;
|
||||
|
||||
*target = value;
|
||||
@@ -1314,7 +1320,7 @@ M64P_FPU_INLINE int sub_s(uint32_t* fcr31, const float* source1, const float* so
|
||||
|
||||
float value = *source1 - *source2;
|
||||
|
||||
if (fpu_check_exceptions(fcr31)) return 1;
|
||||
if (fpu_check_exceptions(fcr31, 0)) return 1;
|
||||
if (fpu_check_output_float(fcr31, &value)) return 1;
|
||||
|
||||
*target = value;
|
||||
@@ -1333,7 +1339,7 @@ M64P_FPU_INLINE int mul_s(uint32_t* fcr31, const float* source1, const float* so
|
||||
|
||||
float value = *source1 * *source2;
|
||||
|
||||
if (fpu_check_exceptions(fcr31)) return 1;
|
||||
if (fpu_check_exceptions(fcr31, 0)) return 1;
|
||||
if (fpu_check_output_float(fcr31, &value)) return 1;
|
||||
|
||||
*target = value;
|
||||
@@ -1352,7 +1358,7 @@ M64P_FPU_INLINE int div_s(uint32_t* fcr31, const float* source1, const float* so
|
||||
|
||||
float value = *source1 / *source2;
|
||||
|
||||
if (fpu_check_exceptions(fcr31)) return 1;
|
||||
if (fpu_check_exceptions(fcr31, 0)) return 1;
|
||||
if (fpu_check_output_float(fcr31, &value)) return 1;
|
||||
|
||||
*target = value;
|
||||
@@ -1370,7 +1376,7 @@ M64P_FPU_INLINE int sqrt_s(uint32_t* fcr31, const float* source, float* target)
|
||||
|
||||
float value = sqrtf(*source);
|
||||
|
||||
if (fpu_check_exceptions(fcr31)) return 1;
|
||||
if (fpu_check_exceptions(fcr31, 0)) return 1;
|
||||
if (fpu_check_output_float(fcr31, &value)) return 1;
|
||||
|
||||
*target = value;
|
||||
@@ -1419,7 +1425,7 @@ M64P_FPU_INLINE int add_d(uint32_t* fcr31, const double* source1, const double*
|
||||
|
||||
double value = *source1 + *source2;
|
||||
|
||||
if (fpu_check_exceptions(fcr31)) return 1;
|
||||
if (fpu_check_exceptions(fcr31, 0)) return 1;
|
||||
if (fpu_check_output_double(fcr31, &value)) return 1;
|
||||
|
||||
*target = value;
|
||||
@@ -1438,7 +1444,7 @@ M64P_FPU_INLINE int sub_d(uint32_t* fcr31, const double* source1, const double*
|
||||
|
||||
double value = *source1 - *source2;
|
||||
|
||||
if (fpu_check_exceptions(fcr31)) return 1;
|
||||
if (fpu_check_exceptions(fcr31, 0)) return 1;
|
||||
if (fpu_check_output_double(fcr31, &value)) return 1;
|
||||
|
||||
*target = value;
|
||||
@@ -1457,7 +1463,7 @@ M64P_FPU_INLINE int mul_d(uint32_t* fcr31, const double* source1, const double*
|
||||
|
||||
double value = *source1 * *source2;
|
||||
|
||||
if (fpu_check_exceptions(fcr31)) return 1;
|
||||
if (fpu_check_exceptions(fcr31, 0)) return 1;
|
||||
if (fpu_check_output_double(fcr31, &value)) return 1;
|
||||
|
||||
*target = value;
|
||||
@@ -1476,7 +1482,7 @@ M64P_FPU_INLINE int div_d(uint32_t* fcr31, const double* source1, const double*
|
||||
|
||||
double value = *source1 / *source2;
|
||||
|
||||
if (fpu_check_exceptions(fcr31)) return 1;
|
||||
if (fpu_check_exceptions(fcr31, 0)) return 1;
|
||||
if (fpu_check_output_double(fcr31, &value)) return 1;
|
||||
|
||||
*target = value;
|
||||
@@ -1494,7 +1500,7 @@ M64P_FPU_INLINE int sqrt_d(uint32_t* fcr31, const double* source, double* target
|
||||
|
||||
double value = sqrt(*source);
|
||||
|
||||
if (fpu_check_exceptions(fcr31)) return 1;
|
||||
if (fpu_check_exceptions(fcr31, 0)) return 1;
|
||||
if (fpu_check_output_double(fcr31, &value)) return 1;
|
||||
|
||||
*target = value;
|
||||
|
||||
Reference in New Issue
Block a user