... before falling back to an indirect branch. Signed-off-by: Richard Henderson <r...@twiddle.net> --- tcg/ppc64/tcg-target.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-)
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c index 94960a3..fce3e5d 100644 --- a/tcg/ppc64/tcg-target.c +++ b/tcg/ppc64/tcg-target.c @@ -173,13 +173,17 @@ static const int tcg_target_callee_save_regs[] = { TCG_REG_R31 }; +static inline bool in_range_b(intptr_t disp) +{ + return disp >= -0x4000000 && disp < 0x4000000; +} + static uint32_t reloc_pc24_val (void *pc, tcg_target_long target) { tcg_target_long disp; disp = target - (tcg_target_long) pc; - if ((disp << 38) >> 38 != disp) - tcg_abort (); + assert(in_range_b(disp)); return disp & 0x3fffffc; } @@ -195,8 +199,7 @@ static uint16_t reloc_pc14_val (void *pc, tcg_target_long target) tcg_target_long disp; disp = target - (tcg_target_long) pc; - if (disp != (int16_t) disp) - tcg_abort (); + assert(disp == (int16_t)disp); return disp & 0xfffc; } @@ -454,6 +457,7 @@ static int tcg_target_const_match (tcg_target_long val, #define FXM(b) (1 << (19 - (b))) #define LK 1 +#define AA 2 #define TAB(t, a, b) (RT(t) | RA(a) | RB(b)) #define SAB(s, a, b) (RS(s) | RA(a) | RB(b)) @@ -688,17 +692,18 @@ static void tcg_out_xori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c) tcg_out_zori32(s, dst, src, c, XORI, XORIS); } -static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target) +static void tcg_out_b(TCGContext *s, int lk, tcg_target_long target) { - tcg_target_long disp; + tcg_target_long disp = target - (tcg_target_long) s->code_ptr; - disp = target - (tcg_target_long) s->code_ptr; - if ((disp << 38) >> 38 == disp) - tcg_out32 (s, B | (disp & 0x3fffffc) | mask); - else { - tcg_out_movi (s, TCG_TYPE_I64, 0, (tcg_target_long) target); - tcg_out32 (s, MTSPR | RS (0) | CTR); - tcg_out32 (s, BCCTR | BO_ALWAYS | mask); + if (in_range_b(disp)) { + tcg_out32(s, B | (disp & 0x3fffffc) | lk); + } else if (in_range_b(target)) { + tcg_out32(s, B | AA | target | lk); + } else { + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R0, target); + tcg_out32 (s, MTSPR | RS(TCG_REG_R0) | CTR); + tcg_out32 (s, BCCTR | BO_ALWAYS | lk); } } -- 1.8.3.1