diff --git a/src/vm.rs b/src/vm.rs index 75f9782..c3d4bd6 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -130,6 +130,9 @@ impl Uxn { match self.lda1(self.pc) { Err(e) => return Err(UxnError::MemoryError(e)), Ok(opcode) => { + // The value of PC is defined to be the value of the NEXT pc ala Mips + self.pc += 1; + // Extract flags let sflag: u8 = opcode & 0x20 >> 5; let rflag: u8 = opcode & 0x40 >> 6; @@ -144,7 +147,11 @@ impl Uxn { } }; - // FIXME: Keep flag is unimplemented + // Just bail out of we get a keep flag, haven't figured out an abstraction for that yet. + if kflag != 0 { + panic!("Got unsupported keep-mode instruction"); + } + match (kflag, rflag, sflag, icode) { (0, 0, 0, 0x00) => { // BRK @@ -152,39 +159,39 @@ impl Uxn { } (_, _, 0, 0x00) => { // LIT1 - wst.borrow_mut().push1(self.lda1(self.pc + 1)?); + wst.borrow_mut().push1(self.lda1(self.pc + 1)?)?; self.pc += 1; continue 'run; } (_, _, 1, 0x00) => { // LIT2 - wst.borrow_mut().push2(self.lda2(self.pc + 1)?); + wst.borrow_mut().push2(self.lda2(self.pc + 1)?)?; self.pc += 2; continue 'run; } (_, _, 0, 0x01) => { // INC1 let a = wst.borrow_mut().pop1()?; - wst.borrow_mut().push1(a + 1); + wst.borrow_mut().push1(a + 1)?; } (_, _, 1, 0x01) => { // INC1 let a = wst.borrow_mut().pop2()?; - wst.borrow_mut().push2(a + 1); + wst.borrow_mut().push2(a + 1)?; } (_, _, 0, 0x02) => { // POP1 - wst.borrow_mut().pop1(); + wst.borrow_mut().pop1()?; } (_, _, 1, 0x02) => { // POP2 - wst.borrow_mut().pop2(); + wst.borrow_mut().pop2()?; } (_, _, 0, 0x03) => { // NIP1 a b -- a let mut wst = wst.borrow_mut(); let keep = wst.pop1()?; - wst.pop1(); + wst.pop1()?; wst.push1(keep)?; } (_, _, 1, 0x03) => { @@ -352,85 +359,257 @@ impl Uxn { } (_, _, _, 0x0c) => { // JMP - () + let delta = wst.borrow_mut().pop1()? as i8; + self.pc += delta as u16; } - (_, _, _, 0x0d) => { - // JCN - () + (_, _, 0, 0x0d) => { + // JCN1 cnd8 addr8 (relative) + let delta = wst.borrow_mut().pop1()? as i8; + let cnd = wst.borrow_mut().pop1()?; + if cnd != 0 { + self.pc += delta; + } } - (_, _, _, 0x0e) => { - // JSR - () + (_, _, 2, 0x0d) => { + // JCN2 cnd8 addr16 (absolute) + let addr = wst.borrow_mut().pop2()?; + let cnd = wst.borrow_mut().pop1()?; + if cnd != 0 { + self.pc = addr; + } } - (_, _, _, 0x0f) => { - // STH - () + (_, _, 0, 0x0e) => { + // JSR1 addr8 (relative) + rst.borrow_mut().push2(self.pc); + self.pc += (wst.borrow_mut().pop1()? as i8); } - (_, _, _, 0x10) => { - // LDZ - () + (_, _, 1, 0x0e) => { + // JSR2 addr16 (absolute) + rst.borrow_mut().push2(self.pc); + self.pc = wst.borrow_mut().pop2()?; } - (_, _, _, 0x11) => { - // STZ - () + (_, _, 0, 0x0f) => { + // STH1 a + rst.borrow_mut().push1(wst.borrow_mut().pop1()?)?; } - (_, _, _, 0x12) => { - // LDR - () + (_, _, 1, 0x0f) => { + // STH2 a + rst.borrow_mut().push2(wst.borrow_mut().pop2()?)?; } - (_, _, _, 0x13) => { - // STR - () + (_, _, 0, 0x10) => { + // LDZ1 a -- b8 + let wst = wst.borrow_mut(); + let val = self.memory.borrow().get1(wst.pop1()? as u16)?; + wst.push1(val)?; } - (_, _, _, 0x14) => { - // LDA - () + (_, _, 1, 0x10) => { + // LDZ2 a -- b16 + let wst = wst.borrow_mut(); + let val = self.memory.borrow().get2(wst.pop1()? as u16)?; + wst.push2(val)?; } - (_, _, _, 0x15) => { - // STA - () + (_, _, 0, 0x11) => { + // STZ1 val addr8 -- + let wst = wst.borrow_mut(); + let addr = wst.pop1()?; + let val = wst.pop1()?; + self.memory.borrow_mut().set1(addr as u16, val); } - (_, _, _, 0x16) => { - // DEI - () + (_, _, 1, 0x11) => { + // STZ2 val16 addr8 -- + let wst = wst.borrow_mut(); + let addr = wst.pop1()?; + let val = wst.pop2()?; + self.memory.borrow_mut().set2(addr as u16, val); } - (_, _, _, 0x17) => { - // DEO - () + (_, _, 0, 0x12) => { + // LDR1 addr8 -- a8 + let wst = wst.borrow_mut(); + let delta = wst.pop1()? as i8; + let val = self.memory.borrow().get1(self.pc + delta)?; + wst.push1(val)?; } - (_, _, _, 0x18) => { - // ADD - () + (_, _, 1, 0x12) => { + // LDR2 addr8 -- a16 + let wst = wst.borrow_mut(); + let delta = wst.pop1()? as i8; + let val = self.memory.borrow().get2(self.pc + delta)?; + wst.push2(val)?; } - (_, _, _, 0x19) => { - // SUB - () + (_, _, 0, 0x13) => { + // STR1 val8 addr8 + let wst = wst.borrow_mut(); + let delta = wst.pop1()? as i8; + let val = wst.pop1()?; + self.memory.borrow_mut().set1(self.pc + delta, val); } - (_, _, _, 0x1a) => { - // MUL - () + (_, _, 1, 0x13) => { + // STR2 val16 addr8 + let wst = wst.borrow_mut(); + let delta = wst.pop1()? as i8; + let val = wst.pop2()?; + self.memory.borrow_mut().set2(self.pc + delta, val); } - (_, _, _, 0x1b) => { - // DIV - () + (_, _, 0, 0x14) => { + // LDA1 a16 -- a8 + let wst = wst.borrow_mut(); + let addr = wst.pop2()?; + let val = self.memory.borrow_mut().get1(addr)?; + wst.push1(val)?; } - (_, _, _, 0x1c) => { - // AND - () + (_, _, 1, 0x14) => { + // LDA2 a16 -- a16 + let wst = wst.borrow_mut(); + let addr = wst.pop2()?; + let val = self.memory.borrow_mut().get2(addr)?; + wst.push2(val)?; } - (_, _, _, 0x1d) => { - // OR - () + (_, _, 0, 0x15) => { + // STA1 val a16 -- + let wst = wst.borrow_mut(); + let addr = wst.pop2()?; + let val = wst.pop1()?; + self.memory.borrow_mut().set1(addr, val)?; } - (_, _, _, 0x1e) => { - // XOR - () + (_, _, 1, 0x15) => { + // STA1 val a16 -- + let wst = wst.borrow_mut(); + let addr = wst.pop2()?; + let val = wst.pop2()?; + self.memory.borrow_mut().set2(addr, val)?; } - (_, _, _, 0x1f) => { - // SFT - () + (_, _, 0, 0x16) => { + // DEI1 port8 -- a8 + let wst = wst.borrow_mut(); + let port = wst.pop1()?; + wst.push1(self.dei1(port)); + } + (_, _, 1, 0x16) => { + // DEI2 port8 -- a16 + let wst = wst.borrow_mut(); + let port = wst.pop1()?; + wst.push2(self.dei2(port)); + } + (_, _, 0, 0x17) => { + // DEO1 a8 port8 -- + let wst = wst.borrow_mut(); + let port = wst.pop1()?; + let val = wst.pop1()?; + self.deo1(port, val); + } + (_, _, 1, 0x17) => { + // DEO2 a16 port8 -- + let wst = wst.borrow_mut(); + let port = wst.pop1()?; + let val = wst.pop2()?; + self.deo2(port, val); + } + (_, _, 0, 0x18) => { + // ADD1 a b -- c + let wst = wst.borrow_mut(); + let b = wst.pop1()?; + let a = wst.pop1()?; + wst.push1(a + b)?; + } + (_, _, 1, 0x18) => { + // ADD2 a16 b16 -- c16 + let wst = wst.borrow_mut(); + let b = wst.pop2()?; + let a = wst.pop2()?; + wst.push2(a + b)?; + } + (_, _, 0, 0x19) => { + // SUB1 a b -- c + let wst = wst.borrow_mut(); + let b = wst.pop1()?; + let a = wst.pop1()?; + wst.push1(a - b)?; + } + (_, _, 1, 0x19) => { + // SUB2 a16 b16 -- c16 + let wst = wst.borrow_mut(); + let b = wst.pop2()?; + let a = wst.pop2()?; + wst.push2(a - b)?; + } + (_, _, 0, 0x1a) => { + // MUL1 a b -- c + let wst = wst.borrow_mut(); + let b = wst.pop1()?; + let a = wst.pop1()?; + wst.push1(a * b)?; + } + (_, _, 1, 0x1a) => { + // MUL2 a16 b16 -- c16 + let wst = wst.borrow_mut(); + let b = wst.pop2()?; + let a = wst.pop2()?; + wst.push2(a * b)?; + } + (_, _, 0, 0x1b) => { + // DIV1 a b -- c + let wst = wst.borrow_mut(); + let b = wst.pop1()?; + let a = wst.pop1()?; + wst.push1(a / b)?; + } + (_, _, 1, 0x1b) => { + // DIV2 a16 b16 -- c16 + let wst = wst.borrow_mut(); + let b = wst.pop2()?; + let a = wst.pop2()?; + wst.push2(a / b)?; + } + (_, _, 0, 0x1c) => { + // AND1 a8 b8 -- c8 + let wst = wst.borrow_mut(); + let b = wst.pop1()?; + let a = wst.pop1()?; + wst.push1(a & b)?; + } + (_, _, 1, 0x1c) => { + // AND2 a16 b16 -- c16 + let wst = wst.borrow_mut(); + let b = wst.pop2()?; + let a = wst.pop2()?; + wst.push2(a & b)?; + } + (_, _, 0, 0x1d) => { + // OR1 a8 b8 -- c8 + let wst = wst.borrow_mut(); + let b = wst.pop1()?; + let a = wst.pop1()?; + wst.push1(a | b)?; + } + (_, _, 1, 0x1d) => { + // OR2 a16 b16 -- c16 + let wst = wst.borrow_mut(); + let b = wst.pop2()?; + let a = wst.pop2()?; + wst.push2(a | b)?; + } + (_, _, 0, 0x1e) => { + // XOR1 a8 b8 -- c8 + let wst = wst.borrow_mut(); + let b = wst.pop1()?; + let a = wst.pop1()?; + wst.push1(a ^ b)?; + } + (_, _, 1, 0x1e) => { + // XOR2 a16 b16 -- c16 + let wst = wst.borrow_mut(); + let b = wst.pop2()?; + let a = wst.pop2()?; + wst.push2(a ^ b)?; + } + (_, _, 0, 0x1f) => { + // SFT1 + unimplemented!() + } + (_, _, 1, 0x1f) => { + // SFT2 + unimplemented!() } - _ => unreachable!(), } } }