diff options
author | Peter Maydell | 2020-06-16 11:32:26 +0200 |
---|---|---|
committer | Peter Maydell | 2020-06-16 11:32:26 +0200 |
commit | 18fb58d588898550919392277787979ee7d0d84e (patch) | |
tree | 95081ce9e65d312a84d51bee7e2ca50177bdb50e | |
parent | target/arm: Convert Neon 3-reg-diff saturating doubling multiplies (diff) | |
download | qemu-18fb58d588898550919392277787979ee7d0d84e.tar.gz qemu-18fb58d588898550919392277787979ee7d0d84e.tar.xz qemu-18fb58d588898550919392277787979ee7d0d84e.zip |
target/arm: Convert Neon 3-reg-diff polynomial VMULL
Convert the Neon 3-reg-diff insn polynomial VMULL. This is the last
insn in this group to be converted.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r-- | target/arm/neon-dp.decode | 2 | ||||
-rw-r--r-- | target/arm/translate-neon.inc.c | 43 | ||||
-rw-r--r-- | target/arm/translate.c | 60 |
3 files changed, 48 insertions, 57 deletions
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode index 65ea30d3ed..ed49726abf 100644 --- a/target/arm/neon-dp.decode +++ b/target/arm/neon-dp.decode @@ -465,5 +465,7 @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm VMULL_U_3d 1111 001 1 1 . .. .... .... 1100 . 0 . 0 .... @3diff VQDMULL_3d 1111 001 0 1 . .. .... .... 1101 . 0 . 0 .... @3diff + + VMULL_P_3d 1111 001 0 1 . .. .... .... 1110 . 0 . 0 .... @3diff ] } diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c index 083e3af8c5..c2cc10913f 100644 --- a/target/arm/translate-neon.inc.c +++ b/target/arm/translate-neon.inc.c @@ -2304,3 +2304,46 @@ static bool trans_VQDMLSL_3d(DisasContext *s, arg_3diff *a) return do_long_3d(s, a, opfn[a->size], accfn[a->size]); } + +static bool trans_VMULL_P_3d(DisasContext *s, arg_3diff *a) +{ + gen_helper_gvec_3 *fn_gvec; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vn | a->vm) & 0x10)) { + return false; + } + + if (a->vd & 1) { + return false; + } + + switch (a->size) { + case 0: + fn_gvec = gen_helper_neon_pmull_h; + break; + case 2: + if (!dc_isar_feature(aa32_pmull, s)) { + return false; + } + fn_gvec = gen_helper_gvec_pmull_q; + break; + default: + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + tcg_gen_gvec_3_ool(neon_reg_offset(a->vd, 0), + neon_reg_offset(a->vn, 0), + neon_reg_offset(a->vm, 0), + 16, 16, 0, fn_gvec); + return true; +} diff --git a/target/arm/translate.c b/target/arm/translate.c index 88e91845c0..f459fad864 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -5181,7 +5181,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) { int op; int q; - int rd, rn, rm, rd_ofs, rn_ofs, rm_ofs; + int rd, rn, rm, rd_ofs, rm_ofs; int size; int pass; int u; @@ -5215,7 +5215,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) size = (insn >> 20) & 3; vec_size = q ? 16 : 8; rd_ofs = neon_reg_offset(rd, 0); - rn_ofs = neon_reg_offset(rn, 0); rm_ofs = neon_reg_offset(rm, 0); if ((insn & (1 << 23)) == 0) { @@ -5228,61 +5227,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) if (size != 3) { op = (insn >> 8) & 0xf; if ((insn & (1 << 6)) == 0) { - /* Three registers of different lengths. */ - /* undefreq: bit 0 : UNDEF if size == 0 - * bit 1 : UNDEF if size == 1 - * bit 2 : UNDEF if size == 2 - * bit 3 : UNDEF if U == 1 - * Note that [2:0] set implies 'always UNDEF' - */ - int undefreq; - /* prewiden, src1_wide, src2_wide, undefreq */ - static const int neon_3reg_wide[16][4] = { - {0, 0, 0, 7}, /* VADDL: handled by decodetree */ - {0, 0, 0, 7}, /* VADDW: handled by decodetree */ - {0, 0, 0, 7}, /* VSUBL: handled by decodetree */ - {0, 0, 0, 7}, /* VSUBW: handled by decodetree */ - {0, 0, 0, 7}, /* VADDHN: handled by decodetree */ - {0, 0, 0, 7}, /* VABAL */ - {0, 0, 0, 7}, /* VSUBHN: handled by decodetree */ - {0, 0, 0, 7}, /* VABDL */ - {0, 0, 0, 7}, /* VMLAL */ - {0, 0, 0, 7}, /* VQDMLAL */ - {0, 0, 0, 7}, /* VMLSL */ - {0, 0, 0, 7}, /* VQDMLSL */ - {0, 0, 0, 7}, /* Integer VMULL */ - {0, 0, 0, 7}, /* VQDMULL */ - {0, 0, 0, 0xa}, /* Polynomial VMULL */ - {0, 0, 0, 7}, /* Reserved: always UNDEF */ - }; - - undefreq = neon_3reg_wide[op][3]; - - if ((undefreq & (1 << size)) || - ((undefreq & 8) && u)) { - return 1; - } - if (rd & 1) { - return 1; - } - - /* Handle polynomial VMULL in a single pass. */ - if (op == 14) { - if (size == 0) { - /* VMULL.P8 */ - tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, 16, 16, - 0, gen_helper_neon_pmull_h); - } else { - /* VMULL.P64 */ - if (!dc_isar_feature(aa32_pmull, s)) { - return 1; - } - tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, 16, 16, - 0, gen_helper_gvec_pmull_q); - } - return 0; - } - abort(); /* all others handled by decodetree */ + /* Three registers of different lengths: handled by decodetree */ + return 1; } else { /* Two registers and a scalar. NB that for ops of this form * the ARM ARM labels bit 24 as Q, but it is in our variable |