diff options
Diffstat (limited to 'tcg/ppc/tcg-target.inc.c')
| -rw-r--r-- | tcg/ppc/tcg-target.inc.c | 60 |
1 files changed, 30 insertions, 30 deletions
diff --git a/tcg/ppc/tcg-target.inc.c b/tcg/ppc/tcg-target.inc.c index c2f729ee8f..8c1cfdd7ac 100644 --- a/tcg/ppc/tcg-target.inc.c +++ b/tcg/ppc/tcg-target.inc.c @@ -193,9 +193,14 @@ static uint32_t reloc_pc24_val(tcg_insn_unit *pc, tcg_insn_unit *target) return disp & 0x3fffffc; } -static void reloc_pc24(tcg_insn_unit *pc, tcg_insn_unit *target) +static bool reloc_pc24(tcg_insn_unit *pc, tcg_insn_unit *target) { - *pc = (*pc & ~0x3fffffc) | reloc_pc24_val(pc, target); + ptrdiff_t disp = tcg_ptr_byte_diff(target, pc); + if (in_range_b(disp)) { + *pc = (*pc & ~0x3fffffc) | (disp & 0x3fffffc); + return true; + } + return false; } static uint16_t reloc_pc14_val(tcg_insn_unit *pc, tcg_insn_unit *target) @@ -205,21 +210,14 @@ static uint16_t reloc_pc14_val(tcg_insn_unit *pc, tcg_insn_unit *target) return disp & 0xfffc; } -static void reloc_pc14(tcg_insn_unit *pc, tcg_insn_unit *target) +static bool reloc_pc14(tcg_insn_unit *pc, tcg_insn_unit *target) { - *pc = (*pc & ~0xfffc) | reloc_pc14_val(pc, target); -} - -static inline void tcg_out_b_noaddr(TCGContext *s, int insn) -{ - unsigned retrans = *s->code_ptr & 0x3fffffc; - tcg_out32(s, insn | retrans); -} - -static inline void tcg_out_bc_noaddr(TCGContext *s, int insn) -{ - unsigned retrans = *s->code_ptr & 0xfffc; - tcg_out32(s, insn | retrans); + ptrdiff_t disp = tcg_ptr_byte_diff(target, pc); + if (disp == (int16_t) disp) { + *pc = (*pc & ~0xfffc) | (disp & 0xfffc); + return true; + } + return false; } /* parse target specific constraints */ @@ -525,7 +523,7 @@ static const uint32_t tcg_to_isel[] = { [TCG_COND_GTU] = ISEL | BC_(7, CR_GT), }; -static void patch_reloc(tcg_insn_unit *code_ptr, int type, +static bool patch_reloc(tcg_insn_unit *code_ptr, int type, intptr_t value, intptr_t addend) { tcg_insn_unit *target; @@ -536,11 +534,9 @@ static void patch_reloc(tcg_insn_unit *code_ptr, int type, switch (type) { case R_PPC_REL14: - reloc_pc14(code_ptr, target); - break; + return reloc_pc14(code_ptr, target); case R_PPC_REL24: - reloc_pc24(code_ptr, target); - break; + return reloc_pc24(code_ptr, target); case R_PPC_ADDR16: /* We are abusing this relocation type. This points to a pair of insns, addis + load. If the displacement is small, we @@ -552,7 +548,9 @@ static void patch_reloc(tcg_insn_unit *code_ptr, int type, } else { int16_t lo = value; int hi = value - lo; - assert(hi + lo == value); + if (hi + lo != value) { + return false; + } code_ptr[0] = deposit32(code_ptr[0], 0, 16, hi >> 16); code_ptr[1] = deposit32(code_ptr[1], 0, 16, lo); } @@ -560,6 +558,7 @@ static void patch_reloc(tcg_insn_unit *code_ptr, int type, default: g_assert_not_reached(); } + return true; } static void tcg_out_mem_long(TCGContext *s, int opi, int opx, TCGReg rt, @@ -1179,11 +1178,11 @@ static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond, static void tcg_out_bc(TCGContext *s, int bc, TCGLabel *l) { if (l->has_value) { - tcg_out32(s, bc | reloc_pc14_val(s->code_ptr, l->u.value_ptr)); + bc |= reloc_pc14_val(s->code_ptr, l->u.value_ptr); } else { tcg_out_reloc(s, s->code_ptr, R_PPC_REL14, l, 0); - tcg_out_bc_noaddr(s, bc); } + tcg_out32(s, bc); } static void tcg_out_brcond(TCGContext *s, TCGCond cond, @@ -1649,7 +1648,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) TCGMemOp opc = get_memop(oi); TCGReg hi, lo, arg = TCG_REG_R3; - reloc_pc14(lb->label_ptr[0], s->code_ptr); + **lb->label_ptr |= reloc_pc14_val(*lb->label_ptr, s->code_ptr); tcg_out_mov(s, TCG_TYPE_PTR, arg++, TCG_AREG0); @@ -1694,7 +1693,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) TCGMemOp s_bits = opc & MO_SIZE; TCGReg hi, lo, arg = TCG_REG_R3; - reloc_pc14(lb->label_ptr[0], s->code_ptr); + **lb->label_ptr |= reloc_pc14_val(*lb->label_ptr, s->code_ptr); tcg_out_mov(s, TCG_TYPE_PTR, arg++, TCG_AREG0); @@ -1771,7 +1770,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64) /* Load a pointer into the current opcode w/conditional branch-link. */ label_ptr = s->code_ptr; - tcg_out_bc_noaddr(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK); + tcg_out32(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK); rbase = TCG_REG_R3; #else /* !CONFIG_SOFTMMU */ @@ -1846,7 +1845,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64) /* Load a pointer into the current opcode w/conditional branch-link. */ label_ptr = s->code_ptr; - tcg_out_bc_noaddr(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK); + tcg_out32(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK); rbase = TCG_REG_R3; #else /* !CONFIG_SOFTMMU */ @@ -2044,13 +2043,14 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, case INDEX_op_br: { TCGLabel *l = arg_label(args[0]); + uint32_t insn = B; if (l->has_value) { - tcg_out_b(s, 0, l->u.value_ptr); + insn |= reloc_pc24_val(s->code_ptr, l->u.value_ptr); } else { tcg_out_reloc(s, s->code_ptr, R_PPC_REL24, l, 0); - tcg_out_b_noaddr(s, B); } + tcg_out32(s, insn); } break; case INDEX_op_ld8u_i32: |