use crate::modeling::machine::cpu::concrete::ConcretePcodeAddress;
use jingle_sleigh::PcodeOperation;
use jingle_sleigh::context::loaded::LoadedSleighContext;
use std::borrow::{Borrow, Cow};
pub struct PcodeOpRef<'a>(std::borrow::Cow<'a, PcodeOperation>);
impl<'a> AsRef<PcodeOperation> for PcodeOpRef<'a> {
fn as_ref(&self) -> &PcodeOperation {
self.0.as_ref()
}
}
impl<'a> std::ops::Deref for PcodeOpRef<'a> {
type Target = PcodeOperation;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<'a> From<PcodeOperation> for PcodeOpRef<'a> {
fn from(op: PcodeOperation) -> Self {
PcodeOpRef(Cow::Owned(op))
}
}
impl<'a> From<&'a PcodeOperation> for PcodeOpRef<'a> {
fn from(op: &'a PcodeOperation) -> Self {
PcodeOpRef(Cow::Borrowed(op))
}
}
pub trait PcodeStore {
fn get_pcode_op_at<'a, T: Borrow<ConcretePcodeAddress>>(
&'a self,
addr: T,
) -> Option<PcodeOpRef<'a>>;
}
pub trait EntryPoint {
fn get_entry(&self) -> ConcretePcodeAddress;
}
impl<'a> PcodeStore for LoadedSleighContext<'a> {
fn get_pcode_op_at<'b, T: Borrow<ConcretePcodeAddress>>(
&'b self,
addr: T,
) -> Option<PcodeOpRef<'b>> {
let addr = addr.borrow();
let instr = self.instruction_at(addr.machine())?;
instr
.ops
.get(addr.pcode() as usize)
.cloned()
.map(PcodeOpRef::from)
}
}
impl<T: PcodeStore + ?Sized> PcodeStore for &T {
fn get_pcode_op_at<'a, B: Borrow<ConcretePcodeAddress>>(
&'a self,
addr: B,
) -> Option<PcodeOpRef<'a>> {
(*self).get_pcode_op_at(addr)
}
}