qemu-devel
[Top][All Lists]
Advanced

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

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


From: Glauber Costa
Subject: [Qemu-devel] [PATCH 4/5] simply cpu_exec further
Date: Thu, 29 May 2008 12:16:05 -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              |  198 +++++------------------------------------------
 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/op_helper.c |   68 ++++++++++++++++-
 target-m68k/cpu.h       |    2 +-
 target-m68k/helper.c    |   16 ++++
 target-m68k/op_helper.c |    8 +-
 target-mips/helper.c    |   16 ++++
 target-ppc/helper.c     |   15 ++++
 target-sh4/helper.c     |    8 ++
 target-sparc/helper.c   |   24 ++++++
 15 files changed, 224 insertions(+), 189 deletions(-)

diff --git a/cpu-defs.h b/cpu-defs.h
index f7f5f17..33d47e8 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -163,6 +163,7 @@ typedef struct CPUTLBEntry {
     /* Core interrupt code */                                           \
     jmp_buf jmp_env;                                                    \
     int exception_index;                                                \
+    int exception_is_hw;                                                \
                                                                         \
     void *next_cpu; /* next CPU sharing TB cache */                     \
     int cpu_index; /* CPU index (informative) */                        \
diff --git a/cpu-exec.c b/cpu-exec.c
index 4d87742..9526608 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -240,6 +240,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)
@@ -280,43 +295,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);
-#elif defined(TARGET_ARM)
-                    do_interrupt(env);
-#elif defined(TARGET_SH4)
-                   do_interrupt(env);
-#elif defined(TARGET_ALPHA)
+                    env->exception_is_hw = 0;
                     do_interrupt(env);
-#elif defined(TARGET_CRIS)
-                    do_interrupt(env);
-#elif defined(TARGET_M68K)
-                    do_interrupt(0);
-#endif
                 }
                 env->exception_index = -1;
             }
@@ -359,157 +347,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;
-                            env->exception_index = env->interrupt_index;
-                            do_interrupt(env);
-                           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
+
+                   cpu_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 072172c..3a6f2a5 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -79,6 +79,13 @@ void cpu_exec_init(CPUState *env);
 
 extern int cpu_info_ip(CPUState *env, char *buf);
 
+/* implemented by the targets */
+void cpu_handle_interrupt_request(CPUState *env);
+void do_interrupt(CPUState *env);
+/* implemented by cpu-exec.c */
+void handle_interrupt_common(CPUState *env);
+void reset_tb(void);
+
 int page_unprotect(target_ulong address, unsigned long pc, void *puc);
 void tb_invalidate_phys_page_range(target_phys_addr_t start, 
target_phys_addr_t end,
                                    int is_cpu_write_access);
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 507929e..593f600 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -454,3 +454,12 @@ void cpu_dump_EA (target_ulong EA)
 }
 
 int cpu_info_ip(CPUState *env, char *buf) { return 0; }
+
+void cpu_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 8dd6209..80eda6f 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2524,3 +2524,30 @@ uint32_t HELPER(rsqrte_u32)(uint32_t a, CPUState *env)
 }
 
 int cpu_info_ip(CPUState *env, char *buf) { return 0; }
+
+void cpu_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 5e566b4..5ae7c52 100644
--- a/target-cris/helper.c
+++ b/target-cris/helper.c
@@ -184,3 +184,12 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, 
target_ulong addr)
 #endif
 
 int cpu_info_ip(CPUState *env, char *buf) { return 0; }
+
+void cpu_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 c5cdbf9..1a7f563 100644
--- a/target-i386/exec.h
+++ b/target-i386/exec.h
@@ -83,10 +83,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/op_helper.c b/target-i386/op_helper.c
index bb76618..3e7fb01 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -1182,7 +1182,7 @@ 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,
+void do_interrupt_system(int intno, int is_int, int error_code,
                   target_ulong next_eip, int is_hw)
 {
     if (loglevel & CPU_LOG_INT) {
@@ -1230,6 +1230,72 @@ 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 cpu_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 d5c5a10..027ae61 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -121,7 +121,7 @@ void m68k_tcg_init(void);
 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 4503006..83f0fe0 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -305,6 +305,22 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, 
target_ulong addr)
     return addr;
 }
 
+void cpu_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 f2e9f03..0233911 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -22,7 +22,7 @@
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt(int is_hw)
+void do_interrupt(CPUState *env)
 {
     env->exception_index = -1;
 }
@@ -91,7 +91,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;
@@ -101,7 +101,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.  */
@@ -139,7 +139,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 3e0b172..2cd322a 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -583,6 +583,22 @@ void do_interrupt (CPUState *env)
     env->exception_index = EXCP_NONE;
 }
 
+void cpu_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();
+    }
+}
 void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra)
 {
     r4k_tlb_t *tlb;
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 464a92e..d6a3ea5 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -2994,3 +2994,18 @@ int cpu_info_ip(CPUState *env, char *buf)
     sprintf(buf, " nip=0x" TARGET_FMT_lx, env->nip);
     return 1;
 }
+
+void cpu_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 1e5ca19..7043fb4 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -536,3 +536,11 @@ void cpu_load_tlb(CPUState * env)
 #endif
 
 int cpu_info_ip(CPUState *env, char *buf) { return 0; }
+
+void cpu_handle_interrupt_request(CPUState *env)
+{
+    if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+        do_interrupt(env);
+        reset_tb();
+    }
+}
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 9b6eba4..39f077a 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -866,6 +866,30 @@ void do_interrupt(CPUState *env)
 }
 #endif
 
+void cpu_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;
+            env->exception_index = env->interrupt_index;
+            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;
+    }
+}
+
 void memcpy32(target_ulong *dst, const target_ulong *src)
 {
     dst[0] = src[0];
-- 
1.5.4.5





reply via email to

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