use crate::run_thread::{ThreadToken, RunThread}; use asm::instr::{Op, Cond}; use crate::fault::Fault; use crate::frame::StackFrame; use asm::data::literal::{Value, is_positive, is_negative}; pub type CyclesSpent = usize; pub struct EvalRes { pub cycles: u8, pub advance: i64, } impl RunThread { pub fn eval_op(&mut self) -> Result { let mut cycles = 1; let mut advance = 1; let mut frame = &mut self.frame; let op = self.program.read(frame.pc); debug!("{} | {:?}", frame.pc, op); /* Operations can be given different execution times when run in slow mode. */ /* Presently, all that do anything use 1 cycle. */ match op { Op::Nop => {} Op::FarLabel(_) | Op::Routine(_) => { /* this is nop, but without any cost - just markers */ cycles = 0; } Op::Barrier(msg) => { return Err(Fault::Barrier { msg: msg.clone().unwrap_or_else(|| "No msg".into()) }) } Op::Fault(msg) => { return Err(Fault::FaultInstr { msg: msg.clone().unwrap_or_else(|| "No msg".into()) }) } Op::FarJump(_) => unimplemented!(), Op::Call(_, _) => unimplemented!(), Op::Ret(_) => unimplemented!(), Op::Skip(val) => { let steps = frame.read(*val)?; advance = i64::from_ne_bytes(steps.to_ne_bytes()); } Op::SkipIf(cond, val) => { if frame.status.test(*cond) { let steps = frame.read(*val)?; advance = i64::from_ne_bytes(steps.to_ne_bytes()); } } Op::Mov(dst, src) => { let val = frame.read(*src)?; frame.write(*dst, val)?; } Op::Cmp(a, b) => { frame.status.clear(); let a = frame.read(*a)?; let b = frame.read(*b)?; frame.status.equal = a == b; frame.status.zero = a == 0 && b == 0; frame.status.lower = a < b; frame.status.greater = a > b; frame.status.positive = is_positive(a) && is_positive(b); frame.status.negative = is_negative(a) && is_negative(b); } Op::Inc(reg) => { frame.status.clear(); let mut val = frame.read(reg.as_rd())?; val = val.wrapping_add(1); frame.status.overflow = (val == 0); frame.status.zero = (val == 0); frame.status.positive = is_positive(val); frame.status.negative = is_negative(val); frame.write(*reg, val)?; } Op::Dec(reg) => { frame.status.clear(); let mut val = frame.read(reg.as_rd())?; frame.status.overflow = (val == 0); // will overflow val = val.wrapping_sub(1); frame.status.zero = (val == 0); frame.status.positive = is_positive(val); frame.status.negative = is_negative(val); frame.write(*reg, val)?; } } Ok(EvalRes { cycles, advance, }) } }