[NO TESTS] WIP

This commit is contained in:
Reid 'arrdem' McKenzie 2022-12-20 10:20:40 -07:00
parent 6bf7c7425e
commit 6e92ae507f

157
src/vm.rs
View file

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