From: Richard Henderson <[email protected]>
Reviewed-by: Peter Maydell <[email protected]>
Signed-off-by: Richard Henderson <[email protected]>
Message-id: [email protected]
Signed-off-by: Peter Maydell <[email protected]>
---
target/arm/tcg/helper-sve-defs.h | 5 +++++
target/arm/tcg/sve.decode | 2 ++
target/arm/tcg/sve_helper.c | 26 ++++++++++++++++++++++++++
target/arm/tcg/translate-sve.c | 7 +++++++
4 files changed, 40 insertions(+)
diff --git a/target/arm/tcg/helper-sve-defs.h b/target/arm/tcg/helper-sve-defs.h
index de2254bb19..1d9066dcbb 100644
--- a/target/arm/tcg/helper-sve-defs.h
+++ b/target/arm/tcg/helper-sve-defs.h
@@ -3203,3 +3203,8 @@ DEF_HELPER_FLAGS_6(sve2_famin_s, TCG_CALL_NO_RWG,
void, ptr, ptr, ptr, ptr, fpst, i32)
DEF_HELPER_FLAGS_6(sve2_famin_d, TCG_CALL_NO_RWG,
void, ptr, ptr, ptr, ptr, fpst, i32)
+
+DEF_HELPER_FLAGS_4(sve_expand_b, TCG_CALL_NO_WG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(sve_expand_h, TCG_CALL_NO_WG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(sve_expand_s, TCG_CALL_NO_WG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(sve_expand_d, TCG_CALL_NO_WG, void, ptr, ptr, ptr, i32)
diff --git a/target/arm/tcg/sve.decode b/target/arm/tcg/sve.decode
index 2795c2ec7f..5ec1d420c2 100644
--- a/target/arm/tcg/sve.decode
+++ b/target/arm/tcg/sve.decode
@@ -742,6 +742,8 @@ SPLICE 00000101 .. 101 100 100 ... ..... .....
@rdn_pg_rm
# SVE2 vector splice (predicated, constructive)
SPLICE_sve2 00000101 .. 101 101 100 ... ..... ..... @rd_pg_rn
+EXPAND 00000101 .. 110 001 100 ... ..... ..... @rd_pg_rn
+
### SVE Select Vectors Group
# SVE select vector elements (predicated)
diff --git a/target/arm/tcg/sve_helper.c b/target/arm/tcg/sve_helper.c
index a0a189eb1e..2517362189 100644
--- a/target/arm/tcg/sve_helper.c
+++ b/target/arm/tcg/sve_helper.c
@@ -3671,6 +3671,32 @@ void HELPER(sve_compact_d)(void *vd, void *vn, void *vg,
uint32_t desc)
}
}
+#define DO_EXPAND(NAME, TYPE, H) \
+void HELPER(NAME)(void *vd, void *vn, void *vg, uint32_t desc) \
+{ \
+ intptr_t oprsz = simd_oprsz(desc); \
+ ARMVectorReg tmp_n = *(ARMVectorReg *)vn; \
+ for (intptr_t i = 0, j = 0; i < oprsz; ) { \
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
+ do { \
+ TYPE nn = 0; \
+ if (pg & 1) { \
+ nn = *(TYPE *)((void *)&tmp_n + H(j)); \
+ j += sizeof(TYPE); \
+ } \
+ *(TYPE *)(vd + H(i)) = nn; \
+ i += sizeof(TYPE); \
+ pg >>= sizeof(TYPE); \
+ } while (i & 15); \
+ } \
+}
+
+DO_EXPAND(sve_expand_b, uint8_t, H1)
+DO_EXPAND(sve_expand_h, uint16_t, H1_2)
+DO_EXPAND(sve_expand_s, uint32_t, H1_4)
+DO_EXPAND(sve_expand_d, uint64_t, H1_8)
+
+#undef DO_EXPAND
/* Similar to the ARM LastActiveElement pseudocode function, except the
* result is multiplied by the element size. This includes the not found
* indication; e.g. not found for esz=3 is -8.
diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c
index 9a72e03513..57c21a13e8 100644
--- a/target/arm/tcg/translate-sve.c
+++ b/target/arm/tcg/translate-sve.c
@@ -6956,6 +6956,13 @@ static gen_helper_gvec_3 * const sqneg_fns[4] = {
TRANS_FEAT(SQNEG_m, aa64_sme_or_sve2, gen_gvec_ool_arg_zpz, sqneg_fns[a->esz],
a, 0)
TRANS_FEAT(SQNEG_z, aa64_sme2p2_or_sve2p2, gen_gvec_ool_arg_zpz,
sqneg_fns[a->esz], a, 1)
+static gen_helper_gvec_3 * const expand_fns[4] = {
+ gen_helper_sve_expand_b, gen_helper_sve_expand_h,
+ gen_helper_sve_expand_s, gen_helper_sve_expand_d,
+};
+TRANS_FEAT_STREAMING_IF(EXPAND, aa64_sme2p2_or_sve2p2, aa64_sme2p2,
+ gen_gvec_ool_arg_zpz, expand_fns[a->esz], a, 0)
+
DO_ZPZZ(SQSHL, aa64_sme_or_sve2, sve2_sqshl)
DO_ZPZZ(SQRSHL, aa64_sme_or_sve2, sve2_sqrshl)
DO_ZPZZ(SRSHL, aa64_sme_or_sve2, sve2_srshl)
--
2.43.0