]> Git Repo - qemu.git/blobdiff - target-m68k/op_helper.c
trace: add "-trace enable=..."
[qemu.git] / target-m68k / op_helper.c
index 9dd3e74ab8c7e6e37c46bfc04a39833a5890b63f..17d0a11914aab1c61a24e0d7ab3d1800689760b3 100644 (file)
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
+#include "qemu/osdep.h"
 #include "cpu.h"
 #include "exec/helper-proto.h"
 #include "exec/cpu_ldst.h"
+#include "exec/semihost.h"
 
 #if defined(CONFIG_USER_ONLY)
 
@@ -27,14 +29,12 @@ void m68k_cpu_do_interrupt(CPUState *cs)
     cs->exception_index = -1;
 }
 
-void do_interrupt_m68k_hardirq(CPUM68KState *env)
+static inline void do_interrupt_m68k_hardirq(CPUM68KState *env)
 {
 }
 
 #else
 
-extern int semihosting_enabled;
-
 /* Try to fill the TLB and return an exception if error. If retaddr is
    NULL, it means that the function was called in C code (i.e. not
    from generated code or from helper.c) */
@@ -63,8 +63,8 @@ static void do_rte(CPUM68KState *env)
     env->pc = cpu_ldl_kernel(env, sp + 4);
     sp |= (fmt >> 28) & 3;
     env->sr = fmt & 0xffff;
-    m68k_switch_sp(env);
     env->aregs[7] = sp + 8;
+    m68k_switch_sp(env);
 }
 
 static void do_interrupt_all(CPUM68KState *env, int is_hw)
@@ -85,7 +85,7 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
             do_rte(env);
             return;
         case EXCP_HALT_INSN:
-            if (semihosting_enabled
+            if (semihosting_enabled()
                     && (env->sr & SR_S) != 0
                     && (env->pc & 3) == 0
                     && cpu_lduw_code(env, env->pc - 4) == 0x4e71
@@ -108,10 +108,7 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
 
     vector = cs->exception_index << 2;
 
-    sp = env->aregs[7];
-
     fmt |= 0x40000000;
-    fmt |= (sp & 3) << 28;
     fmt |= vector << 16;
     fmt |= env->sr;
 
@@ -121,6 +118,8 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
         env->sr &= ~SR_M;
     }
     m68k_switch_sp(env);
+    sp = env->aregs[7];
+    fmt |= (sp & 3) << 28;
 
     /* ??? This could cause MMU faults.  */
     sp &= ~3;
@@ -141,12 +140,30 @@ void m68k_cpu_do_interrupt(CPUState *cs)
     do_interrupt_all(env, 0);
 }
 
-void do_interrupt_m68k_hardirq(CPUM68KState *env)
+static inline void do_interrupt_m68k_hardirq(CPUM68KState *env)
 {
     do_interrupt_all(env, 1);
 }
 #endif
 
+bool m68k_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
+{
+    M68kCPU *cpu = M68K_CPU(cs);
+    CPUM68KState *env = &cpu->env;
+
+    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.  */
+        cs->exception_index = env->pending_vector;
+        do_interrupt_m68k_hardirq(env);
+        return true;
+    }
+    return false;
+}
+
 static void raise_exception(CPUM68KState *env, int tt)
 {
     CPUState *cs = CPU(m68k_env_get_cpu(env));
This page took 0.025952 seconds and 4 git commands to generate.