struct Processor {
stack_a: Vec<u16>,
stack_b: Vec<u16>,
pub memory: [u16;1024],
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;
if !conditional || self.carry {
let address = self.stack_a.pop().expect("End of stack");
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 mut 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().expect("End of stack");
let b = stack.pop().expect("End of stack");
stack.push(a);
stack.push(b);
}
1 => { //clone top
let a = stack.pop().expect("End of stack");
stack.push(a);
stack.push(a);
}
2 => { //clone second
let a = stack.pop().expect("End of stack");
let b = stack.pop().expect("End of stack");
stack.push(b);
stack.push(a);
stack.push(b);
}
3 => { //move between stacks
if toggle {self.stack_a.push(self.stack_b.pop().expect("End of stack"));}
else {self.stack_b.push(self.stack_a.pop().expect("End of stack"));};
}
4 => { //push/pop
let addr = self.stack_a.pop().expect("End of stack") as usize;
if toggle {
let value = self.stack_a.pop().expect("End of stack");
self.memory[addr] = value;
}
else {self.stack_a.push(self.memory[addr]);};
}
5 => { //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().expect("End of stack");
let operand_b = stack.pop().expect("End of stack");
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
}