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
|
#define PPC_OPERATIONS_H
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "mathlib/ieeefp.hpp"
|
|
||||||
#include "mathlib/mathlib.hpp"
|
#include "mathlib/mathlib.hpp"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -200,6 +199,11 @@ struct op_mhraddsh {
|
|||||||
|
|
||||||
struct op_cvt_fp2si {
|
struct op_cvt_fp2si {
|
||||||
static inline int64 apply(uint32 a, float b) {
|
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));
|
return (int64)(b * (1U << a));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -46,4 +46,68 @@ extern "C" int fesetround(int);
|
|||||||
|
|
||||||
#endif /* FENV_H */
|
#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 */
|
#endif /* IEEEFP_H */
|
||||||
|
@ -25,83 +25,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.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
|
* Arch-dependent optimizations
|
||||||
@ -132,7 +55,7 @@ int mathlib_fpclassifyf (float x)
|
|||||||
uint32 wx;
|
uint32 wx;
|
||||||
int retval = FP_NORMAL;
|
int retval = FP_NORMAL;
|
||||||
|
|
||||||
GET_FLOAT_WORD (wx, x);
|
MATHLIB_GET_FLOAT_WORD (wx, x);
|
||||||
wx &= 0x7fffffff;
|
wx &= 0x7fffffff;
|
||||||
if (wx == 0)
|
if (wx == 0)
|
||||||
retval = FP_ZERO;
|
retval = FP_ZERO;
|
||||||
@ -149,7 +72,7 @@ int mathlib_fpclassify (double x)
|
|||||||
uint32 hx, lx;
|
uint32 hx, lx;
|
||||||
int retval = FP_NORMAL;
|
int retval = FP_NORMAL;
|
||||||
|
|
||||||
EXTRACT_WORDS (hx, lx, x);
|
MATHLIB_EXTRACT_WORDS (hx, lx, x);
|
||||||
lx |= hx & 0xfffff;
|
lx |= hx & 0xfffff;
|
||||||
hx &= 0x7ff00000;
|
hx &= 0x7ff00000;
|
||||||
if ((hx | lx) == 0)
|
if ((hx | lx) == 0)
|
||||||
@ -176,7 +99,7 @@ int mathlib_signbitf (float x)
|
|||||||
{
|
{
|
||||||
int32 hx;
|
int32 hx;
|
||||||
|
|
||||||
GET_FLOAT_WORD (hx, x);
|
MATHLIB_GET_FLOAT_WORD (hx, x);
|
||||||
return hx & 0x80000000;
|
return hx & 0x80000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,7 +107,7 @@ int mathlib_signbit (double x)
|
|||||||
{
|
{
|
||||||
int32 hx;
|
int32 hx;
|
||||||
|
|
||||||
GET_HIGH_WORD (hx, x);
|
MATHLIB_GET_HIGH_WORD (hx, x);
|
||||||
return hx & 0x80000000;
|
return hx & 0x80000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,7 +126,7 @@ float mathlib_roundf(float x)
|
|||||||
int32 i0, j0;
|
int32 i0, j0;
|
||||||
static const float huge = 1.0e30;
|
static const float huge = 1.0e30;
|
||||||
|
|
||||||
GET_FLOAT_WORD (i0, x);
|
MATHLIB_GET_FLOAT_WORD (i0, x);
|
||||||
j0 = ((i0 >> 23) & 0xff) - 0x7f;
|
j0 = ((i0 >> 23) & 0xff) - 0x7f;
|
||||||
if (j0 < 23) {
|
if (j0 < 23) {
|
||||||
if (j0 < 0) {
|
if (j0 < 0) {
|
||||||
@ -233,6 +156,6 @@ float mathlib_roundf(float x)
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
SET_FLOAT_WORD (x, i0);
|
MATHLIB_SET_FLOAT_WORD (x, i0);
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#define MATHLIB_H
|
#define MATHLIB_H
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include "mathlib/ieeefp.hpp"
|
||||||
|
|
||||||
// Broken MacOS X headers
|
// Broken MacOS X headers
|
||||||
#if defined(__APPLE__) && defined(__MACH__)
|
#if defined(__APPLE__) && defined(__MACH__)
|
||||||
@ -168,6 +169,87 @@ extern int mathlib_fpclassifyl(long double x);
|
|||||||
? mathlib_fpclassify (x) : mathlib_fpclassifyl (x))
|
? mathlib_fpclassify (x) : mathlib_fpclassifyl (x))
|
||||||
#endif
|
#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
|
// 7.12.3.6 The signbit macro
|
||||||
#ifndef signbit
|
#ifndef signbit
|
||||||
#ifndef mathlib_signbitf
|
#ifndef mathlib_signbitf
|
||||||
@ -198,15 +280,4 @@ extern int mathlib_signbitl(long double x);
|
|||||||
#define isless(x, y) ((x) < (y))
|
#define isless(x, y) ((x) < (y))
|
||||||
#endif
|
#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 */
|
#endif /* MATHLIB_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user