@@ -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;
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(-)