提交 f090c9d4 编写于 作者: P pbrook

Add strict checking mode for softfp code.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3688 c046a42c-6fe2-441c-8c8c-71466251a162
上级 b881c2c6
...@@ -66,9 +66,9 @@ typedef struct { ...@@ -66,9 +66,9 @@ typedef struct {
| The pattern for a default generated single-precision NaN. | The pattern for a default generated single-precision NaN.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if SNAN_BIT_IS_ONE #if SNAN_BIT_IS_ONE
#define float32_default_nan 0x7FBFFFFF #define float32_default_nan make_float32(0x7FBFFFFF)
#else #else
#define float32_default_nan 0xFFC00000 #define float32_default_nan make_float32(0xFFC00000)
#endif #endif
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
...@@ -76,8 +76,9 @@ typedef struct { ...@@ -76,8 +76,9 @@ typedef struct {
| NaN; otherwise returns 0. | NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
int float32_is_nan( float32 a ) int float32_is_nan( float32 a_ )
{ {
uint32_t a = float32_val(a_);
#if SNAN_BIT_IS_ONE #if SNAN_BIT_IS_ONE
return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
#else #else
...@@ -90,8 +91,9 @@ int float32_is_nan( float32 a ) ...@@ -90,8 +91,9 @@ int float32_is_nan( float32 a )
| NaN; otherwise returns 0. | NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
int float32_is_signaling_nan( float32 a ) int float32_is_signaling_nan( float32 a_ )
{ {
uint32_t a = float32_val(a_);
#if SNAN_BIT_IS_ONE #if SNAN_BIT_IS_ONE
return ( 0xFF800000 <= (bits32) ( a<<1 ) ); return ( 0xFF800000 <= (bits32) ( a<<1 ) );
#else #else
...@@ -110,9 +112,9 @@ static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM ) ...@@ -110,9 +112,9 @@ static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )
commonNaNT z; commonNaNT z;
if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR ); if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR );
z.sign = a>>31; z.sign = float32_val(a)>>31;
z.low = 0; z.low = 0;
z.high = ( (bits64) a )<<41; z.high = ( (bits64) float32_val(a) )<<41;
return z; return z;
} }
...@@ -123,7 +125,8 @@ static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM ) ...@@ -123,7 +125,8 @@ static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )
static float32 commonNaNToFloat32( commonNaNT a ) static float32 commonNaNToFloat32( commonNaNT a )
{ {
return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); return make_float32(
( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ) );
} }
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
...@@ -135,42 +138,52 @@ static float32 commonNaNToFloat32( commonNaNT a ) ...@@ -135,42 +138,52 @@ static float32 commonNaNToFloat32( commonNaNT a )
static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM) static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
{ {
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
bits32 av, bv, res;
aIsNaN = float32_is_nan( a ); aIsNaN = float32_is_nan( a );
aIsSignalingNaN = float32_is_signaling_nan( a ); aIsSignalingNaN = float32_is_signaling_nan( a );
bIsNaN = float32_is_nan( b ); bIsNaN = float32_is_nan( b );
bIsSignalingNaN = float32_is_signaling_nan( b ); bIsSignalingNaN = float32_is_signaling_nan( b );
av = float32_val(a);
bv = float32_val(b);
#if SNAN_BIT_IS_ONE #if SNAN_BIT_IS_ONE
a &= ~0x00400000; av &= ~0x00400000;
b &= ~0x00400000; bv &= ~0x00400000;
#else #else
a |= 0x00400000; av |= 0x00400000;
b |= 0x00400000; bv |= 0x00400000;
#endif #endif
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR); if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
if ( aIsSignalingNaN ) { if ( aIsSignalingNaN ) {
if ( bIsSignalingNaN ) goto returnLargerSignificand; if ( bIsSignalingNaN ) goto returnLargerSignificand;
return bIsNaN ? b : a; res = bIsNaN ? bv : av;
} }
else if ( aIsNaN ) { else if ( aIsNaN ) {
if ( bIsSignalingNaN | ! bIsNaN ) return a; if ( bIsSignalingNaN | ! bIsNaN )
res = av;
else {
returnLargerSignificand: returnLargerSignificand:
if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b; if ( (bits32) ( av<<1 ) < (bits32) ( bv<<1 ) )
if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a; res = bv;
return ( a < b ) ? a : b; else if ( (bits32) ( bv<<1 ) < (bits32) ( av<<1 ) )
res = av;
else
res = ( av < bv ) ? av : bv;
}
} }
else { else {
return b; res = bv;
} }
return make_float32(res);
} }
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The pattern for a default generated double-precision NaN. | The pattern for a default generated double-precision NaN.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if SNAN_BIT_IS_ONE #if SNAN_BIT_IS_ONE
#define float64_default_nan LIT64( 0x7FF7FFFFFFFFFFFF ) #define float64_default_nan make_float64(LIT64( 0x7FF7FFFFFFFFFFFF ))
#else #else
#define float64_default_nan LIT64( 0xFFF8000000000000 ) #define float64_default_nan make_float64(LIT64( 0xFFF8000000000000 ))
#endif #endif
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
...@@ -178,8 +191,9 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM) ...@@ -178,8 +191,9 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
| NaN; otherwise returns 0. | NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
int float64_is_nan( float64 a ) int float64_is_nan( float64 a_ )
{ {
bits64 a = float64_val(a_);
#if SNAN_BIT_IS_ONE #if SNAN_BIT_IS_ONE
return return
( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
...@@ -194,8 +208,9 @@ int float64_is_nan( float64 a ) ...@@ -194,8 +208,9 @@ int float64_is_nan( float64 a )
| NaN; otherwise returns 0. | NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
int float64_is_signaling_nan( float64 a ) int float64_is_signaling_nan( float64 a_ )
{ {
bits64 a = float64_val(a_);
#if SNAN_BIT_IS_ONE #if SNAN_BIT_IS_ONE
return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) ); return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) );
#else #else
...@@ -216,9 +231,9 @@ static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM) ...@@ -216,9 +231,9 @@ static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)
commonNaNT z; commonNaNT z;
if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR); if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
z.sign = a>>63; z.sign = float64_val(a)>>63;
z.low = 0; z.low = 0;
z.high = a<<12; z.high = float64_val(a)<<12;
return z; return z;
} }
...@@ -229,10 +244,10 @@ static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM) ...@@ -229,10 +244,10 @@ static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)
static float64 commonNaNToFloat64( commonNaNT a ) static float64 commonNaNToFloat64( commonNaNT a )
{ {
return return make_float64(
( ( (bits64) a.sign )<<63 ) ( ( (bits64) a.sign )<<63 )
| LIT64( 0x7FF8000000000000 ) | LIT64( 0x7FF8000000000000 )
| ( a.high>>12 ); | ( a.high>>12 ));
} }
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
...@@ -244,33 +259,43 @@ static float64 commonNaNToFloat64( commonNaNT a ) ...@@ -244,33 +259,43 @@ static float64 commonNaNToFloat64( commonNaNT a )
static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM) static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
{ {
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
bits64 av, bv, res;
aIsNaN = float64_is_nan( a ); aIsNaN = float64_is_nan( a );
aIsSignalingNaN = float64_is_signaling_nan( a ); aIsSignalingNaN = float64_is_signaling_nan( a );
bIsNaN = float64_is_nan( b ); bIsNaN = float64_is_nan( b );
bIsSignalingNaN = float64_is_signaling_nan( b ); bIsSignalingNaN = float64_is_signaling_nan( b );
av = float64_val(a);
bv = float64_val(b);
#if SNAN_BIT_IS_ONE #if SNAN_BIT_IS_ONE
a &= ~LIT64( 0x0008000000000000 ); av &= ~LIT64( 0x0008000000000000 );
b &= ~LIT64( 0x0008000000000000 ); bv &= ~LIT64( 0x0008000000000000 );
#else #else
a |= LIT64( 0x0008000000000000 ); av |= LIT64( 0x0008000000000000 );
b |= LIT64( 0x0008000000000000 ); bv |= LIT64( 0x0008000000000000 );
#endif #endif
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR); if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
if ( aIsSignalingNaN ) { if ( aIsSignalingNaN ) {
if ( bIsSignalingNaN ) goto returnLargerSignificand; if ( bIsSignalingNaN ) goto returnLargerSignificand;
return bIsNaN ? b : a; res = bIsNaN ? bv : av;
} }
else if ( aIsNaN ) { else if ( aIsNaN ) {
if ( bIsSignalingNaN | ! bIsNaN ) return a; if ( bIsSignalingNaN | ! bIsNaN )
res = av;
else {
returnLargerSignificand: returnLargerSignificand:
if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b; if ( (bits64) ( av<<1 ) < (bits64) ( bv<<1 ) )
if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a; res = bv;
return ( a < b ) ? a : b; else if ( (bits64) ( bv<<1 ) < (bits64) ( av<<1 ) )
res = av;
else
res = ( av < bv ) ? av : bv;
}
} }
else { else {
return b; res = bv;
} }
return make_float64(res);
} }
#ifdef FLOATX80 #ifdef FLOATX80
......
此差异已折叠。
...@@ -111,8 +111,31 @@ enum { ...@@ -111,8 +111,31 @@ enum {
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point types. | Software IEC/IEEE floating-point types.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/* Use structures for soft-float types. This prevents accidentally mixing
them with native int/float types. A sufficiently clever compiler and
sane ABI should be able to see though these structs. However
x86/gcc 3.x seems to struggle a bit, so leave them disabled by default. */
//#define USE_SOFTFLOAT_STRUCT_TYPES
#ifdef USE_SOFTFLOAT_STRUCT_TYPES
typedef struct {
uint32_t v;
} float32;
/* The cast ensures an error if the wrong type is passed. */
#define float32_val(x) (((float32)(x)).v)
#define make_float32(x) __extension__ ({ float32 f32_val = {x}; f32_val; })
typedef struct {
uint64_t v;
} float64;
#define float64_val(x) (((float64)(x)).v)
#define make_float64(x) __extension__ ({ float64 f64_val = {x}; f64_val; })
#else
typedef uint32_t float32; typedef uint32_t float32;
typedef uint64_t float64; typedef uint64_t float64;
#define float32_val(x) (x)
#define float64_val(x) (x)
#define make_float32(x) (x)
#define make_float64(x) (x)
#endif
#ifdef FLOATX80 #ifdef FLOATX80
typedef struct { typedef struct {
uint64_t low; uint64_t low;
...@@ -248,14 +271,16 @@ float32 float32_scalbn( float32, int STATUS_PARAM ); ...@@ -248,14 +271,16 @@ float32 float32_scalbn( float32, int STATUS_PARAM );
INLINE float32 float32_abs(float32 a) INLINE float32 float32_abs(float32 a)
{ {
return a & 0x7fffffff; return make_float32(float32_val(a) & 0x7fffffff);
} }
INLINE float32 float32_chs(float32 a) INLINE float32 float32_chs(float32 a)
{ {
return a ^ 0x80000000; return make_float32(float32_val(a) ^ 0x80000000);
} }
#define float32_zero make_float32(0)
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision conversion routines. | Software IEC/IEEE double-precision conversion routines.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
...@@ -300,14 +325,16 @@ float64 float64_scalbn( float64, int STATUS_PARAM ); ...@@ -300,14 +325,16 @@ float64 float64_scalbn( float64, int STATUS_PARAM );
INLINE float64 float64_abs(float64 a) INLINE float64 float64_abs(float64 a)
{ {
return a & 0x7fffffffffffffffLL; return make_float64(float64_val(a) & 0x7fffffffffffffffLL);
} }
INLINE float64 float64_chs(float64 a) INLINE float64 float64_chs(float64 a)
{ {
return a ^ 0x8000000000000000LL; return make_float64(float64_val(a) ^ 0x8000000000000000LL);
} }
#define float64_zero make_float64(0)
#ifdef FLOATX80 #ifdef FLOATX80
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
......
...@@ -38,7 +38,7 @@ float64 float64_pol(float64 rFn,float64 rFm); ...@@ -38,7 +38,7 @@ float64 float64_pol(float64 rFn,float64 rFm);
unsigned int DoubleCPDO(const unsigned int opcode) unsigned int DoubleCPDO(const unsigned int opcode)
{ {
FPA11 *fpa11 = GET_FPA11(); FPA11 *fpa11 = GET_FPA11();
float64 rFm, rFn = 0; float64 rFm, rFn = float64_zero;
unsigned int Fd, Fm, Fn, nRc = 1; unsigned int Fd, Fm, Fn, nRc = 1;
//printk("DoubleCPDO(0x%08x)\n",opcode); //printk("DoubleCPDO(0x%08x)\n",opcode);
......
...@@ -38,7 +38,7 @@ float32 float32_pol(float32 rFn,float32 rFm); ...@@ -38,7 +38,7 @@ float32 float32_pol(float32 rFn,float32 rFm);
unsigned int SingleCPDO(const unsigned int opcode) unsigned int SingleCPDO(const unsigned int opcode)
{ {
FPA11 *fpa11 = GET_FPA11(); FPA11 *fpa11 = GET_FPA11();
float32 rFm, rFn = 0; float32 rFm, rFn = float32_zero;
unsigned int Fd, Fm, Fn, nRc = 1; unsigned int Fd, Fm, Fn, nRc = 1;
Fm = getFm(opcode); Fm = getFm(opcode);
...@@ -128,13 +128,11 @@ unsigned int SingleCPDO(const unsigned int opcode) ...@@ -128,13 +128,11 @@ unsigned int SingleCPDO(const unsigned int opcode)
break; break;
case MNF_CODE: case MNF_CODE:
rFm ^= 0x80000000; fpa11->fpreg[Fd].fSingle = float32_chs(rFm);
fpa11->fpreg[Fd].fSingle = rFm;
break; break;
case ABS_CODE: case ABS_CODE:
rFm &= 0x7fffffff; fpa11->fpreg[Fd].fSingle = float32_abs(rFm);
fpa11->fpreg[Fd].fSingle = rFm;
break; break;
case RND_CODE: case RND_CODE:
......
...@@ -255,7 +255,7 @@ float64 helper_sub_cmpf64(CPUM68KState *env, float64 src0, float64 src1) ...@@ -255,7 +255,7 @@ float64 helper_sub_cmpf64(CPUM68KState *env, float64 src0, float64 src1)
/* +/-inf compares equal against itself, but sub returns nan. */ /* +/-inf compares equal against itself, but sub returns nan. */
if (!float64_is_nan(src0) if (!float64_is_nan(src0)
&& !float64_is_nan(src1)) { && !float64_is_nan(src1)) {
res = 0; res = float64_zero;
if (float64_lt_quiet(src0, res, &env->fp_status)) if (float64_lt_quiet(src0, res, &env->fp_status))
res = float64_chs(res); res = float64_chs(res);
} }
......
...@@ -108,7 +108,7 @@ OP(movf64) ...@@ -108,7 +108,7 @@ OP(movf64)
OP(zerof64) OP(zerof64)
{ {
set_opf64(PARAM1, 0); set_opf64(PARAM1, float64_zero);
FORCE_RET(); FORCE_RET();
} }
......
...@@ -624,10 +624,10 @@ void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, ...@@ -624,10 +624,10 @@ void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
/* Complex FPU operations which may need stack space. */ /* Complex FPU operations which may need stack space. */
#define FLOAT_ONE32 (0x3f8 << 20) #define FLOAT_ONE32 make_float32(0x3f8 << 20)
#define FLOAT_ONE64 (0x3ffULL << 52) #define FLOAT_ONE64 make_float64(0x3ffULL << 52)
#define FLOAT_TWO32 (1 << 30) #define FLOAT_TWO32 make_float32(1 << 30)
#define FLOAT_TWO64 (1ULL << 62) #define FLOAT_TWO64 make_float64(1ULL << 62)
#define FLOAT_QNAN32 0x7fbfffff #define FLOAT_QNAN32 0x7fbfffff
#define FLOAT_QNAN64 0x7ff7ffffffffffffULL #define FLOAT_QNAN64 0x7ff7ffffffffffffULL
#define FLOAT_SNAN32 0x7fffffff #define FLOAT_SNAN32 0x7fffffff
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册