Commit f090c9d4 authored by Paul Brook's avatar Paul Brook
Browse files

Add strict checking mode for softfp code.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3688 c046a42c-6fe2-441c-8c8c-71466251a162
parent b881c2c6
Loading
Loading
Loading
Loading
+60 −35
Original line number Diff line number Diff line
@@ -66,9 +66,9 @@ typedef struct {
| The pattern for a default generated single-precision NaN.
*----------------------------------------------------------------------------*/
#if SNAN_BIT_IS_ONE
#define float32_default_nan 0x7FBFFFFF
#define float32_default_nan make_float32(0x7FBFFFFF)
#else
#define float32_default_nan 0xFFC00000
#define float32_default_nan make_float32(0xFFC00000)
#endif

/*----------------------------------------------------------------------------
@@ -76,8 +76,9 @@ typedef struct {
| 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
    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
#else
@@ -90,8 +91,9 @@ int float32_is_nan( float32 a )
| 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
    return ( 0xFF800000 <= (bits32) ( a<<1 ) );
#else
@@ -110,9 +112,9 @@ static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )
    commonNaNT z;

    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.high = ( (bits64) a )<<41;
    z.high = ( (bits64) float32_val(a) )<<41;
    return z;
}

@@ -123,7 +125,8 @@ static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )

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 )
static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
{
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    bits32 av, bv, res;

    aIsNaN = float32_is_nan( a );
    aIsSignalingNaN = float32_is_signaling_nan( a );
    bIsNaN = float32_is_nan( b );
    bIsSignalingNaN = float32_is_signaling_nan( b );
    av = float32_val(a);
    bv = float32_val(b);
#if SNAN_BIT_IS_ONE
    a &= ~0x00400000;
    b &= ~0x00400000;
    av &= ~0x00400000;
    bv &= ~0x00400000;
#else
    a |= 0x00400000;
    b |= 0x00400000;
    av |= 0x00400000;
    bv |= 0x00400000;
#endif
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
    if ( aIsSignalingNaN ) {
        if ( bIsSignalingNaN ) goto returnLargerSignificand;
        return bIsNaN ? b : a;
        res = bIsNaN ? bv : av;
    }
    else if ( aIsNaN ) {
        if ( bIsSignalingNaN | ! bIsNaN ) return a;
        if ( bIsSignalingNaN | ! bIsNaN )
            res = av;
        else {
 returnLargerSignificand:
        if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b;
        if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a;
        return ( a < b ) ? a : b;
            if ( (bits32) ( av<<1 ) < (bits32) ( bv<<1 ) )
                res = bv;
            else if ( (bits32) ( bv<<1 ) < (bits32) ( av<<1 ) )
                res = av;
            else
                res = ( av < bv ) ? av : bv;
        }
    }
    else {
        return b;
        res = bv;
    }
    return make_float32(res);
}

/*----------------------------------------------------------------------------
| The pattern for a default generated double-precision NaN.
*----------------------------------------------------------------------------*/
#if SNAN_BIT_IS_ONE
#define float64_default_nan LIT64( 0x7FF7FFFFFFFFFFFF )
#define float64_default_nan make_float64(LIT64( 0x7FF7FFFFFFFFFFFF ))
#else
#define float64_default_nan LIT64( 0xFFF8000000000000 )
#define float64_default_nan make_float64(LIT64( 0xFFF8000000000000 ))
#endif

/*----------------------------------------------------------------------------
@@ -178,8 +191,9 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
| 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
    return
           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
@@ -194,8 +208,9 @@ int float64_is_nan( float64 a )
| 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
    return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) );
#else
@@ -216,9 +231,9 @@ static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)
    commonNaNT z;

    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.high = a<<12;
    z.high = float64_val(a)<<12;
    return z;
}

@@ -229,10 +244,10 @@ static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)

static float64 commonNaNToFloat64( commonNaNT a )
{
    return
    return make_float64(
          ( ( (bits64) a.sign )<<63 )
        | LIT64( 0x7FF8000000000000 )
        | ( a.high>>12 );
        | ( a.high>>12 ));
}

/*----------------------------------------------------------------------------
@@ -244,33 +259,43 @@ static float64 commonNaNToFloat64( commonNaNT a )
static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
{
    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    bits64 av, bv, res;

    aIsNaN = float64_is_nan( a );
    aIsSignalingNaN = float64_is_signaling_nan( a );
    bIsNaN = float64_is_nan( b );
    bIsSignalingNaN = float64_is_signaling_nan( b );
    av = float64_val(a);
    bv = float64_val(b);
#if SNAN_BIT_IS_ONE
    a &= ~LIT64( 0x0008000000000000 );
    b &= ~LIT64( 0x0008000000000000 );
    av &= ~LIT64( 0x0008000000000000 );
    bv &= ~LIT64( 0x0008000000000000 );
#else
    a |= LIT64( 0x0008000000000000 );
    b |= LIT64( 0x0008000000000000 );
    av |= LIT64( 0x0008000000000000 );
    bv |= LIT64( 0x0008000000000000 );
#endif
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
    if ( aIsSignalingNaN ) {
        if ( bIsSignalingNaN ) goto returnLargerSignificand;
        return bIsNaN ? b : a;
        res = bIsNaN ? bv : av;
    }
    else if ( aIsNaN ) {
        if ( bIsSignalingNaN | ! bIsNaN ) return a;
        if ( bIsSignalingNaN | ! bIsNaN )
            res = av;
        else {
 returnLargerSignificand:
        if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b;
        if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a;
        return ( a < b ) ? a : b;
            if ( (bits64) ( av<<1 ) < (bits64) ( bv<<1 ) )
                res = bv;
            else if ( (bits64) ( bv<<1 ) < (bits64) ( av<<1 ) )
                res = av;
            else
                res = ( av < bv ) ? av : bv;
        }
    }
    else {
        return b;
        res = bv;
    }
    return make_float64(res);
}

#ifdef FLOATX80
+109 −66

File changed.

Preview size limit exceeded, changes collapsed.

+31 −4
Original line number Diff line number Diff line
@@ -111,8 +111,31 @@ enum {
/*----------------------------------------------------------------------------
| 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 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
typedef struct {
    uint64_t low;
@@ -248,14 +271,16 @@ float32 float32_scalbn( float32, int STATUS_PARAM );

INLINE float32 float32_abs(float32 a)
{
    return a & 0x7fffffff;
    return make_float32(float32_val(a) & 0x7fffffff);
}

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.
*----------------------------------------------------------------------------*/
@@ -300,14 +325,16 @@ float64 float64_scalbn( float64, int STATUS_PARAM );

INLINE float64 float64_abs(float64 a)
{
    return a & 0x7fffffffffffffffLL;
    return make_float64(float64_val(a) & 0x7fffffffffffffffLL);
}

INLINE float64 float64_chs(float64 a)
{
    return a ^ 0x8000000000000000LL;
    return make_float64(float64_val(a) ^ 0x8000000000000000LL);
}

#define float64_zero make_float64(0)

#ifdef FLOATX80

/*----------------------------------------------------------------------------
+1 −1
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ float64 float64_pol(float64 rFn,float64 rFm);
unsigned int DoubleCPDO(const unsigned int opcode)
{
   FPA11 *fpa11 = GET_FPA11();
   float64 rFm, rFn = 0;
   float64 rFm, rFn = float64_zero;
   unsigned int Fd, Fm, Fn, nRc = 1;

   //printk("DoubleCPDO(0x%08x)\n",opcode);
+3 −5
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ float32 float32_pol(float32 rFn,float32 rFm);
unsigned int SingleCPDO(const unsigned int opcode)
{
   FPA11 *fpa11 = GET_FPA11();
   float32 rFm, rFn = 0;
   float32 rFm, rFn = float32_zero;
   unsigned int Fd, Fm, Fn, nRc = 1;

   Fm = getFm(opcode);
@@ -128,13 +128,11 @@ unsigned int SingleCPDO(const unsigned int opcode)
      break;

      case MNF_CODE:
         rFm ^= 0x80000000;
         fpa11->fpreg[Fd].fSingle = rFm;
         fpa11->fpreg[Fd].fSingle = float32_chs(rFm);
      break;

      case ABS_CODE:
         rFm &= 0x7fffffff;
         fpa11->fpreg[Fd].fSingle = rFm;
         fpa11->fpreg[Fd].fSingle = float32_abs(rFm);
      break;

      case RND_CODE:
Loading