slightly different 64-bit rv_mulhu elwidth rules
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 10 Nov 2018 06:59:17 +0000 (06:59 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 10 Nov 2018 06:59:17 +0000 (06:59 +0000)
riscv/sv_insn_redirect.cc

index 937b232e9e0662b2a88257925ce924891846d502..3ce22f30c00d73e146523d47815941cb48567e13 100644 (file)
@@ -451,6 +451,8 @@ bool sv_proc_t::rv_int_op_prepare(SLHSTYPE const & lhs, SRHSTYPE const & rhs, \
         bitwidth = xlen; \
     } \
     if (bitwidth == xlen) {                                                \
+        vlhs = lhs;                                   \
+        vrhs = rhs;                                   \
         return true;                                                       \
     }                                                                   \
     uint8_t lbitwidth = get_bitwidth(lhs.get_elwidth(), xlen);            \
@@ -459,8 +461,8 @@ bool sv_proc_t::rv_int_op_prepare(SLHSTYPE const & lhs, SRHSTYPE const & rhs, \
         vlhs = sext_bwid(lhs, lbitwidth);                                   \
         vrhs = sext_bwid(rhs, rbitwidth);                                   \
     } else {                                                               \
-        vlhs = zext_bwid(lhs, lbitwidth);                                   \
-        vrhs = zext_bwid(rhs, rbitwidth);                                   \
+        vlhs = zext_bwid(lhs, lbitwidth);                              \
+        vrhs = zext_bwid(rhs, rbitwidth);                              \
     }                                                                   \
     return false;                                                          \
 }                                                                   \
@@ -558,9 +560,25 @@ OP_MULH_FN(_mulhsu, sv_sreg_t, sv_reg_t, sv_sreg_t, int64_t, uint64_t, int64_t )
 OP_MULH_FN(_mulh  , sv_sreg_t, sv_sreg_t, sv_sreg_t, int64_t, int64_t, int64_t )
 
 /* 64-bit mulh/mulhu/mulhsu */
-sv_reg_t (sv_proc_t::mulhu)(sv_reg_t const& a, sv_reg_t const& b)
+/* here is slightly different from other macros, because if either
+   src register is 64-bit it's necessary to use the 64-bit mulhu
+   function.  then, if the result is <64bit it's truncated.
+   only when both source registers are <= 32 bit can we use
+   the 32-bit rv_mulh.
+ */
+sv_reg_t (sv_proc_t::mulhu)(sv_reg_t const& lhs, sv_reg_t const& rhs)
 {
-    return sv_reg_t(::mulhu(a, b));
+    uint8_t bitwidth = _insn->src_bitwidth;                                  \
+    uint64_t vlhs = 0;                                                       \
+    uint64_t vrhs = 0;                                                       \
+    if (rv_int_op_prepare(lhs, rhs, vlhs, vrhs, bitwidth) ||                 \
+        lhs.get_elwidth() == 0 || rhs.get_elwidth() == 0 ) {                 \
+        uint64_t result = ::mulhu(vlhs, vrhs);
+        fprintf(stderr, "%s result %lx %lx %lx\n",               \
+                "mulhu", (uint64_t)vlhs, (uint64_t)vrhs, (uint64_t)result);  \
+        return rv_int_op_finish(lhs, rhs, result, bitwidth);                 \
+    }                                                                        \
+    return rv_mulh(lhs, rhs);
 }
 
 sv_sreg_t (sv_proc_t::mulhsu)(sv_sreg_t const& a, sv_reg_t const& b)