summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Lee <me@nwlee.tech>2026-06-04 12:07:29 -0500
committerNathan Lee <me@nwlee.tech>2026-06-04 12:07:29 -0500
commitb31680496f402b50f3862be98f3637d007e263c3 (patch)
tree11e8e76467763efb6cd34bdfb4846376edb8af17
parent7108182de52cf4befcbd4e158c3c9c57b68aa94b (diff)
finish M extension
-rw-r--r--src/main.rs55
1 files changed, 48 insertions, 7 deletions
diff --git a/src/main.rs b/src/main.rs
index d9e75d7..8c69c20 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -66,14 +66,14 @@ fn handle_instruction(memory: &mut [u8], registers: &mut [u32], pc: &mut u32) {
let rd = ((word >> 7) & 0b11111) as usize;
match (f7 << 3) | f3 {
- 0 => registers[rd] = registers[rs1] + registers[rs2], // add
- 256 => registers[rd] = registers[rs1] - registers[rs2], // sub
+ 0 => registers[rd] = registers[rs1].wrapping_add(registers[rs2]), // add
+ 256 => registers[rd] = registers[rs1].wrapping_sub(registers[rs2]), // sub
4 => registers[rd] = registers[rs1] ^ registers[rs2], // xor
6 => registers[rd] = registers[rs1] | registers[rs2], // or
7 => registers[rd] = registers[rs1] & registers[rs2], // and
- 1 => registers[rd] = registers[rs1] << registers[rs2], // sll
- 5 => registers[rd] = registers[rs1] >> registers[rs2], // srl
- 261 => registers[rd] = ((registers[rs1] as i32) >> registers[rs2]) as u32, // sra
+ 1 => registers[rd] = registers[rs1] << (registers[rs2] & 0b11111), // sll
+ 5 => registers[rd] = registers[rs1] >> (registers[rs2] & 0b11111), // srl
+ 261 => registers[rd] = ((registers[rs1] as i32) >> (registers[rs2] & 0b11111)) as u32, // sra
2 => {
let rs1_signed: i32 = registers[rs1] as i32;
let rs2_signed: i32 = registers[rs2] as i32;
@@ -86,6 +86,47 @@ fn handle_instruction(memory: &mut [u8], registers: &mut [u32], pc: &mut u32) {
0
}
} // sltu
+ 8 => registers[rd] = registers[rs1].wrapping_mul(registers[rs2]), // mul
+ 9 => registers[rd] = (((registers[rs1] as i32 as i64) * (registers[rs2] as i32 as i64)) >> 32) as u32, // mulh
+ 10 => {
+ let rs1_signed = (registers[rs1] as i32) as i64;
+ let rs2_unsigned = registers[rs2] as i64;
+ registers[rd] = ((rs1_signed * rs2_unsigned) >> 32) as u32;
+ } // mulhsu
+ 11 => registers[rd] = ((registers[rs1] as u64 * registers[rs2] as u64) >> 32) as u32, // mulhu
+ 12 => {
+ let a = registers[rs1] as i32;
+ let b = registers[rs2] as i32;
+ registers[rd] = if b == 0 {
+ u32::MAX
+ } else if a == i32::MIN && b == -1 {
+ a as u32
+ } else {
+ (a / b) as u32
+ };
+ }, // div
+ 13 => registers[rd] = if registers[rs2] == 0 {
+ u32::MAX
+ } else {
+ registers[rs1] / registers[rs2]
+ }, // divu
+ 14 => {
+ let a = registers[rs1] as i32;
+ let b = registers[rs2] as i32;
+ registers[rd] = if b == 0 {
+ a as u32
+ } else if a == i32::MIN && b == -1 {
+ 0
+ } else {
+ (a % b) as u32
+ }
+ }, // rem
+ 15 => registers[rd] = if registers[rs2] == 0 {
+ registers[rs1]
+ } else {
+ registers[rs1] % registers[rs2]
+ }, //remu
+
_ => panic!("Illegal instruction: {:x}", word),
}
}
@@ -219,13 +260,13 @@ fn handle_instruction(memory: &mut [u8], registers: &mut [u32], pc: &mut u32) {
return;
} // bge
6 => {
- if (registers[rs1] < registers[rs2]) {
+ if registers[rs1] < registers[rs2] {
*pc += imm;
}
return;
} // bltu
7 => {
- if (registers[rs1] >= registers[rs2]) {
+ if registers[rs1] >= registers[rs2] {
*pc += imm;
}
return;