2022-03-28 21:59:30 +02:00
|
|
|
//---------------------------------------------------------------------------//
|
|
|
|
// 1100101 |_ mov #0, r4 __ //
|
|
|
|
// 11 |_ <0xb380 %5c4> / _|_ _____ ___ //
|
|
|
|
// 0110 |_ 3.50 -> 3.60 | _\ \ / _ (_-< //
|
|
|
|
// |_ base# + offset |_| /_\_\___/__/ //
|
|
|
|
//---------------------------------------------------------------------------//
|
2019-12-28 17:18:13 +01:00
|
|
|
|
2022-03-28 21:59:30 +02:00
|
|
|
#include <fxos/passes/pcrel.h>
|
2022-03-28 23:42:53 +02:00
|
|
|
#include <fxos/vspace.h>
|
2019-12-28 17:18:13 +01:00
|
|
|
|
|
|
|
namespace FxOS {
|
|
|
|
|
2022-04-14 13:30:43 +02:00
|
|
|
PcrelPass::PcrelPass(Disassembly &disasm): InstructionPass(disasm)
|
2019-12-28 17:18:13 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2022-04-05 12:02:56 +02:00
|
|
|
bool PcrelPass::analyzeInstruction(uint32_t pc, Instruction &ci)
|
2019-12-28 17:18:13 +01:00
|
|
|
{
|
2022-03-28 21:59:30 +02:00
|
|
|
AsmInstruction const *i = ci.inst;
|
|
|
|
if(!i)
|
2022-03-28 23:42:53 +02:00
|
|
|
return true;
|
2020-02-12 07:53:00 +01:00
|
|
|
|
2022-03-28 21:59:30 +02:00
|
|
|
for(size_t n = 0; n < i->arg_count; n++) {
|
|
|
|
AsmArgument const &arg = i->args[n];
|
|
|
|
Argument &a = ci.args[n];
|
2020-02-12 07:53:00 +01:00
|
|
|
|
2022-04-14 13:30:43 +02:00
|
|
|
if(arg.kind == AsmArgument::PcRel
|
|
|
|
&& (i->opsize == 2 || i->opsize == 4)) {
|
2022-03-28 21:59:30 +02:00
|
|
|
uint32_t addr = (pc & ~(arg.opsize - 1)) + 4 + arg.disp;
|
|
|
|
a.location = RelConstDomain().constant(addr);
|
2020-02-12 16:33:08 +01:00
|
|
|
|
2022-03-28 21:59:30 +02:00
|
|
|
/* Also compute the value. This is sign-extended from 16-bit with
|
|
|
|
mov.w. There is no mov.b for this instruction. */
|
2022-04-05 15:02:06 +02:00
|
|
|
VirtualSpace &space = m_disasm.vspace;
|
2022-03-28 21:59:30 +02:00
|
|
|
uint32_t v = -1;
|
2020-02-28 16:19:50 +01:00
|
|
|
|
2022-03-28 21:59:30 +02:00
|
|
|
if(i->opsize == 2 && space.covers(addr, 2)) {
|
|
|
|
v = space.read_i16(addr);
|
|
|
|
a.value = RelConstDomain().constant(v);
|
|
|
|
}
|
|
|
|
if(i->opsize == 4 && space.covers(addr, 4)) {
|
|
|
|
v = space.read_i32(addr);
|
|
|
|
a.value = RelConstDomain().constant(v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(arg.kind == AsmArgument::PcJump) {
|
|
|
|
uint32_t addr = pc + 4 + arg.disp;
|
|
|
|
a.location = RelConstDomain().constant(addr);
|
|
|
|
a.value = RelConstDomain().constant(addr);
|
|
|
|
}
|
2022-04-14 13:30:43 +02:00
|
|
|
else if(arg.kind == AsmArgument::PcAddr) {
|
2022-03-28 21:59:30 +02:00
|
|
|
uint32_t addr = (pc & ~3) + 4 + arg.disp;
|
2020-02-15 18:42:14 +01:00
|
|
|
|
2022-03-28 21:59:30 +02:00
|
|
|
/* SH3 manual says that mova uses the target address of the jump
|
|
|
|
when in a delay slot. SH4AL-DSP makes it invalid. */
|
|
|
|
// if(ci.delayslot) addr = (ci.jmptarget & ~3) + 4 + a.disp;
|
2020-02-29 11:22:26 +01:00
|
|
|
|
2022-03-28 21:59:30 +02:00
|
|
|
a.location = RelConstDomain().constant(addr);
|
|
|
|
a.value = RelConstDomain().constant(addr);
|
|
|
|
}
|
|
|
|
}
|
2020-02-29 11:22:26 +01:00
|
|
|
|
2022-03-28 21:59:30 +02:00
|
|
|
return true;
|
2019-12-28 17:18:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
} /* namespace FxOS */
|