Introduce the special register FPMR and its fields. Migrate it when present.
Signed-off-by: Richard Henderson <[email protected]> --- target/arm/cpregs.h | 5 +++++ target/arm/cpu-features.h | 5 +++++ target/arm/cpu.h | 1 + target/arm/internals.h | 10 ++++++++++ target/arm/helper.c | 12 +++++++++++- target/arm/machine.c | 20 ++++++++++++++++++++ 6 files changed, 52 insertions(+), 1 deletion(-) diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h index f5ec7484c1..391c0e322b 100644 --- a/target/arm/cpregs.h +++ b/target/arm/cpregs.h @@ -149,6 +149,11 @@ enum { * should not trap to EL2 when HCR_EL2.NV is set. */ ARM_CP_NV_NO_TRAP = 1 << 22, + /* + * Flag: Access check for this sysreg is constrained by the + * ARM pseudocode function CheckFPMREnabled(). + */ + ARM_CP_FPMR = 1 << 23, }; /* diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index a7ab7e2a31..e13c1c1331 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -1192,6 +1192,11 @@ static inline bool isar_feature_aa64_gcie(const ARMISARegisters *id) return FIELD_EX64_IDREG(id, ID_AA64PFR2, GCIE) != 0; } +static inline bool isar_feature_aa64_fpmr(const ARMISARegisters *id) +{ + return FIELD_EX64_IDREG(id, ID_AA64PFR2, FPMR) != 0; +} + static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id) { return FIELD_SEX64_IDREG(id, ID_AA64MMFR0, TGRAN4) >= 1; diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 0a11dd9002..498af7db08 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -713,6 +713,7 @@ typedef struct CPUArchState { */ uint64_t fpsr; uint64_t fpcr; + uint64_t fpmr; uint32_t xregs[16]; diff --git a/target/arm/internals.h b/target/arm/internals.h index 4414be85d9..ff30381fa5 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -292,6 +292,16 @@ FIELD(CNTHCTL, EVNTIS, 17, 1) FIELD(CNTHCTL, CNTVMASK, 18, 1) FIELD(CNTHCTL, CNTPMASK, 19, 1) +FIELD(FPMR, F8S1, 0, 3) +FIELD(FPMR, F8S2, 3, 3) +FIELD(FPMR, F8D, 6, 3) +FIELD(FPMR, OSM, 14, 1) +FIELD(FPMR, OSC, 15, 1) +FIELD(FPMR, LSCALE, 16, 7) +FIELD(FPMR, NSCALE, 24, 8) +FIELD(FPMR, NSCALE_F16, 24, 5) +FIELD(FPMR, LSCALE2, 32, 6) + /* We use a few fake FSR values for internal purposes in M profile. * M profile cores don't have A/R format FSRs, but currently our * get_phys_addr() code assumes A/R profile and reports failures via diff --git a/target/arm/helper.c b/target/arm/helper.c index 6ad01b345f..ae1dd42dc4 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6229,6 +6229,14 @@ static const ARMCPRegInfo aie_reginfo[] = { .type = ARM_CP_CONST, .resetvalue = 0 }, }; +static const ARMCPRegInfo fpmr_reginfo[] = { + { .name = "FPMR", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 4, .opc2 = 2, + .access = PL0_RW, .type = ARM_CP_FPU | ARM_CP_FPMR, + .fieldoffset = offsetof(CPUARMState, vfp.fpmr), + } +}; + void register_cp_regs_for_features(ARMCPU *cpu) { /* Register all the coprocessor registers based on feature bits */ @@ -7502,10 +7510,12 @@ void register_cp_regs_for_features(ARMCPU *cpu) define_arm_cp_regs(cpu, mec_mte_reginfo); } } - if (cpu_isar_feature(aa64_aie, cpu)) { define_arm_cp_regs(cpu, aie_reginfo); } + if (cpu_isar_feature(aa64_fpmr, cpu)) { + define_arm_cp_regs(cpu, fpmr_reginfo); + } if (cpu_isar_feature(any_predinv, cpu)) { define_arm_cp_regs(cpu, predinv_reginfo); diff --git a/target/arm/machine.c b/target/arm/machine.c index 8dc766d322..58f8dfd53c 100644 --- a/target/arm/machine.c +++ b/target/arm/machine.c @@ -960,6 +960,25 @@ static const VMStateDescription vmstate_syndrome64 = { }, }; +static bool fpmr_needed(void *opaque) +{ + ARMCPU *cpu = opaque; + + return arm_feature(&cpu->env, ARM_FEATURE_AARCH64) + && cpu_isar_feature(aa64_fpmr, cpu); +} + +static const VMStateDescription vmstate_fpmr = { + .name = "cpu/fpmr", + .version_id = 1, + .minimum_version_id = 1, + .needed = fpmr_needed, + .fields = (const VMStateField[]) { + VMSTATE_UINT64(env.vfp.fpmr, ARMCPU), + VMSTATE_END_OF_LIST() + }, +}; + static int cpu_pre_save(void *opaque) { ARMCPU *cpu = opaque; @@ -1323,6 +1342,7 @@ const VMStateDescription vmstate_arm_cpu = { &vmstate_syndrome64, &vmstate_pstate64, &vmstate_event, + &vmstate_fpmr, NULL } }; -- 2.43.0
