diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa index 3acd80ebf0..47519eeeb4 100644 --- a/src/arch/riscv/isa/decoder.isa +++ b/src/arch/riscv/isa/decoder.isa @@ -1084,34 +1084,13 @@ decode QUADRANT default Unknown::unknown() { 0x0: sll({{ Rd = rvSext(Rs1 << rvSelect(Rs2<4:0>, Rs2<5:0>)); }}); - 0x1: decode RVTYPE { - 0x0: rv32_mulh({{ - Rd_sw = ((int64_t)Rs1_sw * Rs2_sw) >> 32; - }}, IntMultOp); - 0x1: mulh({{ - bool negate = (Rs1_sd < 0) != (Rs2_sd < 0); - - uint64_t Rs1_lo = (uint32_t)std::abs(Rs1_sd); - uint64_t Rs1_hi = (uint64_t)std::abs(Rs1_sd) >> 32; - uint64_t Rs2_lo = (uint32_t)std::abs(Rs2_sd); - uint64_t Rs2_hi = (uint64_t)std::abs(Rs2_sd) >> 32; - - uint64_t hi = Rs1_hi*Rs2_hi; - uint64_t mid1 = Rs1_hi*Rs2_lo; - uint64_t mid2 = Rs1_lo*Rs2_hi; - uint64_t lo = Rs2_lo*Rs1_lo; - uint64_t carry = ((uint64_t)(uint32_t)mid1 - + (uint64_t)(uint32_t)mid2 - + (lo >> 32)) >> 32; - - uint64_t res = hi + - (mid1 >> 32) + - (mid2 >> 32) + - carry; - Rd = negate ? ~res + (Rs1_sd*Rs2_sd == 0 ? 1 : 0) - : res; - }}, IntMultOp); - } + 0x1: mulh({{ + if (machInst.rv_type == RV32) { + Rd_sd = mulh_32(Rs1_sd, Rs2_sd); + } else { + Rd_sd = mulh_64(Rs1_sd, Rs2_sd); + } + }}, IntMultOp); 0x5: clmul({{ uint64_t result = 0; for (int i = 0; i < rvSelect(32, 64); i++) { @@ -1144,32 +1123,13 @@ decode QUADRANT default Unknown::unknown() { 0x0: slt({{ Rd = (rvSext(Rs1_sd) < rvSext(Rs2_sd)) ? 1 : 0; }}); - 0x1: decode RVTYPE { - 0x0: rv32_mulhsu({{ - Rd_sw = ((int64_t)Rs1_sw * Rs2_uw) >> 32; - }}, IntMultOp); - 0x1: mulhsu({{ - bool negate = Rs1_sd < 0; - uint64_t Rs1_lo = (uint32_t)std::abs(Rs1_sd); - uint64_t Rs1_hi = (uint64_t)std::abs(Rs1_sd) >> 32; - uint64_t Rs2_lo = (uint32_t)Rs2; - uint64_t Rs2_hi = Rs2 >> 32; - - uint64_t hi = Rs1_hi*Rs2_hi; - uint64_t mid1 = Rs1_hi*Rs2_lo; - uint64_t mid2 = Rs1_lo*Rs2_hi; - uint64_t lo = Rs1_lo*Rs2_lo; - uint64_t carry = ((uint64_t)(uint32_t)mid1 - + (uint64_t)(uint32_t)mid2 - + (lo >> 32)) >> 32; - - uint64_t res = hi + - (mid1 >> 32) + - (mid2 >> 32) + - carry; - Rd = negate ? ~res + (Rs1_sd*Rs2 == 0 ? 1 : 0) : res; - }}, IntMultOp); - } + 0x1: mulhsu({{ + if (machInst.rv_type == RV32) { + Rd_sd = mulhsu_32(Rs1_sd, Rs2); + } else { + Rd_sd = mulhsu_64(Rs1_sd, Rs2); + } + }}, IntMultOp); 0x5: clmulr({{ uint64_t result = 0; uint64_t xlen = rvSelect(32, 64); @@ -1197,27 +1157,13 @@ decode QUADRANT default Unknown::unknown() { 0x0: sltu({{ Rd = (rvZext(Rs1) < rvZext(Rs2)) ? 1 : 0; }}); - 0x1: decode RVTYPE { - 0x0: rv32_mulhu({{ - Rd_sw = ((uint64_t)Rs1_uw * Rs2_uw) >> 32; - }}, IntMultOp); - 0x1: mulhu({{ - uint64_t Rs1_lo = (uint32_t)Rs1; - uint64_t Rs1_hi = Rs1 >> 32; - uint64_t Rs2_lo = (uint32_t)Rs2; - uint64_t Rs2_hi = Rs2 >> 32; - - uint64_t hi = Rs1_hi*Rs2_hi; - uint64_t mid1 = Rs1_hi*Rs2_lo; - uint64_t mid2 = Rs1_lo*Rs2_hi; - uint64_t lo = Rs1_lo*Rs2_lo; - uint64_t carry = ((uint64_t)(uint32_t)mid1 - + (uint64_t)(uint32_t)mid2 - + (lo >> 32)) >> 32; - - Rd = hi + (mid1 >> 32) + (mid2 >> 32) + carry; - }}, IntMultOp); - } + 0x1: mulhu({{ + if (machInst.rv_type == RV32) { + Rd = (int32_t)mulhu_32(Rs1, Rs2); + } else { + Rd = mulhu_64(Rs1, Rs2); + } + }}, IntMultOp); 0x5: clmulh({{ uint64_t result = 0; uint64_t xlen = rvSelect(32, 64); @@ -1235,30 +1181,13 @@ decode QUADRANT default Unknown::unknown() { 0x0: xor({{ Rd = rvSext(Rs1 ^ Rs2); }}); - 0x1: decode RVTYPE { - 0x0: rv32_div({{ - constexpr int32_t kRsMin = \ - std::numeric_limits::min(); - if (Rs2_sw == 0) { - Rd_sw = -1; - } else if (Rs1_sw == kRsMin && Rs2_sw == -1) { - Rd_sw = kRsMin; - } else { - Rd_sw = Rs1_sw/Rs2_sw; - } - }}, IntDivOp); - 0x1: div({{ - constexpr int64_t kRsMin = \ - std::numeric_limits::min(); - if (Rs2_sd == 0) { - Rd_sd = -1; - } else if (Rs1_sd == kRsMin && Rs2_sd == -1) { - Rd_sd = kRsMin; - } else { - Rd_sd = Rs1_sd/Rs2_sd; - } - }}, IntDivOp); - } + 0x1: div({{ + if (machInst.rv_type == RV32) { + Rd_sd = div(Rs1, Rs2); + } else { + Rd_sd = div(Rs1, Rs2); + } + }}, IntDivOp); 0x4: pack({{ int xlen = rvSelect(32, 64); Rd = rvSext( @@ -1289,22 +1218,13 @@ decode QUADRANT default Unknown::unknown() { Rd = rvSext(rvZext(Rs1) >> rvSelect(Rs2<4:0>, Rs2<5:0>)); }}); - 0x1: decode RVTYPE { - 0x0: rv32_divu({{ - if (Rs2_uw == 0) { - Rd_sw = std::numeric_limits::max(); - } else { - Rd_sw = Rs1_uw/Rs2_uw; - } - }}, IntDivOp); - 0x1: divu({{ - if (Rs2 == 0) { - Rd = std::numeric_limits::max(); - } else { - Rd = Rs1/Rs2; - } - }}, IntDivOp); - } + 0x1: divu({{ + if (machInst.rv_type == RV32) { + Rd = (int32_t)divu(Rs1, Rs2); + } else { + Rd = divu(Rs1, Rs2); + } + }}, IntDivOp); 0x20: sra({{ Rd = rvSext(Rs1_sd) >> rvSelect(Rs2<4:0>, Rs2<5:0>); }}); @@ -1327,30 +1247,13 @@ decode QUADRANT default Unknown::unknown() { 0x0: or({{ Rd = rvSext(Rs1 | Rs2); }}); - 0x1: decode RVTYPE { - 0x0: rv32_rem({{ - constexpr int32_t kRsMin = \ - std::numeric_limits::min(); - if (Rs2_sw == 0) { - Rd_sw = Rs1_sw; - } else if (Rs1_sw == kRsMin && Rs2_sw == -1) { - Rd_sw = 0; - } else { - Rd_sw = Rs1_sw%Rs2_sw; - } - }}, IntDivOp); - 0x1: rem({{ - constexpr int64_t kRsMin = \ - std::numeric_limits::min(); - if (Rs2_sd == 0) { - Rd = Rs1_sd; - } else if (Rs1_sd == kRsMin && Rs2_sd == -1) { - Rd = 0; - } else { - Rd = Rs1_sd%Rs2_sd; - } - }}, IntDivOp); - } + 0x1: rem({{ + if (machInst.rv_type == RV32) { + Rd_sd = rem(Rs1, Rs2); + } else { + Rd_sd = rem(Rs1, Rs2); + } + }}, IntDivOp); 0x5: max({{ Rd_sd = std::max(rvSext(Rs1_sd), rvSext(Rs2_sd)); }}); @@ -1365,22 +1268,13 @@ decode QUADRANT default Unknown::unknown() { 0x0: and({{ Rd = rvSext(Rs1 & Rs2); }}); - 0x1: decode RVTYPE { - 0x0: rv32_remu({{ - if (Rs2_uw == 0) { - Rd_sw = Rs1_uw; - } else { - Rd_sw = Rs1_uw%Rs2_uw; - } - }}, IntDivOp); - 0x1: remu({{ - if (Rs2 == 0) { - Rd = Rs1; - } else { - Rd = Rs1%Rs2; - } - }}, IntDivOp); - } + 0x1: remu({{ + if (machInst.rv_type == RV32) { + Rd = (int32_t)remu(Rs1, Rs2); + } else { + Rd = remu(Rs1, Rs2); + } + }}, IntDivOp); 0x4: packh({{ // It doesn't need to sign ext as MSB is always 0 Rd = (Rs2_ub << 8) | Rs1_ub; @@ -1432,15 +1326,7 @@ decode QUADRANT default Unknown::unknown() { } 0x4: decode FUNCT7 { 0x1: divw({{ - constexpr int32_t kRsMin = \ - std::numeric_limits::min(); - if (Rs2_sw == 0) { - Rd_sd = -1; - } else if (Rs1_sw == kRsMin && Rs2_sw == -1) { - Rd_sd = kRsMin; - } else { - Rd_sd = Rs1_sw/Rs2_sw; - } + Rd_sd = div(Rs1, Rs2); }}, IntDivOp); 0x4: packw({{ Rd_sd = sext<32>((Rs2_uh << 16) | Rs1_uh); @@ -1454,11 +1340,7 @@ decode QUADRANT default Unknown::unknown() { Rd_sd = (int32_t)(Rs1_uw >> Rs2<4:0>); }}); 0x1: divuw({{ - if (Rs2_uw == 0) { - Rd_sd = std::numeric_limits::max(); - } else { - Rd_sd = (int32_t)(Rs1_uw/Rs2_uw); - } + Rd = sext<32>(divu(Rs1, Rs2)); }}, IntDivOp); 0x20: sraw({{ Rd_sd = Rs1_sw >> Rs2<4:0>; @@ -1470,26 +1352,14 @@ decode QUADRANT default Unknown::unknown() { } 0x6: decode FUNCT7 { 0x1: remw({{ - constexpr int32_t kRsMin = \ - std::numeric_limits::min(); - if (Rs2_sw == 0) { - Rd_sd = Rs1_sw; - } else if (Rs1_sw == kRsMin && Rs2_sw == -1) { - Rd_sd = 0; - } else { - Rd_sd = Rs1_sw%Rs2_sw; - } + Rd_sd = rem(Rs1, Rs2); }}, IntDivOp); 0x10: sh3add_uw({{ Rd = (((uint64_t)Rs1_uw) << 3) + Rs2; }}); } 0x7: remuw({{ - if (Rs2_uw == 0) { - Rd_sd = (int32_t)Rs1_uw; - } else { - Rd_sd = (int32_t)(Rs1_uw%Rs2_uw); - } + Rd = sext<32>(remu(Rs1, Rs2)); }}, IntDivOp); } } diff --git a/src/arch/riscv/utility.hh b/src/arch/riscv/utility.hh index 3bd34c4801..5fccc84c79 100644 --- a/src/arch/riscv/utility.hh +++ b/src/arch/riscv/utility.hh @@ -55,6 +55,7 @@ #include "cpu/reg_class.hh" #include "cpu/static_inst.hh" #include "cpu/thread_context.hh" +#include "enums/RiscvType.hh" #include "rvk.hh" namespace gem5 @@ -137,6 +138,101 @@ registerName(RegId reg) } } +inline uint32_t +mulhu_32(uint32_t rs1, uint32_t rs2) +{ + return ((uint64_t)rs1 * rs2) >> 32; +} + +inline uint64_t +mulhu_64(uint64_t rs1, uint64_t rs2) +{ + uint64_t rs1_lo = (uint32_t)rs1; + uint64_t rs1_hi = rs1 >> 32; + uint64_t rs2_lo = (uint32_t)rs2; + uint64_t rs2_hi = rs2 >> 32; + + uint64_t hi = rs1_hi * rs2_hi; + uint64_t mid1 = rs1_hi * rs2_lo; + uint64_t mid2 = rs1_lo * rs2_hi; + uint64_t lo = rs1_lo * rs2_lo; + uint64_t carry = ((uint64_t)(uint32_t)mid1 + + (uint64_t)(uint32_t)mid2 + + (lo >> 32)) >> 32; + + return hi + (mid1 >> 32) + (mid2 >> 32) + carry; +} + +inline int32_t +mulh_32(int32_t rs1, int32_t rs2) +{ + return ((int64_t)rs1 * rs2) >> 32; +} + +inline int64_t +mulh_64(int64_t rs1, int64_t rs2) +{ + bool negate = (rs1 < 0) != (rs2 < 0); + uint64_t res = mulhu_64(std::abs(rs1), std::abs(rs2)); + return negate ? ~res + (rs1 * rs2 == 0 ? 1 : 0) : res; +} + +inline int32_t +mulhsu_32(int32_t rs1, uint32_t rs2) +{ + return ((int64_t)rs1 * rs2) >> 32; +} + +inline int64_t +mulhsu_64(int64_t rs1, uint64_t rs2) +{ + bool negate = rs1 < 0; + uint64_t res = mulhu_64(std::abs(rs1), rs2); + return negate ? ~res + (rs1 * rs2 == 0 ? 1 : 0) : res; +} + +template inline T +div(T rs1, T rs2) +{ + constexpr T kRsMin = std::numeric_limits::min(); + if (rs2 == 0) { + return -1; + } else if (rs1 == kRsMin && rs2 == -1) { + return kRsMin; + } else { + return rs1 / rs2; + } +} + +template inline T +divu(T rs1, T rs2) +{ + if (rs2 == 0) { + return std::numeric_limits::max(); + } else { + return rs1 / rs2; + } +} + +template inline T +rem(T rs1, T rs2) +{ + constexpr T kRsMin = std::numeric_limits::min(); + if (rs2 == 0) { + return rs1; + } else if (rs1 == kRsMin && rs2 == -1) { + return 0; + } else { + return rs1 % rs2; + } +} + +template inline T +remu(T rs1, T rs2) +{ + return (rs2 == 0) ? rs1 : rs1 % rs2; +} + } // namespace RiscvISA } // namespace gem5