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
This commit is contained in:
Peter Maydell 2021-02-25 12:20:56 -05:00 committed by Lioncash
parent 48d57d0dc7
commit 4ca33c54a2
3 changed files with 56 additions and 35 deletions

View file

@ -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

View file

@ -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;
}

View file

@ -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;