mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-11 12:15:41 +00:00
target/arm: Convert VZIP, VUZP to decodetree
Convert the Neon VZIP and VUZP insns in the 2-reg-misc group to decodetree. Backports commit 567663a2af2457da8aa74f221b1f3f8a6d2eddf6 from qemu
This commit is contained in:
parent
d21fae82ba
commit
35d8a3e83f
|
@ -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_S 1111 001 11 . 11 .. 00 .... 0 1100 . . 0 .... @2misc
|
||||||
VPADAL_U 1111 001 11 . 11 .. 00 .... 0 1101 . . 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
|
# Subgroup for size != 0b11
|
||||||
|
|
|
@ -3208,3 +3208,78 @@ static bool trans_VPADAL_U(DisasContext *s, arg_2misc *a)
|
||||||
return do_2misc_pairwise(s, a, widenfn[a->size], opfn[a->size],
|
return do_2misc_pairwise(s, a, widenfn[a->size], opfn[a->size],
|
||||||
accfn[a->size]);
|
accfn[a->size]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef void ZipFn(TCGContext *, TCGv_ptr, TCGv_ptr);
|
||||||
|
|
||||||
|
static bool do_zip_uzp(DisasContext *s, arg_2misc *a,
|
||||||
|
ZipFn *fn)
|
||||||
|
{
|
||||||
|
TCGv_ptr pd, pm;
|
||||||
|
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->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(s, true, a->vd);
|
||||||
|
pm = vfp_reg_ptr(s, true, a->vm);
|
||||||
|
fn(tcg_ctx, pd, pm);
|
||||||
|
tcg_temp_free_ptr(tcg_ctx, pd);
|
||||||
|
tcg_temp_free_ptr(tcg_ctx, 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]);
|
||||||
|
}
|
||||||
|
|
|
@ -3038,88 +3038,6 @@ static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
|
||||||
gen_rfe(s, pc, load_cpu_field(s, spsr));
|
gen_rfe(s, pc, load_cpu_field(s, spsr));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gen_neon_unzip(DisasContext *s, int rd, int rm, int size, int q)
|
|
||||||
{
|
|
||||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
|
||||||
TCGv_ptr pd, pm;
|
|
||||||
|
|
||||||
if (!q && size == 2) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
pd = vfp_reg_ptr(s, true, rd);
|
|
||||||
pm = vfp_reg_ptr(s, true, rm);
|
|
||||||
if (q) {
|
|
||||||
switch (size) {
|
|
||||||
case 0:
|
|
||||||
gen_helper_neon_qunzip8(tcg_ctx, pd, pm);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
gen_helper_neon_qunzip16(tcg_ctx, pd, pm);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
gen_helper_neon_qunzip32(tcg_ctx, pd, pm);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch (size) {
|
|
||||||
case 0:
|
|
||||||
gen_helper_neon_unzip8(tcg_ctx, pd, pm);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
gen_helper_neon_unzip16(tcg_ctx, pd, pm);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tcg_temp_free_ptr(tcg_ctx, pd);
|
|
||||||
tcg_temp_free_ptr(tcg_ctx, pm);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int gen_neon_zip(DisasContext *s, int rd, int rm, int size, int q)
|
|
||||||
{
|
|
||||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
|
||||||
TCGv_ptr pd, pm;
|
|
||||||
|
|
||||||
if (!q && size == 2) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
pd = vfp_reg_ptr(s, true, rd);
|
|
||||||
pm = vfp_reg_ptr(s, true, rm);
|
|
||||||
if (q) {
|
|
||||||
switch (size) {
|
|
||||||
case 0:
|
|
||||||
gen_helper_neon_qzip8(tcg_ctx, pd, pm);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
gen_helper_neon_qzip16(tcg_ctx, pd, pm);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
gen_helper_neon_qzip32(tcg_ctx, pd, pm);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch (size) {
|
|
||||||
case 0:
|
|
||||||
gen_helper_neon_zip8(tcg_ctx, pd, pm);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
gen_helper_neon_zip16(tcg_ctx, pd, pm);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tcg_temp_free_ptr(tcg_ctx, pd);
|
|
||||||
tcg_temp_free_ptr(tcg_ctx, pm);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void gen_neon_trn_u8(DisasContext *s, TCGv_i32 t0, TCGv_i32 t1)
|
static void gen_neon_trn_u8(DisasContext *s, TCGv_i32 t0, TCGv_i32 t1)
|
||||||
{
|
{
|
||||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
|
@ -5194,6 +5112,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
|
||||||
case NEON_2RM_VREV64:
|
case NEON_2RM_VREV64:
|
||||||
case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
|
case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
|
||||||
case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
|
case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
|
||||||
|
case NEON_2RM_VUZP:
|
||||||
|
case NEON_2RM_VZIP:
|
||||||
/* handled by decodetree */
|
/* handled by decodetree */
|
||||||
return 1;
|
return 1;
|
||||||
case NEON_2RM_VTRN:
|
case NEON_2RM_VTRN:
|
||||||
|
@ -5209,16 +5129,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
|
||||||
goto elementwise;
|
goto elementwise;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NEON_2RM_VUZP:
|
|
||||||
if (gen_neon_unzip(s, rd, rm, size, q)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NEON_2RM_VZIP:
|
|
||||||
if (gen_neon_zip(s, rd, rm, size, q)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
|
case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
|
||||||
/* also VQMOVUN; op field and mnemonics don't line up */
|
/* also VQMOVUN; op field and mnemonics don't line up */
|
||||||
if (rm & 1) {
|
if (rm & 1) {
|
||||||
|
|
Loading…
Reference in a new issue