Finish RV64M

This commit is contained in:
2025-12-30 20:53:57 +01:00
parent 5a383956c9
commit 0f0e844223
3 changed files with 52 additions and 3 deletions

View File

@@ -4,7 +4,7 @@ taitep's RISC-V Emulator.
The goal is to support at least RV64GC and be able to run Linux, The goal is to support at least RV64GC and be able to run Linux,
potentially more. No plans for RV32I or RV32/64E. potentially more. No plans for RV32I or RV32/64E.
Currently implemented RISC-V ISA: `RV64I` Currently implemented RISC-V ISA: `RV64IM`
## Current Use ## Current Use
Currently, the emulator is nowhere near complete, Currently, the emulator is nowhere near complete,

View File

@@ -32,7 +32,6 @@ pub(crate) fn find_and_exec(instr: Instruction, core: &mut Core) -> Result<(), E
// OP // OP
(0b000, 0b0000000) => rvi::add(core, instr), (0b000, 0b0000000) => rvi::add(core, instr),
(0b000, 0b0100000) => rvi::sub(core, instr), (0b000, 0b0100000) => rvi::sub(core, instr),
(0b000, 0b0000001) => rvm::mul(core, instr),
(0b010, 0b0000000) => rvi::slt(core, instr), (0b010, 0b0000000) => rvi::slt(core, instr),
(0b011, 0b0000000) => rvi::sltu(core, instr), (0b011, 0b0000000) => rvi::sltu(core, instr),
(0b001, 0b0000000) => rvi::sll(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), (0b101, 0b0100000) => rvi::sra(core, instr),
(0b111, 0b0000000) => rvi::and(core, instr), (0b111, 0b0000000) => rvi::and(core, instr),
(0b100, 0b0000000) => rvi::xor(core, instr), (0b100, 0b0000000) => rvi::xor(core, instr),
(0b100, 0b0000001) => rvm::div(core, instr),
(0b110, 0b0000000) => rvi::or(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), _ => illegal(instr),
}, },
0b01110 => match (instr.funct3(), instr.funct7()) { 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), (0b001, 0b0000000) => rvi::sllw(core, instr),
(0b101, 0b0000000) => rvi::srlw(core, instr), (0b101, 0b0000000) => rvi::srlw(core, instr),
(0b101, 0b0100000) => rvi::sraw(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), _ => illegal(instr),
}, },
0b00100 => match instr.funct3() { 0b00100 => match instr.funct3() {

View File

@@ -8,9 +8,45 @@ use crate::{core::Core, decode::Instruction, exceptions::Exception};
// multiplication // multiplication
instr_op_r!(mul, u64::wrapping_mul); 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 // division
instr_op_r!(div, |a, b| match b { instr_op_r!(div, |a, b| match b {
0 => -1, 0 => -1,
_ => i64::wrapping_div(a as i64, b as i64), _ => i64::wrapping_div(a as i64, b as i64),
} as u64); } 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);