@@ -156,11 +156,9 @@ typedef enum S390Opcode {
RXY_LGF = 0xe314,
RXY_LGH = 0xe315,
RXY_LHY = 0xe378,
- RXY_LLC = 0xe394,
RXY_LLGC = 0xe390,
RXY_LLGF = 0xe316,
RXY_LLGH = 0xe391,
- RXY_LLH = 0xe395,
RXY_LMG = 0xeb04,
RXY_LRV = 0xe31e,
RXY_LRVG = 0xe30f,
@@ -653,24 +651,84 @@ static void tcg_out_ld_abs(TCGContext *s, TCGType type, TCGReg dest, void *abs)
tcg_out_ld(s, type, dest, dest, addr & 0xffff);
}
-static inline void tgen_ext8s(TCGContext *s, TCGReg dest, TCGReg src)
+static void tgen_ext8s(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
{
- tcg_out_insn(s, RRE, LGBR, dest, src);
+ if (facilities & FACILITY_EXT_IMM) {
+ tcg_out_insn(s, RRE, LGBR, dest, src);
+ return;
+ }
+
+ if (type == TCG_TYPE_I32) {
+ if (dest == src) {
+ tcg_out_sh32(s, RS_SLL, dest, SH32_REG_NONE, 24);
+ } else {
+ tcg_out_sh64(s, RSY_SLLG, dest, src, SH64_REG_NONE, 24);
+ }
+ tcg_out_sh32(s, RS_SRA, dest, SH32_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);
+ }
}
-static inline void tgen_ext8u(TCGContext *s, TCGReg dest, TCGReg src)
+static void tgen_ext8u(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
{
- tcg_out_insn(s, RRE, LLGCR, dest, src);
+ if (facilities & FACILITY_EXT_IMM) {
+ tcg_out_insn(s, RRE, LLGCR, dest, src);
+ return;
+ }
+
+ if (dest == src) {
+ tcg_out_movi(s, type, TCG_TMP0, 0xff);
+ src = TCG_TMP0;
+ } else {
+ tcg_out_movi(s, type, dest, 0xff);
+ }
+ if (type == TCG_TYPE_I32) {
+ tcg_out_insn(s, RR, NR, dest, src);
+ } else {
+ tcg_out_insn(s, RRE, NGR, dest, src);
+ }
}
-static inline void tgen_ext16s(TCGContext *s, TCGReg dest, TCGReg src)
+static void tgen_ext16s(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
{
- tcg_out_insn(s, RRE, LGHR, dest, src);
+ if (facilities & FACILITY_EXT_IMM) {
+ tcg_out_insn(s, RRE, LGHR, dest, src);
+ return;
+ }
+
+ if (type == TCG_TYPE_I32) {
+ if (dest == src) {
+ tcg_out_sh32(s, RS_SLL, dest, SH32_REG_NONE, 16);
+ } else {
+ tcg_out_sh64(s, RSY_SLLG, dest, src, SH64_REG_NONE, 16);
+ }
+ tcg_out_sh32(s, RS_SRA, dest, SH32_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);
+ }
}
-static inline void tgen_ext16u(TCGContext *s, TCGReg dest, TCGReg src)
+static void tgen_ext16u(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
{
- tcg_out_insn(s, RRE, LLGHR, dest, src);
+ if (facilities & FACILITY_EXT_IMM) {
+ tcg_out_insn(s, RRE, LLGHR, dest, src);
+ return;
+ }
+
+ if (dest == src) {
+ tcg_out_movi(s, type, TCG_TMP0, 0xffff);
+ src = TCG_TMP0;
+ } else {
+ tcg_out_movi(s, type, dest, 0xffff);
+ }
+ if (type == TCG_TYPE_I32) {
+ tcg_out_insn(s, RR, NR, dest, src);
+ } else {
+ tcg_out_insn(s, RRE, NGR, dest, src);
+ }
}
static inline void tgen_ext32s(TCGContext *s, TCGReg dest, TCGReg src)
@@ -972,7 +1030,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, int opc, TCGReg data,
if (bswap) {
/* swapped unsigned halfword load with upper bits zeroed */
tcg_out_insn(s, RXY, LRVH, data, base, index, disp);
- tgen_ext16u(s, data, data);
+ tgen_ext16u(s, TCG_TYPE_I64, data, data);
} else {
tcg_out_insn(s, RXY, LLGH, data, base, index, disp);
}
@@ -981,7 +1039,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, int opc, TCGReg data,
if (bswap) {
/* swapped sign-extended halfword load */
tcg_out_insn(s, RXY, LRVH, data, base, index, disp);
- tgen_ext16s(s, data, data);
+ tgen_ext16s(s, TCG_TYPE_I64, data, data);
} else {
tcg_out_insn(s, RXY, LGH, data, base, index, disp);
}
@@ -1117,10 +1175,10 @@ static void tcg_prepare_qemu_ldst(TCGContext* s, TCGReg data_reg,
/* sign extension */
switch (opc) {
case LD_INT8:
- tgen_ext8s(s, data_reg, arg0);
+ tgen_ext8s(s, TCG_TYPE_I64, data_reg, arg0);
break;
case LD_INT16:
- tgen_ext16s(s, data_reg, arg0);
+ tgen_ext16s(s, TCG_TYPE_I64, data_reg, arg0);
break;
case LD_INT32:
tgen_ext32s(s, data_reg, arg0);
@@ -1264,23 +1322,22 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
break;
case INDEX_op_ld8u_i32:
- tcg_out_ldst(s, 0, RXY_LLC, args[0], args[1], args[2]);
- break;
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]);
break;
case INDEX_op_ld8s_i32:
- tcg_out_ldst(s, 0, RXY_LB, args[0], args[1], args[2]);
- break;
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]);
break;
case INDEX_op_ld16u_i32:
- tcg_out_ldst(s, 0, RXY_LLH, args[0], args[1], args[2]);
- break;
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]);
break;
@@ -1517,24 +1574,32 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
break;
case INDEX_op_ext8s_i32:
+ tgen_ext8s(s, TCG_TYPE_I32, args[0], args[1]);
+ break;
case INDEX_op_ext8s_i64:
- tgen_ext8s(s, args[0], args[1]);
+ tgen_ext8s(s, TCG_TYPE_I64, args[0], args[1]);
break;
case INDEX_op_ext16s_i32:
+ tgen_ext16s(s, TCG_TYPE_I32, args[0], args[1]);
+ break;
case INDEX_op_ext16s_i64:
- tgen_ext16s(s, args[0], args[1]);
+ tgen_ext16s(s, TCG_TYPE_I64, args[0], args[1]);
break;
case INDEX_op_ext32s_i64:
tgen_ext32s(s, args[0], args[1]);
break;
case INDEX_op_ext8u_i32:
+ tgen_ext8u(s, TCG_TYPE_I32, args[0], args[1]);
+ break;
case INDEX_op_ext8u_i64:
- tgen_ext8u(s, args[0], args[1]);
+ tgen_ext8u(s, TCG_TYPE_I64, args[0], args[1]);
break;
case INDEX_op_ext16u_i32:
+ tgen_ext16u(s, TCG_TYPE_I32, args[0], args[1]);
+ break;
case INDEX_op_ext16u_i64:
- tgen_ext16u(s, args[0], args[1]);
+ tgen_ext16u(s, TCG_TYPE_I64, args[0], args[1]);
break;
case INDEX_op_ext32u_i64:
tgen_ext32u(s, args[0], args[1]);
@@ -1545,7 +1610,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_insn(s, RS, SRL, args[0], 0, SH32_REG_NONE, 16);
+ tcg_out_sh32(s, RS_SRL, args[0], SH32_REG_NONE, 16);
break;
case INDEX_op_bswap32_i32:
case INDEX_op_bswap32_i64:
These instructions are part of the extended-immediate facility. Signed-off-by: Richard Henderson <rth@twiddle.net> --- tcg/s390/tcg-target.c | 115 ++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 90 insertions(+), 25 deletions(-)