diff mbox

[23/62] tcg-s390: Add tgen_calli.

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

Commit Message

Richard Henderson May 27, 2010, 8:46 p.m. UTC
Use it in the softmmu code paths, and INDEX_op_call.

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

Patch

diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c
index f4dab1a..0bd4276 100644
--- a/tcg/s390/tcg-target.c
+++ b/tcg/s390/tcg-target.c
@@ -347,12 +347,6 @@  static void tcg_out_sh32(TCGContext* s, S390Opcode op, TCGReg dest,
     tcg_out_insn_RS(s, op, dest, sh_reg, 0, sh_imm);
 }
 
-/* branch to relative address (long) */
-static void tcg_out_brasl(TCGContext *s, TCGReg r, tcg_target_long raddr)
-{
-    tcg_out_insn(s, RIL, BRASL, r, raddr >> 1);
-}
-
 static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
 {
     /* ??? With a TCGType argument, we could emit the smaller LR insn.  */
@@ -372,7 +366,7 @@  static inline void tcg_out_movi(TCGContext *s, TCGType type,
         tcg_out_insn(s, RI, IILH, ret, arg >> 16);
     } else {
         /* branch over constant and store its address in R13 */
-        tcg_out_brasl(s, TCG_REG_R13, 14);
+        tcg_out_insn(s, RIL, BRASL, TCG_REG_R13, (6 + 8) >> 1);
         /* 64-bit constant */
         tcg_out32(s, arg >> 32);
         tcg_out32(s, arg);
@@ -491,6 +485,17 @@  static void tgen_branch(TCGContext *s, int cc, int labelno)
     }
 }
 
+static void tgen_calli(TCGContext *s, tcg_target_long dest)
+{
+    tcg_target_long off = (dest - (tcg_target_long)s->code_ptr) >> 1;
+    if (off == (int32_t)off) {
+        tcg_out_insn(s, RIL, BRASL, TCG_REG_R14, off);
+    } else {
+        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, dest);
+        tcg_out_insn(s, RR, BASR, TCG_REG_R14, TCG_REG_R13);
+    }
+}
+
 #if defined(CONFIG_SOFTMMU)
 static void tcg_prepare_qemu_ldst(TCGContext* s, int data_reg, int addr_reg,
                                   int mem_index, int opc,
@@ -555,14 +560,10 @@  static void tcg_prepare_qemu_ldst(TCGContext* s, int data_reg, int addr_reg,
     if (is_store) {
         tcg_out_mov(s, arg1, data_reg);
         tcg_out_movi(s, TCG_TYPE_I32, arg2, mem_index);
-        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13,
-                     (tcg_target_ulong)qemu_st_helpers[s_bits]);
-        tcg_out_insn(s, RR, BASR, TCG_REG_R14, TCG_REG_R13);
+        tgen_calli(s, (tcg_target_ulong)qemu_st_helpers[s_bits]);
     } else {
         tcg_out_movi(s, TCG_TYPE_I32, arg1, mem_index);
-        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13,
-                     (tcg_target_ulong)qemu_ld_helpers[s_bits]);
-        tcg_out_insn(s, RR, BASR, TCG_REG_R14, TCG_REG_R13);
+        tgen_calli(s, (tcg_target_ulong)qemu_ld_helpers[s_bits]);
 
         /* sign extension */
         switch (opc) {
@@ -785,7 +786,7 @@  static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         } else {
             tcg_target_long off = ((tcg_target_long)(s->tb_next + args[0]) -
                                    (tcg_target_long)s->code_ptr) >> 1;
-            if (off > -0x80000000L && off < 0x7fffffffL) {
+            if (off == (int32_t)off) {
                 /* load address relative to PC */
                 tcg_out_insn(s, RIL, LARL, TCG_REG_R13, off);
             } else {
@@ -803,22 +804,8 @@  static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
 
     case INDEX_op_call:
         if (const_args[0]) {
-            tcg_target_long off;
-
-            /* FIXME: + 4? Where did that come from? */
-            off = (args[0] - (tcg_target_long)s->code_ptr + 4) >> 1;
-            if (off > -0x80000000 && off < 0x7fffffff) {
-                /* relative call */
-                tcg_out_brasl(s, TCG_REG_R14, off << 1);
-                /* XXX untested */
-                tcg_abort();
-            } else {
-                /* too far for a relative call, load full address */
-                tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, args[0]);
-                tcg_out_insn(s, RR, BASR, TCG_REG_R14, TCG_REG_R13);
-            }
+            tgen_calli(s, args[0]);
         } else {
-            /* call function in register args[0] */
             tcg_out_insn(s, RR, BASR, TCG_REG_R14, args[0]);
         }
         break;