diff --git a/src/lib.rs b/src/lib.rs index 30bf3b6..4a0a829 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ use std::rc::Rc; use std::*; use memory::MemoryError; +use stack::StackError; use crate::memory::{Memory, TrivialMemory}; use crate::stack::Stack; @@ -98,6 +99,15 @@ impl Device for SystemDevice { } } +pub enum UxnError { + StackError(StackError), + MemoryError(MemoryError), + ExecutionLimit(u16), + ArithmeticOverflow, + ArithmeticUnderflow, + DivisionByZero, +} + #[derive(Debug)] pub struct Uxn { memory: Rc>, @@ -169,4 +179,99 @@ impl Uxn { self.memory.borrow_mut().set2(address, val)?; Ok(()) } + + pub fn lda1(&mut self, address: u16) -> Result { + self.memory.borrow().get1(address) + } + + // Run one clock cycle (instruction) + pub fn step(&mut self) -> Result<(), UxnError> { + Ok(()) + } + + pub fn run(&mut self, limit: u16) -> Result<(), UxnError> { + let mut executed = 0; + loop { + if executed == limit { + return Err(UxnError::ExecutionLimit(executed)); + } + if self.is_halted() { + break; + } + match self.lda1(self.pc) { + Err(e) => return Err(UxnError::MemoryError(e)), + Ok(0) => break, + Ok(opcode) => { + // Extract flags + let sflag: bool = opcode & 0x20 != 0; + let rflag: bool = opcode & 0x40 != 0; + let kflag: bool = opcode & 0x80 != 0; + + match opcode & 0x1F { + 0x00 => { + // LIT1 + () + } + 0x01 => { + // INC1 + () + } + 0x02 => { + // POP1 + () + } + 0x03 => { + // NIP1 + () + } + 0x04 => { + // SWP1 + () + } + 0x05 => { + // ROT1 + () + } + 0x06 => { + // DUP1 + () + } + 0x07 => { + // OVR1 + } + 0x08 => { + // EQ1 + () + } + 0x09 => { + // NEQ1 + () + } + 0x0a => { + // GTH1 + () + } + 0x0b => { + // LTH1 + () + } + 0x0c => { + // JMP1 + } + 0x0d => { + // JCN1 + } + 0x0e => { + // JSR1 + } + + _ => (), + } + } + } + + executed += 1; + } + Ok(()) + } }