aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Hildenbrand <david@redhat.com>2019-03-07 13:15:12 +0100
committerCornelia Huck <cohuck@redhat.com>2019-03-11 09:31:01 +0100
commit64052062a4696417e613ffc01d7b37c81e4c9012 (patch)
treef7509029a85d652aeb1a6c684c2d493ca417782a
parent6d841663be823d69a7dc22c5a175b8934d55c39c (diff)
downloadqemu-64052062a4696417e613ffc01d7b37c81e4c9012.zip
qemu-64052062a4696417e613ffc01d7b37c81e4c9012.tar.gz
qemu-64052062a4696417e613ffc01d7b37c81e4c9012.tar.bz2
s390x/tcg: Implement VECTOR GENERATE BYTE MASK
Let's optimize it for the common cases (setting a vector to zero or all ones) - courtesy of Richard. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: David Hildenbrand <david@redhat.com> Message-Id: <20190307121539.12842-6-david@redhat.com> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
-rw-r--r--target/s390x/insn-data.def2
-rw-r--r--target/s390x/translate.c1
-rw-r--r--target/s390x/translate_vx.inc.c39
3 files changed, 42 insertions, 0 deletions
diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def
index 7d128ac..d3f66c8 100644
--- a/target/s390x/insn-data.def
+++ b/target/s390x/insn-data.def
@@ -977,6 +977,8 @@
/* VECTOR GATHER ELEMENT */
E(0xe713, VGEF, VRV, V, la2, 0, 0, 0, vge, 0, ES_32, IF_VEC)
E(0xe712, VGEG, VRV, V, la2, 0, 0, 0, vge, 0, ES_64, IF_VEC)
+/* VECTOR GENERATE BYTE MASK */
+ F(0xe744, VGBM, VRI_a, V, 0, 0, 0, 0, vgbm, 0, IF_VEC)
#ifndef CONFIG_USER_ONLY
/* COMPARE AND SWAP AND PURGE */
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index a1c6698..588fc21 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -34,6 +34,7 @@
#include "disas/disas.h"
#include "exec/exec-all.h"
#include "tcg-op.h"
+#include "tcg-op-gvec.h"
#include "qemu/log.h"
#include "qemu/host-utils.h"
#include "exec/cpu_ldst.h"
diff --git a/target/s390x/translate_vx.inc.c b/target/s390x/translate_vx.inc.c
index 9864ec5..395c0eb 100644
--- a/target/s390x/translate_vx.inc.c
+++ b/target/s390x/translate_vx.inc.c
@@ -112,6 +112,9 @@ static void write_vec_element_i64(TCGv_i64 src, int reg, uint8_t enr,
}
}
+#define gen_gvec_dup64i(v1, c) \
+ tcg_gen_gvec_dup64i(vec_full_reg_offset(v1), 16, 16, c)
+
static DisasJumpType op_vge(DisasContext *s, DisasOps *o)
{
const uint8_t es = s->insn->data;
@@ -133,3 +136,39 @@ static DisasJumpType op_vge(DisasContext *s, DisasOps *o)
tcg_temp_free_i64(tmp);
return DISAS_NEXT;
}
+
+static uint64_t generate_byte_mask(uint8_t mask)
+{
+ uint64_t r = 0;
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ if ((mask >> i) & 1) {
+ r |= 0xffull << (i * 8);
+ }
+ }
+ return r;
+}
+
+static DisasJumpType op_vgbm(DisasContext *s, DisasOps *o)
+{
+ const uint16_t i2 = get_field(s->fields, i2);
+
+ if (i2 == (i2 & 0xff) * 0x0101) {
+ /*
+ * Masks for both 64 bit elements of the vector are the same.
+ * Trust tcg to produce a good constant loading.
+ */
+ gen_gvec_dup64i(get_field(s->fields, v1),
+ generate_byte_mask(i2 & 0xff));
+ } else {
+ TCGv_i64 t = tcg_temp_new_i64();
+
+ tcg_gen_movi_i64(t, generate_byte_mask(i2 >> 8));
+ write_vec_element_i64(t, get_field(s->fields, v1), 0, ES_64);
+ tcg_gen_movi_i64(t, generate_byte_mask(i2));
+ write_vec_element_i64(t, get_field(s->fields, v1), 1, ES_64);
+ tcg_temp_free_i64(t);
+ }
+ return DISAS_NEXT;
+}