summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNathan Lee <me@nwlee.tech>2026-06-04 12:37:50 -0500
committerNathan Lee <me@nwlee.tech>2026-06-04 12:37:50 -0500
commit26c0e95d64b31bb2393cb7f5c18969d3d8475bda (patch)
tree654b63ecf464a1ae66f8f0d688a86df079c55d4d /src
parentb31680496f402b50f3862be98f3637d007e263c3 (diff)
fix small issues with other I extension and move allocation to heap instead of stack
Diffstat (limited to 'src')
-rw-r--r--src/main.rs42
1 files changed, 27 insertions, 15 deletions
diff --git a/src/main.rs b/src/main.rs
index 8c69c20..0ad8162 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,9 +2,13 @@ use elf::ElfBytes;
use elf::endian::AnyEndian;
use std::io;
use std::io::Write;
+use std::process::exit;
use std::sync::{LazyLock, Mutex};
-static MEMORY: LazyLock<Mutex<[u8; 64 * 1024 * 1024]>> =
- LazyLock::new(|| Mutex::new([0u8; 64 * 1024 * 1024]));
+
+const MEMORY_SIZE: usize = 64 * 1024 * 1024;
+static MEMORY: LazyLock<Mutex<Box<[u8]>>> = LazyLock::new(|| {
+ Mutex::new(vec![0u8; MEMORY_SIZE].into_boxed_slice())
+});
fn main() {
let path = std::path::PathBuf::from("hi");
@@ -43,12 +47,14 @@ fn main() {
}
loop {
- let mut memory = MEMORY.lock().expect("Unable to get memory");
- handle_instruction(&mut *memory, &mut registers, &mut pc);
+ {
+ let mut memory = MEMORY.lock().expect("Unable to get memory");
+ handle_instruction(&mut *memory, &mut registers, &mut pc);
+ }
}
}
-fn handle_instruction(memory: &mut [u8], registers: &mut [u32], pc: &mut u32) {
+fn handle_instruction(memory: &mut Box<[u8]>, registers: &mut [u32], pc: &mut u32) {
let word = u32::from_le_bytes([
memory[*pc as usize],
memory[*pc as usize + 1],
@@ -138,24 +144,24 @@ fn handle_instruction(memory: &mut [u8], registers: &mut [u32], pc: &mut u32) {
let rd = ((word >> 7) & 0b11111) as usize;
match f3 {
- 0 => registers[rd] = registers[rs1] + imm, // addi
+ 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
1 => {
- if (word >> 5) != 0 {
+ if (imm >> 5) != 0 {
panic!("Illegal instruction: {:x}", word);
}
registers[rd] = registers[rs1] << (imm & 0b11111); // slli
}
5 => {
- if (word >> 5) != 0 {
+ if (imm >> 5) != 0 {
panic!("Illegal instruction: {:x}", word);
}
if (imm >> 5) & 0b1111111 == 0 {
registers[rd] = registers[rs1] >> (imm & 0b11111); // srli
} else {
- registers[rd] = ((registers[rs1] >> (imm & 0b11111)) as i32) as u32; // srai
+ registers[rd] = ((registers[rs1] as i32 >> (imm & 0b11111))) as u32; // srai
}
}
2 => {
@@ -170,7 +176,7 @@ fn handle_instruction(memory: &mut [u8], registers: &mut [u32], pc: &mut u32) {
}
}
0b0000011 => {
- let imm = word >> 20;
+ let imm = ((word as i32) >> 20) as u32;
let f3 = (word >> 12) & 0b111;
let rs1 = ((word >> 15) & 0b11111) as usize;
@@ -189,7 +195,7 @@ fn handle_instruction(memory: &mut [u8], registers: &mut [u32], pc: &mut u32) {
2 => {
let addr = (registers[rs1] + imm) as usize;
let slice = memory.get(addr..addr + 4).unwrap();
- let number: u32 = slice.iter().fold(0u32, |acc, &n| (acc << 8) | n as u32);
+ 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
@@ -208,7 +214,7 @@ fn handle_instruction(memory: &mut [u8], registers: &mut [u32], pc: &mut u32) {
let rs1 = ((word >> 15) & 0b11111) as usize;
let rs2 = ((word >> 20) & 0b11111) as usize;
- let imm = (imm_high << 5) | imm_low;
+ 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
@@ -226,13 +232,17 @@ fn handle_instruction(memory: &mut [u8], registers: &mut [u32], pc: &mut u32) {
};
}
0b1100011 => {
- let imm_low = (word >> 7) & 0b11111;
- let imm_high = (word >> 25) & 0b1111111;
let f3 = (word >> 12) & 0b111;
let rs1 = ((word >> 15) & 0b11111) as usize;
let rs2 = ((word >> 20) & 0b11111) as usize;
- let imm = (imm_high << 5) | imm_low;
+ let imm =
+ (((word >> 31) & 0x1) << 12)
+ | (((word >> 7) & 0x1) << 11)
+ | (((word >> 25) & 0x3f) << 5)
+ | (((word >> 8) & 0xf) << 1);
+
+ let imm = ((imm as i32) << 19 >> 19) as u32;
match f3 {
0 => {
@@ -317,6 +327,8 @@ fn handle_instruction(memory: &mut [u8], registers: &mut [u32], pc: &mut u32) {
let len = registers[12] as usize;
let total_bytes = &memory[buf..buf + len];
io::stdout().write(&total_bytes).unwrap();
+ } else if registers[17] == 60 {
+ exit(registers[10] as i32);
}
} // ecall (ebreak not implemented)
_ => panic!("Illegal instruction or todo: {:x}", word),