qemu-devel
[Top][All Lists]
Advanced

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

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


From: Glauber Costa
Subject: [Qemu-devel] [PATCH 5/6] simply cpu_exec further
Date: Wed, 28 May 2008 11:01:35 -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              |    6 ++
 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    |   16 ++++
 target-ppc/helper.c     |   15 ++++
 target-sh4/helper.c     |    8 ++
 target-sparc/helper.c   |   23 ++++++
 15 files changed, 222 insertions(+), 190 deletions(-)

diff --git a/cpu-defs.h b/cpu-defs.h
index bcfec91..742f24d 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 halted;                                                         \
                                                                         \
diff --git a/cpu-exec.c b/cpu-exec.c
index af22e3c..46b0eb8 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);
-#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;
             }
@@ -360,157 +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;
-                            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 9999761..b9a9348 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -96,6 +96,12 @@ void cpu_exec_init(CPUState *env);
 #define cpu_info_ip(env, buf) (0)
 #endif
 
+/* implemented by the targets */
+void cpu_handle_interrupt_request(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 fd39f5f..3ffdc23 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -452,3 +452,12 @@ void cpu_dump_EA (target_ulong EA)
         f = stdout;
     fprintf(f, "Memory access at address " TARGET_FMT_lx "\n", EA);
 }
+
+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 8e85435..9326be2 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2522,3 +2522,30 @@ uint32_t HELPER(rsqrte_u32)(uint32_t a, CPUState *env)
     tmp = float32_scalbn(tmp, 31, s);
     return float32_to_int32(tmp, s);
 }
+
+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 5548b76..94d7660 100644
--- a/target-cris/helper.c
+++ b/target-cris/helper.c
@@ -183,3 +183,12 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, 
target_ulong addr)
        return phy;
 }
 #endif
+
+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 f2da292..2c96914 100644
--- a/target-i386/exec.h
+++ b/target-i386/exec.h
@@ -85,10 +85,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 89c18ee..5e83efd 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1213,8 +1213,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)) {
@@ -1261,6 +1261,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 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 7f01392..f3e95d7 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 b962295..5677a8e 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 2f83438..38a6a34 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -2994,3 +2994,18 @@ int ppc_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 917f02f..71436cd 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -534,3 +534,11 @@ void cpu_load_tlb(CPUState * env)
 }
 
 #endif
+
+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 78a3fe5..68cf78c 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -866,6 +866,29 @@ 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;
+            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]