@@ -47,6 +47,7 @@
#define TCG_CT_CONST_XORI 0x4000
#define TCG_CT_CONST_CMPI 0x8000
+#define TCG_REG_NONE TCG_REG_R0
#define TCG_TMP0 TCG_REG_R14
#ifdef CONFIG_USE_GUEST_BASE
@@ -204,9 +205,6 @@ typedef enum S390Opcode {
RX_STH = 0x40,
} S390Opcode;
-#define SH32_REG_NONE 0
-#define SH64_REG_NONE 0
-
#define LD_SIGNED 0x04
#define LD_UINT8 0x00
#define LD_INT8 (LD_UINT8 | LD_SIGNED)
@@ -338,7 +336,7 @@ static void patch_reloc(uint8_t *code_ptr, int type,
/* ??? Not the usual definition of "addend". */
pcrel2 = (value - (code_ptr_tl + addend)) >> 1;
-
+
switch (type) {
case R_390_PC16DBL:
assert(pcrel2 == (int16_t)pcrel2);
@@ -597,7 +595,7 @@ static int tcg_target_const_match(tcg_target_long val,
} else if (ct & TCG_CT_CONST_MULI) {
/* Immediates that may be used with multiply. If we have the
general-instruction-extensions, then we have MULTIPLY SINGLE
- IMMEDIATE with a signed 32-bit, otherwise we have only
+ IMMEDIATE with a signed 32-bit, otherwise we have only
MULTIPLY HALFWORD IMMEDIATE, with a signed 16-bit. */
if (facilities & FACILITY_GEN_INST_EXT) {
return val == (int32_t)val;
@@ -799,17 +797,21 @@ static void tcg_out_movi(TCGContext *s, TCGType type,
OPC_RX: If the operation has an RX format opcode (e.g. STC), otherwise 0.
OPC_RXY: The RXY format opcode for the operation (e.g. STCY). */
-static void tcg_out_ldst(TCGContext *s, S390Opcode opc_rx, S390Opcode opc_rxy,
- TCGReg data, TCGReg base, tcg_target_long ofs)
+static void tcg_out_mem(TCGContext *s, S390Opcode opc_rx, S390Opcode opc_rxy,
+ TCGReg data, TCGReg base, TCGReg index,
+ tcg_target_long ofs)
{
- TCGReg index = 0;
-
if (ofs < -0x80000 || ofs >= 0x80000) {
/* Combine the low 16 bits of the offset with the actual load insn;
the high 48 bits must come from an immediate load. */
- index = TCG_TMP0;
- tcg_out_movi(s, TCG_TYPE_PTR, index, ofs & ~0xffff);
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, ofs & ~0xffff);
ofs &= 0xffff;
+
+ /* If we were already given an index register, add it in. */
+ if (index != TCG_REG_NONE) {
+ tcg_out_insn(s, RRE, AGR, TCG_TMP0, index);
+ }
+ index = TCG_TMP0;
}
if (opc_rx && ofs >= 0 && ofs < 0x1000) {
@@ -825,9 +827,9 @@ static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg data,
TCGReg base, tcg_target_long ofs)
{
if (type == TCG_TYPE_I32) {
- tcg_out_ldst(s, RX_L, RXY_LY, data, base, ofs);
+ tcg_out_mem(s, RX_L, RXY_LY, data, base, TCG_REG_NONE, ofs);
} else {
- tcg_out_ldst(s, 0, RXY_LG, data, base, ofs);
+ tcg_out_mem(s, 0, RXY_LG, data, base, TCG_REG_NONE, ofs);
}
}
@@ -835,9 +837,9 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg data,
TCGReg base, tcg_target_long ofs)
{
if (type == TCG_TYPE_I32) {
- tcg_out_ldst(s, RX_ST, RXY_STY, data, base, ofs);
+ tcg_out_mem(s, RX_ST, RXY_STY, data, base, TCG_REG_NONE, ofs);
} else {
- tcg_out_ldst(s, 0, RXY_STG, data, base, ofs);
+ tcg_out_mem(s, 0, RXY_STG, data, base, TCG_REG_NONE, ofs);
}
}
@@ -871,14 +873,14 @@ static void tgen_ext8s(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
if (type == TCG_TYPE_I32) {
if (dest == src) {
- tcg_out_sh32(s, RS_SLL, dest, SH32_REG_NONE, 24);
+ tcg_out_sh32(s, RS_SLL, dest, TCG_REG_NONE, 24);
} else {
- tcg_out_sh64(s, RSY_SLLG, dest, src, SH64_REG_NONE, 24);
+ tcg_out_sh64(s, RSY_SLLG, dest, src, TCG_REG_NONE, 24);
}
- tcg_out_sh32(s, RS_SRA, dest, SH32_REG_NONE, 24);
+ tcg_out_sh32(s, RS_SRA, dest, TCG_REG_NONE, 24);
} else {
- tcg_out_sh64(s, RSY_SLLG, dest, src, SH64_REG_NONE, 56);
- tcg_out_sh64(s, RSY_SRAG, dest, dest, SH64_REG_NONE, 56);
+ tcg_out_sh64(s, RSY_SLLG, dest, src, TCG_REG_NONE, 56);
+ tcg_out_sh64(s, RSY_SRAG, dest, dest, TCG_REG_NONE, 56);
}
}
@@ -911,14 +913,14 @@ static void tgen_ext16s(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
if (type == TCG_TYPE_I32) {
if (dest == src) {
- tcg_out_sh32(s, RS_SLL, dest, SH32_REG_NONE, 16);
+ tcg_out_sh32(s, RS_SLL, dest, TCG_REG_NONE, 16);
} else {
- tcg_out_sh64(s, RSY_SLLG, dest, src, SH64_REG_NONE, 16);
+ tcg_out_sh64(s, RSY_SLLG, dest, src, TCG_REG_NONE, 16);
}
- tcg_out_sh32(s, RS_SRA, dest, SH32_REG_NONE, 24);
+ tcg_out_sh32(s, RS_SRA, dest, TCG_REG_NONE, 24);
} else {
- tcg_out_sh64(s, RSY_SLLG, dest, src, SH64_REG_NONE, 48);
- tcg_out_sh64(s, RSY_SRAG, dest, dest, SH64_REG_NONE, 48);
+ tcg_out_sh64(s, RSY_SLLG, dest, src, TCG_REG_NONE, 48);
+ tcg_out_sh64(s, RSY_SRAG, dest, dest, TCG_REG_NONE, 48);
}
}
@@ -1427,7 +1429,7 @@ static void tcg_prepare_qemu_ldst(TCGContext* s, TCGReg data_reg,
tcg_out_mov(s, arg0, addr_reg);
}
- tcg_out_sh64(s, RSY_SRLG, arg1, addr_reg, SH64_REG_NONE,
+ tcg_out_sh64(s, RSY_SRLG, arg1, addr_reg, TCG_REG_NONE,
TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
tgen64_andi_tmp(s, arg0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
@@ -1615,37 +1617,37 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_ld8u_i64:
/* ??? LLC (RXY format) is only present with the extended-immediate
facility, whereas LLGC is always present. */
- tcg_out_ldst(s, 0, RXY_LLGC, args[0], args[1], args[2]);
+ tcg_out_mem(s, 0, RXY_LLGC, args[0], args[1], TCG_REG_NONE, args[2]);
break;
case INDEX_op_ld8s_i32:
case INDEX_op_ld8s_i64:
/* ??? LB is no smaller than LGB, so no point to using it. */
- tcg_out_ldst(s, 0, RXY_LGB, args[0], args[1], args[2]);
+ tcg_out_mem(s, 0, RXY_LGB, args[0], args[1], TCG_REG_NONE, args[2]);
break;
case INDEX_op_ld16u_i32:
case INDEX_op_ld16u_i64:
/* ??? LLH (RXY format) is only present with the extended-immediate
facility, whereas LLGH is always present. */
- tcg_out_ldst(s, 0, RXY_LLGH, args[0], args[1], args[2]);
+ tcg_out_mem(s, 0, RXY_LLGH, args[0], args[1], TCG_REG_NONE, args[2]);
break;
case INDEX_op_ld16s_i32:
- tcg_out_ldst(s, RX_LH, RXY_LHY, args[0], args[1], args[2]);
+ tcg_out_mem(s, RX_LH, RXY_LHY, args[0], args[1], TCG_REG_NONE, args[2]);
break;
case INDEX_op_ld16s_i64:
- tcg_out_ldst(s, 0, RXY_LGH, args[0], args[1], args[2]);
+ tcg_out_mem(s, 0, RXY_LGH, args[0], args[1], TCG_REG_NONE, args[2]);
break;
case INDEX_op_ld_i32:
tcg_out_ld(s, TCG_TYPE_I32, args[0], args[1], args[2]);
break;
case INDEX_op_ld32u_i64:
- tcg_out_ldst(s, 0, RXY_LLGF, args[0], args[1], args[2]);
+ tcg_out_mem(s, 0, RXY_LLGF, args[0], args[1], TCG_REG_NONE, args[2]);
break;
case INDEX_op_ld32s_i64:
- tcg_out_ldst(s, 0, RXY_LGF, args[0], args[1], args[2]);
+ tcg_out_mem(s, 0, RXY_LGF, args[0], args[1], TCG_REG_NONE, args[2]);
break;
case INDEX_op_ld_i64:
@@ -1654,12 +1656,14 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_st8_i32:
case INDEX_op_st8_i64:
- tcg_out_ldst(s, RX_STC, RXY_STCY, args[0], args[1], args[2]);
+ tcg_out_mem(s, RX_STC, RXY_STCY, args[0], args[1],
+ TCG_REG_NONE, args[2]);
break;
case INDEX_op_st16_i32:
case INDEX_op_st16_i64:
- tcg_out_ldst(s, RX_STH, RXY_STHY, args[0], args[1], args[2]);
+ tcg_out_mem(s, RX_STH, RXY_STHY, args[0], args[1],
+ TCG_REG_NONE, args[2]);
break;
case INDEX_op_st_i32:
@@ -1797,7 +1801,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
op = RS_SLL;
do_shift32:
if (const_args[2]) {
- tcg_out_sh32(s, op, args[0], SH32_REG_NONE, args[2]);
+ tcg_out_sh32(s, op, args[0], TCG_REG_NONE, args[2]);
} else {
tcg_out_sh32(s, op, args[0], args[2], 0);
}
@@ -1813,7 +1817,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
op = RSY_SLLG;
do_shift64:
if (const_args[2]) {
- tcg_out_sh64(s, op, args[0], args[1], SH64_REG_NONE, args[2]);
+ tcg_out_sh64(s, op, args[0], args[1], TCG_REG_NONE, args[2]);
} else {
tcg_out_sh64(s, op, args[0], args[1], args[2], 0);
}
@@ -1828,7 +1832,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_rotl_i32:
/* ??? Using tcg_out_sh64 here for the format; it is a 32-bit rol. */
if (const_args[2]) {
- tcg_out_sh64(s, RSY_RLL, args[0], args[1], SH32_REG_NONE, args[2]);
+ tcg_out_sh64(s, RSY_RLL, args[0], args[1], TCG_REG_NONE, args[2]);
} else {
tcg_out_sh64(s, RSY_RLL, args[0], args[1], args[2], 0);
}
@@ -1836,7 +1840,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_rotr_i32:
if (const_args[2]) {
tcg_out_sh64(s, RSY_RLL, args[0], args[1],
- SH32_REG_NONE, (32 - args[2]) & 31);
+ TCG_REG_NONE, (32 - args[2]) & 31);
} else {
tcg_out_insn(s, RR, LCR, TCG_TMP0, args[2]);
tcg_out_sh64(s, RSY_RLL, args[0], args[1], TCG_TMP0, 0);
@@ -1846,7 +1850,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_rotl_i64:
if (const_args[2]) {
tcg_out_sh64(s, RSY_RLLG, args[0], args[1],
- SH64_REG_NONE, args[2]);
+ TCG_REG_NONE, args[2]);
} else {
tcg_out_sh64(s, RSY_RLLG, args[0], args[1], args[2], 0);
}
@@ -1854,7 +1858,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_rotr_i64:
if (const_args[2]) {
tcg_out_sh64(s, RSY_RLLG, args[0], args[1],
- SH64_REG_NONE, (64 - args[2]) & 63);
+ TCG_REG_NONE, (64 - args[2]) & 63);
} else {
/* We can use the smaller 32-bit negate because only the
low 6 bits are examined for the rotate. */
@@ -1900,7 +1904,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
/* The TCG bswap definition requires bits 0-47 already be zero.
Thus we don't need the G-type insns to implement bswap16_i64. */
tcg_out_insn(s, RRE, LRVR, args[0], args[1]);
- tcg_out_sh32(s, RS_SRL, args[0], SH32_REG_NONE, 16);
+ tcg_out_sh32(s, RS_SRL, args[0], TCG_REG_NONE, 16);
break;
case INDEX_op_bswap32_i32:
case INDEX_op_bswap32_i64:
@@ -2113,9 +2117,9 @@ static const TCGTargetOpDef s390_op_defs[] = {
/* ??? Linux kernels provide an AUXV entry AT_HWCAP that provides most of
this information. However, getting at that entry is not easy this far
- away from main. Our options are: start searching from environ, but
+ away from main. Our options are: start searching from environ, but
that fails as soon as someone does a setenv in between. Read the data
- from /proc/self/auxv. Or do the probing ourselves. The only thing
+ from /proc/self/auxv. Or do the probing ourselves. The only thing
extra that AT_HWCAP gives us is HWCAP_S390_HIGH_GPRS, which indicates
that the kernel saves all 64-bits of the registers around traps while
in 31-bit mode. But this is true of all "recent" kernels (ought to dig
@@ -2156,7 +2160,7 @@ static void query_facilities(void)
/* ??? Possibly some of these are in practice never present unless
the store-facility-extended facility is also present. But since
that isn't documented it's just better to probe for each. */
-
+
/* Test for z/Architecture. Required even in 31-bit mode. */
got_sigill = 0;
/* agr %r0,%r0 */
Rename tcg_out_ldst to tcg_out_mem and add an index parameter. If the index parameter is present, handle it when the offset parameter is large and the addend must be (partially) loaded. Rename SH{32,64}_REG_NONE to TCG_REG_NONE, as the concept of a missing register is not unique to the shift operations. Adjust all users of tcg_out_mem to add TCG_REG_NONE as the index. Signed-off-by: Richard Henderson <rth@twiddle.net> --- tcg/s390/tcg-target.c | 94 +++++++++++++++++++++++++----------------------- 1 files changed, 49 insertions(+), 45 deletions(-)