1
From 0d80b9f0fd22f5da30c66bcb046ac0e5813f4c9a Mon Sep 17 00:00:00 2001
2
From: Peter Maydell <peter.maydell@linaro.org>
3
Date: Tue, 7 Jan 2014 17:19:12 +0000
4
Subject: [PATCH 101/158] softfloat: Add support for ties-away rounding
6
IEEE754-2008 specifies a new rounding mode:
8
"roundTiesToAway: the floating-point number nearest to the infinitely
9
precise result shall be delivered; if the two nearest floating-point
10
numbers bracketing an unrepresentable infinitely precise result are
11
equally near, the one with larger magnitude shall be delivered."
13
Implement this new mode (it is needed for ARM). The general principle
14
is that the required code is exactly like the ties-to-even code,
15
except that we do not need to do the "in case of exact tie clear LSB
16
to round-to-even", because the rounding operation naturally causes
17
the exact tie to round up in magnitude.
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Richard Henderson <rth@twiddle.net>
22
fpu/softfloat.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++
23
include/fpu/softfloat.h | 3 ++-
24
2 files changed, 56 insertions(+), 1 deletion(-)
26
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
27
index 234b545..85c9095 100644
30
@@ -111,6 +111,7 @@ static int32 roundAndPackInt32( flag zSign, uint64_t absZ STATUS_PARAM)
31
roundNearestEven = ( roundingMode == float_round_nearest_even );
32
switch (roundingMode) {
33
case float_round_nearest_even:
34
+ case float_round_ties_away:
35
roundIncrement = 0x40;
37
case float_round_to_zero:
38
@@ -161,6 +162,7 @@ static int64 roundAndPackInt64( flag zSign, uint64_t absZ0, uint64_t absZ1 STATU
39
roundNearestEven = ( roundingMode == float_round_nearest_even );
40
switch (roundingMode) {
41
case float_round_nearest_even:
42
+ case float_round_ties_away:
43
increment = ((int64_t) absZ1 < 0);
45
case float_round_to_zero:
46
@@ -214,6 +216,7 @@ static int64 roundAndPackUint64(flag zSign, uint64_t absZ0,
47
roundNearestEven = (roundingMode == float_round_nearest_even);
48
switch (roundingMode) {
49
case float_round_nearest_even:
50
+ case float_round_ties_away:
51
increment = ((int64_t)absZ1 < 0);
53
case float_round_to_zero:
54
@@ -366,6 +369,7 @@ static float32 roundAndPackFloat32(flag zSign, int_fast16_t zExp, uint32_t zSig
55
roundNearestEven = ( roundingMode == float_round_nearest_even );
56
switch (roundingMode) {
57
case float_round_nearest_even:
58
+ case float_round_ties_away:
59
roundIncrement = 0x40;
61
case float_round_to_zero:
62
@@ -550,6 +554,7 @@ static float64 roundAndPackFloat64(flag zSign, int_fast16_t zExp, uint64_t zSig
63
roundNearestEven = ( roundingMode == float_round_nearest_even );
64
switch (roundingMode) {
65
case float_round_nearest_even:
66
+ case float_round_ties_away:
67
roundIncrement = 0x200;
69
case float_round_to_zero:
70
@@ -734,6 +739,7 @@ static floatx80
71
zSig0 |= ( zSig1 != 0 );
72
switch (roundingMode) {
73
case float_round_nearest_even:
74
+ case float_round_ties_away:
76
case float_round_to_zero:
78
@@ -794,6 +800,7 @@ static floatx80
80
switch (roundingMode) {
81
case float_round_nearest_even:
82
+ case float_round_ties_away:
83
increment = ((int64_t)zSig1 < 0);
85
case float_round_to_zero:
86
@@ -838,6 +845,7 @@ static floatx80
87
if ( zSig1 ) STATUS(float_exception_flags) |= float_flag_inexact;
88
switch (roundingMode) {
89
case float_round_nearest_even:
90
+ case float_round_ties_away:
91
increment = ((int64_t)zSig1 < 0);
93
case float_round_to_zero:
94
@@ -1052,6 +1060,7 @@ static float128
95
roundNearestEven = ( roundingMode == float_round_nearest_even );
96
switch (roundingMode) {
97
case float_round_nearest_even:
98
+ case float_round_ties_away:
99
increment = ((int64_t)zSig2 < 0);
101
case float_round_to_zero:
102
@@ -1114,6 +1123,7 @@ static float128
103
if ( isTiny && zSig2 ) float_raise( float_flag_underflow STATUS_VAR);
104
switch (roundingMode) {
105
case float_round_nearest_even:
106
+ case float_round_ties_away:
107
increment = ((int64_t)zSig2 < 0);
109
case float_round_to_zero:
110
@@ -1785,6 +1795,11 @@ float32 float32_round_to_int( float32 a STATUS_PARAM)
111
return packFloat32( aSign, 0x7F, 0 );
114
+ case float_round_ties_away:
115
+ if (aExp == 0x7E) {
116
+ return packFloat32(aSign, 0x7F, 0);
119
case float_round_down:
120
return make_float32(aSign ? 0xBF800000 : 0);
122
@@ -1803,6 +1818,9 @@ float32 float32_round_to_int( float32 a STATUS_PARAM)
126
+ case float_round_ties_away:
127
+ z += lastBitMask >> 1;
129
case float_round_to_zero:
132
@@ -3183,6 +3201,9 @@ static float32 roundAndPackFloat16(flag zSign, int_fast16_t zExp,
133
increment = zSig & (increment << 1);
136
+ case float_round_ties_away:
137
+ increment = (mask + 1) >> 1;
140
increment = zSign ? 0 : mask;
142
@@ -3487,6 +3508,11 @@ float64 float64_round_to_int( float64 a STATUS_PARAM )
143
return packFloat64( aSign, 0x3FF, 0 );
146
+ case float_round_ties_away:
147
+ if (aExp == 0x3FE) {
148
+ return packFloat64(aSign, 0x3ff, 0);
151
case float_round_down:
152
return make_float64(aSign ? LIT64( 0xBFF0000000000000 ) : 0);
154
@@ -3506,6 +3532,9 @@ float64 float64_round_to_int( float64 a STATUS_PARAM )
158
+ case float_round_ties_away:
159
+ z += lastBitMask >> 1;
161
case float_round_to_zero:
164
@@ -4771,6 +4800,11 @@ floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM )
165
packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) );
168
+ case float_round_ties_away:
169
+ if (aExp == 0x3FFE) {
170
+ return packFloatx80(aSign, 0x3FFF, LIT64(0x8000000000000000));
173
case float_round_down:
176
@@ -4794,6 +4828,9 @@ floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM )
177
z.low &= ~lastBitMask;
180
+ case float_round_ties_away:
181
+ z.low += lastBitMask >> 1;
183
case float_round_to_zero:
186
@@ -5862,6 +5899,15 @@ float128 float128_round_to_int( float128 a STATUS_PARAM )
190
+ case float_round_ties_away:
192
+ add128(z.high, z.low, 0, lastBitMask >> 1, &z.high, &z.low);
194
+ if ((int64_t) z.low < 0) {
199
case float_round_to_zero:
202
@@ -5893,6 +5939,11 @@ float128 float128_round_to_int( float128 a STATUS_PARAM )
203
return packFloat128( aSign, 0x3FFF, 0, 0 );
206
+ case float_round_ties_away:
207
+ if (aExp == 0x3FFE) {
208
+ return packFloat128(aSign, 0x3FFF, 0, 0);
211
case float_round_down:
213
aSign ? packFloat128( 1, 0x3FFF, 0, 0 )
214
@@ -5916,6 +5967,9 @@ float128 float128_round_to_int( float128 a STATUS_PARAM )
215
z.high &= ~ lastBitMask;
218
+ case float_round_ties_away:
219
+ z.high += lastBitMask>>1;
221
case float_round_to_zero:
224
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
225
index 83d324a..806ae13 100644
226
--- a/include/fpu/softfloat.h
227
+++ b/include/fpu/softfloat.h
228
@@ -152,7 +152,8 @@ enum {
229
float_round_nearest_even = 0,
230
float_round_down = 1,
232
- float_round_to_zero = 3
233
+ float_round_to_zero = 3,
234
+ float_round_ties_away = 4,
237
/*----------------------------------------------------------------------------