2019-12-28 17:18:13 +01:00
|
|
|
//---
|
2020-02-12 07:53:00 +01:00
|
|
|
// fxos.passes.pcrel: Resolution of PC-relative addresses
|
2019-12-28 17:18:13 +01:00
|
|
|
//---
|
|
|
|
|
2020-02-12 07:53:00 +01:00
|
|
|
#include <fxos/disasm-passes/pcrel.h>
|
2019-12-28 17:18:13 +01:00
|
|
|
|
|
|
|
namespace FxOS {
|
|
|
|
|
|
|
|
PcrelPass::PcrelPass(Disassembly &disasm):
|
2020-02-29 11:22:26 +01:00
|
|
|
InstructionDisassemblyPass(disasm, "pcrel")
|
2019-12-28 17:18:13 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void PcrelPass::analyze(uint32_t pc, ConcreteInstruction &ci)
|
|
|
|
{
|
2020-02-29 16:32:25 +01:00
|
|
|
Instruction const *i = ci.inst;
|
|
|
|
if(!i) return;
|
2020-02-12 07:53:00 +01:00
|
|
|
|
2021-03-16 13:29:31 +01:00
|
|
|
for(size_t n = 0; n < i->arg_count; n++)
|
2020-02-12 07:53:00 +01:00
|
|
|
{
|
2020-02-29 16:32:25 +01:00
|
|
|
Argument const &a = i->args[n];
|
2020-02-12 07:53:00 +01:00
|
|
|
ConcreteInstructionArg &ca = ci.args[n];
|
|
|
|
|
2020-02-29 16:32:25 +01:00
|
|
|
if(a.kind == Argument::PcRel &&
|
|
|
|
(i->opsize == 2 || i->opsize == 4))
|
2020-02-12 07:53:00 +01:00
|
|
|
{
|
2020-02-12 16:33:08 +01:00
|
|
|
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();
|
2020-02-28 16:19:50 +01:00
|
|
|
uint32_t v = -1;
|
|
|
|
|
2020-02-29 16:32:25 +01:00
|
|
|
if(i->opsize == 2) v = t.read_i16(addr);
|
|
|
|
if(i->opsize == 4) v = t.read_i32(addr);
|
2020-02-12 16:33:08 +01:00
|
|
|
|
|
|
|
ca.value = DataValue(IntegerType::u32);
|
2020-02-15 18:42:14 +01:00
|
|
|
ca.value.write(0, 4, v);
|
2020-02-12 07:53:00 +01:00
|
|
|
}
|
|
|
|
else if(a.kind == Argument::PcJump)
|
|
|
|
{
|
2020-02-12 16:33:08 +01:00
|
|
|
uint32_t addr = pc + 4 + a.disp;
|
|
|
|
ca.location = RelConstDomain().constant(addr);
|
2020-02-15 18:42:14 +01:00
|
|
|
|
|
|
|
ca.value = DataValue(IntegerType::u32);
|
|
|
|
ca.value.write(0, 4, addr);
|
2020-02-12 07:53:00 +01:00
|
|
|
}
|
2020-02-29 11:22:26 +01:00
|
|
|
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);
|
|
|
|
}
|
2020-02-12 07:53:00 +01:00
|
|
|
}
|
2019-12-28 17:18:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
} /* namespace FxOS */
|