Implemented precision lost up indication in floating point status word

This commit is contained in:
Stanislav Shwartsman 2004-06-25 18:51:28 +00:00
parent dfd17222b0
commit 2a0a361298
7 changed files with 21 additions and 30 deletions

View File

@ -32,8 +32,6 @@ Changes to next release:
! Unmasked underflow/overflow should correct the result
by magic number for all operations, including float32
and float64.
! set SW_C1 according to PRECISION_UP or PRECISION_DOWN
conditions.
! improve performance of transcendential instructions.
- Disassembler

View File

@ -31,7 +31,6 @@ static void prepare_softfloat_status_word
status.float_nan_handling_mode = float_first_operand_nan;
status.float_rounding_mode = rounding_mode;
status.flush_underflow_to_zero = 0;
status.float_precision_lost_up = 0;
}
void BX_CPU_C::PFPNACC_PqQq(bxInstruction_c *i)

View File

@ -46,7 +46,6 @@ static void mxcsr_to_softfloat_status_word(float_status_t &status, bx_mxcsr_t mx
// if underflow is masked and FUZ is 1, set it to 1, else to 0
status.flush_underflow_to_zero =
(mxcsr.get_flush_masked_underflow() && mxcsr.get_UM()) ? 1 : 0;
status.float_precision_lost_up = 0;
}
// handle DAZ

View File

@ -57,7 +57,6 @@ float_status_t FPU_pre_exception_handling(Bit16u control_word)
status.float_nan_handling_mode = float_first_operand_nan;
status.float_rounding_mode = (control_word & FPU_CW_RC) >> 10;
status.flush_underflow_to_zero = 0;
status.float_precision_lost_up = 0;
return status;
}

View File

@ -385,6 +385,7 @@ floatx80 roundAndPackFloatx80(int roundingPrecision,
{
Bit64u roundIncrement, roundMask, roundBits;
int increment;
Bit64u zSigExact; /* support rounding-up response */
Bit8u roundingMode = get_float_rounding_mode(status);
int roundNearestEven = (roundingMode == float_round_nearest_even);
@ -421,22 +422,23 @@ floatx80 roundAndPackFloatx80(int roundingPrecision,
if (zExp <= 0) {
int isTiny = (zExp < 0) || (zSig0 <= zSig0 + roundIncrement);
shift64RightJamming(zSig0, 1 - zExp, &zSig0);
zSigExact = zSig0;
zExp = 0;
roundBits = zSig0 & roundMask;
if (isTiny && roundBits) float_raise(status, float_flag_underflow);
if (roundBits) float_raise(status, float_flag_inexact);
if (roundIncrement) set_float_rounding_up(status);
zSig0 += roundIncrement;
if ((Bit64s) zSig0 < 0) zExp = 1;
roundIncrement = roundMask + 1;
if (roundNearestEven && (roundBits<<1 == roundIncrement))
roundMask |= roundIncrement;
zSig0 &= ~roundMask;
if (zSig0 > zSigExact) set_float_rounding_up(status);
return packFloatx80(zSign, zExp, zSig0);
}
}
if (roundBits) float_raise(status, float_flag_inexact);
if (roundIncrement) set_float_rounding_up(status);
zSigExact = zSig0;
zSig0 += roundIncrement;
if (zSig0 < roundIncrement) {
++zExp;
@ -446,6 +448,7 @@ floatx80 roundAndPackFloatx80(int roundingPrecision,
if (roundNearestEven && (roundBits<<1 == roundIncrement))
roundMask |= roundIncrement;
zSig0 &= ~roundMask;
if (zSig0 > zSigExact) set_float_rounding_up(status);
if (zSig0 == 0) zExp = 0;
return packFloatx80(zSign, zExp, zSig0);
precision80:
@ -476,7 +479,7 @@ floatx80 roundAndPackFloatx80(int roundingPrecision,
{
return packFloatx80(zSign, 0x7FFE, ~roundMask);
}
set_float_rounding_up(status);
return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000));
}
if (zExp <= 0) {
@ -486,8 +489,7 @@ floatx80 roundAndPackFloatx80(int roundingPrecision,
zExp = 0;
if (isTiny && zSig1) float_raise(status, float_flag_underflow);
if (zSig1) float_raise(status, float_flag_inexact);
if (roundNearestEven)
increment = ((Bit64s) zSig1 < 0);
if (roundNearestEven) increment = ((Bit64s) zSig1 < 0);
else {
if (zSign) {
increment = (roundingMode == float_round_down) && zSig1;
@ -496,25 +498,25 @@ floatx80 roundAndPackFloatx80(int roundingPrecision,
}
}
if (increment) {
zSig0++;
zSigExact = zSig0++;
zSig0 &= ~(((Bit64u) (zSig1<<1) == 0) & roundNearestEven);
if (zSig0 > zSigExact) set_float_rounding_up(status);
if ((Bit64s) zSig0 < 0) zExp = 1;
set_float_rounding_up(status);
}
return packFloatx80(zSign, zExp, zSig0);
}
}
if (zSig1) float_raise(status, float_flag_inexact);
if (increment) {
++zSig0;
set_float_rounding_up(status);
zSigExact = zSig0++;
if (zSig0 == 0) {
++zExp;
zExp++;
zSig0 = BX_CONST64(0x8000000000000000);
}
else {
zSig0 &= ~(((Bit64u) (zSig1<<1) == 0) & roundNearestEven);
}
if (zSig0 > zSigExact) set_float_rounding_up(status);
}
else {
if (zSig0 == 0) zExp = 0;

View File

@ -87,6 +87,10 @@ enum float_exception_flag_t {
float_flag_inexact = 0x20
};
#ifdef FLOATX80
#define RAISE_SW_C1 0x0200
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point ordering relations
*----------------------------------------------------------------------------*/
@ -104,7 +108,6 @@ struct float_status_t
{
#ifdef FLOATX80
int float_rounding_precision; /* floatx80 only */
int float_precision_lost_up; /* flag register, floatx80 only */
#endif
int float_rounding_mode;
int float_exception_flags;
@ -159,7 +162,7 @@ BX_CPP_INLINE int get_float_nan_handling_mode(float_status_t &status)
#ifdef FLOATX80
BX_CPP_INLINE void set_float_rounding_up(float_status_t &status)
{
status.float_precision_lost_up = 1;
status.float_exception_flags |= (float_flag_inexact | RAISE_SW_C1);
}
#endif
@ -290,19 +293,12 @@ struct floatx80 {
floatx80 int32_to_floatx80(Bit32s);
floatx80 int64_to_floatx80(Bit64s);
/*----------------------------------------------------------------------------
| Software IEC/IEEE single-precision conversion routines.
*----------------------------------------------------------------------------*/
floatx80 float32_to_floatx80(float32, float_status_t &status);
/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision conversion routines.
*----------------------------------------------------------------------------*/
floatx80 float64_to_floatx80(float64, float_status_t &status);
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision conversion routines.
*----------------------------------------------------------------------------*/
floatx80 float32_to_floatx80(float32, float_status_t &status);
floatx80 float64_to_floatx80(float64, float_status_t &status);
Bit32s floatx80_to_int32(floatx80, float_status_t &status);
Bit32s floatx80_to_int32_round_to_zero(floatx80, float_status_t &status);
Bit64s floatx80_to_int64(floatx80, float_status_t &status);

View File

@ -7,9 +7,7 @@ TODO:
2. Unmasked underflow/overflow should correct the result by magic number
for all operations, including float32 and float64.
3. Set SW_C1 according to PRECISION_UP or PRECISION_DOWN conditions.
4. Elliminate floa128 use, Intel uses only 67-bit precision calculations
3. Elliminate floa128 use, Intel uses only 67-bit precision calculations
when float128 has at least 112-bit. Replacement of float128 with for
example 96-bit precision number could significantly speed up
calculations.