diff --git a/src/vm.rs b/src/vm.rs index d1f48fc..8abb406 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -17,6 +17,18 @@ pub enum UxnError { DivisionByZero, } +impl From for UxnError { + fn from(e: StackError) -> UxnError { + UxnError::StackError(e) + } +} + +impl From for UxnError { + fn from(e: MemoryError) -> UxnError { + UxnError::MemoryError(e) + } +} + #[derive(Debug)] pub struct Uxn { memory: Rc>, @@ -93,6 +105,10 @@ impl Uxn { self.memory.borrow().get1(address) } + pub fn lda2(&mut self, address: u16) -> Result { + self.memory.borrow().get2(address) + } + // Run one clock cycle (instruction) pub fn step(&mut self) -> Result<(), UxnError> { Ok(()) @@ -115,21 +131,22 @@ impl Uxn { Err(e) => return Err(UxnError::MemoryError(e)), Ok(opcode) => { // Extract flags - let sflag: bool = opcode & 0x20 != 0; - let rflag: bool = opcode & 0x40 != 0; - let kflag: bool = opcode & 0x80 != 0; + let sflag: u8 = opcode & 0x20 >> 5; + let rflag: u8 = opcode & 0x40 >> 6; + let kflag: u8 = opcode & 0x80 >> 7; let icode: u8 = opcode & 0x1F; - let wst = || if rflag { self.wst } else { self.rst }; + let wst = || if rflag == 1 { self.wst } else { self.rst }; let mut wd = 0u8; // Accumulated pop let mut widx = || { assert!(wd <= wst().idx); wst().idx - wd }; // Current index - let rst = || if rflag { self.rst } else { self.wst }; + let rst = || if rflag == 1 { self.rst } else { self.wst }; let mut rd = 0u8; // Accumulated pop let mut ridx = || rst().idx - rd; // Current index + // FIXME: Keep flag is unimplemented match (kflag, rflag, sflag, icode) { (0, 0, 0, 0x00) => { // BRK @@ -137,24 +154,24 @@ impl Uxn { } (_, _, 0, 0x00) => { // LIT1 - wst().push1(self.ld1(self.pc + 1)); + wst().push1(self.lda1(self.pc + 1)?); self.pc += 1; continue 'run; } (_, _, 1, 0x00) => { // LIT2 - wst().push2(self.ld2(self.pc + 1)); + wst().push2(self.lda2(self.pc + 1)?); self.pc += 2; continue 'run; } (_, _, 0, 0x01) => { // INC1 - let a = wst().pop1(); + let a = wst().pop1()?; wst().push1(a + 1); } (_, _, 1, 0x01) => { // INC1 - let a = wst().pop2(); + let a = wst().pop2()?; wst().push2(a + 1); } (_, _, 0, 0x02) => { @@ -167,63 +184,111 @@ impl Uxn { } (_, _, 0, 0x03) => { // NIP1 a b -- a - let keep = wst().pop1(); + let keep = wst().pop1()?; wst().pop1(); - wst().push1(keep); + wst().push1(keep)?; } (_, _, 1, 0x03) => { // NIP2 a b -- a - let keep = wst().pop12(); - wst().pop2(); - wst().push2(keep); + let keep = wst().pop2()?; + wst().pop2()?; + wst().push2(keep)?; } (_, _, 0, 0x04) => { // SWP1 - let a = wst().pop1(); - let b = wst().pop1(); - wst().push1(a); - wst().push1(b); + let a = wst().pop1()?; + let b = wst().pop1()?; + wst().push1(a)?; + wst().push1(b)?; } (_, _, 1, 0x04) => { // SWP2 - let a = wst().pop2(); - let b = wst().pop2(); - wst().push2(a); - wst().push2(b); + let a = wst().pop2()?; + let b = wst().pop2()?; + wst().push2(a)?; + wst().push2(b)?; } (_, _, 0, 0x05) => { // ROT - let a = wst().pop1(); - let b = wst().pop1(); - let c = wst().pop1(); - wst().push1(b); - wst().push1(c); - wst().push1(a); + let a = wst().pop1()?; + let b = wst().pop1()?; + let c = wst().pop1()?; + wst().push1(b)?; + wst().push1(c)?; + wst().push1(a)?; } (_, _, 1, 0x05) => { // ROT - let a = wst().pop2(); - let b = wst().pop2(); - let c = wst().pop2(); - wst().push2(b); - wst().push2(c); - wst().push2(a); + let a = wst().pop2()?; + let b = wst().pop2()?; + let c = wst().pop2()?; + wst().push2(b)?; + wst().push2(c)?; + wst().push2(a)?; } - (_, _, _, 0x06) => { - // DUP - () + (_, _, 0, 0x06) => { + // DUP2 + let a = wst().peek1()?; + wst().push1(a)?; } - (_, _, _, 0x07) => { - // OVR - () + (_, _, 1, 0x06) => { + // DUP2 + let a = wst().peek2()?; + wst().push2(a)?; } - (_, _, _, 0x08) => { - // EQ - () + (_, _, 0, 0x07) => { + // OVR1 a b -- a b a + if wst().idx < 2 { + return Err(UxnError::StackError(StackError::StackUnderflow)); + } + wst().push1(wst().get1(wst().idx - 2)?)?; } - (_, _, _, 0x09) => { - // NEQ - () + (_, _, 1, 0x07) => { + // OVR2 a b -- a b a + if wst().idx < 4 { + return Err(UxnError::StackError(StackError::StackUnderflow)); + } + wst().push2(wst().get2(wst().idx - 4)?)?; + } + (_, _, 0, 0x08) => { + // EQU1 + let a = wst().pop1()?; + let b = wst().pop1()?; + if a == b { + wst().push1(1)?; + } else { + wst().push1(0)?; + } + } + (_, _, 1, 0x08) => { + // EQU2 + let a = wst().pop2()?; + let b = wst().pop2()?; + if a == b { + wst().push1(1)?; + } else { + wst().push1(0)?; + } + } + (_, _, 0, 0x09) => { + // NEQ1 + let a = wst().pop1()?; + let b = wst().pop1()?; + if a == b { + wst().push1(0)?; + } else { + wst().push1(1)?; + } + } + (_, _, 1, 0x09) => { + // NEQ2 + let a = wst().pop2()?; + let b = wst().pop2()?; + if a == b { + wst().push1(0)?; + } else { + wst().push1(1)?; + } } (_, _, _, 0x0a) => { // GTH