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