diff --git a/qemu/aarch64.h b/qemu/aarch64.h index 9e394fbc..a32c0dd0 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -3282,6 +3282,10 @@ #define helper_sve_add_zpzz_d helper_sve_add_zpzz_d_aarch64 #define helper_sve_add_zpzz_h helper_sve_add_zpzz_h_aarch64 #define helper_sve_add_zpzz_s helper_sve_add_zpzz_s_aarch64 +#define helper_sve_adr_p32 helper_sve_adr_p32_aarch64 +#define helper_sve_adr_p64 helper_sve_adr_p64_aarch64 +#define helper_sve_adr_s32 helper_sve_adr_s32_aarch64 +#define helper_sve_adr_u32 helper_sve_adr_u32_aarch64 #define helper_sve_and_pppp helper_sve_and_pppp_aarch64 #define helper_sve_and_zpzz_b helper_sve_and_zpzz_b_aarch64 #define helper_sve_and_zpzz_d helper_sve_and_zpzz_d_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index 25013b55..30664e9a 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -3282,6 +3282,10 @@ #define helper_sve_add_zpzz_d helper_sve_add_zpzz_d_aarch64eb #define helper_sve_add_zpzz_h helper_sve_add_zpzz_h_aarch64eb #define helper_sve_add_zpzz_s helper_sve_add_zpzz_s_aarch64eb +#define helper_sve_adr_p32 helper_sve_adr_p32_aarch64eb +#define helper_sve_adr_p64 helper_sve_adr_p64_aarch64eb +#define helper_sve_adr_s32 helper_sve_adr_s32_aarch64eb +#define helper_sve_adr_u32 helper_sve_adr_u32_aarch64eb #define helper_sve_and_pppp helper_sve_and_pppp_aarch64eb #define helper_sve_and_zpzz_b helper_sve_and_zpzz_b_aarch64eb #define helper_sve_and_zpzz_d helper_sve_and_zpzz_d_aarch64eb diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 1b503bb5..cf550ec4 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -3303,6 +3303,10 @@ aarch64_symbols = ( 'helper_sve_add_zpzz_d', 'helper_sve_add_zpzz_h', 'helper_sve_add_zpzz_s', + 'helper_sve_adr_p32', + 'helper_sve_adr_p64', + 'helper_sve_adr_s32', + 'helper_sve_adr_u32', 'helper_sve_and_pppp', 'helper_sve_and_zpzz_b', 'helper_sve_and_zpzz_d', diff --git a/qemu/target/arm/helper-sve.h b/qemu/target/arm/helper-sve.h index 00e3cd48..5280d375 100644 --- a/qemu/target/arm/helper-sve.h +++ b/qemu/target/arm/helper-sve.h @@ -380,6 +380,11 @@ DEF_HELPER_FLAGS_4(sve_lsl_zzw_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(sve_lsl_zzw_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(sve_lsl_zzw_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(sve_adr_p32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(sve_adr_p64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(sve_adr_s32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(sve_adr_u32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + DEF_HELPER_FLAGS_5(sve_and_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_5(sve_bic_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_5(sve_eor_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) diff --git a/qemu/target/arm/sve.decode b/qemu/target/arm/sve.decode index e824bacf..58690fe5 100644 --- a/qemu/target/arm/sve.decode +++ b/qemu/target/arm/sve.decode @@ -48,6 +48,7 @@ &rr_esz rd rn esz &rri rd rn imm +&rrri rd rn rm imm &rri_esz rd rn imm esz &rrr_esz rd rn rm esz &rpr_esz rd pg rn esz @@ -75,6 +76,9 @@ # Three operand, vector element size @rd_rn_rm ........ esz:2 . rm:5 ... ... rn:5 rd:5 &rrr_esz +# Three operand with "memory" size, aka immediate left shift +@rd_rn_msz_rm ........ ... rm:5 .... imm:2 rn:5 rd:5 &rrri + # Two register operand, with governing predicate, vector element size @rdn_pg_rm ........ esz:2 ... ... ... pg:3 rm:5 rd:5 \ &rprr_esz rn=%reg_movprfx @@ -276,6 +280,14 @@ ASR_zzw 00000100 .. 1 ..... 1000 00 ..... ..... @rd_rn_rm LSR_zzw 00000100 .. 1 ..... 1000 01 ..... ..... @rd_rn_rm LSL_zzw 00000100 .. 1 ..... 1000 11 ..... ..... @rd_rn_rm +### SVE Compute Vector Address Group + +# SVE vector address generation +ADR_s32 00000100 00 1 ..... 1010 .. ..... ..... @rd_rn_msz_rm +ADR_u32 00000100 01 1 ..... 1010 .. ..... ..... @rd_rn_msz_rm +ADR_p32 00000100 10 1 ..... 1010 .. ..... ..... @rd_rn_msz_rm +ADR_p64 00000100 11 1 ..... 1010 .. ..... ..... @rd_rn_msz_rm + ### SVE Predicate Logical Operations Group # SVE predicate logical operations diff --git a/qemu/target/arm/sve_helper.c b/qemu/target/arm/sve_helper.c index 6eabcbc9..1126dc9e 100644 --- a/qemu/target/arm/sve_helper.c +++ b/qemu/target/arm/sve_helper.c @@ -1061,3 +1061,43 @@ void HELPER(sve_index_d)(void *vd, uint64_t start, d[i] = start + i * incr; } } + +void HELPER(sve_adr_p32)(void *vd, void *vn, void *vm, uint32_t desc) +{ + intptr_t i, opr_sz = simd_oprsz(desc) / 4; + uint32_t sh = simd_data(desc); + uint32_t *d = vd, *n = vn, *m = vm; + for (i = 0; i < opr_sz; i += 1) { + d[i] = n[i] + (m[i] << sh); + } +} + +void HELPER(sve_adr_p64)(void *vd, void *vn, void *vm, uint32_t desc) +{ + intptr_t i, opr_sz = simd_oprsz(desc) / 8; + uint64_t sh = simd_data(desc); + uint64_t *d = vd, *n = vn, *m = vm; + for (i = 0; i < opr_sz; i += 1) { + d[i] = n[i] + (m[i] << sh); + } +} + +void HELPER(sve_adr_s32)(void *vd, void *vn, void *vm, uint32_t desc) +{ + intptr_t i, opr_sz = simd_oprsz(desc) / 8; + uint64_t sh = simd_data(desc); + uint64_t *d = vd, *n = vn, *m = vm; + for (i = 0; i < opr_sz; i += 1) { + d[i] = n[i] + ((uint64_t)(int32_t)m[i] << sh); + } +} + +void HELPER(sve_adr_u32)(void *vd, void *vn, void *vm, uint32_t desc) +{ + intptr_t i, opr_sz = simd_oprsz(desc) / 8; + uint64_t sh = simd_data(desc); + uint64_t *d = vd, *n = vn, *m = vm; + for (i = 0; i < opr_sz; i += 1) { + d[i] = n[i] + ((uint64_t)(uint32_t)m[i] << sh); + } +} diff --git a/qemu/target/arm/translate-sve.c b/qemu/target/arm/translate-sve.c index 2bff73c3..4f6c9805 100644 --- a/qemu/target/arm/translate-sve.c +++ b/qemu/target/arm/translate-sve.c @@ -914,6 +914,43 @@ static bool trans_RDVL(DisasContext *s, arg_RDVL *a, uint32_t insn) return true; } +/* + *** SVE Compute Vector Address Group + */ + +static bool do_adr(DisasContext *s, arg_rrri *a, gen_helper_gvec_3 *fn) +{ + if (sve_access_check(s)) { + TCGContext *tcg_ctx = s->uc->tcg_ctx; + unsigned vsz = vec_full_reg_size(s); + tcg_gen_gvec_3_ool(tcg_ctx, vec_full_reg_offset(s, a->rd), + vec_full_reg_offset(s, a->rn), + vec_full_reg_offset(s, a->rm), + vsz, vsz, a->imm, fn); + } + return true; +} + +static bool trans_ADR_p32(DisasContext *s, arg_rrri *a, uint32_t insn) +{ + return do_adr(s, a, gen_helper_sve_adr_p32); +} + +static bool trans_ADR_p64(DisasContext *s, arg_rrri *a, uint32_t insn) +{ + return do_adr(s, a, gen_helper_sve_adr_p64); +} + +static bool trans_ADR_s32(DisasContext *s, arg_rrri *a, uint32_t insn) +{ + return do_adr(s, a, gen_helper_sve_adr_s32); +} + +static bool trans_ADR_u32(DisasContext *s, arg_rrri *a, uint32_t insn) +{ + return do_adr(s, a, gen_helper_sve_adr_u32); +} + /* *** SVE Predicate Logical Operations Group */