use alloc::boxed::Box;
use core::marker::PhantomData;
use crate::isa::{Instr, InstructionSet, ReservedOp};
use crate::program::LibSite;
use crate::reg::CoreRegs;
use crate::Program;
#[derive(Getters, Debug, Default)]
pub struct Vm<Isa = Instr<ReservedOp>>
where
Isa: InstructionSet,
{
registers: Box<CoreRegs>,
phantom: PhantomData<Isa>,
}
impl<Isa> Vm<Isa>
where
Isa: InstructionSet,
{
pub fn new() -> Self { Self { registers: Box::default(), phantom: Default::default() } }
pub fn run(&mut self, program: &Program<Isa>) -> bool {
self.call(program, program.entrypoint())
}
pub fn call(&mut self, program: &Program<Isa>, method: LibSite) -> bool {
let mut call = Some(method);
while let Some(ref mut site) = call {
if let Some(lib) = program.lib(site.lib) {
call = lib.exec::<Isa>(site.pos, &mut self.registers);
} else if let Some(pos) = site.pos.checked_add(1) {
site.pos = pos;
} else {
call = None;
};
}
self.registers.st0
}
}