mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-23 06:35:27 +00:00
target/arm: Use MVFR1 feature bits to gate A32/T32 FP16 instructions
Instead of gating the A32/T32 FP16 conversion instructions on the ARM_FEATURE_VFP_FP16 flag, switch to our new approach of looking at ID register bits. In this case MVFR1 fields FPHP and SIMDHP indicate the presence of these insns. This change doesn't alter behaviour for any of our CPUs. Backports commit 602f6e42cfbfe9278be34e9b91d2ceb695837e02 from qemu
This commit is contained in:
parent
4f210d0731
commit
118a2bde5c
|
@ -745,7 +745,6 @@ static int arm_cpu_realizefn(struct uc_struct *uc, DeviceState *dev, Error **err
|
|||
}
|
||||
if (arm_feature(env, ARM_FEATURE_VFP4)) {
|
||||
set_feature(env, ARM_FEATURE_VFP3);
|
||||
set_feature(env, ARM_FEATURE_VFP_FP16);
|
||||
}
|
||||
if (arm_feature(env, ARM_FEATURE_VFP3)) {
|
||||
set_feature(env, ARM_FEATURE_VFP);
|
||||
|
@ -1364,7 +1363,6 @@ static void cortex_a9_initfn(struct uc_struct *uc, Object *obj, void *opaque)
|
|||
cpu->dtb_compatible = "arm,cortex-a9";
|
||||
set_feature(&cpu->env, ARM_FEATURE_V7);
|
||||
set_feature(&cpu->env, ARM_FEATURE_VFP3);
|
||||
set_feature(&cpu->env, ARM_FEATURE_VFP_FP16);
|
||||
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL3);
|
||||
|
|
|
@ -1672,6 +1672,27 @@ FIELD(ID_DFR0, MPROFDBG, 20, 4)
|
|||
FIELD(ID_DFR0, PERFMON, 24, 4)
|
||||
FIELD(ID_DFR0, TRACEFILT, 28, 4)
|
||||
|
||||
FIELD(MVFR0, SIMDREG, 0, 4)
|
||||
FIELD(MVFR0, FPSP, 4, 4)
|
||||
FIELD(MVFR0, FPDP, 8, 4)
|
||||
FIELD(MVFR0, FPTRAP, 12, 4)
|
||||
FIELD(MVFR0, FPDIVIDE, 16, 4)
|
||||
FIELD(MVFR0, FPSQRT, 20, 4)
|
||||
FIELD(MVFR0, FPSHVEC, 24, 4)
|
||||
FIELD(MVFR0, FPROUND, 28, 4)
|
||||
|
||||
FIELD(MVFR1, FPFTZ, 0, 4)
|
||||
FIELD(MVFR1, FPDNAN, 4, 4)
|
||||
FIELD(MVFR1, SIMDLS, 8, 4)
|
||||
FIELD(MVFR1, SIMDINT, 12, 4)
|
||||
FIELD(MVFR1, SIMDSP, 16, 4)
|
||||
FIELD(MVFR1, SIMDHP, 20, 4)
|
||||
FIELD(MVFR1, FPHP, 24, 4)
|
||||
FIELD(MVFR1, SIMDFMAC, 28, 4)
|
||||
|
||||
FIELD(MVFR2, SIMDMISC, 0, 4)
|
||||
FIELD(MVFR2, FPMISC, 4, 4)
|
||||
|
||||
QEMU_BUILD_BUG_ON(ARRAY_SIZE(((ARMCPU *)0)->ccsidr) <= R_V7M_CSSELR_INDEX_MASK);
|
||||
|
||||
/* If adding a feature bit which corresponds to a Linux ELF
|
||||
|
@ -1689,7 +1710,6 @@ enum arm_features {
|
|||
ARM_FEATURE_THUMB2,
|
||||
ARM_FEATURE_PMSA, /* no MMU; may have Memory Protection Unit */
|
||||
ARM_FEATURE_VFP3,
|
||||
ARM_FEATURE_VFP_FP16,
|
||||
ARM_FEATURE_NEON,
|
||||
ARM_FEATURE_M, /* Microcontroller profile. */
|
||||
ARM_FEATURE_OMAPCP, /* OMAP specific CP15 ops handling. */
|
||||
|
@ -3267,6 +3287,21 @@ static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
|
|||
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* We always set the FP and SIMD FP16 fields to indicate identical
|
||||
* levels of support (assuming SIMD is implemented at all), so
|
||||
* we only need one set of accessors.
|
||||
*/
|
||||
static inline bool isar_feature_aa32_fp16_spconv(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->mvfr1, MVFR1, FPHP) > 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa32_fp16_dpconv(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->mvfr1, MVFR1, FPHP) > 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* 64-bit feature tests via id registers.
|
||||
*/
|
||||
|
|
|
@ -3785,17 +3785,27 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
|
|||
* UNPREDICTABLE if bit 8 is set prior to ARMv8
|
||||
* (we choose to UNDEF)
|
||||
*/
|
||||
if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
|
||||
!arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
|
||||
return 1;
|
||||
if (dp) {
|
||||
if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (!dc_isar_feature(aa32_fp16_spconv, s)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
rm_is_dp = false;
|
||||
break;
|
||||
case 0x06: /* vcvtb.f16.f32, vcvtb.f16.f64 */
|
||||
case 0x07: /* vcvtt.f16.f32, vcvtt.f16.f64 */
|
||||
if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
|
||||
!arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
|
||||
return 1;
|
||||
if (dp) {
|
||||
if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (!dc_isar_feature(aa32_fp16_spconv, s)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
rd_is_dp = false;
|
||||
break;
|
||||
|
@ -8037,7 +8047,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
|
|||
TCGv_ptr fpst;
|
||||
TCGv_i32 ahp;
|
||||
|
||||
if (!arm_dc_feature(s, ARM_FEATURE_VFP_FP16) ||
|
||||
if (!dc_isar_feature(aa32_fp16_spconv, s) ||
|
||||
q || (rm & 1)) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -8070,7 +8080,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
|
|||
TCGv_ptr fpst;
|
||||
TCGv_i32 ahp;
|
||||
|
||||
if (!arm_dc_feature(s, ARM_FEATURE_VFP_FP16) ||
|
||||
if (!dc_isar_feature(aa32_fp16_spconv, s) ||
|
||||
q || (rd & 1)) {
|
||||
return 1;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue