mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-02-02 07:01:09 +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
|
||||
#
|
||||
# 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
|
||||
# is a simple transformation of the A32 encoding.
|
||||
|
@ -27,3 +31,16 @@
|
|||
# 0b111p_1111_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
|
||||
# This file works on the A32 encoding only; calling code for T32 has to
|
||||
# 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);
|
||||
|
||||
/* 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 */
|
||||
|
|
|
@ -572,3 +572,42 @@ static bool trans_VLDST_single(DisasContext *s, arg_VLDST_single *a)
|
|||
|
||||
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;
|
||||
|
||||
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:
|
||||
tcg_gen_gvec_4(tcg_ctx, rd_ofs, offsetof(CPUARMState, vfp.qc),
|
||||
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,
|
||||
u ? &ushl_op[size] : &sshl_op[size]);
|
||||
return 0;
|
||||
|
||||
case NEON_3R_VADD_VSUB:
|
||||
/* Already handled by decodetree */
|
||||
return 1;
|
||||
}
|
||||
|
||||
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) \
|
||||
({ 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 */
|
||||
|
|
Loading…
Reference in a new issue