aboutsummaryrefslogtreecommitdiff
path: root/target/arm/sve_helper.c
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2018-06-29 15:11:05 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-06-29 15:11:05 +0100
commitf6dbf62a7e3d00e9a1dcc7fe3e53b32c3ed93e24 (patch)
tree7c08b87d5fc4d456b2e83fc55951c6be911a934f /target/arm/sve_helper.c
parent5047c204d0d4a0fff616a24963b2b45c7d9ba4c4 (diff)
target/arm: Implement SVE scatter stores
Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20180627043328.11531-12-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm/sve_helper.c')
-rw-r--r--target/arm/sve_helper.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
index 93f2942590..7622bb2af0 100644
--- a/target/arm/sve_helper.c
+++ b/target/arm/sve_helper.c
@@ -3713,3 +3713,64 @@ void HELPER(sve_st4dd_r)(CPUARMState *env, void *vg,
addr += 4 * 8;
}
}
+
+/* Stores with a vector index. */
+
+#define DO_ST1_ZPZ_S(NAME, TYPEI, FN) \
+void HELPER(NAME)(CPUARMState *env, void *vd, void *vg, void *vm, \
+ target_ulong base, uint32_t desc) \
+{ \
+ intptr_t i, oprsz = simd_oprsz(desc); \
+ unsigned scale = simd_data(desc); \
+ uintptr_t ra = GETPC(); \
+ for (i = 0; i < oprsz; ) { \
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
+ do { \
+ if (likely(pg & 1)) { \
+ target_ulong off = *(TYPEI *)(vm + H1_4(i)); \
+ uint32_t d = *(uint32_t *)(vd + H1_4(i)); \
+ FN(env, base + (off << scale), d, ra); \
+ } \
+ i += sizeof(uint32_t), pg >>= sizeof(uint32_t); \
+ } while (i & 15); \
+ } \
+}
+
+#define DO_ST1_ZPZ_D(NAME, TYPEI, FN) \
+void HELPER(NAME)(CPUARMState *env, void *vd, void *vg, void *vm, \
+ target_ulong base, uint32_t desc) \
+{ \
+ intptr_t i, oprsz = simd_oprsz(desc) / 8; \
+ unsigned scale = simd_data(desc); \
+ uintptr_t ra = GETPC(); \
+ uint64_t *d = vd, *m = vm; uint8_t *pg = vg; \
+ for (i = 0; i < oprsz; i++) { \
+ if (likely(pg[H1(i)] & 1)) { \
+ target_ulong off = (target_ulong)(TYPEI)m[i] << scale; \
+ FN(env, base + off, d[i], ra); \
+ } \
+ } \
+}
+
+DO_ST1_ZPZ_S(sve_stbs_zsu, uint32_t, cpu_stb_data_ra)
+DO_ST1_ZPZ_S(sve_sths_zsu, uint32_t, cpu_stw_data_ra)
+DO_ST1_ZPZ_S(sve_stss_zsu, uint32_t, cpu_stl_data_ra)
+
+DO_ST1_ZPZ_S(sve_stbs_zss, int32_t, cpu_stb_data_ra)
+DO_ST1_ZPZ_S(sve_sths_zss, int32_t, cpu_stw_data_ra)
+DO_ST1_ZPZ_S(sve_stss_zss, int32_t, cpu_stl_data_ra)
+
+DO_ST1_ZPZ_D(sve_stbd_zsu, uint32_t, cpu_stb_data_ra)
+DO_ST1_ZPZ_D(sve_sthd_zsu, uint32_t, cpu_stw_data_ra)
+DO_ST1_ZPZ_D(sve_stsd_zsu, uint32_t, cpu_stl_data_ra)
+DO_ST1_ZPZ_D(sve_stdd_zsu, uint32_t, cpu_stq_data_ra)
+
+DO_ST1_ZPZ_D(sve_stbd_zss, int32_t, cpu_stb_data_ra)
+DO_ST1_ZPZ_D(sve_sthd_zss, int32_t, cpu_stw_data_ra)
+DO_ST1_ZPZ_D(sve_stsd_zss, int32_t, cpu_stl_data_ra)
+DO_ST1_ZPZ_D(sve_stdd_zss, int32_t, cpu_stq_data_ra)
+
+DO_ST1_ZPZ_D(sve_stbd_zd, uint64_t, cpu_stb_data_ra)
+DO_ST1_ZPZ_D(sve_sthd_zd, uint64_t, cpu_stw_data_ra)
+DO_ST1_ZPZ_D(sve_stsd_zd, uint64_t, cpu_stl_data_ra)
+DO_ST1_ZPZ_D(sve_stdd_zd, uint64_t, cpu_stq_data_ra)