diff options
author | Albert Ou <aou@eecs.berkeley.edu> | 2019-10-29 00:47:10 -0700 |
---|---|---|
committer | Chih-Min Chao <chihmin.chao@sifive.com> | 2019-11-11 19:02:34 -0800 |
commit | 590abe0960e9604f439d572c75abb440bbeaeadd (patch) | |
tree | 41903667d41d92e6205090350ca35d98acbe9a8e /riscv | |
parent | b9d9e1ebd02c62ad354195481d1136f5be3f54cd (diff) | |
download | spike-590abe0960e9604f439d572c75abb440bbeaeadd.zip spike-590abe0960e9604f439d572c75abb440bbeaeadd.tar.gz spike-590abe0960e9604f439d572c75abb440bbeaeadd.tar.bz2 |
rvv: fix INT_ROUNDING compliance
* round-to-nearest-even: In the case that result[gb] = 0, the result
should still be rounded up if result[gb-1] != 0 && result[gb-2:0] != 0
(the usual round-to-nearest behavior outside of the tiebreaker).
* round-down: Since all uses of INT_ROUNDING() are immediately followed
with a right shift by gb, clearing the lower bits is unnecessary.
* round-to-odd: The LSB should be OR'd only if result[gb-1:0] != 0.
Signed-off-by: Albert Ou <aou@eecs.berkeley.edu>
Diffstat (limited to 'riscv')
-rw-r--r-- | riscv/decode.h | 24 |
1 files changed, 10 insertions, 14 deletions
diff --git a/riscv/decode.h b/riscv/decode.h index 0f12262..72e2dc8 100644 --- a/riscv/decode.h +++ b/riscv/decode.h @@ -476,31 +476,27 @@ static inline bool is_overlaped(const int astart, const int asize, #define INT_ROUNDING(result, xrm, gb) \ - if (gb > 0) { \ - switch(xrm) {\ + do { \ + const uint64_t lsb = 1UL << (gb); \ + const uint64_t lsb_half = lsb >> 1; \ + switch (xrm) {\ case VRM::RNU:\ - result += ((uint64_t)1 << ((gb) - 1));\ + result += lsb_half; \ break;\ case VRM::RNE:\ - if ((result & ((uint64_t)0x3 << ((gb) - 1))) == 0x1){\ - result -= ((uint64_t)1 << ((gb) - 1));\ - }else if ((result & ((uint64_t)0x3 << ((gb) - 1))) == 0x3){\ - result += ((uint64_t)1 << ((gb) - 1));\ - }\ + if ((result & lsb_half) && ((result & (lsb_half - 1)) || (result & lsb))) \ + result += lsb; \ break;\ case VRM::RDN:\ - result = (result >> ((gb) - 1)) << ((gb) - 1);\ break;\ case VRM::ROD:\ - result |= ((uint64_t)1ul << (gb)); \ + if (result & (lsb - 1)) \ + result |= lsb; \ break;\ case VRM::INVALID_RM:\ assert(true);\ } \ - } else if (gb == 0 && xrm == VRM::ROD) { \ - result |= 1ul; \ - } - + } while (0) // // vector: integer and masking operand access helper |