mirror of https://github.com/xemu-project/xemu.git
target/arm: Convert Neon narrowing moves to decodetree
Convert the Neon narrowing moves VMQNV, VQMOVN, VQMOVUN 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-5-peter.maydell@linaro.org
This commit is contained in:
parent
567663a2af
commit
3882bdacb0
|
@ -439,6 +439,8 @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
|
|||
|
||||
@2misc .... ... .. . .. size:2 .. .... . .... q:1 . . .... \
|
||||
&2misc vm=%vm_dp vd=%vd_dp
|
||||
@2misc_q0 .... ... .. . .. size:2 .. .... . .... . . . .... \
|
||||
&2misc vm=%vm_dp vd=%vd_dp q=0
|
||||
|
||||
VREV64 1111 001 11 . 11 .. 00 .... 0 0000 . . 0 .... @2misc
|
||||
|
||||
|
@ -450,6 +452,13 @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
|
|||
|
||||
VUZP 1111 001 11 . 11 .. 10 .... 0 0010 . . 0 .... @2misc
|
||||
VZIP 1111 001 11 . 11 .. 10 .... 0 0011 . . 0 .... @2misc
|
||||
|
||||
VMOVN 1111 001 11 . 11 .. 10 .... 0 0100 0 . 0 .... @2misc_q0
|
||||
# VQMOVUN: unsigned result (source is always signed)
|
||||
VQMOVUN 1111 001 11 . 11 .. 10 .... 0 0100 1 . 0 .... @2misc_q0
|
||||
# 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
|
||||
]
|
||||
|
||||
# Subgroup for size != 0b11
|
||||
|
|
|
@ -3243,3 +3243,62 @@ static bool trans_VZIP(DisasContext *s, arg_2misc *a)
|
|||
};
|
||||
return do_zip_uzp(s, a, fn[a->q][a->size]);
|
||||
}
|
||||
|
||||
static bool do_vmovn(DisasContext *s, arg_2misc *a,
|
||||
NeonGenNarrowEnvFn *narrowfn)
|
||||
{
|
||||
TCGv_i64 rm;
|
||||
TCGv_i32 rd0, rd1;
|
||||
|
||||
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->vm & 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!narrowfn) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!vfp_access_check(s)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
rm = tcg_temp_new_i64();
|
||||
rd0 = tcg_temp_new_i32();
|
||||
rd1 = tcg_temp_new_i32();
|
||||
|
||||
neon_load_reg64(rm, a->vm);
|
||||
narrowfn(rd0, cpu_env, rm);
|
||||
neon_load_reg64(rm, a->vm + 1);
|
||||
narrowfn(rd1, cpu_env, rm);
|
||||
neon_store_reg(a->vd, 0, rd0);
|
||||
neon_store_reg(a->vd, 1, rd1);
|
||||
tcg_temp_free_i64(rm);
|
||||
return true;
|
||||
}
|
||||
|
||||
#define DO_VMOVN(INSN, FUNC) \
|
||||
static bool trans_##INSN(DisasContext *s, arg_2misc *a) \
|
||||
{ \
|
||||
static NeonGenNarrowEnvFn * const narrowfn[] = { \
|
||||
FUNC##8, \
|
||||
FUNC##16, \
|
||||
FUNC##32, \
|
||||
NULL, \
|
||||
}; \
|
||||
return do_vmovn(s, a, narrowfn[a->size]); \
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
@ -2975,46 +2975,6 @@ static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
|
|||
tcg_temp_free_i32(rd);
|
||||
}
|
||||
|
||||
static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
|
||||
{
|
||||
switch (size) {
|
||||
case 0: gen_helper_neon_narrow_u8(dest, src); break;
|
||||
case 1: gen_helper_neon_narrow_u16(dest, src); break;
|
||||
case 2: tcg_gen_extrl_i64_i32(dest, src); break;
|
||||
default: abort();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
|
||||
{
|
||||
switch (size) {
|
||||
case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
|
||||
case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
|
||||
case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
|
||||
default: abort();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
|
||||
{
|
||||
switch (size) {
|
||||
case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
|
||||
case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
|
||||
case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
|
||||
default: abort();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
|
||||
{
|
||||
switch (size) {
|
||||
case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
|
||||
case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
|
||||
case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
|
||||
default: abort();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
|
||||
{
|
||||
if (u) {
|
||||
|
@ -3035,24 +2995,6 @@ static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
|
|||
tcg_temp_free_i32(src);
|
||||
}
|
||||
|
||||
static void gen_neon_narrow_op(int op, int u, int size,
|
||||
TCGv_i32 dest, TCGv_i64 src)
|
||||
{
|
||||
if (op) {
|
||||
if (u) {
|
||||
gen_neon_unarrow_sats(size, dest, src);
|
||||
} else {
|
||||
gen_neon_narrow(size, dest, src);
|
||||
}
|
||||
} else {
|
||||
if (u) {
|
||||
gen_neon_narrow_satu(size, dest, src);
|
||||
} else {
|
||||
gen_neon_narrow_sats(size, dest, 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.
|
||||
|
@ -4994,8 +4936,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
|
|||
!arm_dc_feature(s, ARM_FEATURE_V8)) {
|
||||
return 1;
|
||||
}
|
||||
if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
|
||||
q && ((rm | rd) & 1)) {
|
||||
if (q && ((rm | rd) & 1)) {
|
||||
return 1;
|
||||
}
|
||||
switch (op) {
|
||||
|
@ -5004,6 +4945,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
|
|||
case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
|
||||
case NEON_2RM_VUZP:
|
||||
case NEON_2RM_VZIP:
|
||||
case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
|
||||
/* handled by decodetree */
|
||||
return 1;
|
||||
case NEON_2RM_VTRN:
|
||||
|
@ -5019,25 +4961,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
|
|||
goto elementwise;
|
||||
}
|
||||
break;
|
||||
case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
|
||||
/* also VQMOVUN; op field and mnemonics don't line up */
|
||||
if (rm & 1) {
|
||||
return 1;
|
||||
}
|
||||
tmp2 = NULL;
|
||||
for (pass = 0; pass < 2; pass++) {
|
||||
neon_load_reg64(cpu_V0, rm + pass);
|
||||
tmp = tcg_temp_new_i32();
|
||||
gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
|
||||
tmp, cpu_V0);
|
||||
if (pass == 0) {
|
||||
tmp2 = tmp;
|
||||
} else {
|
||||
neon_store_reg(rd, 0, tmp2);
|
||||
neon_store_reg(rd, 1, tmp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NEON_2RM_VSHLL:
|
||||
if (q || (rd & 1)) {
|
||||
return 1;
|
||||
|
|
Loading…
Reference in New Issue