[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 68/76] softfloat: Add support for ties-away rounding
From: |
Peter Maydell |
Subject: |
[Qemu-devel] [PULL 68/76] softfloat: Add support for ties-away rounding |
Date: |
Tue, 7 Jan 2014 20:04:04 +0000 |
IEEE754-2008 specifies a new rounding mode:
"roundTiesToAway: the floating-point number nearest to the infinitely
precise result shall be delivered; if the two nearest floating-point
numbers bracketing an unrepresentable infinitely precise result are
equally near, the one with larger magnitude shall be delivered."
Implement this new mode (it is needed for ARM). The general principle
is that the required code is exactly like the ties-to-even code,
except that we do not need to do the "in case of exact tie clear LSB
to round-to-even", because the rounding operation naturally causes
the exact tie to round up in magnitude.
Signed-off-by: Peter Maydell <address@hidden>
Reviewed-by: Richard Henderson <address@hidden>
---
fpu/softfloat.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++
include/fpu/softfloat.h | 3 ++-
2 files changed, 56 insertions(+), 1 deletion(-)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 6c7a90a..e0ea599 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -111,6 +111,7 @@ static int32 roundAndPackInt32( flag zSign, uint64_t absZ
STATUS_PARAM)
roundNearestEven = ( roundingMode == float_round_nearest_even );
switch (roundingMode) {
case float_round_nearest_even:
+ case float_round_ties_away:
roundIncrement = 0x40;
break;
case float_round_to_zero:
@@ -161,6 +162,7 @@ static int64 roundAndPackInt64( flag zSign, uint64_t absZ0,
uint64_t absZ1 STATU
roundNearestEven = ( roundingMode == float_round_nearest_even );
switch (roundingMode) {
case float_round_nearest_even:
+ case float_round_ties_away:
increment = ((int64_t) absZ1 < 0);
break;
case float_round_to_zero:
@@ -214,6 +216,7 @@ static int64 roundAndPackUint64(flag zSign, uint64_t absZ0,
roundNearestEven = (roundingMode == float_round_nearest_even);
switch (roundingMode) {
case float_round_nearest_even:
+ case float_round_ties_away:
increment = ((int64_t)absZ1 < 0);
break;
case float_round_to_zero:
@@ -366,6 +369,7 @@ static float32 roundAndPackFloat32(flag zSign, int_fast16_t
zExp, uint32_t zSig
roundNearestEven = ( roundingMode == float_round_nearest_even );
switch (roundingMode) {
case float_round_nearest_even:
+ case float_round_ties_away:
roundIncrement = 0x40;
break;
case float_round_to_zero:
@@ -550,6 +554,7 @@ static float64 roundAndPackFloat64(flag zSign, int_fast16_t
zExp, uint64_t zSig
roundNearestEven = ( roundingMode == float_round_nearest_even );
switch (roundingMode) {
case float_round_nearest_even:
+ case float_round_ties_away:
roundIncrement = 0x200;
break;
case float_round_to_zero:
@@ -734,6 +739,7 @@ static floatx80
zSig0 |= ( zSig1 != 0 );
switch (roundingMode) {
case float_round_nearest_even:
+ case float_round_ties_away:
break;
case float_round_to_zero:
roundIncrement = 0;
@@ -794,6 +800,7 @@ static floatx80
precision80:
switch (roundingMode) {
case float_round_nearest_even:
+ case float_round_ties_away:
increment = ((int64_t)zSig1 < 0);
break;
case float_round_to_zero:
@@ -838,6 +845,7 @@ static floatx80
if ( zSig1 ) STATUS(float_exception_flags) |= float_flag_inexact;
switch (roundingMode) {
case float_round_nearest_even:
+ case float_round_ties_away:
increment = ((int64_t)zSig1 < 0);
break;
case float_round_to_zero:
@@ -1052,6 +1060,7 @@ static float128
roundNearestEven = ( roundingMode == float_round_nearest_even );
switch (roundingMode) {
case float_round_nearest_even:
+ case float_round_ties_away:
increment = ((int64_t)zSig2 < 0);
break;
case float_round_to_zero:
@@ -1114,6 +1123,7 @@ static float128
if ( isTiny && zSig2 ) float_raise( float_flag_underflow
STATUS_VAR);
switch (roundingMode) {
case float_round_nearest_even:
+ case float_round_ties_away:
increment = ((int64_t)zSig2 < 0);
break;
case float_round_to_zero:
@@ -1785,6 +1795,11 @@ float32 float32_round_to_int( float32 a STATUS_PARAM)
return packFloat32( aSign, 0x7F, 0 );
}
break;
+ case float_round_ties_away:
+ if (aExp == 0x7E) {
+ return packFloat32(aSign, 0x7F, 0);
+ }
+ break;
case float_round_down:
return make_float32(aSign ? 0xBF800000 : 0);
case float_round_up:
@@ -1803,6 +1818,9 @@ float32 float32_round_to_int( float32 a STATUS_PARAM)
z &= ~lastBitMask;
}
break;
+ case float_round_ties_away:
+ z += lastBitMask >> 1;
+ break;
case float_round_to_zero:
break;
case float_round_up:
@@ -3183,6 +3201,9 @@ static float32 roundAndPackFloat16(flag zSign,
int_fast16_t zExp,
increment = zSig & (increment << 1);
}
break;
+ case float_round_ties_away:
+ increment = (mask + 1) >> 1;
+ break;
case float_round_up:
increment = zSign ? 0 : mask;
break;
@@ -3487,6 +3508,11 @@ float64 float64_round_to_int( float64 a STATUS_PARAM )
return packFloat64( aSign, 0x3FF, 0 );
}
break;
+ case float_round_ties_away:
+ if (aExp == 0x3FE) {
+ return packFloat64(aSign, 0x3ff, 0);
+ }
+ break;
case float_round_down:
return make_float64(aSign ? LIT64( 0xBFF0000000000000 ) : 0);
case float_round_up:
@@ -3506,6 +3532,9 @@ float64 float64_round_to_int( float64 a STATUS_PARAM )
z &= ~lastBitMask;
}
break;
+ case float_round_ties_away:
+ z += lastBitMask >> 1;
+ break;
case float_round_to_zero:
break;
case float_round_up:
@@ -4771,6 +4800,11 @@ floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM )
packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) );
}
break;
+ case float_round_ties_away:
+ if (aExp == 0x3FFE) {
+ return packFloatx80(aSign, 0x3FFF, LIT64(0x8000000000000000));
+ }
+ break;
case float_round_down:
return
aSign ?
@@ -4794,6 +4828,9 @@ floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM )
z.low &= ~lastBitMask;
}
break;
+ case float_round_ties_away:
+ z.low += lastBitMask >> 1;
+ break;
case float_round_to_zero:
break;
case float_round_up:
@@ -5862,6 +5899,15 @@ float128 float128_round_to_int( float128 a STATUS_PARAM )
}
}
break;
+ case float_round_ties_away:
+ if (lastBitMask) {
+ add128(z.high, z.low, 0, lastBitMask >> 1, &z.high, &z.low);
+ } else {
+ if ((int64_t) z.low < 0) {
+ ++z.high;
+ }
+ }
+ break;
case float_round_to_zero:
break;
case float_round_up:
@@ -5893,6 +5939,11 @@ float128 float128_round_to_int( float128 a STATUS_PARAM )
return packFloat128( aSign, 0x3FFF, 0, 0 );
}
break;
+ case float_round_ties_away:
+ if (aExp == 0x3FFE) {
+ return packFloat128(aSign, 0x3FFF, 0, 0);
+ }
+ break;
case float_round_down:
return
aSign ? packFloat128( 1, 0x3FFF, 0, 0 )
@@ -5916,6 +5967,9 @@ float128 float128_round_to_int( float128 a STATUS_PARAM )
z.high &= ~ lastBitMask;
}
break;
+ case float_round_ties_away:
+ z.high += lastBitMask>>1;
+ break;
case float_round_to_zero:
break;
case float_round_up:
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 83d324a..806ae13 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -152,7 +152,8 @@ enum {
float_round_nearest_even = 0,
float_round_down = 1,
float_round_up = 2,
- float_round_to_zero = 3
+ float_round_to_zero = 3,
+ float_round_ties_away = 4,
};
/*----------------------------------------------------------------------------
--
1.8.5
- [Qemu-devel] [PULL 03/76] target-arm: A64: add support for ld/st with reg offset, (continued)
- [Qemu-devel] [PULL 03/76] target-arm: A64: add support for ld/st with reg offset, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 75/76] target-arm: A64: Add 1-source 32-to-32 and 64-to-64 FP instructions, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 18/76] target-arm: A64: add support for conditional compare insns, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 12/76] target-arm: Update generic cpreg code for AArch64, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 11/76] target-arm: Pull "add one cpreg to hashtable" into its own function, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 10/76] target-arm: A64: implement FMOV, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 67/76] softfloat: Refactor code handling various rounding modes, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 71/76] target-arm: Ignore most exceptions from scalbn when doing fixpoint conversion, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 70/76] target-arm: Rename A32 VFP conversion helpers, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 66/76] softfloat: Add float16 <=> float64 conversion functions, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 68/76] softfloat: Add support for ties-away rounding,
Peter Maydell <=
- [Qemu-devel] [PULL 61/76] softfloat: Fix float64_to_uint64_round_to_zero, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 73/76] target-arm: A64: Add floating-point<->fixed-point instructions, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 59/76] softfloat: Fix factor 2 error for scalbn on denormal inputs, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 72/76] target-arm: A64: Add extra VFP fixed point conversion helpers, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 60/76] softfloat: Add float32_to_uint64(), Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 76/76] target-arm: A64: Add support for FCVT between half, single and double, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 51/76] arm_gic: Rename GIC_X_TRIGGER to GIC_X_EDGE_TRIGGER, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 69/76] target-arm: Prepare VFP_CONV_FIX helpers for A64 uses, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 54/76] softfloat: Add float to 16bit integer conversions., Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 49/76] arm/xilinx_zynq: Always instantiate the GEMs, Peter Maydell, 2014/01/07