qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PULL 15/21] tcg-ppc64: Look through a constant function de


From: Richard Henderson
Subject: [Qemu-devel] [PULL 15/21] tcg-ppc64: Look through a constant function descriptor
Date: Wed, 25 Sep 2013 09:27:32 -0700

Especially in the user-only configurations, a direct branch into
the executable may be in range.

Signed-off-by: Richard Henderson <address@hidden>
---
 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 8eb0406..0659dd6 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.1.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]