diff --git a/hbvm/src/main.rs b/hbvm/src/main.rs index 255384e..5f9b27f 100644 --- a/hbvm/src/main.rs +++ b/hbvm/src/main.rs @@ -18,7 +18,7 @@ fn main() -> Result<(), Box> { return Ok(()); } else { unsafe { - let mut vm = Vm::new_unchecked(&prog, TestTrapHandler); + let mut vm = Vm::<_, 0>::new_unchecked(&prog, TestTrapHandler); vm.memory.insert_test_page(); println!("Program interrupt: {:?}", vm.run()); println!("{:?}", vm.registers); diff --git a/hbvm/src/vm/mod.rs b/hbvm/src/vm/mod.rs index 0f6fa2f..6528161 100644 --- a/hbvm/src/vm/mod.rs +++ b/hbvm/src/vm/mod.rs @@ -79,7 +79,7 @@ macro_rules! cond_jump { } /// HoleyBytes Virtual Machine -pub struct Vm<'a, T> { +pub struct Vm<'a, T, const TIMER_QUOTIENT: usize> { /// Holds 256 registers /// /// Writing to register 0 is considered undefined behaviour @@ -97,9 +97,12 @@ pub struct Vm<'a, T> { /// Program program: &'a [u8], + + /// Program timer + timer: usize, } -impl<'a, T: HandleTrap> Vm<'a, T> { +impl<'a, T: HandleTrap, const TIMER_QUOTIENT: usize> Vm<'a, T, TIMER_QUOTIENT> { /// Create a new VM with program and trap handler /// /// # Safety @@ -111,6 +114,7 @@ impl<'a, T: HandleTrap> Vm<'a, T> { traph, pc: 0, program, + timer: 0, } } @@ -123,12 +127,19 @@ impl<'a, T: HandleTrap> Vm<'a, T> { /// Execute program /// /// Program can return [`VmRunError`] if a trap handling failed - pub fn run(&mut self) -> Result<(), VmRunError> { + pub fn run(&mut self) -> Result { use hbbytecode::opcode::*; loop { // Fetch instruction let Some(&opcode) = self.program.get(self.pc) - else { return Ok(()) }; + else { return Ok(VmRunOk::End) }; + + if TIMER_QUOTIENT != 0 { + self.timer += 1; + if self.timer % TIMER_QUOTIENT == 0 { + return Ok(VmRunOk::Timer); + } + } // Big match unsafe { @@ -350,3 +361,10 @@ pub enum VmRunError { /// Unhandled store access exception StoreAccessEx(u64), } + +/// Virtual machine halt ok +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum VmRunOk { + End, + Timer, +}