Tighten all this up using helpers

This commit is contained in:
Reid 'arrdem' McKenzie 2022-12-22 23:46:19 -07:00
parent 802a369a8e
commit b7df86ce2a

541
src/vm.rs
View file

@ -139,6 +139,7 @@ impl Uxn {
let kflag: u8 = opcode & 0x80 >> 7; let kflag: u8 = opcode & 0x80 >> 7;
let icode: u8 = opcode & 0x1F; let icode: u8 = opcode & 0x1F;
// Swizzle the stacks as needed
let [wst, rst] = { let [wst, rst] = {
if rflag == 0 { if rflag == 0 {
[self.wst.clone(), self.rst.clone()] [self.wst.clone(), self.rst.clone()]
@ -147,6 +148,39 @@ impl Uxn {
} }
}; };
// Some procedural abstractions over load/store sizes
let pop = |stack: Rc<RefCell<dyn Stack>>| -> Result<u16, StackError> {
if sflag == 1 {
stack.borrow_mut().pop2()
} else {
Ok(stack.borrow_mut().pop1()? as u16)
}
};
let push = |stack: Rc<RefCell<dyn Stack>>, val: u16| {
if sflag == 1 {
stack.borrow_mut().push2(val)
} else {
stack.borrow_mut().push1(val as u8)
}
};
let load = |addr: u16| -> Result<u16, MemoryError> {
if sflag == 1 {
self.memory.borrow_mut().get2(addr)
} else {
Ok(self.memory.borrow_mut().get1(addr)? as u16)
}
};
let store = |addr: u16, value: u16| {
if sflag == 1 {
self.memory.borrow_mut().set2(addr, value)
} else {
self.memory.borrow_mut().set1(addr, value as u8)
}
};
// Just bail out of we get a keep flag, haven't figured out an abstraction for that yet. // Just bail out of we get a keep flag, haven't figured out an abstraction for that yet.
if kflag != 0 { if kflag != 0 {
panic!("Got unsupported keep-mode instruction"); panic!("Got unsupported keep-mode instruction");
@ -159,214 +193,93 @@ impl Uxn {
} }
(_, _, 0, 0x00) => { (_, _, 0, 0x00) => {
// LIT1 // LIT1
wst.borrow_mut().push1(self.lda1(self.pc + 1)?)?; wst.borrow_mut().push1(self.lda1(self.pc)?)?;
self.pc += 1; self.pc += 1;
continue 'run; continue 'run;
} }
(_, _, 1, 0x00) => { (_, _, 1, 0x00) => {
// LIT2 // LIT2
wst.borrow_mut().push2(self.lda2(self.pc + 1)?)?; wst.borrow_mut().push2(self.lda2(self.pc)?)?;
self.pc += 2; self.pc += 2;
continue 'run; continue 'run;
} }
(_, _, 0, 0x01) => { (_, _, _, 0x01) => {
// INC1 // INC
let a = wst.borrow_mut().pop1()?; push(wst.clone(), pop(wst.clone())? + 1)?;
wst.borrow_mut().push1(a + 1)?;
} }
(_, _, 1, 0x01) => { (_, _, _, 0x02) => {
// INC1 // POP
let a = wst.borrow_mut().pop2()?; pop(wst)?;
wst.borrow_mut().push2(a + 1)?;
} }
(_, _, 0, 0x02) => { (_, _, _, 0x03) => {
// POP1 // NIP a b -- a
wst.borrow_mut().pop1()?; let keep = pop(wst.clone())?;
pop(wst.clone())?;
push(wst.clone(), keep)?;
} }
(_, _, 1, 0x02) => { (_, _, _, 0x04) => {
// POP2 // SWP
wst.borrow_mut().pop2()?; let a = pop(wst.clone())?;
let b = pop(wst.clone())?;
push(wst.clone(), b)?;
push(wst.clone(), a)?;
} }
(_, _, 0, 0x03) => { (_, _, _, 0x05) => {
// NIP1 a b -- a // ROT
let mut wst = wst.borrow_mut(); let a = pop(wst.clone())?;
let keep = wst.pop1()?; let b = pop(wst.clone())?;
wst.pop1()?; let c = pop(wst.clone())?;
wst.push1(keep)?; push(wst.clone(), b)?;
push(wst.clone(), c)?;
push(wst.clone(), a)?;
} }
(_, _, 1, 0x03) => { (_, _, _, 0x06) => {
// NIP2 a b -- a // DUP
let mut wst = wst.borrow_mut(); let a = pop(wst.clone())?;
let keep = wst.pop2()?; push(wst.clone(), a)?;
wst.pop2()?; push(wst.clone(), a)?;
wst.push2(keep)?;
} }
(_, _, 0, 0x04) => { (_, _, _, 0x07) => {
// SWP1 // OVR a b -- a b a
let mut wst = wst.borrow_mut(); let b = pop(wst.clone())?;
let a = wst.pop1()?; let a = pop(wst.clone())?;
let b = wst.pop1()?; push(wst.clone(), a)?;
wst.push1(a)?; push(wst.clone(), b)?;
wst.push1(b)?; push(wst.clone(), a)?;
} }
(_, _, 1, 0x04) => { (_, _, _, 0x08) => {
// SWP2 // EQU
let mut wst = wst.borrow_mut(); let b = pop(wst.clone())?;
let a = wst.pop2()?; let a = pop(wst.clone())?;
let b = wst.pop2()?; wst.borrow_mut().push1(if a == b { 1 } else { 0 })?;
wst.push2(a)?;
wst.push2(b)?;
} }
(_, _, 0, 0x05) => { (_, _, _, 0x09) => {
// ROT1 // NEQ
let mut wst = wst.borrow_mut(); let b = pop(wst.clone())?;
let a = wst.pop1()?; let a = pop(wst.clone())?;
let b = wst.pop1()?; wst.borrow_mut().push1(if a == b { 0 } else { 1 })?;
let c = wst.pop1()?;
wst.push1(b)?;
wst.push1(c)?;
wst.push1(a)?;
} }
(_, _, 1, 0x05) => { (_, _, _, 0x0a) => {
// ROT2 // GTH a b
let mut wst = wst.borrow_mut(); let b = pop(wst.clone())?;
let a = wst.pop2()?; let a = pop(wst.clone())?;
let b = wst.pop2()?; wst.borrow_mut().push1(if a > b { 1 } else { 0 })?;
let c = wst.pop2()?;
wst.push2(b)?;
wst.push2(c)?;
wst.push2(a)?;
} }
(_, _, 0, 0x06) => { (_, _, _, 0x0b) => {
// DUP2 // LTH a b
let mut wst = wst.borrow_mut(); let b = pop(wst.clone())?;
let a = wst.peek1()?; let a = pop(wst.clone())?;
wst.push1(a)?; wst.borrow_mut().push1(if a < b { 1 } else { 0 })?;
}
(_, _, 1, 0x06) => {
// DUP2
let mut wst = wst.borrow_mut();
let a = wst.peek2()?;
wst.push2(a)?;
}
(_, _, 0, 0x07) => {
// OVR1 a b -- a b a
let mut wst = wst.borrow_mut();
if wst.idx() < 2 {
return Err(UxnError::StackError(StackError::StackUnderflow));
}
let i = wst.idx() - 2;
let v = wst.get1(i)?;
wst.push1(v)?;
}
(_, _, 1, 0x07) => {
// OVR2 a b -- a b a
let mut wst = wst.borrow_mut();
if wst.idx() < 4 {
return Err(UxnError::StackError(StackError::StackUnderflow));
}
let i = wst.idx() - 4;
let v = wst.get2(i)?;
wst.push2(v)?;
}
(_, _, 0, 0x08) => {
// EQU1
let mut wst = wst.borrow_mut();
let a = wst.pop1()?;
let b = wst.pop1()?;
if a == b {
wst.push1(1)?;
} else {
wst.push1(0)?;
}
}
(_, _, 1, 0x08) => {
// EQU2
let mut wst = wst.borrow_mut();
let a = wst.pop2()?;
let b = wst.pop2()?;
if a == b {
wst.push1(1)?;
} else {
wst.push1(0)?;
}
}
(_, _, 0, 0x09) => {
// NEQ1
let mut wst = wst.borrow_mut();
let b = wst.pop1()?;
let a = wst.pop1()?;
if a == b {
wst.push1(0)?;
} else {
wst.push1(1)?;
}
}
(_, _, 1, 0x09) => {
// NEQ2
let mut wst = wst.borrow_mut();
let b = wst.pop2()?;
let a = wst.pop2()?;
if a == b {
wst.push1(0)?;
} else {
wst.push1(1)?;
}
}
(_, _, 0, 0x0a) => {
// GTH1 a b
let mut wst = wst.borrow_mut();
let b = wst.pop1()?;
let a = wst.pop1()?;
if a > b {
wst.push1(0)?;
} else {
wst.push1(1)?;
}
}
(_, _, 1, 0x0a) => {
// GTH1 a b
let mut wst = wst.borrow_mut();
let b = wst.pop2()?;
let a = wst.pop2()?;
if a > b {
wst.push1(0)?;
} else {
wst.push1(1)?;
}
}
(_, _, 0, 0x0b) => {
// LTH1 a b
let mut wst = wst.borrow_mut();
let b = wst.pop1()?;
let a = wst.pop1()?;
if a < b {
wst.push1(0)?;
} else {
wst.push1(1)?;
}
}
(_, _, 1, 0x0b) => {
// LTH2 a b
let mut wst = wst.borrow_mut();
let b = wst.pop2()?;
let a = wst.pop2()?;
if a < b {
wst.push1(0)?;
} else {
wst.push1(1)?;
}
} }
(_, _, _, 0x0c) => { (_, _, _, 0x0c) => {
// JMP // JMP
let delta = wst.borrow_mut().pop1()? as i8; let delta = wst.borrow_mut().pop1()? as i8;
self.pc += delta as u16; self.pc = self.pc.wrapping_add(delta as u16);
} }
(_, _, 0, 0x0d) => { (_, _, 0, 0x0d) => {
// JCN1 cnd8 addr8 (relative) // JCN1 cnd8 addr8 (relative)
let delta = wst.borrow_mut().pop1()? as i8; let delta = wst.borrow_mut().pop1()? as i8;
let cnd = wst.borrow_mut().pop1()?; let cnd = wst.borrow_mut().pop1()?;
let delta = wst.borrow_mut().pop1()? as i8;
if cnd != 0 { if cnd != 0 {
self.pc = self.pc.wrapping_add(delta as u16); self.pc = self.pc.wrapping_add(delta as u16);
} }
@ -381,116 +294,59 @@ impl Uxn {
} }
(_, _, 0, 0x0e) => { (_, _, 0, 0x0e) => {
// JSR1 addr8 (relative) // JSR1 addr8 (relative)
rst.borrow_mut().push2(self.pc); rst.borrow_mut().push2(self.pc)?;
let delta = wst.borrow_mut().pop1()? as i8; let delta = wst.borrow_mut().pop1()? as i8;
self.pc = self.pc.wrapping_add(delta as u16); self.pc = self.pc.wrapping_add(delta as u16);
} }
(_, _, 1, 0x0e) => { (_, _, 1, 0x0e) => {
// JSR2 addr16 (absolute) // JSR2 addr16 (absolute)
rst.borrow_mut().push2(self.pc); rst.borrow_mut().push2(self.pc)?;
self.pc = wst.borrow_mut().pop2()?; self.pc = wst.borrow_mut().pop2()?;
} }
(_, _, 0, 0x0f) => { (_, _, _, 0x0f) => {
// STH1 a // STH a
rst.borrow_mut().push1(wst.borrow_mut().pop1()?)?; push(rst, pop(wst)?)?;
} }
(_, _, 1, 0x0f) => { (_, _, _, 0x10) => {
// STH2 a // LDZ a -- b8
rst.borrow_mut().push2(wst.borrow_mut().pop2()?)?; push(wst.clone(), load(wst.borrow_mut().pop1()? as u16)?)?;
} }
(_, _, 0, 0x10) => { (_, _, _, 0x11) => {
// LDZ1 a -- b8 // STZ val addr8 --
let mut wst = wst.borrow_mut(); let addr = wst.borrow_mut().pop1()? as u16;
let val = self.memory.borrow().get1(wst.pop1()? as u16)?; store(addr, pop(wst.clone())?)?;
wst.push1(val)?;
} }
(_, _, 1, 0x10) => { (_, _, _, 0x12) => {
// LDZ2 a -- b16 // LDR addr8 -- a8
let mut wst = wst.borrow_mut(); let delta = wst.borrow_mut().pop1()? as i8;
let val = self.memory.borrow().get2(wst.pop1()? as u16)?; push(wst.clone(), load(self.pc.wrapping_add(delta as u16))?)?;
wst.push2(val)?;
} }
(_, _, 0, 0x11) => { (_, _, _, 0x13) => {
// STZ1 val addr8 -- // STR val8 addr8
let mut wst = wst.borrow_mut(); let delta = wst.borrow_mut().pop1()?;
let addr = wst.pop1()?; store(self.pc.wrapping_add(delta as u16), pop(wst.clone())?)?;
let val = wst.pop1()?;
self.memory.borrow_mut().set1(addr as u16, val);
} }
(_, _, 1, 0x11) => { (_, _, _, 0x14) => {
// STZ2 val16 addr8 -- // LDA a16
let mut wst = wst.borrow_mut(); let addr = wst.borrow_mut().pop2()?;
let addr = wst.pop1()?; push(wst.clone(), load(addr)?)?;
let val = wst.pop2()?;
self.memory.borrow_mut().set2(addr as u16, val);
} }
(_, _, 0, 0x12) => { (_, _, _, 0x15) => {
// LDR1 addr8 -- a8 // STA val a16 --
let mut wst = wst.borrow_mut(); let addr = wst.borrow_mut().pop2()?;
let delta = wst.pop1()? as i8; store(addr, pop(wst.clone())?)?;
let val = self.memory.borrow().get1(self.pc.wrapping_add(delta as u16))?;
wst.push1(val)?;
}
(_, _, 1, 0x12) => {
// LDR2 addr8 -- a16
let mut wst = wst.borrow_mut();
let delta = wst.pop1()? as i8;
let val = self.memory.borrow().get2(self.pc.wrapping_add(delta as u16))?;
wst.push2(val)?;
}
(_, _, 0, 0x13) => {
// STR1 val8 addr8
let mut wst = wst.borrow_mut();
let delta = wst.pop1()?;
let val = wst.pop1()?;
self.memory.borrow_mut().set1(self.pc.wrapping_add(delta as u16), val);
}
(_, _, 1, 0x13) => {
// STR2 val16 addr8
let mut wst = wst.borrow_mut();
let delta = wst.pop1()? as i8;
let val = wst.pop2()?;
self.memory.borrow_mut().set2(self.pc.wrapping_add(delta as u16), val);
}
(_, _, 0, 0x14) => {
// LDA1 a16 -- a8
let mut wst = wst.borrow_mut();
let addr = wst.pop2()?;
let val = self.memory.borrow_mut().get1(addr)?;
wst.push1(val)?;
}
(_, _, 1, 0x14) => {
// LDA2 a16 -- a16
let mut wst = wst.borrow_mut();
let addr = wst.pop2()?;
let val = self.memory.borrow_mut().get2(addr)?;
wst.push2(val)?;
}
(_, _, 0, 0x15) => {
// STA1 val a16 --
let mut wst = wst.borrow_mut();
let addr = wst.pop2()?;
let val = wst.pop1()?;
self.memory.borrow_mut().set1(addr, val)?;
}
(_, _, 1, 0x15) => {
// STA1 val a16 --
let mut wst = wst.borrow_mut();
let addr = wst.pop2()?;
let val = wst.pop2()?;
self.memory.borrow_mut().set2(addr, val)?;
} }
(_, _, 0, 0x16) => { (_, _, 0, 0x16) => {
// DEI1 port8 -- a8 // DEI port8 -- a8
let mut wst = wst.borrow_mut(); let mut wst = wst.borrow_mut();
let port = wst.pop1()?; let port = wst.pop1()?;
wst.push1(self.dei1(port)); wst.push1(self.dei1(port))?;
} }
(_, _, 1, 0x16) => { (_, _, 1, 0x16) => {
// DEI2 port8 -- a16 // DEI2 port8 -- a16
let mut wst = wst.borrow_mut(); let mut wst = wst.borrow_mut();
let port = wst.pop1()?; let port = wst.pop1()?;
wst.push2(self.dei2(port)); wst.push2(self.dei2(port))?;
} }
(_, _, 0, 0x17) => { (_, _, 0, 0x17) => {
// DEO1 a8 port8 -- // DEO1 a8 port8 --
@ -506,121 +362,56 @@ impl Uxn {
let val = wst.pop2()?; let val = wst.pop2()?;
self.deo2(port, val); self.deo2(port, val);
} }
(_, _, 0, 0x18) => { (_, _, _, 0x18) => {
// ADD1 a b -- c // ADD a b -- c
let mut wst = wst.borrow_mut(); let b = pop(wst.clone())?;
let b = wst.pop1()?; let a = pop(wst.clone())?;
let a = wst.pop1()?; push(wst.clone(), a + b)?;
wst.push1(a + b)?;
} }
(_, _, 1, 0x18) => { (_, _, _, 0x19) => {
// ADD2 a16 b16 -- c16 // SUB a b -- c
let mut wst = wst.borrow_mut(); let b = pop(wst.clone())?;
let b = wst.pop2()?; let a = pop(wst.clone())?;
let a = wst.pop2()?; push(wst.clone(), a - b)?;
wst.push2(a + b)?;
} }
(_, _, 0, 0x19) => { (_, _, _, 0x1a) => {
// SUB1 a b -- c // MUL a b -- c
let mut wst = wst.borrow_mut(); let b = pop(wst.clone())?;
let b = wst.pop1()?; let a = pop(wst.clone())?;
let a = wst.pop1()?; push(wst.clone(), a * b)?;
wst.push1(a - b)?;
} }
(_, _, 1, 0x19) => { (_, _, _, 0x1b) => {
// SUB2 a16 b16 -- c16 // DIV a b -- c
let mut wst = wst.borrow_mut(); let b = pop(wst.clone())?;
let b = wst.pop2()?; let a = pop(wst.clone())?;
let a = wst.pop2()?; push(wst.clone(), a / b)?;
wst.push2(a - b)?;
} }
(_, _, 0, 0x1a) => { (_, _, _, 0x1c) => {
// MUL1 a b -- c // AND a b -- c
let mut wst = wst.borrow_mut(); let b = pop(wst.clone())?;
let b = wst.pop1()?; let a = pop(wst.clone())?;
let a = wst.pop1()?; push(wst.clone(), a & b)?;
wst.push1(a * b)?;
} }
(_, _, 1, 0x1a) => { (_, _, _, 0x1d) => {
// MUL2 a16 b16 -- c16 // OR a b -- c
let mut wst = wst.borrow_mut(); let b = pop(wst.clone())?;
let b = wst.pop2()?; let a = pop(wst.clone())?;
let a = wst.pop2()?; push(wst.clone(), a | b)?;
wst.push2(a * b)?;
} }
(_, _, 0, 0x1b) => { (_, _, _, 0x1e) => {
// DIV1 a b -- c // XOR a8 b8 -- c8
let mut wst = wst.borrow_mut(); let b = pop(wst.clone())?;
let b = wst.pop1()?; let a = pop(wst.clone())?;
let a = wst.pop1()?; push(wst.clone(), a ^ b)?;
wst.push1(a / b)?;
} }
(_, _, 1, 0x1b) => { (_, _, _, 0x1f) => {
// DIV2 a16 b16 -- c16 // SFT a shift8 -- b
let mut wst = wst.borrow_mut(); let shift = wst.borrow_mut().pop1()?;
let b = wst.pop2()?;
let a = wst.pop2()?;
wst.push2(a / b)?;
}
(_, _, 0, 0x1c) => {
// AND1 a8 b8 -- c8
let mut wst = wst.borrow_mut();
let b = wst.pop1()?;
let a = wst.pop1()?;
wst.push1(a & b)?;
}
(_, _, 1, 0x1c) => {
// AND2 a16 b16 -- c16
let mut wst = wst.borrow_mut();
let b = wst.pop2()?;
let a = wst.pop2()?;
wst.push2(a & b)?;
}
(_, _, 0, 0x1d) => {
// OR1 a8 b8 -- c8
let mut wst = wst.borrow_mut();
let b = wst.pop1()?;
let a = wst.pop1()?;
wst.push1(a | b)?;
}
(_, _, 1, 0x1d) => {
// OR2 a16 b16 -- c16
let mut wst = wst.borrow_mut();
let b = wst.pop2()?;
let a = wst.pop2()?;
wst.push2(a | b)?;
}
(_, _, 0, 0x1e) => {
// XOR1 a8 b8 -- c8
let mut wst = wst.borrow_mut();
let b = wst.pop1()?;
let a = wst.pop1()?;
wst.push1(a ^ b)?;
}
(_, _, 1, 0x1e) => {
// XOR2 a16 b16 -- c16
let mut wst = wst.borrow_mut();
let b = wst.pop2()?;
let a = wst.pop2()?;
wst.push2(a ^ b)?;
}
(_, _, 0, 0x1f) => {
// SFT1 a shift8 -- b
let mut wst = wst.borrow_mut();
let shift = wst.pop1()?;
let [left, right] = [shift >> 4, shift & 0xF]; let [left, right] = [shift >> 4, shift & 0xF];
let a = wst.pop1()?; let a = pop(wst.clone())?;
wst.push1((a >> right) << left)?; push(wst.clone(), (a >> right) << left)?;
} }
(_, _, 1, 0x1f) => { _ => unreachable!(),
// SFT2 a shift8 -- b
let mut wst = wst.borrow_mut();
let shift = wst.pop1()?;
let [left, right] = [shift >> 4, shift & 0xF];
let a = wst.pop2()?;
wst.push2((a >> right) << left)?;
}
_ => unreachable!()
} }
} }
} }