Currently we use vfp_access_check() for AArch32 VFP and Neon instructions. This is not quite right: * there are optional CPACR.ASEDIS and HCPTR.TASE controls that allow trapping of just the Neon and not VFP instructions * Neon instructions are supposed to report a slightly different syndrome in HCR when they trap to AArch32 EL2
As a preliminary refactor so we have somewhere we can make this distinction, separate out Neon access checks into a separate neon_access_check(), which initially just calls vfp_access_check(). The set of insns this needs to cover are those described in section E1.3.9 of the DDI0487M.b Arm ARM. For us this corresponds to everything in neon-dp.decode and neon-ls.decode and thus in translate-neon.c, plus three insns that we handle in translate-vfp.c: - VDUP (general-purpose register) - VMOV (general-purpose register to scalar) byte and halfword - VMOV (scalar to general-purpose register) byte and halfword (which are the ones in that file with ARM_FEATURE_NEON checks). Signed-off-by: Peter Maydell <[email protected]> Reviewed-by: Richard Henderson <[email protected]> Message-id: [email protected] --- target/arm/tcg/translate-a32.h | 1 + target/arm/tcg/translate-neon.c | 74 ++++++++++++++++----------------- target/arm/tcg/translate-vfp.c | 33 +++++++++++---- 3 files changed, 62 insertions(+), 46 deletions(-) diff --git a/target/arm/tcg/translate-a32.h b/target/arm/tcg/translate-a32.h index a8df364171..1023cddab5 100644 --- a/target/arm/tcg/translate-a32.h +++ b/target/arm/tcg/translate-a32.h @@ -33,6 +33,7 @@ void load_reg_var(DisasContext *s, TCGv_i32 var, int reg); void arm_gen_condlabel(DisasContext *s); bool vfp_access_check(DisasContext *s); bool vfp_access_check_m(DisasContext *s, bool skip_context_update); +bool neon_access_check(DisasContext *s); void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop); void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop); void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop); diff --git a/target/arm/tcg/translate-neon.c b/target/arm/tcg/translate-neon.c index e3c7d9217b..50a44511d9 100644 --- a/target/arm/tcg/translate-neon.c +++ b/target/arm/tcg/translate-neon.c @@ -135,7 +135,7 @@ static bool do_neon_ddda(DisasContext *s, int q, int vd, int vn, int vm, return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -165,7 +165,7 @@ static bool do_neon_ddda_env(DisasContext *s, int q, int vd, int vn, int vm, return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -197,7 +197,7 @@ static bool do_neon_ddda_fpst(DisasContext *s, int q, int vd, int vn, int vm, return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -249,7 +249,7 @@ static bool trans_VCADD(DisasContext *s, arg_VCADD *a) return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -319,7 +319,7 @@ static bool trans_VFML(DisasContext *s, arg_VFML *a) return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -413,7 +413,7 @@ static bool trans_VFML_scalar(DisasContext *s, arg_VFML_scalar *a) return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -506,7 +506,7 @@ static bool trans_VLDST_multiple(DisasContext *s, arg_VLDST_multiple *a) return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -617,7 +617,7 @@ static bool trans_VLD_all_lanes(DisasContext *s, arg_VLD_all_lanes *a) } } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -714,7 +714,7 @@ static bool trans_VLDST_single(DisasContext *s, arg_VLDST_single *a) return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -798,7 +798,7 @@ static bool do_3same(DisasContext *s, arg_3same *a, GVecGen3Fn fn) return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -1076,7 +1076,7 @@ static bool do_vector_2sh(DisasContext *s, arg_2reg_shift *a, GVecGen2iFn *fn) return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -1126,7 +1126,7 @@ static bool do_2shift_narrow_64(DisasContext *s, arg_2reg_shift *a, return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -1177,7 +1177,7 @@ static bool do_2shift_narrow_32(DisasContext *s, arg_2reg_shift *a, return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -1302,7 +1302,7 @@ static bool do_vshll_2sh(DisasContext *s, arg_2reg_shift *a, return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -1392,7 +1392,7 @@ static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a, return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -1436,7 +1436,7 @@ static bool do_1reg_imm(DisasContext *s, arg_1reg_imm *a, return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -1499,7 +1499,7 @@ static bool do_prewiden_3d(DisasContext *s, arg_3diff *a, return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -1606,7 +1606,7 @@ static bool do_narrow_3d(DisasContext *s, arg_3diff *a, return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -1696,7 +1696,7 @@ static bool do_long_3d(DisasContext *s, arg_3diff *a, return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -1967,7 +1967,7 @@ static bool trans_VMULL_P_3d(DisasContext *s, arg_3diff *a) return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -2041,7 +2041,7 @@ static bool do_2scalar(DisasContext *s, arg_2scalar *a, return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -2139,7 +2139,7 @@ static bool do_2scalar_fp_vec(DisasContext *s, arg_2scalar *a, return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -2236,7 +2236,7 @@ static bool do_vqrdmlah_2sc(DisasContext *s, arg_2scalar *a, return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -2307,7 +2307,7 @@ static bool do_2scalar_long(DisasContext *s, arg_2scalar *a, return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -2451,7 +2451,7 @@ static bool trans_VEXT(DisasContext *s, arg_VEXT *a) return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -2520,7 +2520,7 @@ static bool trans_VTBL(DisasContext *s, arg_VTBL *a) return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -2555,7 +2555,7 @@ static bool trans_VDUP_scalar(DisasContext *s, arg_VDUP_scalar *a) return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -2591,7 +2591,7 @@ static bool do_zip_uzp(DisasContext *s, arg_2misc *a, return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -2660,7 +2660,7 @@ static bool do_vmovn(DisasContext *s, arg_2misc *a, return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -2724,7 +2724,7 @@ static bool trans_VSHLL(DisasContext *s, arg_2misc *a) return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -2764,7 +2764,7 @@ static bool trans_VCVT_B16_F32(DisasContext *s, arg_2misc *a) return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -2804,7 +2804,7 @@ static bool trans_VCVT_F16_F32(DisasContext *s, arg_2misc *a) return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -2850,7 +2850,7 @@ static bool trans_VCVT_F32_F16(DisasContext *s, arg_2misc *a) return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -2900,7 +2900,7 @@ static bool do_2misc_vec(DisasContext *s, arg_2misc *a, GVecGen2Fn *fn) return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -3028,7 +3028,7 @@ static bool do_2misc(DisasContext *s, arg_2misc *a, NeonGenOneOpFn *fn) return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -3232,7 +3232,7 @@ static bool trans_VSWP(DisasContext *s, arg_2misc *a) return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } @@ -3305,7 +3305,7 @@ static bool trans_VTRN(DisasContext *s, arg_2misc *a) return false; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } diff --git a/target/arm/tcg/translate-vfp.c b/target/arm/tcg/translate-vfp.c index 8d9d1ab877..6f6b234c9a 100644 --- a/target/arm/tcg/translate-vfp.c +++ b/target/arm/tcg/translate-vfp.c @@ -303,6 +303,17 @@ bool vfp_access_check(DisasContext *s) } } +/* + * Access check for Neon; this is for instructions which can be + * trapped by CPACR.ASEDIS and HCPTR.TASE. Support for those traps + * is optional and we currently do not implement them, so this + * is identical to a VFP access check for now. + */ +bool neon_access_check(DisasContext *s) +{ + return vfp_access_check(s); +} + static bool trans_VSEL(DisasContext *s, arg_VSEL *a) { uint32_t rd, rn, rm; @@ -620,15 +631,17 @@ static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a) { /* VMOV scalar to general purpose register */ TCGv_i32 tmp; + bool insn_is_neon = false; /* * SIZE == MO_32 is a VFP instruction; otherwise NEON. MVE has * all sizes, whether the CPU has fp or not. */ if (!dc_isar_feature(aa32_mve, s)) { - if (a->size == MO_32 - ? !dc_isar_feature(aa32_fpsp_v2, s) - : !arm_dc_feature(s, ARM_FEATURE_NEON)) { + insn_is_neon = a->size != MO_32; + if (insn_is_neon + ? !arm_dc_feature(s, ARM_FEATURE_NEON) + : !dc_isar_feature(aa32_fpsp_v2, s)) { return false; } } @@ -644,7 +657,7 @@ static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a) } } - if (!vfp_access_check(s)) { + if (!(insn_is_neon ? neon_access_check(s) : vfp_access_check(s))) { return true; } @@ -665,15 +678,17 @@ static bool trans_VMOV_from_gp(DisasContext *s, arg_VMOV_from_gp *a) { /* VMOV general purpose register to scalar */ TCGv_i32 tmp; + bool insn_is_neon = false; /* * SIZE == MO_32 is a VFP instruction; otherwise NEON. MVE has * all sizes, whether the CPU has fp or not. */ if (!dc_isar_feature(aa32_mve, s)) { - if (a->size == MO_32 - ? !dc_isar_feature(aa32_fpsp_v2, s) - : !arm_dc_feature(s, ARM_FEATURE_NEON)) { + insn_is_neon = a->size != MO_32; + if (insn_is_neon + ? !arm_dc_feature(s, ARM_FEATURE_NEON) + : !dc_isar_feature(aa32_fpsp_v2, s)) { return false; } } @@ -689,7 +704,7 @@ static bool trans_VMOV_from_gp(DisasContext *s, arg_VMOV_from_gp *a) } } - if (!vfp_access_check(s)) { + if (!(insn_is_neon ? neon_access_check(s) : vfp_access_check(s))) { return true; } @@ -736,7 +751,7 @@ static bool trans_VDUP(DisasContext *s, arg_VDUP *a) size = 2; } - if (!vfp_access_check(s)) { + if (!neon_access_check(s)) { return true; } -- 2.43.0
