From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60472) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VGAKK-0000ET-Cr for qemu-devel@nongnu.org; Sun, 01 Sep 2013 12:16:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VGAKE-0006x5-HY for qemu-devel@nongnu.org; Sun, 01 Sep 2013 12:16:36 -0400 Received: from mail-pd0-x22d.google.com ([2607:f8b0:400e:c02::22d]:63858) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VGAKE-0006wv-9Z for qemu-devel@nongnu.org; Sun, 01 Sep 2013 12:16:30 -0400 Received: by mail-pd0-f173.google.com with SMTP id p10so3813428pdj.32 for ; Sun, 01 Sep 2013 09:16:29 -0700 (PDT) Sender: Richard Henderson From: Richard Henderson Date: Sun, 1 Sep 2013 09:16:07 -0700 Message-Id: <1378052173-3579-9-git-send-email-rth@twiddle.net> In-Reply-To: <1378052173-3579-1-git-send-email-rth@twiddle.net> References: <1378052173-3579-1-git-send-email-rth@twiddle.net> Subject: [Qemu-devel] [PATCH 08/14] tcg-ppc64: Look through a constant function descriptor List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: "Vassili Karpov (malc)" , aurelien@aurel32.net, Richard Henderson Especially in the user-only configurations, a direct branch into the executable may be in range. Signed-off-by: Richard Henderson --- tcg/ppc64/tcg-target.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c index 033518c..95980ce 100644 --- a/tcg/ppc64/tcg-target.c +++ b/tcg/ppc64/tcg-target.c @@ -173,14 +173,17 @@ static const int tcg_target_callee_save_regs[] = { TCG_REG_R31 }; +static inline bool in_range_b(tcg_target_long target) +{ + return target == sextract64(target, 0, 26); +} + 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; } @@ -694,7 +697,7 @@ static void tcg_out_b(TCGContext *s, int mask, tcg_target_long target) tcg_target_long disp; disp = target - (tcg_target_long)s->code_ptr; - if ((disp << 38) >> 38 == disp) { + if (in_range_b(disp)) { tcg_out32(s, B | (disp & 0x3fffffc) | mask); } else { tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R0, (tcg_target_long)target); @@ -717,6 +720,18 @@ static void tcg_out_call(TCGContext *s, tcg_target_long arg, int const_arg) int ofs = 0; if (const_arg) { + /* Look through the descriptor. If the branch is in range, and we + don't have to spend too much effort on building the toc. */ + intptr_t tgt = ((intptr_t *)arg)[0]; + intptr_t toc = ((intptr_t *)arg)[1]; + intptr_t diff = tgt - (intptr_t)s->code_ptr; + + if (in_range_b(diff) && toc == (uint32_t)toc) { + tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R2, toc); + tcg_out_b(s, LK, tgt); + return; + } + /* Fold the low bits of the constant into the addresses below. */ ofs = (int16_t)arg; if (ofs + 8 < 0x8000) { -- 1.8.3.1