[NO TESTS] WIP

This commit is contained in:
Reid 'arrdem' McKenzie 2022-12-13 00:27:30 -07:00
parent 12d657097c
commit e6faac5788
2 changed files with 76 additions and 39 deletions

View file

@ -1,6 +1,7 @@
pub mod memory; pub mod memory;
pub mod stack; pub mod stack;
use std::cell::{Cell, RefCell, RefMut};
use std::rc::Rc; use std::rc::Rc;
use std::*; use std::*;
@ -73,8 +74,10 @@ impl Device for SystemDevice {
fn deo1(&mut self, vm: &mut Uxn, port: u8, val: u8) { fn deo1(&mut self, vm: &mut Uxn, port: u8, val: u8) {
let slot = port & 0xF; let slot = port & 0xF;
match slot { match slot {
0x2 => vm.wst.idx = val, // Note: This VM does not support mutating the stack pointers.
0x3 => vm.rst.idx = val, // This operation is not well defined upstream
0x2 => panic!("Invoked unsupported mutation of the data stack pointer"),
0x3 => panic!("Invoked unsupported mutation of the return stack pointer"),
x => self.buffer[x as usize] = val, x => self.buffer[x as usize] = val,
} }
} }
@ -95,9 +98,9 @@ impl Device for SystemDevice {
#[derive(Debug)] #[derive(Debug)]
pub struct Uxn { pub struct Uxn {
memory: Box<TrivialMemory>, memory: Rc<RefCell<TrivialMemory>>,
// Note: Using Rc so we can start with many NullDevs and replace them // Note: Using Rc so we can start with many NullDevs and replace them
devices: [Box<dyn Device>; 16], devices: [Rc<RefCell<dyn Device>>; 16],
pc: u16, // Program counter pc: u16, // Program counter
wst: Stack, // Data stack wst: Stack, // Data stack
rst: Stack, // Return stack pointer rst: Stack, // Return stack pointer
@ -106,24 +109,24 @@ pub struct Uxn {
impl Uxn { impl Uxn {
pub fn new() -> Uxn { pub fn new() -> Uxn {
Uxn { Uxn {
memory: Box::new(TrivialMemory::new()), memory: Rc::new(RefCell::new(TrivialMemory::new())),
devices: [ devices: [
Box::new(SystemDevice::new()), // #00 Rc::new(RefCell::new(SystemDevice::new())), // #00
Box::new(NullDevice::new()), // #01 Rc::new(RefCell::new(NullDevice::new())), // #01
Box::new(NullDevice::new()), // #02 Rc::new(RefCell::new(NullDevice::new())), // #02
Box::new(NullDevice::new()), // #03 Rc::new(RefCell::new(NullDevice::new())), // #03
Box::new(NullDevice::new()), // #04 Rc::new(RefCell::new(NullDevice::new())), // #04
Box::new(NullDevice::new()), // #05 Rc::new(RefCell::new(NullDevice::new())), // #05
Box::new(NullDevice::new()), // #06 Rc::new(RefCell::new(NullDevice::new())), // #06
Box::new(NullDevice::new()), // #07 Rc::new(RefCell::new(NullDevice::new())), // #07
Box::new(NullDevice::new()), // #08 Rc::new(RefCell::new(NullDevice::new())), // #08
Box::new(NullDevice::new()), // #09 Rc::new(RefCell::new(NullDevice::new())), // #09
Box::new(NullDevice::new()), // #0a Rc::new(RefCell::new(NullDevice::new())), // #0a
Box::new(NullDevice::new()), // #0b Rc::new(RefCell::new(NullDevice::new())), // #0b
Box::new(NullDevice::new()), // #0c Rc::new(RefCell::new(NullDevice::new())), // #0c
Box::new(NullDevice::new()), // #0d Rc::new(RefCell::new(NullDevice::new())), // #0d
Box::new(NullDevice::new()), // #0e Rc::new(RefCell::new(NullDevice::new())), // #0e
Box::new(NullDevice::new()), // #0f Rc::new(RefCell::new(NullDevice::new())), // #0f
], ],
pc: 0x0100, pc: 0x0100,
wst: Stack::new(), wst: Stack::new(),
@ -132,27 +135,26 @@ impl Uxn {
} }
pub fn is_halted(&mut self) -> bool { pub fn is_halted(&mut self) -> bool {
let dev = self.devices[0].as_mut(); self.dei1(0x0f) != 0
dev.dei1(self, 0x0f) != 0 }
fn device(&self, port: u8) -> Rc<RefCell<dyn Device>> {
Rc::clone(&self.devices[(port & 0xF0 >> 4) as usize])
} }
pub fn dei1(&mut self, port: u8) -> u8 { pub fn dei1(&mut self, port: u8) -> u8 {
let dev = self.devices[(port & 0xF0 >> 4) as usize]; self.device(port).borrow_mut().dei1(self, port)
dev.dei1(self, port)
} }
pub fn dei2(&mut self, port: u8) -> u16 { pub fn dei2(&mut self, port: u8) -> u16 {
let dev = self.devices[(port & 0xF0 >> 4) as usize]; self.device(port).borrow_mut().dei2(self, port)
dev.dei2(self, port)
} }
pub fn deo1(&mut self, port: u8, val: u8) { pub fn deo1(&mut self, port: u8, val: u8) {
let dev = self.devices[(port & 0xF0 >> 4) as usize].as_mut(); self.device(port).borrow_mut().deo1(self, port, val);
dev.deo1(self, port, val)
} }
pub fn deo2(&mut self, port: u8, val: u16) { pub fn deo2(&mut self, port: u8, val: u16) {
let dev = self.devices[(port & 0xF0 >> 4) as usize].as_mut(); self.device(port).borrow_mut().deo2(self, port, val);
dev.deo2(self, port, val)
} }
} }

View file

@ -39,20 +39,55 @@ impl Stack {
} }
} }
pub fn pop1(&mut self) -> Result<u8, StackError> { pub fn get1(&self, idx: u8) -> Result<u8, StackError> {
Ok(self.buff[idx as usize])
}
pub fn peek1(&self) -> Result<u8, StackError> {
if self.idx == 0 { if self.idx == 0 {
Err(StackError::StackUnderflow) Err(StackError::StackUnderflow)
} else { } else {
Ok(self.get1(self.idx - 1)?)
}
}
pub fn pop1(&mut self) -> Result<u8, StackError> {
let val = self.peek1()?;
self.idx -= 1; self.idx -= 1;
Ok(self.buff[self.idx as usize]) Ok(val)
}
pub fn get2(&self, idx: u8) -> Result<u16, StackError> {
if idx == 255 {
Err(StackError::StackOverflow)
} else {
let high = self.buff[idx as usize] as u16;
let low = self.buff[(idx + 1) as usize] as u16;
Ok((high << 8) + low)
}
}
pub fn peek2(&mut self) -> Result<u16, StackError> {
if self.idx < 2 {
Err(StackError::StackUnderflow)
} else {
self.get2(self.idx - 2)
} }
} }
pub fn pop2(&mut self) -> Result<u16, StackError> { pub fn pop2(&mut self) -> Result<u16, StackError> {
if self.idx < 2 { let val = self.peek2()?;
Err(StackError::StackUnderflow) self.idx -= 2;
} else { Ok(val)
Ok(((self.pop1()? as u16) << 8) + self.pop1()? as u16)
} }
pub fn move1(&mut self, other: &mut Stack) -> Result<(), StackError> {
other.push1(self.pop1()?)?;
Ok(())
}
pub fn move2(&mut self, other: &mut Stack) -> Result<(), StackError> {
other.push2(self.pop2()?)?;
Ok(())
} }
} }