Invent tcg_out_ld_abs, using LOAD RELATIVE instructions, and use it. Signed-off-by: Richard Henderson <r...@twiddle.net> --- tcg/s390/tcg-target.c | 37 +++++++++++++++++++++++++------------ 1 files changed, 25 insertions(+), 12 deletions(-)
diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c index f1e00e9..822835b 100644 --- a/tcg/s390/tcg-target.c +++ b/tcg/s390/tcg-target.c @@ -59,12 +59,14 @@ typedef enum S390Opcode { RIL_ALGFI = 0xc20a, 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, @@ -755,6 +757,27 @@ 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; + + if (facilities & FACILITY_GEN_INST_EXT) { + 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); + } + return; + } + } + + tcg_out_movi(s, TCG_TYPE_PTR, dest, addr & ~0xffff); + tcg_out_ld(s, type, dest, dest, addr & 0xffff); +} + static void tgen_ext8s(TCGContext *s, TCGType type, TCGReg dest, TCGReg src) { if (facilities & FACILITY_EXT_IMM) { @@ -1360,18 +1383,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); } -- 1.7.0.1