|
|
|
@ -2,7 +2,7 @@ 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}; |
|
|
|
|
use asm::data::literal::{Value, is_positive, is_negative, Addr}; |
|
|
|
|
|
|
|
|
|
pub type CyclesSpent = usize; |
|
|
|
|
|
|
|
|
@ -40,21 +40,73 @@ impl RunThread { |
|
|
|
|
msg: msg.clone().unwrap_or_else(|| "No msg".into()) |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
Op::FarJump(_) => unimplemented!(), |
|
|
|
|
Op::Call(_, _) => unimplemented!(), |
|
|
|
|
Op::Ret(_) => unimplemented!(), |
|
|
|
|
Op::FarJump(name) => { |
|
|
|
|
debug!("Far jump to {}", name); |
|
|
|
|
match self.program.find_far_label(name) { |
|
|
|
|
Ok(pos) => { |
|
|
|
|
debug!("label is at {}", pos); |
|
|
|
|
self.frame.pc = pos; |
|
|
|
|
} |
|
|
|
|
Err(e) => { |
|
|
|
|
return Err(e); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
Op::Call(name, args) => { |
|
|
|
|
debug!("Call routine {}", name); |
|
|
|
|
match self.program.find_routine(name) { |
|
|
|
|
Ok(pos) => { |
|
|
|
|
debug!("routine is at {}", pos); |
|
|
|
|
|
|
|
|
|
let mut values = Vec::with_capacity(args.len()); |
|
|
|
|
for arg in args { |
|
|
|
|
values.push(self.frame.read(*arg)?); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let mut frame2 = StackFrame::new(pos, &values); |
|
|
|
|
std::mem::swap(&mut self.frame, &mut frame2); |
|
|
|
|
self.call_stack.push(frame2); |
|
|
|
|
advance = 0; |
|
|
|
|
} |
|
|
|
|
Err(e) => { |
|
|
|
|
return Err(e); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
Op::Ret(retvals) => { |
|
|
|
|
match self.call_stack.pop() { |
|
|
|
|
Some(previous) => { |
|
|
|
|
let mut values = Vec::with_capacity(retvals.len()); |
|
|
|
|
for arg in retvals { |
|
|
|
|
values.push(frame.read(*arg)?); |
|
|
|
|
} |
|
|
|
|
*frame = previous; |
|
|
|
|
frame.set_retvals(&values); |
|
|
|
|
advance = 1; // advance past the call
|
|
|
|
|
} |
|
|
|
|
None => { |
|
|
|
|
return Err(Fault::CallStackUnderflow); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
Op::Skip(val) => { |
|
|
|
|
let steps = frame.read(*val)?; |
|
|
|
|
advance = i64::from_ne_bytes(steps.to_ne_bytes()); |
|
|
|
|
self.program.validate_jump(frame.pc, Addr((frame.pc.0 as i64 + advance) as u64))?; |
|
|
|
|
} |
|
|
|
|
Op::SkipIf(cond, val) => { |
|
|
|
|
if frame.status.test(*cond) { |
|
|
|
|
let steps = frame.read(*val)?; |
|
|
|
|
advance = i64::from_ne_bytes(steps.to_ne_bytes()); |
|
|
|
|
self.program.validate_jump(frame.pc, Addr((frame.pc.0 as i64 + advance) as u64))?; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
Op::Mov(dst, src) => { |
|
|
|
|
frame.status.clear(); |
|
|
|
|
let val = frame.read(*src)?; |
|
|
|
|
frame.status.zero = (val == 0); |
|
|
|
|
frame.status.positive = is_positive(val); |
|
|
|
|
frame.status.negative = is_negative(val); |
|
|
|
|
frame.write(*dst, val)?; |
|
|
|
|
} |
|
|
|
|
Op::Cmp(a, b) => { |
|
|
|
@ -88,6 +140,68 @@ impl RunThread { |
|
|
|
|
frame.status.negative = is_negative(val); |
|
|
|
|
frame.write(*reg, val)?; |
|
|
|
|
} |
|
|
|
|
Op::Add(dst, src) => { |
|
|
|
|
frame.status.clear(); |
|
|
|
|
let mut a = frame.read(dst.as_rd())?; |
|
|
|
|
let mut b = frame.read(*src)?; |
|
|
|
|
|
|
|
|
|
let val = a.wrapping_add(b); |
|
|
|
|
frame.status.zero = (val == 0); |
|
|
|
|
frame.status.positive = is_positive(val); |
|
|
|
|
frame.status.negative = is_negative(val); |
|
|
|
|
frame.status.overflow = b > Value::MAX - a; // TODO check
|
|
|
|
|
// TODO carry?
|
|
|
|
|
frame.write(*dst, val)?; |
|
|
|
|
} |
|
|
|
|
Op::Sub(dst, src) => { |
|
|
|
|
frame.status.clear(); |
|
|
|
|
let mut a = frame.read(dst.as_rd())?; |
|
|
|
|
let mut b = frame.read(*src)?; |
|
|
|
|
|
|
|
|
|
let val = a.wrapping_sub(b); |
|
|
|
|
frame.status.zero = (val == 0); |
|
|
|
|
frame.status.positive = is_positive(val); |
|
|
|
|
frame.status.negative = is_negative(val); |
|
|
|
|
frame.status.overflow = b > a; |
|
|
|
|
// TODO carry?
|
|
|
|
|
frame.write(*dst, val)?; |
|
|
|
|
} |
|
|
|
|
Op::Mul(_, _) => { |
|
|
|
|
unimplemented!() |
|
|
|
|
} |
|
|
|
|
Op::Div(_, _) => { |
|
|
|
|
unimplemented!() |
|
|
|
|
} |
|
|
|
|
Op::Mod(_, _, _) => { |
|
|
|
|
unimplemented!() |
|
|
|
|
} |
|
|
|
|
Op::And(_, _) => { |
|
|
|
|
unimplemented!() |
|
|
|
|
} |
|
|
|
|
Op::Or(_, _) => { |
|
|
|
|
unimplemented!() |
|
|
|
|
} |
|
|
|
|
Op::Xor(_, _) => { |
|
|
|
|
unimplemented!() |
|
|
|
|
} |
|
|
|
|
Op::Cpl(_) => { |
|
|
|
|
unimplemented!() |
|
|
|
|
} |
|
|
|
|
Op::Rol(_, _) => { |
|
|
|
|
unimplemented!() |
|
|
|
|
} |
|
|
|
|
Op::Ror(_, _) => { |
|
|
|
|
unimplemented!() |
|
|
|
|
} |
|
|
|
|
Op::Lsl(_, _) => { |
|
|
|
|
unimplemented!() |
|
|
|
|
} |
|
|
|
|
Op::Lsr(_, _) => { |
|
|
|
|
unimplemented!() |
|
|
|
|
} |
|
|
|
|
Op::Asr(_, _) => { |
|
|
|
|
unimplemented!() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Ok(EvalRes { |
|
|
|
|