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