summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--target/s390x/helper.h3
-rw-r--r--target/s390x/tcg/insn-data.def12
-rw-r--r--target/s390x/tcg/translate_vx.c.inc75
-rw-r--r--target/s390x/tcg/vec_int_helper.c55
4 files changed, 95 insertions, 50 deletions
diff --git a/target/s390x/helper.h b/target/s390x/helper.h
index 7412130883..bf33d86f74 100644
--- a/target/s390x/helper.h
+++ b/target/s390x/helper.h
@@ -203,8 +203,11 @@ DEF_HELPER_FLAGS_3(gvec_vpopct16, TCG_CALL_NO_RWG, void, ptr, cptr, i32)
DEF_HELPER_FLAGS_4(gvec_verim8, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32)
DEF_HELPER_FLAGS_4(gvec_verim16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32)
DEF_HELPER_FLAGS_4(gvec_vsl, TCG_CALL_NO_RWG, void, ptr, cptr, i64, i32)
+DEF_HELPER_FLAGS_4(gvec_vsl_ve2, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32)
DEF_HELPER_FLAGS_4(gvec_vsra, TCG_CALL_NO_RWG, void, ptr, cptr, i64, i32)
+DEF_HELPER_FLAGS_4(gvec_vsra_ve2, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32)
DEF_HELPER_FLAGS_4(gvec_vsrl, TCG_CALL_NO_RWG, void, ptr, cptr, i64, i32)
+DEF_HELPER_FLAGS_4(gvec_vsrl_ve2, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32)
DEF_HELPER_FLAGS_4(gvec_vscbi8, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32)
DEF_HELPER_FLAGS_4(gvec_vscbi16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32)
DEF_HELPER_4(gvec_vtm, void, ptr, cptr, env, i32)
diff --git a/target/s390x/tcg/insn-data.def b/target/s390x/tcg/insn-data.def
index 46add91a0e..f487a64abf 100644
--- a/target/s390x/tcg/insn-data.def
+++ b/target/s390x/tcg/insn-data.def
@@ -1204,19 +1204,19 @@
F(0xe778, VESRLV, VRR_c, V, 0, 0, 0, 0, vesv, 0, IF_VEC)
F(0xe738, VESRL, VRS_a, V, la2, 0, 0, 0, ves, 0, IF_VEC)
/* VECTOR SHIFT LEFT */
- F(0xe774, VSL, VRR_c, V, 0, 0, 0, 0, vsl, 0, IF_VEC)
+ E(0xe774, VSL, VRR_c, V, 0, 0, 0, 0, vsl, 0, 0, IF_VEC)
/* VECTOR SHIFT LEFT BY BYTE */
- F(0xe775, VSLB, VRR_c, V, 0, 0, 0, 0, vsl, 0, IF_VEC)
+ E(0xe775, VSLB, VRR_c, V, 0, 0, 0, 0, vsl, 0, 1, IF_VEC)
/* VECTOR SHIFT LEFT DOUBLE BY BYTE */
F(0xe777, VSLDB, VRI_d, V, 0, 0, 0, 0, vsldb, 0, IF_VEC)
/* VECTOR SHIFT RIGHT ARITHMETIC */
- F(0xe77e, VSRA, VRR_c, V, 0, 0, 0, 0, vsra, 0, IF_VEC)
+ E(0xe77e, VSRA, VRR_c, V, 0, 0, 0, 0, vsra, 0, 0, IF_VEC)
/* VECTOR SHIFT RIGHT ARITHMETIC BY BYTE */
- F(0xe77f, VSRAB, VRR_c, V, 0, 0, 0, 0, vsra, 0, IF_VEC)
+ E(0xe77f, VSRAB, VRR_c, V, 0, 0, 0, 0, vsra, 0, 1, IF_VEC)
/* VECTOR SHIFT RIGHT LOGICAL */
- F(0xe77c, VSRL, VRR_c, V, 0, 0, 0, 0, vsrl, 0, IF_VEC)
+ E(0xe77c, VSRL, VRR_c, V, 0, 0, 0, 0, vsrl, 0, 0, IF_VEC)
/* VECTOR SHIFT RIGHT LOGICAL BY BYTE */
- F(0xe77d, VSRLB, VRR_c, V, 0, 0, 0, 0, vsrl, 0, IF_VEC)
+ E(0xe77d, VSRLB, VRR_c, V, 0, 0, 0, 0, vsrl, 0, 1, IF_VEC)
/* VECTOR SUBTRACT */
F(0xe7f7, VS, VRR_c, V, 0, 0, 0, 0, vs, 0, IF_VEC)
/* VECTOR SUBTRACT COMPUTE BORROW INDICATION */
diff --git a/target/s390x/tcg/translate_vx.c.inc b/target/s390x/tcg/translate_vx.c.inc
index 8ddbd440e2..81673ea68f 100644
--- a/target/s390x/tcg/translate_vx.c.inc
+++ b/target/s390x/tcg/translate_vx.c.inc
@@ -2018,23 +2018,44 @@ static DisasJumpType op_ves(DisasContext *s, DisasOps *o)
return DISAS_NEXT;
}
-static DisasJumpType op_vsl(DisasContext *s, DisasOps *o)
+static DisasJumpType gen_vsh_by_byte(DisasContext *s, DisasOps *o,
+ gen_helper_gvec_2i *gen,
+ gen_helper_gvec_3 *gen_ve2)
{
- TCGv_i64 shift = tcg_temp_new_i64();
+ bool byte = s->insn->data;
- read_vec_element_i64(shift, get_field(s, v3), 7, ES_8);
- if (s->fields.op2 == 0x74) {
- tcg_gen_andi_i64(shift, shift, 0x7);
+ if (!byte && s390_has_feat(S390_FEAT_VECTOR_ENH2)) {
+ gen_gvec_3_ool(get_field(s, v1), get_field(s, v2),
+ get_field(s, v3), 0, gen_ve2);
} else {
- tcg_gen_andi_i64(shift, shift, 0x78);
- }
+ TCGv_i64 shift = tcg_temp_new_i64();
- gen_gvec_2i_ool(get_field(s, v1), get_field(s, v2),
- shift, 0, gen_helper_gvec_vsl);
- tcg_temp_free_i64(shift);
+ read_vec_element_i64(shift, get_field(s, v3), 7, ES_8);
+ tcg_gen_andi_i64(shift, shift, byte ? 0x78 : 7);
+ gen_gvec_2i_ool(get_field(s, v1), get_field(s, v2), shift, 0, gen);
+ tcg_temp_free_i64(shift);
+ }
return DISAS_NEXT;
}
+static DisasJumpType op_vsl(DisasContext *s, DisasOps *o)
+{
+ return gen_vsh_by_byte(s, o, gen_helper_gvec_vsl,
+ gen_helper_gvec_vsl_ve2);
+}
+
+static DisasJumpType op_vsra(DisasContext *s, DisasOps *o)
+{
+ return gen_vsh_by_byte(s, o, gen_helper_gvec_vsra,
+ gen_helper_gvec_vsra_ve2);
+}
+
+static DisasJumpType op_vsrl(DisasContext *s, DisasOps *o)
+{
+ return gen_vsh_by_byte(s, o, gen_helper_gvec_vsrl,
+ gen_helper_gvec_vsrl_ve2);
+}
+
static DisasJumpType op_vsldb(DisasContext *s, DisasOps *o)
{
const uint8_t i4 = get_field(s, i4) & 0xf;
@@ -2064,40 +2085,6 @@ static DisasJumpType op_vsldb(DisasContext *s, DisasOps *o)
return DISAS_NEXT;
}
-static DisasJumpType op_vsra(DisasContext *s, DisasOps *o)
-{
- TCGv_i64 shift = tcg_temp_new_i64();
-
- read_vec_element_i64(shift, get_field(s, v3), 7, ES_8);
- if (s->fields.op2 == 0x7e) {
- tcg_gen_andi_i64(shift, shift, 0x7);
- } else {
- tcg_gen_andi_i64(shift, shift, 0x78);
- }
-
- gen_gvec_2i_ool(get_field(s, v1), get_field(s, v2),
- shift, 0, gen_helper_gvec_vsra);
- tcg_temp_free_i64(shift);
- return DISAS_NEXT;
-}
-
-static DisasJumpType op_vsrl(DisasContext *s, DisasOps *o)
-{
- TCGv_i64 shift = tcg_temp_new_i64();
-
- read_vec_element_i64(shift, get_field(s, v3), 7, ES_8);
- if (s->fields.op2 == 0x7c) {
- tcg_gen_andi_i64(shift, shift, 0x7);
- } else {
- tcg_gen_andi_i64(shift, shift, 0x78);
- }
-
- gen_gvec_2i_ool(get_field(s, v1), get_field(s, v2),
- shift, 0, gen_helper_gvec_vsrl);
- tcg_temp_free_i64(shift);
- return DISAS_NEXT;
-}
-
static DisasJumpType op_vs(DisasContext *s, DisasOps *o)
{
const uint8_t es = get_field(s, m4);
diff --git a/target/s390x/tcg/vec_int_helper.c b/target/s390x/tcg/vec_int_helper.c
index b44859ee16..53ab5c5eb3 100644
--- a/target/s390x/tcg/vec_int_helper.c
+++ b/target/s390x/tcg/vec_int_helper.c
@@ -539,18 +539,73 @@ void HELPER(gvec_vsl)(void *v1, const void *v2, uint64_t count,
s390_vec_shl(v1, v2, count);
}
+void HELPER(gvec_vsl_ve2)(void *v1, const void *v2, const void *v3,
+ uint32_t desc)
+{
+ S390Vector tmp;
+ uint32_t sh, e0, e1 = 0;
+ int i;
+
+ for (i = 15; i >= 0; --i, e1 = e0) {
+ e0 = s390_vec_read_element8(v2, i);
+ sh = s390_vec_read_element8(v3, i) & 7;
+
+ s390_vec_write_element8(&tmp, i, rol32(e0 | (e1 << 24), sh));
+ }
+
+ *(S390Vector *)v1 = tmp;
+}
+
void HELPER(gvec_vsra)(void *v1, const void *v2, uint64_t count,
uint32_t desc)
{
s390_vec_sar(v1, v2, count);
}
+void HELPER(gvec_vsra_ve2)(void *v1, const void *v2, const void *v3,
+ uint32_t desc)
+{
+ S390Vector tmp;
+ uint32_t sh, e0, e1 = 0;
+ int i = 0;
+
+ /* Byte 0 is special only. */
+ e0 = (int32_t)(int8_t)s390_vec_read_element8(v2, i);
+ sh = s390_vec_read_element8(v3, i) & 7;
+ s390_vec_write_element8(&tmp, i, e0 >> sh);
+
+ e1 = e0;
+ for (i = 1; i < 16; ++i, e1 = e0) {
+ e0 = s390_vec_read_element8(v2, i);
+ sh = s390_vec_read_element8(v3, i) & 7;
+ s390_vec_write_element8(&tmp, i, (e0 | e1 << 8) >> sh);
+ }
+
+ *(S390Vector *)v1 = tmp;
+}
+
void HELPER(gvec_vsrl)(void *v1, const void *v2, uint64_t count,
uint32_t desc)
{
s390_vec_shr(v1, v2, count);
}
+void HELPER(gvec_vsrl_ve2)(void *v1, const void *v2, const void *v3,
+ uint32_t desc)
+{
+ S390Vector tmp;
+ uint32_t sh, e0, e1 = 0;
+
+ for (int i = 0; i < 16; ++i, e1 = e0) {
+ e0 = s390_vec_read_element8(v2, i);
+ sh = s390_vec_read_element8(v3, i) & 7;
+
+ s390_vec_write_element8(&tmp, i, (e0 | (e1 << 8)) >> sh);
+ }
+
+ *(S390Vector *)v1 = tmp;
+}
+
#define DEF_VSCBI(BITS) \
void HELPER(gvec_vscbi##BITS)(void *v1, const void *v2, const void *v3, \
uint32_t desc) \