diff --git a/CHANGELOG.md b/CHANGELOG.md index 89af99d..8cec549 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ - Feature: Canonicalize register names when parsing, converting e.g. `x0 -> zero` or `fp -> s0`. - Feature: Added support for `fcvt.d.w[u]` and `fcvt.w[u].d` instructions - BugFix: Fixed that registers were treated as UInt32s instead of Int32 (this may have caused subtle bugs before) + - Feature: Added the remainder of the `M` extension + - BugFix: Fixed a bug in the overflow behavior of `mulh` + - BugFix: Fix faulty length assertion in `jalr` ## 2.2.5 diff --git a/riscemu/instructions/RV32M.py b/riscemu/instructions/RV32M.py index 42ec681..f7d166e 100644 --- a/riscemu/instructions/RV32M.py +++ b/riscemu/instructions/RV32M.py @@ -5,7 +5,6 @@ """ from .instruction_set import * -from riscemu.core.exceptions import INS_NOT_IMPLEMENTED class RV32M(InstructionSet): @@ -19,13 +18,15 @@ def instruction_mul(self, ins: "Instruction"): def instruction_mulh(self, ins: "Instruction"): rd, rs1, rs2 = self.parse_rd_rs_rs(ins) - self.regs.set(rd, (rs1 * rs2) >> 32) + self.regs.set(rd, Int32((rs1.signed().value * rs2.signed().value) >> 32)) def instruction_mulhsu(self, ins: "Instruction"): - INS_NOT_IMPLEMENTED(ins) + rd, rs1, rs2 = self.parse_rd_rs_rs(ins) + self.regs.set(rd, Int32((rs1.signed().value * rs2.unsigned_value) >> 32)) def instruction_mulhu(self, ins: "Instruction"): - INS_NOT_IMPLEMENTED(ins) + rd, rs1, rs2 = self.parse_rd_rs_rs(ins) + self.regs.set(rd, UInt32((rs1.unsigned_value * rs2.unsigned_value) >> 32)) def instruction_div(self, ins: "Instruction"): rd, rs1, rs2 = self.parse_rd_rs_rs(ins) diff --git a/test/filecheck/rv32m-conv.asm b/test/filecheck/rv32m-conv.asm new file mode 100644 index 0000000..addda2e --- /dev/null +++ b/test/filecheck/rv32m-conv.asm @@ -0,0 +1,37 @@ +// RUN: python3 -m riscemu -v %s -o libc | filecheck %s + +.text + +.globl main +main: + // test mulh + li a1, -1 + mulh a0, a1, a1 + print a0 +// CHECK: register a0 contains value 0 + li a2, 2 + mulh a0, a1, a2 + print.uhex a0 +// CHECK-NEXT: register a0 contains value 0xffffffff + + // test mulhu + mulhu a0, a1, a2 + print a0 +// CHECK: register a0 contains value 1 + + mulhu a0, a1, a1 + print.uhex a0 +// CHECK-NEXT: register a0 contains value 0xfffffffe + + // test mulhsu + mulhsu a0, a1, a2 + print.uhex a0 +// CHECK: register a0 contains value 0xffffffff + + mulhsu a0, a2, a1 + print a0 +// CHECK-NEXT: register a0 contains value 1 + + li a0, 0 + ret +// CHECK-NEXT: [CPU] Program exited with code 0