aboutsummaryrefslogtreecommitdiff
path: root/riscv/decode.h
diff options
context:
space:
mode:
authorAlbert Ou <aou@eecs.berkeley.edu>2019-10-29 00:47:10 -0700
committerChih-Min Chao <chihmin.chao@sifive.com>2019-11-11 19:02:34 -0800
commit590abe0960e9604f439d572c75abb440bbeaeadd (patch)
tree41903667d41d92e6205090350ca35d98acbe9a8e /riscv/decode.h
parentb9d9e1ebd02c62ad354195481d1136f5be3f54cd (diff)
downloadspike-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/decode.h')
-rw-r--r--riscv/decode.h24
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