]> rtime.felk.cvut.cz Git - lisovros/qemu_apohw.git/blob - cpu-exec.c
Merge remote branch 'kwolf/for-anthony' into staging
[lisovros/qemu_apohw.git] / cpu-exec.c
1 /*
2  *  i386 emulator main execution loop
3  *
4  *  Copyright (c) 2003-2005 Fabrice Bellard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  */
19 #include "config.h"
20 #include "exec.h"
21 #include "disas.h"
22 #include "tcg.h"
23 #include "kvm.h"
24 #include "qemu-barrier.h"
25
26 #if !defined(CONFIG_SOFTMMU)
27 #undef EAX
28 #undef ECX
29 #undef EDX
30 #undef EBX
31 #undef ESP
32 #undef EBP
33 #undef ESI
34 #undef EDI
35 #undef EIP
36 #include <signal.h>
37 #ifdef __linux__
38 #include <sys/ucontext.h>
39 #endif
40 #endif
41
42 #if defined(__sparc__) && !defined(CONFIG_SOLARIS)
43 // Work around ugly bugs in glibc that mangle global register contents
44 #undef env
45 #define env cpu_single_env
46 #endif
47
48 int tb_invalidated_flag;
49
50 //#define CONFIG_DEBUG_EXEC
51 //#define DEBUG_SIGNAL
52
53 int qemu_cpu_has_work(CPUState *env)
54 {
55     return cpu_has_work(env);
56 }
57
58 void cpu_loop_exit(void)
59 {
60     env->current_tb = NULL;
61     longjmp(env->jmp_env, 1);
62 }
63
64 /* exit the current TB from a signal handler. The host registers are
65    restored in a state compatible with the CPU emulator
66  */
67 void cpu_resume_from_signal(CPUState *env1, void *puc)
68 {
69 #if !defined(CONFIG_SOFTMMU)
70 #ifdef __linux__
71     struct ucontext *uc = puc;
72 #elif defined(__OpenBSD__)
73     struct sigcontext *uc = puc;
74 #endif
75 #endif
76
77     env = env1;
78
79     /* XXX: restore cpu registers saved in host registers */
80
81 #if !defined(CONFIG_SOFTMMU)
82     if (puc) {
83         /* XXX: use siglongjmp ? */
84 #ifdef __linux__
85 #ifdef __ia64
86         sigprocmask(SIG_SETMASK, (sigset_t *)&uc->uc_sigmask, NULL);
87 #else
88         sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
89 #endif
90 #elif defined(__OpenBSD__)
91         sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
92 #endif
93     }
94 #endif
95     env->exception_index = -1;
96     longjmp(env->jmp_env, 1);
97 }
98
99 /* Execute the code without caching the generated code. An interpreter
100    could be used if available. */
101 static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
102 {
103     unsigned long next_tb;
104     TranslationBlock *tb;
105
106     /* Should never happen.
107        We only end up here when an existing TB is too long.  */
108     if (max_cycles > CF_COUNT_MASK)
109         max_cycles = CF_COUNT_MASK;
110
111     tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
112                      max_cycles);
113     env->current_tb = tb;
114     /* execute the generated code */
115     next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
116     env->current_tb = NULL;
117
118     if ((next_tb & 3) == 2) {
119         /* Restore PC.  This may happen if async event occurs before
120            the TB starts executing.  */
121         cpu_pc_from_tb(env, tb);
122     }
123     tb_phys_invalidate(tb, -1);
124     tb_free(tb);
125 }
126
127 static TranslationBlock *tb_find_slow(target_ulong pc,
128                                       target_ulong cs_base,
129                                       uint64_t flags)
130 {
131     TranslationBlock *tb, **ptb1;
132     unsigned int h;
133     tb_page_addr_t phys_pc, phys_page1, phys_page2;
134     target_ulong virt_page2;
135
136     tb_invalidated_flag = 0;
137
138     /* find translated block using physical mappings */
139     phys_pc = get_page_addr_code(env, pc);
140     phys_page1 = phys_pc & TARGET_PAGE_MASK;
141     phys_page2 = -1;
142     h = tb_phys_hash_func(phys_pc);
143     ptb1 = &tb_phys_hash[h];
144     for(;;) {
145         tb = *ptb1;
146         if (!tb)
147             goto not_found;
148         if (tb->pc == pc &&
149             tb->page_addr[0] == phys_page1 &&
150             tb->cs_base == cs_base &&
151             tb->flags == flags) {
152             /* check next page if needed */
153             if (tb->page_addr[1] != -1) {
154                 virt_page2 = (pc & TARGET_PAGE_MASK) +
155                     TARGET_PAGE_SIZE;
156                 phys_page2 = get_page_addr_code(env, virt_page2);
157                 if (tb->page_addr[1] == phys_page2)
158                     goto found;
159             } else {
160                 goto found;
161             }
162         }
163         ptb1 = &tb->phys_hash_next;
164     }
165  not_found:
166    /* if no translated code available, then translate it now */
167     tb = tb_gen_code(env, pc, cs_base, flags, 0);
168
169  found:
170     /* Move the last found TB to the head of the list */
171     if (likely(*ptb1)) {
172         *ptb1 = tb->phys_hash_next;
173         tb->phys_hash_next = tb_phys_hash[h];
174         tb_phys_hash[h] = tb;
175     }
176     /* we add the TB in the virtual pc hash table */
177     env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
178     return tb;
179 }
180
181 static inline TranslationBlock *tb_find_fast(void)
182 {
183     TranslationBlock *tb;
184     target_ulong cs_base, pc;
185     int flags;
186
187     /* we record a subset of the CPU state. It will
188        always be the same before a given translated block
189        is executed. */
190     cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
191     tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
192     if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
193                  tb->flags != flags)) {
194         tb = tb_find_slow(pc, cs_base, flags);
195     }
196     return tb;
197 }
198
199 /* main execution loop */
200
201 volatile sig_atomic_t exit_request;
202
203 int cpu_exec(CPUState *env1)
204 {
205     volatile host_reg_t saved_env_reg;
206     int ret, interrupt_request;
207     TranslationBlock *tb;
208     uint8_t *tc_ptr;
209     unsigned long next_tb;
210
211     if (cpu_halted(env1) == EXCP_HALTED)
212         return EXCP_HALTED;
213
214     cpu_single_env = env1;
215
216     /* the access to env below is actually saving the global register's
217        value, so that files not including target-xyz/exec.h are free to
218        use it.  */
219     QEMU_BUILD_BUG_ON (sizeof (saved_env_reg) != sizeof (env));
220     saved_env_reg = (host_reg_t) env;
221     barrier();
222     env = env1;
223
224     if (unlikely(exit_request)) {
225         env->exit_request = 1;
226     }
227
228 #if defined(TARGET_I386)
229     /* put eflags in CPU temporary format */
230     CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
231     DF = 1 - (2 * ((env->eflags >> 10) & 1));
232     CC_OP = CC_OP_EFLAGS;
233     env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
234 #elif defined(TARGET_SPARC)
235 #elif defined(TARGET_M68K)
236     env->cc_op = CC_OP_FLAGS;
237     env->cc_dest = env->sr & 0xf;
238     env->cc_x = (env->sr >> 4) & 1;
239 #elif defined(TARGET_ALPHA)
240 #elif defined(TARGET_ARM)
241 #elif defined(TARGET_PPC)
242 #elif defined(TARGET_MICROBLAZE)
243 #elif defined(TARGET_MIPS)
244 #elif defined(TARGET_SH4)
245 #elif defined(TARGET_CRIS)
246 #elif defined(TARGET_S390X)
247     /* XXXXX */
248 #else
249 #error unsupported target CPU
250 #endif
251     env->exception_index = -1;
252
253     /* prepare setjmp context for exception handling */
254     for(;;) {
255         if (setjmp(env->jmp_env) == 0) {
256 #if defined(__sparc__) && !defined(CONFIG_SOLARIS)
257 #undef env
258             env = cpu_single_env;
259 #define env cpu_single_env
260 #endif
261             /* if an exception is pending, we execute it here */
262             if (env->exception_index >= 0) {
263                 if (env->exception_index >= EXCP_INTERRUPT) {
264                     /* exit request from the cpu execution loop */
265                     ret = env->exception_index;
266                     break;
267                 } else {
268 #if defined(CONFIG_USER_ONLY)
269                     /* if user mode only, we simulate a fake exception
270                        which will be handled outside the cpu execution
271                        loop */
272 #if defined(TARGET_I386)
273                     do_interrupt_user(env->exception_index,
274                                       env->exception_is_int,
275                                       env->error_code,
276                                       env->exception_next_eip);
277                     /* successfully delivered */
278                     env->old_exception = -1;
279 #endif
280                     ret = env->exception_index;
281                     break;
282 #else
283 #if defined(TARGET_I386)
284                     /* simulate a real cpu exception. On i386, it can
285                        trigger new exceptions, but we do not handle
286                        double or triple faults yet. */
287                     do_interrupt(env->exception_index,
288                                  env->exception_is_int,
289                                  env->error_code,
290                                  env->exception_next_eip, 0);
291                     /* successfully delivered */
292                     env->old_exception = -1;
293 #elif defined(TARGET_PPC)
294                     do_interrupt(env);
295 #elif defined(TARGET_MICROBLAZE)
296                     do_interrupt(env);
297 #elif defined(TARGET_MIPS)
298                     do_interrupt(env);
299 #elif defined(TARGET_SPARC)
300                     do_interrupt(env);
301 #elif defined(TARGET_ARM)
302                     do_interrupt(env);
303 #elif defined(TARGET_SH4)
304                     do_interrupt(env);
305 #elif defined(TARGET_ALPHA)
306                     do_interrupt(env);
307 #elif defined(TARGET_CRIS)
308                     do_interrupt(env);
309 #elif defined(TARGET_M68K)
310                     do_interrupt(0);
311 #endif
312                     env->exception_index = -1;
313 #endif
314                 }
315             }
316
317             next_tb = 0; /* force lookup of first TB */
318             for(;;) {
319                 interrupt_request = env->interrupt_request;
320                 if (unlikely(interrupt_request)) {
321                     if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
322                         /* Mask out external interrupts for this step. */
323                         interrupt_request &= ~(CPU_INTERRUPT_HARD |
324                                                CPU_INTERRUPT_FIQ |
325                                                CPU_INTERRUPT_SMI |
326                                                CPU_INTERRUPT_NMI);
327                     }
328                     if (interrupt_request & CPU_INTERRUPT_DEBUG) {
329                         env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
330                         env->exception_index = EXCP_DEBUG;
331                         cpu_loop_exit();
332                     }
333 #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
334     defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
335     defined(TARGET_MICROBLAZE)
336                     if (interrupt_request & CPU_INTERRUPT_HALT) {
337                         env->interrupt_request &= ~CPU_INTERRUPT_HALT;
338                         env->halted = 1;
339                         env->exception_index = EXCP_HLT;
340                         cpu_loop_exit();
341                     }
342 #endif
343 #if defined(TARGET_I386)
344                     if (interrupt_request & CPU_INTERRUPT_INIT) {
345                             svm_check_intercept(SVM_EXIT_INIT);
346                             do_cpu_init(env);
347                             env->exception_index = EXCP_HALTED;
348                             cpu_loop_exit();
349                     } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
350                             do_cpu_sipi(env);
351                     } else if (env->hflags2 & HF2_GIF_MASK) {
352                         if ((interrupt_request & CPU_INTERRUPT_SMI) &&
353                             !(env->hflags & HF_SMM_MASK)) {
354                             svm_check_intercept(SVM_EXIT_SMI);
355                             env->interrupt_request &= ~CPU_INTERRUPT_SMI;
356                             do_smm_enter();
357                             next_tb = 0;
358                         } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
359                                    !(env->hflags2 & HF2_NMI_MASK)) {
360                             env->interrupt_request &= ~CPU_INTERRUPT_NMI;
361                             env->hflags2 |= HF2_NMI_MASK;
362                             do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
363                             next_tb = 0;
364                         } else if (interrupt_request & CPU_INTERRUPT_MCE) {
365                             env->interrupt_request &= ~CPU_INTERRUPT_MCE;
366                             do_interrupt(EXCP12_MCHK, 0, 0, 0, 0);
367                             next_tb = 0;
368                         } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
369                                    (((env->hflags2 & HF2_VINTR_MASK) && 
370                                      (env->hflags2 & HF2_HIF_MASK)) ||
371                                     (!(env->hflags2 & HF2_VINTR_MASK) && 
372                                      (env->eflags & IF_MASK && 
373                                       !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
374                             int intno;
375                             svm_check_intercept(SVM_EXIT_INTR);
376                             env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
377                             intno = cpu_get_pic_interrupt(env);
378                             qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
379 #if defined(__sparc__) && !defined(CONFIG_SOLARIS)
380 #undef env
381                     env = cpu_single_env;
382 #define env cpu_single_env
383 #endif
384                             do_interrupt(intno, 0, 0, 0, 1);
385                             /* ensure that no TB jump will be modified as
386                                the program flow was changed */
387                             next_tb = 0;
388 #if !defined(CONFIG_USER_ONLY)
389                         } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
390                                    (env->eflags & IF_MASK) && 
391                                    !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
392                             int intno;
393                             /* FIXME: this should respect TPR */
394                             svm_check_intercept(SVM_EXIT_VINTR);
395                             intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
396                             qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
397                             do_interrupt(intno, 0, 0, 0, 1);
398                             env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
399                             next_tb = 0;
400 #endif
401                         }
402                     }
403 #elif defined(TARGET_PPC)
404 #if 0
405                     if ((interrupt_request & CPU_INTERRUPT_RESET)) {
406                         cpu_reset(env);
407                     }
408 #endif
409                     if (interrupt_request & CPU_INTERRUPT_HARD) {
410                         ppc_hw_interrupt(env);
411                         if (env->pending_interrupts == 0)
412                             env->interrupt_request &= ~CPU_INTERRUPT_HARD;
413                         next_tb = 0;
414                     }
415 #elif defined(TARGET_MICROBLAZE)
416                     if ((interrupt_request & CPU_INTERRUPT_HARD)
417                         && (env->sregs[SR_MSR] & MSR_IE)
418                         && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
419                         && !(env->iflags & (D_FLAG | IMM_FLAG))) {
420                         env->exception_index = EXCP_IRQ;
421                         do_interrupt(env);
422                         next_tb = 0;
423                     }
424 #elif defined(TARGET_MIPS)
425                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&
426                         cpu_mips_hw_interrupts_pending(env)) {
427                         /* Raise it */
428                         env->exception_index = EXCP_EXT_INTERRUPT;
429                         env->error_code = 0;
430                         do_interrupt(env);
431                         next_tb = 0;
432                     }
433 #elif defined(TARGET_SPARC)
434                     if (interrupt_request & CPU_INTERRUPT_HARD) {
435                         if (cpu_interrupts_enabled(env) &&
436                             env->interrupt_index > 0) {
437                             int pil = env->interrupt_index & 0xf;
438                             int type = env->interrupt_index & 0xf0;
439
440                             if (((type == TT_EXTINT) &&
441                                   cpu_pil_allowed(env, pil)) ||
442                                   type != TT_EXTINT) {
443                                 env->exception_index = env->interrupt_index;
444                                 do_interrupt(env);
445                                 next_tb = 0;
446                             }
447                         }
448                     } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
449                         //do_interrupt(0, 0, 0, 0, 0);
450                         env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
451                     }
452 #elif defined(TARGET_ARM)
453                     if (interrupt_request & CPU_INTERRUPT_FIQ
454                         && !(env->uncached_cpsr & CPSR_F)) {
455                         env->exception_index = EXCP_FIQ;
456                         do_interrupt(env);
457                         next_tb = 0;
458                     }
459                     /* ARMv7-M interrupt return works by loading a magic value
460                        into the PC.  On real hardware the load causes the
461                        return to occur.  The qemu implementation performs the
462                        jump normally, then does the exception return when the
463                        CPU tries to execute code at the magic address.
464                        This will cause the magic PC value to be pushed to
465                        the stack if an interrupt occured at the wrong time.
466                        We avoid this by disabling interrupts when
467                        pc contains a magic address.  */
468                     if (interrupt_request & CPU_INTERRUPT_HARD
469                         && ((IS_M(env) && env->regs[15] < 0xfffffff0)
470                             || !(env->uncached_cpsr & CPSR_I))) {
471                         env->exception_index = EXCP_IRQ;
472                         do_interrupt(env);
473                         next_tb = 0;
474                     }
475 #elif defined(TARGET_SH4)
476                     if (interrupt_request & CPU_INTERRUPT_HARD) {
477                         do_interrupt(env);
478                         next_tb = 0;
479                     }
480 #elif defined(TARGET_ALPHA)
481                     if (interrupt_request & CPU_INTERRUPT_HARD) {
482                         do_interrupt(env);
483                         next_tb = 0;
484                     }
485 #elif defined(TARGET_CRIS)
486                     if (interrupt_request & CPU_INTERRUPT_HARD
487                         && (env->pregs[PR_CCS] & I_FLAG)
488                         && !env->locked_irq) {
489                         env->exception_index = EXCP_IRQ;
490                         do_interrupt(env);
491                         next_tb = 0;
492                     }
493                     if (interrupt_request & CPU_INTERRUPT_NMI
494                         && (env->pregs[PR_CCS] & M_FLAG)) {
495                         env->exception_index = EXCP_NMI;
496                         do_interrupt(env);
497                         next_tb = 0;
498                     }
499 #elif defined(TARGET_M68K)
500                     if (interrupt_request & CPU_INTERRUPT_HARD
501                         && ((env->sr & SR_I) >> SR_I_SHIFT)
502                             < env->pending_level) {
503                         /* Real hardware gets the interrupt vector via an
504                            IACK cycle at this point.  Current emulated
505                            hardware doesn't rely on this, so we
506                            provide/save the vector when the interrupt is
507                            first signalled.  */
508                         env->exception_index = env->pending_vector;
509                         do_interrupt(1);
510                         next_tb = 0;
511                     }
512 #endif
513                    /* Don't use the cached interupt_request value,
514                       do_interrupt may have updated the EXITTB flag. */
515                     if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
516                         env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
517                         /* ensure that no TB jump will be modified as
518                            the program flow was changed */
519                         next_tb = 0;
520                     }
521                 }
522                 if (unlikely(env->exit_request)) {
523                     env->exit_request = 0;
524                     env->exception_index = EXCP_INTERRUPT;
525                     cpu_loop_exit();
526                 }
527 #if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
528                 if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
529                     /* restore flags in standard format */
530 #if defined(TARGET_I386)
531                     env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
532                     log_cpu_state(env, X86_DUMP_CCOP);
533                     env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
534 #elif defined(TARGET_M68K)
535                     cpu_m68k_flush_flags(env, env->cc_op);
536                     env->cc_op = CC_OP_FLAGS;
537                     env->sr = (env->sr & 0xffe0)
538                               | env->cc_dest | (env->cc_x << 4);
539                     log_cpu_state(env, 0);
540 #else
541                     log_cpu_state(env, 0);
542 #endif
543                 }
544 #endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
545                 spin_lock(&tb_lock);
546                 tb = tb_find_fast();
547                 /* Note: we do it here to avoid a gcc bug on Mac OS X when
548                    doing it in tb_find_slow */
549                 if (tb_invalidated_flag) {
550                     /* as some TB could have been invalidated because
551                        of memory exceptions while generating the code, we
552                        must recompute the hash index here */
553                     next_tb = 0;
554                     tb_invalidated_flag = 0;
555                 }
556 #ifdef CONFIG_DEBUG_EXEC
557                 qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
558                              (long)tb->tc_ptr, tb->pc,
559                              lookup_symbol(tb->pc));
560 #endif
561                 /* see if we can patch the calling TB. When the TB
562                    spans two pages, we cannot safely do a direct
563                    jump. */
564                 if (next_tb != 0 && tb->page_addr[1] == -1) {
565                     tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
566                 }
567                 spin_unlock(&tb_lock);
568
569                 /* cpu_interrupt might be called while translating the
570                    TB, but before it is linked into a potentially
571                    infinite loop and becomes env->current_tb. Avoid
572                    starting execution if there is a pending interrupt. */
573                 env->current_tb = tb;
574                 barrier();
575                 if (likely(!env->exit_request)) {
576                     tc_ptr = tb->tc_ptr;
577                 /* execute the generated code */
578 #if defined(__sparc__) && !defined(CONFIG_SOLARIS)
579 #undef env
580                     env = cpu_single_env;
581 #define env cpu_single_env
582 #endif
583                     next_tb = tcg_qemu_tb_exec(tc_ptr);
584                     if ((next_tb & 3) == 2) {
585                         /* Instruction counter expired.  */
586                         int insns_left;
587                         tb = (TranslationBlock *)(long)(next_tb & ~3);
588                         /* Restore PC.  */
589                         cpu_pc_from_tb(env, tb);
590                         insns_left = env->icount_decr.u32;
591                         if (env->icount_extra && insns_left >= 0) {
592                             /* Refill decrementer and continue execution.  */
593                             env->icount_extra += insns_left;
594                             if (env->icount_extra > 0xffff) {
595                                 insns_left = 0xffff;
596                             } else {
597                                 insns_left = env->icount_extra;
598                             }
599                             env->icount_extra -= insns_left;
600                             env->icount_decr.u16.low = insns_left;
601                         } else {
602                             if (insns_left > 0) {
603                                 /* Execute remaining instructions.  */
604                                 cpu_exec_nocache(insns_left, tb);
605                             }
606                             env->exception_index = EXCP_INTERRUPT;
607                             next_tb = 0;
608                             cpu_loop_exit();
609                         }
610                     }
611                 }
612                 env->current_tb = NULL;
613                 /* reset soft MMU for next block (it can currently
614                    only be set by a memory fault) */
615             } /* for(;;) */
616         }
617     } /* for(;;) */
618
619
620 #if defined(TARGET_I386)
621     /* restore flags in standard format */
622     env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
623 #elif defined(TARGET_ARM)
624     /* XXX: Save/restore host fpu exception state?.  */
625 #elif defined(TARGET_SPARC)
626 #elif defined(TARGET_PPC)
627 #elif defined(TARGET_M68K)
628     cpu_m68k_flush_flags(env, env->cc_op);
629     env->cc_op = CC_OP_FLAGS;
630     env->sr = (env->sr & 0xffe0)
631               | env->cc_dest | (env->cc_x << 4);
632 #elif defined(TARGET_MICROBLAZE)
633 #elif defined(TARGET_MIPS)
634 #elif defined(TARGET_SH4)
635 #elif defined(TARGET_ALPHA)
636 #elif defined(TARGET_CRIS)
637 #elif defined(TARGET_S390X)
638     /* XXXXX */
639 #else
640 #error unsupported target CPU
641 #endif
642
643     /* restore global registers */
644     barrier();
645     env = (void *) saved_env_reg;
646
647     /* fail safe : never use cpu_single_env outside cpu_exec() */
648     cpu_single_env = NULL;
649     return ret;
650 }
651
652 /* must only be called from the generated code as an exception can be
653    generated */
654 void tb_invalidate_page_range(target_ulong start, target_ulong end)
655 {
656     /* XXX: cannot enable it yet because it yields to MMU exception
657        where NIP != read address on PowerPC */
658 #if 0
659     target_ulong phys_addr;
660     phys_addr = get_phys_addr_code(env, start);
661     tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
662 #endif
663 }
664
665 #if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
666
667 void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
668 {
669     CPUX86State *saved_env;
670
671     saved_env = env;
672     env = s;
673     if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
674         selector &= 0xffff;
675         cpu_x86_load_seg_cache(env, seg_reg, selector,
676                                (selector << 4), 0xffff, 0);
677     } else {
678         helper_load_seg(seg_reg, selector);
679     }
680     env = saved_env;
681 }
682
683 void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
684 {
685     CPUX86State *saved_env;
686
687     saved_env = env;
688     env = s;
689
690     helper_fsave(ptr, data32);
691
692     env = saved_env;
693 }
694
695 void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
696 {
697     CPUX86State *saved_env;
698
699     saved_env = env;
700     env = s;
701
702     helper_frstor(ptr, data32);
703
704     env = saved_env;
705 }
706
707 #endif /* TARGET_I386 */
708
709 #if !defined(CONFIG_SOFTMMU)
710
711 #if defined(TARGET_I386)
712 #define EXCEPTION_ACTION raise_exception_err(env->exception_index, env->error_code)
713 #else
714 #define EXCEPTION_ACTION cpu_loop_exit()
715 #endif
716
717 /* 'pc' is the host PC at which the exception was raised. 'address' is
718    the effective address of the memory exception. 'is_write' is 1 if a
719    write caused the exception and otherwise 0'. 'old_set' is the
720    signal set which should be restored */
721 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
722                                     int is_write, sigset_t *old_set,
723                                     void *puc)
724 {
725     TranslationBlock *tb;
726     int ret;
727
728     if (cpu_single_env)
729         env = cpu_single_env; /* XXX: find a correct solution for multithread */
730 #if defined(DEBUG_SIGNAL)
731     qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
732                 pc, address, is_write, *(unsigned long *)old_set);
733 #endif
734     /* XXX: locking issue */
735     if (is_write && page_unprotect(h2g(address), pc, puc)) {
736         return 1;
737     }
738
739     /* see if it is an MMU fault */
740     ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
741     if (ret < 0)
742         return 0; /* not an MMU fault */
743     if (ret == 0)
744         return 1; /* the MMU fault was handled without causing real CPU fault */
745     /* now we have a real cpu fault */
746     tb = tb_find_pc(pc);
747     if (tb) {
748         /* the PC is inside the translated code. It means that we have
749            a virtual CPU fault */
750         cpu_restore_state(tb, env, pc, puc);
751     }
752
753     /* we restore the process signal mask as the sigreturn should
754        do it (XXX: use sigsetjmp) */
755     sigprocmask(SIG_SETMASK, old_set, NULL);
756     EXCEPTION_ACTION;
757
758     /* never comes here */
759     return 1;
760 }
761
762 #if defined(__i386__)
763
764 #if defined(__APPLE__)
765 # include <sys/ucontext.h>
766
767 # define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
768 # define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
769 # define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
770 # define MASK_sig(context)    ((context)->uc_sigmask)
771 #elif defined (__NetBSD__)
772 # include <ucontext.h>
773
774 # define EIP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_EIP])
775 # define TRAP_sig(context)    ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
776 # define ERROR_sig(context)   ((context)->uc_mcontext.__gregs[_REG_ERR])
777 # define MASK_sig(context)    ((context)->uc_sigmask)
778 #elif defined (__FreeBSD__) || defined(__DragonFly__)
779 # include <ucontext.h>
780
781 # define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_eip))
782 # define TRAP_sig(context)    ((context)->uc_mcontext.mc_trapno)
783 # define ERROR_sig(context)   ((context)->uc_mcontext.mc_err)
784 # define MASK_sig(context)    ((context)->uc_sigmask)
785 #elif defined(__OpenBSD__)
786 # define EIP_sig(context)     ((context)->sc_eip)
787 # define TRAP_sig(context)    ((context)->sc_trapno)
788 # define ERROR_sig(context)   ((context)->sc_err)
789 # define MASK_sig(context)    ((context)->sc_mask)
790 #else
791 # define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
792 # define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
793 # define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
794 # define MASK_sig(context)    ((context)->uc_sigmask)
795 #endif
796
797 int cpu_signal_handler(int host_signum, void *pinfo,
798                        void *puc)
799 {
800     siginfo_t *info = pinfo;
801 #if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
802     ucontext_t *uc = puc;
803 #elif defined(__OpenBSD__)
804     struct sigcontext *uc = puc;
805 #else
806     struct ucontext *uc = puc;
807 #endif
808     unsigned long pc;
809     int trapno;
810
811 #ifndef REG_EIP
812 /* for glibc 2.1 */
813 #define REG_EIP    EIP
814 #define REG_ERR    ERR
815 #define REG_TRAPNO TRAPNO
816 #endif
817     pc = EIP_sig(uc);
818     trapno = TRAP_sig(uc);
819     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
820                              trapno == 0xe ?
821                              (ERROR_sig(uc) >> 1) & 1 : 0,
822                              &MASK_sig(uc), puc);
823 }
824
825 #elif defined(__x86_64__)
826
827 #ifdef __NetBSD__
828 #define PC_sig(context)       _UC_MACHINE_PC(context)
829 #define TRAP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
830 #define ERROR_sig(context)    ((context)->uc_mcontext.__gregs[_REG_ERR])
831 #define MASK_sig(context)     ((context)->uc_sigmask)
832 #elif defined(__OpenBSD__)
833 #define PC_sig(context)       ((context)->sc_rip)
834 #define TRAP_sig(context)     ((context)->sc_trapno)
835 #define ERROR_sig(context)    ((context)->sc_err)
836 #define MASK_sig(context)     ((context)->sc_mask)
837 #elif defined (__FreeBSD__) || defined(__DragonFly__)
838 #include <ucontext.h>
839
840 #define PC_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_rip))
841 #define TRAP_sig(context)     ((context)->uc_mcontext.mc_trapno)
842 #define ERROR_sig(context)    ((context)->uc_mcontext.mc_err)
843 #define MASK_sig(context)     ((context)->uc_sigmask)
844 #else
845 #define PC_sig(context)       ((context)->uc_mcontext.gregs[REG_RIP])
846 #define TRAP_sig(context)     ((context)->uc_mcontext.gregs[REG_TRAPNO])
847 #define ERROR_sig(context)    ((context)->uc_mcontext.gregs[REG_ERR])
848 #define MASK_sig(context)     ((context)->uc_sigmask)
849 #endif
850
851 int cpu_signal_handler(int host_signum, void *pinfo,
852                        void *puc)
853 {
854     siginfo_t *info = pinfo;
855     unsigned long pc;
856 #if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
857     ucontext_t *uc = puc;
858 #elif defined(__OpenBSD__)
859     struct sigcontext *uc = puc;
860 #else
861     struct ucontext *uc = puc;
862 #endif
863
864     pc = PC_sig(uc);
865     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
866                              TRAP_sig(uc) == 0xe ?
867                              (ERROR_sig(uc) >> 1) & 1 : 0,
868                              &MASK_sig(uc), puc);
869 }
870
871 #elif defined(_ARCH_PPC)
872
873 /***********************************************************************
874  * signal context platform-specific definitions
875  * From Wine
876  */
877 #ifdef linux
878 /* All Registers access - only for local access */
879 # define REG_sig(reg_name, context)             ((context)->uc_mcontext.regs->reg_name)
880 /* Gpr Registers access  */
881 # define GPR_sig(reg_num, context)              REG_sig(gpr[reg_num], context)
882 # define IAR_sig(context)                       REG_sig(nip, context)   /* Program counter */
883 # define MSR_sig(context)                       REG_sig(msr, context)   /* Machine State Register (Supervisor) */
884 # define CTR_sig(context)                       REG_sig(ctr, context)   /* Count register */
885 # define XER_sig(context)                       REG_sig(xer, context) /* User's integer exception register */
886 # define LR_sig(context)                        REG_sig(link, context) /* Link register */
887 # define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
888 /* Float Registers access  */
889 # define FLOAT_sig(reg_num, context)            (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
890 # define FPSCR_sig(context)                     (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
891 /* Exception Registers access */
892 # define DAR_sig(context)                       REG_sig(dar, context)
893 # define DSISR_sig(context)                     REG_sig(dsisr, context)
894 # define TRAP_sig(context)                      REG_sig(trap, context)
895 #endif /* linux */
896
897 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
898 #include <ucontext.h>
899 # define IAR_sig(context)               ((context)->uc_mcontext.mc_srr0)
900 # define MSR_sig(context)               ((context)->uc_mcontext.mc_srr1)
901 # define CTR_sig(context)               ((context)->uc_mcontext.mc_ctr)
902 # define XER_sig(context)               ((context)->uc_mcontext.mc_xer)
903 # define LR_sig(context)                ((context)->uc_mcontext.mc_lr)
904 # define CR_sig(context)                ((context)->uc_mcontext.mc_cr)
905 /* Exception Registers access */
906 # define DAR_sig(context)               ((context)->uc_mcontext.mc_dar)
907 # define DSISR_sig(context)             ((context)->uc_mcontext.mc_dsisr)
908 # define TRAP_sig(context)              ((context)->uc_mcontext.mc_exc)
909 #endif /* __FreeBSD__|| __FreeBSD_kernel__ */
910
911 #ifdef __APPLE__
912 # include <sys/ucontext.h>
913 typedef struct ucontext SIGCONTEXT;
914 /* All Registers access - only for local access */
915 # define REG_sig(reg_name, context)             ((context)->uc_mcontext->ss.reg_name)
916 # define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
917 # define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
918 # define VECREG_sig(reg_name, context)          ((context)->uc_mcontext->vs.reg_name)
919 /* Gpr Registers access */
920 # define GPR_sig(reg_num, context)              REG_sig(r##reg_num, context)
921 # define IAR_sig(context)                       REG_sig(srr0, context)  /* Program counter */
922 # define MSR_sig(context)                       REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
923 # define CTR_sig(context)                       REG_sig(ctr, context)
924 # define XER_sig(context)                       REG_sig(xer, context) /* Link register */
925 # define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
926 # define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
927 /* Float Registers access */
928 # define FLOAT_sig(reg_num, context)            FLOATREG_sig(fpregs[reg_num], context)
929 # define FPSCR_sig(context)                     ((double)FLOATREG_sig(fpscr, context))
930 /* Exception Registers access */
931 # define DAR_sig(context)                       EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
932 # define DSISR_sig(context)                     EXCEPREG_sig(dsisr, context)
933 # define TRAP_sig(context)                      EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
934 #endif /* __APPLE__ */
935
936 int cpu_signal_handler(int host_signum, void *pinfo,
937                        void *puc)
938 {
939     siginfo_t *info = pinfo;
940 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
941     ucontext_t *uc = puc;
942 #else
943     struct ucontext *uc = puc;
944 #endif
945     unsigned long pc;
946     int is_write;
947
948     pc = IAR_sig(uc);
949     is_write = 0;
950 #if 0
951     /* ppc 4xx case */
952     if (DSISR_sig(uc) & 0x00800000)
953         is_write = 1;
954 #else
955     if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
956         is_write = 1;
957 #endif
958     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
959                              is_write, &uc->uc_sigmask, puc);
960 }
961
962 #elif defined(__alpha__)
963
964 int cpu_signal_handler(int host_signum, void *pinfo,
965                            void *puc)
966 {
967     siginfo_t *info = pinfo;
968     struct ucontext *uc = puc;
969     uint32_t *pc = uc->uc_mcontext.sc_pc;
970     uint32_t insn = *pc;
971     int is_write = 0;
972
973     /* XXX: need kernel patch to get write flag faster */
974     switch (insn >> 26) {
975     case 0x0d: // stw
976     case 0x0e: // stb
977     case 0x0f: // stq_u
978     case 0x24: // stf
979     case 0x25: // stg
980     case 0x26: // sts
981     case 0x27: // stt
982     case 0x2c: // stl
983     case 0x2d: // stq
984     case 0x2e: // stl_c
985     case 0x2f: // stq_c
986         is_write = 1;
987     }
988
989     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
990                              is_write, &uc->uc_sigmask, puc);
991 }
992 #elif defined(__sparc__)
993
994 int cpu_signal_handler(int host_signum, void *pinfo,
995                        void *puc)
996 {
997     siginfo_t *info = pinfo;
998     int is_write;
999     uint32_t insn;
1000 #if !defined(__arch64__) || defined(CONFIG_SOLARIS)
1001     uint32_t *regs = (uint32_t *)(info + 1);
1002     void *sigmask = (regs + 20);
1003     /* XXX: is there a standard glibc define ? */
1004     unsigned long pc = regs[1];
1005 #else
1006 #ifdef __linux__
1007     struct sigcontext *sc = puc;
1008     unsigned long pc = sc->sigc_regs.tpc;
1009     void *sigmask = (void *)sc->sigc_mask;
1010 #elif defined(__OpenBSD__)
1011     struct sigcontext *uc = puc;
1012     unsigned long pc = uc->sc_pc;
1013     void *sigmask = (void *)(long)uc->sc_mask;
1014 #endif
1015 #endif
1016
1017     /* XXX: need kernel patch to get write flag faster */
1018     is_write = 0;
1019     insn = *(uint32_t *)pc;
1020     if ((insn >> 30) == 3) {
1021       switch((insn >> 19) & 0x3f) {
1022       case 0x05: // stb
1023       case 0x15: // stba
1024       case 0x06: // sth
1025       case 0x16: // stha
1026       case 0x04: // st
1027       case 0x14: // sta
1028       case 0x07: // std
1029       case 0x17: // stda
1030       case 0x0e: // stx
1031       case 0x1e: // stxa
1032       case 0x24: // stf
1033       case 0x34: // stfa
1034       case 0x27: // stdf
1035       case 0x37: // stdfa
1036       case 0x26: // stqf
1037       case 0x36: // stqfa
1038       case 0x25: // stfsr
1039       case 0x3c: // casa
1040       case 0x3e: // casxa
1041         is_write = 1;
1042         break;
1043       }
1044     }
1045     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1046                              is_write, sigmask, NULL);
1047 }
1048
1049 #elif defined(__arm__)
1050
1051 int cpu_signal_handler(int host_signum, void *pinfo,
1052                        void *puc)
1053 {
1054     siginfo_t *info = pinfo;
1055     struct ucontext *uc = puc;
1056     unsigned long pc;
1057     int is_write;
1058
1059 #if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
1060     pc = uc->uc_mcontext.gregs[R15];
1061 #else
1062     pc = uc->uc_mcontext.arm_pc;
1063 #endif
1064     /* XXX: compute is_write */
1065     is_write = 0;
1066     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1067                              is_write,
1068                              &uc->uc_sigmask, puc);
1069 }
1070
1071 #elif defined(__mc68000)
1072
1073 int cpu_signal_handler(int host_signum, void *pinfo,
1074                        void *puc)
1075 {
1076     siginfo_t *info = pinfo;
1077     struct ucontext *uc = puc;
1078     unsigned long pc;
1079     int is_write;
1080
1081     pc = uc->uc_mcontext.gregs[16];
1082     /* XXX: compute is_write */
1083     is_write = 0;
1084     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1085                              is_write,
1086                              &uc->uc_sigmask, puc);
1087 }
1088
1089 #elif defined(__ia64)
1090
1091 #ifndef __ISR_VALID
1092   /* This ought to be in <bits/siginfo.h>... */
1093 # define __ISR_VALID    1
1094 #endif
1095
1096 int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1097 {
1098     siginfo_t *info = pinfo;
1099     struct ucontext *uc = puc;
1100     unsigned long ip;
1101     int is_write = 0;
1102
1103     ip = uc->uc_mcontext.sc_ip;
1104     switch (host_signum) {
1105       case SIGILL:
1106       case SIGFPE:
1107       case SIGSEGV:
1108       case SIGBUS:
1109       case SIGTRAP:
1110           if (info->si_code && (info->si_segvflags & __ISR_VALID))
1111               /* ISR.W (write-access) is bit 33:  */
1112               is_write = (info->si_isr >> 33) & 1;
1113           break;
1114
1115       default:
1116           break;
1117     }
1118     return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1119                              is_write,
1120                              (sigset_t *)&uc->uc_sigmask, puc);
1121 }
1122
1123 #elif defined(__s390__)
1124
1125 int cpu_signal_handler(int host_signum, void *pinfo,
1126                        void *puc)
1127 {
1128     siginfo_t *info = pinfo;
1129     struct ucontext *uc = puc;
1130     unsigned long pc;
1131     uint16_t *pinsn;
1132     int is_write = 0;
1133
1134     pc = uc->uc_mcontext.psw.addr;
1135
1136     /* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
1137        of the normal 2 arguments.  The 3rd argument contains the "int_code"
1138        from the hardware which does in fact contain the is_write value.
1139        The rt signal handler, as far as I can tell, does not give this value
1140        at all.  Not that we could get to it from here even if it were.  */
1141     /* ??? This is not even close to complete, since it ignores all
1142        of the read-modify-write instructions.  */
1143     pinsn = (uint16_t *)pc;
1144     switch (pinsn[0] >> 8) {
1145     case 0x50: /* ST */
1146     case 0x42: /* STC */
1147     case 0x40: /* STH */
1148         is_write = 1;
1149         break;
1150     case 0xc4: /* RIL format insns */
1151         switch (pinsn[0] & 0xf) {
1152         case 0xf: /* STRL */
1153         case 0xb: /* STGRL */
1154         case 0x7: /* STHRL */
1155             is_write = 1;
1156         }
1157         break;
1158     case 0xe3: /* RXY format insns */
1159         switch (pinsn[2] & 0xff) {
1160         case 0x50: /* STY */
1161         case 0x24: /* STG */
1162         case 0x72: /* STCY */
1163         case 0x70: /* STHY */
1164         case 0x8e: /* STPQ */
1165         case 0x3f: /* STRVH */
1166         case 0x3e: /* STRV */
1167         case 0x2f: /* STRVG */
1168             is_write = 1;
1169         }
1170         break;
1171     }
1172     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1173                              is_write, &uc->uc_sigmask, puc);
1174 }
1175
1176 #elif defined(__mips__)
1177
1178 int cpu_signal_handler(int host_signum, void *pinfo,
1179                        void *puc)
1180 {
1181     siginfo_t *info = pinfo;
1182     struct ucontext *uc = puc;
1183     greg_t pc = uc->uc_mcontext.pc;
1184     int is_write;
1185
1186     /* XXX: compute is_write */
1187     is_write = 0;
1188     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1189                              is_write, &uc->uc_sigmask, puc);
1190 }
1191
1192 #elif defined(__hppa__)
1193
1194 int cpu_signal_handler(int host_signum, void *pinfo,
1195                        void *puc)
1196 {
1197     struct siginfo *info = pinfo;
1198     struct ucontext *uc = puc;
1199     unsigned long pc = uc->uc_mcontext.sc_iaoq[0];
1200     uint32_t insn = *(uint32_t *)pc;
1201     int is_write = 0;
1202
1203     /* XXX: need kernel patch to get write flag faster.  */
1204     switch (insn >> 26) {
1205     case 0x1a: /* STW */
1206     case 0x19: /* STH */
1207     case 0x18: /* STB */
1208     case 0x1b: /* STWM */
1209         is_write = 1;
1210         break;
1211
1212     case 0x09: /* CSTWX, FSTWX, FSTWS */
1213     case 0x0b: /* CSTDX, FSTDX, FSTDS */
1214         /* Distinguish from coprocessor load ... */
1215         is_write = (insn >> 9) & 1;
1216         break;
1217
1218     case 0x03:
1219         switch ((insn >> 6) & 15) {
1220         case 0xa: /* STWS */
1221         case 0x9: /* STHS */
1222         case 0x8: /* STBS */
1223         case 0xe: /* STWAS */
1224         case 0xc: /* STBYS */
1225             is_write = 1;
1226         }
1227         break;
1228     }
1229
1230     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1231                              is_write, &uc->uc_sigmask, puc);
1232 }
1233
1234 #else
1235
1236 #error host CPU specific signal handler needed
1237
1238 #endif
1239
1240 #endif /* !defined(CONFIG_SOFTMMU) */