removed unused code
[sdk/emulator/qemu.git] / cpu-exec.c
1 /*
2  *  i386 emulator main execution loop
3  *
4  *  Copyright (c) 2003-2005 Fabrice Bellard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, 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 | X_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);
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                             env->exception_index = env->interrupt_index;
478                             do_interrupt(env);
479                             env->interrupt_index = 0;
480 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
481                             cpu_check_irqs(env);
482 #endif
483                         next_tb = 0;
484                         }
485                     } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
486                         //do_interrupt(0, 0, 0, 0, 0);
487                         env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
488                     }
489 #elif defined(TARGET_ARM)
490                     if (interrupt_request & CPU_INTERRUPT_FIQ
491                         && !(env->uncached_cpsr & CPSR_F)) {
492                         env->exception_index = EXCP_FIQ;
493                         do_interrupt(env);
494                         next_tb = 0;
495                     }
496                     /* ARMv7-M interrupt return works by loading a magic value
497                        into the PC.  On real hardware the load causes the
498                        return to occur.  The qemu implementation performs the
499                        jump normally, then does the exception return when the
500                        CPU tries to execute code at the magic address.
501                        This will cause the magic PC value to be pushed to
502                        the stack if an interrupt occured at the wrong time.
503                        We avoid this by disabling interrupts when
504                        pc contains a magic address.  */
505                     if (interrupt_request & CPU_INTERRUPT_HARD
506                         && ((IS_M(env) && env->regs[15] < 0xfffffff0)
507                             || !(env->uncached_cpsr & CPSR_I))) {
508                         env->exception_index = EXCP_IRQ;
509                         do_interrupt(env);
510                         next_tb = 0;
511                     }
512 #elif defined(TARGET_SH4)
513                     if (interrupt_request & CPU_INTERRUPT_HARD) {
514                         do_interrupt(env);
515                         next_tb = 0;
516                     }
517 #elif defined(TARGET_ALPHA)
518                     if (interrupt_request & CPU_INTERRUPT_HARD) {
519                         do_interrupt(env);
520                         next_tb = 0;
521                     }
522 #elif defined(TARGET_CRIS)
523                     if (interrupt_request & CPU_INTERRUPT_HARD) {
524                         do_interrupt(env);
525                         next_tb = 0;
526                     }
527 #elif defined(TARGET_M68K)
528                     if (interrupt_request & CPU_INTERRUPT_HARD
529                         && ((env->sr & SR_I) >> SR_I_SHIFT)
530                             < env->pending_level) {
531                         /* Real hardware gets the interrupt vector via an
532                            IACK cycle at this point.  Current emulated
533                            hardware doesn't rely on this, so we
534                            provide/save the vector when the interrupt is
535                            first signalled.  */
536                         env->exception_index = env->pending_vector;
537                         do_interrupt(1);
538                         next_tb = 0;
539                     }
540 #endif
541                    /* Don't use the cached interupt_request value,
542                       do_interrupt may have updated the EXITTB flag. */
543                     if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
544                         env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
545                         /* ensure that no TB jump will be modified as
546                            the program flow was changed */
547                         next_tb = 0;
548                     }
549                     if (interrupt_request & CPU_INTERRUPT_EXIT) {
550                         env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
551                         env->exception_index = EXCP_INTERRUPT;
552                         cpu_loop_exit();
553                     }
554                 }
555 #ifdef DEBUG_EXEC
556                 if ((loglevel & CPU_LOG_TB_CPU)) {
557                     /* restore flags in standard format */
558                     regs_to_env();
559 #if defined(TARGET_I386)
560                     env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
561                     cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
562                     env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
563 #elif defined(TARGET_ARM)
564                     cpu_dump_state(env, logfile, fprintf, 0);
565 #elif defined(TARGET_SPARC)
566                     REGWPTR = env->regbase + (env->cwp * 16);
567                     env->regwptr = REGWPTR;
568                     cpu_dump_state(env, logfile, fprintf, 0);
569 #elif defined(TARGET_PPC)
570                     cpu_dump_state(env, logfile, fprintf, 0);
571 #elif defined(TARGET_M68K)
572                     cpu_m68k_flush_flags(env, env->cc_op);
573                     env->cc_op = CC_OP_FLAGS;
574                     env->sr = (env->sr & 0xffe0)
575                               | env->cc_dest | (env->cc_x << 4);
576                     cpu_dump_state(env, logfile, fprintf, 0);
577 #elif defined(TARGET_MIPS)
578                     cpu_dump_state(env, logfile, fprintf, 0);
579 #elif defined(TARGET_SH4)
580                     cpu_dump_state(env, logfile, fprintf, 0);
581 #elif defined(TARGET_ALPHA)
582                     cpu_dump_state(env, logfile, fprintf, 0);
583 #elif defined(TARGET_CRIS)
584                     cpu_dump_state(env, logfile, fprintf, 0);
585 #else
586 #error unsupported target CPU
587 #endif
588                 }
589 #endif
590                 tb = tb_find_fast();
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                     spin_lock(&tb_lock);
608                     tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
609                     spin_unlock(&tb_lock);
610                 }
611                 }
612                 tc_ptr = tb->tc_ptr;
613                 env->current_tb = tb;
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                 /* reset soft MMU for next block (it can currently
623                    only be set by a memory fault) */
624 #if defined(USE_KQEMU)
625 #define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
626                 if (kqemu_is_ok(env) &&
627                     (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
628                     cpu_loop_exit();
629                 }
630 #endif
631             } /* for(;;) */
632         } else {
633             env_to_regs();
634         }
635     } /* for(;;) */
636
637
638 #if defined(TARGET_I386)
639     /* restore flags in standard format */
640     env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
641 #elif defined(TARGET_ARM)
642     /* XXX: Save/restore host fpu exception state?.  */
643 #elif defined(TARGET_SPARC)
644 #if defined(reg_REGWPTR)
645     REGWPTR = saved_regwptr;
646 #endif
647 #elif defined(TARGET_PPC)
648 #elif defined(TARGET_M68K)
649     cpu_m68k_flush_flags(env, env->cc_op);
650     env->cc_op = CC_OP_FLAGS;
651     env->sr = (env->sr & 0xffe0)
652               | env->cc_dest | (env->cc_x << 4);
653 #elif defined(TARGET_MIPS)
654 #elif defined(TARGET_SH4)
655 #elif defined(TARGET_ALPHA)
656 #elif defined(TARGET_CRIS)
657     /* XXXXX */
658 #else
659 #error unsupported target CPU
660 #endif
661
662     /* restore global registers */
663 #include "hostregs_helper.h"
664
665     /* fail safe : never use cpu_single_env outside cpu_exec() */
666     cpu_single_env = NULL;
667     return ret;
668 }
669
670 /* must only be called from the generated code as an exception can be
671    generated */
672 void tb_invalidate_page_range(target_ulong start, target_ulong end)
673 {
674     /* XXX: cannot enable it yet because it yields to MMU exception
675        where NIP != read address on PowerPC */
676 #if 0
677     target_ulong phys_addr;
678     phys_addr = get_phys_addr_code(env, start);
679     tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
680 #endif
681 }
682
683 #if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
684
685 void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
686 {
687     CPUX86State *saved_env;
688
689     saved_env = env;
690     env = s;
691     if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
692         selector &= 0xffff;
693         cpu_x86_load_seg_cache(env, seg_reg, selector,
694                                (selector << 4), 0xffff, 0);
695     } else {
696         helper_load_seg(seg_reg, selector);
697     }
698     env = saved_env;
699 }
700
701 void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
702 {
703     CPUX86State *saved_env;
704
705     saved_env = env;
706     env = s;
707
708     helper_fsave(ptr, data32);
709
710     env = saved_env;
711 }
712
713 void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
714 {
715     CPUX86State *saved_env;
716
717     saved_env = env;
718     env = s;
719
720     helper_frstor(ptr, data32);
721
722     env = saved_env;
723 }
724
725 #endif /* TARGET_I386 */
726
727 #if !defined(CONFIG_SOFTMMU)
728
729 #if defined(TARGET_I386)
730
731 /* 'pc' is the host PC at which the exception was raised. 'address' is
732    the effective address of the memory exception. 'is_write' is 1 if a
733    write caused the exception and otherwise 0'. 'old_set' is the
734    signal set which should be restored */
735 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
736                                     int is_write, sigset_t *old_set,
737                                     void *puc)
738 {
739     TranslationBlock *tb;
740     int ret;
741
742     if (cpu_single_env)
743         env = cpu_single_env; /* XXX: find a correct solution for multithread */
744 #if defined(DEBUG_SIGNAL)
745     qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
746                 pc, address, is_write, *(unsigned long *)old_set);
747 #endif
748     /* XXX: locking issue */
749     if (is_write && page_unprotect(h2g(address), pc, puc)) {
750         return 1;
751     }
752
753     /* see if it is an MMU fault */
754     ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
755     if (ret < 0)
756         return 0; /* not an MMU fault */
757     if (ret == 0)
758         return 1; /* the MMU fault was handled without causing real CPU fault */
759     /* now we have a real cpu fault */
760     tb = tb_find_pc(pc);
761     if (tb) {
762         /* the PC is inside the translated code. It means that we have
763            a virtual CPU fault */
764         cpu_restore_state(tb, env, pc, puc);
765     }
766     if (ret == 1) {
767 #if 0
768         printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
769                env->eip, env->cr[2], env->error_code);
770 #endif
771         /* we restore the process signal mask as the sigreturn should
772            do it (XXX: use sigsetjmp) */
773         sigprocmask(SIG_SETMASK, old_set, NULL);
774         raise_exception_err(env->exception_index, env->error_code);
775     } else {
776         /* activate soft MMU for this block */
777         env->hflags |= HF_SOFTMMU_MASK;
778         cpu_resume_from_signal(env, puc);
779     }
780     /* never comes here */
781     return 1;
782 }
783
784 #elif defined(TARGET_ARM)
785 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
786                                     int is_write, sigset_t *old_set,
787                                     void *puc)
788 {
789     TranslationBlock *tb;
790     int ret;
791
792     if (cpu_single_env)
793         env = cpu_single_env; /* XXX: find a correct solution for multithread */
794 #if defined(DEBUG_SIGNAL)
795     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
796            pc, address, is_write, *(unsigned long *)old_set);
797 #endif
798     /* XXX: locking issue */
799     if (is_write && page_unprotect(h2g(address), pc, puc)) {
800         return 1;
801     }
802     /* see if it is an MMU fault */
803     ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
804     if (ret < 0)
805         return 0; /* not an MMU fault */
806     if (ret == 0)
807         return 1; /* the MMU fault was handled without causing real CPU fault */
808     /* now we have a real cpu fault */
809     tb = tb_find_pc(pc);
810     if (tb) {
811         /* the PC is inside the translated code. It means that we have
812            a virtual CPU fault */
813         cpu_restore_state(tb, env, pc, puc);
814     }
815     /* we restore the process signal mask as the sigreturn should
816        do it (XXX: use sigsetjmp) */
817     sigprocmask(SIG_SETMASK, old_set, NULL);
818     cpu_loop_exit();
819     /* never comes here */
820     return 1;
821 }
822 #elif defined(TARGET_SPARC)
823 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
824                                     int is_write, sigset_t *old_set,
825                                     void *puc)
826 {
827     TranslationBlock *tb;
828     int ret;
829
830     if (cpu_single_env)
831         env = cpu_single_env; /* XXX: find a correct solution for multithread */
832 #if defined(DEBUG_SIGNAL)
833     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
834            pc, address, is_write, *(unsigned long *)old_set);
835 #endif
836     /* XXX: locking issue */
837     if (is_write && page_unprotect(h2g(address), pc, puc)) {
838         return 1;
839     }
840     /* see if it is an MMU fault */
841     ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
842     if (ret < 0)
843         return 0; /* not an MMU fault */
844     if (ret == 0)
845         return 1; /* the MMU fault was handled without causing real CPU fault */
846     /* now we have a real cpu fault */
847     tb = tb_find_pc(pc);
848     if (tb) {
849         /* the PC is inside the translated code. It means that we have
850            a virtual CPU fault */
851         cpu_restore_state(tb, env, pc, puc);
852     }
853     /* we restore the process signal mask as the sigreturn should
854        do it (XXX: use sigsetjmp) */
855     sigprocmask(SIG_SETMASK, old_set, NULL);
856     cpu_loop_exit();
857     /* never comes here */
858     return 1;
859 }
860 #elif defined (TARGET_PPC)
861 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
862                                     int is_write, sigset_t *old_set,
863                                     void *puc)
864 {
865     TranslationBlock *tb;
866     int ret;
867
868     if (cpu_single_env)
869         env = cpu_single_env; /* XXX: find a correct solution for multithread */
870 #if defined(DEBUG_SIGNAL)
871     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
872            pc, address, is_write, *(unsigned long *)old_set);
873 #endif
874     /* XXX: locking issue */
875     if (is_write && page_unprotect(h2g(address), pc, puc)) {
876         return 1;
877     }
878
879     /* see if it is an MMU fault */
880     ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
881     if (ret < 0)
882         return 0; /* not an MMU fault */
883     if (ret == 0)
884         return 1; /* the MMU fault was handled without causing real CPU fault */
885
886     /* now we have a real cpu fault */
887     tb = tb_find_pc(pc);
888     if (tb) {
889         /* the PC is inside the translated code. It means that we have
890            a virtual CPU fault */
891         cpu_restore_state(tb, env, pc, puc);
892     }
893     if (ret == 1) {
894 #if 0
895         printf("PF exception: NIP=0x%08x error=0x%x %p\n",
896                env->nip, env->error_code, tb);
897 #endif
898     /* we restore the process signal mask as the sigreturn should
899        do it (XXX: use sigsetjmp) */
900         sigprocmask(SIG_SETMASK, old_set, NULL);
901         do_raise_exception_err(env->exception_index, env->error_code);
902     } else {
903         /* activate soft MMU for this block */
904         cpu_resume_from_signal(env, puc);
905     }
906     /* never comes here */
907     return 1;
908 }
909
910 #elif defined(TARGET_M68K)
911 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
912                                     int is_write, sigset_t *old_set,
913                                     void *puc)
914 {
915     TranslationBlock *tb;
916     int ret;
917
918     if (cpu_single_env)
919         env = cpu_single_env; /* XXX: find a correct solution for multithread */
920 #if defined(DEBUG_SIGNAL)
921     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
922            pc, address, is_write, *(unsigned long *)old_set);
923 #endif
924     /* XXX: locking issue */
925     if (is_write && page_unprotect(address, pc, puc)) {
926         return 1;
927     }
928     /* see if it is an MMU fault */
929     ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
930     if (ret < 0)
931         return 0; /* not an MMU fault */
932     if (ret == 0)
933         return 1; /* the MMU fault was handled without causing real CPU fault */
934     /* now we have a real cpu fault */
935     tb = tb_find_pc(pc);
936     if (tb) {
937         /* the PC is inside the translated code. It means that we have
938            a virtual CPU fault */
939         cpu_restore_state(tb, env, pc, puc);
940     }
941     /* we restore the process signal mask as the sigreturn should
942        do it (XXX: use sigsetjmp) */
943     sigprocmask(SIG_SETMASK, old_set, NULL);
944     cpu_loop_exit();
945     /* never comes here */
946     return 1;
947 }
948
949 #elif defined (TARGET_MIPS)
950 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
951                                     int is_write, sigset_t *old_set,
952                                     void *puc)
953 {
954     TranslationBlock *tb;
955     int ret;
956
957     if (cpu_single_env)
958         env = cpu_single_env; /* XXX: find a correct solution for multithread */
959 #if defined(DEBUG_SIGNAL)
960     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
961            pc, address, is_write, *(unsigned long *)old_set);
962 #endif
963     /* XXX: locking issue */
964     if (is_write && page_unprotect(h2g(address), pc, puc)) {
965         return 1;
966     }
967
968     /* see if it is an MMU fault */
969     ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
970     if (ret < 0)
971         return 0; /* not an MMU fault */
972     if (ret == 0)
973         return 1; /* the MMU fault was handled without causing real CPU fault */
974
975     /* now we have a real cpu fault */
976     tb = tb_find_pc(pc);
977     if (tb) {
978         /* the PC is inside the translated code. It means that we have
979            a virtual CPU fault */
980         cpu_restore_state(tb, env, pc, puc);
981     }
982     if (ret == 1) {
983 #if 0
984         printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
985                env->PC, env->error_code, tb);
986 #endif
987     /* we restore the process signal mask as the sigreturn should
988        do it (XXX: use sigsetjmp) */
989         sigprocmask(SIG_SETMASK, old_set, NULL);
990         do_raise_exception_err(env->exception_index, env->error_code);
991     } else {
992         /* activate soft MMU for this block */
993         cpu_resume_from_signal(env, puc);
994     }
995     /* never comes here */
996     return 1;
997 }
998
999 #elif defined (TARGET_SH4)
1000 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1001                                     int is_write, sigset_t *old_set,
1002                                     void *puc)
1003 {
1004     TranslationBlock *tb;
1005     int ret;
1006
1007     if (cpu_single_env)
1008         env = cpu_single_env; /* XXX: find a correct solution for multithread */
1009 #if defined(DEBUG_SIGNAL)
1010     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1011            pc, address, is_write, *(unsigned long *)old_set);
1012 #endif
1013     /* XXX: locking issue */
1014     if (is_write && page_unprotect(h2g(address), pc, puc)) {
1015         return 1;
1016     }
1017
1018     /* see if it is an MMU fault */
1019     ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1020     if (ret < 0)
1021         return 0; /* not an MMU fault */
1022     if (ret == 0)
1023         return 1; /* the MMU fault was handled without causing real CPU fault */
1024
1025     /* now we have a real cpu fault */
1026     tb = tb_find_pc(pc);
1027     if (tb) {
1028         /* the PC is inside the translated code. It means that we have
1029            a virtual CPU fault */
1030         cpu_restore_state(tb, env, pc, puc);
1031     }
1032 #if 0
1033         printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1034                env->nip, env->error_code, tb);
1035 #endif
1036     /* we restore the process signal mask as the sigreturn should
1037        do it (XXX: use sigsetjmp) */
1038     sigprocmask(SIG_SETMASK, old_set, NULL);
1039     cpu_loop_exit();
1040     /* never comes here */
1041     return 1;
1042 }
1043
1044 #elif defined (TARGET_ALPHA)
1045 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1046                                     int is_write, sigset_t *old_set,
1047                                     void *puc)
1048 {
1049     TranslationBlock *tb;
1050     int ret;
1051
1052     if (cpu_single_env)
1053         env = cpu_single_env; /* XXX: find a correct solution for multithread */
1054 #if defined(DEBUG_SIGNAL)
1055     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1056            pc, address, is_write, *(unsigned long *)old_set);
1057 #endif
1058     /* XXX: locking issue */
1059     if (is_write && page_unprotect(h2g(address), pc, puc)) {
1060         return 1;
1061     }
1062
1063     /* see if it is an MMU fault */
1064     ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1065     if (ret < 0)
1066         return 0; /* not an MMU fault */
1067     if (ret == 0)
1068         return 1; /* the MMU fault was handled without causing real CPU fault */
1069
1070     /* now we have a real cpu fault */
1071     tb = tb_find_pc(pc);
1072     if (tb) {
1073         /* the PC is inside the translated code. It means that we have
1074            a virtual CPU fault */
1075         cpu_restore_state(tb, env, pc, puc);
1076     }
1077 #if 0
1078         printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1079                env->nip, env->error_code, tb);
1080 #endif
1081     /* we restore the process signal mask as the sigreturn should
1082        do it (XXX: use sigsetjmp) */
1083     sigprocmask(SIG_SETMASK, old_set, NULL);
1084     cpu_loop_exit();
1085     /* never comes here */
1086     return 1;
1087 }
1088 #elif defined (TARGET_CRIS)
1089 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1090                                     int is_write, sigset_t *old_set,
1091                                     void *puc)
1092 {
1093     TranslationBlock *tb;
1094     int ret;
1095
1096     if (cpu_single_env)
1097         env = cpu_single_env; /* XXX: find a correct solution for multithread */
1098 #if defined(DEBUG_SIGNAL)
1099     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1100            pc, address, is_write, *(unsigned long *)old_set);
1101 #endif
1102     /* XXX: locking issue */
1103     if (is_write && page_unprotect(h2g(address), pc, puc)) {
1104         return 1;
1105     }
1106
1107     /* see if it is an MMU fault */
1108     ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1109     if (ret < 0)
1110         return 0; /* not an MMU fault */
1111     if (ret == 0)
1112         return 1; /* the MMU fault was handled without causing real CPU fault */
1113
1114     /* now we have a real cpu fault */
1115     tb = tb_find_pc(pc);
1116     if (tb) {
1117         /* the PC is inside the translated code. It means that we have
1118            a virtual CPU fault */
1119         cpu_restore_state(tb, env, pc, puc);
1120     }
1121     /* we restore the process signal mask as the sigreturn should
1122        do it (XXX: use sigsetjmp) */
1123     sigprocmask(SIG_SETMASK, old_set, NULL);
1124     cpu_loop_exit();
1125     /* never comes here */
1126     return 1;
1127 }
1128
1129 #else
1130 #error unsupported target CPU
1131 #endif
1132
1133 #if defined(__i386__)
1134
1135 #if defined(__APPLE__)
1136 # include <sys/ucontext.h>
1137
1138 # define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1139 # define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
1140 # define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
1141 #else
1142 # define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
1143 # define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
1144 # define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
1145 #endif
1146
1147 int cpu_signal_handler(int host_signum, void *pinfo,
1148                        void *puc)
1149 {
1150     siginfo_t *info = pinfo;
1151     struct ucontext *uc = puc;
1152     unsigned long pc;
1153     int trapno;
1154
1155 #ifndef REG_EIP
1156 /* for glibc 2.1 */
1157 #define REG_EIP    EIP
1158 #define REG_ERR    ERR
1159 #define REG_TRAPNO TRAPNO
1160 #endif
1161     pc = EIP_sig(uc);
1162     trapno = TRAP_sig(uc);
1163     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1164                              trapno == 0xe ?
1165                              (ERROR_sig(uc) >> 1) & 1 : 0,
1166                              &uc->uc_sigmask, puc);
1167 }
1168
1169 #elif defined(__x86_64__)
1170
1171 int cpu_signal_handler(int host_signum, void *pinfo,
1172                        void *puc)
1173 {
1174     siginfo_t *info = pinfo;
1175     struct ucontext *uc = puc;
1176     unsigned long pc;
1177
1178     pc = uc->uc_mcontext.gregs[REG_RIP];
1179     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1180                              uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
1181                              (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1182                              &uc->uc_sigmask, puc);
1183 }
1184
1185 #elif defined(__powerpc__)
1186
1187 /***********************************************************************
1188  * signal context platform-specific definitions
1189  * From Wine
1190  */
1191 #ifdef linux
1192 /* All Registers access - only for local access */
1193 # define REG_sig(reg_name, context)             ((context)->uc_mcontext.regs->reg_name)
1194 /* Gpr Registers access  */
1195 # define GPR_sig(reg_num, context)              REG_sig(gpr[reg_num], context)
1196 # define IAR_sig(context)                       REG_sig(nip, context)   /* Program counter */
1197 # define MSR_sig(context)                       REG_sig(msr, context)   /* Machine State Register (Supervisor) */
1198 # define CTR_sig(context)                       REG_sig(ctr, context)   /* Count register */
1199 # define XER_sig(context)                       REG_sig(xer, context) /* User's integer exception register */
1200 # define LR_sig(context)                        REG_sig(link, context) /* Link register */
1201 # define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
1202 /* Float Registers access  */
1203 # define FLOAT_sig(reg_num, context)            (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1204 # define FPSCR_sig(context)                     (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1205 /* Exception Registers access */
1206 # define DAR_sig(context)                       REG_sig(dar, context)
1207 # define DSISR_sig(context)                     REG_sig(dsisr, context)
1208 # define TRAP_sig(context)                      REG_sig(trap, context)
1209 #endif /* linux */
1210
1211 #ifdef __APPLE__
1212 # include <sys/ucontext.h>
1213 typedef struct ucontext SIGCONTEXT;
1214 /* All Registers access - only for local access */
1215 # define REG_sig(reg_name, context)             ((context)->uc_mcontext->ss.reg_name)
1216 # define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
1217 # define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
1218 # define VECREG_sig(reg_name, context)          ((context)->uc_mcontext->vs.reg_name)
1219 /* Gpr Registers access */
1220 # define GPR_sig(reg_num, context)              REG_sig(r##reg_num, context)
1221 # define IAR_sig(context)                       REG_sig(srr0, context)  /* Program counter */
1222 # define MSR_sig(context)                       REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
1223 # define CTR_sig(context)                       REG_sig(ctr, context)
1224 # define XER_sig(context)                       REG_sig(xer, context) /* Link register */
1225 # define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
1226 # define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
1227 /* Float Registers access */
1228 # define FLOAT_sig(reg_num, context)            FLOATREG_sig(fpregs[reg_num], context)
1229 # define FPSCR_sig(context)                     ((double)FLOATREG_sig(fpscr, context))
1230 /* Exception Registers access */
1231 # define DAR_sig(context)                       EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
1232 # define DSISR_sig(context)                     EXCEPREG_sig(dsisr, context)
1233 # define TRAP_sig(context)                      EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1234 #endif /* __APPLE__ */
1235
1236 int cpu_signal_handler(int host_signum, void *pinfo,
1237                        void *puc)
1238 {
1239     siginfo_t *info = pinfo;
1240     struct ucontext *uc = puc;
1241     unsigned long pc;
1242     int is_write;
1243
1244     pc = IAR_sig(uc);
1245     is_write = 0;
1246 #if 0
1247     /* ppc 4xx case */
1248     if (DSISR_sig(uc) & 0x00800000)
1249         is_write = 1;
1250 #else
1251     if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1252         is_write = 1;
1253 #endif
1254     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1255                              is_write, &uc->uc_sigmask, puc);
1256 }
1257
1258 #elif defined(__alpha__)
1259
1260 int cpu_signal_handler(int host_signum, void *pinfo,
1261                            void *puc)
1262 {
1263     siginfo_t *info = pinfo;
1264     struct ucontext *uc = puc;
1265     uint32_t *pc = uc->uc_mcontext.sc_pc;
1266     uint32_t insn = *pc;
1267     int is_write = 0;
1268
1269     /* XXX: need kernel patch to get write flag faster */
1270     switch (insn >> 26) {
1271     case 0x0d: // stw
1272     case 0x0e: // stb
1273     case 0x0f: // stq_u
1274     case 0x24: // stf
1275     case 0x25: // stg
1276     case 0x26: // sts
1277     case 0x27: // stt
1278     case 0x2c: // stl
1279     case 0x2d: // stq
1280     case 0x2e: // stl_c
1281     case 0x2f: // stq_c
1282         is_write = 1;
1283     }
1284
1285     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1286                              is_write, &uc->uc_sigmask, puc);
1287 }
1288 #elif defined(__sparc__)
1289
1290 int cpu_signal_handler(int host_signum, void *pinfo,
1291                        void *puc)
1292 {
1293     siginfo_t *info = pinfo;
1294     int is_write;
1295     uint32_t insn;
1296 #if !defined(__arch64__) || defined(HOST_SOLARIS)
1297     uint32_t *regs = (uint32_t *)(info + 1);
1298     void *sigmask = (regs + 20);
1299     /* XXX: is there a standard glibc define ? */
1300     unsigned long pc = regs[1];
1301 #else
1302     struct sigcontext *sc = puc;
1303     unsigned long pc = sc->sigc_regs.tpc;
1304     void *sigmask = (void *)sc->sigc_mask;
1305 #endif
1306
1307     /* XXX: need kernel patch to get write flag faster */
1308     is_write = 0;
1309     insn = *(uint32_t *)pc;
1310     if ((insn >> 30) == 3) {
1311       switch((insn >> 19) & 0x3f) {
1312       case 0x05: // stb
1313       case 0x06: // sth
1314       case 0x04: // st
1315       case 0x07: // std
1316       case 0x24: // stf
1317       case 0x27: // stdf
1318       case 0x25: // stfsr
1319         is_write = 1;
1320         break;
1321       }
1322     }
1323     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1324                              is_write, sigmask, NULL);
1325 }
1326
1327 #elif defined(__arm__)
1328
1329 int cpu_signal_handler(int host_signum, void *pinfo,
1330                        void *puc)
1331 {
1332     siginfo_t *info = pinfo;
1333     struct ucontext *uc = puc;
1334     unsigned long pc;
1335     int is_write;
1336
1337     pc = uc->uc_mcontext.arm_pc;
1338     /* XXX: compute is_write */
1339     is_write = 0;
1340     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1341                              is_write,
1342                              &uc->uc_sigmask, puc);
1343 }
1344
1345 #elif defined(__mc68000)
1346
1347 int cpu_signal_handler(int host_signum, void *pinfo,
1348                        void *puc)
1349 {
1350     siginfo_t *info = pinfo;
1351     struct ucontext *uc = puc;
1352     unsigned long pc;
1353     int is_write;
1354
1355     pc = uc->uc_mcontext.gregs[16];
1356     /* XXX: compute is_write */
1357     is_write = 0;
1358     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1359                              is_write,
1360                              &uc->uc_sigmask, puc);
1361 }
1362
1363 #elif defined(__ia64)
1364
1365 #ifndef __ISR_VALID
1366   /* This ought to be in <bits/siginfo.h>... */
1367 # define __ISR_VALID    1
1368 #endif
1369
1370 int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1371 {
1372     siginfo_t *info = pinfo;
1373     struct ucontext *uc = puc;
1374     unsigned long ip;
1375     int is_write = 0;
1376
1377     ip = uc->uc_mcontext.sc_ip;
1378     switch (host_signum) {
1379       case SIGILL:
1380       case SIGFPE:
1381       case SIGSEGV:
1382       case SIGBUS:
1383       case SIGTRAP:
1384           if (info->si_code && (info->si_segvflags & __ISR_VALID))
1385               /* ISR.W (write-access) is bit 33:  */
1386               is_write = (info->si_isr >> 33) & 1;
1387           break;
1388
1389       default:
1390           break;
1391     }
1392     return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1393                              is_write,
1394                              &uc->uc_sigmask, puc);
1395 }
1396
1397 #elif defined(__s390__)
1398
1399 int cpu_signal_handler(int host_signum, void *pinfo,
1400                        void *puc)
1401 {
1402     siginfo_t *info = pinfo;
1403     struct ucontext *uc = puc;
1404     unsigned long pc;
1405     int is_write;
1406
1407     pc = uc->uc_mcontext.psw.addr;
1408     /* XXX: compute is_write */
1409     is_write = 0;
1410     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1411                              is_write, &uc->uc_sigmask, puc);
1412 }
1413
1414 #elif defined(__mips__)
1415
1416 int cpu_signal_handler(int host_signum, void *pinfo,
1417                        void *puc)
1418 {
1419     siginfo_t *info = pinfo;
1420     struct ucontext *uc = puc;
1421     greg_t pc = uc->uc_mcontext.pc;
1422     int is_write;
1423
1424     /* XXX: compute is_write */
1425     is_write = 0;
1426     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1427                              is_write, &uc->uc_sigmask, puc);
1428 }
1429
1430 #elif defined(__hppa__)
1431
1432 int cpu_signal_handler(int host_signum, void *pinfo,
1433                        void *puc)
1434 {
1435     struct siginfo *info = pinfo;
1436     struct ucontext *uc = puc;
1437     unsigned long pc;
1438     int is_write;
1439
1440     pc = uc->uc_mcontext.sc_iaoq[0];
1441     /* FIXME: compute is_write */
1442     is_write = 0;
1443     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1444                              is_write,
1445                              &uc->uc_sigmask, puc);
1446 }
1447
1448 #else
1449
1450 #error host CPU specific signal handler needed
1451
1452 #endif
1453
1454 #endif /* !defined(CONFIG_SOFTMMU) */