[NO TESTS] WIP
This commit is contained in:
parent
2bc93922bc
commit
8630125e4d
4 changed files with 223 additions and 92 deletions
|
@ -1,10 +1,9 @@
|
||||||
use std::env::args;
|
use std::env::args;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
use uxn::Uxn;
|
use uxn::vm::Uxn;
|
||||||
|
|
||||||
fn main() -> Result<(), std::io::Error> {
|
fn main() -> Result<(), std::io::Error> {
|
||||||
let mut vm = Uxn::new();
|
let mut vm = Uxn::new();
|
||||||
|
|
|
@ -19,8 +19,8 @@ impl Device for SystemDevice {
|
||||||
fn dei1(&mut self, vm: &mut Uxn, port: u8) -> u8 {
|
fn dei1(&mut self, vm: &mut Uxn, port: u8) -> u8 {
|
||||||
let slot = port & 0xF;
|
let slot = port & 0xF;
|
||||||
match slot {
|
match slot {
|
||||||
0x2 => vm.wst.idx,
|
0x2 => vm.wst.borrow().idx(),
|
||||||
0x3 => vm.rst.idx,
|
0x3 => vm.rst.borrow().idx(),
|
||||||
x => self.buffer[x as usize],
|
x => self.buffer[x as usize],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
196
src/stack.rs
196
src/stack.rs
|
@ -1,37 +1,66 @@
|
||||||
use std;
|
use std;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::result::Result;
|
use std::result::Result;
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Stack {
|
|
||||||
buff: [u8; 0xFF],
|
|
||||||
pub idx: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum StackError {
|
pub enum StackError {
|
||||||
StackOverflow,
|
StackOverflow,
|
||||||
StackUnderflow,
|
StackUnderflow,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Stack {
|
pub trait Stack: std::fmt::Debug {
|
||||||
pub fn new() -> Stack {
|
fn idx(&self) -> u8;
|
||||||
Stack {
|
fn push1(&mut self, val: u8) -> Result<(), StackError>;
|
||||||
buff: [0; 0xFF],
|
fn push2(&mut self, val: u16) -> Result<(), StackError>;
|
||||||
idx: 0,
|
fn get1(&self, idx: u8) -> Result<u8, StackError>;
|
||||||
}
|
fn get2(&self, idx: u8) -> Result<u16, StackError>;
|
||||||
|
fn peek1(&self) -> Result<u8, StackError>;
|
||||||
|
fn peek2(&self) -> Result<u16, StackError>;
|
||||||
|
fn pop1(&mut self) -> Result<u8, StackError>;
|
||||||
|
fn pop2(&mut self) -> Result<u16, StackError>;
|
||||||
|
|
||||||
|
fn move1(&mut self, other: &mut dyn Stack) -> Result<(), StackError> {
|
||||||
|
other.push1(self.pop1()?)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push1(&mut self, val: u8) -> Result<(), StackError> {
|
fn move2(&mut self, other: &mut dyn Stack) -> Result<(), StackError> {
|
||||||
if self.idx == 255 {
|
other.push2(self.pop2()?)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ArrayStack {
|
||||||
|
buff: [u8; 0xFF],
|
||||||
|
_idx: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ArrayStack {
|
||||||
|
pub fn new() -> ArrayStack {
|
||||||
|
ArrayStack {
|
||||||
|
buff: [0; 0xFF],
|
||||||
|
_idx: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Stack for ArrayStack {
|
||||||
|
fn idx(&self) -> u8 {
|
||||||
|
return self._idx;
|
||||||
|
}
|
||||||
|
fn push1(&mut self, val: u8) -> Result<(), StackError> {
|
||||||
|
if self._idx == 255 {
|
||||||
Err(StackError::StackOverflow)
|
Err(StackError::StackOverflow)
|
||||||
} else {
|
} else {
|
||||||
self.buff[self.idx as usize] = val;
|
self.buff[self._idx as usize] = val;
|
||||||
self.idx += 1;
|
self._idx += 1;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push2(&mut self, val: u16) -> Result<(), StackError> {
|
fn push2(&mut self, val: u16) -> Result<(), StackError> {
|
||||||
if self.idx > 254 {
|
if self._idx > 254 {
|
||||||
Err(StackError::StackOverflow)
|
Err(StackError::StackOverflow)
|
||||||
} else {
|
} else {
|
||||||
val.to_be_bytes().map(|x| self.push1(x).ok());
|
val.to_be_bytes().map(|x| self.push1(x).ok());
|
||||||
|
@ -39,133 +68,123 @@ impl Stack {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get1(&self, idx: u8) -> Result<u8, StackError> {
|
fn get1(&self, _idx: u8) -> Result<u8, StackError> {
|
||||||
Ok(self.buff[idx as usize])
|
Ok(self.buff[_idx as usize])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn peek1(&self) -> Result<u8, StackError> {
|
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)?)
|
Ok(self.get1(self._idx - 1)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pop1(&mut self) -> Result<u8, StackError> {
|
fn pop1(&mut self) -> Result<u8, StackError> {
|
||||||
let val = self.peek1()?;
|
let val = self.peek1()?;
|
||||||
self.idx -= 1;
|
self._idx -= 1;
|
||||||
Ok(val)
|
Ok(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get2(&self, idx: u8) -> Result<u16, StackError> {
|
fn get2(&self, _idx: u8) -> Result<u16, StackError> {
|
||||||
if idx == 255 {
|
if _idx == 255 {
|
||||||
Err(StackError::StackOverflow)
|
Err(StackError::StackOverflow)
|
||||||
} else {
|
} else {
|
||||||
let high = self.buff[idx as usize] as u16;
|
let high = self.buff[_idx as usize] as u16;
|
||||||
let low = self.buff[(idx + 1) as usize] as u16;
|
let low = self.buff[(_idx + 1) as usize] as u16;
|
||||||
println!("idx {}; high {:#02x}; low {:#02x};", idx, high, low);
|
println!("_idx {}; high {:#02x}; low {:#02x};", _idx, high, low);
|
||||||
Ok((high << 8) + low)
|
Ok((high << 8) + low)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn peek2(&mut self) -> Result<u16, StackError> {
|
fn peek2(&self) -> Result<u16, StackError> {
|
||||||
if self.idx < 2 {
|
if self._idx < 2 {
|
||||||
Err(StackError::StackUnderflow)
|
Err(StackError::StackUnderflow)
|
||||||
} else {
|
} else {
|
||||||
self.get2(self.idx - 2)
|
self.get2(self._idx - 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pop2(&mut self) -> Result<u16, StackError> {
|
fn pop2(&mut self) -> Result<u16, StackError> {
|
||||||
let val = self.peek2()?;
|
let val = self.peek2()?;
|
||||||
self.idx -= 2;
|
self._idx -= 2;
|
||||||
Ok(val)
|
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(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod stack_test {
|
mod arraystack_test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_push_pop() {
|
fn test_push_pop() {
|
||||||
let mut s = Stack::new();
|
let mut s = ArrayStack::new();
|
||||||
match s.push1(0xFF) {
|
match s.push1(0xFF) {
|
||||||
Ok(()) => (),
|
Ok(()) => (),
|
||||||
Err(_) => assert!(false, "pushing stack of size 0 errored"),
|
Err(_) => assert!(false, "pushing stack of size 0 errored"),
|
||||||
}
|
}
|
||||||
assert_eq!(s.idx, 1);
|
assert_eq!(s._idx, 1);
|
||||||
|
|
||||||
match s.peek1() {
|
match s.peek1() {
|
||||||
Ok(val) => assert_eq!(val, 0xFF),
|
Ok(val) => assert_eq!(val, 0xFF),
|
||||||
Err(_) => assert!(false, "popping stack of size 1 errored"),
|
Err(_) => assert!(false, "popping stack of size 1 errored"),
|
||||||
}
|
}
|
||||||
assert_eq!(s.idx, 1);
|
assert_eq!(s._idx, 1);
|
||||||
|
|
||||||
match s.pop1() {
|
match s.pop1() {
|
||||||
Ok(val) => assert_eq!(val, 0xFF),
|
Ok(val) => assert_eq!(val, 0xFF),
|
||||||
Err(_) => assert!(false, "popping stack of size 1 errored"),
|
Err(_) => assert!(false, "popping stack of size 1 errored"),
|
||||||
}
|
}
|
||||||
assert_eq!(s.idx, 0);
|
assert_eq!(s._idx, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_push2_pop2() {
|
fn test_push2_pop2() {
|
||||||
let mut s = Stack::new();
|
let mut s = ArrayStack::new();
|
||||||
match s.push2(0xFF00) {
|
match s.push2(0xFF00) {
|
||||||
Ok(()) => (),
|
Ok(()) => (),
|
||||||
Err(_) => assert!(false, "pushing stack of size 0 errored"),
|
Err(_) => assert!(false, "pushing stack of size 0 errored"),
|
||||||
}
|
}
|
||||||
assert_eq!(s.idx, 2);
|
assert_eq!(s._idx, 2);
|
||||||
|
|
||||||
match s.peek2() {
|
match s.peek2() {
|
||||||
Ok(val) => assert_eq!(val, 0xFF00),
|
Ok(val) => assert_eq!(val, 0xFF00),
|
||||||
Err(_) => assert!(false, "peek2 stack of size 2 errored"),
|
Err(_) => assert!(false, "peek2 stack of size 2 errored"),
|
||||||
}
|
}
|
||||||
assert_eq!(s.idx, 2);
|
assert_eq!(s._idx, 2);
|
||||||
|
|
||||||
match s.pop2() {
|
match s.pop2() {
|
||||||
Ok(val) => assert_eq!(val, 0xFF00),
|
Ok(val) => assert_eq!(val, 0xFF00),
|
||||||
Err(_) => assert!(false, "peek2 stack of size 2 errored"),
|
Err(_) => assert!(false, "peek2 stack of size 2 errored"),
|
||||||
}
|
}
|
||||||
assert_eq!(s.idx, 0);
|
assert_eq!(s._idx, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_push2_pop1_pop1() {
|
fn test_push2_pop1_pop1() {
|
||||||
let mut s = Stack::new();
|
let mut s = ArrayStack::new();
|
||||||
match s.push2(0xFF00) {
|
match s.push2(0xFF00) {
|
||||||
Ok(()) => (),
|
Ok(()) => (),
|
||||||
Err(_) => assert!(false, "pushing stack of size 0 errored"),
|
Err(_) => assert!(false, "pushing stack of size 0 errored"),
|
||||||
}
|
}
|
||||||
assert_eq!(s.idx, 2);
|
assert_eq!(s._idx, 2);
|
||||||
|
|
||||||
match s.pop1() {
|
match s.pop1() {
|
||||||
Ok(val) => assert_eq!(val, 0x00),
|
Ok(val) => assert_eq!(val, 0x00),
|
||||||
Err(_) => assert!(false, "peek1 stack of size 2 errored"),
|
Err(_) => assert!(false, "peek1 stack of size 2 errored"),
|
||||||
}
|
}
|
||||||
assert_eq!(s.idx, 1);
|
assert_eq!(s._idx, 1);
|
||||||
|
|
||||||
match s.pop1() {
|
match s.pop1() {
|
||||||
Ok(val) => assert_eq!(val, 0xFF),
|
Ok(val) => assert_eq!(val, 0xFF),
|
||||||
Err(_) => assert!(false, "peek1 stack of size 2 errored"),
|
Err(_) => assert!(false, "peek1 stack of size 2 errored"),
|
||||||
}
|
}
|
||||||
assert_eq!(s.idx, 0);
|
assert_eq!(s._idx, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pop_empty() {
|
fn test_pop_empty() {
|
||||||
let mut s = Stack::new();
|
let mut s = ArrayStack::new();
|
||||||
match s.pop1() {
|
match s.pop1() {
|
||||||
Ok(_) => assert!(false, "popping stack of size 0 succeeded"),
|
Ok(_) => assert!(false, "popping stack of size 0 succeeded"),
|
||||||
Err(StackError::StackUnderflow) => (),
|
Err(StackError::StackUnderflow) => (),
|
||||||
|
@ -173,3 +192,62 @@ mod stack_test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum StackOp {
|
||||||
|
Push1(u8),
|
||||||
|
Push2(u16),
|
||||||
|
Pop1(),
|
||||||
|
Pop2(),
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A writeahead log wrapping a read copy of another stack.
|
||||||
|
* Can be committed
|
||||||
|
*/
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct StackWAL {
|
||||||
|
log: Vec<StackOp>,
|
||||||
|
_idx: u8,
|
||||||
|
wrapped: Rc<RefCell<dyn Stack>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StackWAL {
|
||||||
|
pub fn new(wrapped: Rc<RefCell<dyn Stack>>) -> StackWAL {
|
||||||
|
return StackWAL {
|
||||||
|
log: vec![],
|
||||||
|
_idx: wrapped.borrow().idx(),
|
||||||
|
wrapped: wrapped.clone(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Stack for StackWAL {
|
||||||
|
fn idx(&self) -> u8 {
|
||||||
|
return self._idx;
|
||||||
|
}
|
||||||
|
fn push1(&mut self, val: u8) -> Result<(), StackError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
fn push2(&mut self, val: u16) -> Result<(), StackError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
fn get1(&self, idx: u8) -> Result<u8, StackError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
fn get2(&self, idx: u8) -> Result<u16, StackError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
fn peek1(&self) -> Result<u8, StackError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
fn peek2(&self) -> Result<u16, StackError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
fn pop1(&mut self) -> Result<u8, StackError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
fn pop2(&mut self) -> Result<u16, StackError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
110
src/vm.rs
110
src/vm.rs
|
@ -35,8 +35,8 @@ pub struct Uxn {
|
||||||
// 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
|
||||||
pub devices: [Rc<RefCell<dyn Device>>; 16],
|
pub devices: [Rc<RefCell<dyn Device>>; 16],
|
||||||
pub pc: u16, // Program counter
|
pub pc: u16, // Program counter
|
||||||
pub wst: Stack, // Data stack
|
pub wst: Rc<RefCell<dyn Stack>>, // Data stack
|
||||||
pub rst: Stack, // Return stack pointer
|
pub rst: Rc<RefCell<dyn Stack>>, // Return stack pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Uxn {
|
impl Uxn {
|
||||||
|
@ -62,8 +62,8 @@ impl Uxn {
|
||||||
Rc::new(RefCell::new(NullDevice::new())), // #0f
|
Rc::new(RefCell::new(NullDevice::new())), // #0f
|
||||||
],
|
],
|
||||||
pc: 0x0100,
|
pc: 0x0100,
|
||||||
wst: Stack::new(),
|
wst: Rc::new(RefCell::new(ArrayStack::new())),
|
||||||
rst: Stack::new(),
|
rst: Rc::new(RefCell::new(ArrayStack::new())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,9 +138,9 @@ impl Uxn {
|
||||||
|
|
||||||
let [wst, rst] = {
|
let [wst, rst] = {
|
||||||
if rflag == 0 {
|
if rflag == 0 {
|
||||||
[&mut self.wst, &mut self.rst]
|
[self.wst.clone(), self.rst.clone()]
|
||||||
} else {
|
} else {
|
||||||
[&mut self.wst, &mut self.rst]
|
[self.wst.clone(), self.rst.clone()]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -152,48 +152,51 @@ impl Uxn {
|
||||||
}
|
}
|
||||||
(_, _, 0, 0x00) => {
|
(_, _, 0, 0x00) => {
|
||||||
// LIT1
|
// LIT1
|
||||||
wst.push1(self.lda1(self.pc + 1)?);
|
wst.borrow_mut().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.lda2(self.pc + 1)?);
|
wst.borrow_mut().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.borrow_mut().pop1()?;
|
||||||
wst.push1(a + 1);
|
wst.borrow_mut().push1(a + 1);
|
||||||
}
|
}
|
||||||
(_, _, 1, 0x01) => {
|
(_, _, 1, 0x01) => {
|
||||||
// INC1
|
// INC1
|
||||||
let a = wst.pop2()?;
|
let a = wst.borrow_mut().pop2()?;
|
||||||
wst.push2(a + 1);
|
wst.borrow_mut().push2(a + 1);
|
||||||
}
|
}
|
||||||
(_, _, 0, 0x02) => {
|
(_, _, 0, 0x02) => {
|
||||||
// POP1
|
// POP1
|
||||||
wst.pop1();
|
wst.borrow_mut().pop1();
|
||||||
}
|
}
|
||||||
(_, _, 1, 0x02) => {
|
(_, _, 1, 0x02) => {
|
||||||
// POP2
|
// POP2
|
||||||
wst.pop2();
|
wst.borrow_mut().pop2();
|
||||||
}
|
}
|
||||||
(_, _, 0, 0x03) => {
|
(_, _, 0, 0x03) => {
|
||||||
// NIP1 a b -- a
|
// NIP1 a b -- a
|
||||||
|
let mut wst = wst.borrow_mut();
|
||||||
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 mut wst = wst.borrow_mut();
|
||||||
let keep = wst.pop2()?;
|
let keep = wst.pop2()?;
|
||||||
wst.pop2()?;
|
wst.pop2()?;
|
||||||
wst.push2(keep)?;
|
wst.push2(keep)?;
|
||||||
}
|
}
|
||||||
(_, _, 0, 0x04) => {
|
(_, _, 0, 0x04) => {
|
||||||
// SWP1
|
// SWP1
|
||||||
|
let mut wst = wst.borrow_mut();
|
||||||
let a = wst.pop1()?;
|
let a = wst.pop1()?;
|
||||||
let b = wst.pop1()?;
|
let b = wst.pop1()?;
|
||||||
wst.push1(a)?;
|
wst.push1(a)?;
|
||||||
|
@ -201,13 +204,15 @@ impl Uxn {
|
||||||
}
|
}
|
||||||
(_, _, 1, 0x04) => {
|
(_, _, 1, 0x04) => {
|
||||||
// SWP2
|
// SWP2
|
||||||
|
let mut wst = wst.borrow_mut();
|
||||||
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
|
// ROT1
|
||||||
|
let mut wst = wst.borrow_mut();
|
||||||
let a = wst.pop1()?;
|
let a = wst.pop1()?;
|
||||||
let b = wst.pop1()?;
|
let b = wst.pop1()?;
|
||||||
let c = wst.pop1()?;
|
let c = wst.pop1()?;
|
||||||
|
@ -216,7 +221,8 @@ impl Uxn {
|
||||||
wst.push1(a)?;
|
wst.push1(a)?;
|
||||||
}
|
}
|
||||||
(_, _, 1, 0x05) => {
|
(_, _, 1, 0x05) => {
|
||||||
// ROT
|
// ROT2
|
||||||
|
let mut wst = wst.borrow_mut();
|
||||||
let a = wst.pop2()?;
|
let a = wst.pop2()?;
|
||||||
let b = wst.pop2()?;
|
let b = wst.pop2()?;
|
||||||
let c = wst.pop2()?;
|
let c = wst.pop2()?;
|
||||||
|
@ -226,30 +232,39 @@ impl Uxn {
|
||||||
}
|
}
|
||||||
(_, _, 0, 0x06) => {
|
(_, _, 0, 0x06) => {
|
||||||
// DUP2
|
// DUP2
|
||||||
|
let mut wst = wst.borrow_mut();
|
||||||
let a = wst.peek1()?;
|
let a = wst.peek1()?;
|
||||||
wst.push1(a)?;
|
wst.push1(a)?;
|
||||||
}
|
}
|
||||||
(_, _, 1, 0x06) => {
|
(_, _, 1, 0x06) => {
|
||||||
// DUP2
|
// DUP2
|
||||||
|
let mut wst = wst.borrow_mut();
|
||||||
let a = wst.peek2()?;
|
let a = wst.peek2()?;
|
||||||
wst.push2(a)?;
|
wst.push2(a)?;
|
||||||
}
|
}
|
||||||
(_, _, 0, 0x07) => {
|
(_, _, 0, 0x07) => {
|
||||||
// OVR1 a b -- a b a
|
// OVR1 a b -- a b a
|
||||||
if wst.idx < 2 {
|
let mut wst = wst.borrow_mut();
|
||||||
|
if wst.idx() < 2 {
|
||||||
return Err(UxnError::StackError(StackError::StackUnderflow));
|
return Err(UxnError::StackError(StackError::StackUnderflow));
|
||||||
}
|
}
|
||||||
wst.push1(wst.get1(wst.idx - 2)?)?;
|
let i = wst.idx() - 2;
|
||||||
|
let v = wst.get1(i)?;
|
||||||
|
wst.push1(v)?;
|
||||||
}
|
}
|
||||||
(_, _, 1, 0x07) => {
|
(_, _, 1, 0x07) => {
|
||||||
// OVR2 a b -- a b a
|
// OVR2 a b -- a b a
|
||||||
if wst.idx < 4 {
|
let mut wst = wst.borrow_mut();
|
||||||
|
if wst.idx() < 4 {
|
||||||
return Err(UxnError::StackError(StackError::StackUnderflow));
|
return Err(UxnError::StackError(StackError::StackUnderflow));
|
||||||
}
|
}
|
||||||
wst.push2(wst.get2(wst.idx - 4)?)?;
|
let i = wst.idx() - 4;
|
||||||
|
let v = wst.get2(i)?;
|
||||||
|
wst.push2(v)?;
|
||||||
}
|
}
|
||||||
(_, _, 0, 0x08) => {
|
(_, _, 0, 0x08) => {
|
||||||
// EQU1
|
// EQU1
|
||||||
|
let mut wst = wst.borrow_mut();
|
||||||
let a = wst.pop1()?;
|
let a = wst.pop1()?;
|
||||||
let b = wst.pop1()?;
|
let b = wst.pop1()?;
|
||||||
if a == b {
|
if a == b {
|
||||||
|
@ -260,6 +275,7 @@ impl Uxn {
|
||||||
}
|
}
|
||||||
(_, _, 1, 0x08) => {
|
(_, _, 1, 0x08) => {
|
||||||
// EQU2
|
// EQU2
|
||||||
|
let mut wst = wst.borrow_mut();
|
||||||
let a = wst.pop2()?;
|
let a = wst.pop2()?;
|
||||||
let b = wst.pop2()?;
|
let b = wst.pop2()?;
|
||||||
if a == b {
|
if a == b {
|
||||||
|
@ -270,8 +286,9 @@ impl Uxn {
|
||||||
}
|
}
|
||||||
(_, _, 0, 0x09) => {
|
(_, _, 0, 0x09) => {
|
||||||
// NEQ1
|
// NEQ1
|
||||||
let a = wst.pop1()?;
|
let mut wst = wst.borrow_mut();
|
||||||
let b = wst.pop1()?;
|
let b = wst.pop1()?;
|
||||||
|
let a = wst.pop1()?;
|
||||||
if a == b {
|
if a == b {
|
||||||
wst.push1(0)?;
|
wst.push1(0)?;
|
||||||
} else {
|
} else {
|
||||||
|
@ -280,21 +297,58 @@ impl Uxn {
|
||||||
}
|
}
|
||||||
(_, _, 1, 0x09) => {
|
(_, _, 1, 0x09) => {
|
||||||
// NEQ2
|
// NEQ2
|
||||||
let a = wst.pop2()?;
|
let mut wst = wst.borrow_mut();
|
||||||
let b = wst.pop2()?;
|
let b = wst.pop2()?;
|
||||||
|
let a = wst.pop2()?;
|
||||||
if a == b {
|
if a == b {
|
||||||
wst.push1(0)?;
|
wst.push1(0)?;
|
||||||
} else {
|
} else {
|
||||||
wst.push1(1)?;
|
wst.push1(1)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(_, _, _, 0x0a) => {
|
(_, _, 0, 0x0a) => {
|
||||||
// GTH
|
// 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)?;
|
||||||
}
|
}
|
||||||
(_, _, _, 0x0b) => {
|
|
||||||
// LTH
|
|
||||||
()
|
|
||||||
}
|
}
|
||||||
(_, _, _, 0x0c) => {
|
(_, _, _, 0x0c) => {
|
||||||
// JMP
|
// JMP
|
||||||
|
|
Loading…
Reference in a new issue