[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 stack;
use std::cell::{Cell, RefCell, RefMut};
use std::rc::Rc;
use std::*;
@ -73,8 +74,10 @@ impl Device for SystemDevice {
fn deo1(&mut self, vm: &mut Uxn, port: u8, val: u8) {
let slot = port & 0xF;
match slot {
0x2 => vm.wst.idx = val,
0x3 => vm.rst.idx = val,
// Note: This VM does not support mutating the stack pointers.
// 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,
}
}
@ -95,9 +98,9 @@ impl Device for SystemDevice {
#[derive(Debug)]
pub struct Uxn {
memory: Box<TrivialMemory>,
memory: Rc<RefCell<TrivialMemory>>,
// 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
wst: Stack, // Data stack
rst: Stack, // Return stack pointer
@ -106,24 +109,24 @@ pub struct Uxn {
impl Uxn {
pub fn new() -> Uxn {
Uxn {
memory: Box::new(TrivialMemory::new()),
memory: Rc::new(RefCell::new(TrivialMemory::new())),
devices: [
Box::new(SystemDevice::new()), // #00
Box::new(NullDevice::new()), // #01
Box::new(NullDevice::new()), // #02
Box::new(NullDevice::new()), // #03
Box::new(NullDevice::new()), // #04
Box::new(NullDevice::new()), // #05
Box::new(NullDevice::new()), // #06
Box::new(NullDevice::new()), // #07
Box::new(NullDevice::new()), // #08
Box::new(NullDevice::new()), // #09
Box::new(NullDevice::new()), // #0a
Box::new(NullDevice::new()), // #0b
Box::new(NullDevice::new()), // #0c
Box::new(NullDevice::new()), // #0d
Box::new(NullDevice::new()), // #0e
Box::new(NullDevice::new()), // #0f
Rc::new(RefCell::new(SystemDevice::new())), // #00
Rc::new(RefCell::new(NullDevice::new())), // #01
Rc::new(RefCell::new(NullDevice::new())), // #02
Rc::new(RefCell::new(NullDevice::new())), // #03
Rc::new(RefCell::new(NullDevice::new())), // #04
Rc::new(RefCell::new(NullDevice::new())), // #05
Rc::new(RefCell::new(NullDevice::new())), // #06
Rc::new(RefCell::new(NullDevice::new())), // #07
Rc::new(RefCell::new(NullDevice::new())), // #08
Rc::new(RefCell::new(NullDevice::new())), // #09
Rc::new(RefCell::new(NullDevice::new())), // #0a
Rc::new(RefCell::new(NullDevice::new())), // #0b
Rc::new(RefCell::new(NullDevice::new())), // #0c
Rc::new(RefCell::new(NullDevice::new())), // #0d
Rc::new(RefCell::new(NullDevice::new())), // #0e
Rc::new(RefCell::new(NullDevice::new())), // #0f
],
pc: 0x0100,
wst: Stack::new(),
@ -132,27 +135,26 @@ impl Uxn {
}
pub fn is_halted(&mut self) -> bool {
let dev = self.devices[0].as_mut();
dev.dei1(self, 0x0f) != 0
self.dei1(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 {
let dev = self.devices[(port & 0xF0 >> 4) as usize];
dev.dei1(self, port)
self.device(port).borrow_mut().dei1(self, port)
}
pub fn dei2(&mut self, port: u8) -> u16 {
let dev = self.devices[(port & 0xF0 >> 4) as usize];
dev.dei2(self, port)
self.device(port).borrow_mut().dei2(self, port)
}
pub fn deo1(&mut self, port: u8, val: u8) {
let dev = self.devices[(port & 0xF0 >> 4) as usize].as_mut();
dev.deo1(self, port, val)
self.device(port).borrow_mut().deo1(self, port, val);
}
pub fn deo2(&mut self, port: u8, val: u16) {
let dev = self.devices[(port & 0xF0 >> 4) as usize].as_mut();
dev.deo2(self, port, val)
self.device(port).borrow_mut().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 {
Err(StackError::StackUnderflow)
} else {
self.idx -= 1;
Ok(self.buff[self.idx as usize])
Ok(self.get1(self.idx - 1)?)
}
}
pub fn pop1(&mut self) -> Result<u8, StackError> {
let val = self.peek1()?;
self.idx -= 1;
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> {
if self.idx < 2 {
Err(StackError::StackUnderflow)
} else {
Ok(((self.pop1()? as u16) << 8) + self.pop1()? as u16)
}
let val = self.peek2()?;
self.idx -= 2;
Ok(val)
}
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(())
}
}