target/arm: Convert VZIP, VUZP to decodetree

Convert the Neon VZIP and VUZP insns in the 2-reg-misc group to
decodetree.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20200616170844.13318-4-peter.maydell@linaro.org
This commit is contained in:
Peter Maydell 2020-06-16 18:08:26 +01:00
parent 6106af3aa2
commit 567663a2af
3 changed files with 79 additions and 90 deletions

View file

@ -447,6 +447,9 @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
VPADAL_S 1111 001 11 . 11 .. 00 .... 0 1100 . . 0 .... @2misc
VPADAL_U 1111 001 11 . 11 .. 00 .... 0 1101 . . 0 .... @2misc
VUZP 1111 001 11 . 11 .. 10 .... 0 0010 . . 0 .... @2misc
VZIP 1111 001 11 . 11 .. 10 .... 0 0011 . . 0 .... @2misc
]
# Subgroup for size != 0b11

View file

@ -3169,3 +3169,77 @@ static bool trans_VPADAL_U(DisasContext *s, arg_2misc *a)
return do_2misc_pairwise(s, a, widenfn[a->size], opfn[a->size],
accfn[a->size]);
}
typedef void ZipFn(TCGv_ptr, TCGv_ptr);
static bool do_zip_uzp(DisasContext *s, arg_2misc *a,
ZipFn *fn)
{
TCGv_ptr pd, pm;
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->vm) & a->q) {
return false;
}
if (!fn) {
/* Bad size or size/q combination */
return false;
}
if (!vfp_access_check(s)) {
return true;
}
pd = vfp_reg_ptr(true, a->vd);
pm = vfp_reg_ptr(true, a->vm);
fn(pd, pm);
tcg_temp_free_ptr(pd);
tcg_temp_free_ptr(pm);
return true;
}
static bool trans_VUZP(DisasContext *s, arg_2misc *a)
{
static ZipFn * const fn[2][4] = {
{
gen_helper_neon_unzip8,
gen_helper_neon_unzip16,
NULL,
NULL,
}, {
gen_helper_neon_qunzip8,
gen_helper_neon_qunzip16,
gen_helper_neon_qunzip32,
NULL,
}
};
return do_zip_uzp(s, a, fn[a->q][a->size]);
}
static bool trans_VZIP(DisasContext *s, arg_2misc *a)
{
static ZipFn * const fn[2][4] = {
{
gen_helper_neon_zip8,
gen_helper_neon_zip16,
NULL,
NULL,
}, {
gen_helper_neon_qzip8,
gen_helper_neon_qzip16,
gen_helper_neon_qzip32,
NULL,
}
};
return do_zip_uzp(s, a, fn[a->q][a->size]);
}

View file

@ -2934,86 +2934,6 @@ static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
gen_rfe(s, pc, load_cpu_field(spsr));
}
static int gen_neon_unzip(int rd, int rm, int size, int q)
{
TCGv_ptr pd, pm;
if (!q && size == 2) {
return 1;
}
pd = vfp_reg_ptr(true, rd);
pm = vfp_reg_ptr(true, rm);
if (q) {
switch (size) {
case 0:
gen_helper_neon_qunzip8(pd, pm);
break;
case 1:
gen_helper_neon_qunzip16(pd, pm);
break;
case 2:
gen_helper_neon_qunzip32(pd, pm);
break;
default:
abort();
}
} else {
switch (size) {
case 0:
gen_helper_neon_unzip8(pd, pm);
break;
case 1:
gen_helper_neon_unzip16(pd, pm);
break;
default:
abort();
}
}
tcg_temp_free_ptr(pd);
tcg_temp_free_ptr(pm);
return 0;
}
static int gen_neon_zip(int rd, int rm, int size, int q)
{
TCGv_ptr pd, pm;
if (!q && size == 2) {
return 1;
}
pd = vfp_reg_ptr(true, rd);
pm = vfp_reg_ptr(true, rm);
if (q) {
switch (size) {
case 0:
gen_helper_neon_qzip8(pd, pm);
break;
case 1:
gen_helper_neon_qzip16(pd, pm);
break;
case 2:
gen_helper_neon_qzip32(pd, pm);
break;
default:
abort();
}
} else {
switch (size) {
case 0:
gen_helper_neon_zip8(pd, pm);
break;
case 1:
gen_helper_neon_zip16(pd, pm);
break;
default:
abort();
}
}
tcg_temp_free_ptr(pd);
tcg_temp_free_ptr(pm);
return 0;
}
static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
{
TCGv_i32 rd, tmp;
@ -5082,6 +5002,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
case NEON_2RM_VREV64:
case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
case NEON_2RM_VUZP:
case NEON_2RM_VZIP:
/* handled by decodetree */
return 1;
case NEON_2RM_VTRN:
@ -5097,16 +5019,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
goto elementwise;
}
break;
case NEON_2RM_VUZP:
if (gen_neon_unzip(rd, rm, size, q)) {
return 1;
}
break;
case NEON_2RM_VZIP:
if (gen_neon_zip(rd, rm, size, q)) {
return 1;
}
break;
case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
/* also VQMOVUN; op field and mnemonics don't line up */
if (rm & 1) {