[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[qemu-s390x] [PULL SUBSYSTEM s390x 18/40] s390x/tcg: Implement VECTOR MU
From: |
David Hildenbrand |
Subject: |
[qemu-s390x] [PULL SUBSYSTEM s390x 18/40] s390x/tcg: Implement VECTOR MULTIPLY AND ADD * |
Date: |
Fri, 17 May 2019 12:21:23 +0200 |
Quite some variants to handle. At least handle some 32-bit element
variants via gvec expansion (we could also handle 16/32-bit variants
for ODD and EVEN easily via gvec expansion, but let's keep it simple
for now).
Reviewed-by: Richard Henderson <address@hidden>
Signed-off-by: David Hildenbrand <address@hidden>
---
target/s390x/helper.h | 18 +++++
target/s390x/insn-data.def | 14 ++++
target/s390x/translate_vx.inc.c | 122 +++++++++++++++++++++++++++++++
target/s390x/vec_int_helper.c | 123 ++++++++++++++++++++++++++++++++
4 files changed, 277 insertions(+)
diff --git a/target/s390x/helper.h b/target/s390x/helper.h
index 6e6ba9bf32..18f8756d43 100644
--- a/target/s390x/helper.h
+++ b/target/s390x/helper.h
@@ -162,6 +162,24 @@ DEF_HELPER_FLAGS_5(gvec_vgfma8, TCG_CALL_NO_RWG, void,
ptr, cptr, cptr, cptr, i3
DEF_HELPER_FLAGS_5(gvec_vgfma16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr,
i32)
DEF_HELPER_FLAGS_5(gvec_vgfma32, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr,
i32)
DEF_HELPER_FLAGS_5(gvec_vgfma64, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr,
i32)
+DEF_HELPER_FLAGS_5(gvec_vmal8, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr,
i32)
+DEF_HELPER_FLAGS_5(gvec_vmal16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr,
i32)
+DEF_HELPER_FLAGS_5(gvec_vmah8, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr,
i32)
+DEF_HELPER_FLAGS_5(gvec_vmah16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr,
i32)
+DEF_HELPER_FLAGS_5(gvec_vmalh8, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr,
i32)
+DEF_HELPER_FLAGS_5(gvec_vmalh16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr,
i32)
+DEF_HELPER_FLAGS_5(gvec_vmae8, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr,
i32)
+DEF_HELPER_FLAGS_5(gvec_vmae16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr,
i32)
+DEF_HELPER_FLAGS_5(gvec_vmae32, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr,
i32)
+DEF_HELPER_FLAGS_5(gvec_vmale8, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr,
i32)
+DEF_HELPER_FLAGS_5(gvec_vmale16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr,
i32)
+DEF_HELPER_FLAGS_5(gvec_vmale32, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr,
i32)
+DEF_HELPER_FLAGS_5(gvec_vmao8, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr,
i32)
+DEF_HELPER_FLAGS_5(gvec_vmao16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr,
i32)
+DEF_HELPER_FLAGS_5(gvec_vmao32, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr,
i32)
+DEF_HELPER_FLAGS_5(gvec_vmalo8, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr,
i32)
+DEF_HELPER_FLAGS_5(gvec_vmalo16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr,
i32)
+DEF_HELPER_FLAGS_5(gvec_vmalo32, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr,
i32)
#ifndef CONFIG_USER_ONLY
DEF_HELPER_3(servc, i32, env, i64, i64)
diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def
index b22d9f0f6a..7ccec0544f 100644
--- a/target/s390x/insn-data.def
+++ b/target/s390x/insn-data.def
@@ -1106,6 +1106,20 @@
F(0xe7fe, VMN, VRR_c, V, 0, 0, 0, 0, vmx, 0, IF_VEC)
/* VECTOR MINIMUM LOGICAL */
F(0xe7fc, VMNL, VRR_c, V, 0, 0, 0, 0, vmx, 0, IF_VEC)
+/* VECTOR MULTIPLY AND ADD LOW */
+ F(0xe7aa, VMAL, VRR_d, V, 0, 0, 0, 0, vma, 0, IF_VEC)
+/* VECTOR MULTIPLY AND ADD HIGH */
+ F(0xe7ab, VMAH, VRR_d, V, 0, 0, 0, 0, vma, 0, IF_VEC)
+/* VECTOR MULTIPLY AND ADD LOGICAL HIGH */
+ F(0xe7a9, VMALH, VRR_d, V, 0, 0, 0, 0, vma, 0, IF_VEC)
+/* VECTOR MULTIPLY AND ADD EVEN */
+ F(0xe7ae, VMAE, VRR_d, V, 0, 0, 0, 0, vma, 0, IF_VEC)
+/* VECTOR MULTIPLY AND ADD LOGICAL EVEN */
+ F(0xe7ac, VMALE, VRR_d, V, 0, 0, 0, 0, vma, 0, IF_VEC)
+/* VECTOR MULTIPLY AND ADD ODD */
+ F(0xe7af, VMAO, VRR_d, V, 0, 0, 0, 0, vma, 0, IF_VEC)
+/* VECTOR MULTIPLY AND ADD LOGICAL ODD */
+ F(0xe7ad, VMALO, VRR_d, V, 0, 0, 0, 0, vma, 0, IF_VEC)
#ifndef CONFIG_USER_ONLY
/* COMPARE AND SWAP AND PURGE */
diff --git a/target/s390x/translate_vx.inc.c b/target/s390x/translate_vx.inc.c
index bb27cad4d8..7de411f4f6 100644
--- a/target/s390x/translate_vx.inc.c
+++ b/target/s390x/translate_vx.inc.c
@@ -1581,3 +1581,125 @@ static DisasJumpType op_vmx(DisasContext *s, DisasOps
*o)
}
return DISAS_NEXT;
}
+
+static void gen_mal_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b, TCGv_i32 c)
+{
+ TCGv_i32 t0 = tcg_temp_new_i32();
+
+ tcg_gen_mul_i32(t0, a, b);
+ tcg_gen_add_i32(d, t0, c);
+
+ tcg_temp_free_i32(t0);
+}
+
+static void gen_mah_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b, TCGv_i32 c)
+{
+ TCGv_i64 t0 = tcg_temp_new_i64();
+ TCGv_i64 t1 = tcg_temp_new_i64();
+ TCGv_i64 t2 = tcg_temp_new_i64();
+
+ tcg_gen_ext_i32_i64(t0, a);
+ tcg_gen_ext_i32_i64(t1, b);
+ tcg_gen_ext_i32_i64(t2, c);
+ tcg_gen_mul_i64(t0, t0, t1);
+ tcg_gen_add_i64(t0, t0, t2);
+ tcg_gen_extrh_i64_i32(d, t0);
+
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+ tcg_temp_free(t2);
+}
+
+static void gen_malh_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b, TCGv_i32 c)
+{
+ TCGv_i64 t0 = tcg_temp_new_i64();
+ TCGv_i64 t1 = tcg_temp_new_i64();
+ TCGv_i64 t2 = tcg_temp_new_i64();
+
+ tcg_gen_extu_i32_i64(t0, a);
+ tcg_gen_extu_i32_i64(t1, b);
+ tcg_gen_extu_i32_i64(t2, c);
+ tcg_gen_mul_i64(t0, t0, t1);
+ tcg_gen_add_i64(t0, t0, t2);
+ tcg_gen_extrh_i64_i32(d, t0);
+
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+ tcg_temp_free(t2);
+}
+
+static DisasJumpType op_vma(DisasContext *s, DisasOps *o)
+{
+ const uint8_t es = get_field(s->fields, m5);
+ static const GVecGen4 g_vmal[3] = {
+ { .fno = gen_helper_gvec_vmal8, },
+ { .fno = gen_helper_gvec_vmal16, },
+ { .fni4 = gen_mal_i32, },
+ };
+ static const GVecGen4 g_vmah[3] = {
+ { .fno = gen_helper_gvec_vmah8, },
+ { .fno = gen_helper_gvec_vmah16, },
+ { .fni4 = gen_mah_i32, },
+ };
+ static const GVecGen4 g_vmalh[3] = {
+ { .fno = gen_helper_gvec_vmalh8, },
+ { .fno = gen_helper_gvec_vmalh16, },
+ { .fni4 = gen_malh_i32, },
+ };
+ static const GVecGen4 g_vmae[3] = {
+ { .fno = gen_helper_gvec_vmae8, },
+ { .fno = gen_helper_gvec_vmae16, },
+ { .fno = gen_helper_gvec_vmae32, },
+ };
+ static const GVecGen4 g_vmale[3] = {
+ { .fno = gen_helper_gvec_vmale8, },
+ { .fno = gen_helper_gvec_vmale16, },
+ { .fno = gen_helper_gvec_vmale32, },
+ };
+ static const GVecGen4 g_vmao[3] = {
+ { .fno = gen_helper_gvec_vmao8, },
+ { .fno = gen_helper_gvec_vmao16, },
+ { .fno = gen_helper_gvec_vmao32, },
+ };
+ static const GVecGen4 g_vmalo[3] = {
+ { .fno = gen_helper_gvec_vmalo8, },
+ { .fno = gen_helper_gvec_vmalo16, },
+ { .fno = gen_helper_gvec_vmalo32, },
+ };
+ const GVecGen4 *fn;
+
+ if (es > ES_32) {
+ gen_program_exception(s, PGM_SPECIFICATION);
+ return DISAS_NORETURN;
+ }
+
+ switch (s->fields->op2) {
+ case 0xaa:
+ fn = &g_vmal[es];
+ break;
+ case 0xab:
+ fn = &g_vmah[es];
+ break;
+ case 0xa9:
+ fn = &g_vmalh[es];
+ break;
+ case 0xae:
+ fn = &g_vmae[es];
+ break;
+ case 0xac:
+ fn = &g_vmale[es];
+ break;
+ case 0xaf:
+ fn = &g_vmao[es];
+ break;
+ case 0xad:
+ fn = &g_vmalo[es];
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ gen_gvec_4(get_field(s->fields, v1), get_field(s->fields, v2),
+ get_field(s->fields, v3), get_field(s->fields, v4), fn);
+ return DISAS_NEXT;
+}
diff --git a/target/s390x/vec_int_helper.c b/target/s390x/vec_int_helper.c
index 20a1034dd8..171c20fc54 100644
--- a/target/s390x/vec_int_helper.c
+++ b/target/s390x/vec_int_helper.c
@@ -241,3 +241,126 @@ void HELPER(gvec_vgfma64)(void *v1, const void *v2, const
void *v3,
s390_vec_xor(&tmp1, &tmp1, &tmp2);
s390_vec_xor(v1, &tmp1, v4);
}
+
+#define DEF_VMAL(BITS)
\
+void HELPER(gvec_vmal##BITS)(void *v1, const void *v2, const void *v3,
\
+ const void *v4, uint32_t desc)
\
+{
\
+ int i;
\
+
\
+ for (i = 0; i < (128 / BITS); i++) {
\
+ const uint##BITS##_t a = s390_vec_read_element##BITS(v2, i);
\
+ const uint##BITS##_t b = s390_vec_read_element##BITS(v3, i);
\
+ const uint##BITS##_t c = s390_vec_read_element##BITS(v4, i);
\
+
\
+ s390_vec_write_element##BITS(v1, i, a * b + c);
\
+ }
\
+}
+DEF_VMAL(8)
+DEF_VMAL(16)
+
+#define DEF_VMAH(BITS)
\
+void HELPER(gvec_vmah##BITS)(void *v1, const void *v2, const void *v3,
\
+ const void *v4, uint32_t desc)
\
+{
\
+ int i;
\
+
\
+ for (i = 0; i < (128 / BITS); i++) {
\
+ const int32_t a = (int##BITS##_t)s390_vec_read_element##BITS(v2, i);
\
+ const int32_t b = (int##BITS##_t)s390_vec_read_element##BITS(v3, i);
\
+ const int32_t c = (int##BITS##_t)s390_vec_read_element##BITS(v4, i);
\
+
\
+ s390_vec_write_element##BITS(v1, i, (a * b + c) >> BITS);
\
+ }
\
+}
+DEF_VMAH(8)
+DEF_VMAH(16)
+
+#define DEF_VMALH(BITS)
\
+void HELPER(gvec_vmalh##BITS)(void *v1, const void *v2, const void *v3,
\
+ const void *v4, uint32_t desc)
\
+{
\
+ int i;
\
+
\
+ for (i = 0; i < (128 / BITS); i++) {
\
+ const uint##BITS##_t a = s390_vec_read_element##BITS(v2, i);
\
+ const uint##BITS##_t b = s390_vec_read_element##BITS(v3, i);
\
+ const uint##BITS##_t c = s390_vec_read_element##BITS(v4, i);
\
+
\
+ s390_vec_write_element##BITS(v1, i, (a * b + c) >> BITS);
\
+ }
\
+}
+DEF_VMALH(8)
+DEF_VMALH(16)
+
+#define DEF_VMAE(BITS, TBITS)
\
+void HELPER(gvec_vmae##BITS)(void *v1, const void *v2, const void *v3,
\
+ const void *v4, uint32_t desc)
\
+{
\
+ int i, j;
\
+
\
+ for (i = 0, j = 0; i < (128 / TBITS); i++, j += 2) {
\
+ int##TBITS##_t a = (int##BITS##_t)s390_vec_read_element##BITS(v2, j);
\
+ int##TBITS##_t b = (int##BITS##_t)s390_vec_read_element##BITS(v3, j);
\
+ int##TBITS##_t c = (int##BITS##_t)s390_vec_read_element##BITS(v4, j);
\
+
\
+ s390_vec_write_element##TBITS(v1, i, a * b + c);
\
+ }
\
+}
+DEF_VMAE(8, 16)
+DEF_VMAE(16, 32)
+DEF_VMAE(32, 64)
+
+#define DEF_VMALE(BITS, TBITS)
\
+void HELPER(gvec_vmale##BITS)(void *v1, const void *v2, const void *v3,
\
+ const void *v4, uint32_t desc)
\
+{
\
+ int i, j;
\
+
\
+ for (i = 0, j = 0; i < (128 / TBITS); i++, j += 2) {
\
+ uint##TBITS##_t a = s390_vec_read_element##BITS(v2, j);
\
+ uint##TBITS##_t b = s390_vec_read_element##BITS(v3, j);
\
+ uint##TBITS##_t c = s390_vec_read_element##BITS(v4, j);
\
+
\
+ s390_vec_write_element##TBITS(v1, i, a * b + c);
\
+ }
\
+}
+DEF_VMALE(8, 16)
+DEF_VMALE(16, 32)
+DEF_VMALE(32, 64)
+
+#define DEF_VMAO(BITS, TBITS)
\
+void HELPER(gvec_vmao##BITS)(void *v1, const void *v2, const void *v3,
\
+ const void *v4, uint32_t desc)
\
+{
\
+ int i, j;
\
+
\
+ for (i = 0, j = 1; i < (128 / TBITS); i++, j += 2) {
\
+ int##TBITS##_t a = (int##BITS##_t)s390_vec_read_element##BITS(v2, j);
\
+ int##TBITS##_t b = (int##BITS##_t)s390_vec_read_element##BITS(v3, j);
\
+ int##TBITS##_t c = (int##BITS##_t)s390_vec_read_element##BITS(v4, j);
\
+
\
+ s390_vec_write_element##TBITS(v1, i, a * b + c);
\
+ }
\
+}
+DEF_VMAO(8, 16)
+DEF_VMAO(16, 32)
+DEF_VMAO(32, 64)
+
+#define DEF_VMALO(BITS, TBITS)
\
+void HELPER(gvec_vmalo##BITS)(void *v1, const void *v2, const void *v3,
\
+ const void *v4, uint32_t desc)
\
+{
\
+ int i, j;
\
+
\
+ for (i = 0, j = 1; i < (128 / TBITS); i++, j += 2) {
\
+ uint##TBITS##_t a = s390_vec_read_element##BITS(v2, j);
\
+ uint##TBITS##_t b = s390_vec_read_element##BITS(v3, j);
\
+ uint##TBITS##_t c = s390_vec_read_element##BITS(v4, j);
\
+
\
+ s390_vec_write_element##TBITS(v1, i, a * b + c);
\
+ }
\
+}
+DEF_VMALO(8, 16)
+DEF_VMALO(16, 32)
+DEF_VMALO(32, 64)
--
2.20.1
- [qemu-s390x] [PULL SUBSYSTEM s390x 34/40] s390x/tcg: Implement VECTOR SUBTRACT COMPUTE BORROW INDICATION, (continued)
- [qemu-s390x] [PULL SUBSYSTEM s390x 34/40] s390x/tcg: Implement VECTOR SUBTRACT COMPUTE BORROW INDICATION, David Hildenbrand, 2019/05/17
- [qemu-s390x] [PULL SUBSYSTEM s390x 33/40] s390x/tcg: Implement VECTOR SUBTRACT, David Hildenbrand, 2019/05/17
- [qemu-s390x] [PULL SUBSYSTEM s390x 31/40] s390x/tcg: Implement VECTOR SHIFT RIGHT ARITHMETIC, David Hildenbrand, 2019/05/17
- [qemu-s390x] [PULL SUBSYSTEM s390x 30/40] s390x/tcg: Implement VECTOR SHIFT LEFT DOUBLE BY BYTE, David Hildenbrand, 2019/05/17
- [qemu-s390x] [PULL SUBSYSTEM s390x 29/40] s390x/tcg: Implement VECTOR SHIFT LEFT (BY BYTE), David Hildenbrand, 2019/05/17
- [qemu-s390x] [PULL SUBSYSTEM s390x 28/40] s390x/tcg: Implement VECTOR ELEMENT SHIFT, David Hildenbrand, 2019/05/17
- [qemu-s390x] [PULL SUBSYSTEM s390x 26/40] s390x/tcg: Implement VECTOR ELEMENT ROTATE LEFT LOGICAL, David Hildenbrand, 2019/05/17
- [qemu-s390x] [PULL SUBSYSTEM s390x 25/40] s390x/tcg: Implement VECTOR POPULATION COUNT, David Hildenbrand, 2019/05/17
- [qemu-s390x] [PULL SUBSYSTEM s390x 23/40] s390x/tcg: Implement VECTOR OR, David Hildenbrand, 2019/05/17
- [qemu-s390x] [PULL SUBSYSTEM s390x 22/40] s390x/tcg: Implement VECTOR NOT EXCLUSIVE OR, David Hildenbrand, 2019/05/17
- [qemu-s390x] [PULL SUBSYSTEM s390x 18/40] s390x/tcg: Implement VECTOR MULTIPLY AND ADD *,
David Hildenbrand <=
- [qemu-s390x] [PULL SUBSYSTEM s390x 27/40] s390x/tcg: Implement VECTOR ELEMENT ROTATE AND INSERT UNDER MASK, David Hildenbrand, 2019/05/17
- [qemu-s390x] [PULL SUBSYSTEM s390x 24/40] s390x/tcg: Implement VECTOR OR WITH COMPLEMENT, David Hildenbrand, 2019/05/17
- [qemu-s390x] [PULL SUBSYSTEM s390x 21/40] s390x/tcg: Implement VECTOR NOR, David Hildenbrand, 2019/05/17
- [qemu-s390x] [PULL SUBSYSTEM s390x 20/40] s390x/tcg: Implement VECTOR NAND, David Hildenbrand, 2019/05/17
- [qemu-s390x] [PULL SUBSYSTEM s390x 17/40] s390x/tcg: Implement VECTOR (MAXIMUM|MINIMUM) (LOGICAL), David Hildenbrand, 2019/05/17
- [qemu-s390x] [PULL SUBSYSTEM s390x 16/40] s390x/tcg: Implement VECTOR LOAD POSITIVE, David Hildenbrand, 2019/05/17
- [qemu-s390x] [PULL SUBSYSTEM s390x 15/40] s390x/tcg: Implement VECTOR LOAD COMPLEMENT, David Hildenbrand, 2019/05/17
- [qemu-s390x] [PULL SUBSYSTEM s390x 19/40] s390x/tcg: Implement VECTOR MULTIPLY *, David Hildenbrand, 2019/05/17
- [qemu-s390x] [PULL SUBSYSTEM s390x 14/40] s390x/tcg: Implement VECTOR GALOIS FIELD MULTIPLY SUM (AND ACCUMULATE), David Hildenbrand, 2019/05/17
- [qemu-s390x] [PULL SUBSYSTEM s390x 13/40] s390x/tcg: Implement VECTOR EXCLUSIVE OR, David Hildenbrand, 2019/05/17