[NO TESTS] WIP
This commit is contained in:
parent
12d657097c
commit
e6faac5788
2 changed files with 76 additions and 39 deletions
64
src/lib.rs
64
src/lib.rs
|
@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
51
src/stack.rs
51
src/stack.rs
|
@ -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 {
|
||||||
self.idx -= 1;
|
Ok(self.get1(self.idx - 1)?)
|
||||||
Ok(self.buff[self.idx as usize])
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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> {
|
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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue