summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.rs439
1 files changed, 171 insertions, 268 deletions
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],
+ &registers[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], &registers[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
+}