diff options
Diffstat (limited to 'target/arm/helper.c')
| -rw-r--r-- | target/arm/helper.c | 84 |
1 files changed, 64 insertions, 20 deletions
diff --git a/target/arm/helper.c b/target/arm/helper.c index 180ab75458..e7586fcf6c 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -3356,10 +3356,12 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { .writefn = aa64_daif_write, .resetfn = arm_cp_reset_ignore }, { .name = "FPCR", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .opc2 = 0, .crn = 4, .crm = 4, - .access = PL0_RW, .readfn = aa64_fpcr_read, .writefn = aa64_fpcr_write }, + .access = PL0_RW, .type = ARM_CP_FPU | ARM_CP_SUPPRESS_TB_END, + .readfn = aa64_fpcr_read, .writefn = aa64_fpcr_write }, { .name = "FPSR", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 4, .crm = 4, - .access = PL0_RW, .readfn = aa64_fpsr_read, .writefn = aa64_fpsr_write }, + .access = PL0_RW, .type = ARM_CP_FPU | ARM_CP_SUPPRESS_TB_END, + .readfn = aa64_fpsr_read, .writefn = aa64_fpsr_write }, { .name = "DCZID_EL0", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .opc2 = 7, .crn = 0, .crm = 0, .access = PL0_R, .type = ARM_CP_NO_RAW, @@ -4333,20 +4335,6 @@ static int sve_exception_el(CPUARMState *env) return 0; } -static CPAccessResult zcr_access(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - switch (sve_exception_el(env)) { - case 3: - return CP_ACCESS_TRAP_EL3; - case 2: - return CP_ACCESS_TRAP_EL2; - case 1: - return CP_ACCESS_TRAP; - } - return CP_ACCESS_OK; -} - static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { @@ -4357,7 +4345,7 @@ static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri, static const ARMCPRegInfo zcr_el1_reginfo = { .name = "ZCR_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 2, .opc2 = 0, - .access = PL1_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT, + .access = PL1_RW, .type = ARM_CP_SVE | ARM_CP_FPU, .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[1]), .writefn = zcr_write, .raw_writefn = raw_write }; @@ -4365,7 +4353,7 @@ static const ARMCPRegInfo zcr_el1_reginfo = { static const ARMCPRegInfo zcr_el2_reginfo = { .name = "ZCR_EL2", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0, - .access = PL2_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT, + .access = PL2_RW, .type = ARM_CP_SVE | ARM_CP_FPU, .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[2]), .writefn = zcr_write, .raw_writefn = raw_write }; @@ -4373,14 +4361,14 @@ static const ARMCPRegInfo zcr_el2_reginfo = { static const ARMCPRegInfo zcr_no_el2_reginfo = { .name = "ZCR_EL2", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0, - .access = PL2_RW, .type = ARM_CP_64BIT, + .access = PL2_RW, .type = ARM_CP_SVE | ARM_CP_FPU, .readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore }; static const ARMCPRegInfo zcr_el3_reginfo = { .name = "ZCR_EL3", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 2, .opc2 = 0, - .access = PL3_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT, + .access = PL3_RW, .type = ARM_CP_SVE | ARM_CP_FPU, .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[3]), .writefn = zcr_write, .raw_writefn = raw_write }; @@ -10415,6 +10403,16 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg) return 0; } return env->v7m.other_ss_psp; + case 0x8a: /* MSPLIM_NS */ + if (!env->v7m.secure) { + return 0; + } + return env->v7m.msplim[M_REG_NS]; + case 0x8b: /* PSPLIM_NS */ + if (!env->v7m.secure) { + return 0; + } + return env->v7m.psplim[M_REG_NS]; case 0x90: /* PRIMASK_NS */ if (!env->v7m.secure) { return 0; @@ -10456,6 +10454,16 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg) return v7m_using_psp(env) ? env->v7m.other_sp : env->regs[13]; case 9: /* PSP */ return v7m_using_psp(env) ? env->regs[13] : env->v7m.other_sp; + case 10: /* MSPLIM */ + if (!arm_feature(env, ARM_FEATURE_V8)) { + goto bad_reg; + } + return env->v7m.msplim[env->v7m.secure]; + case 11: /* PSPLIM */ + if (!arm_feature(env, ARM_FEATURE_V8)) { + goto bad_reg; + } + return env->v7m.psplim[env->v7m.secure]; case 16: /* PRIMASK */ return env->v7m.primask[env->v7m.secure]; case 17: /* BASEPRI */ @@ -10464,6 +10472,7 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg) case 19: /* FAULTMASK */ return env->v7m.faultmask[env->v7m.secure]; default: + bad_reg: qemu_log_mask(LOG_GUEST_ERROR, "Attempt to read unknown special" " register %d\n", reg); return 0; @@ -10501,6 +10510,18 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val) } env->v7m.other_ss_psp = val; return; + case 0x8a: /* MSPLIM_NS */ + if (!env->v7m.secure) { + return; + } + env->v7m.msplim[M_REG_NS] = val & ~7; + return; + case 0x8b: /* PSPLIM_NS */ + if (!env->v7m.secure) { + return; + } + env->v7m.psplim[M_REG_NS] = val & ~7; + return; case 0x90: /* PRIMASK_NS */ if (!env->v7m.secure) { return; @@ -10519,6 +10540,16 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val) } env->v7m.faultmask[M_REG_NS] = val & 1; return; + case 0x94: /* CONTROL_NS */ + if (!env->v7m.secure) { + return; + } + write_v7m_control_spsel_for_secstate(env, + val & R_V7M_CONTROL_SPSEL_MASK, + M_REG_NS); + env->v7m.control[M_REG_NS] &= ~R_V7M_CONTROL_NPRIV_MASK; + env->v7m.control[M_REG_NS] |= val & R_V7M_CONTROL_NPRIV_MASK; + return; case 0x98: /* SP_NS */ { /* This gives the non-secure SP selected based on whether we're @@ -10570,6 +10601,18 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val) env->v7m.other_sp = val; } break; + case 10: /* MSPLIM */ + if (!arm_feature(env, ARM_FEATURE_V8)) { + goto bad_reg; + } + env->v7m.msplim[env->v7m.secure] = val & ~7; + break; + case 11: /* PSPLIM */ + if (!arm_feature(env, ARM_FEATURE_V8)) { + goto bad_reg; + } + env->v7m.psplim[env->v7m.secure] = val & ~7; + break; case 16: /* PRIMASK */ env->v7m.primask[env->v7m.secure] = val & 1; break; @@ -10602,6 +10645,7 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val) env->v7m.control[env->v7m.secure] |= val & R_V7M_CONTROL_NPRIV_MASK; break; default: + bad_reg: qemu_log_mask(LOG_GUEST_ERROR, "Attempt to write unknown special" " register %d\n", reg); return; |