use crate::recompiler::decoder::DecodedInstruction;
use crate::recompiler::ir::instruction::{IRInstruction, IRFunction, IRBasicBlock, Address, Condition};
use anyhow::Result;
use smallvec::SmallVec;
pub struct IRBuilder;
impl IRBuilder {
#[inline] pub fn build_ir(
instructions: &[DecodedInstruction],
function_name: &str,
function_address: u32,
) -> Result<IRFunction> {
let mut basic_blocks: Vec<IRBasicBlock> = Vec::new();
let mut current_block: IRBasicBlock = IRBasicBlock {
id: 0u32,
instructions: Vec::new(),
successors: SmallVec::new(),
};
let mut block_id: u32 = 0u32;
for inst in instructions.iter() {
match Self::convert_instruction(inst)? {
Some(ir_inst) => {
current_block.instructions.push(ir_inst);
}
None => {
}
}
}
if !current_block.instructions.is_empty() {
basic_blocks.push(current_block);
}
Ok(IRFunction {
name: function_name.to_string(),
address: function_address,
parameters: SmallVec::new(), return_register: None,
basic_blocks,
})
}
#[inline] fn convert_instruction(inst: &DecodedInstruction) -> Result<Option<IRInstruction>> {
match inst.instruction.instruction_type {
crate::recompiler::decoder::InstructionType::Arithmetic => {
Self::convert_arithmetic(inst)
}
crate::recompiler::decoder::InstructionType::Load => {
Self::convert_load(inst)
}
crate::recompiler::decoder::InstructionType::Store => {
Self::convert_store(inst)
}
crate::recompiler::decoder::InstructionType::Branch => {
Self::convert_branch(inst)
}
_ => Ok(None),
}
}
#[inline] fn convert_arithmetic(inst: &DecodedInstruction) -> Result<Option<IRInstruction>> {
if inst.instruction.operands.len() < 3usize {
return Ok(None);
}
let dst: u8 = if let Some(crate::recompiler::decoder::Operand::Register(reg)) = inst.instruction.operands.get(0usize) {
*reg
} else {
return Ok(None);
};
let src1: u8 = if let Some(crate::recompiler::decoder::Operand::Register(reg)) = inst.instruction.operands.get(1usize) {
*reg
} else {
return Ok(None);
};
let src2: u8 = if let Some(crate::recompiler::decoder::Operand::Register(reg)) = inst.instruction.operands.get(2usize) {
*reg
} else {
return Ok(None);
};
Ok(Some(IRInstruction::Add {
dst,
src1,
src2,
}))
}
#[inline] fn convert_load(inst: &DecodedInstruction) -> Result<Option<IRInstruction>> {
Ok(None)
}
#[inline] fn convert_store(inst: &DecodedInstruction) -> Result<Option<IRInstruction>> {
Ok(None)
}
#[inline] fn convert_branch(inst: &DecodedInstruction) -> Result<Option<IRInstruction>> {
Ok(None)
}
}