Statistics
| Branch: | Revision:

root / cpu-exec.c @ 2cade6a3

History | View | Annotate | Download (50.7 kB)

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;
213
    cs_base = 0;
214
    pc = env->pc;
215
#elif defined(TARGET_ALPHA)
216
    flags = env->ps;
217
    cs_base = 0;
218
    pc = env->pc;
219
#elif defined(TARGET_CRIS)
220
    flags = env->pregs[PR_CCS] & (P_FLAG | U_FLAG | X_FLAG);
221
    flags |= env->dslot;
222
    cs_base = 0;
223
    pc = env->pc;
224
#else
225
#error unsupported CPU
226
#endif
227
    tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
228
    if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
229
                 tb->flags != flags)) {
230
        tb = tb_find_slow(pc, cs_base, flags);
231
    }
232
    return tb;
233
}
234

    
235
/* main execution loop */
236

    
237
int cpu_exec(CPUState *env1)
238
{
239
#define DECLARE_HOST_REGS 1
240
#include "hostregs_helper.h"
241
    int ret, interrupt_request;
242
    TranslationBlock *tb;
243
    uint8_t *tc_ptr;
244
    unsigned long next_tb;
245

    
246
    if (cpu_halted(env1) == EXCP_HALTED)
247
        return EXCP_HALTED;
248

    
249
    cpu_single_env = env1;
250

    
251
    /* first we save global registers */
252
#define SAVE_HOST_REGS 1
253
#include "hostregs_helper.h"
254
    env = env1;
255

    
256
    env_to_regs();
257
#if defined(TARGET_I386)
258
    /* put eflags in CPU temporary format */
259
    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
260
    DF = 1 - (2 * ((env->eflags >> 10) & 1));
261
    CC_OP = CC_OP_EFLAGS;
262
    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
263
#elif defined(TARGET_SPARC)
264
#elif defined(TARGET_M68K)
265
    env->cc_op = CC_OP_FLAGS;
266
    env->cc_dest = env->sr & 0xf;
267
    env->cc_x = (env->sr >> 4) & 1;
268
#elif defined(TARGET_ALPHA)
269
#elif defined(TARGET_ARM)
270
#elif defined(TARGET_PPC)
271
#elif defined(TARGET_MIPS)
272
#elif defined(TARGET_SH4)
273
#elif defined(TARGET_CRIS)
274
    /* XXXXX */
275
#else
276
#error unsupported target CPU
277
#endif
278
    env->exception_index = -1;
279

    
280
    /* prepare setjmp context for exception handling */
281
    for(;;) {
282
        if (setjmp(env->jmp_env) == 0) {
283
            env->current_tb = NULL;
284
            /* if an exception is pending, we execute it here */
285
            if (env->exception_index >= 0) {
286
                if (env->exception_index >= EXCP_INTERRUPT) {
287
                    /* exit request from the cpu execution loop */
288
                    ret = env->exception_index;
289
                    break;
290
                } else if (env->user_mode_only) {
291
                    /* if user mode only, we simulate a fake exception
292
                       which will be handled outside the cpu execution
293
                       loop */
294
#if defined(TARGET_I386)
295
                    do_interrupt_user(env->exception_index,
296
                                      env->exception_is_int,
297
                                      env->error_code,
298
                                      env->exception_next_eip);
299
                    /* successfully delivered */
300
                    env->old_exception = -1;
301
#endif
302
                    ret = env->exception_index;
303
                    break;
304
                } else {
305
#if defined(TARGET_I386)
306
                    /* simulate a real cpu exception. On i386, it can
307
                       trigger new exceptions, but we do not handle
308
                       double or triple faults yet. */
309
                    do_interrupt(env->exception_index,
310
                                 env->exception_is_int,
311
                                 env->error_code,
312
                                 env->exception_next_eip, 0);
313
                    /* successfully delivered */
314
                    env->old_exception = -1;
315
#elif defined(TARGET_PPC)
316
                    do_interrupt(env);
317
#elif defined(TARGET_MIPS)
318
                    do_interrupt(env);
319
#elif defined(TARGET_SPARC)
320
                    do_interrupt(env);
321
#elif defined(TARGET_ARM)
322
                    do_interrupt(env);
323
#elif defined(TARGET_SH4)
324
                    do_interrupt(env);
325
#elif defined(TARGET_ALPHA)
326
                    do_interrupt(env);
327
#elif defined(TARGET_CRIS)
328
                    do_interrupt(env);
329
#elif defined(TARGET_M68K)
330
                    do_interrupt(0);
331
#endif
332
                }
333
                env->exception_index = -1;
334
            }
335
#ifdef USE_KQEMU
336
            if (kqemu_is_ok(env) && env->interrupt_request == 0) {
337
                int ret;
338
                env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
339
                ret = kqemu_cpu_exec(env);
340
                /* put eflags in CPU temporary format */
341
                CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
342
                DF = 1 - (2 * ((env->eflags >> 10) & 1));
343
                CC_OP = CC_OP_EFLAGS;
344
                env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
345
                if (ret == 1) {
346
                    /* exception */
347
                    longjmp(env->jmp_env, 1);
348
                } else if (ret == 2) {
349
                    /* softmmu execution needed */
350
                } else {
351
                    if (env->interrupt_request != 0) {
352
                        /* hardware interrupt will be executed just after */
353
                    } else {
354
                        /* otherwise, we restart */
355
                        longjmp(env->jmp_env, 1);
356
                    }
357
                }
358
            }
359
#endif
360

    
361
            next_tb = 0; /* force lookup of first TB */
362
            for(;;) {
363
                interrupt_request = env->interrupt_request;
364
                if (unlikely(interrupt_request) &&
365
                    likely(!(env->singlestep_enabled & SSTEP_NOIRQ))) {
366
                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {
367
                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
368
                        env->exception_index = EXCP_DEBUG;
369
                        cpu_loop_exit();
370
                    }
371
#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
372
    defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS)
373
                    if (interrupt_request & CPU_INTERRUPT_HALT) {
374
                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
375
                        env->halted = 1;
376
                        env->exception_index = EXCP_HLT;
377
                        cpu_loop_exit();
378
                    }
379
#endif
380
#if defined(TARGET_I386)
381
                    if (env->hflags2 & HF2_GIF_MASK) {
382
                        if ((interrupt_request & CPU_INTERRUPT_SMI) &&
383
                            !(env->hflags & HF_SMM_MASK)) {
384
                            svm_check_intercept(SVM_EXIT_SMI);
385
                            env->interrupt_request &= ~CPU_INTERRUPT_SMI;
386
                            do_smm_enter();
387
                            next_tb = 0;
388
                        } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
389
                                   !(env->hflags2 & HF2_NMI_MASK)) {
390
                            env->interrupt_request &= ~CPU_INTERRUPT_NMI;
391
                            env->hflags2 |= HF2_NMI_MASK;
392
                            do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
393
                            next_tb = 0;
394
                        } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
395
                                   (((env->hflags2 & HF2_VINTR_MASK) && 
396
                                     (env->hflags2 & HF2_HIF_MASK)) ||
397
                                    (!(env->hflags2 & HF2_VINTR_MASK) && 
398
                                     (env->eflags & IF_MASK && 
399
                                      !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
400
                            int intno;
401
                            svm_check_intercept(SVM_EXIT_INTR);
402
                            env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
403
                            intno = cpu_get_pic_interrupt(env);
404
                            if (loglevel & CPU_LOG_TB_IN_ASM) {
405
                                fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
406
                            }
407
                            do_interrupt(intno, 0, 0, 0, 1);
408
                            /* ensure that no TB jump will be modified as
409
                               the program flow was changed */
410
                            next_tb = 0;
411
#if !defined(CONFIG_USER_ONLY)
412
                        } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
413
                                   (env->eflags & IF_MASK) && 
414
                                   !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
415
                            int intno;
416
                            /* FIXME: this should respect TPR */
417
                            svm_check_intercept(SVM_EXIT_VINTR);
418
                            env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
419
                            intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
420
                            if (loglevel & CPU_LOG_TB_IN_ASM)
421
                                fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
422
                            do_interrupt(intno, 0, 0, 0, 1);
423
                            next_tb = 0;
424
#endif
425
                        }
426
                    }
427
#elif defined(TARGET_PPC)
428
#if 0
429
                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
430
                        cpu_ppc_reset(env);
431
                    }
432
#endif
433
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
434
                        ppc_hw_interrupt(env);
435
                        if (env->pending_interrupts == 0)
436
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
437
                        next_tb = 0;
438
                    }
439
#elif defined(TARGET_MIPS)
440
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
441
                        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
442
                        (env->CP0_Status & (1 << CP0St_IE)) &&
443
                        !(env->CP0_Status & (1 << CP0St_EXL)) &&
444
                        !(env->CP0_Status & (1 << CP0St_ERL)) &&
445
                        !(env->hflags & MIPS_HFLAG_DM)) {
446
                        /* Raise it */
447
                        env->exception_index = EXCP_EXT_INTERRUPT;
448
                        env->error_code = 0;
449
                        do_interrupt(env);
450
                        next_tb = 0;
451
                    }
452
#elif defined(TARGET_SPARC)
453
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
454
                        (env->psret != 0)) {
455
                        int pil = env->interrupt_index & 15;
456
                        int type = env->interrupt_index & 0xf0;
457

    
458
                        if (((type == TT_EXTINT) &&
459
                             (pil == 15 || pil > env->psrpil)) ||
460
                            type != TT_EXTINT) {
461
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
462
                            env->exception_index = env->interrupt_index;
463
                            do_interrupt(env);
464
                            env->interrupt_index = 0;
465
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
466
                            cpu_check_irqs(env);
467
#endif
468
                        next_tb = 0;
469
                        }
470
                    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
471
                        //do_interrupt(0, 0, 0, 0, 0);
472
                        env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
473
                    }
474
#elif defined(TARGET_ARM)
475
                    if (interrupt_request & CPU_INTERRUPT_FIQ
476
                        && !(env->uncached_cpsr & CPSR_F)) {
477
                        env->exception_index = EXCP_FIQ;
478
                        do_interrupt(env);
479
                        next_tb = 0;
480
                    }
481
                    /* ARMv7-M interrupt return works by loading a magic value
482
                       into the PC.  On real hardware the load causes the
483
                       return to occur.  The qemu implementation performs the
484
                       jump normally, then does the exception return when the
485
                       CPU tries to execute code at the magic address.
486
                       This will cause the magic PC value to be pushed to
487
                       the stack if an interrupt occured at the wrong time.
488
                       We avoid this by disabling interrupts when
489
                       pc contains a magic address.  */
490
                    if (interrupt_request & CPU_INTERRUPT_HARD
491
                        && ((IS_M(env) && env->regs[15] < 0xfffffff0)
492
                            || !(env->uncached_cpsr & CPSR_I))) {
493
                        env->exception_index = EXCP_IRQ;
494
                        do_interrupt(env);
495
                        next_tb = 0;
496
                    }
497
#elif defined(TARGET_SH4)
498
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
499
                        do_interrupt(env);
500
                        next_tb = 0;
501
                    }
502
#elif defined(TARGET_ALPHA)
503
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
504
                        do_interrupt(env);
505
                        next_tb = 0;
506
                    }
507
#elif defined(TARGET_CRIS)
508
                    if (interrupt_request & CPU_INTERRUPT_HARD
509
                        && (env->pregs[PR_CCS] & I_FLAG)) {
510
                        env->exception_index = EXCP_IRQ;
511
                        do_interrupt(env);
512
                        next_tb = 0;
513
                    }
514
                    if (interrupt_request & CPU_INTERRUPT_NMI
515
                        && (env->pregs[PR_CCS] & M_FLAG)) {
516
                        env->exception_index = EXCP_NMI;
517
                        do_interrupt(env);
518
                        next_tb = 0;
519
                    }
520
#elif defined(TARGET_M68K)
521
                    if (interrupt_request & CPU_INTERRUPT_HARD
522
                        && ((env->sr & SR_I) >> SR_I_SHIFT)
523
                            < env->pending_level) {
524
                        /* Real hardware gets the interrupt vector via an
525
                           IACK cycle at this point.  Current emulated
526
                           hardware doesn't rely on this, so we
527
                           provide/save the vector when the interrupt is
528
                           first signalled.  */
529
                        env->exception_index = env->pending_vector;
530
                        do_interrupt(1);
531
                        next_tb = 0;
532
                    }
533
#endif
534
                   /* Don't use the cached interupt_request value,
535
                      do_interrupt may have updated the EXITTB flag. */
536
                    if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
537
                        env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
538
                        /* ensure that no TB jump will be modified as
539
                           the program flow was changed */
540
                        next_tb = 0;
541
                    }
542
                    if (interrupt_request & CPU_INTERRUPT_EXIT) {
543
                        env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
544
                        env->exception_index = EXCP_INTERRUPT;
545
                        cpu_loop_exit();
546
                    }
547
                }
548
#ifdef DEBUG_EXEC
549
                if ((loglevel & CPU_LOG_TB_CPU)) {
550
                    /* restore flags in standard format */
551
                    regs_to_env();
552
#if defined(TARGET_I386)
553
                    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
554
                    cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
555
                    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
556
#elif defined(TARGET_ARM)
557
                    cpu_dump_state(env, logfile, fprintf, 0);
558
#elif defined(TARGET_SPARC)
559
                    cpu_dump_state(env, logfile, fprintf, 0);
560
#elif defined(TARGET_PPC)
561
                    cpu_dump_state(env, logfile, fprintf, 0);
562
#elif defined(TARGET_M68K)
563
                    cpu_m68k_flush_flags(env, env->cc_op);
564
                    env->cc_op = CC_OP_FLAGS;
565
                    env->sr = (env->sr & 0xffe0)
566
                              | env->cc_dest | (env->cc_x << 4);
567
                    cpu_dump_state(env, logfile, fprintf, 0);
568
#elif defined(TARGET_MIPS)
569
                    cpu_dump_state(env, logfile, fprintf, 0);
570
#elif defined(TARGET_SH4)
571
                    cpu_dump_state(env, logfile, fprintf, 0);
572
#elif defined(TARGET_ALPHA)
573
                    cpu_dump_state(env, logfile, fprintf, 0);
574
#elif defined(TARGET_CRIS)
575
                    cpu_dump_state(env, logfile, fprintf, 0);
576
#else
577
#error unsupported target CPU
578
#endif
579
                }
580
#endif
581
                spin_lock(&tb_lock);
582
                tb = tb_find_fast();
583
                /* Note: we do it here to avoid a gcc bug on Mac OS X when
584
                   doing it in tb_find_slow */
585
                if (tb_invalidated_flag) {
586
                    /* as some TB could have been invalidated because
587
                       of memory exceptions while generating the code, we
588
                       must recompute the hash index here */
589
                    next_tb = 0;
590
                    tb_invalidated_flag = 0;
591
                }
592
#ifdef DEBUG_EXEC
593
                if ((loglevel & CPU_LOG_EXEC)) {
594
                    fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
595
                            (long)tb->tc_ptr, tb->pc,
596
                            lookup_symbol(tb->pc));
597
                }
598
#endif
599
                /* see if we can patch the calling TB. When the TB
600
                   spans two pages, we cannot safely do a direct
601
                   jump. */
602
                {
603
                    if (next_tb != 0 &&
604
#ifdef USE_KQEMU
605
                        (env->kqemu_enabled != 2) &&
606
#endif
607
                        tb->page_addr[1] == -1) {
608
                    tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
609
                }
610
                }
611
                spin_unlock(&tb_lock);
612
                env->current_tb = tb;
613
                while (env->current_tb) {
614
                    tc_ptr = tb->tc_ptr;
615
                /* execute the generated code */
616
#if defined(__sparc__) && !defined(HOST_SOLARIS)
617
#undef env
618
                    env = cpu_single_env;
619
#define env cpu_single_env
620
#endif
621
                    next_tb = tcg_qemu_tb_exec(tc_ptr);
622
                    env->current_tb = NULL;
623
                    if ((next_tb & 3) == 2) {
624
                        /* Instruction counter expired.  */
625
                        int insns_left;
626
                        tb = (TranslationBlock *)(long)(next_tb & ~3);
627
                        /* Restore PC.  */
628
                        CPU_PC_FROM_TB(env, tb);
629
                        insns_left = env->icount_decr.u32;
630
                        if (env->icount_extra && insns_left >= 0) {
631
                            /* Refill decrementer and continue execution.  */
632
                            env->icount_extra += insns_left;
633
                            if (env->icount_extra > 0xffff) {
634
                                insns_left = 0xffff;
635
                            } else {
636
                                insns_left = env->icount_extra;
637
                            }
638
                            env->icount_extra -= insns_left;
639
                            env->icount_decr.u16.low = insns_left;
640
                        } else {
641
                            if (insns_left > 0) {
642
                                /* Execute remaining instructions.  */
643
                                cpu_exec_nocache(insns_left, tb);
644
                            }
645
                            env->exception_index = EXCP_INTERRUPT;
646
                            next_tb = 0;
647
                            cpu_loop_exit();
648
                        }
649
                    }
650
                }
651
                /* reset soft MMU for next block (it can currently
652
                   only be set by a memory fault) */
653
#if defined(USE_KQEMU)
654
#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
655
                if (kqemu_is_ok(env) &&
656
                    (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
657
                    cpu_loop_exit();
658
                }
659
#endif
660
            } /* for(;;) */
661
        } else {
662
            env_to_regs();
663
        }
664
    } /* for(;;) */
665

    
666

    
667
#if defined(TARGET_I386)
668
    /* restore flags in standard format */
669
    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
670
#elif defined(TARGET_ARM)
671
    /* XXX: Save/restore host fpu exception state?.  */
672
#elif defined(TARGET_SPARC)
673
#elif defined(TARGET_PPC)
674
#elif defined(TARGET_M68K)
675
    cpu_m68k_flush_flags(env, env->cc_op);
676
    env->cc_op = CC_OP_FLAGS;
677
    env->sr = (env->sr & 0xffe0)
678
              | env->cc_dest | (env->cc_x << 4);
679
#elif defined(TARGET_MIPS)
680
#elif defined(TARGET_SH4)
681
#elif defined(TARGET_ALPHA)
682
#elif defined(TARGET_CRIS)
683
    /* XXXXX */
684
#else
685
#error unsupported target CPU
686
#endif
687

    
688
    /* restore global registers */
689
#include "hostregs_helper.h"
690

    
691
    /* fail safe : never use cpu_single_env outside cpu_exec() */
692
    cpu_single_env = NULL;
693
    return ret;
694
}
695

    
696
/* must only be called from the generated code as an exception can be
697
   generated */
698
void tb_invalidate_page_range(target_ulong start, target_ulong end)
699
{
700
    /* XXX: cannot enable it yet because it yields to MMU exception
701
       where NIP != read address on PowerPC */
702
#if 0
703
    target_ulong phys_addr;
704
    phys_addr = get_phys_addr_code(env, start);
705
    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
706
#endif
707
}
708

    
709
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
710

    
711
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
712
{
713
    CPUX86State *saved_env;
714

    
715
    saved_env = env;
716
    env = s;
717
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
718
        selector &= 0xffff;
719
        cpu_x86_load_seg_cache(env, seg_reg, selector,
720
                               (selector << 4), 0xffff, 0);
721
    } else {
722
        helper_load_seg(seg_reg, selector);
723
    }
724
    env = saved_env;
725
}
726

    
727
void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
728
{
729
    CPUX86State *saved_env;
730

    
731
    saved_env = env;
732
    env = s;
733

    
734
    helper_fsave(ptr, data32);
735

    
736
    env = saved_env;
737
}
738

    
739
void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
740
{
741
    CPUX86State *saved_env;
742

    
743
    saved_env = env;
744
    env = s;
745

    
746
    helper_frstor(ptr, data32);
747

    
748
    env = saved_env;
749
}
750

    
751
#endif /* TARGET_I386 */
752

    
753
#if !defined(CONFIG_SOFTMMU)
754

    
755
#if defined(TARGET_I386)
756

    
757
/* 'pc' is the host PC at which the exception was raised. 'address' is
758
   the effective address of the memory exception. 'is_write' is 1 if a
759
   write caused the exception and otherwise 0'. 'old_set' is the
760
   signal set which should be restored */
761
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
762
                                    int is_write, sigset_t *old_set,
763
                                    void *puc)
764
{
765
    TranslationBlock *tb;
766
    int ret;
767

    
768
    if (cpu_single_env)
769
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
770
#if defined(DEBUG_SIGNAL)
771
    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
772
                pc, address, is_write, *(unsigned long *)old_set);
773
#endif
774
    /* XXX: locking issue */
775
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
776
        return 1;
777
    }
778

    
779
    /* see if it is an MMU fault */
780
    ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
781
    if (ret < 0)
782
        return 0; /* not an MMU fault */
783
    if (ret == 0)
784
        return 1; /* the MMU fault was handled without causing real CPU fault */
785
    /* now we have a real cpu fault */
786
    tb = tb_find_pc(pc);
787
    if (tb) {
788
        /* the PC is inside the translated code. It means that we have
789
           a virtual CPU fault */
790
        cpu_restore_state(tb, env, pc, puc);
791
    }
792
    if (ret == 1) {
793
#if 0
794
        printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
795
               env->eip, env->cr[2], env->error_code);
796
#endif
797
        /* we restore the process signal mask as the sigreturn should
798
           do it (XXX: use sigsetjmp) */
799
        sigprocmask(SIG_SETMASK, old_set, NULL);
800
        raise_exception_err(env->exception_index, env->error_code);
801
    } else {
802
        /* activate soft MMU for this block */
803
        env->hflags |= HF_SOFTMMU_MASK;
804
        cpu_resume_from_signal(env, puc);
805
    }
806
    /* never comes here */
807
    return 1;
808
}
809

    
810
#elif defined(TARGET_ARM)
811
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
812
                                    int is_write, sigset_t *old_set,
813
                                    void *puc)
814
{
815
    TranslationBlock *tb;
816
    int ret;
817

    
818
    if (cpu_single_env)
819
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
820
#if defined(DEBUG_SIGNAL)
821
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
822
           pc, address, is_write, *(unsigned long *)old_set);
823
#endif
824
    /* XXX: locking issue */
825
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
826
        return 1;
827
    }
828
    /* see if it is an MMU fault */
829
    ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
830
    if (ret < 0)
831
        return 0; /* not an MMU fault */
832
    if (ret == 0)
833
        return 1; /* the MMU fault was handled without causing real CPU fault */
834
    /* now we have a real cpu fault */
835
    tb = tb_find_pc(pc);
836
    if (tb) {
837
        /* the PC is inside the translated code. It means that we have
838
           a virtual CPU fault */
839
        cpu_restore_state(tb, env, pc, puc);
840
    }
841
    /* we restore the process signal mask as the sigreturn should
842
       do it (XXX: use sigsetjmp) */
843
    sigprocmask(SIG_SETMASK, old_set, NULL);
844
    cpu_loop_exit();
845
    /* never comes here */
846
    return 1;
847
}
848
#elif defined(TARGET_SPARC)
849
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
850
                                    int is_write, sigset_t *old_set,
851
                                    void *puc)
852
{
853
    TranslationBlock *tb;
854
    int ret;
855

    
856
    if (cpu_single_env)
857
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
858
#if defined(DEBUG_SIGNAL)
859
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
860
           pc, address, is_write, *(unsigned long *)old_set);
861
#endif
862
    /* XXX: locking issue */
863
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
864
        return 1;
865
    }
866
    /* see if it is an MMU fault */
867
    ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
868
    if (ret < 0)
869
        return 0; /* not an MMU fault */
870
    if (ret == 0)
871
        return 1; /* the MMU fault was handled without causing real CPU fault */
872
    /* now we have a real cpu fault */
873
    tb = tb_find_pc(pc);
874
    if (tb) {
875
        /* the PC is inside the translated code. It means that we have
876
           a virtual CPU fault */
877
        cpu_restore_state(tb, env, pc, puc);
878
    }
879
    /* we restore the process signal mask as the sigreturn should
880
       do it (XXX: use sigsetjmp) */
881
    sigprocmask(SIG_SETMASK, old_set, NULL);
882
    cpu_loop_exit();
883
    /* never comes here */
884
    return 1;
885
}
886
#elif defined (TARGET_PPC)
887
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
888
                                    int is_write, sigset_t *old_set,
889
                                    void *puc)
890
{
891
    TranslationBlock *tb;
892
    int ret;
893

    
894
    if (cpu_single_env)
895
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
896
#if defined(DEBUG_SIGNAL)
897
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
898
           pc, address, is_write, *(unsigned long *)old_set);
899
#endif
900
    /* XXX: locking issue */
901
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
902
        return 1;
903
    }
904

    
905
    /* see if it is an MMU fault */
906
    ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
907
    if (ret < 0)
908
        return 0; /* not an MMU fault */
909
    if (ret == 0)
910
        return 1; /* the MMU fault was handled without causing real CPU fault */
911

    
912
    /* now we have a real cpu fault */
913
    tb = tb_find_pc(pc);
914
    if (tb) {
915
        /* the PC is inside the translated code. It means that we have
916
           a virtual CPU fault */
917
        cpu_restore_state(tb, env, pc, puc);
918
    }
919
    if (ret == 1) {
920
#if 0
921
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
922
               env->nip, env->error_code, tb);
923
#endif
924
    /* we restore the process signal mask as the sigreturn should
925
       do it (XXX: use sigsetjmp) */
926
        sigprocmask(SIG_SETMASK, old_set, NULL);
927
        do_raise_exception_err(env->exception_index, env->error_code);
928
    } else {
929
        /* activate soft MMU for this block */
930
        cpu_resume_from_signal(env, puc);
931
    }
932
    /* never comes here */
933
    return 1;
934
}
935

    
936
#elif defined(TARGET_M68K)
937
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
938
                                    int is_write, sigset_t *old_set,
939
                                    void *puc)
940
{
941
    TranslationBlock *tb;
942
    int ret;
943

    
944
    if (cpu_single_env)
945
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
946
#if defined(DEBUG_SIGNAL)
947
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
948
           pc, address, is_write, *(unsigned long *)old_set);
949
#endif
950
    /* XXX: locking issue */
951
    if (is_write && page_unprotect(address, pc, puc)) {
952
        return 1;
953
    }
954
    /* see if it is an MMU fault */
955
    ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
956
    if (ret < 0)
957
        return 0; /* not an MMU fault */
958
    if (ret == 0)
959
        return 1; /* the MMU fault was handled without causing real CPU fault */
960
    /* now we have a real cpu fault */
961
    tb = tb_find_pc(pc);
962
    if (tb) {
963
        /* the PC is inside the translated code. It means that we have
964
           a virtual CPU fault */
965
        cpu_restore_state(tb, env, pc, puc);
966
    }
967
    /* we restore the process signal mask as the sigreturn should
968
       do it (XXX: use sigsetjmp) */
969
    sigprocmask(SIG_SETMASK, old_set, NULL);
970
    cpu_loop_exit();
971
    /* never comes here */
972
    return 1;
973
}
974

    
975
#elif defined (TARGET_MIPS)
976
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
977
                                    int is_write, sigset_t *old_set,
978
                                    void *puc)
979
{
980
    TranslationBlock *tb;
981
    int ret;
982

    
983
    if (cpu_single_env)
984
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
985
#if defined(DEBUG_SIGNAL)
986
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
987
           pc, address, is_write, *(unsigned long *)old_set);
988
#endif
989
    /* XXX: locking issue */
990
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
991
        return 1;
992
    }
993

    
994
    /* see if it is an MMU fault */
995
    ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
996
    if (ret < 0)
997
        return 0; /* not an MMU fault */
998
    if (ret == 0)
999
        return 1; /* the MMU fault was handled without causing real CPU fault */
1000

    
1001
    /* now we have a real cpu fault */
1002
    tb = tb_find_pc(pc);
1003
    if (tb) {
1004
        /* the PC is inside the translated code. It means that we have
1005
           a virtual CPU fault */
1006
        cpu_restore_state(tb, env, pc, puc);
1007
    }
1008
    if (ret == 1) {
1009
#if 0
1010
        printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
1011
               env->PC, env->error_code, tb);
1012
#endif
1013
    /* we restore the process signal mask as the sigreturn should
1014
       do it (XXX: use sigsetjmp) */
1015
        sigprocmask(SIG_SETMASK, old_set, NULL);
1016
        do_raise_exception_err(env->exception_index, env->error_code);
1017
    } else {
1018
        /* activate soft MMU for this block */
1019
        cpu_resume_from_signal(env, puc);
1020
    }
1021
    /* never comes here */
1022
    return 1;
1023
}
1024

    
1025
#elif defined (TARGET_SH4)
1026
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1027
                                    int is_write, sigset_t *old_set,
1028
                                    void *puc)
1029
{
1030
    TranslationBlock *tb;
1031
    int ret;
1032

    
1033
    if (cpu_single_env)
1034
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1035
#if defined(DEBUG_SIGNAL)
1036
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1037
           pc, address, is_write, *(unsigned long *)old_set);
1038
#endif
1039
    /* XXX: locking issue */
1040
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1041
        return 1;
1042
    }
1043

    
1044
    /* see if it is an MMU fault */
1045
    ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1046
    if (ret < 0)
1047
        return 0; /* not an MMU fault */
1048
    if (ret == 0)
1049
        return 1; /* the MMU fault was handled without causing real CPU fault */
1050

    
1051
    /* now we have a real cpu fault */
1052
    tb = tb_find_pc(pc);
1053
    if (tb) {
1054
        /* the PC is inside the translated code. It means that we have
1055
           a virtual CPU fault */
1056
        cpu_restore_state(tb, env, pc, puc);
1057
    }
1058
#if 0
1059
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1060
               env->nip, env->error_code, tb);
1061
#endif
1062
    /* we restore the process signal mask as the sigreturn should
1063
       do it (XXX: use sigsetjmp) */
1064
    sigprocmask(SIG_SETMASK, old_set, NULL);
1065
    cpu_loop_exit();
1066
    /* never comes here */
1067
    return 1;
1068
}
1069

    
1070
#elif defined (TARGET_ALPHA)
1071
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1072
                                    int is_write, sigset_t *old_set,
1073
                                    void *puc)
1074
{
1075
    TranslationBlock *tb;
1076
    int ret;
1077

    
1078
    if (cpu_single_env)
1079
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1080
#if defined(DEBUG_SIGNAL)
1081
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1082
           pc, address, is_write, *(unsigned long *)old_set);
1083
#endif
1084
    /* XXX: locking issue */
1085
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1086
        return 1;
1087
    }
1088

    
1089
    /* see if it is an MMU fault */
1090
    ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1091
    if (ret < 0)
1092
        return 0; /* not an MMU fault */
1093
    if (ret == 0)
1094
        return 1; /* the MMU fault was handled without causing real CPU fault */
1095

    
1096
    /* now we have a real cpu fault */
1097
    tb = tb_find_pc(pc);
1098
    if (tb) {
1099
        /* the PC is inside the translated code. It means that we have
1100
           a virtual CPU fault */
1101
        cpu_restore_state(tb, env, pc, puc);
1102
    }
1103
#if 0
1104
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1105
               env->nip, env->error_code, tb);
1106
#endif
1107
    /* we restore the process signal mask as the sigreturn should
1108
       do it (XXX: use sigsetjmp) */
1109
    sigprocmask(SIG_SETMASK, old_set, NULL);
1110
    cpu_loop_exit();
1111
    /* never comes here */
1112
    return 1;
1113
}
1114
#elif defined (TARGET_CRIS)
1115
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1116
                                    int is_write, sigset_t *old_set,
1117
                                    void *puc)
1118
{
1119
    TranslationBlock *tb;
1120
    int ret;
1121

    
1122
    if (cpu_single_env)
1123
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1124
#if defined(DEBUG_SIGNAL)
1125
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1126
           pc, address, is_write, *(unsigned long *)old_set);
1127
#endif
1128
    /* XXX: locking issue */
1129
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1130
        return 1;
1131
    }
1132

    
1133
    /* see if it is an MMU fault */
1134
    ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1135
    if (ret < 0)
1136
        return 0; /* not an MMU fault */
1137
    if (ret == 0)
1138
        return 1; /* the MMU fault was handled without causing real CPU fault */
1139

    
1140
    /* now we have a real cpu fault */
1141
    tb = tb_find_pc(pc);
1142
    if (tb) {
1143
        /* the PC is inside the translated code. It means that we have
1144
           a virtual CPU fault */
1145
        cpu_restore_state(tb, env, pc, puc);
1146
    }
1147
    /* we restore the process signal mask as the sigreturn should
1148
       do it (XXX: use sigsetjmp) */
1149
    sigprocmask(SIG_SETMASK, old_set, NULL);
1150
    cpu_loop_exit();
1151
    /* never comes here */
1152
    return 1;
1153
}
1154

    
1155
#else
1156
#error unsupported target CPU
1157
#endif
1158

    
1159
#if defined(__i386__)
1160

    
1161
#if defined(__APPLE__)
1162
# include <sys/ucontext.h>
1163

    
1164
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1165
# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
1166
# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
1167
#else
1168
# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
1169
# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
1170
# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
1171
#endif
1172

    
1173
int cpu_signal_handler(int host_signum, void *pinfo,
1174
                       void *puc)
1175
{
1176
    siginfo_t *info = pinfo;
1177
    struct ucontext *uc = puc;
1178
    unsigned long pc;
1179
    int trapno;
1180

    
1181
#ifndef REG_EIP
1182
/* for glibc 2.1 */
1183
#define REG_EIP    EIP
1184
#define REG_ERR    ERR
1185
#define REG_TRAPNO TRAPNO
1186
#endif
1187
    pc = EIP_sig(uc);
1188
    trapno = TRAP_sig(uc);
1189
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1190
                             trapno == 0xe ?
1191
                             (ERROR_sig(uc) >> 1) & 1 : 0,
1192
                             &uc->uc_sigmask, puc);
1193
}
1194

    
1195
#elif defined(__x86_64__)
1196

    
1197
int cpu_signal_handler(int host_signum, void *pinfo,
1198
                       void *puc)
1199
{
1200
    siginfo_t *info = pinfo;
1201
    struct ucontext *uc = puc;
1202
    unsigned long pc;
1203

    
1204
    pc = uc->uc_mcontext.gregs[REG_RIP];
1205
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1206
                             uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
1207
                             (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1208
                             &uc->uc_sigmask, puc);
1209
}
1210

    
1211
#elif defined(__powerpc__)
1212

    
1213
/***********************************************************************
1214
 * signal context platform-specific definitions
1215
 * From Wine
1216
 */
1217
#ifdef linux
1218
/* All Registers access - only for local access */
1219
# define REG_sig(reg_name, context)                ((context)->uc_mcontext.regs->reg_name)
1220
/* Gpr Registers access  */
1221
# define GPR_sig(reg_num, context)                REG_sig(gpr[reg_num], context)
1222
# define IAR_sig(context)                        REG_sig(nip, context)        /* Program counter */
1223
# define MSR_sig(context)                        REG_sig(msr, context)   /* Machine State Register (Supervisor) */
1224
# define CTR_sig(context)                        REG_sig(ctr, context)   /* Count register */
1225
# define XER_sig(context)                        REG_sig(xer, context) /* User's integer exception register */
1226
# define LR_sig(context)                        REG_sig(link, context) /* Link register */
1227
# define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
1228
/* Float Registers access  */
1229
# define FLOAT_sig(reg_num, context)                (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1230
# define FPSCR_sig(context)                        (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1231
/* Exception Registers access */
1232
# define DAR_sig(context)                        REG_sig(dar, context)
1233
# define DSISR_sig(context)                        REG_sig(dsisr, context)
1234
# define TRAP_sig(context)                        REG_sig(trap, context)
1235
#endif /* linux */
1236

    
1237
#ifdef __APPLE__
1238
# include <sys/ucontext.h>
1239
typedef struct ucontext SIGCONTEXT;
1240
/* All Registers access - only for local access */
1241
# define REG_sig(reg_name, context)                ((context)->uc_mcontext->ss.reg_name)
1242
# define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
1243
# define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
1244
# define VECREG_sig(reg_name, context)                ((context)->uc_mcontext->vs.reg_name)
1245
/* Gpr Registers access */
1246
# define GPR_sig(reg_num, context)                REG_sig(r##reg_num, context)
1247
# define IAR_sig(context)                        REG_sig(srr0, context)        /* Program counter */
1248
# define MSR_sig(context)                        REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
1249
# define CTR_sig(context)                        REG_sig(ctr, context)
1250
# define XER_sig(context)                        REG_sig(xer, context) /* Link register */
1251
# define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
1252
# define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
1253
/* Float Registers access */
1254
# define FLOAT_sig(reg_num, context)                FLOATREG_sig(fpregs[reg_num], context)
1255
# define FPSCR_sig(context)                        ((double)FLOATREG_sig(fpscr, context))
1256
/* Exception Registers access */
1257
# define DAR_sig(context)                        EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
1258
# define DSISR_sig(context)                        EXCEPREG_sig(dsisr, context)
1259
# define TRAP_sig(context)                        EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1260
#endif /* __APPLE__ */
1261

    
1262
int cpu_signal_handler(int host_signum, void *pinfo,
1263
                       void *puc)
1264
{
1265
    siginfo_t *info = pinfo;
1266
    struct ucontext *uc = puc;
1267
    unsigned long pc;
1268
    int is_write;
1269

    
1270
    pc = IAR_sig(uc);
1271
    is_write = 0;
1272
#if 0
1273
    /* ppc 4xx case */
1274
    if (DSISR_sig(uc) & 0x00800000)
1275
        is_write = 1;
1276
#else
1277
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1278
        is_write = 1;
1279
#endif
1280
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1281
                             is_write, &uc->uc_sigmask, puc);
1282
}
1283

    
1284
#elif defined(__alpha__)
1285

    
1286
int cpu_signal_handler(int host_signum, void *pinfo,
1287
                           void *puc)
1288
{
1289
    siginfo_t *info = pinfo;
1290
    struct ucontext *uc = puc;
1291
    uint32_t *pc = uc->uc_mcontext.sc_pc;
1292
    uint32_t insn = *pc;
1293
    int is_write = 0;
1294

    
1295
    /* XXX: need kernel patch to get write flag faster */
1296
    switch (insn >> 26) {
1297
    case 0x0d: // stw
1298
    case 0x0e: // stb
1299
    case 0x0f: // stq_u
1300
    case 0x24: // stf
1301
    case 0x25: // stg
1302
    case 0x26: // sts
1303
    case 0x27: // stt
1304
    case 0x2c: // stl
1305
    case 0x2d: // stq
1306
    case 0x2e: // stl_c
1307
    case 0x2f: // stq_c
1308
        is_write = 1;
1309
    }
1310

    
1311
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1312
                             is_write, &uc->uc_sigmask, puc);
1313
}
1314
#elif defined(__sparc__)
1315

    
1316
int cpu_signal_handler(int host_signum, void *pinfo,
1317
                       void *puc)
1318
{
1319
    siginfo_t *info = pinfo;
1320
    int is_write;
1321
    uint32_t insn;
1322
#if !defined(__arch64__) || defined(HOST_SOLARIS)
1323
    uint32_t *regs = (uint32_t *)(info + 1);
1324
    void *sigmask = (regs + 20);
1325
    /* XXX: is there a standard glibc define ? */
1326
    unsigned long pc = regs[1];
1327
#else
1328
    struct sigcontext *sc = puc;
1329
    unsigned long pc = sc->sigc_regs.tpc;
1330
    void *sigmask = (void *)sc->sigc_mask;
1331
#endif
1332

    
1333
    /* XXX: need kernel patch to get write flag faster */
1334
    is_write = 0;
1335
    insn = *(uint32_t *)pc;
1336
    if ((insn >> 30) == 3) {
1337
      switch((insn >> 19) & 0x3f) {
1338
      case 0x05: // stb
1339
      case 0x06: // sth
1340
      case 0x04: // st
1341
      case 0x07: // std
1342
      case 0x24: // stf
1343
      case 0x27: // stdf
1344
      case 0x25: // stfsr
1345
        is_write = 1;
1346
        break;
1347
      }
1348
    }
1349
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1350
                             is_write, sigmask, NULL);
1351
}
1352

    
1353
#elif defined(__arm__)
1354

    
1355
int cpu_signal_handler(int host_signum, void *pinfo,
1356
                       void *puc)
1357
{
1358
    siginfo_t *info = pinfo;
1359
    struct ucontext *uc = puc;
1360
    unsigned long pc;
1361
    int is_write;
1362

    
1363
#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
1364
    pc = uc->uc_mcontext.gregs[R15];
1365
#else
1366
    pc = uc->uc_mcontext.arm_pc;
1367
#endif
1368
    /* XXX: compute is_write */
1369
    is_write = 0;
1370
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1371
                             is_write,
1372
                             &uc->uc_sigmask, puc);
1373
}
1374

    
1375
#elif defined(__mc68000)
1376

    
1377
int cpu_signal_handler(int host_signum, void *pinfo,
1378
                       void *puc)
1379
{
1380
    siginfo_t *info = pinfo;
1381
    struct ucontext *uc = puc;
1382
    unsigned long pc;
1383
    int is_write;
1384

    
1385
    pc = uc->uc_mcontext.gregs[16];
1386
    /* XXX: compute is_write */
1387
    is_write = 0;
1388
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1389
                             is_write,
1390
                             &uc->uc_sigmask, puc);
1391
}
1392

    
1393
#elif defined(__ia64)
1394

    
1395
#ifndef __ISR_VALID
1396
  /* This ought to be in <bits/siginfo.h>... */
1397
# define __ISR_VALID        1
1398
#endif
1399

    
1400
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1401
{
1402
    siginfo_t *info = pinfo;
1403
    struct ucontext *uc = puc;
1404
    unsigned long ip;
1405
    int is_write = 0;
1406

    
1407
    ip = uc->uc_mcontext.sc_ip;
1408
    switch (host_signum) {
1409
      case SIGILL:
1410
      case SIGFPE:
1411
      case SIGSEGV:
1412
      case SIGBUS:
1413
      case SIGTRAP:
1414
          if (info->si_code && (info->si_segvflags & __ISR_VALID))
1415
              /* ISR.W (write-access) is bit 33:  */
1416
              is_write = (info->si_isr >> 33) & 1;
1417
          break;
1418

    
1419
      default:
1420
          break;
1421
    }
1422
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1423
                             is_write,
1424
                             &uc->uc_sigmask, puc);
1425
}
1426

    
1427
#elif defined(__s390__)
1428

    
1429
int cpu_signal_handler(int host_signum, void *pinfo,
1430
                       void *puc)
1431
{
1432
    siginfo_t *info = pinfo;
1433
    struct ucontext *uc = puc;
1434
    unsigned long pc;
1435
    int is_write;
1436

    
1437
    pc = uc->uc_mcontext.psw.addr;
1438
    /* XXX: compute is_write */
1439
    is_write = 0;
1440
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1441
                             is_write, &uc->uc_sigmask, puc);
1442
}
1443

    
1444
#elif defined(__mips__)
1445

    
1446
int cpu_signal_handler(int host_signum, void *pinfo,
1447
                       void *puc)
1448
{
1449
    siginfo_t *info = pinfo;
1450
    struct ucontext *uc = puc;
1451
    greg_t pc = uc->uc_mcontext.pc;
1452
    int is_write;
1453

    
1454
    /* XXX: compute is_write */
1455
    is_write = 0;
1456
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1457
                             is_write, &uc->uc_sigmask, puc);
1458
}
1459

    
1460
#elif defined(__hppa__)
1461

    
1462
int cpu_signal_handler(int host_signum, void *pinfo,
1463
                       void *puc)
1464
{
1465
    struct siginfo *info = pinfo;
1466
    struct ucontext *uc = puc;
1467
    unsigned long pc;
1468
    int is_write;
1469

    
1470
    pc = uc->uc_mcontext.sc_iaoq[0];
1471
    /* FIXME: compute is_write */
1472
    is_write = 0;
1473
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1474
                             is_write,
1475
                             &uc->uc_sigmask, puc);
1476
}
1477

    
1478
#else
1479

    
1480
#error host CPU specific signal handler needed
1481

    
1482
#endif
1483

    
1484
#endif /* !defined(CONFIG_SOFTMMU) */