tcg/ppc: Allow a 32-bit offset to the constant pool
We recently relaxed the limit of the number of opcodes that can appear in a TranslationBlock. In certain cases this has resulted in relocation overflow. Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
4a64e0fd68
commit
030ffe39dd
|
@ -222,33 +222,6 @@ static inline void tcg_out_bc_noaddr(TCGContext *s, int insn)
|
||||||
tcg_out32(s, insn | retrans);
|
tcg_out32(s, insn | retrans);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void patch_reloc(tcg_insn_unit *code_ptr, int type,
|
|
||||||
intptr_t value, intptr_t addend)
|
|
||||||
{
|
|
||||||
tcg_insn_unit *target;
|
|
||||||
tcg_insn_unit old;
|
|
||||||
|
|
||||||
value += addend;
|
|
||||||
target = (tcg_insn_unit *)value;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case R_PPC_REL14:
|
|
||||||
reloc_pc14(code_ptr, target);
|
|
||||||
break;
|
|
||||||
case R_PPC_REL24:
|
|
||||||
reloc_pc24(code_ptr, target);
|
|
||||||
break;
|
|
||||||
case R_PPC_ADDR16:
|
|
||||||
assert(value == (int16_t)value);
|
|
||||||
old = *code_ptr;
|
|
||||||
old = deposit32(old, 0, 16, value);
|
|
||||||
*code_ptr = old;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
tcg_abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parse target specific constraints */
|
/* parse target specific constraints */
|
||||||
static const char *target_parse_constraint(TCGArgConstraint *ct,
|
static const char *target_parse_constraint(TCGArgConstraint *ct,
|
||||||
const char *ct_str, TCGType type)
|
const char *ct_str, TCGType type)
|
||||||
|
@ -552,6 +525,43 @@ static const uint32_t tcg_to_isel[] = {
|
||||||
[TCG_COND_GTU] = ISEL | BC_(7, CR_GT),
|
[TCG_COND_GTU] = ISEL | BC_(7, CR_GT),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||||
|
intptr_t value, intptr_t addend)
|
||||||
|
{
|
||||||
|
tcg_insn_unit *target;
|
||||||
|
tcg_insn_unit old;
|
||||||
|
|
||||||
|
value += addend;
|
||||||
|
target = (tcg_insn_unit *)value;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case R_PPC_REL14:
|
||||||
|
reloc_pc14(code_ptr, target);
|
||||||
|
break;
|
||||||
|
case R_PPC_REL24:
|
||||||
|
reloc_pc24(code_ptr, target);
|
||||||
|
break;
|
||||||
|
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
|
||||||
|
can nop out the addis. */
|
||||||
|
if (value == (int16_t)value) {
|
||||||
|
code_ptr[0] = NOP;
|
||||||
|
old = deposit32(code_ptr[1], 0, 16, value);
|
||||||
|
code_ptr[1] = deposit32(old, 16, 5, TCG_REG_TB);
|
||||||
|
} else {
|
||||||
|
int16_t lo = value;
|
||||||
|
int hi = value - lo;
|
||||||
|
assert(hi + lo == value);
|
||||||
|
code_ptr[0] = deposit32(code_ptr[0], 0, 16, hi >> 16);
|
||||||
|
code_ptr[1] = deposit32(code_ptr[1], 0, 16, lo);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void tcg_out_mem_long(TCGContext *s, int opi, int opx, TCGReg rt,
|
static void tcg_out_mem_long(TCGContext *s, int opi, int opx, TCGReg rt,
|
||||||
TCGReg base, tcg_target_long offset);
|
TCGReg base, tcg_target_long offset);
|
||||||
|
|
||||||
|
@ -690,7 +700,8 @@ static void tcg_out_movi_int(TCGContext *s, TCGType type, TCGReg ret,
|
||||||
if (!in_prologue && USE_REG_TB) {
|
if (!in_prologue && USE_REG_TB) {
|
||||||
new_pool_label(s, arg, R_PPC_ADDR16, s->code_ptr,
|
new_pool_label(s, arg, R_PPC_ADDR16, s->code_ptr,
|
||||||
-(intptr_t)s->code_gen_ptr);
|
-(intptr_t)s->code_gen_ptr);
|
||||||
tcg_out32(s, LD | TAI(ret, TCG_REG_TB, 0));
|
tcg_out32(s, ADDIS | TAI(ret, TCG_REG_TB, 0));
|
||||||
|
tcg_out32(s, LD | TAI(ret, ret, 0));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue