]> Git Repo - qemu.git/blob - cpu-exec.c
siginfo fix for Darwin/Mac OS X, by Pierre d'Herbemont.
[qemu.git] / 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 #if defined(__sparc__) && !defined(HOST_SOLARIS)
539                         tmp_T0 = 0;
540 #else
541                         T0 = 0;
542 #endif
543                     }
544 #elif defined(TARGET_SPARC)
545                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&
546                         (env->psret != 0)) {
547                         int pil = env->interrupt_index & 15;
548                         int type = env->interrupt_index & 0xf0;
549
550                         if (((type == TT_EXTINT) &&
551                              (pil == 15 || pil > env->psrpil)) ||
552                             type != TT_EXTINT) {
553                             env->interrupt_request &= ~CPU_INTERRUPT_HARD;
554                             do_interrupt(env->interrupt_index);
555                             env->interrupt_index = 0;
556 #if defined(__sparc__) && !defined(HOST_SOLARIS)
557                             tmp_T0 = 0;
558 #else
559                             T0 = 0;
560 #endif
561                         }
562                     } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
563                         //do_interrupt(0, 0, 0, 0, 0);
564                         env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
565                     } else if (interrupt_request & CPU_INTERRUPT_HALT) {
566                         env->interrupt_request &= ~CPU_INTERRUPT_HALT;
567                         env->halted = 1;
568                         env->exception_index = EXCP_HLT;
569                         cpu_loop_exit();
570                     }
571 #elif defined(TARGET_ARM)
572                     if (interrupt_request & CPU_INTERRUPT_FIQ
573                         && !(env->uncached_cpsr & CPSR_F)) {
574                         env->exception_index = EXCP_FIQ;
575                         do_interrupt(env);
576                     }
577                     if (interrupt_request & CPU_INTERRUPT_HARD
578                         && !(env->uncached_cpsr & CPSR_I)) {
579                         env->exception_index = EXCP_IRQ;
580                         do_interrupt(env);
581                     }
582 #elif defined(TARGET_SH4)
583                     /* XXXXX */
584 #endif
585                    /* Don't use the cached interupt_request value,
586                       do_interrupt may have updated the EXITTB flag. */
587                     if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
588                         env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
589                         /* ensure that no TB jump will be modified as
590                            the program flow was changed */
591 #if defined(__sparc__) && !defined(HOST_SOLARIS)
592                         tmp_T0 = 0;
593 #else
594                         T0 = 0;
595 #endif
596                     }
597                     if (interrupt_request & CPU_INTERRUPT_EXIT) {
598                         env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
599                         env->exception_index = EXCP_INTERRUPT;
600                         cpu_loop_exit();
601                     }
602                 }
603 #ifdef DEBUG_EXEC
604                 if ((loglevel & CPU_LOG_TB_CPU)) {
605 #if defined(TARGET_I386)
606                     /* restore flags in standard format */
607 #ifdef reg_EAX
608                     env->regs[R_EAX] = EAX;
609 #endif
610 #ifdef reg_EBX
611                     env->regs[R_EBX] = EBX;
612 #endif
613 #ifdef reg_ECX
614                     env->regs[R_ECX] = ECX;
615 #endif
616 #ifdef reg_EDX
617                     env->regs[R_EDX] = EDX;
618 #endif
619 #ifdef reg_ESI
620                     env->regs[R_ESI] = ESI;
621 #endif
622 #ifdef reg_EDI
623                     env->regs[R_EDI] = EDI;
624 #endif
625 #ifdef reg_EBP
626                     env->regs[R_EBP] = EBP;
627 #endif
628 #ifdef reg_ESP
629                     env->regs[R_ESP] = ESP;
630 #endif
631                     env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
632                     cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
633                     env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
634 #elif defined(TARGET_ARM)
635                     cpu_dump_state(env, logfile, fprintf, 0);
636 #elif defined(TARGET_SPARC)
637                     REGWPTR = env->regbase + (env->cwp * 16);
638                     env->regwptr = REGWPTR;
639                     cpu_dump_state(env, logfile, fprintf, 0);
640 #elif defined(TARGET_PPC)
641                     cpu_dump_state(env, logfile, fprintf, 0);
642 #elif defined(TARGET_M68K)
643                     cpu_m68k_flush_flags(env, env->cc_op);
644                     env->cc_op = CC_OP_FLAGS;
645                     env->sr = (env->sr & 0xffe0)
646                               | env->cc_dest | (env->cc_x << 4);
647                     cpu_dump_state(env, logfile, fprintf, 0);
648 #elif defined(TARGET_MIPS)
649                     cpu_dump_state(env, logfile, fprintf, 0);
650 #elif defined(TARGET_SH4)
651                     cpu_dump_state(env, logfile, fprintf, 0);
652 #else
653 #error unsupported target CPU 
654 #endif
655                 }
656 #endif
657                 tb = tb_find_fast();
658 #ifdef DEBUG_EXEC
659                 if ((loglevel & CPU_LOG_EXEC)) {
660                     fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
661                             (long)tb->tc_ptr, tb->pc,
662                             lookup_symbol(tb->pc));
663                 }
664 #endif
665 #if defined(__sparc__) && !defined(HOST_SOLARIS)
666                 T0 = tmp_T0;
667 #endif      
668                 /* see if we can patch the calling TB. When the TB
669                    spans two pages, we cannot safely do a direct
670                    jump. */
671                 {
672                     if (T0 != 0 &&
673 #if USE_KQEMU
674                         (env->kqemu_enabled != 2) &&
675 #endif
676                         tb->page_addr[1] == -1
677 #if defined(TARGET_I386) && defined(USE_CODE_COPY)
678                     && (tb->cflags & CF_CODE_COPY) == 
679                     (((TranslationBlock *)(T0 & ~3))->cflags & CF_CODE_COPY)
680 #endif
681                     ) {
682                     spin_lock(&tb_lock);
683                     tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb);
684 #if defined(USE_CODE_COPY)
685                     /* propagates the FP use info */
686                     ((TranslationBlock *)(T0 & ~3))->cflags |= 
687                         (tb->cflags & CF_FP_USED);
688 #endif
689                     spin_unlock(&tb_lock);
690                 }
691                 }
692                 tc_ptr = tb->tc_ptr;
693                 env->current_tb = tb;
694                 /* execute the generated code */
695                 gen_func = (void *)tc_ptr;
696 #if defined(__sparc__)
697                 __asm__ __volatile__("call      %0\n\t"
698                                      "mov       %%o7,%%i0"
699                                      : /* no outputs */
700                                      : "r" (gen_func) 
701                                      : "i0", "i1", "i2", "i3", "i4", "i5",
702                                        "l0", "l1", "l2", "l3", "l4", "l5",
703                                        "l6", "l7");
704 #elif defined(__arm__)
705                 asm volatile ("mov pc, %0\n\t"
706                               ".global exec_loop\n\t"
707                               "exec_loop:\n\t"
708                               : /* no outputs */
709                               : "r" (gen_func)
710                               : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
711 #elif defined(TARGET_I386) && defined(USE_CODE_COPY)
712 {
713     if (!(tb->cflags & CF_CODE_COPY)) {
714         if ((tb->cflags & CF_FP_USED) && env->native_fp_regs) {
715             save_native_fp_state(env);
716         }
717         gen_func();
718     } else {
719         if ((tb->cflags & CF_FP_USED) && !env->native_fp_regs) {
720             restore_native_fp_state(env);
721         }
722         /* we work with native eflags */
723         CC_SRC = cc_table[CC_OP].compute_all();
724         CC_OP = CC_OP_EFLAGS;
725         asm(".globl exec_loop\n"
726             "\n"
727             "debug1:\n"
728             "    pushl %%ebp\n"
729             "    fs movl %10, %9\n"
730             "    fs movl %11, %%eax\n"
731             "    andl $0x400, %%eax\n"
732             "    fs orl %8, %%eax\n"
733             "    pushl %%eax\n"
734             "    popf\n"
735             "    fs movl %%esp, %12\n"
736             "    fs movl %0, %%eax\n"
737             "    fs movl %1, %%ecx\n"
738             "    fs movl %2, %%edx\n"
739             "    fs movl %3, %%ebx\n"
740             "    fs movl %4, %%esp\n"
741             "    fs movl %5, %%ebp\n"
742             "    fs movl %6, %%esi\n"
743             "    fs movl %7, %%edi\n"
744             "    fs jmp *%9\n"
745             "exec_loop:\n"
746             "    fs movl %%esp, %4\n"
747             "    fs movl %12, %%esp\n"
748             "    fs movl %%eax, %0\n"
749             "    fs movl %%ecx, %1\n"
750             "    fs movl %%edx, %2\n"
751             "    fs movl %%ebx, %3\n"
752             "    fs movl %%ebp, %5\n"
753             "    fs movl %%esi, %6\n"
754             "    fs movl %%edi, %7\n"
755             "    pushf\n"
756             "    popl %%eax\n"
757             "    movl %%eax, %%ecx\n"
758             "    andl $0x400, %%ecx\n"
759             "    shrl $9, %%ecx\n"
760             "    andl $0x8d5, %%eax\n"
761             "    fs movl %%eax, %8\n"
762             "    movl $1, %%eax\n"
763             "    subl %%ecx, %%eax\n"
764             "    fs movl %%eax, %11\n"
765             "    fs movl %9, %%ebx\n" /* get T0 value */
766             "    popl %%ebp\n"
767             :
768             : "m" (*(uint8_t *)offsetof(CPUState, regs[0])),
769             "m" (*(uint8_t *)offsetof(CPUState, regs[1])),
770             "m" (*(uint8_t *)offsetof(CPUState, regs[2])),
771             "m" (*(uint8_t *)offsetof(CPUState, regs[3])),
772             "m" (*(uint8_t *)offsetof(CPUState, regs[4])),
773             "m" (*(uint8_t *)offsetof(CPUState, regs[5])),
774             "m" (*(uint8_t *)offsetof(CPUState, regs[6])),
775             "m" (*(uint8_t *)offsetof(CPUState, regs[7])),
776             "m" (*(uint8_t *)offsetof(CPUState, cc_src)),
777             "m" (*(uint8_t *)offsetof(CPUState, tmp0)),
778             "a" (gen_func),
779             "m" (*(uint8_t *)offsetof(CPUState, df)),
780             "m" (*(uint8_t *)offsetof(CPUState, saved_esp))
781             : "%ecx", "%edx"
782             );
783     }
784 }
785 #elif defined(__ia64)
786                 struct fptr {
787                         void *ip;
788                         void *gp;
789                 } fp;
790
791                 fp.ip = tc_ptr;
792                 fp.gp = code_gen_buffer + 2 * (1 << 20);
793                 (*(void (*)(void)) &fp)();
794 #else
795                 gen_func();
796 #endif
797                 env->current_tb = NULL;
798                 /* reset soft MMU for next block (it can currently
799                    only be set by a memory fault) */
800 #if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU)
801                 if (env->hflags & HF_SOFTMMU_MASK) {
802                     env->hflags &= ~HF_SOFTMMU_MASK;
803                     /* do not allow linking to another block */
804                     T0 = 0;
805                 }
806 #endif
807 #if defined(USE_KQEMU)
808 #define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
809                 if (kqemu_is_ok(env) &&
810                     (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
811                     cpu_loop_exit();
812                 }
813 #endif
814             }
815         } else {
816             env_to_regs();
817         }
818     } /* for(;;) */
819
820
821 #if defined(TARGET_I386)
822 #if defined(USE_CODE_COPY)
823     if (env->native_fp_regs) {
824         save_native_fp_state(env);
825     }
826 #endif
827     /* restore flags in standard format */
828     env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
829
830     /* restore global registers */
831 #ifdef reg_EAX
832     EAX = saved_EAX;
833 #endif
834 #ifdef reg_ECX
835     ECX = saved_ECX;
836 #endif
837 #ifdef reg_EDX
838     EDX = saved_EDX;
839 #endif
840 #ifdef reg_EBX
841     EBX = saved_EBX;
842 #endif
843 #ifdef reg_ESP
844     ESP = saved_ESP;
845 #endif
846 #ifdef reg_EBP
847     EBP = saved_EBP;
848 #endif
849 #ifdef reg_ESI
850     ESI = saved_ESI;
851 #endif
852 #ifdef reg_EDI
853     EDI = saved_EDI;
854 #endif
855 #elif defined(TARGET_ARM)
856     /* XXX: Save/restore host fpu exception state?.  */
857 #elif defined(TARGET_SPARC)
858 #if defined(reg_REGWPTR)
859     REGWPTR = saved_regwptr;
860 #endif
861 #elif defined(TARGET_PPC)
862 #elif defined(TARGET_M68K)
863     cpu_m68k_flush_flags(env, env->cc_op);
864     env->cc_op = CC_OP_FLAGS;
865     env->sr = (env->sr & 0xffe0)
866               | env->cc_dest | (env->cc_x << 4);
867 #elif defined(TARGET_MIPS)
868 #elif defined(TARGET_SH4)
869     /* XXXXX */
870 #else
871 #error unsupported target CPU
872 #endif
873 #if defined(__sparc__) && !defined(HOST_SOLARIS)
874     asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
875 #endif
876     T0 = saved_T0;
877     T1 = saved_T1;
878 #if defined(reg_T2)
879     T2 = saved_T2;
880 #endif
881     env = saved_env;
882     /* fail safe : never use cpu_single_env outside cpu_exec() */
883     cpu_single_env = NULL; 
884     return ret;
885 }
886
887 /* must only be called from the generated code as an exception can be
888    generated */
889 void tb_invalidate_page_range(target_ulong start, target_ulong end)
890 {
891     /* XXX: cannot enable it yet because it yields to MMU exception
892        where NIP != read address on PowerPC */
893 #if 0
894     target_ulong phys_addr;
895     phys_addr = get_phys_addr_code(env, start);
896     tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
897 #endif
898 }
899
900 #if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
901
902 void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
903 {
904     CPUX86State *saved_env;
905
906     saved_env = env;
907     env = s;
908     if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
909         selector &= 0xffff;
910         cpu_x86_load_seg_cache(env, seg_reg, selector, 
911                                (selector << 4), 0xffff, 0);
912     } else {
913         load_seg(seg_reg, selector);
914     }
915     env = saved_env;
916 }
917
918 void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32)
919 {
920     CPUX86State *saved_env;
921
922     saved_env = env;
923     env = s;
924     
925     helper_fsave((target_ulong)ptr, data32);
926
927     env = saved_env;
928 }
929
930 void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32)
931 {
932     CPUX86State *saved_env;
933
934     saved_env = env;
935     env = s;
936     
937     helper_frstor((target_ulong)ptr, data32);
938
939     env = saved_env;
940 }
941
942 #endif /* TARGET_I386 */
943
944 #if !defined(CONFIG_SOFTMMU)
945
946 #if defined(TARGET_I386)
947
948 /* 'pc' is the host PC at which the exception was raised. 'address' is
949    the effective address of the memory exception. 'is_write' is 1 if a
950    write caused the exception and otherwise 0'. 'old_set' is the
951    signal set which should be restored */
952 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
953                                     int is_write, sigset_t *old_set, 
954                                     void *puc)
955 {
956     TranslationBlock *tb;
957     int ret;
958
959     if (cpu_single_env)
960         env = cpu_single_env; /* XXX: find a correct solution for multithread */
961 #if defined(DEBUG_SIGNAL)
962     qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
963                 pc, address, is_write, *(unsigned long *)old_set);
964 #endif
965     /* XXX: locking issue */
966     if (is_write && page_unprotect(h2g(address), pc, puc)) {
967         return 1;
968     }
969
970     /* see if it is an MMU fault */
971     ret = cpu_x86_handle_mmu_fault(env, address, is_write, 
972                                    ((env->hflags & HF_CPL_MASK) == 3), 0);
973     if (ret < 0)
974         return 0; /* not an MMU fault */
975     if (ret == 0)
976         return 1; /* the MMU fault was handled without causing real CPU fault */
977     /* now we have a real cpu fault */
978     tb = tb_find_pc(pc);
979     if (tb) {
980         /* the PC is inside the translated code. It means that we have
981            a virtual CPU fault */
982         cpu_restore_state(tb, env, pc, puc);
983     }
984     if (ret == 1) {
985 #if 0
986         printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n", 
987                env->eip, env->cr[2], env->error_code);
988 #endif
989         /* we restore the process signal mask as the sigreturn should
990            do it (XXX: use sigsetjmp) */
991         sigprocmask(SIG_SETMASK, old_set, NULL);
992         raise_exception_err(env->exception_index, env->error_code);
993     } else {
994         /* activate soft MMU for this block */
995         env->hflags |= HF_SOFTMMU_MASK;
996         cpu_resume_from_signal(env, puc);
997     }
998     /* never comes here */
999     return 1;
1000 }
1001
1002 #elif defined(TARGET_ARM)
1003 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1004                                     int is_write, sigset_t *old_set,
1005                                     void *puc)
1006 {
1007     TranslationBlock *tb;
1008     int ret;
1009
1010     if (cpu_single_env)
1011         env = cpu_single_env; /* XXX: find a correct solution for multithread */
1012 #if defined(DEBUG_SIGNAL)
1013     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
1014            pc, address, is_write, *(unsigned long *)old_set);
1015 #endif
1016     /* XXX: locking issue */
1017     if (is_write && page_unprotect(h2g(address), pc, puc)) {
1018         return 1;
1019     }
1020     /* see if it is an MMU fault */
1021     ret = cpu_arm_handle_mmu_fault(env, address, is_write, 1, 0);
1022     if (ret < 0)
1023         return 0; /* not an MMU fault */
1024     if (ret == 0)
1025         return 1; /* the MMU fault was handled without causing real CPU fault */
1026     /* now we have a real cpu fault */
1027     tb = tb_find_pc(pc);
1028     if (tb) {
1029         /* the PC is inside the translated code. It means that we have
1030            a virtual CPU fault */
1031         cpu_restore_state(tb, env, pc, puc);
1032     }
1033     /* we restore the process signal mask as the sigreturn should
1034        do it (XXX: use sigsetjmp) */
1035     sigprocmask(SIG_SETMASK, old_set, NULL);
1036     cpu_loop_exit();
1037 }
1038 #elif defined(TARGET_SPARC)
1039 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1040                                     int is_write, sigset_t *old_set,
1041                                     void *puc)
1042 {
1043     TranslationBlock *tb;
1044     int ret;
1045
1046     if (cpu_single_env)
1047         env = cpu_single_env; /* XXX: find a correct solution for multithread */
1048 #if defined(DEBUG_SIGNAL)
1049     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
1050            pc, address, is_write, *(unsigned long *)old_set);
1051 #endif
1052     /* XXX: locking issue */
1053     if (is_write && page_unprotect(h2g(address), pc, puc)) {
1054         return 1;
1055     }
1056     /* see if it is an MMU fault */
1057     ret = cpu_sparc_handle_mmu_fault(env, address, is_write, 1, 0);
1058     if (ret < 0)
1059         return 0; /* not an MMU fault */
1060     if (ret == 0)
1061         return 1; /* the MMU fault was handled without causing real CPU fault */
1062     /* now we have a real cpu fault */
1063     tb = tb_find_pc(pc);
1064     if (tb) {
1065         /* the PC is inside the translated code. It means that we have
1066            a virtual CPU fault */
1067         cpu_restore_state(tb, env, pc, puc);
1068     }
1069     /* we restore the process signal mask as the sigreturn should
1070        do it (XXX: use sigsetjmp) */
1071     sigprocmask(SIG_SETMASK, old_set, NULL);
1072     cpu_loop_exit();
1073 }
1074 #elif defined (TARGET_PPC)
1075 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1076                                     int is_write, sigset_t *old_set,
1077                                     void *puc)
1078 {
1079     TranslationBlock *tb;
1080     int ret;
1081     
1082     if (cpu_single_env)
1083         env = cpu_single_env; /* XXX: find a correct solution for multithread */
1084 #if defined(DEBUG_SIGNAL)
1085     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
1086            pc, address, is_write, *(unsigned long *)old_set);
1087 #endif
1088     /* XXX: locking issue */
1089     if (is_write && page_unprotect(h2g(address), pc, puc)) {
1090         return 1;
1091     }
1092
1093     /* see if it is an MMU fault */
1094     ret = cpu_ppc_handle_mmu_fault(env, address, is_write, msr_pr, 0);
1095     if (ret < 0)
1096         return 0; /* not an MMU fault */
1097     if (ret == 0)
1098         return 1; /* the MMU fault was handled without causing real CPU fault */
1099
1100     /* now we have a real cpu fault */
1101     tb = tb_find_pc(pc);
1102     if (tb) {
1103         /* the PC is inside the translated code. It means that we have
1104            a virtual CPU fault */
1105         cpu_restore_state(tb, env, pc, puc);
1106     }
1107     if (ret == 1) {
1108 #if 0
1109         printf("PF exception: NIP=0x%08x error=0x%x %p\n", 
1110                env->nip, env->error_code, tb);
1111 #endif
1112     /* we restore the process signal mask as the sigreturn should
1113        do it (XXX: use sigsetjmp) */
1114         sigprocmask(SIG_SETMASK, old_set, NULL);
1115         do_raise_exception_err(env->exception_index, env->error_code);
1116     } else {
1117         /* activate soft MMU for this block */
1118         cpu_resume_from_signal(env, puc);
1119     }
1120     /* never comes here */
1121     return 1;
1122 }
1123
1124 #elif defined(TARGET_M68K)
1125 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1126                                     int is_write, sigset_t *old_set,
1127                                     void *puc)
1128 {
1129     TranslationBlock *tb;
1130     int ret;
1131
1132     if (cpu_single_env)
1133         env = cpu_single_env; /* XXX: find a correct solution for multithread */
1134 #if defined(DEBUG_SIGNAL)
1135     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
1136            pc, address, is_write, *(unsigned long *)old_set);
1137 #endif
1138     /* XXX: locking issue */
1139     if (is_write && page_unprotect(address, pc, puc)) {
1140         return 1;
1141     }
1142     /* see if it is an MMU fault */
1143     ret = cpu_m68k_handle_mmu_fault(env, address, is_write, 1, 0);
1144     if (ret < 0)
1145         return 0; /* not an MMU fault */
1146     if (ret == 0)
1147         return 1; /* the MMU fault was handled without causing real CPU fault */
1148     /* now we have a real cpu fault */
1149     tb = tb_find_pc(pc);
1150     if (tb) {
1151         /* the PC is inside the translated code. It means that we have
1152            a virtual CPU fault */
1153         cpu_restore_state(tb, env, pc, puc);
1154     }
1155     /* we restore the process signal mask as the sigreturn should
1156        do it (XXX: use sigsetjmp) */
1157     sigprocmask(SIG_SETMASK, old_set, NULL);
1158     cpu_loop_exit();
1159     /* never comes here */
1160     return 1;
1161 }
1162
1163 #elif defined (TARGET_MIPS)
1164 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1165                                     int is_write, sigset_t *old_set,
1166                                     void *puc)
1167 {
1168     TranslationBlock *tb;
1169     int ret;
1170     
1171     if (cpu_single_env)
1172         env = cpu_single_env; /* XXX: find a correct solution for multithread */
1173 #if defined(DEBUG_SIGNAL)
1174     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
1175            pc, address, is_write, *(unsigned long *)old_set);
1176 #endif
1177     /* XXX: locking issue */
1178     if (is_write && page_unprotect(h2g(address), pc, puc)) {
1179         return 1;
1180     }
1181
1182     /* see if it is an MMU fault */
1183     ret = cpu_mips_handle_mmu_fault(env, address, is_write, 1, 0);
1184     if (ret < 0)
1185         return 0; /* not an MMU fault */
1186     if (ret == 0)
1187         return 1; /* the MMU fault was handled without causing real CPU fault */
1188
1189     /* now we have a real cpu fault */
1190     tb = tb_find_pc(pc);
1191     if (tb) {
1192         /* the PC is inside the translated code. It means that we have
1193            a virtual CPU fault */
1194         cpu_restore_state(tb, env, pc, puc);
1195     }
1196     if (ret == 1) {
1197 #if 0
1198         printf("PF exception: NIP=0x%08x error=0x%x %p\n", 
1199                env->nip, env->error_code, tb);
1200 #endif
1201     /* we restore the process signal mask as the sigreturn should
1202        do it (XXX: use sigsetjmp) */
1203         sigprocmask(SIG_SETMASK, old_set, NULL);
1204         do_raise_exception_err(env->exception_index, env->error_code);
1205     } else {
1206         /* activate soft MMU for this block */
1207         cpu_resume_from_signal(env, puc);
1208     }
1209     /* never comes here */
1210     return 1;
1211 }
1212
1213 #elif defined (TARGET_SH4)
1214 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1215                                     int is_write, sigset_t *old_set,
1216                                     void *puc)
1217 {
1218     TranslationBlock *tb;
1219     int ret;
1220     
1221     if (cpu_single_env)
1222         env = cpu_single_env; /* XXX: find a correct solution for multithread */
1223 #if defined(DEBUG_SIGNAL)
1224     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
1225            pc, address, is_write, *(unsigned long *)old_set);
1226 #endif
1227     /* XXX: locking issue */
1228     if (is_write && page_unprotect(h2g(address), pc, puc)) {
1229         return 1;
1230     }
1231
1232     /* see if it is an MMU fault */
1233     ret = cpu_sh4_handle_mmu_fault(env, address, is_write, 1, 0);
1234     if (ret < 0)
1235         return 0; /* not an MMU fault */
1236     if (ret == 0)
1237         return 1; /* the MMU fault was handled without causing real CPU fault */
1238
1239     /* now we have a real cpu fault */
1240     tb = tb_find_pc(pc);
1241     if (tb) {
1242         /* the PC is inside the translated code. It means that we have
1243            a virtual CPU fault */
1244         cpu_restore_state(tb, env, pc, puc);
1245     }
1246 #if 0
1247         printf("PF exception: NIP=0x%08x error=0x%x %p\n", 
1248                env->nip, env->error_code, tb);
1249 #endif
1250     /* we restore the process signal mask as the sigreturn should
1251        do it (XXX: use sigsetjmp) */
1252     sigprocmask(SIG_SETMASK, old_set, NULL);
1253     cpu_loop_exit();
1254     /* never comes here */
1255     return 1;
1256 }
1257 #else
1258 #error unsupported target CPU
1259 #endif
1260
1261 #if defined(__i386__)
1262
1263 #if defined(USE_CODE_COPY)
1264 static void cpu_send_trap(unsigned long pc, int trap, 
1265                           struct ucontext *uc)
1266 {
1267     TranslationBlock *tb;
1268
1269     if (cpu_single_env)
1270         env = cpu_single_env; /* XXX: find a correct solution for multithread */
1271     /* now we have a real cpu fault */
1272     tb = tb_find_pc(pc);
1273     if (tb) {
1274         /* the PC is inside the translated code. It means that we have
1275            a virtual CPU fault */
1276         cpu_restore_state(tb, env, pc, uc);
1277     }
1278     sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
1279     raise_exception_err(trap, env->error_code);
1280 }
1281 #endif
1282
1283 int cpu_signal_handler(int host_signum, void *pinfo, 
1284                        void *puc)
1285 {
1286     siginfo_t *info = pinfo;
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, void *pinfo,
1315                        void *puc)
1316 {
1317     siginfo_t *info = pinfo;
1318     struct ucontext *uc = puc;
1319     unsigned long pc;
1320
1321     pc = uc->uc_mcontext.gregs[REG_RIP];
1322     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1323                              uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ? 
1324                              (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1325                              &uc->uc_sigmask, puc);
1326 }
1327
1328 #elif defined(__powerpc__)
1329
1330 /***********************************************************************
1331  * signal context platform-specific definitions
1332  * From Wine
1333  */
1334 #ifdef linux
1335 /* All Registers access - only for local access */
1336 # define REG_sig(reg_name, context)             ((context)->uc_mcontext.regs->reg_name)
1337 /* Gpr Registers access  */
1338 # define GPR_sig(reg_num, context)              REG_sig(gpr[reg_num], context)
1339 # define IAR_sig(context)                       REG_sig(nip, context)   /* Program counter */
1340 # define MSR_sig(context)                       REG_sig(msr, context)   /* Machine State Register (Supervisor) */
1341 # define CTR_sig(context)                       REG_sig(ctr, context)   /* Count register */
1342 # define XER_sig(context)                       REG_sig(xer, context) /* User's integer exception register */
1343 # define LR_sig(context)                        REG_sig(link, context) /* Link register */
1344 # define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
1345 /* Float Registers access  */
1346 # define FLOAT_sig(reg_num, context)            (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1347 # define FPSCR_sig(context)                     (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1348 /* Exception Registers access */
1349 # define DAR_sig(context)                       REG_sig(dar, context)
1350 # define DSISR_sig(context)                     REG_sig(dsisr, context)
1351 # define TRAP_sig(context)                      REG_sig(trap, context)
1352 #endif /* linux */
1353
1354 #ifdef __APPLE__
1355 # include <sys/ucontext.h>
1356 typedef struct ucontext SIGCONTEXT;
1357 /* All Registers access - only for local access */
1358 # define REG_sig(reg_name, context)             ((context)->uc_mcontext->ss.reg_name)
1359 # define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
1360 # define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
1361 # define VECREG_sig(reg_name, context)          ((context)->uc_mcontext->vs.reg_name)
1362 /* Gpr Registers access */
1363 # define GPR_sig(reg_num, context)              REG_sig(r##reg_num, context)
1364 # define IAR_sig(context)                       REG_sig(srr0, context)  /* Program counter */
1365 # define MSR_sig(context)                       REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
1366 # define CTR_sig(context)                       REG_sig(ctr, context)
1367 # define XER_sig(context)                       REG_sig(xer, context) /* Link register */
1368 # define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
1369 # define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
1370 /* Float Registers access */
1371 # define FLOAT_sig(reg_num, context)            FLOATREG_sig(fpregs[reg_num], context)
1372 # define FPSCR_sig(context)                     ((double)FLOATREG_sig(fpscr, context))
1373 /* Exception Registers access */
1374 # define DAR_sig(context)                       EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
1375 # define DSISR_sig(context)                     EXCEPREG_sig(dsisr, context)
1376 # define TRAP_sig(context)                      EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1377 #endif /* __APPLE__ */
1378
1379 int cpu_signal_handler(int host_signum, void *pinfo, 
1380                        void *puc)
1381 {
1382     siginfo_t *info = pinfo;
1383     struct ucontext *uc = puc;
1384     unsigned long pc;
1385     int is_write;
1386
1387     pc = IAR_sig(uc);
1388     is_write = 0;
1389 #if 0
1390     /* ppc 4xx case */
1391     if (DSISR_sig(uc) & 0x00800000)
1392         is_write = 1;
1393 #else
1394     if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1395         is_write = 1;
1396 #endif
1397     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1398                              is_write, &uc->uc_sigmask, puc);
1399 }
1400
1401 #elif defined(__alpha__)
1402
1403 int cpu_signal_handler(int host_signum, void *pinfo, 
1404                            void *puc)
1405 {
1406     siginfo_t *info = pinfo;
1407     struct ucontext *uc = puc;
1408     uint32_t *pc = uc->uc_mcontext.sc_pc;
1409     uint32_t insn = *pc;
1410     int is_write = 0;
1411
1412     /* XXX: need kernel patch to get write flag faster */
1413     switch (insn >> 26) {
1414     case 0x0d: // stw
1415     case 0x0e: // stb
1416     case 0x0f: // stq_u
1417     case 0x24: // stf
1418     case 0x25: // stg
1419     case 0x26: // sts
1420     case 0x27: // stt
1421     case 0x2c: // stl
1422     case 0x2d: // stq
1423     case 0x2e: // stl_c
1424     case 0x2f: // stq_c
1425         is_write = 1;
1426     }
1427
1428     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1429                              is_write, &uc->uc_sigmask, puc);
1430 }
1431 #elif defined(__sparc__)
1432
1433 int cpu_signal_handler(int host_signum, void *pinfo, 
1434                        void *puc)
1435 {
1436     siginfo_t *info = pinfo;
1437     uint32_t *regs = (uint32_t *)(info + 1);
1438     void *sigmask = (regs + 20);
1439     unsigned long pc;
1440     int is_write;
1441     uint32_t insn;
1442     
1443     /* XXX: is there a standard glibc define ? */
1444     pc = regs[1];
1445     /* XXX: need kernel patch to get write flag faster */
1446     is_write = 0;
1447     insn = *(uint32_t *)pc;
1448     if ((insn >> 30) == 3) {
1449       switch((insn >> 19) & 0x3f) {
1450       case 0x05: // stb
1451       case 0x06: // sth
1452       case 0x04: // st
1453       case 0x07: // std
1454       case 0x24: // stf
1455       case 0x27: // stdf
1456       case 0x25: // stfsr
1457         is_write = 1;
1458         break;
1459       }
1460     }
1461     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1462                              is_write, sigmask, NULL);
1463 }
1464
1465 #elif defined(__arm__)
1466
1467 int cpu_signal_handler(int host_signum, void *pinfo, 
1468                        void *puc)
1469 {
1470     siginfo_t *info = pinfo;
1471     struct ucontext *uc = puc;
1472     unsigned long pc;
1473     int is_write;
1474     
1475     pc = uc->uc_mcontext.gregs[R15];
1476     /* XXX: compute is_write */
1477     is_write = 0;
1478     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1479                              is_write,
1480                              &uc->uc_sigmask, puc);
1481 }
1482
1483 #elif defined(__mc68000)
1484
1485 int cpu_signal_handler(int host_signum, void *pinfo, 
1486                        void *puc)
1487 {
1488     siginfo_t *info = pinfo;
1489     struct ucontext *uc = puc;
1490     unsigned long pc;
1491     int is_write;
1492     
1493     pc = uc->uc_mcontext.gregs[16];
1494     /* XXX: compute is_write */
1495     is_write = 0;
1496     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1497                              is_write,
1498                              &uc->uc_sigmask, puc);
1499 }
1500
1501 #elif defined(__ia64)
1502
1503 #ifndef __ISR_VALID
1504   /* This ought to be in <bits/siginfo.h>... */
1505 # define __ISR_VALID    1
1506 #endif
1507
1508 int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1509 {
1510     siginfo_t *info = pinfo;
1511     struct ucontext *uc = puc;
1512     unsigned long ip;
1513     int is_write = 0;
1514
1515     ip = uc->uc_mcontext.sc_ip;
1516     switch (host_signum) {
1517       case SIGILL:
1518       case SIGFPE:
1519       case SIGSEGV:
1520       case SIGBUS:
1521       case SIGTRAP:
1522           if (info->si_code && (info->si_segvflags & __ISR_VALID))
1523               /* ISR.W (write-access) is bit 33:  */
1524               is_write = (info->si_isr >> 33) & 1;
1525           break;
1526
1527       default:
1528           break;
1529     }
1530     return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1531                              is_write,
1532                              &uc->uc_sigmask, puc);
1533 }
1534
1535 #elif defined(__s390__)
1536
1537 int cpu_signal_handler(int host_signum, void *pinfo, 
1538                        void *puc)
1539 {
1540     siginfo_t *info = pinfo;
1541     struct ucontext *uc = puc;
1542     unsigned long pc;
1543     int is_write;
1544     
1545     pc = uc->uc_mcontext.psw.addr;
1546     /* XXX: compute is_write */
1547     is_write = 0;
1548     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1549                              is_write,
1550                              &uc->uc_sigmask, puc);
1551 }
1552
1553 #else
1554
1555 #error host CPU specific signal handler needed
1556
1557 #endif
1558
1559 #endif /* !defined(CONFIG_SOFTMMU) */
This page took 0.110741 seconds and 4 git commands to generate.