OP_RES_FN ( _mul, sv_sreg_t, sv_sreg_t, sv_sreg_t, int64_t, int64_t, int64_t )
/* 32-bit mulh/mulhu/mulhsu */
-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,
// using the SOURCE registers to determine that width.
// specifically: truncation of the result due to a shorter
// destination elwidth is NOT our problem.
- 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, "mulhu result %lx %lx %lx\n",
- (uint64_t)lhs, (uint64_t)rhs, (uint64_t)result);
- return result;
- }
- uint8_t bw32 = std::min(bitwidth, (uint8_t)32);
- uint64_t result = (vlhs * vrhs) >> bw32;
- result = zext_bwid(result, bw32);
- fprintf(stderr, "mulhu result %lx %lx %lx bw %d\n",
- (uint64_t)lhs, (uint64_t)rhs, (uint64_t)(result), bitwidth);
- 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)
-{
- uint8_t bitwidth = _insn->src_bitwidth;
- int64_t vlhs = 0;
- uint64_t vrhs = 0;
- if (rv_int_op_prepare(lhs, rhs, vlhs, vrhs, bitwidth)) {
- sv_sreg_t result = (lhs * rhs) >> 32;
- fprintf(stderr, "mulhsu result %lx %lx %lx\n",
- (int64_t)lhs, (uint64_t)rhs, (int64_t)result);
- return result;
- }
- uint8_t bw32 = std::min(bitwidth, (uint8_t)32);
- int64_t result = (vlhs * vrhs) >> bw32;
- result = sext_bwid(result, bw32);
- fprintf(stderr, "mulhu result %lx %lx %lx bw %d\n",
- (int64_t)lhs, (uint64_t)rhs, (int64_t)(result), bitwidth);
- return rv_int_op_finish(lhs, rhs, result, bitwidth);
+#define OP_MULH_FN( fname, SLHSTYPE, SRHSTYPE, SRESTYPE, \
+ LHSTYPE, RHSTYPE, RESTYPE ) \
+SRESTYPE sv_proc_t::rv##fname (SLHSTYPE const & lhs, SRHSTYPE const & rhs) \
+{ \
+ uint8_t bitwidth = _insn->src_bitwidth; \
+ LHSTYPE vlhs = 0; \
+ RHSTYPE vrhs = 0; \
+ if (rv_int_op_prepare(lhs, rhs, vlhs, vrhs, bitwidth)) { \
+ RESTYPE result = (lhs * rhs) >> 32; \
+ fprintf(stderr, "%s result %lx %lx %lx\n", \
+ xstr(fname), (LHSTYPE)lhs, (RHSTYPE)rhs, (RESTYPE)result); \
+ return SRESTYPE(result); \
+ } \
+ uint8_t bw32 = std::min(bitwidth, (uint8_t)32); \
+ RESTYPE result = (vlhs * vrhs) >> bw32; \
+ result = zext_bwid(result, bw32); \
+ fprintf(stderr, "%s result %lx %lx %lx bw %d\n", \
+ xstr(fname), (LHSTYPE)lhs, (RHSTYPE)rhs, (RESTYPE)result, bitwidth); \
+ return rv_int_op_finish(lhs, rhs, result, bitwidth); \
}
-sv_sreg_t sv_proc_t::rv_mulh(sv_sreg_t const & lhs, sv_sreg_t const & rhs)
-{
- uint8_t bitwidth = _insn->src_bitwidth;
- int64_t vlhs = 0;
- int64_t vrhs = 0;
- if (rv_int_op_prepare(lhs, rhs, vlhs, vrhs, bitwidth)) {
- sv_sreg_t result = (lhs * rhs) >> 32;
- fprintf(stderr, "mulh result %lx %lx %lx\n",
- (int64_t)lhs, (int64_t)rhs, (int64_t)result);
- return result;
- }
- uint8_t bw32 = std::min(bitwidth, (uint8_t)32);
- int64_t result = (vlhs * vrhs) >> bw32;
- result = sext_bwid(result, bw32);
- fprintf(stderr, "mulh result %lx %lx %lx bw %d\n",
- (int64_t)lhs, (int64_t)rhs, (int64_t)(result), bitwidth);
- return rv_int_op_finish(lhs, rhs, result, bitwidth);
-}
+OP_MULH_FN(_mulhu , sv_reg_t, sv_reg_t, sv_reg_t, uint64_t, uint64_t, uint64_t )
+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_sreg_t (sv_proc_t::mulhsu)(sv_sreg_t const& a, sv_reg_t const& b)