//---------------------------------------------------------------------------// // 1100101 |_ mov #0, r4 __ // // 11 |_ <0xb380 %5c4> / _|_ _____ ___ // // 0110 |_ 3.50 -> 3.60 | _\ \ / _ (_-< // // |_ base# + offset |_| /_\_\___/__/ // //---------------------------------------------------------------------------// #include #include namespace FxOS { PcrelPass::PcrelPass(Disassembly &disasm): InstructionPass(disasm) { } bool PcrelPass::analyzeInstruction(uint32_t pc, Instruction &ci) { AsmInstruction const *i = ci.inst; if(!i) return true; for(size_t n = 0; n < i->arg_count; n++) { AsmArgument const &arg = i->args[n]; Argument &a = ci.args[n]; if(arg.kind == AsmArgument::PcRel && (i->opsize == 2 || i->opsize == 4)) { uint32_t addr = (pc & ~(arg.opsize - 1)) + 4 + arg.disp; a.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. */ VirtualSpace &space = m_disasm.vspace; uint32_t v = -1; 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); } else if(arg.kind == AsmArgument::PcAddr) { uint32_t addr = (pc & ~3) + 4 + arg.disp; /* 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; a.location = RelConstDomain().constant(addr); a.value = RelConstDomain().constant(addr); } } return true; } } /* namespace FxOS */