annoyingly, have to modify rv_mulhu to take source reg width as basis
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 8 Nov 2018 11:08:18 +0000 (11:08 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 8 Nov 2018 11:08:18 +0000 (11:08 +0000)
riscv/sv_insn_redirect.cc

index 6de7ea92833eae82ab84f63a67a2bb6bcfe6e642..5db0afeea04e6ba61a4fb135605a1c42721bd077 100644 (file)
@@ -606,15 +606,19 @@ sv_sreg_t sv_proc_t::rv_mul(sv_sreg_t const & lhs, sv_sreg_t const & rhs)
 sv_reg_t sv_proc_t::rv_mulhu(sv_reg_t const & lhs, sv_reg_t const & rhs)
 {
     // normally the result is shuffled down by 32 bits (elwidth==default)
-    // however with variable bitwidth we want the top elwidth bits.
-    // so, get the destination bitwidth first...
-    reg_t reg = _insn->rd().reg;
-    uint8_t dest_elwidth = _insn->reg_elwidth(reg, true);
-    uint8_t bitwidth = get_bitwidth(dest_elwidth, xlen);
-    sv_reg_t m = rv_mul(lhs, rhs);
-    uint64_t result = (uint64_t)m;
-    result >>= std::min(bitwidth, (uint8_t)32);
-    return sv_reg_t(result, xlen, bitwidth);
+    // however with variable bitwidth we want the top elwidth bits,
+    // using the SOURCE registers to determine that width.
+    uint8_t bitwidth = _insn->src_bitwidth;
+    uint64_t vlhs = 0;
+    uint64_t vrhs = 0;
+    if (rv_int_op_prepare(lhs, rhs, vlhs, vrhs, bitwidth)) {
+        sv_reg_t result = (lhs * rhs) >> 32;
+        fprintf(stderr, "mul result %lx %lx %lx\n",
+                (uint64_t)lhs, (uint64_t)rhs, (uint64_t)result);
+        return result;
+    }
+    uint64_t result = (vlhs * vrhs) >> std::min(bitwidth, (uint8_t)32);
+    return rv_int_op_finish(lhs, rhs, result, bitwidth);
 }
 
 sv_sreg_t sv_proc_t::rv_mulhsu(sv_sreg_t const & lhs, sv_reg_t const & rhs)