diff options
| author | Nathan Lee <me@nwlee.tech> | 2026-06-03 20:17:09 -0500 |
|---|---|---|
| committer | Nathan Lee <me@nwlee.tech> | 2026-06-03 20:17:09 -0500 |
| commit | 7febe921cfa155dfc63454ec29fb4db8999afdd0 (patch) | |
| tree | dcbe6b0efcffa2ecb26346b94b587fd7a09039d1 | |
| parent | af92f678bcd80e365411c2f5ffae94e359e28e82 (diff) | |
refactor `handle_instruction` and make memory exist
| -rwxr-xr-x | hi | bin | 0 -> 6384 bytes | |||
| -rw-r--r-- | src/main.rs | 439 |
2 files changed, 171 insertions, 268 deletions
| Binary files differ diff --git a/src/main.rs b/src/main.rs index 2af20ca..77685a4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,8 @@ +use elf::ElfBytes; +use elf::endian::AnyEndian; use std::io; use std::io::Write; -use elf::endian::AnyEndian; -use elf::ElfBytes; +use std::sync::{LazyLock, Mutex}; const ABI: [&str; 32] = [ "x0", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", @@ -9,8 +10,11 @@ const ABI: [&str; 32] = [ "t6", ]; +static MEMORY: LazyLock<Mutex<[u8; 64 * 1024 * 1024]>> = + LazyLock::new(|| Mutex::new([0u8; 64 * 1024 * 1024])); + fn main() { - let path = std::path::PathBuf::from("/home/theavgeekbee/projects/webos/sample/hi"); + let path = std::path::PathBuf::from("hi"); let f_dat = std::fs::read(path).expect("Unable to read file"); @@ -20,12 +24,19 @@ fn main() { .section_headers_with_strtab() .expect("Unable to get section headers"); - let memory: &mut [u8;0xFFFF] = &mut [0; 0xFFFF]; let dup = f_dat.clone(); - for i in 0..dup.len() { - memory[i] = dup[i]; + + // 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 pc: u32 = 0; + let str_tab = stab.expect("Cannot read strtab"); if let Some(headers) = sh { for header in headers { @@ -37,282 +48,174 @@ fn main() { .section_data(&header) .expect("Unable to get section data"); - handle_instruction(sh_data, header.sh_addr as u32, memory); + pc = header.sh_addr as u32; } } } -} - -fn handle_instruction(sh_data: &[u8], instruction: u32, memory: &[u8;0xFFFF]) { - let mut registers: [u32;32] = [0;32]; - let mut pc = instruction; - for i in (0..sh_data.len()).step_by(4) { - let word = u32::from_le_bytes([sh_data[i], sh_data[i + 1], sh_data[i + 2], sh_data[i + 3]]); - let opcode = word & 0x7f; - match opcode { - 0b0110011 => { - let f7 = word >> 25; - let f3 = (word >> 12) & 0b111; - - let rs2 = ((word >> 20) & 0b11111) as usize; - let rs1 = ((word >> 15) & 0b11111) as usize; - let rd = ((word >> 7) & 0b11111) as usize; + loop { + let mut memory = MEMORY.lock().expect("Unable to get memory"); + handle_instruction(&mut *memory, &mut registers, pc); + pc += 4; + } +} - match (f7 << 3) | f3 { - 0 => { - println!( - "add {} {} {}", - ABI[rd], ABI[rs1], ABI[rs2] - ); - registers[rd] = registers[rs1] + registers[rs2]; - }, - 256 => { - println!( - "sub {} {} {}", - ABI[rd], ABI[rs1], ABI[rs2] - ); - registers[rd] = registers[rs1] - registers[rs2]; - }, - 4 => { - println!( - "xor {} {} {}", - ABI[rd], ABI[rs1], ABI[rs2] - ); - registers[rd] = registers[rs1] ^ registers[rs2]; - }, - 6 => { - println!( - "or {} {} {}", - ABI[rd], ABI[rs1], ABI[rs2] - ); - registers[rd] = registers[rs1] | registers[rs2]; - }, - 7 => { - println!( - "and {} {} {}", - ABI[rd], ABI[rs1], ABI[rs2] - ); - registers[rd] = registers[rs1] & registers[rs2]; - }, - 1 => { - println!( - "sll {} {} {}", - ABI[rd], ABI[rs1], ABI[rs2] - ); - registers[rd] = registers[rs1] << registers[rs2]; - }, - 5 => { - println!( - "srl {} {} {}", - ABI[rd], ABI[rs1], ABI[rs2] - ); - registers[rd] = registers[rs1] >> registers[rs2]; - }, - 261 => { - println!( - "sra {} {} {}", - ABI[rd], ABI[rs1], ABI[rs2] - ); - registers[rd] = ((registers[rs1] as i32) >> registers[rs2]) as u32; - }, - 2 => { - println!( - "slt {} {} {}", - ABI[rd], ABI[rs1], ABI[rs2] - ); - 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}; - }, - 3 => { - println!( - "sltu {} {} {}", - ABI[rd], ABI[rs1], ABI[rs2] - ); - registers[rd] = if registers[rs1] < registers[rs2] {1} else {0}; - }, - _ => println!("Invalid opcode"), +fn handle_instruction(memory: &mut [u8], registers: &mut [u32], pc: u32) { + 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], + ]); + let opcode = word & 0x7f; + match opcode { + 0b0110011 => { + let f7 = word >> 25; + let f3 = (word >> 12) & 0b111; + + let rs2 = ((word >> 20) & 0b11111) as usize; + let rs1 = ((word >> 15) & 0b11111) as usize; + 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 + 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 + 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 + _ => panic!("Illegal instruction: {:x}", word), } - 0b0010011 => { - let imm = ((word as i32) >> 20) as u32; - let f3 = (word >> 12) & 0b111; - - let rs1 = ((word >> 15) & 0b11111) as usize; - let rd = ((word >> 7) & 0b11111) as usize; - - match f3 { - 0 => { - println!("addi {} {} {}", ABI[rd], ABI[rs1], imm); - registers[rd] = registers[rs1] + imm; - }, - 4 => { - println!("xori {} {} {}", ABI[rd], ABI[rs1], imm); - registers[rd] = registers[rs1] ^ imm; - }, - 6 => { - println!("ori {} {} {}", ABI[rd], ABI[rs1], imm); - registers[rd] = registers[rs1] | imm; - }, - 7 => { - println!("andi {} {} {}", ABI[rd], ABI[rs1], imm); - registers[rd] = registers[rs1] & imm; - }, - 1 => { - if (word >> 5) != 0 { - todo!("Illegal instruction (trap)"); - } - println!( - "slli {} {} {}", - ABI[rd], - ABI[rs1], - imm & 0b11111 - ); - registers[rd] = registers[rs1] << (imm & 0b11111); - }, - 5 => { - if (word >> 5) != 0 { - todo!("Illegal instruction (trap)"); - } - if (imm >> 5) & 0b1111111 == 0 { - println!( - "srli {} {} {}", - ABI[rd], - ABI[rs1], - imm & 0b11111 - ); - registers[rd] = registers[rs1] >> (imm & 0b11111); - } else { - println!( - "srai {} {} {}", - ABI[rd], - ABI[rs1], - imm & 0b11111 - ); - registers[rd] = ((registers[rs1] >> (imm & 0b11111)) as i32) as u32; - - } + } + 0b0010011 => { + let imm = ((word as i32) >> 20) as u32; + let f3 = (word >> 12) & 0b111; + + let rs1 = ((word >> 15) & 0b11111) as usize; + let rd = ((word >> 7) & 0b11111) as usize; + + match f3 { + 0 => registers[rd] = registers[rs1] + 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 { + panic!("Illegal instruction: {:x}", word); + } + registers[rd] = registers[rs1] << (imm & 0b11111); // slli + } + 5 => { + if (word >> 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 } - 2 => { - println!("slti {} {} {}", ABI[rd], ABI[rs1], imm); - registers[rd] = if (registers[rs1] as i32) < (imm as i32) {1} else {0}; - }, - 3 => { - println!("sltiu {} {} {}", ABI[rd], ABI[rs1], imm); - registers[rd] = if registers[rs1] < imm {1} else {0}; - }, - _ => println!("Invalid opcode"), } + 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 + _ => panic!("Illegal instruction: {:x}", word), } - 0b0000011 => { - let imm = word >> 20; - let f3 = (word >> 12) & 0b111; - - let rs1 = ((word >> 15) & 0b11111) as usize; - let rd = ((word >> 7) & 0b11111) as usize; - - match f3 { - 0 => { - println!( - "lb {} {} {}", - ABI[rd], - ABI[rs1], - imm & 0xFF - ); - let byte: u8 = memory[(registers[rs1] + imm) as usize]; - registers[rd] = (byte as i8) as u32; + } + 0b0000011 => { + let imm = word >> 20; + let f3 = (word >> 12) & 0b111; - }, - 1 => { - println!( - "lh {} {} {}", - ABI[rd], - ABI[rs1], - imm & 0xFFFF - ); - 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; - }, - 2 => { - println!( - "lw {} {} {}", - ABI[rd], - ABI[rs1], - imm & 0xFFFFFF - ); - 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 - }); - registers[rd] = number; - }, - 4 => { - println!( - "lbu {} {} {}", - ABI[rd], - ABI[rs1], - imm & 0xFF - ); + let rs1 = ((word >> 15) & 0b11111) as usize; + let rd = ((word >> 7) & 0b11111) as usize; - }, - 5 => println!( - "lhu {} {} {}", - ABI[rd], - ABI[rs1], - imm & 0xFFFF - ), - _ => println!("Invalid opcode"), + 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 = slice.iter().fold(0u32, |acc, &n| (acc << 8) | n as u32); + registers[rd] = number; // lw } + 4 => { + println!("lbu {} {} {}", ABI[rd], ABI[rs1], imm & 0xFF); + } + 5 => println!("lhu {} {} {}", ABI[rd], ABI[rs1], imm & 0xFFFF), + _ => panic!("Illegal instruction: {:x}", word), } - 0b0100011 => { - 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; - - match f3 { - 0 => println!("sb {} {} {}", ABI[rs1], ABI[rs2], imm & 0xFF), - 1 => println!("sh {} {} {}", ABI[rs1], ABI[rs2], imm & 0xFFFF), - 2 => println!("sw {} {} {}", ABI[rs1], ABI[rs2], imm & 0xFFFFFF), - _ => println!("Invalid opcode") - }; - - // todo: in real kernel use memory pages - }, - 0b1100011 => println!("B-type"), - 0b1101111 => println!("J-type"), - 0b1100111 => println!("jalr"), - 0b0110111 => { - let imm = word >> 12; - let rd = ((word >> 7) & 0b11111) as usize; - println!("lui {} {}", rd, imm as i32); - registers[rd] = imm << 12; - }, - 0b0010111 => { - let imm = word >> 12; - let rd = (word >> 7) & 0b11111; - println!("auipc {} {}", ABI[rd as usize], imm); - registers[rd as usize] = pc + (imm << 12); + } + 0b0100011 => { + 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; + + match f3 { + 0 => println!("sb {} {} {}", ABI[rs1], ABI[rs2], imm & 0xFF), + 1 => println!("sh {} {} {}", ABI[rs1], ABI[rs2], imm & 0xFFFF), + 2 => println!("sw {} {} {}", ABI[rs1], ABI[rs2], imm & 0xFFFFFF), + _ => panic!("Illegal instruction: {:x}", word), + }; + } + 0b1100011 => println!("B-type (todo)"), + 0b1101111 => println!("J-type (todo)"), + 0b1100111 => println!("jalr"), + 0b0110111 => { + let imm = word >> 12; + let rd = ((word >> 7) & 0b11111) as usize; + println!("lui {} {}", rd, imm as i32); + registers[rd] = imm << 12; + } + 0b0010111 => { + let imm = word >> 12; + let rd = (word >> 7) & 0b11111; + registers[rd as usize] = pc + (imm << 12); // auipc + } + 0b1110011 => { + // ecall + eprintln!( + "TRAP! syscall {} with gp registers {:?} calling instruction {:x}", + registers[17], + ®isters[10..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(); } - 0b1110011 => { - println!("ecall"); - eprintln!("TRAP! syscall {} with gp registers {:?} calling instruction {:x}", registers[17], ®isters[10..17], pc); - if registers[17] == 0 { // sys_write - 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(); - } - }, - _ => println!("Invalid opcode"), } - - pc += 4; + _ => panic!("Illegal instruction or todo: {:x}", word), } -}
\ No newline at end of file +} |
