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