]> git.proxmox.com Git - mirror_qemu.git/blobdiff - cpu-exec.c
Update TODO.
[mirror_qemu.git] / cpu-exec.c
index 5c85c1e9d8d4573ef858c43401ed3d04e154d0e6..c3d99d418123c24b5cf6c58261fc0ebf1b8bc395 100644 (file)
@@ -40,14 +40,15 @@ int tb_invalidated_flag;
 //#define DEBUG_EXEC
 //#define DEBUG_SIGNAL
 
-#if defined(TARGET_ARM) || defined(TARGET_SPARC)
+#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_M68K) || \
+    defined(TARGET_ALPHA)
 /* XXX: unify with i386 target */
 void cpu_loop_exit(void)
 {
     longjmp(env->jmp_env, 1);
 }
 #endif
-#ifndef TARGET_SPARC
+#if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K))
 #define reg_T2
 #endif
 
@@ -126,7 +127,7 @@ static TranslationBlock *tb_find_slow(target_ulong pc,
         /* cannot fail at this point */
         tb = tb_alloc(pc);
         /* don't forget to invalidate previous TB info */
-        T0 = 0;
+        tb_invalidated_flag = 1;
     }
     tc_ptr = code_gen_ptr;
     tb->tc_ptr = tc_ptr;
@@ -144,12 +145,6 @@ static TranslationBlock *tb_find_slow(target_ulong pc,
     tb_link_phys(tb, phys_pc, phys_page2);
     
  found:
-    if (tb_invalidated_flag) {
-        /* as some TB could have been invalidated because
-           of memory exceptions while generating the code, we
-           must recompute the hash index here */
-        T0 = 0;
-    }
     /* we add the TB in the virtual pc hash table */
     env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
     spin_unlock(&tb_lock);
@@ -175,13 +170,19 @@ static inline TranslationBlock *tb_find_fast(void)
             | (env->vfp.vec_stride << 4);
     if ((env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR)
         flags |= (1 << 6);
+    if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
+        flags |= (1 << 7);
     cs_base = 0;
     pc = env->regs[15];
 #elif defined(TARGET_SPARC)
 #ifdef TARGET_SPARC64
-    flags = (env->pstate << 2) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
+    // Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
+    flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
+        | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
 #else
-    flags = env->psrs | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1);
+    // FPU enable . MMU enabled . MMU no-fault . Supervisor
+    flags = (env->psref << 3) | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1)
+        | env->psrs;
 #endif
     cs_base = env->npc;
     pc = env->pc;
@@ -191,9 +192,23 @@ static inline TranslationBlock *tb_find_fast(void)
     cs_base = 0;
     pc = env->nip;
 #elif defined(TARGET_MIPS)
-    flags = env->hflags & MIPS_HFLAGS_TMASK;
+    flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
     cs_base = 0;
     pc = env->PC;
+#elif defined(TARGET_M68K)
+    flags = (env->fpcr & M68K_FPCR_PREC)  /* Bit  6 */
+            | (env->sr & SR_S)            /* Bit  13 */
+            | ((env->macsr >> 4) & 0xf);  /* Bits 0-3 */
+    cs_base = 0;
+    pc = env->pc;
+#elif defined(TARGET_SH4)
+    flags = env->sr & (SR_MD | SR_RB);
+    cs_base = 0;         /* XXXXX */
+    pc = env->pc;
+#elif defined(TARGET_ALPHA)
+    flags = env->ps;
+    cs_base = 0;
+    pc = env->pc;
 #else
 #error unsupported CPU
 #endif
@@ -201,6 +216,14 @@ static inline TranslationBlock *tb_find_fast(void)
     if (__builtin_expect(!tb || tb->pc != pc || tb->cs_base != cs_base ||
                          tb->flags != flags, 0)) {
         tb = tb_find_slow(pc, cs_base, flags);
+        /* Note: we do it here to avoid a gcc bug on Mac OS X when
+           doing it in tb_find_slow */
+        if (tb_invalidated_flag) {
+            /* as some TB could have been invalidated because
+               of memory exceptions while generating the code, we
+               must recompute the hash index here */
+            T0 = 0;
+        }
     }
     return tb;
 }
@@ -210,43 +233,16 @@ static inline TranslationBlock *tb_find_fast(void)
 
 int cpu_exec(CPUState *env1)
 {
-    int saved_T0, saved_T1;
-#if defined(reg_T2)
-    int saved_T2;
-#endif
-    CPUState *saved_env;
-#if defined(TARGET_I386)
-#ifdef reg_EAX
-    int saved_EAX;
-#endif
-#ifdef reg_ECX
-    int saved_ECX;
-#endif
-#ifdef reg_EDX
-    int saved_EDX;
-#endif
-#ifdef reg_EBX
-    int saved_EBX;
-#endif
-#ifdef reg_ESP
-    int saved_ESP;
-#endif
-#ifdef reg_EBP
-    int saved_EBP;
-#endif
-#ifdef reg_ESI
-    int saved_ESI;
-#endif
-#ifdef reg_EDI
-    int saved_EDI;
-#endif
-#elif defined(TARGET_SPARC)
+#define DECLARE_HOST_REGS 1
+#include "hostregs_helper.h"
+#if defined(TARGET_SPARC)
 #if defined(reg_REGWPTR)
     uint32_t *saved_regwptr;
 #endif
 #endif
-#ifdef __sparc__
-    int saved_i7, tmp_T0;
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
+    int saved_i7;
+    target_ulong tmp_T0;
 #endif
     int ret, interrupt_request;
     void (*gen_func)(void);
@@ -265,11 +261,19 @@ int cpu_exec(CPUState *env1)
         }
     }
 #elif defined(TARGET_PPC)
-    if (env1->msr[MSR_POW]) {
+    if (env1->halted) {
         if (env1->msr[MSR_EE] && 
-            (env1->interrupt_request & 
-             (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER))) {
-            env1->msr[MSR_POW] = 0;
+            (env1->interrupt_request & CPU_INTERRUPT_HARD)) {
+            env1->halted = 0;
+        } else {
+            return EXCP_HALTED;
+        }
+    }
+#elif defined(TARGET_SPARC)
+    if (env1->halted) {
+        if ((env1->interrupt_request & CPU_INTERRUPT_HARD) &&
+            (env1->psret != 0)) {
+            env1->halted = 0;
         } else {
             return EXCP_HALTED;
         }
@@ -277,9 +281,27 @@ int cpu_exec(CPUState *env1)
 #elif defined(TARGET_ARM)
     if (env1->halted) {
         /* An interrupt wakes the CPU even if the I and F CPSR bits are
-           set.  */
-        if (env1->interrupt_request
-            & (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD)) {
+           set.  We use EXITTB to silently wake CPU without causing an
+           actual interrupt.  */
+        if (env1->interrupt_request &
+            (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB)) {
+            env1->halted = 0;
+        } else {
+            return EXCP_HALTED;
+        }
+    }
+#elif defined(TARGET_MIPS)
+    if (env1->halted) {
+        if (env1->interrupt_request &
+            (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER)) {
+            env1->halted = 0;
+        } else {
+            return EXCP_HALTED;
+        }
+    }
+#elif defined(TARGET_ALPHA) || defined(TARGET_M68K)
+    if (env1->halted) {
+        if (env1->interrupt_request & CPU_INTERRUPT_HARD) {
             env1->halted = 0;
         } else {
             return EXCP_HALTED;
@@ -290,44 +312,15 @@ int cpu_exec(CPUState *env1)
     cpu_single_env = env1; 
 
     /* first we save global registers */
-    saved_env = env;
+#define SAVE_HOST_REGS 1
+#include "hostregs_helper.h"
     env = env1;
-    saved_T0 = T0;
-    saved_T1 = T1;
-#if defined(reg_T2)
-    saved_T2 = T2;
-#endif
-#ifdef __sparc__
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
     /* we also save i7 because longjmp may not restore it */
     asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
 #endif
 
 #if defined(TARGET_I386)
-#ifdef reg_EAX
-    saved_EAX = EAX;
-#endif
-#ifdef reg_ECX
-    saved_ECX = ECX;
-#endif
-#ifdef reg_EDX
-    saved_EDX = EDX;
-#endif
-#ifdef reg_EBX
-    saved_EBX = EBX;
-#endif
-#ifdef reg_ESP
-    saved_ESP = ESP;
-#endif
-#ifdef reg_EBP
-    saved_EBP = EBP;
-#endif
-#ifdef reg_ESI
-    saved_ESI = ESI;
-#endif
-#ifdef reg_EDI
-    saved_EDI = EDI;
-#endif
-
     env_to_regs();
     /* put eflags in CPU temporary format */
     CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
@@ -340,7 +333,15 @@ int cpu_exec(CPUState *env1)
     saved_regwptr = REGWPTR;
 #endif
 #elif defined(TARGET_PPC)
+#elif defined(TARGET_M68K)
+    env->cc_op = CC_OP_FLAGS;
+    env->cc_dest = env->sr & 0xf;
+    env->cc_x = (env->sr >> 4) & 1;
 #elif defined(TARGET_MIPS)
+#elif defined(TARGET_SH4)
+    /* XXXXX */
+#elif defined(TARGET_ALPHA)
+    env_to_regs();
 #else
 #error unsupported target CPU
 #endif
@@ -358,7 +359,7 @@ int cpu_exec(CPUState *env1)
                     break;
                 } else if (env->user_mode_only) {
                     /* if user mode only, we simulate a fake exception
-                       which will be hanlded outside the cpu execution
+                       which will be handled outside the cpu execution
                        loop */
 #if defined(TARGET_I386)
                     do_interrupt_user(env->exception_index, 
@@ -377,6 +378,8 @@ int cpu_exec(CPUState *env1)
                                  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)
@@ -385,6 +388,12 @@ int cpu_exec(CPUState *env1)
                     do_interrupt(env->exception_index);
 #elif defined(TARGET_ARM)
                     do_interrupt(env);
+#elif defined(TARGET_SH4)
+                   do_interrupt(env);
+#elif defined(TARGET_ALPHA)
+                    do_interrupt(env);
+#elif defined(TARGET_M68K)
+                    do_interrupt(0);
 #endif
                 }
                 env->exception_index = -1;
@@ -417,15 +426,37 @@ int cpu_exec(CPUState *env1)
 
             T0 = 0; /* force lookup of first TB */
             for(;;) {
-#ifdef __sparc__
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
                 /* g1 can be modified by some libc? functions */ 
                 tmp_T0 = T0;
 #endif     
                 interrupt_request = env->interrupt_request;
                 if (__builtin_expect(interrupt_request, 0)) {
+                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {
+                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
+                        env->exception_index = EXCP_DEBUG;
+                        cpu_loop_exit();
+                    }
+#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
+    defined(TARGET_PPC) || defined(TARGET_ALPHA)
+                    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 hardware interrupt pending, we execute it */
-                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
+                    if ((interrupt_request & CPU_INTERRUPT_SMI) &&
+                        !(env->hflags & HF_SMM_MASK)) {
+                        env->interrupt_request &= ~CPU_INTERRUPT_SMI;
+                        do_smm_enter();
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
+                        tmp_T0 = 0;
+#else
+                        T0 = 0;
+#endif
+                    } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
                         (env->eflags & IF_MASK) && 
                         !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
                         int intno;
@@ -437,7 +468,7 @@ int cpu_exec(CPUState *env1)
                         do_interrupt(intno, 0, 0, 0, 1);
                         /* ensure that no TB jump will be modified as
                            the program flow was changed */
-#ifdef __sparc__
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
                         tmp_T0 = 0;
 #else
                         T0 = 0;
@@ -449,44 +480,28 @@ int cpu_exec(CPUState *env1)
                         cpu_ppc_reset(env);
                     }
 #endif
-                    if (msr_ee != 0) {
-                        if ((interrupt_request & CPU_INTERRUPT_HARD)) {
-                           /* Raise it */
-                           env->exception_index = EXCP_EXTERNAL;
-                           env->error_code = 0;
-                            do_interrupt(env);
+                    if (interrupt_request & CPU_INTERRUPT_HARD) {
+                        ppc_hw_interrupt(env);
+                        if (env->pending_interrupts == 0)
                             env->interrupt_request &= ~CPU_INTERRUPT_HARD;
-#ifdef __sparc__
-                            tmp_T0 = 0;
-#else
-                            T0 = 0;
-#endif
-                        } else if ((interrupt_request & CPU_INTERRUPT_TIMER)) {
-                            /* Raise it */
-                            env->exception_index = EXCP_DECR;
-                            env->error_code = 0;
-                            do_interrupt(env);
-                            env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
-#ifdef __sparc__
-                            tmp_T0 = 0;
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
+                        tmp_T0 = 0;
 #else
-                            T0 = 0;
+                        T0 = 0;
 #endif
-                        }
                     }
 #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 & env->CP0_Cause & 0x0000FF00) &&
-                        !(env->hflags & MIPS_HFLAG_EXL) &&
-                        !(env->hflags & MIPS_HFLAG_ERL) &&
+                        !(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);
-                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
-#ifdef __sparc__
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
                         tmp_T0 = 0;
 #else
                         T0 = 0;
@@ -504,7 +519,7 @@ int cpu_exec(CPUState *env1)
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
                            do_interrupt(env->interrupt_index);
                            env->interrupt_index = 0;
-#ifdef __sparc__
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
                             tmp_T0 = 0;
 #else
                             T0 = 0;
@@ -525,12 +540,32 @@ int cpu_exec(CPUState *env1)
                         env->exception_index = EXCP_IRQ;
                         do_interrupt(env);
                     }
+#elif defined(TARGET_SH4)
+                   /* XXXXX */
+#elif defined(TARGET_ALPHA)
+                    if (interrupt_request & CPU_INTERRUPT_HARD) {
+                        do_interrupt(env);
+                    }
+#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);
+                    }
 #endif
+                   /* Don't use the cached interupt_request value,
+                      do_interrupt may have updated the EXITTB flag. */
                     if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
                         env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
                         /* ensure that no TB jump will be modified as
                            the program flow was changed */
-#ifdef __sparc__
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
                         tmp_T0 = 0;
 #else
                         T0 = 0;
@@ -581,8 +616,18 @@ int cpu_exec(CPUState *env1)
                     cpu_dump_state(env, logfile, fprintf, 0);
 #elif defined(TARGET_PPC)
                     cpu_dump_state(env, logfile, fprintf, 0);
+#elif defined(TARGET_M68K)
+                    cpu_m68k_flush_flags(env, env->cc_op);
+                    env->cc_op = CC_OP_FLAGS;
+                    env->sr = (env->sr & 0xffe0)
+                              | env->cc_dest | (env->cc_x << 4);
+                    cpu_dump_state(env, logfile, fprintf, 0);
 #elif defined(TARGET_MIPS)
                     cpu_dump_state(env, logfile, fprintf, 0);
+#elif defined(TARGET_SH4)
+                   cpu_dump_state(env, logfile, fprintf, 0);
+#elif defined(TARGET_ALPHA)
+                    cpu_dump_state(env, logfile, fprintf, 0);
 #else
 #error unsupported target CPU 
 #endif
@@ -596,7 +641,7 @@ int cpu_exec(CPUState *env1)
                             lookup_symbol(tb->pc));
                 }
 #endif
-#ifdef __sparc__
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
                 T0 = tmp_T0;
 #endif     
                 /* see if we can patch the calling TB. When the TB
@@ -604,6 +649,9 @@ int cpu_exec(CPUState *env1)
                    jump. */
                 {
                     if (T0 != 0 &&
+#if USE_KQEMU
+                        (env->kqemu_enabled != 2) &&
+#endif
                         tb->page_addr[1] == -1
 #if defined(TARGET_I386) && defined(USE_CODE_COPY)
                     && (tb->cflags & CF_CODE_COPY) == 
@@ -629,7 +677,10 @@ int cpu_exec(CPUState *env1)
                                      "mov      %%o7,%%i0"
                                      : /* no outputs */
                                      : "r" (gen_func) 
-                                     : "i0", "i1", "i2", "i3", "i4", "i5");
+                                     : "i0", "i1", "i2", "i3", "i4", "i5",
+                                       "o0", "o1", "o2", "o3", "o4", "o5",
+                                       "l0", "l1", "l2", "l3", "l4", "l5",
+                                       "l6", "l7");
 #elif defined(__arm__)
                 asm volatile ("mov pc, %0\n\t"
                               ".global exec_loop\n\t"
@@ -732,6 +783,13 @@ int cpu_exec(CPUState *env1)
                     /* do not allow linking to another block */
                     T0 = 0;
                 }
+#endif
+#if defined(USE_KQEMU)
+#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
+                if (kqemu_is_ok(env) &&
+                    (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
+                    cpu_loop_exit();
+                }
 #endif
             }
         } else {
@@ -748,32 +806,6 @@ int cpu_exec(CPUState *env1)
 #endif
     /* restore flags in standard format */
     env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
-
-    /* restore global registers */
-#ifdef reg_EAX
-    EAX = saved_EAX;
-#endif
-#ifdef reg_ECX
-    ECX = saved_ECX;
-#endif
-#ifdef reg_EDX
-    EDX = saved_EDX;
-#endif
-#ifdef reg_EBX
-    EBX = saved_EBX;
-#endif
-#ifdef reg_ESP
-    ESP = saved_ESP;
-#endif
-#ifdef reg_EBP
-    EBP = saved_EBP;
-#endif
-#ifdef reg_ESI
-    ESI = saved_ESI;
-#endif
-#ifdef reg_EDI
-    EDI = saved_EDI;
-#endif
 #elif defined(TARGET_ARM)
     /* XXX: Save/restore host fpu exception state?.  */
 #elif defined(TARGET_SPARC)
@@ -781,19 +813,25 @@ int cpu_exec(CPUState *env1)
     REGWPTR = saved_regwptr;
 #endif
 #elif defined(TARGET_PPC)
+#elif defined(TARGET_M68K)
+    cpu_m68k_flush_flags(env, env->cc_op);
+    env->cc_op = CC_OP_FLAGS;
+    env->sr = (env->sr & 0xffe0)
+              | env->cc_dest | (env->cc_x << 4);
 #elif defined(TARGET_MIPS)
+#elif defined(TARGET_SH4)
+#elif defined(TARGET_ALPHA)
+    /* XXXXX */
 #else
 #error unsupported target CPU
 #endif
-#ifdef __sparc__
+
+    /* restore global registers */
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
     asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
 #endif
-    T0 = saved_T0;
-    T1 = saved_T1;
-#if defined(reg_T2)
-    T2 = saved_T2;
-#endif
-    env = saved_env;
+#include "hostregs_helper.h"
+
     /* fail safe : never use cpu_single_env outside cpu_exec() */
     cpu_single_env = NULL; 
     return ret;
@@ -878,7 +916,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                 pc, address, is_write, *(unsigned long *)old_set);
 #endif
     /* XXX: locking issue */
-    if (is_write && page_unprotect(address, pc, puc)) {
+    if (is_write && page_unprotect(h2g(address), pc, puc)) {
         return 1;
     }
 
@@ -904,7 +942,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
         /* we restore the process signal mask as the sigreturn should
            do it (XXX: use sigsetjmp) */
         sigprocmask(SIG_SETMASK, old_set, NULL);
-        raise_exception_err(EXCP0E_PAGE, env->error_code);
+        raise_exception_err(env->exception_index, env->error_code);
     } else {
         /* activate soft MMU for this block */
         env->hflags |= HF_SOFTMMU_MASK;
@@ -929,7 +967,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
            pc, address, is_write, *(unsigned long *)old_set);
 #endif
     /* XXX: locking issue */
-    if (is_write && page_unprotect(address, pc, puc)) {
+    if (is_write && page_unprotect(h2g(address), pc, puc)) {
         return 1;
     }
     /* see if it is an MMU fault */
@@ -965,7 +1003,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
            pc, address, is_write, *(unsigned long *)old_set);
 #endif
     /* XXX: locking issue */
-    if (is_write && page_unprotect(address, pc, puc)) {
+    if (is_write && page_unprotect(h2g(address), pc, puc)) {
         return 1;
     }
     /* see if it is an MMU fault */
@@ -1001,7 +1039,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
            pc, address, is_write, *(unsigned long *)old_set);
 #endif
     /* XXX: locking issue */
-    if (is_write && page_unprotect(address, pc, puc)) {
+    if (is_write && page_unprotect(h2g(address), pc, puc)) {
         return 1;
     }
 
@@ -1036,6 +1074,45 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
     return 1;
 }
 
+#elif defined(TARGET_M68K)
+static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
+                                    int is_write, sigset_t *old_set,
+                                    void *puc)
+{
+    TranslationBlock *tb;
+    int ret;
+
+    if (cpu_single_env)
+        env = cpu_single_env; /* XXX: find a correct solution for multithread */
+#if defined(DEBUG_SIGNAL)
+    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
+           pc, address, is_write, *(unsigned long *)old_set);
+#endif
+    /* XXX: locking issue */
+    if (is_write && page_unprotect(address, pc, puc)) {
+        return 1;
+    }
+    /* see if it is an MMU fault */
+    ret = cpu_m68k_handle_mmu_fault(env, address, is_write, 1, 0);
+    if (ret < 0)
+        return 0; /* not an MMU fault */
+    if (ret == 0)
+        return 1; /* the MMU fault was handled without causing real CPU fault */
+    /* now we have a real cpu fault */
+    tb = tb_find_pc(pc);
+    if (tb) {
+        /* the PC is inside the translated code. It means that we have
+           a virtual CPU fault */
+        cpu_restore_state(tb, env, pc, puc);
+    }
+    /* we restore the process signal mask as the sigreturn should
+       do it (XXX: use sigsetjmp) */
+    sigprocmask(SIG_SETMASK, old_set, NULL);
+    cpu_loop_exit();
+    /* never comes here */
+    return 1;
+}
+
 #elif defined (TARGET_MIPS)
 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                                     int is_write, sigset_t *old_set,
@@ -1051,7 +1128,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
            pc, address, is_write, *(unsigned long *)old_set);
 #endif
     /* XXX: locking issue */
-    if (is_write && page_unprotect(address, pc, puc)) {
+    if (is_write && page_unprotect(h2g(address), pc, puc)) {
         return 1;
     }
 
@@ -1071,8 +1148,8 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
     }
     if (ret == 1) {
 #if 0
-        printf("PF exception: NIP=0x%08x error=0x%x %p\n", 
-               env->nip, env->error_code, tb);
+        printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n", 
+               env->PC, env->error_code, tb);
 #endif
     /* we restore the process signal mask as the sigreturn should
        do it (XXX: use sigsetjmp) */
@@ -1086,12 +1163,113 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
     return 1;
 }
 
+#elif defined (TARGET_SH4)
+static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
+                                    int is_write, sigset_t *old_set,
+                                    void *puc)
+{
+    TranslationBlock *tb;
+    int ret;
+    
+    if (cpu_single_env)
+        env = cpu_single_env; /* XXX: find a correct solution for multithread */
+#if defined(DEBUG_SIGNAL)
+    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
+           pc, address, is_write, *(unsigned long *)old_set);
+#endif
+    /* XXX: locking issue */
+    if (is_write && page_unprotect(h2g(address), pc, puc)) {
+        return 1;
+    }
+
+    /* see if it is an MMU fault */
+    ret = cpu_sh4_handle_mmu_fault(env, address, is_write, 1, 0);
+    if (ret < 0)
+        return 0; /* not an MMU fault */
+    if (ret == 0)
+        return 1; /* the MMU fault was handled without causing real CPU fault */
+
+    /* now we have a real cpu fault */
+    tb = tb_find_pc(pc);
+    if (tb) {
+        /* the PC is inside the translated code. It means that we have
+           a virtual CPU fault */
+        cpu_restore_state(tb, env, pc, puc);
+    }
+#if 0
+        printf("PF exception: NIP=0x%08x error=0x%x %p\n", 
+               env->nip, env->error_code, tb);
+#endif
+    /* we restore the process signal mask as the sigreturn should
+       do it (XXX: use sigsetjmp) */
+    sigprocmask(SIG_SETMASK, old_set, NULL);
+    cpu_loop_exit();
+    /* never comes here */
+    return 1;
+}
+
+#elif defined (TARGET_ALPHA)
+static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
+                                    int is_write, sigset_t *old_set,
+                                    void *puc)
+{
+    TranslationBlock *tb;
+    int ret;
+    
+    if (cpu_single_env)
+        env = cpu_single_env; /* XXX: find a correct solution for multithread */
+#if defined(DEBUG_SIGNAL)
+    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
+           pc, address, is_write, *(unsigned long *)old_set);
+#endif
+    /* XXX: locking issue */
+    if (is_write && page_unprotect(h2g(address), pc, puc)) {
+        return 1;
+    }
+
+    /* see if it is an MMU fault */
+    ret = cpu_alpha_handle_mmu_fault(env, address, is_write, 1, 0);
+    if (ret < 0)
+        return 0; /* not an MMU fault */
+    if (ret == 0)
+        return 1; /* the MMU fault was handled without causing real CPU fault */
+
+    /* now we have a real cpu fault */
+    tb = tb_find_pc(pc);
+    if (tb) {
+        /* the PC is inside the translated code. It means that we have
+           a virtual CPU fault */
+        cpu_restore_state(tb, env, pc, puc);
+    }
+#if 0
+        printf("PF exception: NIP=0x%08x error=0x%x %p\n", 
+               env->nip, env->error_code, tb);
+#endif
+    /* we restore the process signal mask as the sigreturn should
+       do it (XXX: use sigsetjmp) */
+    sigprocmask(SIG_SETMASK, old_set, NULL);
+    cpu_loop_exit();
+    /* never comes here */
+    return 1;
+}
 #else
 #error unsupported target CPU
 #endif
 
 #if defined(__i386__)
 
+#if defined(__APPLE__)
+# include <sys/ucontext.h>
+
+# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
+# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
+# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
+#else
+# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
+# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
+# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
+#endif
+
 #if defined(USE_CODE_COPY)
 static void cpu_send_trap(unsigned long pc, int trap, 
                           struct ucontext *uc)
@@ -1112,9 +1290,10 @@ static void cpu_send_trap(unsigned long pc, int trap,
 }
 #endif
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
     int trapno;
@@ -1125,8 +1304,8 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
 #define REG_ERR    ERR
 #define REG_TRAPNO TRAPNO
 #endif
-    pc = uc->uc_mcontext.gregs[REG_EIP];
-    trapno = uc->uc_mcontext.gregs[REG_TRAPNO];
+    pc = EIP_sig(uc);
+    trapno = TRAP_sig(uc);
 #if defined(TARGET_I386) && defined(USE_CODE_COPY)
     if (trapno == 0x00 || trapno == 0x05) {
         /* send division by zero or bound exception */
@@ -1136,15 +1315,16 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
 #endif
         return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
                                  trapno == 0xe ? 
-                                 (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
+                                 (ERROR_sig(uc) >> 1) & 1 : 0,
                                  &uc->uc_sigmask, puc);
 }
 
 #elif defined(__x86_64__)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info,
+int cpu_signal_handler(int host_signum, void *pinfo,
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
 
@@ -1206,9 +1386,10 @@ typedef struct ucontext SIGCONTEXT;
 # define TRAP_sig(context)                     EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
 #endif /* __APPLE__ */
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
     int is_write;
@@ -1229,9 +1410,10 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
 
 #elif defined(__alpha__)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                            void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     uint32_t *pc = uc->uc_mcontext.sc_pc;
     uint32_t insn = *pc;
@@ -1258,9 +1440,10 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
 }
 #elif defined(__sparc__)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     uint32_t *regs = (uint32_t *)(info + 1);
     void *sigmask = (regs + 20);
     unsigned long pc;
@@ -1291,9 +1474,10 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
 
 #elif defined(__arm__)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
     int is_write;
@@ -1303,14 +1487,15 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
     is_write = 0;
     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
                              is_write,
-                             &uc->uc_sigmask);
+                             &uc->uc_sigmask, puc);
 }
 
 #elif defined(__mc68000)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
     int is_write;
@@ -1328,11 +1513,11 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
 #ifndef __ISR_VALID
   /* This ought to be in <bits/siginfo.h>... */
 # define __ISR_VALID   1
-# define si_flags      _sifields._sigfault._si_pad0
 #endif
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc)
+int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long ip;
     int is_write = 0;
@@ -1344,7 +1529,7 @@ int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc)
       case SIGSEGV:
       case SIGBUS:
       case SIGTRAP:
-         if (info->si_code && (info->si_flags & __ISR_VALID))
+         if (info->si_code && (info->si_segvflags & __ISR_VALID))
              /* ISR.W (write-access) is bit 33:  */
              is_write = (info->si_isr >> 33) & 1;
          break;
@@ -1359,9 +1544,10 @@ int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc)
 
 #elif defined(__s390__)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
     int is_write;
@@ -1370,8 +1556,23 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
     /* XXX: compute is_write */
     is_write = 0;
     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
-                             is_write,
-                             &uc->uc_sigmask, puc);
+                             is_write, &uc->uc_sigmask, puc);
+}
+
+#elif defined(__mips__)
+
+int cpu_signal_handler(int host_signum, void *pinfo, 
+                       void *puc)
+{
+    siginfo_t *info = pinfo;
+    struct ucontext *uc = puc;
+    greg_t pc = uc->uc_mcontext.pc;
+    int is_write;
+    
+    /* XXX: compute is_write */
+    is_write = 0;
+    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
+                             is_write, &uc->uc_sigmask, puc);
 }
 
 #else