On 06/29/2017 05:40 PM, Pranith Kumar wrote:
void aarch64_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr)
{
tcg_insn_unit *code_ptr = (tcg_insn_unit *)jmp_addr;
- tcg_insn_unit *target = (tcg_insn_unit *)addr;
+ tcg_insn_unit i1, i2;
+ uint64_t pair;
+ ptrdiff_t offset = addr - jmp_addr;
+
+ if (offset == sextract64(offset, 0, 26)) {
+ i1 = NOP;
+ i2 = I3206_B | ((offset >> 2) & 0x3ffffff);
Branch first, since that's the offset you calculated.
Also, the nop need not be executed.
+ } else {
+ offset = (addr >> 12) - (jmp_addr >> 12);
+
+ /* patch ADRP */
+ i2 = deposit32(*code_ptr++, 29, 2, offset & 0x3);
+ i2 = deposit32(i2, 5, 19, offset >> 2);
+ /* patch ADDI */
+ i1 = deposit32(*code_ptr, 10, 12, addr & 0xfff);
You can't just patch these insns, because they aren't necessarily ADRP+ADD.
Indeed, they will very likely be B and NOP. The first address we patch in is
tb_jmp_reset_offset, which is the following opcode, which is definitely in
range of the branch above.
r~