bitwidth = xlen; \
} \
if (bitwidth == xlen) { \
+ vlhs = lhs; \
+ vrhs = rhs; \
return true; \
} \
uint8_t lbitwidth = get_bitwidth(lhs.get_elwidth(), xlen); \
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; \
} \
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)