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