From 4ca33c54a270be5da35eab829f7f0768e3c41b1a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 25 Feb 2021 12:20:56 -0500 Subject: [PATCH] target/arm: Convert Neon 2-reg-misc VSHLL to decodetree Convert the VSHLL insn in the 2-reg-misc Neon group to decodetree. Backports commit 749e2be36d75f11d5fa8f8277e2a0569bd2a1c97 from qemu --- qemu/target/arm/neon-dp.decode | 2 ++ qemu/target/arm/translate-neon.inc.c | 53 ++++++++++++++++++++++++++++ qemu/target/arm/translate.c | 36 +------------------ 3 files changed, 56 insertions(+), 35 deletions(-) diff --git a/qemu/target/arm/neon-dp.decode b/qemu/target/arm/neon-dp.decode index 2277b4c7..0102aa72 100644 --- a/qemu/target/arm/neon-dp.decode +++ b/qemu/target/arm/neon-dp.decode @@ -459,6 +459,8 @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm # VQMOVN: signed result, source may be signed (_S) or unsigned (_U) VQMOVN_S 1111 001 11 . 11 .. 10 .... 0 0101 0 . 0 .... @2misc_q0 VQMOVN_U 1111 001 11 . 11 .. 10 .... 0 0101 1 . 0 .... @2misc_q0 + + VSHLL 1111 001 11 . 11 .. 10 .... 0 0110 0 . 0 .... @2misc_q0 ] # Subgroup for size != 0b11 diff --git a/qemu/target/arm/translate-neon.inc.c b/qemu/target/arm/translate-neon.inc.c index 6de6c66b..f13ce1f9 100644 --- a/qemu/target/arm/translate-neon.inc.c +++ b/qemu/target/arm/translate-neon.inc.c @@ -3343,3 +3343,56 @@ DO_VMOVN(VMOVN, gen_neon_narrow_u) DO_VMOVN(VQMOVUN, gen_helper_neon_unarrow_sat) DO_VMOVN(VQMOVN_S, gen_helper_neon_narrow_sat_s) DO_VMOVN(VQMOVN_U, gen_helper_neon_narrow_sat_u) + +static bool trans_VSHLL(DisasContext *s, arg_2misc *a) +{ + TCGContext *tcg_ctx = s->uc->tcg_ctx; + TCGv_i32 rm0, rm1; + TCGv_i64 rd; + static NeonGenWidenFn * const widenfns[] = { + gen_helper_neon_widen_u8, + gen_helper_neon_widen_u16, + tcg_gen_extu_i32_i64, + NULL, + }; + NeonGenWidenFn *widenfn = widenfns[a->size]; + + 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->vm) & 0x10)) { + return false; + } + + if (a->vd & 1) { + return false; + } + + if (!widenfn) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + rd = tcg_temp_new_i64(tcg_ctx); + + rm0 = neon_load_reg(s, a->vm, 0); + rm1 = neon_load_reg(s, a->vm, 1); + + widenfn(tcg_ctx, rd, rm0); + tcg_gen_shli_i64(tcg_ctx, rd, rd, 8 << a->size); + neon_store_reg64(s, rd, a->vd); + widenfn(tcg_ctx, rd, rm1); + tcg_gen_shli_i64(tcg_ctx, rd, rd, 8 << a->size); + neon_store_reg64(s, rd, a->vd + 1); + + tcg_temp_free_i64(tcg_ctx, rd); + tcg_temp_free_i32(tcg_ctx, rm0); + tcg_temp_free_i32(tcg_ctx, rm1); + return true; +} diff --git a/qemu/target/arm/translate.c b/qemu/target/arm/translate.c index c56985a6..0518c574 100644 --- a/qemu/target/arm/translate.c +++ b/qemu/target/arm/translate.c @@ -3081,27 +3081,6 @@ static void gen_neon_trn_u16(DisasContext *s, TCGv_i32 t0, TCGv_i32 t1) tcg_temp_free_i32(tcg_ctx, rd); } -static inline void gen_neon_widen(DisasContext *s, TCGv_i64 dest, TCGv_i32 src, int size, int u) -{ - TCGContext *tcg_ctx = s->uc->tcg_ctx; - if (u) { - switch (size) { - case 0: gen_helper_neon_widen_u8(tcg_ctx, dest, src); break; - case 1: gen_helper_neon_widen_u16(tcg_ctx, dest, src); break; - case 2: tcg_gen_extu_i32_i64(tcg_ctx, dest, src); break; - default: abort(); - } - } else { - switch (size) { - case 0: gen_helper_neon_widen_s8(tcg_ctx, dest, src); break; - case 1: gen_helper_neon_widen_s16(tcg_ctx, dest, src); break; - case 2: tcg_gen_ext_i32_i64(tcg_ctx, dest, src); break; - default: abort(); - } - } - tcg_temp_free_i32(tcg_ctx, src); -} - /* Symbolic constants for op fields for Neon 2-register miscellaneous. * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B * table A7-13. @@ -5052,6 +5031,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) case NEON_2RM_VUZP: case NEON_2RM_VZIP: case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN: + case NEON_2RM_VSHLL: /* handled by decodetree */ return 1; case NEON_2RM_VTRN: @@ -5067,20 +5047,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) goto elementwise; } break; - case NEON_2RM_VSHLL: - if (q || (rd & 1)) { - return 1; - } - tmp = neon_load_reg(s, rm, 0); - tmp2 = neon_load_reg(s, rm, 1); - for (pass = 0; pass < 2; pass++) { - if (pass == 1) - tmp = tmp2; - gen_neon_widen(s, s->V0, tmp, size, 1); - tcg_gen_shli_i64(tcg_ctx, s->V0, s->V0, 8 << size); - neon_store_reg64(s, s->V0, rd + pass); - } - break; case NEON_2RM_VCVT_F16_F32: { TCGv_ptr fpst;