struct Processor { stack_a: Vec<u16>, stack_b: Vec<u16>, pub memory: Vec<u16>, carry: bool, pub pc: u16 //program counter } impl Processor { pub fn run(&mut self) { let instruction = self.memory[self.pc as usize]; let mut is_jump = false; match instruction & 0x300 { 0x000 => self.carry = calc(&mut self.stack_a, instruction, self.carry), 0x100 => self.carry = calc(&mut self.stack_a, instruction, self.carry), 0x200 => self.stack_a.push(instruction & 0xFF), 0x300 => { if (instruction & 0x80) != 0 { let conditional = (instruction & 0x40) != 0; let relative = (instruction & 0x20) != 0; let save_pc = (instruction & 0x10) != 0; let long_address = (instruction & 0x8) != 0; if !conditional || self.carry { let address; if long_address {address = self.stack_a.pop().unwrap_or(0) | (self.stack_a.pop().unwrap_or(0) << 10)} //lower value on stack is high half of long address else {address = self.stack_a.pop().unwrap_or(0)}; if save_pc {self.stack_a.push(self.pc+1)}; if relative {self.pc += address} else {self.pc = address}; is_jump = true; } } else { let toggle = (instruction & 0x40) != 0; let stack; if toggle {stack = &mut self.stack_b;} else {stack = &mut self.stack_a;}; match instruction & 0x3F { 0 => { //swap top 2 let a = stack.pop().unwrap_or(0); let b = stack.pop().unwrap_or(0); stack.push(a); stack.push(b); } 1 => { //clone top let a = stack.pop().unwrap_or(0); stack.push(a); stack.push(a); } 2 => { //clone second let a = stack.pop().unwrap_or(0); let b = stack.pop().unwrap_or(0); stack.push(b); stack.push(a); stack.push(b); } 3 => { //move between stacks if toggle {self.stack_a.push(self.stack_b.pop().unwrap_or(0));} else {self.stack_b.push(self.stack_a.pop().unwrap_or(0));}; } 4 => { //push/pop let addr = self.stack_a.pop().unwrap_or(0) as usize; if toggle { let value = self.stack_a.pop().unwrap_or(0); self.memory[addr] = value; } else {self.stack_a.push(self.memory[addr])}; } 5 => { //long addr push/pop let addr = (self.stack_a.pop().unwrap_or(0) | (self.stack_a.pop().unwrap_or(0) << 10)) as usize; if toggle { let value = self.stack_a.pop().unwrap_or(0); self.memory[addr] = value; } else {self.stack_a.push(self.memory[addr])}; } 6 => { //set/clear carry self.carry = toggle; } _ => () } } } _ => unreachable!() } if !is_jump {self.pc += 1}; } } fn calc(stack: &mut Vec::<u16>, instruction: u16, carry_in: bool) -> bool { let operand_a = stack.pop().unwrap_or(0); let operand_b = stack.pop().unwrap_or(0); let mut carry = carry_in; let mut result = 0; for i in 0..10 { let bit = 1 << i; let count = ((operand_a & bit) >> i) + ((operand_b & bit) >> i) + carry as u16; result += ((instruction & (1<<(count+4))) >> count) << i; carry = (instruction & (1<<count)) != 0; } stack.push(result); carry }