//--- // fxos.passes.pcrel: Resolution of PC-relative addresses //--- #include namespace FxOS { PcrelPass::PcrelPass(Disassembly &disasm): InstructionDisassemblyPass(disasm, "pcrel") { } void PcrelPass::analyze(uint32_t pc, ConcreteInstruction &ci) { Instruction const *i = ci.inst; if(!i) return; for(size_t n = 0; n < i->arg_count; n++) { Argument const &a = i->args[n]; ConcreteInstructionArg &ca = ci.args[n]; if(a.kind == Argument::PcRel && (i->opsize == 2 || i->opsize == 4)) { uint32_t addr = (pc & ~(a.opsize - 1)) + 4 + a.disp; ca.location = RelConstDomain().constant(addr); /* Also compute the value. This is sign-extended from 16-bit with mov.w. There is no mov.b for this instruction. */ Target &t = m_disasm.target(); uint32_t v = -1; if(i->opsize == 2) v = t.read_i16(addr); if(i->opsize == 4) v = t.read_i32(addr); ca.value = DataValue(IntegerType::u32); ca.value.write(0, 4, v); } else if(a.kind == Argument::PcJump) { uint32_t addr = pc + 4 + a.disp; ca.location = RelConstDomain().constant(addr); ca.value = DataValue(IntegerType::u32); ca.value.write(0, 4, addr); } else if(a.kind == Argument::PcAddr && m_disasm.passes.count("cfg")) { uint32_t addr = (pc & ~3) + 4 + a.disp; /* SH3 manual says that the semantics of mova change in a delay slot. GNU as: "yeah but sorry they don't" */ // if(ci.delayslot) addr = (ci.jmptarget&~3) + 4 + a.disp; ca.location = RelConstDomain().constant(addr); ca.value = DataValue(IntegerType::u32); ca.value.write(0, 4, addr); } } } } /* namespace FxOS */