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