tcg/s390: Support split-wx code generation

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2020-11-04 20:56:16 -08:00
parent dd90043f5d
commit 79dae4ddd8
2 changed files with 31 additions and 40 deletions

View File

@ -363,36 +363,37 @@ static void * const qemu_st_helpers[16] = {
};
#endif
static tcg_insn_unit *tb_ret_addr;
static const tcg_insn_unit *tb_ret_addr;
uint64_t s390_facilities;
static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
static bool patch_reloc(tcg_insn_unit *src_rw, int type,
intptr_t value, intptr_t addend)
{
const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
intptr_t pcrel2;
uint32_t old;
value += addend;
pcrel2 = (tcg_insn_unit *)value - code_ptr;
pcrel2 = (tcg_insn_unit *)value - src_rx;
switch (type) {
case R_390_PC16DBL:
if (pcrel2 == (int16_t)pcrel2) {
tcg_patch16(code_ptr, pcrel2);
tcg_patch16(src_rw, pcrel2);
return true;
}
break;
case R_390_PC32DBL:
if (pcrel2 == (int32_t)pcrel2) {
tcg_patch32(code_ptr, pcrel2);
tcg_patch32(src_rw, pcrel2);
return true;
}
break;
case R_390_20:
if (value == sextract64(value, 0, 20)) {
old = *(uint32_t *)code_ptr & 0xf00000ff;
old = *(uint32_t *)src_rw & 0xf00000ff;
old |= ((value & 0xfff) << 16) | ((value & 0xff000) >> 4);
tcg_patch32(code_ptr, old);
tcg_patch32(src_rw, old);
return true;
}
break;
@ -730,7 +731,8 @@ static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
}
/* load data from an absolute host address */
static void tcg_out_ld_abs(TCGContext *s, TCGType type, TCGReg dest, void *abs)
static void tcg_out_ld_abs(TCGContext *s, TCGType type,
TCGReg dest, const void *abs)
{
intptr_t addr = (intptr_t)abs;
@ -1304,7 +1306,7 @@ static void tgen_extract(TCGContext *s, TCGReg dest, TCGReg src,
static void tgen_gotoi(TCGContext *s, int cc, const tcg_insn_unit *dest)
{
ptrdiff_t off = dest - s->code_ptr;
ptrdiff_t off = tcg_pcrel_diff(s, dest) >> 1;
if (off == (int16_t)off) {
tcg_out_insn(s, RI, BRC, cc, off);
} else if (off == (int32_t)off) {
@ -1333,34 +1335,18 @@ static void tgen_branch(TCGContext *s, int cc, TCGLabel *l)
static void tgen_compare_branch(TCGContext *s, S390Opcode opc, int cc,
TCGReg r1, TCGReg r2, TCGLabel *l)
{
intptr_t off = 0;
if (l->has_value) {
off = l->u.value_ptr - s->code_ptr;
tcg_debug_assert(off == (int16_t)off);
} else {
tcg_out_reloc(s, s->code_ptr + 1, R_390_PC16DBL, l, 2);
}
tcg_out_reloc(s, s->code_ptr + 1, R_390_PC16DBL, l, 2);
tcg_out16(s, (opc & 0xff00) | (r1 << 4) | r2);
tcg_out16(s, off);
tcg_out16(s, 0);
tcg_out16(s, cc << 12 | (opc & 0xff));
}
static void tgen_compare_imm_branch(TCGContext *s, S390Opcode opc, int cc,
TCGReg r1, int i2, TCGLabel *l)
{
tcg_target_long off = 0;
if (l->has_value) {
off = l->u.value_ptr - s->code_ptr;
tcg_debug_assert(off == (int16_t)off);
} else {
tcg_out_reloc(s, s->code_ptr + 1, R_390_PC16DBL, l, 2);
}
tcg_out_reloc(s, s->code_ptr + 1, R_390_PC16DBL, l, 2);
tcg_out16(s, (opc & 0xff00) | (r1 << 4) | cc);
tcg_out16(s, off);
tcg_out16(s, 0);
tcg_out16(s, (i2 << 8) | (opc & 0xff));
}
@ -1417,7 +1403,7 @@ static void tgen_brcond(TCGContext *s, TCGType type, TCGCond c,
static void tcg_out_call(TCGContext *s, const tcg_insn_unit *dest)
{
ptrdiff_t off = dest - s->code_ptr;
ptrdiff_t off = tcg_pcrel_diff(s, dest) >> 1;
if (off == (int32_t)off) {
tcg_out_insn(s, RIL, BRASL, TCG_REG_R14, off);
} else {
@ -1601,7 +1587,8 @@ static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi,
label->oi = oi;
label->datalo_reg = data;
label->addrlo_reg = addr;
label->raddr = raddr;
/* TODO: Cast goes away when all hosts converted */
label->raddr = (void *)tcg_splitwx_to_rx(raddr);
label->label_ptr[0] = label_ptr;
}
@ -1613,7 +1600,7 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
MemOp opc = get_memop(oi);
if (!patch_reloc(lb->label_ptr[0], R_390_PC16DBL,
(intptr_t)s->code_ptr, 2)) {
(intptr_t)tcg_splitwx_to_rx(s->code_ptr), 2)) {
return false;
}
@ -1638,7 +1625,7 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
MemOp opc = get_memop(oi);
if (!patch_reloc(lb->label_ptr[0], R_390_PC16DBL,
(intptr_t)s->code_ptr, 2)) {
(intptr_t)tcg_splitwx_to_rx(s->code_ptr), 2)) {
return false;
}
@ -1766,7 +1753,8 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_goto_tb:
a0 = args[0];
if (s->tb_jmp_insn_offset) {
/* branch displacement must be aligned for atomic patching;
/*
* branch displacement must be aligned for atomic patching;
* see if we need to add extra nop before branch
*/
if (!QEMU_PTR_IS_ALIGNED(s->code_ptr + 1, 4)) {
@ -1779,7 +1767,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
} else {
/* load address stored at s->tb_jmp_target_addr + a0 */
tcg_out_ld_abs(s, TCG_TYPE_PTR, TCG_REG_TB,
s->tb_jmp_target_addr + a0);
tcg_splitwx_to_rx(s->tb_jmp_target_addr + a0));
/* and go there */
tcg_out_insn(s, RR, BCR, S390_CC_ALWAYS, TCG_REG_TB);
}
@ -1789,8 +1777,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
TCG_REG_TB to the beginning of this TB. */
if (USE_REG_TB) {
int ofs = -tcg_current_code_size(s);
assert(ofs == (int16_t)ofs);
tcg_out_insn(s, RI, AGHI, TCG_REG_TB, ofs);
/* All TB are restricted to 64KiB by unwind info. */
tcg_debug_assert(ofs == sextract64(ofs, 0, 20));
tcg_out_insn(s, RXY, LAY, TCG_REG_TB,
TCG_REG_TB, TCG_REG_NONE, ofs);
}
break;
@ -2561,11 +2551,12 @@ static void tcg_target_qemu_prologue(TCGContext *s)
* Return path for goto_ptr. Set return value to 0, a-la exit_tb,
* and fall through to the rest of the epilogue.
*/
tcg_code_gen_epilogue = s->code_ptr;
/* TODO: Cast goes away when all hosts converted */
tcg_code_gen_epilogue = (void *)tcg_splitwx_to_rx(s->code_ptr);
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, 0);
/* TB epilogue */
tb_ret_addr = s->code_ptr;
tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr);
/* lmg %r6,%r15,fs+48(%r15) (restore registers) */
tcg_out_insn(s, RXY, LMG, TCG_REG_R6, TCG_REG_R15, TCG_REG_R15,

View File

@ -159,6 +159,6 @@ static inline void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
#define TCG_TARGET_NEED_LDST_LABELS
#endif
#define TCG_TARGET_NEED_POOL_LABELS
#define TCG_TARGET_SUPPORT_MIRROR 0
#define TCG_TARGET_SUPPORT_MIRROR 1
#endif