mirror of
https://github.com/kanjitalk755/macemu.git
synced 2025-03-01 07:30:27 +00:00
Fix vctsxs & vctuxs emulation (VEX's jm-ppc-test -a, triggered inf/nan bugs)
This commit is contained in:
parent
0a2f9d3f03
commit
39ee6ba1aa
@ -22,7 +22,6 @@
|
||||
#define PPC_OPERATIONS_H
|
||||
|
||||
#include <math.h>
|
||||
#include "mathlib/ieeefp.hpp"
|
||||
#include "mathlib/mathlib.hpp"
|
||||
|
||||
/**
|
||||
@ -200,6 +199,11 @@ struct op_mhraddsh {
|
||||
|
||||
struct op_cvt_fp2si {
|
||||
static inline int64 apply(uint32 a, float b) {
|
||||
// Delegate saturation to upper level
|
||||
if (mathlib_isinf(b))
|
||||
return ((int64)(b < 0 ? 0x80000000 : 0x7fffffff)) << 32;
|
||||
if (mathlib_isnan(b))
|
||||
return 0;
|
||||
return (int64)(b * (1U << a));
|
||||
}
|
||||
};
|
||||
|
@ -46,4 +46,68 @@ extern "C" int fesetround(int);
|
||||
|
||||
#endif /* FENV_H */
|
||||
|
||||
// HOST_FLOAT_WORDS_BIG_ENDIAN is a tristate:
|
||||
// yes (1) / no (0) / default (undefined)
|
||||
#if HOST_FLOAT_WORDS_BIG_ENDIAN
|
||||
#define FLOAT_WORD_ORDER_BIG_ENDIAN
|
||||
#elif defined(WORDS_BIGENDIAN)
|
||||
#define FLOAT_WORD_ORDER_BIG_ENDIAN
|
||||
#endif
|
||||
|
||||
// Representation of an IEEE 754 float
|
||||
union mathlib_ieee_float_shape_type {
|
||||
float value;
|
||||
uint32 word;
|
||||
};
|
||||
|
||||
#define MATHLIB_GET_FLOAT_WORD(i,d) \
|
||||
do { \
|
||||
mathlib_ieee_float_shape_type gf_u; \
|
||||
gf_u.value = (d); \
|
||||
(i) = gf_u.word; \
|
||||
} while (0)
|
||||
|
||||
#define MATHLIB_SET_FLOAT_WORD(d,i) \
|
||||
do { \
|
||||
mathlib_ieee_float_shape_type sf_u; \
|
||||
sf_u.word = (i); \
|
||||
(d) = sf_u.value; \
|
||||
} while (0)
|
||||
|
||||
// Representation of an IEEE 754 double
|
||||
union mathlib_ieee_double_shape_type {
|
||||
double value;
|
||||
struct {
|
||||
#ifdef FLOAT_WORD_ORDER_BIG_ENDIAN
|
||||
uint32 msw;
|
||||
uint32 lsw;
|
||||
#else
|
||||
uint32 lsw;
|
||||
uint32 msw;
|
||||
#endif
|
||||
} parts;
|
||||
};
|
||||
|
||||
#define MATHLIB_EXTRACT_WORDS(ix0,ix1,d) \
|
||||
do { \
|
||||
mathlib_ieee_double_shape_type ew_u; \
|
||||
ew_u.value = (d); \
|
||||
(ix0) = ew_u.parts.msw; \
|
||||
(ix1) = ew_u.parts.lsw; \
|
||||
} while (0)
|
||||
|
||||
#define MATHLIB_GET_HIGH_WORD(i,d) \
|
||||
do { \
|
||||
mathlib_ieee_double_shape_type gh_u; \
|
||||
gh_u.value = (d); \
|
||||
(i) = gh_u.parts.msw; \
|
||||
} while (0)
|
||||
|
||||
#define MATHLIB_GET_LOW_WORD(i,d) \
|
||||
do { \
|
||||
mathlib_ieee_double_shape_type gl_u; \
|
||||
gl_u.value = (d); \
|
||||
(i) = gl_u.parts.lsw; \
|
||||
} while (0)
|
||||
|
||||
#endif /* IEEEFP_H */
|
||||
|
@ -25,83 +25,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// HOST_FLOAT_WORDS_BIG_ENDIAN is a tristate:
|
||||
// yes (1) / no (0) / default (undefined)
|
||||
#if HOST_FLOAT_WORDS_BIG_ENDIAN
|
||||
#define FLOAT_WORD_ORDER_BIG_ENDIAN
|
||||
#elif defined(WORDS_BIGENDIAN)
|
||||
#define FLOAT_WORD_ORDER_BIG_ENDIAN
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Representation of an IEEE 754 float
|
||||
**/
|
||||
|
||||
union ieee_float_shape_type {
|
||||
float value;
|
||||
uint32 word;
|
||||
};
|
||||
|
||||
// Get a 32 bit int from a float
|
||||
#define GET_FLOAT_WORD(i,d) \
|
||||
do { \
|
||||
ieee_float_shape_type gf_u; \
|
||||
gf_u.value = (d); \
|
||||
(i) = gf_u.word; \
|
||||
} while (0)
|
||||
|
||||
// Set a float from a 32 bit int
|
||||
#define SET_FLOAT_WORD(d,i) \
|
||||
do { \
|
||||
ieee_float_shape_type sf_u; \
|
||||
sf_u.word = (i); \
|
||||
(d) = sf_u.value; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/**
|
||||
* Representation of an IEEE 754 double
|
||||
**/
|
||||
|
||||
union ieee_double_shape_type {
|
||||
double value;
|
||||
struct {
|
||||
#ifdef FLOAT_WORD_ORDER_BIG_ENDIAN
|
||||
uint32 msw;
|
||||
uint32 lsw;
|
||||
#else
|
||||
uint32 lsw;
|
||||
uint32 msw;
|
||||
#endif
|
||||
} parts;
|
||||
};
|
||||
|
||||
// Get two 32-bit ints from a double
|
||||
#define EXTRACT_WORDS(ix0,ix1,d) \
|
||||
do { \
|
||||
ieee_double_shape_type ew_u; \
|
||||
ew_u.value = (d); \
|
||||
(ix0) = ew_u.parts.msw; \
|
||||
(ix1) = ew_u.parts.lsw; \
|
||||
} while (0)
|
||||
|
||||
// Get the more significant 32 bit int from a double
|
||||
#define GET_HIGH_WORD(i,d) \
|
||||
do { \
|
||||
ieee_double_shape_type gh_u; \
|
||||
gh_u.value = (d); \
|
||||
(i) = gh_u.parts.msw; \
|
||||
} while (0)
|
||||
|
||||
// Get the less significant 32 bit int from a double
|
||||
#define GET_LOW_WORD(i,d) \
|
||||
do { \
|
||||
ieee_double_shape_type gl_u; \
|
||||
gl_u.value = (d); \
|
||||
(i) = gl_u.parts.lsw; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/**
|
||||
* Arch-dependent optimizations
|
||||
@ -132,7 +55,7 @@ int mathlib_fpclassifyf (float x)
|
||||
uint32 wx;
|
||||
int retval = FP_NORMAL;
|
||||
|
||||
GET_FLOAT_WORD (wx, x);
|
||||
MATHLIB_GET_FLOAT_WORD (wx, x);
|
||||
wx &= 0x7fffffff;
|
||||
if (wx == 0)
|
||||
retval = FP_ZERO;
|
||||
@ -149,7 +72,7 @@ int mathlib_fpclassify (double x)
|
||||
uint32 hx, lx;
|
||||
int retval = FP_NORMAL;
|
||||
|
||||
EXTRACT_WORDS (hx, lx, x);
|
||||
MATHLIB_EXTRACT_WORDS (hx, lx, x);
|
||||
lx |= hx & 0xfffff;
|
||||
hx &= 0x7ff00000;
|
||||
if ((hx | lx) == 0)
|
||||
@ -176,7 +99,7 @@ int mathlib_signbitf (float x)
|
||||
{
|
||||
int32 hx;
|
||||
|
||||
GET_FLOAT_WORD (hx, x);
|
||||
MATHLIB_GET_FLOAT_WORD (hx, x);
|
||||
return hx & 0x80000000;
|
||||
}
|
||||
|
||||
@ -184,7 +107,7 @@ int mathlib_signbit (double x)
|
||||
{
|
||||
int32 hx;
|
||||
|
||||
GET_HIGH_WORD (hx, x);
|
||||
MATHLIB_GET_HIGH_WORD (hx, x);
|
||||
return hx & 0x80000000;
|
||||
}
|
||||
|
||||
@ -203,7 +126,7 @@ float mathlib_roundf(float x)
|
||||
int32 i0, j0;
|
||||
static const float huge = 1.0e30;
|
||||
|
||||
GET_FLOAT_WORD (i0, x);
|
||||
MATHLIB_GET_FLOAT_WORD (i0, x);
|
||||
j0 = ((i0 >> 23) & 0xff) - 0x7f;
|
||||
if (j0 < 23) {
|
||||
if (j0 < 0) {
|
||||
@ -233,6 +156,6 @@ float mathlib_roundf(float x)
|
||||
return x;
|
||||
}
|
||||
|
||||
SET_FLOAT_WORD (x, i0);
|
||||
MATHLIB_SET_FLOAT_WORD (x, i0);
|
||||
return x;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
#define MATHLIB_H
|
||||
|
||||
#include <math.h>
|
||||
#include "mathlib/ieeefp.hpp"
|
||||
|
||||
// Broken MacOS X headers
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
@ -168,6 +169,87 @@ extern int mathlib_fpclassifyl(long double x);
|
||||
? mathlib_fpclassify (x) : mathlib_fpclassifyl (x))
|
||||
#endif
|
||||
|
||||
// 7.12.3.2 The isfinite macro
|
||||
static inline int mathlib_isfinite(float x)
|
||||
{
|
||||
int32 ix;
|
||||
|
||||
MATHLIB_GET_FLOAT_WORD(ix, x);
|
||||
return (int)((uint32)((ix & 0x7fffffff) - 0x7f800000) >> 31);
|
||||
}
|
||||
|
||||
static inline int mathlib_isfinite(double x)
|
||||
{
|
||||
int32 hx;
|
||||
|
||||
MATHLIB_GET_HIGH_WORD(hx, x);
|
||||
return (int)((uint32)((hx & 0x7fffffff) - 0x7ff00000) >> 31);
|
||||
}
|
||||
|
||||
#ifndef isfinite
|
||||
#define isfinite(x) mathlib_isfinite(x)
|
||||
#endif
|
||||
|
||||
// 7.12.3.3 The isinf macro
|
||||
static inline int mathlib_isinf(float x)
|
||||
{
|
||||
int32 ix, t;
|
||||
|
||||
MATHLIB_GET_FLOAT_WORD(ix, x);
|
||||
t = ix & 0x7fffffff;
|
||||
t ^= 0x7f800000;
|
||||
t |= -t;
|
||||
return ~(t >> 31) & (ix >> 30);
|
||||
}
|
||||
|
||||
static inline int mathlib_isinf(double x)
|
||||
{
|
||||
int32 hx, lx;
|
||||
|
||||
MATHLIB_EXTRACT_WORDS(hx, lx, x);
|
||||
lx |= (hx & 0x7fffffff) ^ 0x7ff00000;
|
||||
lx |= -lx;
|
||||
return ~(lx >> 31) & (hx >> 30);
|
||||
}
|
||||
|
||||
#ifndef isinf
|
||||
#if defined __sgi && defined __mips
|
||||
// specialized implementation for IRIX mips compilers
|
||||
extern "C" int _isinf(double);
|
||||
extern "C" int _isinff(float);
|
||||
static inline int isinf(double x) { return _isinf(x); }
|
||||
static inline int isinf(float x) { return _isinff(x); }
|
||||
#else
|
||||
#define isinf(x) mathlib_isinf(x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// 7.12.3.4 The isnan macro
|
||||
static inline int mathlib_isnan(float x)
|
||||
{
|
||||
int32 ix;
|
||||
|
||||
MATHLIB_GET_FLOAT_WORD(ix, x);
|
||||
ix &= 0x7fffffff;
|
||||
ix = 0x7f800000 - ix;
|
||||
return (int)(((uint32)ix) >> 31);
|
||||
}
|
||||
|
||||
static inline int mathlib_isnan(double x)
|
||||
{
|
||||
int32 hx, lx;
|
||||
|
||||
MATHLIB_EXTRACT_WORDS(hx, lx, x);
|
||||
hx &= 0x7fffffff;
|
||||
hx |= (uint32)(lx|(-lx)) >> 31;
|
||||
hx = 0x7ff00000 - hx;
|
||||
return (int)(((uint32)hx) >> 31);
|
||||
}
|
||||
|
||||
#ifndef isnan
|
||||
#define isnan(x) mathlib_isnan(x)
|
||||
#endif
|
||||
|
||||
// 7.12.3.6 The signbit macro
|
||||
#ifndef signbit
|
||||
#ifndef mathlib_signbitf
|
||||
@ -198,15 +280,4 @@ extern int mathlib_signbitl(long double x);
|
||||
#define isless(x, y) ((x) < (y))
|
||||
#endif
|
||||
|
||||
// 7.12.3.3 The isinf macro
|
||||
#ifndef isinf
|
||||
#if defined __sgi && defined __mips
|
||||
// specialized implementation for IRIX mips compilers
|
||||
extern "C" int _isinf(double);
|
||||
extern "C" int _isinff(float);
|
||||
static inline int isinf(double x) { return _isinf(x); }
|
||||
static inline int isinf(float x) { return _isinff(x); }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* MATHLIB_H */
|
||||
|
Loading…
x
Reference in New Issue
Block a user