{
CPUState *cs = env_cpu(env);
int minlevel = xtensa_get_cintlevel(env);
- uint32_t int_set_enabled = env->sregs[INTSET] & env->sregs[INTENABLE];
+ uint32_t int_set_enabled = env->sregs[INTSET] &
+ (env->sregs[INTENABLE] | env->config->inttype_mask[INTTYPE_NMI]);
int level;
+ if (minlevel >= env->config->nmi_level) {
+ minlevel = env->config->nmi_level - 1;
+ }
for (level = env->config->nlevel; level > minlevel; --level) {
if (env->config->level_mask[level] & int_set_enabled) {
env->pending_irq_level = level;
v & env->config->inttype_mask[INTTYPE_SOFTWARE]);
}
+static void intclear(CPUXtensaState *env, uint32_t v)
+{
+ atomic_and(&env->sregs[INTSET], ~v);
+}
+
void HELPER(intclear)(CPUXtensaState *env, uint32_t v)
{
- atomic_and(&env->sregs[INTSET],
- ~(v & (env->config->inttype_mask[INTTYPE_SOFTWARE] |
- env->config->inttype_mask[INTTYPE_EDGE])));
+ intclear(env, v & (env->config->inttype_mask[INTTYPE_SOFTWARE] |
+ env->config->inttype_mask[INTTYPE_EDGE]));
}
static uint32_t relocated_vector(CPUXtensaState *env, uint32_t vector)
{
int level = env->pending_irq_level;
- if (level > xtensa_get_cintlevel(env) &&
- level <= env->config->nlevel &&
- (env->config->level_mask[level] &
- env->sregs[INTSET] &
- env->sregs[INTENABLE])) {
+ if ((level > xtensa_get_cintlevel(env) &&
+ level <= env->config->nlevel &&
+ (env->config->level_mask[level] &
+ env->sregs[INTSET] & env->sregs[INTENABLE])) ||
+ level == env->config->nmi_level) {
CPUState *cs = env_cpu(env);
if (level > 1) {
(env->sregs[PS] & ~PS_INTLEVEL) | level | PS_EXCM;
env->pc = relocated_vector(env,
env->config->interrupt_vector[level]);
+ if (level == env->config->nmi_level) {
+ intclear(env, env->config->inttype_mask[INTTYPE_NMI]);
+ }
} else {
env->sregs[EXCCAUSE] = LEVEL1_INTERRUPT_CAUSE;
#define XTHAL_INTTYPE_IDMA_ERR INTTYPE_IDMA_ERR
#define XTHAL_INTTYPE_GS_ERR INTTYPE_GS_ERR
+#ifndef XCHAL_NMILEVEL
+#define XCHAL_NMILEVEL (XCHAL_NUM_INTLEVELS + 1)
+#endif
#define INTERRUPT(i) { \
.level = XCHAL_INT ## i ## _LEVEL, \
#define INTERRUPTS_SECTION \
.ninterrupt = XCHAL_NUM_INTERRUPTS, \
- .nlevel = XCHAL_NUM_INTLEVELS, \
+ .nlevel = XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI, \
+ .nmi_level = XCHAL_NMILEVEL, \
.interrupt_vector = INTERRUPT_VECTORS, \
.level_mask = LEVEL_MASKS, \
.inttype_mask = INTTYPE_MASKS, \