Fix vctsxs & vctuxs emulation (VEX's jm-ppc-test -a, triggered inf/nan bugs)

This commit is contained in:
gbeauche 2006-07-04 04:37:15 +00:00
parent 0a2f9d3f03
commit 39ee6ba1aa
4 changed files with 157 additions and 95 deletions

View File

@ -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));
} }
}; };

View File

@ -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 */

View File

@ -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;
} }

View File

@ -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 */