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