Break out step()
This commit is contained in:
parent
09bb1854bf
commit
b7ade42661
1 changed files with 287 additions and 282 deletions
569
src/vm.rs
569
src/vm.rs
|
@ -12,6 +12,7 @@ pub enum UxnError {
|
|||
StackError(StackError),
|
||||
MemoryError(MemoryError),
|
||||
ExecutionLimit(u16),
|
||||
Break,
|
||||
ArithmeticOverflow,
|
||||
ArithmeticUnderflow,
|
||||
DivisionByZero,
|
||||
|
@ -111,12 +112,293 @@ impl Uxn {
|
|||
|
||||
// Run one clock cycle (instruction)
|
||||
pub fn step(&mut self) -> Result<(), UxnError> {
|
||||
match self.lda1(self.pc) {
|
||||
Err(e) => return Err(UxnError::MemoryError(e)),
|
||||
Ok(opcode) => {
|
||||
// The value of PC is defined to be the value of the NEXT pc ala Mips
|
||||
self.pc += 1;
|
||||
|
||||
// Extract flags
|
||||
let sflag: u8 = opcode & 0x20 >> 5;
|
||||
let rflag: u8 = opcode & 0x40 >> 6;
|
||||
let kflag: u8 = opcode & 0x80 >> 7;
|
||||
let icode: u8 = opcode & 0x1F;
|
||||
|
||||
// Swizzle the stacks as needed
|
||||
let [wst, rst] = {
|
||||
if rflag == 0 {
|
||||
[self.wst.clone(), self.rst.clone()]
|
||||
} else {
|
||||
[self.rst.clone(), self.wst.clone()]
|
||||
}
|
||||
};
|
||||
|
||||
// Some procedural abstractions over load/store sizes
|
||||
let pop = |stack: Rc<RefCell<dyn Stack>>| -> Result<u16, StackError> {
|
||||
if sflag == 1 {
|
||||
stack.borrow_mut().pop2()
|
||||
} else {
|
||||
Ok(stack.borrow_mut().pop1()? as u16)
|
||||
}
|
||||
};
|
||||
|
||||
let push = |stack: Rc<RefCell<dyn Stack>>, val: u16| {
|
||||
if sflag == 1 {
|
||||
stack.borrow_mut().push2(val)
|
||||
} else {
|
||||
stack.borrow_mut().push1(val as u8)
|
||||
}
|
||||
};
|
||||
|
||||
let load = |addr: u16| -> Result<u16, MemoryError> {
|
||||
if sflag == 1 {
|
||||
self.memory.borrow_mut().get2(addr)
|
||||
} else {
|
||||
Ok(self.memory.borrow_mut().get1(addr)? as u16)
|
||||
}
|
||||
};
|
||||
|
||||
let store = |addr: u16, value: u16| {
|
||||
if sflag == 1 {
|
||||
self.memory.borrow_mut().set2(addr, value)
|
||||
} else {
|
||||
self.memory.borrow_mut().set1(addr, value as u8)
|
||||
}
|
||||
};
|
||||
|
||||
// Just bail out of we get a keep flag, haven't figured out an abstraction for that yet.
|
||||
if kflag != 0 {
|
||||
panic!("Got unsupported keep-mode instruction");
|
||||
}
|
||||
|
||||
match (kflag, rflag, sflag, icode) {
|
||||
(0, 0, 0, 0x00) => {
|
||||
// BRK
|
||||
return Err(UxnError::Break);
|
||||
}
|
||||
(_, _, _, 0x00) => {
|
||||
// LIT
|
||||
push(wst.clone(), load(self.pc)?)?;
|
||||
self.pc += if sflag == 1 { 2 } else { 1 };
|
||||
}
|
||||
(_, _, _, 0x01) => {
|
||||
// INC
|
||||
push(wst.clone(), pop(wst.clone())? + 1)?;
|
||||
}
|
||||
(_, _, _, 0x02) => {
|
||||
// POP
|
||||
pop(wst)?;
|
||||
}
|
||||
(_, _, _, 0x03) => {
|
||||
// NIP a b -- a
|
||||
let keep = pop(wst.clone())?;
|
||||
pop(wst.clone())?;
|
||||
push(wst.clone(), keep)?;
|
||||
}
|
||||
(_, _, _, 0x04) => {
|
||||
// SWP
|
||||
let a = pop(wst.clone())?;
|
||||
let b = pop(wst.clone())?;
|
||||
push(wst.clone(), b)?;
|
||||
push(wst.clone(), a)?;
|
||||
}
|
||||
(_, _, _, 0x05) => {
|
||||
// ROT
|
||||
let a = pop(wst.clone())?;
|
||||
let b = pop(wst.clone())?;
|
||||
let c = pop(wst.clone())?;
|
||||
push(wst.clone(), b)?;
|
||||
push(wst.clone(), c)?;
|
||||
push(wst.clone(), a)?;
|
||||
}
|
||||
(_, _, _, 0x06) => {
|
||||
// DUP
|
||||
let a = pop(wst.clone())?;
|
||||
push(wst.clone(), a)?;
|
||||
push(wst.clone(), a)?;
|
||||
}
|
||||
(_, _, _, 0x07) => {
|
||||
// OVR a b -- a b a
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
push(wst.clone(), a)?;
|
||||
push(wst.clone(), b)?;
|
||||
push(wst.clone(), a)?;
|
||||
}
|
||||
(_, _, _, 0x08) => {
|
||||
// EQU
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
wst.borrow_mut().push1(if a == b { 1 } else { 0 })?;
|
||||
}
|
||||
(_, _, _, 0x09) => {
|
||||
// NEQ
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
wst.borrow_mut().push1(if a == b { 0 } else { 1 })?;
|
||||
}
|
||||
(_, _, _, 0x0a) => {
|
||||
// GTH a b
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
wst.borrow_mut().push1(if a > b { 1 } else { 0 })?;
|
||||
}
|
||||
(_, _, _, 0x0b) => {
|
||||
// LTH a b
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
wst.borrow_mut().push1(if a < b { 1 } else { 0 })?;
|
||||
}
|
||||
(_, _, _, 0x0c) => {
|
||||
// JMP
|
||||
let delta = wst.borrow_mut().pop1()? as i8;
|
||||
self.pc = self.pc.wrapping_add(delta as u16);
|
||||
}
|
||||
(_, _, 0, 0x0d) => {
|
||||
// JCN1 cnd8 addr8 (relative)
|
||||
let delta = wst.borrow_mut().pop1()? as i8;
|
||||
let cnd = wst.borrow_mut().pop1()?;
|
||||
if cnd != 0 {
|
||||
self.pc = self.pc.wrapping_add(delta as u16);
|
||||
}
|
||||
}
|
||||
(_, _, 2, 0x0d) => {
|
||||
// JCN2 cnd8 addr16 (absolute)
|
||||
let addr = wst.borrow_mut().pop2()?;
|
||||
let cnd = wst.borrow_mut().pop1()?;
|
||||
if cnd != 0 {
|
||||
self.pc = addr;
|
||||
}
|
||||
}
|
||||
(_, _, 0, 0x0e) => {
|
||||
// JSR1 addr8 (relative)
|
||||
rst.borrow_mut().push2(self.pc)?;
|
||||
let delta = wst.borrow_mut().pop1()? as i8;
|
||||
self.pc = self.pc.wrapping_add(delta as u16);
|
||||
}
|
||||
(_, _, 1, 0x0e) => {
|
||||
// JSR2 addr16 (absolute)
|
||||
rst.borrow_mut().push2(self.pc)?;
|
||||
self.pc = wst.borrow_mut().pop2()?;
|
||||
}
|
||||
(_, _, _, 0x0f) => {
|
||||
// STH a
|
||||
push(rst, pop(wst)?)?;
|
||||
}
|
||||
(_, _, _, 0x10) => {
|
||||
// LDZ a -- b8
|
||||
push(wst.clone(), load(wst.borrow_mut().pop1()? as u16)?)?;
|
||||
}
|
||||
(_, _, _, 0x11) => {
|
||||
// STZ val addr8 --
|
||||
let addr = wst.borrow_mut().pop1()? as u16;
|
||||
store(addr, pop(wst.clone())?)?;
|
||||
}
|
||||
(_, _, _, 0x12) => {
|
||||
// LDR addr8 -- a8
|
||||
let delta = wst.borrow_mut().pop1()? as i8;
|
||||
push(wst.clone(), load(self.pc.wrapping_add(delta as u16))?)?;
|
||||
}
|
||||
(_, _, _, 0x13) => {
|
||||
// STR val8 addr8
|
||||
let delta = wst.borrow_mut().pop1()?;
|
||||
store(self.pc.wrapping_add(delta as u16), pop(wst.clone())?)?;
|
||||
}
|
||||
(_, _, _, 0x14) => {
|
||||
// LDA a16
|
||||
let addr = wst.borrow_mut().pop2()?;
|
||||
push(wst.clone(), load(addr)?)?;
|
||||
}
|
||||
(_, _, _, 0x15) => {
|
||||
// STA val a16 --
|
||||
let addr = wst.borrow_mut().pop2()?;
|
||||
store(addr, pop(wst.clone())?)?;
|
||||
}
|
||||
(_, _, 0, 0x16) => {
|
||||
// DEI port8 -- a8
|
||||
let mut wst = wst.borrow_mut();
|
||||
let port = wst.pop1()?;
|
||||
wst.push1(self.dei1(port))?;
|
||||
}
|
||||
(_, _, 1, 0x16) => {
|
||||
// DEI2 port8 -- a16
|
||||
let mut wst = wst.borrow_mut();
|
||||
let port = wst.pop1()?;
|
||||
wst.push2(self.dei2(port))?;
|
||||
}
|
||||
(_, _, 0, 0x17) => {
|
||||
// DEO1 a8 port8 --
|
||||
let mut wst = wst.borrow_mut();
|
||||
let port = wst.pop1()?;
|
||||
let val = wst.pop1()?;
|
||||
self.deo1(port, val);
|
||||
}
|
||||
(_, _, 1, 0x17) => {
|
||||
// DEO2 a16 port8 --
|
||||
let mut wst = wst.borrow_mut();
|
||||
let port = wst.pop1()?;
|
||||
let val = wst.pop2()?;
|
||||
self.deo2(port, val);
|
||||
}
|
||||
(_, _, _, 0x18) => {
|
||||
// ADD a b -- c
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
push(wst.clone(), a + b)?;
|
||||
}
|
||||
(_, _, _, 0x19) => {
|
||||
// SUB a b -- c
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
push(wst.clone(), a - b)?;
|
||||
}
|
||||
(_, _, _, 0x1a) => {
|
||||
// MUL a b -- c
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
push(wst.clone(), a * b)?;
|
||||
}
|
||||
(_, _, _, 0x1b) => {
|
||||
// DIV a b -- c
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
push(wst.clone(), a / b)?;
|
||||
}
|
||||
(_, _, _, 0x1c) => {
|
||||
// AND a b -- c
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
push(wst.clone(), a & b)?;
|
||||
}
|
||||
(_, _, _, 0x1d) => {
|
||||
// OR a b -- c
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
push(wst.clone(), a | b)?;
|
||||
}
|
||||
(_, _, _, 0x1e) => {
|
||||
// XOR a8 b8 -- c8
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
push(wst.clone(), a ^ b)?;
|
||||
}
|
||||
(_, _, _, 0x1f) => {
|
||||
// SFT a shift8 -- b
|
||||
let shift = wst.borrow_mut().pop1()?;
|
||||
let [left, right] = [shift >> 4, shift & 0xF];
|
||||
let a = pop(wst.clone())?;
|
||||
push(wst.clone(), (a >> right) << left)?;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run(&mut self, limit: u16) -> Result<(), UxnError> {
|
||||
let mut executed = 0;
|
||||
'run: loop {
|
||||
loop {
|
||||
if executed == limit {
|
||||
return Err(UxnError::ExecutionLimit(executed));
|
||||
}
|
||||
|
@ -127,287 +409,10 @@ impl Uxn {
|
|||
|
||||
executed += 1;
|
||||
|
||||
match self.lda1(self.pc) {
|
||||
Err(e) => return Err(UxnError::MemoryError(e)),
|
||||
Ok(opcode) => {
|
||||
// The value of PC is defined to be the value of the NEXT pc ala Mips
|
||||
self.pc += 1;
|
||||
|
||||
// Extract flags
|
||||
let sflag: u8 = opcode & 0x20 >> 5;
|
||||
let rflag: u8 = opcode & 0x40 >> 6;
|
||||
let kflag: u8 = opcode & 0x80 >> 7;
|
||||
let icode: u8 = opcode & 0x1F;
|
||||
|
||||
// Swizzle the stacks as needed
|
||||
let [wst, rst] = {
|
||||
if rflag == 0 {
|
||||
[self.wst.clone(), self.rst.clone()]
|
||||
} else {
|
||||
[self.rst.clone(), self.wst.clone()]
|
||||
}
|
||||
};
|
||||
|
||||
// Some procedural abstractions over load/store sizes
|
||||
let pop = |stack: Rc<RefCell<dyn Stack>>| -> Result<u16, StackError> {
|
||||
if sflag == 1 {
|
||||
stack.borrow_mut().pop2()
|
||||
} else {
|
||||
Ok(stack.borrow_mut().pop1()? as u16)
|
||||
}
|
||||
};
|
||||
|
||||
let push = |stack: Rc<RefCell<dyn Stack>>, val: u16| {
|
||||
if sflag == 1 {
|
||||
stack.borrow_mut().push2(val)
|
||||
} else {
|
||||
stack.borrow_mut().push1(val as u8)
|
||||
}
|
||||
};
|
||||
|
||||
let load = |addr: u16| -> Result<u16, MemoryError> {
|
||||
if sflag == 1 {
|
||||
self.memory.borrow_mut().get2(addr)
|
||||
} else {
|
||||
Ok(self.memory.borrow_mut().get1(addr)? as u16)
|
||||
}
|
||||
};
|
||||
|
||||
let store = |addr: u16, value: u16| {
|
||||
if sflag == 1 {
|
||||
self.memory.borrow_mut().set2(addr, value)
|
||||
} else {
|
||||
self.memory.borrow_mut().set1(addr, value as u8)
|
||||
}
|
||||
};
|
||||
|
||||
// Just bail out of we get a keep flag, haven't figured out an abstraction for that yet.
|
||||
if kflag != 0 {
|
||||
panic!("Got unsupported keep-mode instruction");
|
||||
}
|
||||
|
||||
match (kflag, rflag, sflag, icode) {
|
||||
(0, 0, 0, 0x00) => {
|
||||
// BRK
|
||||
break 'run;
|
||||
}
|
||||
(_, _, _, 0x00) => {
|
||||
// LIT
|
||||
push(wst.clone(), load(self.pc)?)?;
|
||||
self.pc += if sflag == 1 { 2 } else { 1 };
|
||||
}
|
||||
(_, _, _, 0x01) => {
|
||||
// INC
|
||||
push(wst.clone(), pop(wst.clone())? + 1)?;
|
||||
}
|
||||
(_, _, _, 0x02) => {
|
||||
// POP
|
||||
pop(wst)?;
|
||||
}
|
||||
(_, _, _, 0x03) => {
|
||||
// NIP a b -- a
|
||||
let keep = pop(wst.clone())?;
|
||||
pop(wst.clone())?;
|
||||
push(wst.clone(), keep)?;
|
||||
}
|
||||
(_, _, _, 0x04) => {
|
||||
// SWP
|
||||
let a = pop(wst.clone())?;
|
||||
let b = pop(wst.clone())?;
|
||||
push(wst.clone(), b)?;
|
||||
push(wst.clone(), a)?;
|
||||
}
|
||||
(_, _, _, 0x05) => {
|
||||
// ROT
|
||||
let a = pop(wst.clone())?;
|
||||
let b = pop(wst.clone())?;
|
||||
let c = pop(wst.clone())?;
|
||||
push(wst.clone(), b)?;
|
||||
push(wst.clone(), c)?;
|
||||
push(wst.clone(), a)?;
|
||||
}
|
||||
(_, _, _, 0x06) => {
|
||||
// DUP
|
||||
let a = pop(wst.clone())?;
|
||||
push(wst.clone(), a)?;
|
||||
push(wst.clone(), a)?;
|
||||
}
|
||||
(_, _, _, 0x07) => {
|
||||
// OVR a b -- a b a
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
push(wst.clone(), a)?;
|
||||
push(wst.clone(), b)?;
|
||||
push(wst.clone(), a)?;
|
||||
}
|
||||
(_, _, _, 0x08) => {
|
||||
// EQU
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
wst.borrow_mut().push1(if a == b { 1 } else { 0 })?;
|
||||
}
|
||||
(_, _, _, 0x09) => {
|
||||
// NEQ
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
wst.borrow_mut().push1(if a == b { 0 } else { 1 })?;
|
||||
}
|
||||
(_, _, _, 0x0a) => {
|
||||
// GTH a b
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
wst.borrow_mut().push1(if a > b { 1 } else { 0 })?;
|
||||
}
|
||||
(_, _, _, 0x0b) => {
|
||||
// LTH a b
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
wst.borrow_mut().push1(if a < b { 1 } else { 0 })?;
|
||||
}
|
||||
(_, _, _, 0x0c) => {
|
||||
// JMP
|
||||
let delta = wst.borrow_mut().pop1()? as i8;
|
||||
self.pc = self.pc.wrapping_add(delta as u16);
|
||||
}
|
||||
(_, _, 0, 0x0d) => {
|
||||
// JCN1 cnd8 addr8 (relative)
|
||||
let delta = wst.borrow_mut().pop1()? as i8;
|
||||
let cnd = wst.borrow_mut().pop1()?;
|
||||
if cnd != 0 {
|
||||
self.pc = self.pc.wrapping_add(delta as u16);
|
||||
}
|
||||
}
|
||||
(_, _, 2, 0x0d) => {
|
||||
// JCN2 cnd8 addr16 (absolute)
|
||||
let addr = wst.borrow_mut().pop2()?;
|
||||
let cnd = wst.borrow_mut().pop1()?;
|
||||
if cnd != 0 {
|
||||
self.pc = addr;
|
||||
}
|
||||
}
|
||||
(_, _, 0, 0x0e) => {
|
||||
// JSR1 addr8 (relative)
|
||||
rst.borrow_mut().push2(self.pc)?;
|
||||
let delta = wst.borrow_mut().pop1()? as i8;
|
||||
self.pc = self.pc.wrapping_add(delta as u16);
|
||||
}
|
||||
(_, _, 1, 0x0e) => {
|
||||
// JSR2 addr16 (absolute)
|
||||
rst.borrow_mut().push2(self.pc)?;
|
||||
self.pc = wst.borrow_mut().pop2()?;
|
||||
}
|
||||
(_, _, _, 0x0f) => {
|
||||
// STH a
|
||||
push(rst, pop(wst)?)?;
|
||||
}
|
||||
(_, _, _, 0x10) => {
|
||||
// LDZ a -- b8
|
||||
push(wst.clone(), load(wst.borrow_mut().pop1()? as u16)?)?;
|
||||
}
|
||||
(_, _, _, 0x11) => {
|
||||
// STZ val addr8 --
|
||||
let addr = wst.borrow_mut().pop1()? as u16;
|
||||
store(addr, pop(wst.clone())?)?;
|
||||
}
|
||||
(_, _, _, 0x12) => {
|
||||
// LDR addr8 -- a8
|
||||
let delta = wst.borrow_mut().pop1()? as i8;
|
||||
push(wst.clone(), load(self.pc.wrapping_add(delta as u16))?)?;
|
||||
}
|
||||
(_, _, _, 0x13) => {
|
||||
// STR val8 addr8
|
||||
let delta = wst.borrow_mut().pop1()?;
|
||||
store(self.pc.wrapping_add(delta as u16), pop(wst.clone())?)?;
|
||||
}
|
||||
(_, _, _, 0x14) => {
|
||||
// LDA a16
|
||||
let addr = wst.borrow_mut().pop2()?;
|
||||
push(wst.clone(), load(addr)?)?;
|
||||
}
|
||||
(_, _, _, 0x15) => {
|
||||
// STA val a16 --
|
||||
let addr = wst.borrow_mut().pop2()?;
|
||||
store(addr, pop(wst.clone())?)?;
|
||||
}
|
||||
(_, _, 0, 0x16) => {
|
||||
// DEI port8 -- a8
|
||||
let mut wst = wst.borrow_mut();
|
||||
let port = wst.pop1()?;
|
||||
wst.push1(self.dei1(port))?;
|
||||
}
|
||||
(_, _, 1, 0x16) => {
|
||||
// DEI2 port8 -- a16
|
||||
let mut wst = wst.borrow_mut();
|
||||
let port = wst.pop1()?;
|
||||
wst.push2(self.dei2(port))?;
|
||||
}
|
||||
(_, _, 0, 0x17) => {
|
||||
// DEO1 a8 port8 --
|
||||
let mut wst = wst.borrow_mut();
|
||||
let port = wst.pop1()?;
|
||||
let val = wst.pop1()?;
|
||||
self.deo1(port, val);
|
||||
}
|
||||
(_, _, 1, 0x17) => {
|
||||
// DEO2 a16 port8 --
|
||||
let mut wst = wst.borrow_mut();
|
||||
let port = wst.pop1()?;
|
||||
let val = wst.pop2()?;
|
||||
self.deo2(port, val);
|
||||
}
|
||||
(_, _, _, 0x18) => {
|
||||
// ADD a b -- c
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
push(wst.clone(), a + b)?;
|
||||
}
|
||||
(_, _, _, 0x19) => {
|
||||
// SUB a b -- c
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
push(wst.clone(), a - b)?;
|
||||
}
|
||||
(_, _, _, 0x1a) => {
|
||||
// MUL a b -- c
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
push(wst.clone(), a * b)?;
|
||||
}
|
||||
(_, _, _, 0x1b) => {
|
||||
// DIV a b -- c
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
push(wst.clone(), a / b)?;
|
||||
}
|
||||
(_, _, _, 0x1c) => {
|
||||
// AND a b -- c
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
push(wst.clone(), a & b)?;
|
||||
}
|
||||
(_, _, _, 0x1d) => {
|
||||
// OR a b -- c
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
push(wst.clone(), a | b)?;
|
||||
}
|
||||
(_, _, _, 0x1e) => {
|
||||
// XOR a8 b8 -- c8
|
||||
let b = pop(wst.clone())?;
|
||||
let a = pop(wst.clone())?;
|
||||
push(wst.clone(), a ^ b)?;
|
||||
}
|
||||
(_, _, _, 0x1f) => {
|
||||
// SFT a shift8 -- b
|
||||
let shift = wst.borrow_mut().pop1()?;
|
||||
let [left, right] = [shift >> 4, shift & 0xF];
|
||||
let a = pop(wst.clone())?;
|
||||
push(wst.clone(), (a >> right) << left)?;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
match self.step() {
|
||||
Err(e) => return Err(e),
|
||||
Ok(()) => continue,
|
||||
};
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue