Use target_ulong type for emulator registers.
[sdk/emulator/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     target_ulong saved_T0, saved_T1;
230 #if defined(reg_T2)
231     target_ulong 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;
266     target_ulong tmp_T0;
267 #endif
268     int ret, interrupt_request;
269     void (*gen_func)(void);
270     TranslationBlock *tb;
271     uint8_t *tc_ptr;
272
273 #if defined(TARGET_I386)
274     /* handle exit of HALTED state */
275     if (env1->hflags & HF_HALTED_MASK) {
276         /* disable halt condition */
277         if ((env1->interrupt_request & CPU_INTERRUPT_HARD) &&
278             (env1->eflags & IF_MASK)) {
279             env1->hflags &= ~HF_HALTED_MASK;
280         } else {
281             return EXCP_HALTED;
282         }
283     }
284 #elif defined(TARGET_PPC)
285     if (env1->halted) {
286         if (env1->msr[MSR_EE] && 
287             (env1->interrupt_request & 
288              (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER))) {
289             env1->halted = 0;
290         } else {
291             return EXCP_HALTED;
292         }
293     }
294 #elif defined(TARGET_SPARC)
295     if (env1->halted) {
296         if ((env1->interrupt_request & CPU_INTERRUPT_HARD) &&
297             (env1->psret != 0)) {
298             env1->halted = 0;
299         } else {
300             return EXCP_HALTED;
301         }
302     }
303 #elif defined(TARGET_ARM)
304     if (env1->halted) {
305         /* An interrupt wakes the CPU even if the I and F CPSR bits are
306            set.  */
307         if (env1->interrupt_request
308             & (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD)) {
309             env1->halted = 0;
310         } else {
311             return EXCP_HALTED;
312         }
313     }
314 #elif defined(TARGET_MIPS)
315     if (env1->halted) {
316         if (env1->interrupt_request &
317             (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER)) {
318             env1->halted = 0;
319         } else {
320             return EXCP_HALTED;
321         }
322     }
323 #endif
324
325     cpu_single_env = env1; 
326
327     /* first we save global registers */
328     saved_env = env;
329     env = env1;
330     saved_T0 = T0;
331     saved_T1 = T1;
332 #if defined(reg_T2)
333     saved_T2 = T2;
334 #endif
335 #if defined(__sparc__) && !defined(HOST_SOLARIS)
336     /* we also save i7 because longjmp may not restore it */
337     asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
338 #endif
339
340 #if defined(TARGET_I386)
341 #ifdef reg_EAX
342     saved_EAX = EAX;
343 #endif
344 #ifdef reg_ECX
345     saved_ECX = ECX;
346 #endif
347 #ifdef reg_EDX
348     saved_EDX = EDX;
349 #endif
350 #ifdef reg_EBX
351     saved_EBX = EBX;
352 #endif
353 #ifdef reg_ESP
354     saved_ESP = ESP;
355 #endif
356 #ifdef reg_EBP
357     saved_EBP = EBP;
358 #endif
359 #ifdef reg_ESI
360     saved_ESI = ESI;
361 #endif
362 #ifdef reg_EDI
363     saved_EDI = EDI;
364 #endif
365
366     env_to_regs();
367     /* put eflags in CPU temporary format */
368     CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
369     DF = 1 - (2 * ((env->eflags >> 10) & 1));
370     CC_OP = CC_OP_EFLAGS;
371     env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
372 #elif defined(TARGET_ARM)
373 #elif defined(TARGET_SPARC)
374 #if defined(reg_REGWPTR)
375     saved_regwptr = REGWPTR;
376 #endif
377 #elif defined(TARGET_PPC)
378 #elif defined(TARGET_M68K)
379     env->cc_op = CC_OP_FLAGS;
380     env->cc_dest = env->sr & 0xf;
381     env->cc_x = (env->sr >> 4) & 1;
382 #elif defined(TARGET_MIPS)
383 #elif defined(TARGET_SH4)
384     /* XXXXX */
385 #else
386 #error unsupported target CPU
387 #endif
388     env->exception_index = -1;
389
390     /* prepare setjmp context for exception handling */
391     for(;;) {
392         if (setjmp(env->jmp_env) == 0) {
393             env->current_tb = NULL;
394             /* if an exception is pending, we execute it here */
395             if (env->exception_index >= 0) {
396                 if (env->exception_index >= EXCP_INTERRUPT) {
397                     /* exit request from the cpu execution loop */
398                     ret = env->exception_index;
399                     break;
400                 } else if (env->user_mode_only) {
401                     /* if user mode only, we simulate a fake exception
402                        which will be handled outside the cpu execution
403                        loop */
404 #if defined(TARGET_I386)
405                     do_interrupt_user(env->exception_index, 
406                                       env->exception_is_int, 
407                                       env->error_code, 
408                                       env->exception_next_eip);
409 #endif
410                     ret = env->exception_index;
411                     break;
412                 } else {
413 #if defined(TARGET_I386)
414                     /* simulate a real cpu exception. On i386, it can
415                        trigger new exceptions, but we do not handle
416                        double or triple faults yet. */
417                     do_interrupt(env->exception_index, 
418                                  env->exception_is_int, 
419                                  env->error_code, 
420                                  env->exception_next_eip, 0);
421 #elif defined(TARGET_PPC)
422                     do_interrupt(env);
423 #elif defined(TARGET_MIPS)
424                     do_interrupt(env);
425 #elif defined(TARGET_SPARC)
426                     do_interrupt(env->exception_index);
427 #elif defined(TARGET_ARM)
428                     do_interrupt(env);
429 #elif defined(TARGET_SH4)
430                     do_interrupt(env);
431 #endif
432                 }
433                 env->exception_index = -1;
434             } 
435 #ifdef USE_KQEMU
436             if (kqemu_is_ok(env) && env->interrupt_request == 0) {
437                 int ret;
438                 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
439                 ret = kqemu_cpu_exec(env);
440                 /* put eflags in CPU temporary format */
441                 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
442                 DF = 1 - (2 * ((env->eflags >> 10) & 1));
443                 CC_OP = CC_OP_EFLAGS;
444                 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
445                 if (ret == 1) {
446                     /* exception */
447                     longjmp(env->jmp_env, 1);
448                 } else if (ret == 2) {
449                     /* softmmu execution needed */
450                 } else {
451                     if (env->interrupt_request != 0) {
452                         /* hardware interrupt will be executed just after */
453                     } else {
454                         /* otherwise, we restart */
455                         longjmp(env->jmp_env, 1);
456                     }
457                 }
458             }
459 #endif
460
461             T0 = 0; /* force lookup of first TB */
462             for(;;) {
463 #if defined(__sparc__) && !defined(HOST_SOLARIS)
464                 /* g1 can be modified by some libc? functions */ 
465                 tmp_T0 = T0;
466 #endif      
467                 interrupt_request = env->interrupt_request;
468                 if (__builtin_expect(interrupt_request, 0)) {
469 #if defined(TARGET_I386)
470                     if ((interrupt_request & CPU_INTERRUPT_SMI) &&
471                         !(env->hflags & HF_SMM_MASK)) {
472                         env->interrupt_request &= ~CPU_INTERRUPT_SMI;
473                         do_smm_enter();
474 #if defined(__sparc__) && !defined(HOST_SOLARIS)
475                         tmp_T0 = 0;
476 #else
477                         T0 = 0;
478 #endif
479                     } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
480                         (env->eflags & IF_MASK) && 
481                         !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
482                         int intno;
483                         env->interrupt_request &= ~CPU_INTERRUPT_HARD;
484                         intno = cpu_get_pic_interrupt(env);
485                         if (loglevel & CPU_LOG_TB_IN_ASM) {
486                             fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
487                         }
488                         do_interrupt(intno, 0, 0, 0, 1);
489                         /* ensure that no TB jump will be modified as
490                            the program flow was changed */
491 #if defined(__sparc__) && !defined(HOST_SOLARIS)
492                         tmp_T0 = 0;
493 #else
494                         T0 = 0;
495 #endif
496                     }
497 #elif defined(TARGET_PPC)
498 #if 0
499                     if ((interrupt_request & CPU_INTERRUPT_RESET)) {
500                         cpu_ppc_reset(env);
501                     }
502 #endif
503                     if (msr_ee != 0) {
504                         if ((interrupt_request & CPU_INTERRUPT_HARD)) {
505                             /* Raise it */
506                             env->exception_index = EXCP_EXTERNAL;
507                             env->error_code = 0;
508                             do_interrupt(env);
509                             env->interrupt_request &= ~CPU_INTERRUPT_HARD;
510 #if defined(__sparc__) && !defined(HOST_SOLARIS)
511                             tmp_T0 = 0;
512 #else
513                             T0 = 0;
514 #endif
515                         } else if ((interrupt_request & CPU_INTERRUPT_TIMER)) {
516                             /* Raise it */
517                             env->exception_index = EXCP_DECR;
518                             env->error_code = 0;
519                             do_interrupt(env);
520                             env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
521 #if defined(__sparc__) && !defined(HOST_SOLARIS)
522                             tmp_T0 = 0;
523 #else
524                             T0 = 0;
525 #endif
526                         }
527                     }
528 #elif defined(TARGET_MIPS)
529                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&
530                         (env->CP0_Status & (1 << CP0St_IE)) &&
531                         (env->CP0_Status & env->CP0_Cause & 0x0000FF00) &&
532                         !(env->hflags & MIPS_HFLAG_EXL) &&
533                         !(env->hflags & MIPS_HFLAG_ERL) &&
534                         !(env->hflags & MIPS_HFLAG_DM)) {
535                         /* Raise it */
536                         env->exception_index = EXCP_EXT_INTERRUPT;
537                         env->error_code = 0;
538                         do_interrupt(env);
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, void *pinfo, 
1285                        void *puc)
1286 {
1287     siginfo_t *info = pinfo;
1288     struct ucontext *uc = puc;
1289     unsigned long pc;
1290     int trapno;
1291
1292 #ifndef REG_EIP
1293 /* for glibc 2.1 */
1294 #define REG_EIP    EIP
1295 #define REG_ERR    ERR
1296 #define REG_TRAPNO TRAPNO
1297 #endif
1298     pc = uc->uc_mcontext.gregs[REG_EIP];
1299     trapno = uc->uc_mcontext.gregs[REG_TRAPNO];
1300 #if defined(TARGET_I386) && defined(USE_CODE_COPY)
1301     if (trapno == 0x00 || trapno == 0x05) {
1302         /* send division by zero or bound exception */
1303         cpu_send_trap(pc, trapno, uc);
1304         return 1;
1305     } else
1306 #endif
1307         return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1308                                  trapno == 0xe ? 
1309                                  (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1310                                  &uc->uc_sigmask, puc);
1311 }
1312
1313 #elif defined(__x86_64__)
1314
1315 int cpu_signal_handler(int host_signum, void *pinfo,
1316                        void *puc)
1317 {
1318     siginfo_t *info = pinfo;
1319     struct ucontext *uc = puc;
1320     unsigned long pc;
1321
1322     pc = uc->uc_mcontext.gregs[REG_RIP];
1323     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1324                              uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ? 
1325                              (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1326                              &uc->uc_sigmask, puc);
1327 }
1328
1329 #elif defined(__powerpc__)
1330
1331 /***********************************************************************
1332  * signal context platform-specific definitions
1333  * From Wine
1334  */
1335 #ifdef linux
1336 /* All Registers access - only for local access */
1337 # define REG_sig(reg_name, context)             ((context)->uc_mcontext.regs->reg_name)
1338 /* Gpr Registers access  */
1339 # define GPR_sig(reg_num, context)              REG_sig(gpr[reg_num], context)
1340 # define IAR_sig(context)                       REG_sig(nip, context)   /* Program counter */
1341 # define MSR_sig(context)                       REG_sig(msr, context)   /* Machine State Register (Supervisor) */
1342 # define CTR_sig(context)                       REG_sig(ctr, context)   /* Count register */
1343 # define XER_sig(context)                       REG_sig(xer, context) /* User's integer exception register */
1344 # define LR_sig(context)                        REG_sig(link, context) /* Link register */
1345 # define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
1346 /* Float Registers access  */
1347 # define FLOAT_sig(reg_num, context)            (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1348 # define FPSCR_sig(context)                     (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1349 /* Exception Registers access */
1350 # define DAR_sig(context)                       REG_sig(dar, context)
1351 # define DSISR_sig(context)                     REG_sig(dsisr, context)
1352 # define TRAP_sig(context)                      REG_sig(trap, context)
1353 #endif /* linux */
1354
1355 #ifdef __APPLE__
1356 # include <sys/ucontext.h>
1357 typedef struct ucontext SIGCONTEXT;
1358 /* All Registers access - only for local access */
1359 # define REG_sig(reg_name, context)             ((context)->uc_mcontext->ss.reg_name)
1360 # define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
1361 # define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
1362 # define VECREG_sig(reg_name, context)          ((context)->uc_mcontext->vs.reg_name)
1363 /* Gpr Registers access */
1364 # define GPR_sig(reg_num, context)              REG_sig(r##reg_num, context)
1365 # define IAR_sig(context)                       REG_sig(srr0, context)  /* Program counter */
1366 # define MSR_sig(context)                       REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
1367 # define CTR_sig(context)                       REG_sig(ctr, context)
1368 # define XER_sig(context)                       REG_sig(xer, context) /* Link register */
1369 # define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
1370 # define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
1371 /* Float Registers access */
1372 # define FLOAT_sig(reg_num, context)            FLOATREG_sig(fpregs[reg_num], context)
1373 # define FPSCR_sig(context)                     ((double)FLOATREG_sig(fpscr, context))
1374 /* Exception Registers access */
1375 # define DAR_sig(context)                       EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
1376 # define DSISR_sig(context)                     EXCEPREG_sig(dsisr, context)
1377 # define TRAP_sig(context)                      EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1378 #endif /* __APPLE__ */
1379
1380 int cpu_signal_handler(int host_signum, void *pinfo, 
1381                        void *puc)
1382 {
1383     siginfo_t *info = pinfo;
1384     struct ucontext *uc = puc;
1385     unsigned long pc;
1386     int is_write;
1387
1388     pc = IAR_sig(uc);
1389     is_write = 0;
1390 #if 0
1391     /* ppc 4xx case */
1392     if (DSISR_sig(uc) & 0x00800000)
1393         is_write = 1;
1394 #else
1395     if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1396         is_write = 1;
1397 #endif
1398     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1399                              is_write, &uc->uc_sigmask, puc);
1400 }
1401
1402 #elif defined(__alpha__)
1403
1404 int cpu_signal_handler(int host_signum, void *pinfo, 
1405                            void *puc)
1406 {
1407     siginfo_t *info = pinfo;
1408     struct ucontext *uc = puc;
1409     uint32_t *pc = uc->uc_mcontext.sc_pc;
1410     uint32_t insn = *pc;
1411     int is_write = 0;
1412
1413     /* XXX: need kernel patch to get write flag faster */
1414     switch (insn >> 26) {
1415     case 0x0d: // stw
1416     case 0x0e: // stb
1417     case 0x0f: // stq_u
1418     case 0x24: // stf
1419     case 0x25: // stg
1420     case 0x26: // sts
1421     case 0x27: // stt
1422     case 0x2c: // stl
1423     case 0x2d: // stq
1424     case 0x2e: // stl_c
1425     case 0x2f: // stq_c
1426         is_write = 1;
1427     }
1428
1429     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1430                              is_write, &uc->uc_sigmask, puc);
1431 }
1432 #elif defined(__sparc__)
1433
1434 int cpu_signal_handler(int host_signum, void *pinfo, 
1435                        void *puc)
1436 {
1437     siginfo_t *info = pinfo;
1438     uint32_t *regs = (uint32_t *)(info + 1);
1439     void *sigmask = (regs + 20);
1440     unsigned long pc;
1441     int is_write;
1442     uint32_t insn;
1443     
1444     /* XXX: is there a standard glibc define ? */
1445     pc = regs[1];
1446     /* XXX: need kernel patch to get write flag faster */
1447     is_write = 0;
1448     insn = *(uint32_t *)pc;
1449     if ((insn >> 30) == 3) {
1450       switch((insn >> 19) & 0x3f) {
1451       case 0x05: // stb
1452       case 0x06: // sth
1453       case 0x04: // st
1454       case 0x07: // std
1455       case 0x24: // stf
1456       case 0x27: // stdf
1457       case 0x25: // stfsr
1458         is_write = 1;
1459         break;
1460       }
1461     }
1462     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1463                              is_write, sigmask, NULL);
1464 }
1465
1466 #elif defined(__arm__)
1467
1468 int cpu_signal_handler(int host_signum, void *pinfo, 
1469                        void *puc)
1470 {
1471     siginfo_t *info = pinfo;
1472     struct ucontext *uc = puc;
1473     unsigned long pc;
1474     int is_write;
1475     
1476     pc = uc->uc_mcontext.gregs[R15];
1477     /* XXX: compute is_write */
1478     is_write = 0;
1479     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1480                              is_write,
1481                              &uc->uc_sigmask, puc);
1482 }
1483
1484 #elif defined(__mc68000)
1485
1486 int cpu_signal_handler(int host_signum, void *pinfo, 
1487                        void *puc)
1488 {
1489     siginfo_t *info = pinfo;
1490     struct ucontext *uc = puc;
1491     unsigned long pc;
1492     int is_write;
1493     
1494     pc = uc->uc_mcontext.gregs[16];
1495     /* XXX: compute is_write */
1496     is_write = 0;
1497     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1498                              is_write,
1499                              &uc->uc_sigmask, puc);
1500 }
1501
1502 #elif defined(__ia64)
1503
1504 #ifndef __ISR_VALID
1505   /* This ought to be in <bits/siginfo.h>... */
1506 # define __ISR_VALID    1
1507 #endif
1508
1509 int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1510 {
1511     siginfo_t *info = pinfo;
1512     struct ucontext *uc = puc;
1513     unsigned long ip;
1514     int is_write = 0;
1515
1516     ip = uc->uc_mcontext.sc_ip;
1517     switch (host_signum) {
1518       case SIGILL:
1519       case SIGFPE:
1520       case SIGSEGV:
1521       case SIGBUS:
1522       case SIGTRAP:
1523           if (info->si_code && (info->si_segvflags & __ISR_VALID))
1524               /* ISR.W (write-access) is bit 33:  */
1525               is_write = (info->si_isr >> 33) & 1;
1526           break;
1527
1528       default:
1529           break;
1530     }
1531     return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1532                              is_write,
1533                              &uc->uc_sigmask, puc);
1534 }
1535
1536 #elif defined(__s390__)
1537
1538 int cpu_signal_handler(int host_signum, void *pinfo, 
1539                        void *puc)
1540 {
1541     siginfo_t *info = pinfo;
1542     struct ucontext *uc = puc;
1543     unsigned long pc;
1544     int is_write;
1545     
1546     pc = uc->uc_mcontext.psw.addr;
1547     /* XXX: compute is_write */
1548     is_write = 0;
1549     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1550                              is_write,
1551                              &uc->uc_sigmask, puc);
1552 }
1553
1554 #else
1555
1556 #error host CPU specific signal handler needed
1557
1558 #endif
1559
1560 #endif /* !defined(CONFIG_SOFTMMU) */