diff mbox

[40/62] tcg-s390: Tidy goto_tb.

Message ID 1274993204-30766-41-git-send-email-rth@twiddle.net
State New
Headers show

Commit Message

Richard Henderson May 27, 2010, 8:46 p.m. UTC
Invent tcg_out_ld_abs, using LOAD RELATIVE instructions, and use it.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/s390/tcg-target.c |   34 ++++++++++++++++++++++------------
 1 files changed, 22 insertions(+), 12 deletions(-)
diff mbox

Patch

diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c
index eb57e24..627f7b7 100644
--- a/tcg/s390/tcg-target.c
+++ b/tcg/s390/tcg-target.c
@@ -48,12 +48,14 @@  typedef enum S390Opcode {
     RIL_AGFI    = 0xc208,
     RIL_BRASL   = 0xc005,
     RIL_BRCL    = 0xc004,
-    RIL_LARL    = 0xc000,
     RIL_IIHF    = 0xc008,
     RIL_IILF    = 0xc009,
+    RIL_LARL    = 0xc000,
     RIL_LGFI    = 0xc001,
+    RIL_LGRL    = 0xc408,
     RIL_LLIHF   = 0xc00e,
     RIL_LLILF   = 0xc00f,
+    RIL_LRL     = 0xc40d,
     RIL_MSFI    = 0xc201,
     RIL_MSGFI   = 0xc200,
     RIL_NIHF    = 0xc00a,
@@ -531,6 +533,24 @@  static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg data,
     }
 }
 
+/* load data from an absolute host address */
+static void tcg_out_ld_abs(TCGContext *s, TCGType type, TCGReg dest, void *abs)
+{
+    tcg_target_long addr = (tcg_target_long)abs;
+    tcg_target_long disp = (addr - (tcg_target_long)s->code_ptr) >> 1;
+
+    if (disp == (int32_t)disp) {
+        if (type == TCG_TYPE_I32) {
+            tcg_out_insn(s, RIL, LRL, dest, disp);
+        } else {
+            tcg_out_insn(s, RIL, LGRL, dest, disp);
+        }
+    } else {
+        tcg_out_movi(s, TCG_TYPE_PTR, dest, addr & ~0xffff);
+        tcg_out_ld(s, type, dest, dest, addr & 0xffff);
+    }
+}
+
 static inline void tgen_ext8s(TCGContext *s, TCGReg dest, TCGReg src)
 {
     tcg_out_insn(s, RRE, LGBR, dest, src);
@@ -1105,18 +1125,8 @@  static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         if (s->tb_jmp_offset) {
             tcg_abort();
         } else {
-            tcg_target_long off = ((tcg_target_long)(s->tb_next + args[0]) -
-                                   (tcg_target_long)s->code_ptr) >> 1;
-            if (off == (int32_t)off) {
-                /* load address relative to PC */
-                tcg_out_insn(s, RIL, LARL, TCG_TMP0, off);
-            } else {
-                /* too far for larl */
-                tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0,
-                             (tcg_target_long)(s->tb_next + args[0]));
-            }
             /* load address stored at s->tb_next + args[0] */
-            tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_TMP0, 0);
+            tcg_out_ld_abs(s, TCG_TYPE_PTR, TCG_TMP0, s->tb_next + args[0]);
             /* and go there */
             tcg_out_insn(s, RR, BCR, S390_CC_ALWAYS, TCG_TMP0);
         }