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