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