Skip to content

Commit

Permalink
softfloat: Introduce Floatx80RoundPrec
Browse files Browse the repository at this point in the history
Use an enumeration instead of raw 32/64/80 values.

Reviewed-by: Alex Bennée <[email protected]>
Signed-off-by: Richard Henderson <[email protected]>
  • Loading branch information
rth7680 committed Jun 3, 2021
1 parent d6e1f0c commit 8da5f1d
Show file tree
Hide file tree
Showing 9 changed files with 182 additions and 134 deletions.
32 changes: 17 additions & 15 deletions fpu/softfloat.c
Original file line number Diff line number Diff line change
Expand Up @@ -4342,38 +4342,40 @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
| a subnormal number, and the underflow and inexact exceptions are raised if
| the abstract input cannot be represented exactly as a subnormal extended
| double-precision floating-point number.
| If `roundingPrecision' is 32 or 64, the result is rounded to the same
| number of bits as single or double precision, respectively. Otherwise, the
| result is rounded to the full precision of the extended double-precision
| format.
| If `roundingPrecision' is floatx80_precision_s or floatx80_precision_d,
| the result is rounded to the same number of bits as single or double
| precision, respectively. Otherwise, the result is rounded to the full
| precision of the extended double-precision format.
| The input significand must be normalized or smaller. If the input
| significand is not normalized, `zExp' must be 0; in that case, the result
| returned is a subnormal number, and it must not require rounding. The
| handling of underflow and overflow follows the IEC/IEEE Standard for Binary
| Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/

floatx80 roundAndPackFloatx80(int8_t roundingPrecision, bool zSign,
floatx80 roundAndPackFloatx80(FloatX80RoundPrec roundingPrecision, bool zSign,
int32_t zExp, uint64_t zSig0, uint64_t zSig1,
float_status *status)
{
int8_t roundingMode;
FloatRoundMode roundingMode;
bool roundNearestEven, increment, isTiny;
int64_t roundIncrement, roundMask, roundBits;

roundingMode = status->float_rounding_mode;
roundNearestEven = ( roundingMode == float_round_nearest_even );
if ( roundingPrecision == 80 ) goto precision80;
if ( roundingPrecision == 64 ) {
switch (roundingPrecision) {
case floatx80_precision_x:
goto precision80;
case floatx80_precision_d:
roundIncrement = UINT64_C(0x0000000000000400);
roundMask = UINT64_C(0x00000000000007FF);
}
else if ( roundingPrecision == 32 ) {
break;
case floatx80_precision_s:
roundIncrement = UINT64_C(0x0000008000000000);
roundMask = UINT64_C(0x000000FFFFFFFFFF);
}
else {
goto precision80;
break;
default:
g_assert_not_reached();
}
zSig0 |= ( zSig1 != 0 );
switch (roundingMode) {
Expand Down Expand Up @@ -4550,7 +4552,7 @@ floatx80 roundAndPackFloatx80(int8_t roundingPrecision, bool zSign,
| normalized.
*----------------------------------------------------------------------------*/

floatx80 normalizeRoundAndPackFloatx80(int8_t roundingPrecision,
floatx80 normalizeRoundAndPackFloatx80(FloatX80RoundPrec roundingPrecision,
bool zSign, int32_t zExp,
uint64_t zSig0, uint64_t zSig1,
float_status *status)
Expand Down Expand Up @@ -6203,7 +6205,7 @@ floatx80 floatx80_modrem(floatx80 a, floatx80 b, bool mod, uint64_t *quotient,
}
return
normalizeRoundAndPackFloatx80(
80, zSign, bExp + expDiff, aSig0, aSig1, status);
floatx80_precision_x, zSign, bExp + expDiff, aSig0, aSig1, status);

}

Expand Down
5 changes: 3 additions & 2 deletions include/fpu/softfloat-helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ static inline void set_float_exception_flags(int val, float_status *status)
status->float_exception_flags = val;
}

static inline void set_floatx80_rounding_precision(int val,
static inline void set_floatx80_rounding_precision(FloatX80RoundPrec val,
float_status *status)
{
status->floatx80_rounding_precision = val;
Expand Down Expand Up @@ -120,7 +120,8 @@ static inline int get_float_exception_flags(float_status *status)
return status->float_exception_flags;
}

static inline int get_floatx80_rounding_precision(float_status *status)
static inline FloatX80RoundPrec
get_floatx80_rounding_precision(float_status *status)
{
return status->floatx80_rounding_precision;
}
Expand Down
10 changes: 9 additions & 1 deletion include/fpu/softfloat-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,14 @@ enum {
float_flag_output_denormal = 128
};

/*
* Rounding precision for floatx80.
*/
typedef enum __attribute__((__packed__)) {
floatx80_precision_x,
floatx80_precision_d,
floatx80_precision_s,
} FloatX80RoundPrec;

/*
* Floating Point Status. Individual architectures may maintain
Expand All @@ -165,7 +173,7 @@ enum {
typedef struct float_status {
FloatRoundMode float_rounding_mode;
uint8_t float_exception_flags;
signed char floatx80_rounding_precision;
FloatX80RoundPrec floatx80_rounding_precision;
bool tininess_before_rounding;
/* should denormalised results go to zero and set the inexact flag? */
bool flush_to_zero;
Expand Down
4 changes: 2 additions & 2 deletions include/fpu/softfloat.h
Original file line number Diff line number Diff line change
Expand Up @@ -1152,7 +1152,7 @@ floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status);
| Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/

floatx80 roundAndPackFloatx80(int8_t roundingPrecision, bool zSign,
floatx80 roundAndPackFloatx80(FloatX80RoundPrec roundingPrecision, bool zSign,
int32_t zExp, uint64_t zSig0, uint64_t zSig1,
float_status *status);

Expand All @@ -1165,7 +1165,7 @@ floatx80 roundAndPackFloatx80(int8_t roundingPrecision, bool zSign,
| normalized.
*----------------------------------------------------------------------------*/

floatx80 normalizeRoundAndPackFloatx80(int8_t roundingPrecision,
floatx80 normalizeRoundAndPackFloatx80(FloatX80RoundPrec roundingPrecision,
bool zSign, int32_t zExp,
uint64_t zSig0, uint64_t zSig1,
float_status *status);
Expand Down
41 changes: 21 additions & 20 deletions linux-user/arm/nwfpe/fpa11.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,37 +97,38 @@ void SetRoundingMode(const unsigned int opcode)

void SetRoundingPrecision(const unsigned int opcode)
{
int rounding_precision;
FPA11 *fpa11 = GET_FPA11();
FloatX80RoundPrec rounding_precision;
FPA11 *fpa11 = GET_FPA11();
#ifdef MAINTAIN_FPCR
fpa11->fpcr &= ~MASK_ROUNDING_PRECISION;
fpa11->fpcr &= ~MASK_ROUNDING_PRECISION;
#endif
switch (opcode & MASK_ROUNDING_PRECISION)
{
case ROUND_SINGLE:
rounding_precision = 32;
switch (opcode & MASK_ROUNDING_PRECISION) {
case ROUND_SINGLE:
rounding_precision = floatx80_precision_s;
#ifdef MAINTAIN_FPCR
fpa11->fpcr |= ROUND_SINGLE;
fpa11->fpcr |= ROUND_SINGLE;
#endif
break;
break;

case ROUND_DOUBLE:
rounding_precision = 64;
case ROUND_DOUBLE:
rounding_precision = floatx80_precision_d;
#ifdef MAINTAIN_FPCR
fpa11->fpcr |= ROUND_DOUBLE;
fpa11->fpcr |= ROUND_DOUBLE;
#endif
break;
break;

case ROUND_EXTENDED:
rounding_precision = 80;
case ROUND_EXTENDED:
rounding_precision = floatx80_precision_x;
#ifdef MAINTAIN_FPCR
fpa11->fpcr |= ROUND_EXTENDED;
fpa11->fpcr |= ROUND_EXTENDED;
#endif
break;
break;

default: rounding_precision = 80;
}
set_floatx80_rounding_precision(rounding_precision, &fpa11->fp_status);
default:
rounding_precision = floatx80_precision_x;
break;
}
set_floatx80_rounding_precision(rounding_precision, &fpa11->fp_status);
}

/* Emulate the instruction in the opcode. */
Expand Down
Loading

0 comments on commit 8da5f1d

Please sign in to comment.