summaryrefslogtreecommitdiffstats
path: root/target/s390x/tcg
diff options
context:
space:
mode:
Diffstat (limited to 'target/s390x/tcg')
-rw-r--r--target/s390x/tcg/insn-data.def30
-rw-r--r--target/s390x/tcg/mem_helper.c20
-rw-r--r--target/s390x/tcg/translate.c60
3 files changed, 105 insertions, 5 deletions
diff --git a/target/s390x/tcg/insn-data.def b/target/s390x/tcg/insn-data.def
index 4911952080..6c8a8b229f 100644
--- a/target/s390x/tcg/insn-data.def
+++ b/target/s390x/tcg/insn-data.def
@@ -105,6 +105,9 @@
D(0xa507, NILL, RI_a, Z, r1_o, i2_16u, r1, 0, andi, 0, 0x1000)
D(0x9400, NI, SI, Z, la1, i2_8u, new, 0, ni, nz64, MO_UB)
D(0xeb54, NIY, SIY, LD, la1, i2_8u, new, 0, ni, nz64, MO_UB)
+/* AND WITH COMPLEMENT */
+ C(0xb9f5, NCRK, RRF_a, MIE3, r2, r3, new, r1_32, andc, nz32)
+ C(0xb9e5, NCGRK, RRF_a, MIE3, r2, r3, r1, 0, andc, nz64)
/* BRANCH AND LINK */
C(0x0500, BALR, RR_a, Z, 0, r2_nz, r1, 0, bal, 0)
@@ -640,6 +643,8 @@
C(0xeb8e, MVCLU, RSY_a, E2, 0, a2, 0, 0, mvclu, 0)
/* MOVE NUMERICS */
C(0xd100, MVN, SS_a, Z, la1, a2, 0, 0, mvn, 0)
+/* MOVE RIGHT TO LEFT */
+ C(0xe50a, MVCRL, SSE, MIE3, la1, a2, 0, 0, mvcrl, 0)
/* MOVE PAGE */
C(0xb254, MVPG, RRE, Z, 0, 0, 0, 0, mvpg, 0)
/* MOVE STRING */
@@ -707,6 +712,16 @@
F(0xed0f, MSEB, RXF, Z, e1, m2_32u, new, e1, mseb, 0, IF_BFP)
F(0xed1f, MSDB, RXF, Z, f1, m2_64, new, f1, msdb, 0, IF_BFP)
+/* NAND */
+ C(0xb974, NNRK, RRF_a, MIE3, r2, r3, new, r1_32, nand, nz32)
+ C(0xb964, NNGRK, RRF_a, MIE3, r2, r3, r1, 0, nand, nz64)
+/* NOR */
+ C(0xb976, NORK, RRF_a, MIE3, r2, r3, new, r1_32, nor, nz32)
+ C(0xb966, NOGRK, RRF_a, MIE3, r2, r3, r1, 0, nor, nz64)
+/* NOT EXCLUSIVE OR */
+ C(0xb977, NXRK, RRF_a, MIE3, r2, r3, new, r1_32, nxor, nz32)
+ C(0xb967, NXGRK, RRF_a, MIE3, r2, r3, r1, 0, nxor, nz64)
+
/* OR */
C(0x1600, OR, RR_a, Z, r1, r2, new, r1_32, or, nz32)
C(0xb9f6, ORK, RRF_a, DO, r2, r3, new, r1_32, or, nz32)
@@ -725,6 +740,9 @@
D(0xa50b, OILL, RI_a, Z, r1_o, i2_16u, r1, 0, ori, 0, 0x1000)
D(0x9600, OI, SI, Z, la1, i2_8u, new, 0, oi, nz64, MO_UB)
D(0xeb56, OIY, SIY, LD, la1, i2_8u, new, 0, oi, nz64, MO_UB)
+/* OR WITH COMPLEMENT */
+ C(0xb975, OCRK, RRF_a, MIE3, r2, r3, new, r1_32, orc, nz32)
+ C(0xb965, OCGRK, RRF_a, MIE3, r2, r3, r1, 0, orc, nz64)
/* PACK */
/* Really format SS_b, but we pack both lengths into one argument
@@ -735,6 +753,9 @@
/* PACK UNICODE */
C(0xe100, PKU, SS_f, E2, la1, a2, 0, 0, pku, 0)
+/* POPULATION COUNT */
+ C(0xb9e1, POPCNT, RRF_c, PC, 0, r2_o, r1, 0, popcnt, nz64)
+
/* PREFETCH */
/* Implemented as nops of course. */
C(0xe336, PFD, RXY_b, GIE, 0, 0, 0, 0, 0, 0)
@@ -743,9 +764,6 @@
/* Implemented as nop of course. */
C(0xb2e8, PPA, RRF_c, PPA, 0, 0, 0, 0, 0, 0)
-/* POPULATION COUNT */
- C(0xb9e1, POPCNT, RRE, PC, 0, r2_o, r1, 0, popcnt, nz64)
-
/* ROTATE LEFT SINGLE LOGICAL */
C(0xeb1d, RLL, RSY_a, Z, r3_o, sh, new, r1_32, rll32, 0)
C(0xeb1c, RLLG, RSY_a, Z, r3_o, sh, r1, 0, rll64, 0)
@@ -765,6 +783,12 @@
/* SEARCH STRING UNICODE */
C(0xb9be, SRSTU, RRE, ETF3, 0, 0, 0, 0, srstu, 0)
+/* SELECT */
+ C(0xb9f0, SELR, RRF_a, MIE3, r3, r2, new, r1_32, loc, 0)
+ C(0xb9e3, SELGR, RRF_a, MIE3, r3, r2, r1, 0, loc, 0)
+/* SELECT HIGH */
+ C(0xb9c0, SELFHR, RRF_a, MIE3, r3_sr32, r2_sr32, new, r1_32h, loc, 0)
+
/* SET ACCESS */
C(0xb24e, SAR, RRE, Z, 0, r2_o, 0, 0, sar, 0)
/* SET ADDRESSING MODE */
diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c
index b5523ef3c7..fc52aa128b 100644
--- a/target/s390x/tcg/mem_helper.c
+++ b/target/s390x/tcg/mem_helper.c
@@ -547,6 +547,26 @@ void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
do_helper_mvc(env, l, dest, src, GETPC());
}
+/* move right to left */
+void HELPER(mvcrl)(CPUS390XState *env, uint64_t l, uint64_t dest, uint64_t src)
+{
+ const int mmu_idx = cpu_mmu_index(env, false);
+ const uint64_t ra = GETPC();
+ S390Access srca, desta;
+ int32_t i;
+
+ /* MVCRL always copies one more byte than specified - maximum is 256 */
+ l++;
+
+ srca = access_prepare(env, src, l, MMU_DATA_LOAD, mmu_idx, ra);
+ desta = access_prepare(env, dest, l, MMU_DATA_STORE, mmu_idx, ra);
+
+ for (i = l - 1; i >= 0; i--) {
+ uint8_t byte = access_get_byte(env, &srca, i, ra);
+ access_set_byte(env, &desta, i, byte, ra);
+ }
+}
+
/* move inverse */
void HELPER(mvcin)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
{
diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c
index e21da539e5..904b51542f 100644
--- a/target/s390x/tcg/translate.c
+++ b/target/s390x/tcg/translate.c
@@ -1498,6 +1498,36 @@ static DisasJumpType op_andi(DisasContext *s, DisasOps *o)
return DISAS_NEXT;
}
+static DisasJumpType op_andc(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_andc_i64(o->out, o->in1, o->in2);
+ return DISAS_NEXT;
+}
+
+static DisasJumpType op_orc(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_orc_i64(o->out, o->in1, o->in2);
+ return DISAS_NEXT;
+}
+
+static DisasJumpType op_nand(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_nand_i64(o->out, o->in1, o->in2);
+ return DISAS_NEXT;
+}
+
+static DisasJumpType op_nor(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_nor_i64(o->out, o->in1, o->in2);
+ return DISAS_NEXT;
+}
+
+static DisasJumpType op_nxor(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_eqv_i64(o->out, o->in1, o->in2);
+ return DISAS_NEXT;
+}
+
static DisasJumpType op_ni(DisasContext *s, DisasOps *o)
{
o->in1 = tcg_temp_new_i64();
@@ -2958,7 +2988,13 @@ static DisasJumpType op_loc(DisasContext *s, DisasOps *o)
{
DisasCompare c;
- disas_jcc(s, &c, get_field(s, m3));
+ if (have_field(s, m3)) {
+ /* LOAD * ON CONDITION */
+ disas_jcc(s, &c, get_field(s, m3));
+ } else {
+ /* SELECT */
+ disas_jcc(s, &c, get_field(s, m4));
+ }
if (c.is_64) {
tcg_gen_movcond_i64(c.cond, o->out, c.u.s64.a, c.u.s64.b,
@@ -3358,6 +3394,12 @@ static DisasJumpType op_mvc(DisasContext *s, DisasOps *o)
return DISAS_NEXT;
}
+static DisasJumpType op_mvcrl(DisasContext *s, DisasOps *o)
+{
+ gen_helper_mvcrl(cpu_env, regs[0], o->addr1, o->in2);
+ return DISAS_NEXT;
+}
+
static DisasJumpType op_mvcin(DisasContext *s, DisasOps *o)
{
TCGv_i32 l = tcg_const_i32(get_field(s, l1));
@@ -3744,7 +3786,13 @@ static DisasJumpType op_pku(DisasContext *s, DisasOps *o)
static DisasJumpType op_popcnt(DisasContext *s, DisasOps *o)
{
- gen_helper_popcnt(o->out, o->in2);
+ const uint8_t m3 = get_field(s, m3);
+
+ if ((m3 & 8) && s390_has_feat(S390_FEAT_MISC_INSTRUCTION_EXT3)) {
+ tcg_gen_ctpop_i64(o->out, o->in2);
+ } else {
+ gen_helper_popcnt(o->out, o->in2);
+ }
return DISAS_NEXT;
}
@@ -5667,6 +5715,13 @@ static void in1_r3_D32(DisasContext *s, DisasOps *o)
}
#define SPEC_in1_r3_D32 SPEC_r3_even
+static void in1_r3_sr32(DisasContext *s, DisasOps *o)
+{
+ o->in1 = tcg_temp_new_i64();
+ tcg_gen_shri_i64(o->in1, regs[get_field(s, r3)], 32);
+}
+#define SPEC_in1_r3_sr32 0
+
static void in1_e1(DisasContext *s, DisasOps *o)
{
o->in1 = load_freg32_i64(get_field(s, r1));
@@ -6169,6 +6224,7 @@ enum DisasInsnEnum {
#define FAC_V S390_FEAT_VECTOR /* vector facility */
#define FAC_VE S390_FEAT_VECTOR_ENH /* vector enhancements facility 1 */
#define FAC_MIE2 S390_FEAT_MISC_INSTRUCTION_EXT2 /* miscellaneous-instruction-extensions facility 2 */
+#define FAC_MIE3 S390_FEAT_MISC_INSTRUCTION_EXT3 /* miscellaneous-instruction-extensions facility 3 */
static const DisasInsn insn_info[] = {
#include "insn-data.def"