mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-02-02 02:11:09 +00:00
target/arm: Implement SVE scatter stores
Backports commit f6dbf62a7e3d00e9a1dcc7fe3e53b32c3ed93e24 from qemu
This commit is contained in:
parent
d71cdfa41f
commit
b78e283513
|
@ -3784,6 +3784,24 @@
|
|||
#define helper_sve_st2ss_r helper_sve_st2ss_r_aarch64
|
||||
#define helper_sve_st3ss_r helper_sve_st3ss_r_aarch64
|
||||
#define helper_sve_st4ss_r helper_sve_st4ss_r_aarch64
|
||||
#define helper_sve_stbd_zd helper_sve_stbd_zd_aarch64
|
||||
#define helper_sve_stbd_zss helper_sve_stbd_zss_aarch64
|
||||
#define helper_sve_stbd_zsu helper_sve_stbd_zsu_aarch64
|
||||
#define helper_sve_stbs_zss helper_sve_stbs_zss_aarch64
|
||||
#define helper_sve_stbs_zsu helper_sve_stbs_zsu_aarch64
|
||||
#define helper_sve_stdd_zd helper_sve_stdd_zd_aarch64
|
||||
#define helper_sve_stdd_zss helper_sve_stdd_zss_aarch64
|
||||
#define helper_sve_stdd_zsu helper_sve_stdd_zsu_aarch64
|
||||
#define helper_sve_sthd_zd helper_sve_sthd_zd_aarch64
|
||||
#define helper_sve_sthd_zss helper_sve_sthd_zss_aarch64
|
||||
#define helper_sve_sthd_zsu helper_sve_sthd_zsu_aarch64
|
||||
#define helper_sve_sths_zss helper_sve_sths_zss_aarch64
|
||||
#define helper_sve_sths_zsu helper_sve_sths_zsu_aarch64
|
||||
#define helper_sve_stsd_zd helper_sve_stsd_zd_aarch64
|
||||
#define helper_sve_stsd_zss helper_sve_stsd_zss_aarch64
|
||||
#define helper_sve_stsd_zsu helper_sve_stsd_zsu_aarch64
|
||||
#define helper_sve_stss_zss helper_sve_stss_zss_aarch64
|
||||
#define helper_sve_stss_zsu helper_sve_stss_zsu_aarch64
|
||||
#define helper_sve_sub_zpzz_b helper_sve_sub_zpzz_b_aarch64
|
||||
#define helper_sve_sub_zpzz_d helper_sve_sub_zpzz_d_aarch64
|
||||
#define helper_sve_sub_zpzz_h helper_sve_sub_zpzz_h_aarch64
|
||||
|
|
|
@ -3784,6 +3784,24 @@
|
|||
#define helper_sve_st2ss_r helper_sve_st2ss_r_aarch64eb
|
||||
#define helper_sve_st3ss_r helper_sve_st3ss_r_aarch64eb
|
||||
#define helper_sve_st4ss_r helper_sve_st4ss_r_aarch64eb
|
||||
#define helper_sve_stbd_zd helper_sve_stbd_zd_aarch64eb
|
||||
#define helper_sve_stbd_zss helper_sve_stbd_zss_aarch64eb
|
||||
#define helper_sve_stbd_zsu helper_sve_stbd_zsu_aarch64eb
|
||||
#define helper_sve_stbs_zss helper_sve_stbs_zss_aarch64eb
|
||||
#define helper_sve_stbs_zsu helper_sve_stbs_zsu_aarch64eb
|
||||
#define helper_sve_stdd_zd helper_sve_stdd_zd_aarch64eb
|
||||
#define helper_sve_stdd_zss helper_sve_stdd_zss_aarch64eb
|
||||
#define helper_sve_stdd_zsu helper_sve_stdd_zsu_aarch64eb
|
||||
#define helper_sve_sthd_zd helper_sve_sthd_zd_aarch64eb
|
||||
#define helper_sve_sthd_zss helper_sve_sthd_zss_aarch64eb
|
||||
#define helper_sve_sthd_zsu helper_sve_sthd_zsu_aarch64eb
|
||||
#define helper_sve_sths_zss helper_sve_sths_zss_aarch64eb
|
||||
#define helper_sve_sths_zsu helper_sve_sths_zsu_aarch64eb
|
||||
#define helper_sve_stsd_zd helper_sve_stsd_zd_aarch64eb
|
||||
#define helper_sve_stsd_zss helper_sve_stsd_zss_aarch64eb
|
||||
#define helper_sve_stsd_zsu helper_sve_stsd_zsu_aarch64eb
|
||||
#define helper_sve_stss_zss helper_sve_stss_zss_aarch64eb
|
||||
#define helper_sve_stss_zsu helper_sve_stss_zsu_aarch64eb
|
||||
#define helper_sve_sub_zpzz_b helper_sve_sub_zpzz_b_aarch64eb
|
||||
#define helper_sve_sub_zpzz_d helper_sve_sub_zpzz_d_aarch64eb
|
||||
#define helper_sve_sub_zpzz_h helper_sve_sub_zpzz_h_aarch64eb
|
||||
|
|
|
@ -3805,6 +3805,24 @@ aarch64_symbols = (
|
|||
'helper_sve_st2ss_r',
|
||||
'helper_sve_st3ss_r',
|
||||
'helper_sve_st4ss_r',
|
||||
'helper_sve_stbd_zd',
|
||||
'helper_sve_stbd_zss',
|
||||
'helper_sve_stbd_zsu',
|
||||
'helper_sve_stbs_zss',
|
||||
'helper_sve_stbs_zsu',
|
||||
'helper_sve_stdd_zd',
|
||||
'helper_sve_stdd_zss',
|
||||
'helper_sve_stdd_zsu',
|
||||
'helper_sve_sthd_zd',
|
||||
'helper_sve_sthd_zss',
|
||||
'helper_sve_sthd_zsu',
|
||||
'helper_sve_sths_zss',
|
||||
'helper_sve_sths_zsu',
|
||||
'helper_sve_stsd_zd',
|
||||
'helper_sve_stsd_zss',
|
||||
'helper_sve_stsd_zsu',
|
||||
'helper_sve_stss_zss',
|
||||
'helper_sve_stss_zsu',
|
||||
'helper_sve_sub_zpzz_b',
|
||||
'helper_sve_sub_zpzz_d',
|
||||
'helper_sve_sub_zpzz_h',
|
||||
|
|
|
@ -958,3 +958,44 @@ DEF_HELPER_FLAGS_4(sve_st1hs_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
|
|||
DEF_HELPER_FLAGS_4(sve_st1hd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(sve_st1sd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_6(sve_stbs_zsu, TCG_CALL_NO_WG,
|
||||
void, env, ptr, ptr, ptr, tl, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_sths_zsu, TCG_CALL_NO_WG,
|
||||
void, env, ptr, ptr, ptr, tl, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_stss_zsu, TCG_CALL_NO_WG,
|
||||
void, env, ptr, ptr, ptr, tl, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_6(sve_stbs_zss, TCG_CALL_NO_WG,
|
||||
void, env, ptr, ptr, ptr, tl, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_sths_zss, TCG_CALL_NO_WG,
|
||||
void, env, ptr, ptr, ptr, tl, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_stss_zss, TCG_CALL_NO_WG,
|
||||
void, env, ptr, ptr, ptr, tl, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_6(sve_stbd_zsu, TCG_CALL_NO_WG,
|
||||
void, env, ptr, ptr, ptr, tl, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_sthd_zsu, TCG_CALL_NO_WG,
|
||||
void, env, ptr, ptr, ptr, tl, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_stsd_zsu, TCG_CALL_NO_WG,
|
||||
void, env, ptr, ptr, ptr, tl, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_stdd_zsu, TCG_CALL_NO_WG,
|
||||
void, env, ptr, ptr, ptr, tl, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_6(sve_stbd_zss, TCG_CALL_NO_WG,
|
||||
void, env, ptr, ptr, ptr, tl, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_sthd_zss, TCG_CALL_NO_WG,
|
||||
void, env, ptr, ptr, ptr, tl, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_stsd_zss, TCG_CALL_NO_WG,
|
||||
void, env, ptr, ptr, ptr, tl, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_stdd_zss, TCG_CALL_NO_WG,
|
||||
void, env, ptr, ptr, ptr, tl, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_6(sve_stbd_zd, TCG_CALL_NO_WG,
|
||||
void, env, ptr, ptr, ptr, tl, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_sthd_zd, TCG_CALL_NO_WG,
|
||||
void, env, ptr, ptr, ptr, tl, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_stsd_zd, TCG_CALL_NO_WG,
|
||||
void, env, ptr, ptr, ptr, tl, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_stdd_zd, TCG_CALL_NO_WG,
|
||||
void, env, ptr, ptr, ptr, tl, i32)
|
||||
|
|
|
@ -80,6 +80,7 @@
|
|||
&rpri_load rd pg rn imm dtype nreg
|
||||
&rprr_store rd pg rn rm msz esz nreg
|
||||
&rpri_store rd pg rn imm msz esz nreg
|
||||
&rprr_scatter_store rd pg rn rm esz msz xs scale
|
||||
|
||||
###########################################################################
|
||||
# Named instruction formats. These are generally used to
|
||||
|
@ -198,6 +199,8 @@
|
|||
@rpri_store_msz ....... msz:2 .. . imm:s4 ... pg:3 rn:5 rd:5 &rpri_store
|
||||
@rprr_store_esz_n0 ....... .. esz:2 rm:5 ... pg:3 rn:5 rd:5 \
|
||||
&rprr_store nreg=0
|
||||
@rprr_scatter_store ....... msz:2 .. rm:5 ... pg:3 rn:5 rd:5 \
|
||||
&rprr_scatter_store
|
||||
|
||||
###########################################################################
|
||||
# Instruction patterns. Grouped according to the SVE encodingindex.xhtml.
|
||||
|
@ -825,3 +828,39 @@ ST_zpri 1110010 .. nreg:2 1.... 111 ... ..... ..... \
|
|||
# SVE store multiple structures (scalar plus scalar) (nreg != 0)
|
||||
ST_zprr 1110010 msz:2 nreg:2 ..... 011 ... ..... ..... \
|
||||
@rprr_store esz=%size_23
|
||||
|
||||
# SVE 32-bit scatter store (scalar plus 32-bit scaled offsets)
|
||||
# Require msz > 0 && msz <= esz.
|
||||
ST1_zprz 1110010 .. 11 ..... 100 ... ..... ..... \
|
||||
@rprr_scatter_store xs=0 esz=2 scale=1
|
||||
ST1_zprz 1110010 .. 11 ..... 110 ... ..... ..... \
|
||||
@rprr_scatter_store xs=1 esz=2 scale=1
|
||||
|
||||
# SVE 32-bit scatter store (scalar plus 32-bit unscaled offsets)
|
||||
# Require msz <= esz.
|
||||
ST1_zprz 1110010 .. 10 ..... 100 ... ..... ..... \
|
||||
@rprr_scatter_store xs=0 esz=2 scale=0
|
||||
ST1_zprz 1110010 .. 10 ..... 110 ... ..... ..... \
|
||||
@rprr_scatter_store xs=1 esz=2 scale=0
|
||||
|
||||
# SVE 64-bit scatter store (scalar plus 64-bit scaled offset)
|
||||
# Require msz > 0
|
||||
ST1_zprz 1110010 .. 01 ..... 101 ... ..... ..... \
|
||||
@rprr_scatter_store xs=2 esz=3 scale=1
|
||||
|
||||
# SVE 64-bit scatter store (scalar plus 64-bit unscaled offset)
|
||||
ST1_zprz 1110010 .. 00 ..... 101 ... ..... ..... \
|
||||
@rprr_scatter_store xs=2 esz=3 scale=0
|
||||
|
||||
# SVE 64-bit scatter store (scalar plus unpacked 32-bit scaled offset)
|
||||
# Require msz > 0
|
||||
ST1_zprz 1110010 .. 01 ..... 100 ... ..... ..... \
|
||||
@rprr_scatter_store xs=0 esz=3 scale=1
|
||||
ST1_zprz 1110010 .. 01 ..... 110 ... ..... ..... \
|
||||
@rprr_scatter_store xs=1 esz=3 scale=1
|
||||
|
||||
# SVE 64-bit scatter store (scalar plus unpacked 32-bit unscaled offset)
|
||||
ST1_zprz 1110010 .. 00 ..... 100 ... ..... ..... \
|
||||
@rprr_scatter_store xs=0 esz=3 scale=0
|
||||
ST1_zprz 1110010 .. 00 ..... 110 ... ..... ..... \
|
||||
@rprr_scatter_store xs=1 esz=3 scale=0
|
||||
|
|
|
@ -3712,3 +3712,64 @@ DO_ZPZ_FP(sve_ucvt_ds, uint64_t, , uint64_to_float32)
|
|||
DO_ZPZ_FP(sve_ucvt_dd, uint64_t, , uint64_to_float64)
|
||||
|
||||
#undef DO_ZPZ_FP
|
||||
|
||||
/* 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)
|
||||
|
|
|
@ -39,6 +39,9 @@ typedef void gen_helper_gvec_flags_4(TCGContext *, TCGv_i32, TCGv_ptr, TCGv_ptr,
|
|||
TCGv_ptr, TCGv_ptr, TCGv_i32);
|
||||
|
||||
typedef void gen_helper_gvec_mem(TCGContext *, TCGv_env, TCGv_ptr, TCGv_i64, TCGv_i32);
|
||||
typedef void gen_helper_gvec_mem_scatter(TCGContext *, TCGv_env, TCGv_ptr, TCGv_ptr,
|
||||
TCGv_ptr, TCGv_i64, TCGv_i32);
|
||||
|
||||
|
||||
/*
|
||||
* Helpers for extracting complex instruction fields.
|
||||
|
@ -3946,7 +3949,7 @@ static void do_str(DisasContext *s, uint32_t vofs, uint32_t len,
|
|||
|
||||
gen_set_label(tcg_ctx, loop);
|
||||
|
||||
t2 = tcg_temp_new_ptr(tcg_ctx, );
|
||||
t2 = tcg_temp_new_ptr(tcg_ctx);
|
||||
tcg_gen_add_ptr(tcg_ctx, t2, tcg_ctx->cpu_env, i);
|
||||
tcg_gen_ld_i64(tcg_ctx, t0, t2, vofs);
|
||||
|
||||
|
@ -4388,3 +4391,77 @@ static bool trans_ST_zpri(DisasContext *s, arg_rpri_store *a, uint32_t insn)
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
*** SVE gather loads / scatter stores
|
||||
*/
|
||||
|
||||
static void do_mem_zpz(DisasContext *s, int zt, int pg, int zm, int scale,
|
||||
TCGv_i64 scalar, gen_helper_gvec_mem_scatter *fn)
|
||||
{
|
||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||
unsigned vsz = vec_full_reg_size(s);
|
||||
TCGv_i32 desc = tcg_const_i32(tcg_ctx, simd_desc(vsz, vsz, scale));
|
||||
TCGv_ptr t_zm = tcg_temp_new_ptr(tcg_ctx);
|
||||
TCGv_ptr t_pg = tcg_temp_new_ptr(tcg_ctx);
|
||||
TCGv_ptr t_zt = tcg_temp_new_ptr(tcg_ctx);
|
||||
|
||||
tcg_gen_addi_ptr(tcg_ctx, t_pg, tcg_ctx->cpu_env, pred_full_reg_offset(s, pg));
|
||||
tcg_gen_addi_ptr(tcg_ctx, t_zm, tcg_ctx->cpu_env, vec_full_reg_offset(s, zm));
|
||||
tcg_gen_addi_ptr(tcg_ctx, t_zt, tcg_ctx->cpu_env, vec_full_reg_offset(s, zt));
|
||||
fn(tcg_ctx, tcg_ctx->cpu_env, t_zt, t_pg, t_zm, scalar, desc);
|
||||
|
||||
tcg_temp_free_ptr(tcg_ctx, t_zt);
|
||||
tcg_temp_free_ptr(tcg_ctx, t_zm);
|
||||
tcg_temp_free_ptr(tcg_ctx, t_pg);
|
||||
tcg_temp_free_i32(tcg_ctx, desc);
|
||||
}
|
||||
|
||||
static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a, uint32_t insn)
|
||||
{
|
||||
/* Indexed by [xs][msz]. */
|
||||
static gen_helper_gvec_mem_scatter * const fn32[2][3] = {
|
||||
{ gen_helper_sve_stbs_zsu,
|
||||
gen_helper_sve_sths_zsu,
|
||||
gen_helper_sve_stss_zsu, },
|
||||
{ gen_helper_sve_stbs_zss,
|
||||
gen_helper_sve_sths_zss,
|
||||
gen_helper_sve_stss_zss, },
|
||||
};
|
||||
/* Note that we overload xs=2 to indicate 64-bit offset. */
|
||||
static gen_helper_gvec_mem_scatter * const fn64[3][4] = {
|
||||
{ gen_helper_sve_stbd_zsu,
|
||||
gen_helper_sve_sthd_zsu,
|
||||
gen_helper_sve_stsd_zsu,
|
||||
gen_helper_sve_stdd_zsu, },
|
||||
{ gen_helper_sve_stbd_zss,
|
||||
gen_helper_sve_sthd_zss,
|
||||
gen_helper_sve_stsd_zss,
|
||||
gen_helper_sve_stdd_zss, },
|
||||
{ gen_helper_sve_stbd_zd,
|
||||
gen_helper_sve_sthd_zd,
|
||||
gen_helper_sve_stsd_zd,
|
||||
gen_helper_sve_stdd_zd, },
|
||||
};
|
||||
gen_helper_gvec_mem_scatter *fn;
|
||||
|
||||
if (a->esz < a->msz || (a->msz == 0 && a->scale)) {
|
||||
return false;
|
||||
}
|
||||
if (!sve_access_check(s)) {
|
||||
return true;
|
||||
}
|
||||
switch (a->esz) {
|
||||
case MO_32:
|
||||
fn = fn32[a->xs][a->msz];
|
||||
break;
|
||||
case MO_64:
|
||||
fn = fn64[a->xs][a->msz];
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
do_mem_zpz(s, a->rd, a->pg, a->rm, a->scale * a->msz,
|
||||
cpu_reg_sp(s, a->rn), fn);
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue