use std::any::{Any, TypeId}; use std::collections::HashMap; use crate::asm::data::{DstDisp, Rd, Register, SrcDisp, Wr}; use crate::asm::data::literal::{Addr, Value}; use crate::asm::instr::op::EvalRes; use crate::runtime::fault::Fault; use crate::runtime::frame::{CallStack, REG_COUNT, StackFrame}; use crate::runtime::program::Program; use crate::asm::instr::Cond; use crate::runtime::frame::status::StatusFlags; pub struct RunState { /// Active stack frame pub frame: StackFrame, /// Call stack pub call_stack: CallStack, /// Extension data pub ext_data: HashMap>, } impl RunState { pub fn ext_mut(&mut self) -> &mut T { if !self.ext_data.contains_key(&TypeId::of::()) { self.ext_data.insert(TypeId::of::(), Box::new(T::default())); } self.ext_data.get_mut(&TypeId::of::()).unwrap() .downcast_mut().unwrap() } pub fn set_flag(&mut self, cond : Cond, set : bool) { if set { self.frame.status.set(cond); } } pub fn test_cond(&self, cond : Cond) -> bool { self.frame.status.test(cond) } pub fn set_pc(&mut self, pc: Addr) { self.frame.pc = pc; } pub fn get_pc(&self) -> Addr { self.frame.pc } pub fn clear_status(&mut self) { self.frame.status.clear(); } pub fn update_status(&mut self, val: Value) { self.frame.status.update(val); } pub fn read(&mut self, rd: Rd) -> Result { match rd.d() { SrcDisp::Immediate(v) => Ok(v), SrcDisp::Register(Register::Res(rn)) => { if rn >= REG_COUNT as u8 { Err(Fault::RegisterNotExist { reg: Register::Res(rn) }) // TODO use match after @ when stabilized https://github.com/rust-lang/rust/issues/65490 } else { trace!("Rd {:?} = {}", rd, self.frame.res[rn as usize]); Ok(self.frame.res[rn as usize]) } } SrcDisp::Register(Register::Arg(rn)) => { if rn >= REG_COUNT as u8 { Err(Fault::RegisterNotExist { reg: Register::Arg(rn) }) } else { trace!("Rd {:?} = {}", rd, self.frame.arg[rn as usize]); Ok(self.frame.arg[rn as usize]) } } SrcDisp::Register(Register::Gen(rn)) => { if rn >= REG_COUNT as u8 { Err(Fault::RegisterNotExist { reg: Register::Gen(rn) }) } else { trace!("Rd {:?} = {}", rd, self.frame.gen[rn as usize]); Ok(self.frame.gen[rn as usize]) } } SrcDisp::ObjectPtr(_) => { unimplemented!("Read object ptr") } } } pub fn write(&mut self, wr: Wr, val: Value) -> Result<(), Fault> { trace!("WR {:?} := {}", wr, val); match wr.d() { DstDisp::Discard => { /* Discard */ Ok(()) } DstDisp::Register(Register::Res(rn)) => { if rn >= REG_COUNT as u8 { Err(Fault::RegisterNotExist { reg: Register::Res(rn) }) // TODO use match after @ when stabilized https://github.com/rust-lang/rust/issues/65490 } else { Err(Fault::RegisterNotWritable { reg: Register::Res(rn) }) } } DstDisp::Register(Register::Arg(rn)) => { if rn >= REG_COUNT as u8 { Err(Fault::RegisterNotExist { reg: Register::Arg(rn) }) } else { Err(Fault::RegisterNotWritable { reg: Register::Res(rn) }) } } DstDisp::Register(Register::Gen(rn)) => { if rn >= REG_COUNT as u8 { Err(Fault::RegisterNotExist { reg: Register::Gen(rn) }) } else { self.frame.gen[rn as usize] = val; Ok(()) } } DstDisp::ObjectPtr(_) => { unimplemented!("Write object ptr") } } } }