diff options
| author | Nathan Lee <me@nwlee.tech> | 2026-06-04 12:07:29 -0500 |
|---|---|---|
| committer | Nathan Lee <me@nwlee.tech> | 2026-06-04 12:07:29 -0500 |
| commit | b31680496f402b50f3862be98f3637d007e263c3 (patch) | |
| tree | 11e8e76467763efb6cd34bdfb4846376edb8af17 | |
| parent | 7108182de52cf4befcbd4e158c3c9c57b68aa94b (diff) | |
finish M extension
| -rw-r--r-- | src/main.rs | 55 |
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; |
