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