summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
authorNathan Lee <me@nwlee.tech>2026-06-06 14:29:39 -0500
committerNathan Lee <me@nwlee.tech>2026-06-06 14:29:39 -0500
commit8f39a6cb1568f39c623cdb3e60c2848f3252b196 (patch)
tree8fd33ecad45824af82fb5b6387c6930d31cbd625 /src/main.rs
parent4aaac36bd8331a5f61c7dad1911d0d37561e0e2f (diff)
refactor most extensions in to their own separate core.rs file
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs222
1 files changed, 58 insertions, 164 deletions
diff --git a/src/main.rs b/src/main.rs
index 36c1c8c..a351d48 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,9 +1,12 @@
+pub mod core;
+
use elf::ElfBytes;
use elf::endian::AnyEndian;
use std::io;
use std::io::Write;
use std::process::exit;
use std::sync::{LazyLock, Mutex};
+use crate::core::*;
const MEMORY_SIZE: usize = 64 * 1024 * 1024;
const REGISTER_NAME_WIDTH: u32 = 0b11111;
@@ -85,79 +88,24 @@ fn handle_instruction(CpuState { memory, registers, pc, reservations }: CpuState
let rd = ((word >> 7) & REGISTER_NAME_WIDTH) as usize;
match (f7 << 3) | f3 {
- 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] & 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;
- registers[rd] = if rs1_signed < rs2_signed { 1 } else { 0 }; // slt
- }
- 3 => {
- registers[rd] = if registers[rs1] < registers[rs2] {
- 1
- } else {
- 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
-
+ 0 => add(registers, rd, rs1, rs2),
+ 256 => sub(registers, rd, rs1, rs2),
+ 4 => xor(registers, rd, rs1, rs2),
+ 6 => or(registers, rd, rs1, rs2),
+ 7 => and(registers, rd, rs1, rs2),
+ 1 => sll(registers, rd, rs1, rs2),
+ 5 => srl(registers, rd, rs1, rs2),
+ 261 => sra(registers, rd, rs1, rs2),
+ 2 => slt(registers, rd, rs1, rs2),
+ 3 => sltu(registers, rd, rs1, rs2),
+ 8 => mul(registers, rd, rs1, rs2),
+ 9 => mulh(registers, rd, rs1, rs2),
+ 10 => mulhsu(registers, rd, rs1, rs2),
+ 11 => mulhu(registers, rd, rs1, rs2),
+ 12 => div(registers, rd, rs1, rs2),
+ 13 => divu(registers, rd, rs1, rs2),
+ 14 => rem(registers, rd, rs1, rs2),
+ 15 => remu(registers, rd, rs1, rs2),
_ => panic!("Illegal instruction: {:x}", word),
}
}
@@ -169,34 +117,28 @@ fn handle_instruction(CpuState { memory, registers, pc, reservations }: CpuState
let rd = ((word >> 7) & 0b11111) as usize;
match f3 {
- 0 => registers[rd] = registers[rs1].wrapping_add(imm), // addi
- 4 => registers[rd] = registers[rs1] ^ imm, // xori
- 6 => registers[rd] = registers[rs1] | imm, // ori
- 7 => registers[rd] = registers[rs1] & imm, // andi
+ 0 => addi(registers, rd, rs1, imm),
+ 4 => xori(registers, rd, rs1, imm),
+ 6 => ori(registers, rd, rs1, imm),
+ 7 => andi(registers, rd, rs1, imm),
1 => {
if (imm >> 5) != 0 {
panic!("Illegal instruction: {:x}", word);
}
- registers[rd] = registers[rs1] << (imm & 0b11111); // slli
+ slli(registers, rd, rs1, imm);
}
5 => {
if (imm >> 5) != 0 {
panic!("Illegal instruction: {:x}", word);
}
if (imm >> 5) & 0b1111111 == 0 {
- registers[rd] = registers[rs1] >> (imm & 0b11111); // srli
+ srli(registers, rd, rs1, imm);
} else {
- registers[rd] = (registers[rs1] as i32 >> (imm & 0b11111)) as u32; // srai
+ srai(registers, rd, rs1, imm);
}
}
- 2 => {
- registers[rd] = if (registers[rs1] as i32) < (imm as i32) {
- 1
- } else {
- 0
- }
- } // slti
- 3 => registers[rd] = if registers[rs1] < imm { 1 } else { 0 }, // sltiu
+ 2 => slti(registers, rd, rs1, imm),
+ 3 => sltiu(registers, rd, rs1, imm),
_ => panic!("Illegal instruction: {:x}", word),
}
}
@@ -208,27 +150,11 @@ fn handle_instruction(CpuState { memory, registers, pc, reservations }: CpuState
let rd = ((word >> 7) & 0b11111) as usize;
match f3 {
- 0 => {
- let byte: u8 = memory[(registers[rs1] + imm) as usize];
- registers[rd] = (byte as i8) as u32; // lb
- }
- 1 => {
- let low = memory[(registers[rs1] + imm) as usize];
- let high = memory[(registers[rs1] + imm + 1) as usize];
- registers[rd] = (((high as u16) << 8 | low as u16) as i16) as u32; // lh
- }
- 2 => {
- let addr = (registers[rs1] + imm) as usize;
- let slice = memory.get(addr..addr + 4).unwrap();
- let number: u32 = u32::from_le_bytes(slice.try_into().unwrap());
- registers[rd] = number; // lw
- }
- 4 => registers[rd] = memory[(registers[rs1] + imm) as usize] as u32, // lbu
- 5 => {
- let low = memory[(registers[rs1] + imm) as usize];
- let high = memory[(registers[rs1] + imm + 1) as usize];
- registers[rd] = ((high as u16) << 8 | low as u16) as u32; // lhu
- }
+ 0 => lb(registers, memory, rd, rs1, imm),
+ 1 => lh(registers, memory, rd, rs1, imm),
+ 2 => lw(registers, memory, rd, rs1, imm),
+ 4 => lbu(registers, memory, rd, rs1, imm),
+ 5 => lhu(registers, memory, rd, rs1, imm),
_ => panic!("Illegal instruction: {:x}", word),
}
}
@@ -242,17 +168,9 @@ fn handle_instruction(CpuState { memory, registers, pc, reservations }: CpuState
let imm = ((((imm_high << 5) | imm_low) as i32) << 20 >> 20) as u32;
match f3 {
- 0 => memory[(registers[rs1] + imm) as usize] = registers[rs2] as u8, // sb
- 1 => {
- let halfword = registers[rs2] & 0xFFFF;
- let index = (registers[rs1] + imm) as usize;
- memory[index] = (halfword & 0xFF) as u8;
- memory[index + 1] = (halfword >> 8) as u8;
- } // sh
- 2 => {
- let index = (registers[rs1] + imm) as usize;
- memory[index..index + 4].copy_from_slice(&registers[rs2].to_le_bytes()); // sw
- }
+ 0 => sb(registers, memory, rs1, rs2, imm), // sb
+ 1 => sh(registers, memory, rs1, rs2, imm),
+ 2 => sw(registers, memory, rs1, rs2, imm),
_ => panic!("Illegal instruction: {:x}", word),
};
}
@@ -269,51 +187,27 @@ fn handle_instruction(CpuState { memory, registers, pc, reservations }: CpuState
let imm = ((imm as i32) << 19 >> 19) as u32;
match f3 {
- 0 => {
- if registers[rs1] == registers[rs2] {
- *pc += imm;
- }
- return;
- } // beq
- 1 => {
- if registers[rs1] != registers[rs2] {
- *pc += imm;
- }
- return;
- } // bne
- 4 => {
- if (registers[rs1] as i32) < (registers[rs2] as i32) {
- *pc += imm;
- }
- return;
- } // blt
- 5 => {
- if (registers[rs1] as i32) >= (registers[rs2] as i32) {
- *pc += imm;
- }
- return;
- } // bge
- 6 => {
- if registers[rs1] < registers[rs2] {
- *pc += imm;
- }
- return;
- } // bltu
- 7 => {
- if registers[rs1] >= registers[rs2] {
- *pc += imm;
- }
- return;
- } // bgeu
+ 0 => beq(registers, pc, rs1, rs2, imm),
+ 1 => bne(registers, pc, rs1, rs2, imm),
+ 4 => blt(registers, pc, rs1, rs2, imm),
+ 5 => bge(registers, pc, rs1, rs2, imm),
+ 6 => bltu(registers, pc, rs1, rs2, imm),
+ 7 => bgeu(registers, pc, rs1, rs2, imm),
_ => panic!("Illegal instruction: {:x}", word),
}
+ return;
}
0b1101111 => {
let rd = (word >> 7) & REGISTER_NAME_WIDTH;
- let imm = word >> 12;
- registers[rd as usize] = *pc + 4;
- *pc += imm;
- } // jal
+ let imm =
+ (((word >> 31) & 0x1) << 20) |
+ (((word >> 12) & 0xFF) << 12) |
+ (((word >> 20) & 0x1) << 11) |
+ (((word >> 21) & 0x3FF) << 1);
+ let imm = ((imm as i32) << 11 >> 11) as u32;
+ jal(registers, pc, rd as usize, imm);
+ return;
+ }
0b1100111 => {
let rs1 = (word >> 15) & REGISTER_NAME_WIDTH;
let rd = (word >> 7) & REGISTER_NAME_WIDTH;
@@ -324,18 +218,18 @@ fn handle_instruction(CpuState { memory, registers, pc, reservations }: CpuState
panic!("Illegal instruction: {:x}", word);
}
- registers[rd as usize] = *pc + 4;
- *pc = registers[rs1 as usize] + imm;
+ jalr(registers, pc, rd as usize, rs1 as usize, imm);
+ return;
}
0b0110111 => {
let imm = word >> 12;
let rd = ((word >> 7) & 0b11111) as usize;
- registers[rd] = imm << 12; // lui
+ lui(registers, rd, imm);
}
0b0010111 => {
let imm = word >> 12;
let rd = (word >> 7) & REGISTER_NAME_WIDTH;
- registers[rd as usize] = *pc + (imm << 12); // auipc
+ auipc(registers, *pc, rd as usize, imm);
}
0b1110011 => {
// ecall