mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-07-07 14:20:37 +00:00
target/arm: Convert Neon 3-reg-same VADD/VSUB to decodetree
Convert the Neon 3-reg-same VADD and VSUB insns to decodetree. Note that we don't need the neon_3r_sizes[op] check here because all size values are OK for VADD and VSUB; we'll add this when we convert the first insn that has size restrictions. For this we need one of the GVecGen*Fn typedefs currently in translate-a64.h; move them all to translate.h as a block so they are visible to the 32-bit decoder. Backports commit a4e143ac5b9185f670d2f17ee9cc1a430047cb65 from qemu
This commit is contained in:
parent
c7a31355fc
commit
eae3ce9899
|
@ -18,6 +18,10 @@
|
||||||
#
|
#
|
||||||
# This file is processed by scripts/decodetree.py
|
# This file is processed by scripts/decodetree.py
|
||||||
#
|
#
|
||||||
|
# VFP/Neon register fields; same as vfp.decode
|
||||||
|
%vm_dp 5:1 0:4
|
||||||
|
%vn_dp 7:1 16:4
|
||||||
|
%vd_dp 22:1 12:4
|
||||||
|
|
||||||
# Encodings for Neon data processing instructions where the T32 encoding
|
# Encodings for Neon data processing instructions where the T32 encoding
|
||||||
# is a simple transformation of the A32 encoding.
|
# is a simple transformation of the A32 encoding.
|
||||||
|
@ -27,3 +31,16 @@
|
||||||
# 0b111p_1111_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
|
# 0b111p_1111_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
|
||||||
# This file works on the A32 encoding only; calling code for T32 has to
|
# This file works on the A32 encoding only; calling code for T32 has to
|
||||||
# transform the insn into the A32 version first.
|
# transform the insn into the A32 version first.
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# 3-reg-same grouping:
|
||||||
|
# 1111 001 U 0 D sz:2 Vn:4 Vd:4 opc:4 N Q M op Vm:4
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
&3same vm vn vd q size
|
||||||
|
|
||||||
|
@3same .... ... . . . size:2 .... .... .... . q:1 . . .... \
|
||||||
|
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
|
||||||
|
|
||||||
|
VADD_3s 1111 001 0 0 . .. .... .... 1000 . . . 0 .... @3same
|
||||||
|
VSUB_3s 1111 001 1 0 . .. .... .... 1000 . . . 0 .... @3same
|
||||||
|
|
|
@ -116,13 +116,4 @@ static inline int vec_full_reg_size(DisasContext *s)
|
||||||
|
|
||||||
bool disas_sve(DisasContext *, uint32_t);
|
bool disas_sve(DisasContext *, uint32_t);
|
||||||
|
|
||||||
/* Note that the gvec expanders operate on offsets + sizes. */
|
|
||||||
typedef void GVecGen2Fn(TCGContext *, unsigned, uint32_t, uint32_t, uint32_t, uint32_t);
|
|
||||||
typedef void GVecGen2iFn(TCGContext *, unsigned, uint32_t, uint32_t, int64_t,
|
|
||||||
uint32_t, uint32_t);
|
|
||||||
typedef void GVecGen3Fn(TCGContext *, unsigned, uint32_t, uint32_t,
|
|
||||||
uint32_t, uint32_t, uint32_t);
|
|
||||||
typedef void GVecGen4Fn(TCGContext *, unsigned, uint32_t, uint32_t, uint32_t,
|
|
||||||
uint32_t, uint32_t, uint32_t);
|
|
||||||
|
|
||||||
#endif /* TARGET_ARM_TRANSLATE_A64_H */
|
#endif /* TARGET_ARM_TRANSLATE_A64_H */
|
||||||
|
|
|
@ -572,3 +572,42 @@ static bool trans_VLDST_single(DisasContext *s, arg_VLDST_single *a)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool do_3same(DisasContext *s, arg_3same *a, GVecGen3Fn fn)
|
||||||
|
{
|
||||||
|
int vec_size = a->q ? 16 : 8;
|
||||||
|
int rd_ofs = neon_reg_offset(a->vd, 0);
|
||||||
|
int rn_ofs = neon_reg_offset(a->vn, 0);
|
||||||
|
int rm_ofs = neon_reg_offset(a->vm, 0);
|
||||||
|
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->vn | a->vm) & 0x10)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((a->vn | a->vm | a->vd) & a->q) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vfp_access_check(s)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn(tcg_ctx, a->size, rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DO_3SAME(INSN, FUNC) \
|
||||||
|
static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \
|
||||||
|
{ \
|
||||||
|
return do_3same(s, a, FUNC); \
|
||||||
|
}
|
||||||
|
|
||||||
|
DO_3SAME(VADD, tcg_gen_gvec_add)
|
||||||
|
DO_3SAME(VSUB, tcg_gen_gvec_sub)
|
||||||
|
|
|
@ -5016,16 +5016,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case NEON_3R_VADD_VSUB:
|
|
||||||
if (u) {
|
|
||||||
tcg_gen_gvec_sub(tcg_ctx, size, rd_ofs, rn_ofs, rm_ofs,
|
|
||||||
vec_size, vec_size);
|
|
||||||
} else {
|
|
||||||
tcg_gen_gvec_add(tcg_ctx, size, rd_ofs, rn_ofs, rm_ofs,
|
|
||||||
vec_size, vec_size);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case NEON_3R_VQADD:
|
case NEON_3R_VQADD:
|
||||||
tcg_gen_gvec_4(tcg_ctx, rd_ofs, offsetof(CPUARMState, vfp.qc),
|
tcg_gen_gvec_4(tcg_ctx, rd_ofs, offsetof(CPUARMState, vfp.qc),
|
||||||
rn_ofs, rm_ofs, vec_size, vec_size,
|
rn_ofs, rm_ofs, vec_size, vec_size,
|
||||||
|
@ -5101,6 +5091,10 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
|
||||||
tcg_gen_gvec_3(tcg_ctx, rd_ofs, rm_ofs, rn_ofs, vec_size, vec_size,
|
tcg_gen_gvec_3(tcg_ctx, rd_ofs, rm_ofs, rn_ofs, vec_size, vec_size,
|
||||||
u ? &ushl_op[size] : &sshl_op[size]);
|
u ? &ushl_op[size] : &sshl_op[size]);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
case NEON_3R_VADD_VSUB:
|
||||||
|
/* Already handled by decodetree */
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == 3) {
|
if (size == 3) {
|
||||||
|
|
|
@ -312,4 +312,13 @@ void gen_sshl_i64(TCGContext* tcg_ctx, TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
|
||||||
#define dc_isar_feature(name, ctx) \
|
#define dc_isar_feature(name, ctx) \
|
||||||
({ DisasContext *ctx_ = (ctx); isar_feature_##name(ctx_->isar); })
|
({ DisasContext *ctx_ = (ctx); isar_feature_##name(ctx_->isar); })
|
||||||
|
|
||||||
|
/* Note that the gvec expanders operate on offsets + sizes. */
|
||||||
|
typedef void GVecGen2Fn(TCGContext *, unsigned, uint32_t, uint32_t, uint32_t, uint32_t);
|
||||||
|
typedef void GVecGen2iFn(TCGContext *, unsigned, uint32_t, uint32_t, int64_t,
|
||||||
|
uint32_t, uint32_t);
|
||||||
|
typedef void GVecGen3Fn(TCGContext *, unsigned, uint32_t, uint32_t,
|
||||||
|
uint32_t, uint32_t, uint32_t);
|
||||||
|
typedef void GVecGen4Fn(TCGContext *, unsigned, uint32_t, uint32_t, uint32_t,
|
||||||
|
uint32_t, uint32_t, uint32_t);
|
||||||
|
|
||||||
#endif /* TARGET_ARM_TRANSLATE_H */
|
#endif /* TARGET_ARM_TRANSLATE_H */
|
||||||
|
|
Loading…
Reference in a new issue