target/arm: Convert Neon VDUP (scalar) to decodetree

Convert the Neon VDUP (scalar) insn to decodetree. (Note that we
can't call this just "VDUP" as we used that already in vfp.decode for
the "VDUP (general purpose register" insn.)

Backports commit 9aaa23c2ae18e6fb9a291b81baf91341db76dfa0 from qemu
This commit is contained in:
Peter Maydell 2020-06-17 00:43:16 -04:00 committed by Lioncash
parent 8de8a4500a
commit 709610e606
3 changed files with 35 additions and 24 deletions

View file

@ -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 .... \ VTBL 1111 001 1 1 . 11 .... .... 10 len:2 . op:1 . 0 .... \
vm=%vm_dp vn=%vn_dp vd=%vd_dp 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 # Subgroup for size != 0b11

View file

@ -2980,3 +2980,30 @@ static bool trans_VTBL(DisasContext *s, arg_VTBL *a)
tcg_temp_free_i32(tcg_ctx, tmp); tcg_temp_free_i32(tcg_ctx, tmp);
return true; return true;
} }
static bool trans_VDUP_scalar(DisasContext *s, arg_VDUP_scalar *a)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;
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(tcg_ctx, 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;
}

View file

@ -5688,31 +5688,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
} }
break; 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(tcg_ctx, size, neon_reg_offset(rd, 0),
neon_element_offset(rm, element, size),
q ? 16 : 8, q ? 16 : 8);
} else { } else {
/* VTBL, VTBX, VDUP: handled by decodetree */
return 1; return 1;
} }
} }