summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs344
1 files changed, 135 insertions, 209 deletions
diff --git a/src/main.rs b/src/main.rs
index 9ec507b..965826e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,94 +1,38 @@
pub mod core;
+pub mod mem;
+pub mod state;
use crate::core::*;
-use elf::ElfBytes;
-use elf::endian::AnyEndian;
use std::collections::HashSet;
use std::io;
use std::io::Write;
use std::process::exit;
-use std::sync::{LazyLock, Mutex};
+use crate::mem::Memory;
+use crate::state::CpuState;
const MEMORY_SIZE: usize = 64 * 1024 * 1024;
const REGISTER_NAME_WIDTH: u32 = 0b11111;
-static MEMORY: LazyLock<Mutex<Box<[u8]>>> =
- LazyLock::new(|| Mutex::new(vec![0u8; MEMORY_SIZE].into_boxed_slice()));
-
-struct CpuState<'a> {
- memory: &'a mut Box<[u8]>,
- registers: &'a mut [u32; 32],
- f_registers: &'a mut [f32; 32],
- pc: &'a mut u32,
- reservations: &'a mut HashSet<usize>,
-}
+const RO_TARGET: u32 = 0x80000000;
fn main() {
- let path = std::path::PathBuf::from("hi");
-
+ let path = std::path::PathBuf::from("wkern.bin");
let f_dat = std::fs::read(path).expect("Unable to read file");
- let elf = ElfBytes::<AnyEndian>::minimal_parse(f_dat.as_slice()).expect("Unable to parse elf");
-
- let (sh, stab) = elf
- .section_headers_with_strtab()
- .expect("Unable to get section headers");
-
- let dup = f_dat.clone();
+ let memory = Memory::new(MEMORY_SIZE);
- // write memory
- {
- let mut memory = MEMORY.lock().expect("Unable to get memory");
- for i in 0..dup.len() {
- memory[i] = dup[i];
- }
- }
-
- let mut registers: [u32; 32] = [0; 32];
- let mut f_registers: [f32; 32] = [0f32; 32];
- let mut pc: u32 = 0;
- let mut reservations: HashSet<usize> = HashSet::new();
-
- let str_tab = stab.expect("Cannot read strtab");
- if let Some(headers) = sh {
- for header in headers {
- // Search for .text
- if let Ok(sh_name) = str_tab.get(header.sh_name as usize)
- && sh_name == ".text"
- {
- pc = header.sh_addr as u32;
- }
- }
- }
+ let mut state = CpuState::new(memory);
loop {
{
- let mut memory = MEMORY.lock().expect("Unable to get memory");
- handle_instruction(CpuState {
- memory: &mut *memory,
- registers: &mut registers,
- f_registers: &mut f_registers,
- pc: &mut pc,
- reservations: &mut reservations,
- });
+ handle_instruction(&mut state);
}
}
}
-fn handle_instruction(
- CpuState {
- memory,
- registers,
- f_registers,
- pc,
- reservations,
- }: CpuState,
-) {
- let word = u32::from_le_bytes([
- memory[*pc as usize],
- memory[*pc as usize + 1],
- memory[*pc as usize + 2],
- memory[*pc as usize + 3],
- ]);
+fn handle_instruction(state: &mut CpuState) {
+ let pc = state.pc;
+ let instruction = state.memory.read_multiple_bytes(pc as usize, 4, 99);
+ let word = u32::from_le_bytes(instruction.unwrap()[0..4].try_into().unwrap());
let opcode = word & 0x7f;
match opcode {
0b0110011 => {
@@ -100,24 +44,24 @@ fn handle_instruction(
let rd = ((word >> 7) & REGISTER_NAME_WIDTH) as usize;
match (f7 << 3) | f3 {
- 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),
+ 0 => add(state, rd, rs1, rs2),
+ 256 => sub(state, rd, rs1, rs2),
+ 4 => xor(state, rd, rs1, rs2),
+ 6 => or(state, rd, rs1, rs2),
+ 7 => and(state, rd, rs1, rs2),
+ 1 => sll(state, rd, rs1, rs2),
+ 5 => srl(state, rd, rs1, rs2),
+ 261 => sra(state, rd, rs1, rs2),
+ 2 => slt(state, rd, rs1, rs2),
+ 3 => sltu(state, rd, rs1, rs2),
+ 8 => mul(state, rd, rs1, rs2),
+ 9 => mulh(state, rd, rs1, rs2),
+ 10 => mulhsu(state, rd, rs1, rs2),
+ 11 => mulhu(state, rd, rs1, rs2),
+ 12 => div(state, rd, rs1, rs2),
+ 13 => divu(state, rd, rs1, rs2),
+ 14 => rem(state, rd, rs1, rs2),
+ 15 => remu(state, rd, rs1, rs2),
_ => panic!("Illegal instruction: {:x}", word),
}
}
@@ -129,28 +73,28 @@ fn handle_instruction(
let rd = ((word >> 7) & 0b11111) as usize;
match f3 {
- 0 => addi(registers, rd, rs1, imm),
- 4 => xori(registers, rd, rs1, imm),
- 6 => ori(registers, rd, rs1, imm),
- 7 => andi(registers, rd, rs1, imm),
+ 0 => addi(state, rd, rs1, imm),
+ 4 => xori(state, rd, rs1, imm),
+ 6 => ori(state, rd, rs1, imm),
+ 7 => andi(state, rd, rs1, imm),
1 => {
if (imm >> 5) != 0 {
panic!("Illegal instruction: {:x}", word);
}
- slli(registers, rd, rs1, imm);
+ slli(state, rd, rs1, imm);
}
5 => {
if (imm >> 5) != 0 {
panic!("Illegal instruction: {:x}", word);
}
if (imm >> 5) & 0b1111111 == 0 {
- srli(registers, rd, rs1, imm);
+ srli(state, rd, rs1, imm);
} else {
- srai(registers, rd, rs1, imm);
+ srai(state, rd, rs1, imm);
}
}
- 2 => slti(registers, rd, rs1, imm),
- 3 => sltiu(registers, rd, rs1, imm),
+ 2 => slti(state, rd, rs1, imm),
+ 3 => sltiu(state, rd, rs1, imm),
_ => panic!("Illegal instruction: {:x}", word),
}
}
@@ -162,11 +106,11 @@ fn handle_instruction(
let rd = ((word >> 7) & 0b11111) as usize;
match f3 {
- 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),
+ 0 => lb(state, rd, rs1, imm),
+ 1 => lh(state, rd, rs1, imm),
+ 2 => lw(state, rd, rs1, imm),
+ 4 => lbu(state, rd, rs1, imm),
+ 5 => lhu(state, rd, rs1, imm),
_ => panic!("Illegal instruction: {:x}", word),
}
}
@@ -179,20 +123,20 @@ fn handle_instruction(
let imm = ((((imm_high << 5) | imm_low) as i32) << 20 >> 20) as u32;
- let addr = (registers[rs1] + imm) as usize;
+ let addr = (state.registers[rs1] + imm) as usize;
match f3 {
0 => {
- sb(registers, memory, rs1, rs2, imm);
- release_reservations(reservations, &[addr]);
+ sb(state, rs1, rs2, imm);
+ release_reservations(state, &[addr]);
}
1 => {
- sh(registers, memory, rs1, rs2, imm);
- release_reservations(reservations, &[addr, addr + 1]);
+ sh(state, rs1, rs2, imm);
+ release_reservations(state, &[addr, addr + 1]);
}
2 => {
- sw(registers, memory, rs1, rs2, imm);
- release_reservations(reservations, &[addr, addr + 1, addr + 2, addr + 3]);
+ sw(state, rs1, rs2, imm);
+ release_reservations(state, &[addr, addr + 1, addr + 2, addr + 3]);
}
_ => panic!("Illegal instruction: {:x}", word),
};
@@ -210,12 +154,12 @@ fn handle_instruction(
let imm = ((imm as i32) << 19 >> 19) as u32;
match f3 {
- 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),
+ 0 => beq(state, rs1, rs2, imm),
+ 1 => bne(state, rs1, rs2, imm),
+ 4 => blt(state, rs1, rs2, imm),
+ 5 => bge(state, rs1, rs2, imm),
+ 6 => bltu(state, rs1, rs2, imm),
+ 7 => bgeu(state, rs1, rs2, imm),
_ => panic!("Illegal instruction: {:x}", word),
}
return;
@@ -227,7 +171,7 @@ fn handle_instruction(
| (((word >> 20) & 0x1) << 11)
| (((word >> 21) & 0x3FF) << 1);
let imm = ((imm as i32) << 11 >> 11) as u32;
- jal(registers, pc, rd as usize, imm);
+ jal(state, rd as usize, imm);
return;
}
0b1100111 => {
@@ -240,36 +184,26 @@ fn handle_instruction(
panic!("Illegal instruction: {:x}", word);
}
- jalr(registers, pc, rd as usize, rs1 as usize, imm);
+ jalr(state, rd as usize, rs1 as usize, imm);
return;
}
0b0110111 => {
let imm = word >> 12;
let rd = ((word >> 7) & 0b11111) as usize;
- lui(registers, rd, imm);
+ lui(state, rd, imm);
}
0b0010111 => {
let imm = word >> 12;
let rd = (word >> 7) & REGISTER_NAME_WIDTH;
- auipc(registers, *pc, rd as usize, imm);
+ auipc(state, *pc, rd as usize, imm);
}
0b1110011 => {
// ecall
eprintln!(
- "TRAP! syscall {} with gp registers {:?} calling instruction {:x}",
- registers[17],
- &registers[10..17],
- *pc
+ "TRAP! syscall {} with gp state {:?}",
+ state.registers[17],
+ pc
);
- if registers[17] == 0 {
- // sys_write: just a debug
- let buf = registers[11] as usize;
- 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)
0b0101111 => {
let f5 = word >> 27;
@@ -284,73 +218,73 @@ fn handle_instruction(
match f5 {
2 => {
- let addr = registers[rs1] as usize;
- let number: u32 = load_word(&memory, addr);
- registers[rd] = number;
+ let addr = state[rs1] as usize;
+ let number: u32 = load_word(&addr);
+ state[rd] = number;
acquire_reservations(reservations, &[addr, addr + 1, addr + 2, addr + 3]);
} // lr.w
3 => {
- let addr = registers[rs1] as usize;
+ let addr = state[rs1] as usize;
if (*reservations).contains(&addr) {
- memory[addr..addr + 4].copy_from_slice(&registers[rs2].to_le_bytes());
- registers[rd] = 0;
+ memory[addr..addr + 4].copy_from_slice(&state[rs2].to_le_bytes());
+ state[rd] = 0;
} else {
- registers[rd] = 1;
+ state[rd] = 1;
}
} // sc.w
1 => {
- let addr = registers[rs1] as usize;
- let number: u32 = load_word(&memory, addr);
- registers[rd] = number;
- store_word(memory, addr, registers[rs2]);
+ let addr = state[rs1] as usize;
+ let number: u32 = load_word(&addr);
+ state[rd] = number;
+ store_word(addr, state[rs2]);
} // amoswap.w
0 => {
- let addr = registers[rs1] as usize;
- let number: u32 = load_word(&memory, addr);
- registers[rd] = (number as i32 + registers[rs2] as i32) as u32;
- store_word(memory, addr, registers[rd]);
+ let addr = state[rs1] as usize;
+ let number: u32 = load_word(&addr);
+ state[rd] = (number as i32 + state[rs2] as i32) as u32;
+ store_word(addr, state[rd]);
} // amoadd.w
12 => {
- let addr = registers[rs1] as usize;
- let number: u32 = load_word(&memory, addr);
- registers[rd] = number & registers[rs2];
- store_word(memory, addr, registers[rd]);
+ let addr = state[rs1] as usize;
+ let number: u32 = load_word(&addr);
+ state[rd] = number & state[rs2];
+ store_word(addr, state[rd]);
} // amoand.w
8 => {
- let addr = registers[rs1] as usize;
- let number: u32 = load_word(&memory, addr);
- registers[rd] = number | registers[rs2];
- store_word(memory, addr, registers[rd]);
+ let addr = state[rs1] as usize;
+ let number: u32 = load_word(&addr);
+ state[rd] = number | state[rs2];
+ store_word(addr, state[rd]);
} // amoor.w
4 => {
- let addr = registers[rs1] as usize;
- let number: u32 = load_word(&memory, addr);
- registers[rd] = number ^ registers[rs2];
- store_word(memory, addr, registers[rd]);
+ let addr = state[rs1] as usize;
+ let number: u32 = load_word(&addr);
+ state[rd] = number ^ state[rs2];
+ store_word(addr, state[rd]);
} // amoxor.w
20 => {
- let addr = registers[rs1] as usize;
- let number: u32 = load_word(&memory, addr);
- registers[rd] = std::cmp::max(number as i32, registers[rs2] as i32) as u32;
- store_word(memory, addr, registers[rd]);
+ let addr = state[rs1] as usize;
+ let number: u32 = load_word(&addr);
+ state[rd] = std::cmp::max(number as i32, state[rs2] as i32) as u32;
+ store_word(addr, state[rd]);
} // amomax.w
16 => {
- let addr = registers[rs1] as usize;
- let number: u32 = load_word(&memory, addr);
- registers[rd] = std::cmp::min(number as i32, registers[rs2] as i32) as u32;
- store_word(memory, addr, registers[rd]);
+ let addr = state[rs1] as usize;
+ let number: u32 = load_word(&addr);
+ state[rd] = std::cmp::min(number as i32, state[rs2] as i32) as u32;
+ store_word(addr, state[rd]);
} // amomin.w
28 => {
- let addr = registers[rs1] as usize;
- let number: u32 = load_word(&memory, addr);
- registers[rd] = std::cmp::max(number, registers[rs2]);
- store_word(memory, addr, registers[rd]);
+ let addr = state[rs1] as usize;
+ let number: u32 = load_word(&addr);
+ state[rd] = std::cmp::max(number, state[rs2]);
+ store_word(addr, state[rd]);
} // amomaxu.w
24 => {
- let addr = registers[rs1] as usize;
- let number: u32 = load_word(&memory, addr);
- registers[rd] = std::cmp::min(number, registers[rs2]);
- store_word(memory, addr, registers[rd]);
+ let addr = state[rs1] as usize;
+ let number: u32 = load_word(&addr);
+ state[rd] = std::cmp::min(number, state[rs2]);
+ store_word(addr, state[rd]);
} // amomin.w
_ => panic!("Illegal instruction: {:x}", word),
@@ -363,7 +297,7 @@ fn handle_instruction(
let rs2 = ((word >> 20) & REGISTER_NAME_WIDTH) as usize;
let rs3 = ((word >> 27) & REGISTER_NAME_WIDTH) as usize;
- fmadd_s(f_registers, rd, rs1, rs2, rs3);
+ fmadd_s(state, rd, rs1, rs2, rs3);
}
0b1000111 => {
// todo: handle rm bit
@@ -372,7 +306,7 @@ fn handle_instruction(
let rs2 = ((word >> 20) & REGISTER_NAME_WIDTH) as usize;
let rs3 = ((word >> 27) & REGISTER_NAME_WIDTH) as usize;
- fmsub_s(f_registers, rd, rs1, rs2, rs3);
+ fmsub_s(state, rd, rs1, rs2, rs3);
}
0b1001011 => {
// todo: handle rm bit
@@ -381,7 +315,7 @@ fn handle_instruction(
let rs2 = ((word >> 20) & REGISTER_NAME_WIDTH) as usize;
let rs3 = ((word >> 27) & REGISTER_NAME_WIDTH) as usize;
- fnmsub_s(f_registers, rd, rs1, rs2, rs3);
+ fnmsub_s(state, rd, rs1, rs2, rs3);
}
0b1001111 => {
// todo: handle rm bit
@@ -390,7 +324,7 @@ fn handle_instruction(
let rs2 = ((word >> 20) & REGISTER_NAME_WIDTH) as usize;
let rs3 = ((word >> 27) & REGISTER_NAME_WIDTH) as usize;
- fnmadd_s(f_registers, rd, rs1, rs2, rs3);
+ fnmadd_s(state, rd, rs1, rs2, rs3);
}
0b1010011 => {
// todo: handle rm bit
@@ -401,36 +335,36 @@ fn handle_instruction(
let rm = (word >> 12) & 0b111;
match f5 {
- 0 => fadd_s(f_registers, rd, rs1, rs2),
- 1 => fsub_s(f_registers, rd, rs1, rs2),
- 2 => fmul_s(f_registers, rd, rs1, rs2),
- 3 => fdiv_s(f_registers, rd, rs1, rs2),
- 11 => fsqrt_s(f_registers, rd, rs1),
+ 0 => fadd_s(state, rd, rs1, rs2),
+ 1 => fsub_s(state, rd, rs1, rs2),
+ 2 => fmul_s(state, rd, rs1, rs2),
+ 3 => fdiv_s(state, rd, rs1, rs2),
+ 11 => fsqrt_s(state, rd, rs1),
4 => match rm {
- 0 => fsgnj_s(f_registers, rd, rs1, rs2),
- 1 => fsgnjn_s(f_registers, rd, rs1, rs2),
- 2 => fsgnjx_s(f_registers, rd, rs1, rs2),
+ 0 => fsgnj_s(state, rd, rs1, rs2),
+ 1 => fsgnjn_s(state, rd, rs1, rs2),
+ 2 => fsgnjx_s(state, rd, rs1, rs2),
_ => panic!("Illegal instruction: {:x}", rm),
},
5 => match rm {
- 0 => fmin_s(f_registers, rd, rs1, rs2),
- 1 => fmax_s(f_registers, rd, rs1, rs2),
+ 0 => fmin_s(state, rd, rs1, rs2),
+ 1 => fmax_s(state, rd, rs1, rs2),
_ => panic!("Illegal instruction: {:x}", rm),
},
24 => {
- fcvt_wu_s(registers, f_registers, rd, rs1);
+ fcvt_wu_s(state, rd, rs1);
}
28 => {
match rm {
- 0 => fmv_x_w(registers, f_registers, rd, rs1),
- 1 => fclass_s(registers, f_registers, rd, rs1),
+ 0 => fmv_x_w(state, rd, rs1),
+ 1 => fclass_s(state, rd, rs1),
_ => panic!("Illegal instruction: {:x}", rm),
};
}
20 => match rm {
- 0 => feq_s(registers, f_registers, rd, rs1, rs2),
- 1 => flt_s(registers, f_registers, rd, rs1, rs2),
- 2 => fle_s(registers, f_registers, rd, rs1, rs2),
+ 0 => feq_s(state, rd, rs1, rs2),
+ 1 => flt_s(state, rd, rs1, rs2),
+ 2 => fle_s(state, rd, rs1, rs2),
_ => panic!("Illegal instruction: {:x}", rm),
},
@@ -440,29 +374,21 @@ fn handle_instruction(
0b1010101 => {
let rd = ((word >> 7) & REGISTER_NAME_WIDTH) as usize;
let rs1 = ((word >> 15) & REGISTER_NAME_WIDTH) as usize;
- fcvt_w_s(registers, f_registers, rd, rs1);
+ fcvt_w_s(state, rd, rs1);
}
_ => panic!("Illegal instruction or todo: {:x}", word),
}
- *pc += 4;
+ state.pc += 4;
}
-fn release_reservations(reservations: &mut HashSet<usize>, indices: &[usize]) {
+fn release_reservations(state: &mut CpuState, indices: &[usize]) {
for index in indices {
- reservations.remove(&index);
+ state.reservations.remove(&index);
}
}
-fn acquire_reservations(reservations: &mut HashSet<usize>, indices: &[usize]) {
+fn acquire_reservations(state: &mut CpuState, indices: &[usize]) {
for index in indices {
- reservations.insert(*index);
+ state.reservations.insert(*index);
}
-}
-
-fn load_word(memory: &&mut Box<[u8]>, addr: usize) -> u32 {
- let slice = memory.get(addr..addr + 4).unwrap();
- u32::from_le_bytes(slice.try_into().unwrap())
-}
-fn store_word(memory: &mut Box<[u8]>, addr: usize, value: u32) {
- memory[addr..addr + 4].copy_from_slice(&value.to_le_bytes());
-}
+} \ No newline at end of file