diff --git a/hbvm/src/engine/mod.rs b/hbvm/src/engine/mod.rs index 23a11bf..e126928 100644 --- a/hbvm/src/engine/mod.rs +++ b/hbvm/src/engine/mod.rs @@ -2,6 +2,8 @@ pub mod call_stack; pub mod config; pub mod enviroment_calls; pub mod regs; +#[cfg(test)] +pub mod tests; use { self::call_stack::CallStack, @@ -66,7 +68,7 @@ pub struct Engine { pub last_timer_count: u32, pub timer_callback: Option u32>, pub memory: memory::Memory, - pub enviroment_call_table: [EnviromentCall; 256], + pub enviroment_call_table: [Option; 256], pub call_stack: CallStack, } use crate::engine::enviroment_calls::EnviromentCall; @@ -87,7 +89,7 @@ impl Engine { let _ = mem.set_addr8(addr as u64, byte); } trace!("{:?}", mem.read_addr8(0)); - + let ecall_table: [Option; 256] = [None; 256]; Self { index: 0, program, @@ -95,7 +97,7 @@ impl Engine { config: EngineConfig::default(), last_timer_count: 0, timer_callback: None, - enviroment_call_table: [empty_enviroment_call; 256], + enviroment_call_table: ecall_table, memory: mem, call_stack: Vec::new(), } @@ -187,6 +189,9 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}", } pub fn run(&mut self) -> Result { use {HaltStatus::*, RuntimeErrors::*}; + if self.program.len() == 0 { + return Ok(Halted); + } loop { // Break out of the loop if self.index + 1 == self.program.len() { @@ -425,7 +430,7 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}", let addr = usize::from_be_bytes(addr_array); if addr > self.program.len() { - panic!("Invalid jump address {}", addr) + return Err(InvalidJumpAddress(addr as u64)); } else { let call = FnCall { ret: self.index }; self.call_stack.push(call); @@ -434,7 +439,6 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}", trace!("Jumping to {}", addr); self.dump(); - // panic!(); } } @@ -452,9 +456,8 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}", self.index += 2; } - _op_pair => { - // println!("OP Pair {}", op_pair.0); - self.index += 1; + op_pair => { + panic!("OP Pair {} - {}", op_pair.0, op_pair.1); } } @@ -465,6 +468,7 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}", if (ret - self.last_timer_count) >= self.config.quantum { return Ok(Running); } + self.last_timer_count = ret; } } Ok(Halted) diff --git a/hbvm/src/engine/tests/mod.rs b/hbvm/src/engine/tests/mod.rs new file mode 100644 index 0000000..6e9aaf2 --- /dev/null +++ b/hbvm/src/engine/tests/mod.rs @@ -0,0 +1,42 @@ +use { + super::Engine, + crate::{HaltStatus, RuntimeErrors}, + alloc::vec, +}; + +#[test] +fn empty_program() { + let prog = vec![]; + let mut eng = Engine::new(prog); + let ret = eng.run(); + assert_eq!(ret, Ok(HaltStatus::Halted)); +} + +#[test] +fn max_quantum_reached() { + let prog = vec![0, 0, 0, 0]; + let mut eng = Engine::new(prog); + eng.set_timer_callback(|| { + return 1; + }); + eng.config.quantum = 1; + let ret = eng.run(); + assert_eq!(ret, Ok(HaltStatus::Running)); +} + +#[test] +fn jump_out_of_bounds() { + use crate::engine::Operations::JUMP; + let prog = vec![JUMP as u8, 0, 0, 0, 0, 0, 0, 1, 0]; + let mut eng = Engine::new(prog); + let ret = eng.run(); + assert_eq!(ret, Err(RuntimeErrors::InvalidJumpAddress(256))); +} + +#[test] +fn invalid_system_call() { + let prog = vec![255, 0]; + let mut eng = Engine::new(prog); + let ret = eng.run(); + // assert_eq!(ret, ); +} diff --git a/hbvm/src/lib.rs b/hbvm/src/lib.rs index 1b042b0..705c25c 100644 --- a/hbvm/src/lib.rs +++ b/hbvm/src/lib.rs @@ -5,15 +5,17 @@ pub mod bytecode; pub mod engine; pub mod memory; -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub enum RuntimeErrors { InvalidOpcode(u8), RegisterTooSmall, HostError(u64), PageNotMapped(u64), + InvalidJumpAddress(u64), } // If you solve the halting problem feel free to remove this +#[derive(PartialEq, Debug)] pub enum HaltStatus { Halted, Running, diff --git a/hbvm/src/main.rs b/hbvm/src/main.rs index e84a17e..3c38426 100644 --- a/hbvm/src/main.rs +++ b/hbvm/src/main.rs @@ -1,4 +1,4 @@ -use holey_bytes::{ +use hbvm::{ bytecode::ops::{Operations::*, RWSubTypes::*, SubTypes::*}, engine::Engine, RuntimeErrors, @@ -8,7 +8,7 @@ fn main() -> Result<(), RuntimeErrors> { #[rustfmt::skip] let prog: Vec = vec![ NOP as u8, NOP as u8, - 10, 10, + 255, 10, ADD as u8, EightBit as u8, 100, 20, 0xA7, ADD as u8, EightBit as u8, 1, 0, 0xB0, @@ -17,11 +17,11 @@ fn main() -> Result<(), RuntimeErrors> { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0xD0, SUB as u8, EightBit as u8, 255, 0, 0xA7, + DIV as u8, EightBit as u8, 12, 5, 0xA8, ADD as u8, Register8 as u8, 0xA7, 0xB0, 0xA7, LOAD as u8, AddrToReg as u8, 0, 0, 0, 0, 0, 0, 0, 2, 0xA0, - // JUMP as u8, 0, 0, 0, 0, 0, 0, 0, 0, JUMP as u8, 0, 0, 0, 0, 0, 0, 0, 0, ];