From aa97b6b7557f98181d00a67057c039f662df53a1 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 26 Feb 2021 14:51:15 -0500 Subject: [PATCH] target/arm: Convert integer multiply-add (indexed) to gvec for aa64 advsimd Backports 3607440c4df6498585a570cfc1041e4972b41b56 --- qemu/aarch64.h | 6 ++++++ qemu/aarch64eb.h | 6 ++++++ qemu/header_gen.py | 6 ++++++ qemu/target/arm/helper.h | 14 +++++++++++++ qemu/target/arm/translate-a64.c | 34 ++++++++++++++++++++++++++++++++ qemu/target/arm/vec_helper.c | 35 ++++++++++++++++++++++++++++----- 6 files changed, 96 insertions(+), 5 deletions(-) diff --git a/qemu/aarch64.h b/qemu/aarch64.h index 38a31815..4c1915d9 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -3582,6 +3582,12 @@ #define helper_frecpx_f32 helper_frecpx_f32_aarch64 #define helper_frecpx_f64 helper_frecpx_f64_aarch64 #define helper_fjcvtzs helper_fjcvtzs_aarch64 +#define helper_gvec_mla_idx_d helper_gvec_mla_idx_d_aarch64 +#define helper_gvec_mla_idx_h helper_gvec_mla_idx_h_aarch64 +#define helper_gvec_mla_idx_s helper_gvec_mla_idx_s_aarch64 +#define helper_gvec_mls_idx_d helper_gvec_mls_idx_d_aarch64 +#define helper_gvec_mls_idx_h helper_gvec_mls_idx_h_aarch64 +#define helper_gvec_mls_idx_s helper_gvec_mls_idx_s_aarch64 #define helper_gvec_mul_idx_d helper_gvec_mul_idx_d_aarch64 #define helper_gvec_mul_idx_h helper_gvec_mul_idx_h_aarch64 #define helper_gvec_mul_idx_s helper_gvec_mul_idx_s_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index 25d2c134..776d45e9 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -3582,6 +3582,12 @@ #define helper_frecpx_f32 helper_frecpx_f32_aarch64eb #define helper_frecpx_f64 helper_frecpx_f64_aarch64eb #define helper_fjcvtzs helper_fjcvtzs_aarch64eb +#define helper_gvec_mla_idx_d helper_gvec_mla_idx_d_aarch64eb +#define helper_gvec_mla_idx_h helper_gvec_mla_idx_h_aarch64eb +#define helper_gvec_mla_idx_s helper_gvec_mla_idx_s_aarch64eb +#define helper_gvec_mls_idx_d helper_gvec_mls_idx_d_aarch64eb +#define helper_gvec_mls_idx_h helper_gvec_mls_idx_h_aarch64eb +#define helper_gvec_mls_idx_s helper_gvec_mls_idx_s_aarch64eb #define helper_gvec_mul_idx_d helper_gvec_mul_idx_d_aarch64eb #define helper_gvec_mul_idx_h helper_gvec_mul_idx_h_aarch64eb #define helper_gvec_mul_idx_s helper_gvec_mul_idx_s_aarch64eb diff --git a/qemu/header_gen.py b/qemu/header_gen.py index f27a97af..efe4a115 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -3722,6 +3722,12 @@ aarch64_symbols = ( 'helper_frecpx_f32', 'helper_frecpx_f64', 'helper_fjcvtzs', + 'helper_gvec_mla_idx_d', + 'helper_gvec_mla_idx_h', + 'helper_gvec_mla_idx_s', + 'helper_gvec_mls_idx_d', + 'helper_gvec_mls_idx_h', + 'helper_gvec_mls_idx_s', 'helper_gvec_mul_idx_d', 'helper_gvec_mul_idx_h', 'helper_gvec_mul_idx_s', diff --git a/qemu/target/arm/helper.h b/qemu/target/arm/helper.h index b69e7d12..9977be4d 100644 --- a/qemu/target/arm/helper.h +++ b/qemu/target/arm/helper.h @@ -760,6 +760,20 @@ DEF_HELPER_FLAGS_4(gvec_mul_idx_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(gvec_mul_idx_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(gvec_mul_idx_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_mla_idx_h, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_mla_idx_s, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_mla_idx_d, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_5(gvec_mls_idx_h, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_mls_idx_s, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_mls_idx_d, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) + #ifdef TARGET_ARM #define helper_clz helper_clz_arm #define gen_helper_clz gen_helper_clz_arm diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index 56465a78..5636dd3b 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -13814,6 +13814,40 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn) return; } break; + + case 0x10: /* MLA */ + if (!is_long && !is_scalar) { + static gen_helper_gvec_4 * const fns[3] = { + gen_helper_gvec_mla_idx_h, + gen_helper_gvec_mla_idx_s, + gen_helper_gvec_mla_idx_d, + }; + tcg_gen_gvec_4_ool(tcg_ctx, vec_full_reg_offset(s, rd), + vec_full_reg_offset(s, rn), + vec_full_reg_offset(s, rm), + vec_full_reg_offset(s, rd), + is_q ? 16 : 8, vec_full_reg_size(s), + index, fns[size - 1]); + return; + } + break; + + case 0x14: /* MLS */ + if (!is_long && !is_scalar) { + static gen_helper_gvec_4 * const fns[3] = { + gen_helper_gvec_mls_idx_h, + gen_helper_gvec_mls_idx_s, + gen_helper_gvec_mls_idx_d, + }; + tcg_gen_gvec_4_ool(tcg_ctx, vec_full_reg_offset(s, rd), + vec_full_reg_offset(s, rn), + vec_full_reg_offset(s, rm), + vec_full_reg_offset(s, rd), + is_q ? 16 : 8, vec_full_reg_size(s), + index, fns[size - 1]); + return; + } + break; } if (size == 3) { diff --git a/qemu/target/arm/vec_helper.c b/qemu/target/arm/vec_helper.c index 8f11b344..d96f1ed0 100644 --- a/qemu/target/arm/vec_helper.c +++ b/qemu/target/arm/vec_helper.c @@ -732,7 +732,32 @@ DO_MUL_IDX(gvec_mul_idx_d, uint64_t, ) #undef DO_MUL_IDX -#define DO_MUL_IDX(NAME, TYPE, H) \ +#define DO_MLA_IDX(NAME, TYPE, OP, H) \ +void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, uint32_t desc) \ +{ \ + intptr_t i, j, oprsz = simd_oprsz(desc), segment = 16 / sizeof(TYPE); \ + intptr_t idx = simd_data(desc); \ + TYPE *d = vd, *n = vn, *m = vm, *a = va; \ + for (i = 0; i < oprsz / sizeof(TYPE); i += segment) { \ + TYPE mm = m[H(i + idx)]; \ + for (j = 0; j < segment; j++) { \ + d[i + j] = a[i + j] OP n[i + j] * mm; \ + } \ + } \ + clear_tail(d, oprsz, simd_maxsz(desc)); \ +} + +DO_MLA_IDX(gvec_mla_idx_h, uint16_t, +, H2) +DO_MLA_IDX(gvec_mla_idx_s, uint32_t, +, H4) +DO_MLA_IDX(gvec_mla_idx_d, uint64_t, +, ) + +DO_MLA_IDX(gvec_mls_idx_h, uint16_t, -, H2) +DO_MLA_IDX(gvec_mls_idx_s, uint32_t, -, H4) +DO_MLA_IDX(gvec_mls_idx_d, uint64_t, -, ) + +#undef DO_MLA_IDX + +#define DO_FMUL_IDX(NAME, TYPE, H) \ void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \ { \ intptr_t i, j, oprsz = simd_oprsz(desc), segment = 16 / sizeof(TYPE); \ @@ -747,11 +772,11 @@ void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \ clear_tail(d, oprsz, simd_maxsz(desc)); \ } -DO_MUL_IDX(gvec_fmul_idx_h, float16, H2) -DO_MUL_IDX(gvec_fmul_idx_s, float32, H4) -DO_MUL_IDX(gvec_fmul_idx_d, float64, ) +DO_FMUL_IDX(gvec_fmul_idx_h, float16, H2) +DO_FMUL_IDX(gvec_fmul_idx_s, float32, H4) +DO_FMUL_IDX(gvec_fmul_idx_d, float64, ) -#undef DO_MUL_IDX +#undef DO_FMUL_IDX #define DO_FMLA_IDX(NAME, TYPE, H) \ void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, \