From 0f0e844223a17452835aed88adb3af976d2e1eae Mon Sep 17 00:00:00 2001 From: taitep Date: Tue, 30 Dec 2025 20:53:57 +0100 Subject: [PATCH] Finish RV64M --- README.md | 2 +- src/instructions.rs | 17 +++++++++++++++-- src/instructions/rvm.rs | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 697c0f2..0862fe5 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ taitep's RISC-V Emulator. The goal is to support at least RV64GC and be able to run Linux, potentially more. No plans for RV32I or RV32/64E. -Currently implemented RISC-V ISA: `RV64I` +Currently implemented RISC-V ISA: `RV64IM` ## Current Use Currently, the emulator is nowhere near complete, diff --git a/src/instructions.rs b/src/instructions.rs index 2a224b3..d820f35 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -32,7 +32,6 @@ pub(crate) fn find_and_exec(instr: Instruction, core: &mut Core) -> Result<(), E // OP (0b000, 0b0000000) => rvi::add(core, instr), (0b000, 0b0100000) => rvi::sub(core, instr), - (0b000, 0b0000001) => rvm::mul(core, instr), (0b010, 0b0000000) => rvi::slt(core, instr), (0b011, 0b0000000) => rvi::sltu(core, instr), (0b001, 0b0000000) => rvi::sll(core, instr), @@ -40,8 +39,16 @@ pub(crate) fn find_and_exec(instr: Instruction, core: &mut Core) -> Result<(), E (0b101, 0b0100000) => rvi::sra(core, instr), (0b111, 0b0000000) => rvi::and(core, instr), (0b100, 0b0000000) => rvi::xor(core, instr), - (0b100, 0b0000001) => rvm::div(core, instr), (0b110, 0b0000000) => rvi::or(core, instr), + // rvm + (0b000, 0b0000001) => rvm::mul(core, instr), + (0b001, 0b0000001) => rvm::mulh(core, instr), + (0b010, 0b0000001) => rvm::mulhsu(core, instr), + (0b011, 0b0000001) => rvm::mulhu(core, instr), + (0b100, 0b0000001) => rvm::div(core, instr), + (0b101, 0b0000001) => rvm::divu(core, instr), + (0b110, 0b0000001) => rvm::rem(core, instr), + (0b111, 0b0000001) => rvm::remu(core, instr), _ => illegal(instr), }, 0b01110 => match (instr.funct3(), instr.funct7()) { @@ -51,6 +58,12 @@ pub(crate) fn find_and_exec(instr: Instruction, core: &mut Core) -> Result<(), E (0b001, 0b0000000) => rvi::sllw(core, instr), (0b101, 0b0000000) => rvi::srlw(core, instr), (0b101, 0b0100000) => rvi::sraw(core, instr), + // rvm + (0b000, 0b0000001) => rvm::mulw(core, instr), + (0b100, 0b0000001) => rvm::divw(core, instr), + (0b101, 0b0000001) => rvm::divuw(core, instr), + (0b110, 0b0000001) => rvm::remw(core, instr), + (0b111, 0b0000001) => rvm::remuw(core, instr), _ => illegal(instr), }, 0b00100 => match instr.funct3() { diff --git a/src/instructions/rvm.rs b/src/instructions/rvm.rs index bd0c100..b87b9f9 100644 --- a/src/instructions/rvm.rs +++ b/src/instructions/rvm.rs @@ -8,9 +8,45 @@ use crate::{core::Core, decode::Instruction, exceptions::Exception}; // multiplication instr_op_r!(mul, u64::wrapping_mul); +instr_op_r!(mulw, |a, b| u32::wrapping_mul(a as u32, b as u32) as u64); + +instr_op_r!(mulh, |a, b| ((a as i64 as i128 * b as i64 as i128) >> 64) + as u64); +instr_op_r!(mulhsu, |a, b| ((a as i64 as i128 * b as i128) >> 64) as u64); +instr_op_r!(mulhu, |a, b| ((a as u128 * b as u128) >> 64) as u64); // division instr_op_r!(div, |a, b| match b { 0 => -1, _ => i64::wrapping_div(a as i64, b as i64), } as u64); +instr_op_r!(divu, |a, b| match b { + 0 => u64::MAX, + _ => a / b, +}); +instr_op_r!(divw, |a, b| match b { + 0 => -1, + _ => i32::wrapping_div(a as i32, b as i32), +} as i64 as u64); +instr_op_r!(divuw, |a, b| match b { + 0 => u32::MAX, + _ => a as u32 / b as u32, +} as i32 as i64 as u64); + +// remainder +instr_op_r!(rem, |a, b| match b { + 0 => a, + _ => i64::wrapping_rem(a as i64, b as i64) as u64, +}); +instr_op_r!(remu, |a, b| match b { + 0 => a, + _ => a % b, +}); +instr_op_r!(remw, |a, b| match b { + 0 => a as i32, + _ => i32::wrapping_rem(a as i32, b as i32), +} as i64 as u64); +instr_op_r!(remuw, |a, b| match b { + 0 => a as u32, + _ => a as u32 % b as u32, +} as i32 as i64 as u64);