summary refs log tree commit diff stats
path: root/target/hppa/int_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/hppa/int_helper.c')
-rw-r--r--target/hppa/int_helper.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c
index 13073ae2bd..f599dccfff 100644
--- a/target/hppa/int_helper.c
+++ b/target/hppa/int_helper.c
@@ -23,6 +23,7 @@
 #include "cpu.h"
 #include "exec/helper-proto.h"
 #include "hw/core/cpu.h"
+#include "hw/hppa/hppa_hardware.h"
 
 #ifndef CONFIG_USER_ONLY
 static void eval_interrupt(HPPACPU *cpu)
@@ -181,7 +182,14 @@ void hppa_cpu_do_interrupt(CPUState *cs)
     }
 
     /* step 7 */
-    env->iaoq_f = env->cr[CR_IVA] + 32 * i;
+    if (i == EXCP_TOC) {
+        env->iaoq_f = FIRMWARE_START;
+        /* help SeaBIOS and provide iaoq_b and iasq_back in shadow regs */
+        env->gr[24] = env->cr_back[0];
+        env->gr[25] = env->cr_back[1];
+    } else {
+        env->iaoq_f = env->cr[CR_IVA] + 32 * i;
+    }
     env->iaoq_b = env->iaoq_f + 4;
     env->iasq_f = 0;
     env->iasq_b = 0;
@@ -219,6 +227,7 @@ void hppa_cpu_do_interrupt(CPUState *cs)
             [EXCP_PER_INTERRUPT] = "performance monitor interrupt",
             [EXCP_SYSCALL]       = "syscall",
             [EXCP_SYSCALL_LWS]   = "syscall-lws",
+            [EXCP_TOC]           = "TOC (transfer of control)",
         };
         static int count;
         const char *name = NULL;
@@ -248,6 +257,14 @@ bool hppa_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
     HPPACPU *cpu = HPPA_CPU(cs);
     CPUHPPAState *env = &cpu->env;
 
+    if (interrupt_request & CPU_INTERRUPT_NMI) {
+        /* Raise TOC (NMI) interrupt */
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_NMI);
+        cs->exception_index = EXCP_TOC;
+        hppa_cpu_do_interrupt(cs);
+        return true;
+    }
+
     /* If interrupts are requested and enabled, raise them.  */
     if ((env->psw & PSW_I) && (interrupt_request & CPU_INTERRUPT_HARD)) {
         cs->exception_index = EXCP_EXT_INTERRUPT;