Convert remaining __builtin_expect to likely/unlikely, by Jan Kiszka.
[qemu] / 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, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include "config.h"
21 #define CPU_NO_GLOBAL_REGS
22 #include "exec.h"
23 #include "disas.h"
24 #include "tcg.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 #include <sys/ucontext.h>
38 #endif
39
40 #if defined(__sparc__) && !defined(HOST_SOLARIS)
41 // Work around ugly bugs in glibc that mangle global register contents
42 #undef env
43 #define env cpu_single_env
44 #endif
45
46 int tb_invalidated_flag;
47
48 //#define DEBUG_EXEC
49 //#define DEBUG_SIGNAL
50
51 void cpu_loop_exit(void)
52 {
53     /* NOTE: the register at this point must be saved by hand because
54        longjmp restore them */
55     regs_to_env();
56     longjmp(env->jmp_env, 1);
57 }
58
59 #if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K))
60 #define reg_T2
61 #endif
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     struct ucontext *uc = puc;
70 #endif
71
72     env = env1;
73
74     /* XXX: restore cpu registers saved in host registers */
75
76 #if !defined(CONFIG_SOFTMMU)
77     if (puc) {
78         /* XXX: use siglongjmp ? */
79         sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
80     }
81 #endif
82     longjmp(env->jmp_env, 1);
83 }
84
85 /* Execute the code without caching the generated code. An interpreter
86    could be used if available. */
87 static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
88 {
89     unsigned long next_tb;
90     TranslationBlock *tb;
91
92     /* Should never happen.
93        We only end up here when an existing TB is too long.  */
94     if (max_cycles > CF_COUNT_MASK)
95         max_cycles = CF_COUNT_MASK;
96
97     tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
98                      max_cycles);
99     env->current_tb = tb;
100     /* execute the generated code */
101     next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
102
103     if ((next_tb & 3) == 2) {
104         /* Restore PC.  This may happen if async event occurs before
105            the TB starts executing.  */
106         CPU_PC_FROM_TB(env, tb);
107     }
108     tb_phys_invalidate(tb, -1);
109     tb_free(tb);
110 }
111
112 static TranslationBlock *tb_find_slow(target_ulong pc,
113                                       target_ulong cs_base,
114                                       uint64_t flags)
115 {
116     TranslationBlock *tb, **ptb1;
117     unsigned int h;
118     target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
119
120     tb_invalidated_flag = 0;
121
122     regs_to_env(); /* XXX: do it just before cpu_gen_code() */
123
124     /* find translated block using physical mappings */
125     phys_pc = get_phys_addr_code(env, pc);
126     phys_page1 = phys_pc & TARGET_PAGE_MASK;
127     phys_page2 = -1;
128     h = tb_phys_hash_func(phys_pc);
129     ptb1 = &tb_phys_hash[h];
130     for(;;) {
131         tb = *ptb1;
132         if (!tb)
133             goto not_found;
134         if (tb->pc == pc &&
135             tb->page_addr[0] == phys_page1 &&
136             tb->cs_base == cs_base &&
137             tb->flags == flags) {
138             /* check next page if needed */
139             if (tb->page_addr[1] != -1) {
140                 virt_page2 = (pc & TARGET_PAGE_MASK) +
141                     TARGET_PAGE_SIZE;
142                 phys_page2 = get_phys_addr_code(env, virt_page2);
143                 if (tb->page_addr[1] == phys_page2)
144                     goto found;
145             } else {
146                 goto found;
147             }
148         }
149         ptb1 = &tb->phys_hash_next;
150     }
151  not_found:
152    /* if no translated code available, then translate it now */
153     tb = tb_gen_code(env, pc, cs_base, flags, 0);
154
155  found:
156     /* we add the TB in the virtual pc hash table */
157     env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
158     return tb;
159 }
160
161 static inline TranslationBlock *tb_find_fast(void)
162 {
163     TranslationBlock *tb;
164     target_ulong cs_base, pc;
165     uint64_t flags;
166
167     /* we record a subset of the CPU state. It will
168        always be the same before a given translated block
169        is executed. */
170 #if defined(TARGET_I386)
171     flags = env->hflags;
172     flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
173     cs_base = env->segs[R_CS].base;
174     pc = cs_base + env->eip;
175 #elif defined(TARGET_ARM)
176     flags = env->thumb | (env->vfp.vec_len << 1)
177             | (env->vfp.vec_stride << 4);
178     if ((env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR)
179         flags |= (1 << 6);
180     if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
181         flags |= (1 << 7);
182     flags |= (env->condexec_bits << 8);
183     cs_base = 0;
184     pc = env->regs[15];
185 #elif defined(TARGET_SPARC)
186 #ifdef TARGET_SPARC64
187     // Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
188     flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
189         | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
190 #else
191     // FPU enable . Supervisor
192     flags = (env->psref << 4) | env->psrs;
193 #endif
194     cs_base = env->npc;
195     pc = env->pc;
196 #elif defined(TARGET_PPC)
197     flags = env->hflags;
198     cs_base = 0;
199     pc = env->nip;
200 #elif defined(TARGET_MIPS)
201     flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
202     cs_base = 0;
203     pc = env->active_tc.PC;
204 #elif defined(TARGET_M68K)
205     flags = (env->fpcr & M68K_FPCR_PREC)  /* Bit  6 */
206             | (env->sr & SR_S)            /* Bit  13 */
207             | ((env->macsr >> 4) & 0xf);  /* Bits 0-3 */
208     cs_base = 0;
209     pc = env->pc;
210 #elif defined(TARGET_SH4)
211     flags = env->flags;
212     cs_base = 0;
213     pc = env->pc;
214 #elif defined(TARGET_ALPHA)
215     flags = env->ps;
216     cs_base = 0;
217     pc = env->pc;
218 #elif defined(TARGET_CRIS)
219     flags = env->pregs[PR_CCS] & (P_FLAG | U_FLAG | X_FLAG);
220     flags |= env->dslot;
221     cs_base = 0;
222     pc = env->pc;
223 #else
224 #error unsupported CPU
225 #endif
226     tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
227     if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
228                  tb->flags != flags)) {
229         tb = tb_find_slow(pc, cs_base, flags);
230     }
231     return tb;
232 }
233
234 /* main execution loop */
235
236 int cpu_exec(CPUState *env1)
237 {
238 #define DECLARE_HOST_REGS 1
239 #include "hostregs_helper.h"
240     int ret, interrupt_request;
241     TranslationBlock *tb;
242     uint8_t *tc_ptr;
243     unsigned long next_tb;
244
245     if (cpu_halted(env1) == EXCP_HALTED)
246         return EXCP_HALTED;
247
248     cpu_single_env = env1;
249
250     /* first we save global registers */
251 #define SAVE_HOST_REGS 1
252 #include "hostregs_helper.h"
253     env = env1;
254
255     env_to_regs();
256 #if defined(TARGET_I386)
257     /* put eflags in CPU temporary format */
258     CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
259     DF = 1 - (2 * ((env->eflags >> 10) & 1));
260     CC_OP = CC_OP_EFLAGS;
261     env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
262 #elif defined(TARGET_SPARC)
263 #elif defined(TARGET_M68K)
264     env->cc_op = CC_OP_FLAGS;
265     env->cc_dest = env->sr & 0xf;
266     env->cc_x = (env->sr >> 4) & 1;
267 #elif defined(TARGET_ALPHA)
268 #elif defined(TARGET_ARM)
269 #elif defined(TARGET_PPC)
270 #elif defined(TARGET_MIPS)
271 #elif defined(TARGET_SH4)
272 #elif defined(TARGET_CRIS)
273     /* XXXXX */
274 #else
275 #error unsupported target CPU
276 #endif
277     env->exception_index = -1;
278
279     /* prepare setjmp context for exception handling */
280     for(;;) {
281         if (setjmp(env->jmp_env) == 0) {
282             env->current_tb = NULL;
283             /* if an exception is pending, we execute it here */
284             if (env->exception_index >= 0) {
285                 if (env->exception_index >= EXCP_INTERRUPT) {
286                     /* exit request from the cpu execution loop */
287                     ret = env->exception_index;
288                     break;
289                 } else if (env->user_mode_only) {
290                     /* if user mode only, we simulate a fake exception
291                        which will be handled outside the cpu execution
292                        loop */
293 #if defined(TARGET_I386)
294                     do_interrupt_user(env->exception_index,
295                                       env->exception_is_int,
296                                       env->error_code,
297                                       env->exception_next_eip);
298                     /* successfully delivered */
299                     env->old_exception = -1;
300 #endif
301                     ret = env->exception_index;
302                     break;
303                 } else {
304 #if defined(TARGET_I386)
305                     /* simulate a real cpu exception. On i386, it can
306                        trigger new exceptions, but we do not handle
307                        double or triple faults yet. */
308                     do_interrupt(env->exception_index,
309                                  env->exception_is_int,
310                                  env->error_code,
311                                  env->exception_next_eip, 0);
312                     /* successfully delivered */
313                     env->old_exception = -1;
314 #elif defined(TARGET_PPC)
315                     do_interrupt(env);
316 #elif defined(TARGET_MIPS)
317                     do_interrupt(env);
318 #elif defined(TARGET_SPARC)
319                     do_interrupt(env);
320 #elif defined(TARGET_ARM)
321                     do_interrupt(env);
322 #elif defined(TARGET_SH4)
323                     do_interrupt(env);
324 #elif defined(TARGET_ALPHA)
325                     do_interrupt(env);
326 #elif defined(TARGET_CRIS)
327                     do_interrupt(env);
328 #elif defined(TARGET_M68K)
329                     do_interrupt(0);
330 #endif
331                 }
332                 env->exception_index = -1;
333             }
334 #ifdef USE_KQEMU
335             if (kqemu_is_ok(env) && env->interrupt_request == 0) {
336                 int ret;
337                 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
338                 ret = kqemu_cpu_exec(env);
339                 /* put eflags in CPU temporary format */
340                 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
341                 DF = 1 - (2 * ((env->eflags >> 10) & 1));
342                 CC_OP = CC_OP_EFLAGS;
343                 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
344                 if (ret == 1) {
345                     /* exception */
346                     longjmp(env->jmp_env, 1);
347                 } else if (ret == 2) {
348                     /* softmmu execution needed */
349                 } else {
350                     if (env->interrupt_request != 0) {
351                         /* hardware interrupt will be executed just after */
352                     } else {
353                         /* otherwise, we restart */
354                         longjmp(env->jmp_env, 1);
355                     }
356                 }
357             }
358 #endif
359
360             next_tb = 0; /* force lookup of first TB */
361             for(;;) {
362                 interrupt_request = env->interrupt_request;
363                 if (unlikely(interrupt_request) &&
364                     likely(!(env->singlestep_enabled & SSTEP_NOIRQ))) {
365                     if (interrupt_request & CPU_INTERRUPT_DEBUG) {
366                         env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
367                         env->exception_index = EXCP_DEBUG;
368                         cpu_loop_exit();
369                     }
370 #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
371     defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS)
372                     if (interrupt_request & CPU_INTERRUPT_HALT) {
373                         env->interrupt_request &= ~CPU_INTERRUPT_HALT;
374                         env->halted = 1;
375                         env->exception_index = EXCP_HLT;
376                         cpu_loop_exit();
377                     }
378 #endif
379 #if defined(TARGET_I386)
380                     if (env->hflags2 & HF2_GIF_MASK) {
381                         if ((interrupt_request & CPU_INTERRUPT_SMI) &&
382                             !(env->hflags & HF_SMM_MASK)) {
383                             svm_check_intercept(SVM_EXIT_SMI);
384                             env->interrupt_request &= ~CPU_INTERRUPT_SMI;
385                             do_smm_enter();
386                             next_tb = 0;
387                         } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
388                                    !(env->hflags2 & HF2_NMI_MASK)) {
389                             env->interrupt_request &= ~CPU_INTERRUPT_NMI;
390                             env->hflags2 |= HF2_NMI_MASK;
391                             do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
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                             if (loglevel & CPU_LOG_TB_IN_ASM) {
404                                 fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
405                             }
406                             do_interrupt(intno, 0, 0, 0, 1);
407                             /* ensure that no TB jump will be modified as
408                                the program flow was changed */
409                             next_tb = 0;
410 #if !defined(CONFIG_USER_ONLY)
411                         } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
412                                    (env->eflags & IF_MASK) && 
413                                    !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
414                             int intno;
415                             /* FIXME: this should respect TPR */
416                             svm_check_intercept(SVM_EXIT_VINTR);
417                             env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
418                             intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
419                             if (loglevel & CPU_LOG_TB_IN_ASM)
420                                 fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
421                             do_interrupt(intno, 0, 0, 0, 1);
422                             next_tb = 0;
423 #endif
424                         }
425                     }
426 #elif defined(TARGET_PPC)
427 #if 0
428                     if ((interrupt_request & CPU_INTERRUPT_RESET)) {
429                         cpu_ppc_reset(env);
430                     }
431 #endif
432                     if (interrupt_request & CPU_INTERRUPT_HARD) {
433                         ppc_hw_interrupt(env);
434                         if (env->pending_interrupts == 0)
435                             env->interrupt_request &= ~CPU_INTERRUPT_HARD;
436                         next_tb = 0;
437                     }
438 #elif defined(TARGET_MIPS)
439                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&
440                         (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
441                         (env->CP0_Status & (1 << CP0St_IE)) &&
442                         !(env->CP0_Status & (1 << CP0St_EXL)) &&
443                         !(env->CP0_Status & (1 << CP0St_ERL)) &&
444                         !(env->hflags & MIPS_HFLAG_DM)) {
445                         /* Raise it */
446                         env->exception_index = EXCP_EXT_INTERRUPT;
447                         env->error_code = 0;
448                         do_interrupt(env);
449                         next_tb = 0;
450                     }
451 #elif defined(TARGET_SPARC)
452                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&
453                         (env->psret != 0)) {
454                         int pil = env->interrupt_index & 15;
455                         int type = env->interrupt_index & 0xf0;
456
457                         if (((type == TT_EXTINT) &&
458                              (pil == 15 || pil > env->psrpil)) ||
459                             type != TT_EXTINT) {
460                             env->interrupt_request &= ~CPU_INTERRUPT_HARD;
461                             env->exception_index = env->interrupt_index;
462                             do_interrupt(env);
463                             env->interrupt_index = 0;
464 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
465                             cpu_check_irqs(env);
466 #endif
467                         next_tb = 0;
468                         }
469                     } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
470                         //do_interrupt(0, 0, 0, 0, 0);
471                         env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
472                     }
473 #elif defined(TARGET_ARM)
474                     if (interrupt_request & CPU_INTERRUPT_FIQ
475                         && !(env->uncached_cpsr & CPSR_F)) {
476                         env->exception_index = EXCP_FIQ;
477                         do_interrupt(env);
478                         next_tb = 0;
479                     }
480                     /* ARMv7-M interrupt return works by loading a magic value
481                        into the PC.  On real hardware the load causes the
482                        return to occur.  The qemu implementation performs the
483                        jump normally, then does the exception return when the
484                        CPU tries to execute code at the magic address.
485                        This will cause the magic PC value to be pushed to
486                        the stack if an interrupt occured at the wrong time.
487                        We avoid this by disabling interrupts when
488                        pc contains a magic address.  */
489                     if (interrupt_request & CPU_INTERRUPT_HARD
490                         && ((IS_M(env) && env->regs[15] < 0xfffffff0)
491                             || !(env->uncached_cpsr & CPSR_I))) {
492                         env->exception_index = EXCP_IRQ;
493                         do_interrupt(env);
494                         next_tb = 0;
495                     }
496 #elif defined(TARGET_SH4)
497                     if (interrupt_request & CPU_INTERRUPT_HARD) {
498                         do_interrupt(env);
499                         next_tb = 0;
500                     }
501 #elif defined(TARGET_ALPHA)
502                     if (interrupt_request & CPU_INTERRUPT_HARD) {
503                         do_interrupt(env);
504                         next_tb = 0;
505                     }
506 #elif defined(TARGET_CRIS)
507                     if (interrupt_request & CPU_INTERRUPT_HARD
508                         && (env->pregs[PR_CCS] & I_FLAG)) {
509                         env->exception_index = EXCP_IRQ;
510                         do_interrupt(env);
511                         next_tb = 0;
512                     }
513                     if (interrupt_request & CPU_INTERRUPT_NMI
514                         && (env->pregs[PR_CCS] & M_FLAG)) {
515                         env->exception_index = EXCP_NMI;
516                         do_interrupt(env);
517                         next_tb = 0;
518                     }
519 #elif defined(TARGET_M68K)
520                     if (interrupt_request & CPU_INTERRUPT_HARD
521                         && ((env->sr & SR_I) >> SR_I_SHIFT)
522                             < env->pending_level) {
523                         /* Real hardware gets the interrupt vector via an
524                            IACK cycle at this point.  Current emulated
525                            hardware doesn't rely on this, so we
526                            provide/save the vector when the interrupt is
527                            first signalled.  */
528                         env->exception_index = env->pending_vector;
529                         do_interrupt(1);
530                         next_tb = 0;
531                     }
532 #endif
533                    /* Don't use the cached interupt_request value,
534                       do_interrupt may have updated the EXITTB flag. */
535                     if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
536                         env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
537                         /* ensure that no TB jump will be modified as
538                            the program flow was changed */
539                         next_tb = 0;
540                     }
541                     if (interrupt_request & CPU_INTERRUPT_EXIT) {
542                         env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
543                         env->exception_index = EXCP_INTERRUPT;
544                         cpu_loop_exit();
545                     }
546                 }
547 #ifdef DEBUG_EXEC
548                 if ((loglevel & CPU_LOG_TB_CPU)) {
549                     /* restore flags in standard format */
550                     regs_to_env();
551 #if defined(TARGET_I386)
552                     env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
553                     cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
554                     env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
555 #elif defined(TARGET_ARM)
556                     cpu_dump_state(env, logfile, fprintf, 0);
557 #elif defined(TARGET_SPARC)
558                     cpu_dump_state(env, logfile, fprintf, 0);
559 #elif defined(TARGET_PPC)
560                     cpu_dump_state(env, logfile, fprintf, 0);
561 #elif defined(TARGET_M68K)
562                     cpu_m68k_flush_flags(env, env->cc_op);
563                     env->cc_op = CC_OP_FLAGS;
564                     env->sr = (env->sr & 0xffe0)
565                               | env->cc_dest | (env->cc_x << 4);
566                     cpu_dump_state(env, logfile, fprintf, 0);
567 #elif defined(TARGET_MIPS)
568                     cpu_dump_state(env, logfile, fprintf, 0);
569 #elif defined(TARGET_SH4)
570                     cpu_dump_state(env, logfile, fprintf, 0);
571 #elif defined(TARGET_ALPHA)
572                     cpu_dump_state(env, logfile, fprintf, 0);
573 #elif defined(TARGET_CRIS)
574                     cpu_dump_state(env, logfile, fprintf, 0);
575 #else
576 #error unsupported target CPU
577 #endif
578                 }
579 #endif
580                 spin_lock(&tb_lock);
581                 tb = tb_find_fast();
582                 /* Note: we do it here to avoid a gcc bug on Mac OS X when
583                    doing it in tb_find_slow */
584                 if (tb_invalidated_flag) {
585                     /* as some TB could have been invalidated because
586                        of memory exceptions while generating the code, we
587                        must recompute the hash index here */
588                     next_tb = 0;
589                     tb_invalidated_flag = 0;
590                 }
591 #ifdef DEBUG_EXEC
592                 if ((loglevel & CPU_LOG_EXEC)) {
593                     fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
594                             (long)tb->tc_ptr, tb->pc,
595                             lookup_symbol(tb->pc));
596                 }
597 #endif
598                 /* see if we can patch the calling TB. When the TB
599                    spans two pages, we cannot safely do a direct
600                    jump. */
601                 {
602                     if (next_tb != 0 &&
603 #ifdef USE_KQEMU
604                         (env->kqemu_enabled != 2) &&
605 #endif
606                         tb->page_addr[1] == -1) {
607                     tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
608                 }
609                 }
610                 spin_unlock(&tb_lock);
611                 env->current_tb = tb;
612                 while (env->current_tb) {
613                     tc_ptr = tb->tc_ptr;
614                 /* execute the generated code */
615 #if defined(__sparc__) && !defined(HOST_SOLARIS)
616 #undef env
617                     env = cpu_single_env;
618 #define env cpu_single_env
619 #endif
620                     next_tb = tcg_qemu_tb_exec(tc_ptr);
621                     env->current_tb = NULL;
622                     if ((next_tb & 3) == 2) {
623                         /* Instruction counter expired.  */
624                         int insns_left;
625                         tb = (TranslationBlock *)(long)(next_tb & ~3);
626                         /* Restore PC.  */
627                         CPU_PC_FROM_TB(env, tb);
628                         insns_left = env->icount_decr.u32;
629                         if (env->icount_extra && insns_left >= 0) {
630                             /* Refill decrementer and continue execution.  */
631                             env->icount_extra += insns_left;
632                             if (env->icount_extra > 0xffff) {
633                                 insns_left = 0xffff;
634                             } else {
635                                 insns_left = env->icount_extra;
636                             }
637                             env->icount_extra -= insns_left;
638                             env->icount_decr.u16.low = insns_left;
639                         } else {
640                             if (insns_left > 0) {
641                                 /* Execute remaining instructions.  */
642                                 cpu_exec_nocache(insns_left, tb);
643                             }
644                             env->exception_index = EXCP_INTERRUPT;
645                             next_tb = 0;
646                             cpu_loop_exit();
647                         }
648                     }
649                 }
650                 /* reset soft MMU for next block (it can currently
651                    only be set by a memory fault) */
652 #if defined(USE_KQEMU)
653 #define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
654                 if (kqemu_is_ok(env) &&
655                     (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
656                     cpu_loop_exit();
657                 }
658 #endif
659             } /* for(;;) */
660         } else {
661             env_to_regs();
662         }
663     } /* for(;;) */
664
665
666 #if defined(TARGET_I386)
667     /* restore flags in standard format */
668     env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
669 #elif defined(TARGET_ARM)
670     /* XXX: Save/restore host fpu exception state?.  */
671 #elif defined(TARGET_SPARC)
672 #elif defined(TARGET_PPC)
673 #elif defined(TARGET_M68K)
674     cpu_m68k_flush_flags(env, env->cc_op);
675     env->cc_op = CC_OP_FLAGS;
676     env->sr = (env->sr & 0xffe0)
677               | env->cc_dest | (env->cc_x << 4);
678 #elif defined(TARGET_MIPS)
679 #elif defined(TARGET_SH4)
680 #elif defined(TARGET_ALPHA)
681 #elif defined(TARGET_CRIS)
682     /* XXXXX */
683 #else
684 #error unsupported target CPU
685 #endif
686
687     /* restore global registers */
688 #include "hostregs_helper.h"
689
690     /* fail safe : never use cpu_single_env outside cpu_exec() */
691     cpu_single_env = NULL;
692     return ret;
693 }
694
695 /* must only be called from the generated code as an exception can be
696    generated */
697 void tb_invalidate_page_range(target_ulong start, target_ulong end)
698 {
699     /* XXX: cannot enable it yet because it yields to MMU exception
700        where NIP != read address on PowerPC */
701 #if 0
702     target_ulong phys_addr;
703     phys_addr = get_phys_addr_code(env, start);
704     tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
705 #endif
706 }
707
708 #if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
709
710 void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
711 {
712     CPUX86State *saved_env;
713
714     saved_env = env;
715     env = s;
716     if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
717         selector &= 0xffff;
718         cpu_x86_load_seg_cache(env, seg_reg, selector,
719                                (selector << 4), 0xffff, 0);
720     } else {
721         helper_load_seg(seg_reg, selector);
722     }
723     env = saved_env;
724 }
725
726 void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
727 {
728     CPUX86State *saved_env;
729
730     saved_env = env;
731     env = s;
732
733     helper_fsave(ptr, data32);
734
735     env = saved_env;
736 }
737
738 void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
739 {
740     CPUX86State *saved_env;
741
742     saved_env = env;
743     env = s;
744
745     helper_frstor(ptr, data32);
746
747     env = saved_env;
748 }
749
750 #endif /* TARGET_I386 */
751
752 #if !defined(CONFIG_SOFTMMU)
753
754 #if defined(TARGET_I386)
755
756 /* 'pc' is the host PC at which the exception was raised. 'address' is
757    the effective address of the memory exception. 'is_write' is 1 if a
758    write caused the exception and otherwise 0'. 'old_set' is the
759    signal set which should be restored */
760 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
761                                     int is_write, sigset_t *old_set,
762                                     void *puc)
763 {
764     TranslationBlock *tb;
765     int ret;
766
767     if (cpu_single_env)
768         env = cpu_single_env; /* XXX: find a correct solution for multithread */
769 #if defined(DEBUG_SIGNAL)
770     qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
771                 pc, address, is_write, *(unsigned long *)old_set);
772 #endif
773     /* XXX: locking issue */
774     if (is_write && page_unprotect(h2g(address), pc, puc)) {
775         return 1;
776     }
777
778     /* see if it is an MMU fault */
779     ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
780     if (ret < 0)
781         return 0; /* not an MMU fault */
782     if (ret == 0)
783         return 1; /* the MMU fault was handled without causing real CPU fault */
784     /* now we have a real cpu fault */
785     tb = tb_find_pc(pc);
786     if (tb) {
787         /* the PC is inside the translated code. It means that we have
788            a virtual CPU fault */
789         cpu_restore_state(tb, env, pc, puc);
790     }
791     if (ret == 1) {
792 #if 0
793         printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
794                env->eip, env->cr[2], env->error_code);
795 #endif
796         /* we restore the process signal mask as the sigreturn should
797            do it (XXX: use sigsetjmp) */
798         sigprocmask(SIG_SETMASK, old_set, NULL);
799         raise_exception_err(env->exception_index, env->error_code);
800     } else {
801         /* activate soft MMU for this block */
802         env->hflags |= HF_SOFTMMU_MASK;
803         cpu_resume_from_signal(env, puc);
804     }
805     /* never comes here */
806     return 1;
807 }
808
809 #elif defined(TARGET_ARM)
810 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
811                                     int is_write, sigset_t *old_set,
812                                     void *puc)
813 {
814     TranslationBlock *tb;
815     int ret;
816
817     if (cpu_single_env)
818         env = cpu_single_env; /* XXX: find a correct solution for multithread */
819 #if defined(DEBUG_SIGNAL)
820     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
821            pc, address, is_write, *(unsigned long *)old_set);
822 #endif
823     /* XXX: locking issue */
824     if (is_write && page_unprotect(h2g(address), pc, puc)) {
825         return 1;
826     }
827     /* see if it is an MMU fault */
828     ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
829     if (ret < 0)
830         return 0; /* not an MMU fault */
831     if (ret == 0)
832         return 1; /* the MMU fault was handled without causing real CPU fault */
833     /* now we have a real cpu fault */
834     tb = tb_find_pc(pc);
835     if (tb) {
836         /* the PC is inside the translated code. It means that we have
837            a virtual CPU fault */
838         cpu_restore_state(tb, env, pc, puc);
839     }
840     /* we restore the process signal mask as the sigreturn should
841        do it (XXX: use sigsetjmp) */
842     sigprocmask(SIG_SETMASK, old_set, NULL);
843     cpu_loop_exit();
844     /* never comes here */
845     return 1;
846 }
847 #elif defined(TARGET_SPARC)
848 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
849                                     int is_write, sigset_t *old_set,
850                                     void *puc)
851 {
852     TranslationBlock *tb;
853     int ret;
854
855     if (cpu_single_env)
856         env = cpu_single_env; /* XXX: find a correct solution for multithread */
857 #if defined(DEBUG_SIGNAL)
858     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
859            pc, address, is_write, *(unsigned long *)old_set);
860 #endif
861     /* XXX: locking issue */
862     if (is_write && page_unprotect(h2g(address), pc, puc)) {
863         return 1;
864     }
865     /* see if it is an MMU fault */
866     ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
867     if (ret < 0)
868         return 0; /* not an MMU fault */
869     if (ret == 0)
870         return 1; /* the MMU fault was handled without causing real CPU fault */
871     /* now we have a real cpu fault */
872     tb = tb_find_pc(pc);
873     if (tb) {
874         /* the PC is inside the translated code. It means that we have
875            a virtual CPU fault */
876         cpu_restore_state(tb, env, pc, puc);
877     }
878     /* we restore the process signal mask as the sigreturn should
879        do it (XXX: use sigsetjmp) */
880     sigprocmask(SIG_SETMASK, old_set, NULL);
881     cpu_loop_exit();
882     /* never comes here */
883     return 1;
884 }
885 #elif defined (TARGET_PPC)
886 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
887                                     int is_write, sigset_t *old_set,
888                                     void *puc)
889 {
890     TranslationBlock *tb;
891     int ret;
892
893     if (cpu_single_env)
894         env = cpu_single_env; /* XXX: find a correct solution for multithread */
895 #if defined(DEBUG_SIGNAL)
896     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
897            pc, address, is_write, *(unsigned long *)old_set);
898 #endif
899     /* XXX: locking issue */
900     if (is_write && page_unprotect(h2g(address), pc, puc)) {
901         return 1;
902     }
903
904     /* see if it is an MMU fault */
905     ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
906     if (ret < 0)
907         return 0; /* not an MMU fault */
908     if (ret == 0)
909         return 1; /* the MMU fault was handled without causing real CPU fault */
910
911     /* now we have a real cpu fault */
912     tb = tb_find_pc(pc);
913     if (tb) {
914         /* the PC is inside the translated code. It means that we have
915            a virtual CPU fault */
916         cpu_restore_state(tb, env, pc, puc);
917     }
918     if (ret == 1) {
919 #if 0
920         printf("PF exception: NIP=0x%08x error=0x%x %p\n",
921                env->nip, env->error_code, tb);
922 #endif
923     /* we restore the process signal mask as the sigreturn should
924        do it (XXX: use sigsetjmp) */
925         sigprocmask(SIG_SETMASK, old_set, NULL);
926         do_raise_exception_err(env->exception_index, env->error_code);
927     } else {
928         /* activate soft MMU for this block */
929         cpu_resume_from_signal(env, puc);
930     }
931     /* never comes here */
932     return 1;
933 }
934
935 #elif defined(TARGET_M68K)
936 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
937                                     int is_write, sigset_t *old_set,
938                                     void *puc)
939 {
940     TranslationBlock *tb;
941     int ret;
942
943     if (cpu_single_env)
944         env = cpu_single_env; /* XXX: find a correct solution for multithread */
945 #if defined(DEBUG_SIGNAL)
946     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
947            pc, address, is_write, *(unsigned long *)old_set);
948 #endif
949     /* XXX: locking issue */
950     if (is_write && page_unprotect(address, pc, puc)) {
951         return 1;
952     }
953     /* see if it is an MMU fault */
954     ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
955     if (ret < 0)
956         return 0; /* not an MMU fault */
957     if (ret == 0)
958         return 1; /* the MMU fault was handled without causing real CPU fault */
959     /* now we have a real cpu fault */
960     tb = tb_find_pc(pc);
961     if (tb) {
962         /* the PC is inside the translated code. It means that we have
963            a virtual CPU fault */
964         cpu_restore_state(tb, env, pc, puc);
965     }
966     /* we restore the process signal mask as the sigreturn should
967        do it (XXX: use sigsetjmp) */
968     sigprocmask(SIG_SETMASK, old_set, NULL);
969     cpu_loop_exit();
970     /* never comes here */
971     return 1;
972 }
973
974 #elif defined (TARGET_MIPS)
975 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
976                                     int is_write, sigset_t *old_set,
977                                     void *puc)
978 {
979     TranslationBlock *tb;
980     int ret;
981
982     if (cpu_single_env)
983         env = cpu_single_env; /* XXX: find a correct solution for multithread */
984 #if defined(DEBUG_SIGNAL)
985     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
986            pc, address, is_write, *(unsigned long *)old_set);
987 #endif
988     /* XXX: locking issue */
989     if (is_write && page_unprotect(h2g(address), pc, puc)) {
990         return 1;
991     }
992
993     /* see if it is an MMU fault */
994     ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
995     if (ret < 0)
996         return 0; /* not an MMU fault */
997     if (ret == 0)
998         return 1; /* the MMU fault was handled without causing real CPU fault */
999
1000     /* now we have a real cpu fault */
1001     tb = tb_find_pc(pc);
1002     if (tb) {
1003         /* the PC is inside the translated code. It means that we have
1004            a virtual CPU fault */
1005         cpu_restore_state(tb, env, pc, puc);
1006     }
1007     if (ret == 1) {
1008 #if 0
1009         printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
1010                env->PC, env->error_code, tb);
1011 #endif
1012     /* we restore the process signal mask as the sigreturn should
1013        do it (XXX: use sigsetjmp) */
1014         sigprocmask(SIG_SETMASK, old_set, NULL);
1015         do_raise_exception_err(env->exception_index, env->error_code);
1016     } else {
1017         /* activate soft MMU for this block */
1018         cpu_resume_from_signal(env, puc);
1019     }
1020     /* never comes here */
1021     return 1;
1022 }
1023
1024 #elif defined (TARGET_SH4)
1025 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1026                                     int is_write, sigset_t *old_set,
1027                                     void *puc)
1028 {
1029     TranslationBlock *tb;
1030     int ret;
1031
1032     if (cpu_single_env)
1033         env = cpu_single_env; /* XXX: find a correct solution for multithread */
1034 #if defined(DEBUG_SIGNAL)
1035     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1036            pc, address, is_write, *(unsigned long *)old_set);
1037 #endif
1038     /* XXX: locking issue */
1039     if (is_write && page_unprotect(h2g(address), pc, puc)) {
1040         return 1;
1041     }
1042
1043     /* see if it is an MMU fault */
1044     ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1045     if (ret < 0)
1046         return 0; /* not an MMU fault */
1047     if (ret == 0)
1048         return 1; /* the MMU fault was handled without causing real CPU fault */
1049
1050     /* now we have a real cpu fault */
1051     tb = tb_find_pc(pc);
1052     if (tb) {
1053         /* the PC is inside the translated code. It means that we have
1054            a virtual CPU fault */
1055         cpu_restore_state(tb, env, pc, puc);
1056     }
1057 #if 0
1058         printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1059                env->nip, env->error_code, tb);
1060 #endif
1061     /* we restore the process signal mask as the sigreturn should
1062        do it (XXX: use sigsetjmp) */
1063     sigprocmask(SIG_SETMASK, old_set, NULL);
1064     cpu_loop_exit();
1065     /* never comes here */
1066     return 1;
1067 }
1068
1069 #elif defined (TARGET_ALPHA)
1070 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1071                                     int is_write, sigset_t *old_set,
1072                                     void *puc)
1073 {
1074     TranslationBlock *tb;
1075     int ret;
1076
1077     if (cpu_single_env)
1078         env = cpu_single_env; /* XXX: find a correct solution for multithread */
1079 #if defined(DEBUG_SIGNAL)
1080     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1081            pc, address, is_write, *(unsigned long *)old_set);
1082 #endif
1083     /* XXX: locking issue */
1084     if (is_write && page_unprotect(h2g(address), pc, puc)) {
1085         return 1;
1086     }
1087
1088     /* see if it is an MMU fault */
1089     ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1090     if (ret < 0)
1091         return 0; /* not an MMU fault */
1092     if (ret == 0)
1093         return 1; /* the MMU fault was handled without causing real CPU fault */
1094
1095     /* now we have a real cpu fault */
1096     tb = tb_find_pc(pc);
1097     if (tb) {
1098         /* the PC is inside the translated code. It means that we have
1099            a virtual CPU fault */
1100         cpu_restore_state(tb, env, pc, puc);
1101     }
1102 #if 0
1103         printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1104                env->nip, env->error_code, tb);
1105 #endif
1106     /* we restore the process signal mask as the sigreturn should
1107        do it (XXX: use sigsetjmp) */
1108     sigprocmask(SIG_SETMASK, old_set, NULL);
1109     cpu_loop_exit();
1110     /* never comes here */
1111     return 1;
1112 }
1113 #elif defined (TARGET_CRIS)
1114 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1115                                     int is_write, sigset_t *old_set,
1116                                     void *puc)
1117 {
1118     TranslationBlock *tb;
1119     int ret;
1120
1121     if (cpu_single_env)
1122         env = cpu_single_env; /* XXX: find a correct solution for multithread */
1123 #if defined(DEBUG_SIGNAL)
1124     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1125            pc, address, is_write, *(unsigned long *)old_set);
1126 #endif
1127     /* XXX: locking issue */
1128     if (is_write && page_unprotect(h2g(address), pc, puc)) {
1129         return 1;
1130     }
1131
1132     /* see if it is an MMU fault */
1133     ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1134     if (ret < 0)
1135         return 0; /* not an MMU fault */
1136     if (ret == 0)
1137         return 1; /* the MMU fault was handled without causing real CPU fault */
1138
1139     /* now we have a real cpu fault */
1140     tb = tb_find_pc(pc);
1141     if (tb) {
1142         /* the PC is inside the translated code. It means that we have
1143            a virtual CPU fault */
1144         cpu_restore_state(tb, env, pc, puc);
1145     }
1146     /* we restore the process signal mask as the sigreturn should
1147        do it (XXX: use sigsetjmp) */
1148     sigprocmask(SIG_SETMASK, old_set, NULL);
1149     cpu_loop_exit();
1150     /* never comes here */
1151     return 1;
1152 }
1153
1154 #else
1155 #error unsupported target CPU
1156 #endif
1157
1158 #if defined(__i386__)
1159
1160 #if defined(__APPLE__)
1161 # include <sys/ucontext.h>
1162
1163 # define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1164 # define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
1165 # define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
1166 #else
1167 # define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
1168 # define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
1169 # define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
1170 #endif
1171
1172 int cpu_signal_handler(int host_signum, void *pinfo,
1173                        void *puc)
1174 {
1175     siginfo_t *info = pinfo;
1176     struct ucontext *uc = puc;
1177     unsigned long pc;
1178     int trapno;
1179
1180 #ifndef REG_EIP
1181 /* for glibc 2.1 */
1182 #define REG_EIP    EIP
1183 #define REG_ERR    ERR
1184 #define REG_TRAPNO TRAPNO
1185 #endif
1186     pc = EIP_sig(uc);
1187     trapno = TRAP_sig(uc);
1188     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1189                              trapno == 0xe ?
1190                              (ERROR_sig(uc) >> 1) & 1 : 0,
1191                              &uc->uc_sigmask, puc);
1192 }
1193
1194 #elif defined(__x86_64__)
1195
1196 int cpu_signal_handler(int host_signum, void *pinfo,
1197                        void *puc)
1198 {
1199     siginfo_t *info = pinfo;
1200     struct ucontext *uc = puc;
1201     unsigned long pc;
1202
1203     pc = uc->uc_mcontext.gregs[REG_RIP];
1204     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1205                              uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
1206                              (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1207                              &uc->uc_sigmask, puc);
1208 }
1209
1210 #elif defined(__powerpc__)
1211
1212 /***********************************************************************
1213  * signal context platform-specific definitions
1214  * From Wine
1215  */
1216 #ifdef linux
1217 /* All Registers access - only for local access */
1218 # define REG_sig(reg_name, context)             ((context)->uc_mcontext.regs->reg_name)
1219 /* Gpr Registers access  */
1220 # define GPR_sig(reg_num, context)              REG_sig(gpr[reg_num], context)
1221 # define IAR_sig(context)                       REG_sig(nip, context)   /* Program counter */
1222 # define MSR_sig(context)                       REG_sig(msr, context)   /* Machine State Register (Supervisor) */
1223 # define CTR_sig(context)                       REG_sig(ctr, context)   /* Count register */
1224 # define XER_sig(context)                       REG_sig(xer, context) /* User's integer exception register */
1225 # define LR_sig(context)                        REG_sig(link, context) /* Link register */
1226 # define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
1227 /* Float Registers access  */
1228 # define FLOAT_sig(reg_num, context)            (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1229 # define FPSCR_sig(context)                     (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1230 /* Exception Registers access */
1231 # define DAR_sig(context)                       REG_sig(dar, context)
1232 # define DSISR_sig(context)                     REG_sig(dsisr, context)
1233 # define TRAP_sig(context)                      REG_sig(trap, context)
1234 #endif /* linux */
1235
1236 #ifdef __APPLE__
1237 # include <sys/ucontext.h>
1238 typedef struct ucontext SIGCONTEXT;
1239 /* All Registers access - only for local access */
1240 # define REG_sig(reg_name, context)             ((context)->uc_mcontext->ss.reg_name)
1241 # define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
1242 # define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
1243 # define VECREG_sig(reg_name, context)          ((context)->uc_mcontext->vs.reg_name)
1244 /* Gpr Registers access */
1245 # define GPR_sig(reg_num, context)              REG_sig(r##reg_num, context)
1246 # define IAR_sig(context)                       REG_sig(srr0, context)  /* Program counter */
1247 # define MSR_sig(context)                       REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
1248 # define CTR_sig(context)                       REG_sig(ctr, context)
1249 # define XER_sig(context)                       REG_sig(xer, context) /* Link register */
1250 # define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
1251 # define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
1252 /* Float Registers access */
1253 # define FLOAT_sig(reg_num, context)            FLOATREG_sig(fpregs[reg_num], context)
1254 # define FPSCR_sig(context)                     ((double)FLOATREG_sig(fpscr, context))
1255 /* Exception Registers access */
1256 # define DAR_sig(context)                       EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
1257 # define DSISR_sig(context)                     EXCEPREG_sig(dsisr, context)
1258 # define TRAP_sig(context)                      EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1259 #endif /* __APPLE__ */
1260
1261 int cpu_signal_handler(int host_signum, void *pinfo,
1262                        void *puc)
1263 {
1264     siginfo_t *info = pinfo;
1265     struct ucontext *uc = puc;
1266     unsigned long pc;
1267     int is_write;
1268
1269     pc = IAR_sig(uc);
1270     is_write = 0;
1271 #if 0
1272     /* ppc 4xx case */
1273     if (DSISR_sig(uc) & 0x00800000)
1274         is_write = 1;
1275 #else
1276     if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1277         is_write = 1;
1278 #endif
1279     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1280                              is_write, &uc->uc_sigmask, puc);
1281 }
1282
1283 #elif defined(__alpha__)
1284
1285 int cpu_signal_handler(int host_signum, void *pinfo,
1286                            void *puc)
1287 {
1288     siginfo_t *info = pinfo;
1289     struct ucontext *uc = puc;
1290     uint32_t *pc = uc->uc_mcontext.sc_pc;
1291     uint32_t insn = *pc;
1292     int is_write = 0;
1293
1294     /* XXX: need kernel patch to get write flag faster */
1295     switch (insn >> 26) {
1296     case 0x0d: // stw
1297     case 0x0e: // stb
1298     case 0x0f: // stq_u
1299     case 0x24: // stf
1300     case 0x25: // stg
1301     case 0x26: // sts
1302     case 0x27: // stt
1303     case 0x2c: // stl
1304     case 0x2d: // stq
1305     case 0x2e: // stl_c
1306     case 0x2f: // stq_c
1307         is_write = 1;
1308     }
1309
1310     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1311                              is_write, &uc->uc_sigmask, puc);
1312 }
1313 #elif defined(__sparc__)
1314
1315 int cpu_signal_handler(int host_signum, void *pinfo,
1316                        void *puc)
1317 {
1318     siginfo_t *info = pinfo;
1319     int is_write;
1320     uint32_t insn;
1321 #if !defined(__arch64__) || defined(HOST_SOLARIS)
1322     uint32_t *regs = (uint32_t *)(info + 1);
1323     void *sigmask = (regs + 20);
1324     /* XXX: is there a standard glibc define ? */
1325     unsigned long pc = regs[1];
1326 #else
1327     struct sigcontext *sc = puc;
1328     unsigned long pc = sc->sigc_regs.tpc;
1329     void *sigmask = (void *)sc->sigc_mask;
1330 #endif
1331
1332     /* XXX: need kernel patch to get write flag faster */
1333     is_write = 0;
1334     insn = *(uint32_t *)pc;
1335     if ((insn >> 30) == 3) {
1336       switch((insn >> 19) & 0x3f) {
1337       case 0x05: // stb
1338       case 0x06: // sth
1339       case 0x04: // st
1340       case 0x07: // std
1341       case 0x24: // stf
1342       case 0x27: // stdf
1343       case 0x25: // stfsr
1344         is_write = 1;
1345         break;
1346       }
1347     }
1348     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1349                              is_write, sigmask, NULL);
1350 }
1351
1352 #elif defined(__arm__)
1353
1354 int cpu_signal_handler(int host_signum, void *pinfo,
1355                        void *puc)
1356 {
1357     siginfo_t *info = pinfo;
1358     struct ucontext *uc = puc;
1359     unsigned long pc;
1360     int is_write;
1361
1362 #if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ =< 3))
1363     pc = uc->uc_mcontext.gregs[R15];
1364 #else
1365     pc = uc->uc_mcontext.arm_pc;
1366 #endif
1367     /* XXX: compute is_write */
1368     is_write = 0;
1369     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1370                              is_write,
1371                              &uc->uc_sigmask, puc);
1372 }
1373
1374 #elif defined(__mc68000)
1375
1376 int cpu_signal_handler(int host_signum, void *pinfo,
1377                        void *puc)
1378 {
1379     siginfo_t *info = pinfo;
1380     struct ucontext *uc = puc;
1381     unsigned long pc;
1382     int is_write;
1383
1384     pc = uc->uc_mcontext.gregs[16];
1385     /* XXX: compute is_write */
1386     is_write = 0;
1387     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1388                              is_write,
1389                              &uc->uc_sigmask, puc);
1390 }
1391
1392 #elif defined(__ia64)
1393
1394 #ifndef __ISR_VALID
1395   /* This ought to be in <bits/siginfo.h>... */
1396 # define __ISR_VALID    1
1397 #endif
1398
1399 int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1400 {
1401     siginfo_t *info = pinfo;
1402     struct ucontext *uc = puc;
1403     unsigned long ip;
1404     int is_write = 0;
1405
1406     ip = uc->uc_mcontext.sc_ip;
1407     switch (host_signum) {
1408       case SIGILL:
1409       case SIGFPE:
1410       case SIGSEGV:
1411       case SIGBUS:
1412       case SIGTRAP:
1413           if (info->si_code && (info->si_segvflags & __ISR_VALID))
1414               /* ISR.W (write-access) is bit 33:  */
1415               is_write = (info->si_isr >> 33) & 1;
1416           break;
1417
1418       default:
1419           break;
1420     }
1421     return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1422                              is_write,
1423                              &uc->uc_sigmask, puc);
1424 }
1425
1426 #elif defined(__s390__)
1427
1428 int cpu_signal_handler(int host_signum, void *pinfo,
1429                        void *puc)
1430 {
1431     siginfo_t *info = pinfo;
1432     struct ucontext *uc = puc;
1433     unsigned long pc;
1434     int is_write;
1435
1436     pc = uc->uc_mcontext.psw.addr;
1437     /* XXX: compute is_write */
1438     is_write = 0;
1439     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1440                              is_write, &uc->uc_sigmask, puc);
1441 }
1442
1443 #elif defined(__mips__)
1444
1445 int cpu_signal_handler(int host_signum, void *pinfo,
1446                        void *puc)
1447 {
1448     siginfo_t *info = pinfo;
1449     struct ucontext *uc = puc;
1450     greg_t pc = uc->uc_mcontext.pc;
1451     int is_write;
1452
1453     /* XXX: compute is_write */
1454     is_write = 0;
1455     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1456                              is_write, &uc->uc_sigmask, puc);
1457 }
1458
1459 #elif defined(__hppa__)
1460
1461 int cpu_signal_handler(int host_signum, void *pinfo,
1462                        void *puc)
1463 {
1464     struct siginfo *info = pinfo;
1465     struct ucontext *uc = puc;
1466     unsigned long pc;
1467     int is_write;
1468
1469     pc = uc->uc_mcontext.sc_iaoq[0];
1470     /* FIXME: compute is_write */
1471     is_write = 0;
1472     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1473                              is_write,
1474                              &uc->uc_sigmask, puc);
1475 }
1476
1477 #else
1478
1479 #error host CPU specific signal handler needed
1480
1481 #endif
1482
1483 #endif /* !defined(CONFIG_SOFTMMU) */