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