use crate::armv4t::Emulator;
use crate::armv4t::Insn;
use crate::BruteforceSearch;
use crate::Callable;
use crate::StaticAnalysis;
const MODE: armv4t_emu::Mode = armv4t_emu::Mode::User;
trait FitsInRegister {
fn put(&self, emu: &mut Emulator, pos: u8);
fn get(emu: &Emulator, pos: u8) -> Self;
}
impl FitsInRegister for u32 {
fn put(&self, emu: &mut Emulator, pos: u8) {
emu.cpu.reg_set(MODE, pos, *self);
}
fn get(emu: &Emulator, pos: u8) -> Self {
emu.cpu.reg_get(MODE, pos)
}
}
impl FitsInRegister for i32 {
fn put(&self, emu: &mut Emulator, pos: u8) {
emu.cpu.reg_set(MODE, pos, *self as u32);
}
fn get(emu: &Emulator, pos: u8) -> Self {
emu.cpu.reg_get(MODE, pos) as i32
}
}
impl FitsInRegister for f32 {
fn put(&self, emu: &mut Emulator, pos: u8) {
emu.cpu.reg_set(MODE, pos, self.to_bits())
}
fn get(emu: &Emulator, pos: u8) -> Self {
Self::from_bits(emu.cpu.reg_get(MODE, pos))
}
}
pub trait ParameterList {
fn put_list(&self, emu: &mut Emulator);
}
impl<T> ParameterList for T
where
T: FitsInRegister,
{
fn put_list(&self, emu: &mut Emulator) {
self.put(emu, 0);
}
}
pub trait ReturnValue {
fn get_list(emu: &Emulator) -> Self;
}
impl<T> ReturnValue for T
where
T: FitsInRegister,
{
fn get_list(emu: &Emulator) -> Self {
T::get(emu, 0)
}
}
#[derive(Clone, Debug, Default)]
pub struct Function<Params, RetVal> {
seq: crate::Sequence<Insn>,
params: std::marker::PhantomData<Params>,
retval: std::marker::PhantomData<RetVal>,
}
impl<Params: ParameterList, RetVal: ReturnValue> Callable<Params, RetVal>
for Function<Params, RetVal>
{
fn call(&self, input: Params) -> crate::RunResult<RetVal> {
let mut emu = Emulator::init(&input);
emu.call_subroutine(&self.seq)?;
Ok(RetVal::get_list(&emu))
}
}
impl<Params, RetVal> crate::Disassemble for Function<Params, RetVal> {
fn dasm(&self) {
self.seq.dasm()
}
}
impl<Params, RetVal> crate::Goto<Insn> for Function<Params, RetVal> {
fn goto(&mut self, t: &[Insn]) {
self.seq.goto(t);
}
}
impl<Params, RetVal> BruteforceSearch<Insn> for Function<Params, RetVal> {
fn analyze_this(&self) -> Result<(), StaticAnalysis<Insn>> {
crate::subroutine::make_return(&self.seq)?;
Ok(())
}
fn inner(&mut self) -> &mut dyn BruteforceSearch<Insn> {
&mut self.seq
}
}