From 3f0ae7ccee2f8ae4a78946c3597e0e5f3b8d6d99 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 21 Mar 2020 23:48:11 -0400 Subject: [PATCH] target/arm: Replace ARM_FEATURE_VFP4 with isar_feature_aa32_simdfmac All remaining tests for VFP4 are for fused multiply-add insns. Since the MVFR1 field is used for both VFP and NEON, move its adjustment from the !has_neon block to the (!has_vfp && !has_neon) block. Test for vfp of the appropraite width alongside the test for simdfmac within translate-vfp.inc.c. Within disas_neon_data_insn, we have already tested for ARM_FEATURE_NEON. Backports commit c52881bbc22b50db99a6c37171ad3eea7d959ae6 from qemu --- qemu/target/arm/cpu.h | 12 ++++++++++++ qemu/target/arm/translate-vfp.inc.c | 24 ++++++++++++++++++++---- qemu/target/arm/translate.c | 2 +- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/qemu/target/arm/cpu.h b/qemu/target/arm/cpu.h index 19ae37ed..0451e8c1 100644 --- a/qemu/target/arm/cpu.h +++ b/qemu/target/arm/cpu.h @@ -3387,6 +3387,18 @@ static inline bool isar_feature_aa32_fp16_dpconv(const ARMISARegisters *id) return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 1; } +/* + * Note that this ID register field covers both VFP and Neon FMAC, + * so should usually be tested in combination with some other + * check that confirms the presence of whichever of VFP or Neon is + * relevant, to avoid accidentally enabling a Neon feature on + * a VFP-no-Neon core or vice-versa. + */ +static inline bool isar_feature_aa32_simdfmac(const ARMISARegisters *id) +{ + return FIELD_EX32(id->mvfr1, MVFR1, SIMDFMAC) != 0; +} + static inline bool isar_feature_aa32_vsel(const ARMISARegisters *id) { return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 1; diff --git a/qemu/target/arm/translate-vfp.inc.c b/qemu/target/arm/translate-vfp.inc.c index e3afe5ae..719c102d 100644 --- a/qemu/target/arm/translate-vfp.inc.c +++ b/qemu/target/arm/translate-vfp.inc.c @@ -1828,11 +1828,19 @@ static bool trans_VFM_sp(DisasContext *s, arg_VFM_sp *a) /* * Present in VFPv4 only. + * Note that we can't rely on the SIMDFMAC check alone, because + * in a Neon-no-VFP core that ID register field will be non-zero. + */ + if (!dc_isar_feature(aa32_simdfmac, s) || + !dc_isar_feature(aa32_fpsp_v2, s)) { + return false; + } + + /* * In v7A, UNPREDICTABLE with non-zero vector length/stride; from * v8A, must UNDEF. We choose to UNDEF for both v7A and v8A. */ - if (!arm_dc_feature(s, ARM_FEATURE_VFP4) || - (s->vec_len != 0 || s->vec_stride != 0)) { + if (s->vec_len != 0 || s->vec_stride != 0) { return false; } @@ -1887,11 +1895,19 @@ static bool trans_VFM_dp(DisasContext *s, arg_VFM_dp *a) /* * Present in VFPv4 only. + * Note that we can't rely on the SIMDFMAC check alone, because + * in a Neon-no-VFP core that ID register field will be non-zero. + */ + if (!dc_isar_feature(aa32_simdfmac, s) || + !dc_isar_feature(aa32_fpdp_v2, s)) { + return false; + } + + /* * In v7A, UNPREDICTABLE with non-zero vector length/stride; from * v8A, must UNDEF. We choose to UNDEF for both v7A and v8A. */ - if (!arm_dc_feature(s, ARM_FEATURE_VFP4) || - (s->vec_len != 0 || s->vec_stride != 0)) { + if (s->vec_len != 0 || s->vec_stride != 0) { return false; } diff --git a/qemu/target/arm/translate.c b/qemu/target/arm/translate.c index 11adfef2..bd917b07 100644 --- a/qemu/target/arm/translate.c +++ b/qemu/target/arm/translate.c @@ -5283,7 +5283,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) } break; case NEON_3R_VFM_VQRDMLSH: - if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) { + if (!dc_isar_feature(aa32_simdfmac, s)) { return 1; } break;