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