qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 4/6] simply cpu_exec further


From: Glauber Costa
Subject: [Qemu-devel] [PATCH 4/6] simply cpu_exec further
Date: Tue, 27 May 2008 12:18:23 -0300

We change interrupt functions so they have the same
signature, getting only an env parameter. When necessary,
some more attributed were added to the relevant CPUState to
make it possible.

Signed-off-by: Glauber Costa <address@hidden>
---
 cpu-defs.h               |    1 +
 cpu-exec.c               |  197 +++++-----------------------------------------
 exec-all.h               |    7 ++
 target-alpha/helper.c    |    9 ++
 target-arm/helper.c      |   27 ++++++
 target-cris/helper.c     |    9 ++
 target-i386/exec.h       |    5 +-
 target-i386/helper.c     |   69 ++++++++++++++++-
 target-m68k/cpu.h        |    2 +-
 target-m68k/helper.c     |   16 ++++
 target-m68k/op_helper.c  |    8 +-
 target-mips/helper.c     |   17 ++++
 target-ppc/helper.c      |   16 ++++
 target-sh4/helper.c      |    8 ++
 target-sparc/exec.h      |    3 +-
 target-sparc/helper.c    |    1 +
 target-sparc/op_helper.c |   29 ++++++-
 17 files changed, 232 insertions(+), 192 deletions(-)

diff --git a/cpu-defs.h b/cpu-defs.h
index 5bcd1ee..5f3f9df 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -162,6 +162,7 @@ typedef struct CPUTLBEntry {
     /* Core interrupt code */                                           \
     jmp_buf jmp_env;                                                    \
     int exception_index;                                                \
+    int exception_is_hw;                                                \
     int error_code;                                                     \
                                                                         \
     int halted;                                                         \
diff --git a/cpu-exec.c b/cpu-exec.c
index a829b7b..e798b03 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -241,6 +241,21 @@ static inline TranslationBlock *tb_find_fast(void)
     return tb;
 }
 
+void handle_interrupt_common(CPUState *env)
+{
+    if (env->interrupt_request & CPU_INTERRUPT_HALT) {
+        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
+        env->halted = 1;
+        env->exception_index = EXCP_HLT;
+        cpu_loop_exit();
+    }
+}
+
+void reset_tb(void)
+{
+    next_tb = 0;
+}
+
 /* main execution loop */
 
 int cpu_exec(CPUState *env1)
@@ -281,43 +296,16 @@ int cpu_exec(CPUState *env1)
                        which will be handled outside the cpu execution
                        loop */
 #if defined(TARGET_I386)
-                    do_interrupt_user(env->exception_index,
-                                      env->exception_is_int,
-                                      env->error_code,
-                                      env->exception_next_eip);
-                    /* successfully delivered */
-                    env->old_exception = -1;
+                    do_interrupt(env);
 #endif
                     ret = env->exception_index;
                     break;
                 } else {
-#if defined(TARGET_I386)
                     /* simulate a real cpu exception. On i386, it can
                        trigger new exceptions, but we do not handle
                        double or triple faults yet. */
-                    do_interrupt(env->exception_index,
-                                 env->exception_is_int,
-                                 env->error_code,
-                                 env->exception_next_eip, 0);
-                    /* successfully delivered */
-                    env->old_exception = -1;
-#elif defined(TARGET_PPC)
-                    do_interrupt(env);
-#elif defined(TARGET_MIPS)
-                    do_interrupt(env);
-#elif defined(TARGET_SPARC)
-                    do_interrupt(env->exception_index);
-#elif defined(TARGET_ARM)
+                    env->exception_is_hw = 0;
                     do_interrupt(env);
-#elif defined(TARGET_SH4)
-                   do_interrupt(env);
-#elif defined(TARGET_ALPHA)
-                    do_interrupt(env);
-#elif defined(TARGET_CRIS)
-                    do_interrupt(env);
-#elif defined(TARGET_M68K)
-                    do_interrupt(0);
-#endif
                 }
                 env->exception_index = -1;
             }
@@ -360,156 +348,9 @@ int cpu_exec(CPUState *env1)
                         env->exception_index = EXCP_DEBUG;
                         cpu_loop_exit();
                     }
-#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
-    defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS)
-                    if (interrupt_request & CPU_INTERRUPT_HALT) {
-                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
-                        env->halted = 1;
-                        env->exception_index = EXCP_HLT;
-                        cpu_loop_exit();
-                    }
-#endif
-#if defined(TARGET_I386)
-                    if ((interrupt_request & CPU_INTERRUPT_SMI) &&
-                        !(env->hflags & HF_SMM_MASK)) {
-                        svm_check_intercept(SVM_EXIT_SMI);
-                        env->interrupt_request &= ~CPU_INTERRUPT_SMI;
-                        do_smm_enter();
-                        next_tb = 0;
-                    } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
-                        !(env->hflags & HF_NMI_MASK)) {
-                        env->interrupt_request &= ~CPU_INTERRUPT_NMI;
-                        env->hflags |= HF_NMI_MASK;
-                        do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
-                        next_tb = 0;
-                    } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
-                        (env->eflags & IF_MASK || env->hflags & HF_HIF_MASK) &&
-                        !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
-                        int intno;
-                        svm_check_intercept(SVM_EXIT_INTR);
-                        env->interrupt_request &= ~(CPU_INTERRUPT_HARD | 
CPU_INTERRUPT_VIRQ);
-                        intno = cpu_get_pic_interrupt(env);
-                        if (loglevel & CPU_LOG_TB_IN_ASM) {
-                            fprintf(logfile, "Servicing hardware 
INT=0x%02x\n", intno);
-                        }
-                        do_interrupt(intno, 0, 0, 0, 1);
-                        /* ensure that no TB jump will be modified as
-                           the program flow was changed */
-                        next_tb = 0;
-#if !defined(CONFIG_USER_ONLY)
-                    } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
-                        (env->eflags & IF_MASK) && !(env->hflags & 
HF_INHIBIT_IRQ_MASK)) {
-                         int intno;
-                         /* FIXME: this should respect TPR */
-                         env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
-                         svm_check_intercept(SVM_EXIT_VINTR);
-                         intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, 
control.int_vector));
-                         if (loglevel & CPU_LOG_TB_IN_ASM)
-                             fprintf(logfile, "Servicing virtual hardware 
INT=0x%02x\n", intno);
-                        do_interrupt(intno, 0, 0, -1, 1);
-                         stl_phys(env->vm_vmcb + offsetof(struct vmcb, 
control.int_ctl),
-                                  ldl_phys(env->vm_vmcb + offsetof(struct 
vmcb, control.int_ctl)) & ~V_IRQ_MASK);
-                        next_tb = 0;
-#endif
-                    }
-#elif defined(TARGET_PPC)
-#if 0
-                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
-                        cpu_ppc_reset(env);
-                    }
-#endif
-                    if (interrupt_request & CPU_INTERRUPT_HARD) {
-                        ppc_hw_interrupt(env);
-                        if (env->pending_interrupts == 0)
-                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
-                        next_tb = 0;
-                    }
-#elif defined(TARGET_MIPS)
-                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
-                        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
-                        (env->CP0_Status & (1 << CP0St_IE)) &&
-                        !(env->CP0_Status & (1 << CP0St_EXL)) &&
-                        !(env->CP0_Status & (1 << CP0St_ERL)) &&
-                        !(env->hflags & MIPS_HFLAG_DM)) {
-                        /* Raise it */
-                        env->exception_index = EXCP_EXT_INTERRUPT;
-                        env->error_code = 0;
-                        do_interrupt(env);
-                        next_tb = 0;
-                    }
-#elif defined(TARGET_SPARC)
-                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
-                       (env->psret != 0)) {
-                       int pil = env->interrupt_index & 15;
-                       int type = env->interrupt_index & 0xf0;
-
-                       if (((type == TT_EXTINT) &&
-                            (pil == 15 || pil > env->psrpil)) ||
-                           type != TT_EXTINT) {
-                           env->interrupt_request &= ~CPU_INTERRUPT_HARD;
-                           do_interrupt(env->interrupt_index);
-                           env->interrupt_index = 0;
-#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
-                            cpu_check_irqs(env);
-#endif
-                        next_tb = 0;
-                       }
-                   } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
-                       //do_interrupt(0, 0, 0, 0, 0);
-                       env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
-                   }
-#elif defined(TARGET_ARM)
-                    if (interrupt_request & CPU_INTERRUPT_FIQ
-                        && !(env->uncached_cpsr & CPSR_F)) {
-                        env->exception_index = EXCP_FIQ;
-                        do_interrupt(env);
-                        next_tb = 0;
-                    }
-                    /* ARMv7-M interrupt return works by loading a magic value
-                       into the PC.  On real hardware the load causes the
-                       return to occur.  The qemu implementation performs the
-                       jump normally, then does the exception return when the
-                       CPU tries to execute code at the magic address.
-                       This will cause the magic PC value to be pushed to
-                       the stack if an interrupt occured at the wrong time.
-                       We avoid this by disabling interrupts when
-                       pc contains a magic address.  */
-                    if (interrupt_request & CPU_INTERRUPT_HARD
-                        && ((IS_M(env) && env->regs[15] < 0xfffffff0)
-                            || !(env->uncached_cpsr & CPSR_I))) {
-                        env->exception_index = EXCP_IRQ;
-                        do_interrupt(env);
-                        next_tb = 0;
-                    }
-#elif defined(TARGET_SH4)
-                    if (interrupt_request & CPU_INTERRUPT_HARD) {
-                        do_interrupt(env);
-                        next_tb = 0;
-                    }
-#elif defined(TARGET_ALPHA)
-                    if (interrupt_request & CPU_INTERRUPT_HARD) {
-                        do_interrupt(env);
-                        next_tb = 0;
-                    }
-#elif defined(TARGET_CRIS)
-                    if (interrupt_request & CPU_INTERRUPT_HARD) {
-                        do_interrupt(env);
-                        next_tb = 0;
-                    }
-#elif defined(TARGET_M68K)
-                    if (interrupt_request & CPU_INTERRUPT_HARD
-                        && ((env->sr & SR_I) >> SR_I_SHIFT)
-                            < env->pending_level) {
-                        /* Real hardware gets the interrupt vector via an
-                           IACK cycle at this point.  Current emulated
-                           hardware doesn't rely on this, so we
-                           provide/save the vector when the interrupt is
-                           first signalled.  */
-                        env->exception_index = env->pending_vector;
-                        do_interrupt(1);
-                        next_tb = 0;
-                    }
-#endif
+
+                    arch_handle_interrupt_request(env);
+
                    /* Don't use the cached interupt_request value,
                       do_interrupt may have updated the EXITTB flag. */
                     if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
diff --git a/exec-all.h b/exec-all.h
index fd1ea6a..b43526c 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -84,6 +84,13 @@ void cpu_resume_from_signal(CPUState *env1, void *puc);
 void cpu_exec_init(CPUState *env);
 
 extern int  cpu_info_ip(CPUState *env, char *buf);
+
+/* implemented by the targets */
+void arch_handle_interrupt_request(CPUState *env);
+/* implemented by cpu-exec.c */
+void handle_interrupt_common(CPUState *env);
+void reset_tb(void);
+
 void cpu_load_flags(CPUState *env);
 void cpu_put_flags(CPUState *env);
 
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 6056d6c..003601a 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -456,3 +456,12 @@ void cpu_dump_EA (target_ulong EA)
 int cpu_info_ip(CPUState *env, char *buf) { return 0; }
 void cpu_load_flags(CPUState *env) {}
 void cpu_put_flags(CPUState *env) {}
+
+void arch_handle_interrupt_request(CPUState *env)
+{
+    handle_interrupt_common(env);
+    if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+        do_interrupt(env);
+        reset_tb();
+    }
+}
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 6724909..c0b3e84 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2527,3 +2527,30 @@ int cpu_info_ip(CPUState *env, char *buf) { return 0; }
 void cpu_load_flags(CPUState *env) { }
 /* XXX: Save/restore host fpu exception state?.  */
 void cpu_put_flags(CPUState *env) { }
+
+void arch_handle_interrupt_request(CPUState *env)
+{
+    handle_interrupt_common(env);
+    if (env->interrupt_request & CPU_INTERRUPT_FIQ
+        && !(env->uncached_cpsr & CPSR_F)) {
+        env->exception_index = EXCP_FIQ;
+        do_interrupt(env);
+        reset_tb();
+    }
+    /* ARMv7-M interrupt return works by loading a magic value
+       into the PC.  On real hardware the load causes the
+       return to occur.  The qemu implementation performs the
+       jump normally, then does the exception return when the
+       CPU tries to execute code at the magic address.
+       This will cause the magic PC value to be pushed to
+       the stack if an interrupt occured at the wrong time.
+       We avoid this by disabling interrupts when
+       pc contains a magic address.  */
+    if (env->interrupt_request & CPU_INTERRUPT_HARD
+        && ((IS_M(env) && env->regs[15] < 0xfffffff0)
+            || !(env->uncached_cpsr & CPSR_I))) {
+        env->exception_index = EXCP_IRQ;
+        do_interrupt(env);
+        reset_tb();
+    }
+}
diff --git a/target-cris/helper.c b/target-cris/helper.c
index 0ed169c..7acba95 100644
--- a/target-cris/helper.c
+++ b/target-cris/helper.c
@@ -187,3 +187,12 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, 
target_ulong addr)
 int  cpu_info_ip(CPUState *env, char *buf) { return 0; }
 void cpu_load_flags(CPUState *env) {}
 void cpu_put_flags(CPUState *env) {}
+
+void arch_handle_interrupt_request(CPUState *env)
+{
+    handle_interrupt_common(env);
+    if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+        do_interrupt(env);
+        reset_tb();
+    }
+}
diff --git a/target-i386/exec.h b/target-i386/exec.h
index f6517ce..b4adabf 100644
--- a/target-i386/exec.h
+++ b/target-i386/exec.h
@@ -108,10 +108,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx,
               void *retaddr);
 void __hidden cpu_lock(void);
 void __hidden cpu_unlock(void);
-void do_interrupt(int intno, int is_int, int error_code,
-                  target_ulong next_eip, int is_hw);
-void do_interrupt_user(int intno, int is_int, int error_code,
-                       target_ulong next_eip);
+void do_interrupt(CPUState *env);
 void raise_interrupt(int intno, int is_int, int error_code,
                      int next_eip_addend);
 void raise_exception_err(int exception_index, int error_code);
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 7e690de..7682d8e 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1199,8 +1199,8 @@ void do_interrupt_user(int intno, int is_int, int 
error_code,
  * the int instruction. next_eip is the EIP value AFTER the interrupt
  * instruction. It is only relevant if is_int is TRUE.
  */
-void do_interrupt(int intno, int is_int, int error_code,
-                  target_ulong next_eip, int is_hw)
+void do_interrupt_system(int intno, int is_int, int error_code,
+                         target_ulong next_eip, int is_hw)
 {
     if (loglevel & CPU_LOG_INT) {
         if ((env->cr[0] & CR0_PE_MASK)) {
@@ -1247,6 +1247,71 @@ void do_interrupt(int intno, int is_int, int error_code,
     }
 }
 
+void do_interrupt(CPUState *env)
+{
+    if (env->user_mode_only)
+        do_interrupt_user(env->exception_index,
+                          env->exception_is_int,
+                          env->error_code,
+                          env->exception_next_eip);
+    else
+        do_interrupt_system(env->exception_index,
+                            env->exception_is_int,
+                            env->error_code,
+                            env->exception_next_eip,
+                            env->exception_is_hw);
+
+    env->old_exception = -1;
+}
+
+void arch_handle_interrupt_request(CPUState *env)
+{
+    int interrupt_request = env->interrupt_request;
+    int intno;
+
+    if ((interrupt_request & CPU_INTERRUPT_SMI) &&
+        !(env->hflags & HF_SMM_MASK)) {
+        svm_check_intercept(SVM_EXIT_SMI);
+        env->interrupt_request &= ~CPU_INTERRUPT_SMI;
+        do_smm_enter();
+        reset_tb();
+    } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
+        !(env->hflags & HF_NMI_MASK)) {
+        env->interrupt_request &= ~CPU_INTERRUPT_NMI;
+        env->hflags |= HF_NMI_MASK;
+        do_interrupt_system(EXCP02_NMI, 0, 0, 0, 1);
+        reset_tb();
+    } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
+        (env->eflags & IF_MASK || env->hflags & HF_HIF_MASK) &&
+        !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
+        svm_check_intercept(SVM_EXIT_INTR);
+        env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
+        intno = cpu_get_pic_interrupt(env);
+        if (loglevel & CPU_LOG_TB_IN_ASM) {
+            fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
+        }
+
+        do_interrupt_system(intno, 0, 0, 0, 1);
+        /* ensure that no TB jump will be modified as
+           the program flow was changed */
+        reset_tb();
+#if !defined(CONFIG_USER_ONLY)
+    } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
+        (env->eflags & IF_MASK) && !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
+         /* FIXME: this should respect TPR */
+         env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
+         svm_check_intercept(SVM_EXIT_VINTR);
+         intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, 
control.int_vector));
+         if (loglevel & CPU_LOG_TB_IN_ASM)
+             fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", 
intno);
+
+         do_interrupt_system(intno, 0, 0, -1, 1);
+         stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl),
+                  ldl_phys(env->vm_vmcb + offsetof(struct vmcb, 
control.int_ctl)) & ~V_IRQ_MASK);
+         reset_tb();
+#endif
+    }
+}
 /*
  * Check nested exceptions and change to double or triple fault if
  * needed. It should only be called, if this is not an interrupt.
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index e8c1dfc..1acb4a3 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -120,7 +120,7 @@ typedef struct CPUM68KState {
 CPUM68KState *cpu_m68k_init(const char *cpu_model);
 int cpu_m68k_exec(CPUM68KState *s);
 void cpu_m68k_close(CPUM68KState *s);
-void do_interrupt(int is_hw);
+void do_interrupt(CPUM68KState *s);
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
    is returned if the signal was handled by the virtual CPU.  */
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 82b5576..65d68c9 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -355,6 +355,22 @@ void cpu_put_flags(CPUState *env)
               | env->cc_dest | (env->cc_x << 4);
 }
 
+void arch_handle_interrupt_request(CPUState *env)
+{
+    if (env->interrupt_request & CPU_INTERRUPT_HARD
+        && ((env->sr & SR_I) >> SR_I_SHIFT)
+            < env->pending_level) {
+        /* Real hardware gets the interrupt vector via an
+           IACK cycle at this point.  Current emulated
+           hardware doesn't rely on this, so we
+           provide/save the vector when the interrupt is
+           signalled.  */
+        env->exception_index = env->pending_vector;
+        env->exception_is_hw = 1;
+        do_interrupt(env);
+        reset_tb();
+    }
+}
 #if defined(CONFIG_USER_ONLY)
 
 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index 547f13d..2b0fc1c 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -21,7 +21,7 @@
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt(int is_hw)
+void do_interrupt(CPUState *env)
 {
     env->exception_index = -1;
 }
@@ -95,7 +95,7 @@ static void do_rte(void)
     env->aregs[7] = sp + 8;
 }
 
-void do_interrupt(int is_hw)
+void do_interrupt(CPUState *env)
 {
     uint32_t sp;
     uint32_t fmt;
@@ -105,7 +105,7 @@ void do_interrupt(int is_hw)
     fmt = 0;
     retaddr = env->pc;
 
-    if (!is_hw) {
+    if (!env->exception_is_hw) {
         switch (env->exception_index) {
         case EXCP_RTE:
             /* Return from an exception.  */
@@ -143,7 +143,7 @@ void do_interrupt(int is_hw)
     fmt |= env->sr;
 
     env->sr |= SR_S;
-    if (is_hw) {
+    if (env->exception_is_hw) {
         env->sr = (env->sr & ~SR_I) | (env->pending_level << SR_I_SHIFT);
         env->sr &= ~SR_M;
     }
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 81a1a6b..f10930a 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -645,3 +645,20 @@ int cpu_info_ip(CPUState *env, char *buf)
 
 void cpu_put_flags(CPUState *env) { }
 void cpu_load_flags(CPUState *env) { }
+
+void arch_handle_interrupt_request(CPUState *env)
+{
+    handle_interrupt_common(env);
+    if ((env->interrupt_request & CPU_INTERRUPT_HARD) &&
+        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
+        (env->CP0_Status & (1 << CP0St_IE)) &&
+        !(env->CP0_Status & (1 << CP0St_EXL)) &&
+        !(env->CP0_Status & (1 << CP0St_ERL)) &&
+        !(env->hflags & MIPS_HFLAG_DM)) {
+        /* Raise it */
+        env->exception_index = EXCP_EXT_INTERRUPT;
+        env->error_code = 0;
+        do_interrupt(env);
+        reset_tb();
+    }
+}
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 2858780..ff8398f 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -2997,3 +2997,19 @@ int cpu_info_ip(CPUState *env, char *buf)
 
 void cpu_load_flags(CPUState *env) { }
 void cpu_put_flags(CPUState *env) { }
+
+void arch_handle_interrupt_request(CPUState *env)
+{
+#if 0
+    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
+        cpu_ppc_reset(env);
+    }
+#endif
+    if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+        ppc_hw_interrupt(env);
+        if (env->pending_interrupts == 0)
+            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+        reset_tb();
+    }
+}
+
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index df64d28..9d475ba 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -538,3 +538,11 @@ void cpu_load_tlb(CPUState * env)
 int  cpu_info_ip(CPUState *env, char *buf) { return 0; }
 void cpu_load_flags(CPUState *env) {}
 void cpu_put_flags(CPUState *env) {}
+
+void arch_handle_interrupt_request(CPUState *env)
+{
+    if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+        do_interrupt(env);
+        reset_tb();
+    }
+}
diff --git a/target-sparc/exec.h b/target-sparc/exec.h
index 19d1732..33c5267 100644
--- a/target-sparc/exec.h
+++ b/target-sparc/exec.h
@@ -30,7 +30,8 @@ static inline void regs_to_env(void)
 
 int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
                                int mmu_idx, int is_softmmu);
-void do_interrupt(int intno);
+
+void do_interrupt(CPUState *env);
 
 static inline int cpu_halted(CPUState *env1) {
     if (!env1->halted)
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 0a300fc..d63a91d 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -1339,6 +1339,7 @@ void cpu_put_flags(CPUState *env)
     REGWPTR = saved_regwptr;
 #endif
 }
+
 #ifdef TARGET_SPARC64
 #if !defined(CONFIG_USER_ONLY)
 #include "qemu-common.h"
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 2d85560..a22e752 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -2689,8 +2689,9 @@ static const char * const excp_names[0x50] = {
 };
 #endif
 
-void do_interrupt(int intno)
+void do_interrupt(CPUState *cpu)
 {
+    int intno = cpu->exception_index;
 #ifdef DEBUG_PCALL
     if (loglevel & CPU_LOG_INT) {
         static int count;
@@ -2803,9 +2804,10 @@ static const char * const excp_names[0x80] = {
 };
 #endif
 
-void do_interrupt(int intno)
+void do_interrupt(CPUState *env)
 {
     int cwp;
+    int intno = env->exception_index;
 
 #ifdef DEBUG_PCALL
     if (loglevel & CPU_LOG_INT) {
@@ -2864,6 +2866,29 @@ void do_interrupt(int intno)
 }
 #endif
 
+void arch_handle_interrupt_request(CPUState *env)
+{
+    handle_interrupt_common(env);
+    if ((env->interrupt_request & CPU_INTERRUPT_HARD) && (env->psret != 0)) {
+        int pil = env->interrupt_index & 15;
+        int type = env->interrupt_index & 0xf0;
+
+        if (((type == TT_EXTINT) &&
+            (pil == 15 || pil > env->psrpil)) || type != TT_EXTINT) {
+            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+            do_interrupt(env);
+            env->interrupt_index = 0;
+#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
+            cpu_check_irqs(env);
+#endif
+            reset_tb();
+        }
+    } else if (env->interrupt_request & CPU_INTERRUPT_TIMER) {
+        //do_interrupt(0, 0, 0, 0, 0);
+        env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
+    }
+}
+
 #if !defined(CONFIG_USER_ONLY)
 
 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
-- 
1.5.4.5





reply via email to

[Prev in Thread] Current Thread [Next in Thread]