diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode index 91bc770dfb..6d890b2161 100644 --- a/target/arm/neon-dp.decode +++ b/target/arm/neon-dp.decode @@ -422,6 +422,13 @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm VTBL 1111 001 1 1 . 11 .... .... 10 len:2 . op:1 . 0 .... \ vm=%vm_dp vn=%vn_dp vd=%vd_dp + + VDUP_scalar 1111 001 1 1 . 11 index:3 1 .... 11 000 q:1 . 0 .... \ + vm=%vm_dp vd=%vd_dp size=0 + VDUP_scalar 1111 001 1 1 . 11 index:2 10 .... 11 000 q:1 . 0 .... \ + vm=%vm_dp vd=%vd_dp size=1 + VDUP_scalar 1111 001 1 1 . 11 index:1 100 .... 11 000 q:1 . 0 .... \ + vm=%vm_dp vd=%vd_dp size=2 ] # Subgroup for size != 0b11 diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c index da0e5dbc6f..a5aa56bbde 100644 --- a/target/arm/translate-neon.inc.c +++ b/target/arm/translate-neon.inc.c @@ -2944,3 +2944,29 @@ static bool trans_VTBL(DisasContext *s, arg_VTBL *a) tcg_temp_free_i32(tmp); return true; } + +static bool trans_VDUP_scalar(DisasContext *s, arg_VDUP_scalar *a) +{ + 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 & a->q) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + tcg_gen_gvec_dup_mem(a->size, neon_reg_offset(a->vd, 0), + neon_element_offset(a->vm, a->index, a->size), + a->q ? 16 : 8, a->q ? 16 : 8); + return true; +} diff --git a/target/arm/translate.c b/target/arm/translate.c index 0c6425928f..6d18892ade 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -5574,31 +5574,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) } break; } - } else if ((insn & (1 << 10)) == 0) { - /* VTBL, VTBX: handled by decodetree */ - return 1; - } else if ((insn & 0x380) == 0) { - /* VDUP */ - int element; - MemOp size; - - if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) { - return 1; - } - if (insn & (1 << 16)) { - size = MO_8; - element = (insn >> 17) & 7; - } else if (insn & (1 << 17)) { - size = MO_16; - element = (insn >> 18) & 3; - } else { - size = MO_32; - element = (insn >> 19) & 1; - } - tcg_gen_gvec_dup_mem(size, neon_reg_offset(rd, 0), - neon_element_offset(rm, element, size), - q ? 16 : 8, q ? 16 : 8); } else { + /* VTBL, VTBX, VDUP: handled by decodetree */ return 1; } }