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