Statistics
| Branch: | Revision:

root / cpu-exec.c @ 7cb69cae

History | View | Annotate | Download (49.8 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
int tb_invalidated_flag;
41
static unsigned long next_tb;
42

    
43
//#define DEBUG_EXEC
44
//#define DEBUG_SIGNAL
45

    
46
#define SAVE_GLOBALS()
47
#define RESTORE_GLOBALS()
48

    
49
#if defined(__sparc__) && !defined(HOST_SOLARIS)
50
#include <features.h>
51
#if defined(__GLIBC__) && ((__GLIBC__ < 2) || \
52
                           ((__GLIBC__ == 2) && (__GLIBC_MINOR__ <= 90)))
53
// Work around ugly bugs in glibc that mangle global register contents
54

    
55
static volatile void *saved_env;
56
static volatile unsigned long saved_t0, saved_i7;
57
#undef SAVE_GLOBALS
58
#define SAVE_GLOBALS() do {                                     \
59
        saved_env = env;                                        \
60
        saved_t0 = T0;                                          \
61
        asm volatile ("st %%i7, [%0]" : : "r" (&saved_i7));     \
62
    } while(0)
63

    
64
#undef RESTORE_GLOBALS
65
#define RESTORE_GLOBALS() do {                                  \
66
        env = (void *)saved_env;                                \
67
        T0 = saved_t0;                                          \
68
        asm volatile ("ld [%0], %%i7" : : "r" (&saved_i7));     \
69
    } while(0)
70

    
71
static int sparc_setjmp(jmp_buf buf)
72
{
73
    int ret;
74

    
75
    SAVE_GLOBALS();
76
    ret = setjmp(buf);
77
    RESTORE_GLOBALS();
78
    return ret;
79
}
80
#undef setjmp
81
#define setjmp(jmp_buf) sparc_setjmp(jmp_buf)
82

    
83
static void sparc_longjmp(jmp_buf buf, int val)
84
{
85
    SAVE_GLOBALS();
86
    longjmp(buf, val);
87
}
88
#define longjmp(jmp_buf, val) sparc_longjmp(jmp_buf, val)
89
#endif
90
#endif
91

    
92
void cpu_loop_exit(void)
93
{
94
    /* NOTE: the register at this point must be saved by hand because
95
       longjmp restore them */
96
    regs_to_env();
97
    longjmp(env->jmp_env, 1);
98
}
99

    
100
#if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K))
101
#define reg_T2
102
#endif
103

    
104
/* exit the current TB from a signal handler. The host registers are
105
   restored in a state compatible with the CPU emulator
106
 */
107
void cpu_resume_from_signal(CPUState *env1, void *puc)
108
{
109
#if !defined(CONFIG_SOFTMMU)
110
    struct ucontext *uc = puc;
111
#endif
112

    
113
    env = env1;
114

    
115
    /* XXX: restore cpu registers saved in host registers */
116

    
117
#if !defined(CONFIG_SOFTMMU)
118
    if (puc) {
119
        /* XXX: use siglongjmp ? */
120
        sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
121
    }
122
#endif
123
    longjmp(env->jmp_env, 1);
124
}
125

    
126
static TranslationBlock *tb_find_slow(target_ulong pc,
127
                                      target_ulong cs_base,
128
                                      uint64_t flags)
129
{
130
    TranslationBlock *tb, **ptb1;
131
    int code_gen_size;
132
    unsigned int h;
133
    target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
134
    uint8_t *tc_ptr;
135

    
136
    spin_lock(&tb_lock);
137

    
138
    tb_invalidated_flag = 0;
139

    
140
    regs_to_env(); /* XXX: do it just before cpu_gen_code() */
141

    
142
    /* find translated block using physical mappings */
143
    phys_pc = get_phys_addr_code(env, pc);
144
    phys_page1 = phys_pc & TARGET_PAGE_MASK;
145
    phys_page2 = -1;
146
    h = tb_phys_hash_func(phys_pc);
147
    ptb1 = &tb_phys_hash[h];
148
    for(;;) {
149
        tb = *ptb1;
150
        if (!tb)
151
            goto not_found;
152
        if (tb->pc == pc &&
153
            tb->page_addr[0] == phys_page1 &&
154
            tb->cs_base == cs_base &&
155
            tb->flags == flags) {
156
            /* check next page if needed */
157
            if (tb->page_addr[1] != -1) {
158
                virt_page2 = (pc & TARGET_PAGE_MASK) +
159
                    TARGET_PAGE_SIZE;
160
                phys_page2 = get_phys_addr_code(env, virt_page2);
161
                if (tb->page_addr[1] == phys_page2)
162
                    goto found;
163
            } else {
164
                goto found;
165
            }
166
        }
167
        ptb1 = &tb->phys_hash_next;
168
    }
169
 not_found:
170
    /* if no translated code available, then translate it now */
171
    tb = tb_alloc(pc);
172
    if (!tb) {
173
        /* flush must be done */
174
        tb_flush(env);
175
        /* cannot fail at this point */
176
        tb = tb_alloc(pc);
177
        /* don't forget to invalidate previous TB info */
178
        tb_invalidated_flag = 1;
179
    }
180
    tc_ptr = code_gen_ptr;
181
    tb->tc_ptr = tc_ptr;
182
    tb->cs_base = cs_base;
183
    tb->flags = flags;
184
    SAVE_GLOBALS();
185
    cpu_gen_code(env, tb, &code_gen_size);
186
    RESTORE_GLOBALS();
187
    code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
188

    
189
    /* check next page if needed */
190
    virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
191
    phys_page2 = -1;
192
    if ((pc & TARGET_PAGE_MASK) != virt_page2) {
193
        phys_page2 = get_phys_addr_code(env, virt_page2);
194
    }
195
    tb_link_phys(tb, phys_pc, phys_page2);
196

    
197
 found:
198
    /* we add the TB in the virtual pc hash table */
199
    env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
200
    spin_unlock(&tb_lock);
201
    return tb;
202
}
203

    
204
static inline TranslationBlock *tb_find_fast(void)
205
{
206
    TranslationBlock *tb;
207
    target_ulong cs_base, pc;
208
    uint64_t flags;
209

    
210
    /* we record a subset of the CPU state. It will
211
       always be the same before a given translated block
212
       is executed. */
213
#if defined(TARGET_I386)
214
    flags = env->hflags;
215
    flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
216
    flags |= env->intercept;
217
    cs_base = env->segs[R_CS].base;
218
    pc = cs_base + env->eip;
219
#elif defined(TARGET_ARM)
220
    flags = env->thumb | (env->vfp.vec_len << 1)
221
            | (env->vfp.vec_stride << 4);
222
    if ((env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR)
223
        flags |= (1 << 6);
224
    if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
225
        flags |= (1 << 7);
226
    flags |= (env->condexec_bits << 8);
227
    cs_base = 0;
228
    pc = env->regs[15];
229
#elif defined(TARGET_SPARC)
230
#ifdef TARGET_SPARC64
231
    // Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
232
    flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
233
        | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
234
#else
235
    // FPU enable . Supervisor
236
    flags = (env->psref << 4) | env->psrs;
237
#endif
238
    cs_base = env->npc;
239
    pc = env->pc;
240
#elif defined(TARGET_PPC)
241
    flags = env->hflags;
242
    cs_base = 0;
243
    pc = env->nip;
244
#elif defined(TARGET_MIPS)
245
    flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
246
    cs_base = 0;
247
    pc = env->PC[env->current_tc];
248
#elif defined(TARGET_M68K)
249
    flags = (env->fpcr & M68K_FPCR_PREC)  /* Bit  6 */
250
            | (env->sr & SR_S)            /* Bit  13 */
251
            | ((env->macsr >> 4) & 0xf);  /* Bits 0-3 */
252
    cs_base = 0;
253
    pc = env->pc;
254
#elif defined(TARGET_SH4)
255
    flags = env->flags;
256
    cs_base = 0;
257
    pc = env->pc;
258
#elif defined(TARGET_ALPHA)
259
    flags = env->ps;
260
    cs_base = 0;
261
    pc = env->pc;
262
#elif defined(TARGET_CRIS)
263
    flags = env->pregs[PR_CCS] & U_FLAG;
264
    cs_base = 0;
265
    pc = env->pc;
266
#else
267
#error unsupported CPU
268
#endif
269
    tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
270
    if (__builtin_expect(!tb || tb->pc != pc || tb->cs_base != cs_base ||
271
                         tb->flags != flags, 0)) {
272
        tb = tb_find_slow(pc, cs_base, flags);
273
        /* Note: we do it here to avoid a gcc bug on Mac OS X when
274
           doing it in tb_find_slow */
275
        if (tb_invalidated_flag) {
276
            /* as some TB could have been invalidated because
277
               of memory exceptions while generating the code, we
278
               must recompute the hash index here */
279
            next_tb = 0;
280
        }
281
    }
282
    return tb;
283
}
284

    
285
/* main execution loop */
286

    
287
int cpu_exec(CPUState *env1)
288
{
289
#define DECLARE_HOST_REGS 1
290
#include "hostregs_helper.h"
291
#if defined(TARGET_SPARC)
292
#if defined(reg_REGWPTR)
293
    uint32_t *saved_regwptr;
294
#endif
295
#endif
296
    int ret, interrupt_request;
297
    TranslationBlock *tb;
298
    uint8_t *tc_ptr;
299

    
300
    if (cpu_halted(env1) == EXCP_HALTED)
301
        return EXCP_HALTED;
302

    
303
    cpu_single_env = env1;
304

    
305
    /* first we save global registers */
306
#define SAVE_HOST_REGS 1
307
#include "hostregs_helper.h"
308
    env = env1;
309
    SAVE_GLOBALS();
310

    
311
    env_to_regs();
312
#if defined(TARGET_I386)
313
    /* put eflags in CPU temporary format */
314
    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
315
    DF = 1 - (2 * ((env->eflags >> 10) & 1));
316
    CC_OP = CC_OP_EFLAGS;
317
    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
318
#elif defined(TARGET_SPARC)
319
#if defined(reg_REGWPTR)
320
    saved_regwptr = REGWPTR;
321
#endif
322
#elif defined(TARGET_M68K)
323
    env->cc_op = CC_OP_FLAGS;
324
    env->cc_dest = env->sr & 0xf;
325
    env->cc_x = (env->sr >> 4) & 1;
326
#elif defined(TARGET_ALPHA)
327
#elif defined(TARGET_ARM)
328
#elif defined(TARGET_PPC)
329
#elif defined(TARGET_MIPS)
330
#elif defined(TARGET_SH4)
331
#elif defined(TARGET_CRIS)
332
    /* XXXXX */
333
#else
334
#error unsupported target CPU
335
#endif
336
    env->exception_index = -1;
337

    
338
    /* prepare setjmp context for exception handling */
339
    for(;;) {
340
        if (setjmp(env->jmp_env) == 0) {
341
            env->current_tb = NULL;
342
            /* if an exception is pending, we execute it here */
343
            if (env->exception_index >= 0) {
344
                if (env->exception_index >= EXCP_INTERRUPT) {
345
                    /* exit request from the cpu execution loop */
346
                    ret = env->exception_index;
347
                    break;
348
                } else if (env->user_mode_only) {
349
                    /* if user mode only, we simulate a fake exception
350
                       which will be handled outside the cpu execution
351
                       loop */
352
#if defined(TARGET_I386)
353
                    do_interrupt_user(env->exception_index,
354
                                      env->exception_is_int,
355
                                      env->error_code,
356
                                      env->exception_next_eip);
357
#endif
358
                    ret = env->exception_index;
359
                    break;
360
                } else {
361
#if defined(TARGET_I386)
362
                    /* simulate a real cpu exception. On i386, it can
363
                       trigger new exceptions, but we do not handle
364
                       double or triple faults yet. */
365
                    do_interrupt(env->exception_index,
366
                                 env->exception_is_int,
367
                                 env->error_code,
368
                                 env->exception_next_eip, 0);
369
                    /* successfully delivered */
370
                    env->old_exception = -1;
371
#elif defined(TARGET_PPC)
372
                    do_interrupt(env);
373
#elif defined(TARGET_MIPS)
374
                    do_interrupt(env);
375
#elif defined(TARGET_SPARC)
376
                    do_interrupt(env->exception_index);
377
#elif defined(TARGET_ARM)
378
                    do_interrupt(env);
379
#elif defined(TARGET_SH4)
380
                    do_interrupt(env);
381
#elif defined(TARGET_ALPHA)
382
                    do_interrupt(env);
383
#elif defined(TARGET_CRIS)
384
                    do_interrupt(env);
385
#elif defined(TARGET_M68K)
386
                    do_interrupt(0);
387
#endif
388
                }
389
                env->exception_index = -1;
390
            }
391
#ifdef USE_KQEMU
392
            if (kqemu_is_ok(env) && env->interrupt_request == 0) {
393
                int ret;
394
                env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
395
                ret = kqemu_cpu_exec(env);
396
                /* put eflags in CPU temporary format */
397
                CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
398
                DF = 1 - (2 * ((env->eflags >> 10) & 1));
399
                CC_OP = CC_OP_EFLAGS;
400
                env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
401
                if (ret == 1) {
402
                    /* exception */
403
                    longjmp(env->jmp_env, 1);
404
                } else if (ret == 2) {
405
                    /* softmmu execution needed */
406
                } else {
407
                    if (env->interrupt_request != 0) {
408
                        /* hardware interrupt will be executed just after */
409
                    } else {
410
                        /* otherwise, we restart */
411
                        longjmp(env->jmp_env, 1);
412
                    }
413
                }
414
            }
415
#endif
416

    
417
            next_tb = 0; /* force lookup of first TB */
418
            for(;;) {
419
                SAVE_GLOBALS();
420
                interrupt_request = env->interrupt_request;
421
                if (__builtin_expect(interrupt_request, 0)
422
#if defined(TARGET_I386)
423
                        && env->hflags & HF_GIF_MASK
424
#endif
425
            && !(env->singlestep_enabled & SSTEP_NOIRQ)) {
426
                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {
427
                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
428
                        env->exception_index = EXCP_DEBUG;
429
                        cpu_loop_exit();
430
                    }
431
#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
432
    defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS)
433
                    if (interrupt_request & CPU_INTERRUPT_HALT) {
434
                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
435
                        env->halted = 1;
436
                        env->exception_index = EXCP_HLT;
437
                        cpu_loop_exit();
438
                    }
439
#endif
440
#if defined(TARGET_I386)
441
                    if ((interrupt_request & CPU_INTERRUPT_SMI) &&
442
                        !(env->hflags & HF_SMM_MASK)) {
443
                        svm_check_intercept(SVM_EXIT_SMI);
444
                        env->interrupt_request &= ~CPU_INTERRUPT_SMI;
445
                        do_smm_enter();
446
                        next_tb = 0;
447
                    } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
448
                        !(env->hflags & HF_NMI_MASK)) {
449
                        env->interrupt_request &= ~CPU_INTERRUPT_NMI;
450
                        env->hflags |= HF_NMI_MASK;
451
                        do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
452
                        next_tb = 0;
453
                    } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
454
                        (env->eflags & IF_MASK || env->hflags & HF_HIF_MASK) &&
455
                        !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
456
                        int intno;
457
                        svm_check_intercept(SVM_EXIT_INTR);
458
                        env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
459
                        intno = cpu_get_pic_interrupt(env);
460
                        if (loglevel & CPU_LOG_TB_IN_ASM) {
461
                            fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
462
                        }
463
                        do_interrupt(intno, 0, 0, 0, 1);
464
                        /* ensure that no TB jump will be modified as
465
                           the program flow was changed */
466
                        next_tb = 0;
467
#if !defined(CONFIG_USER_ONLY)
468
                    } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
469
                        (env->eflags & IF_MASK) && !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
470
                         int intno;
471
                         /* FIXME: this should respect TPR */
472
                         env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
473
                         svm_check_intercept(SVM_EXIT_VINTR);
474
                         intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
475
                         if (loglevel & CPU_LOG_TB_IN_ASM)
476
                             fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
477
                         do_interrupt(intno, 0, 0, -1, 1);
478
                         stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl),
479
                                  ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK);
480
                        next_tb = 0;
481
#endif
482
                    }
483
#elif defined(TARGET_PPC)
484
#if 0
485
                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
486
                        cpu_ppc_reset(env);
487
                    }
488
#endif
489
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
490
                        ppc_hw_interrupt(env);
491
                        if (env->pending_interrupts == 0)
492
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
493
                        next_tb = 0;
494
                    }
495
#elif defined(TARGET_MIPS)
496
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
497
                        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
498
                        (env->CP0_Status & (1 << CP0St_IE)) &&
499
                        !(env->CP0_Status & (1 << CP0St_EXL)) &&
500
                        !(env->CP0_Status & (1 << CP0St_ERL)) &&
501
                        !(env->hflags & MIPS_HFLAG_DM)) {
502
                        /* Raise it */
503
                        env->exception_index = EXCP_EXT_INTERRUPT;
504
                        env->error_code = 0;
505
                        do_interrupt(env);
506
                        next_tb = 0;
507
                    }
508
#elif defined(TARGET_SPARC)
509
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
510
                        (env->psret != 0)) {
511
                        int pil = env->interrupt_index & 15;
512
                        int type = env->interrupt_index & 0xf0;
513

    
514
                        if (((type == TT_EXTINT) &&
515
                             (pil == 15 || pil > env->psrpil)) ||
516
                            type != TT_EXTINT) {
517
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
518
                            do_interrupt(env->interrupt_index);
519
                            env->interrupt_index = 0;
520
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
521
                            cpu_check_irqs(env);
522
#endif
523
                        next_tb = 0;
524
                        }
525
                    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
526
                        //do_interrupt(0, 0, 0, 0, 0);
527
                        env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
528
                    }
529
#elif defined(TARGET_ARM)
530
                    if (interrupt_request & CPU_INTERRUPT_FIQ
531
                        && !(env->uncached_cpsr & CPSR_F)) {
532
                        env->exception_index = EXCP_FIQ;
533
                        do_interrupt(env);
534
                        next_tb = 0;
535
                    }
536
                    /* ARMv7-M interrupt return works by loading a magic value
537
                       into the PC.  On real hardware the load causes the
538
                       return to occur.  The qemu implementation performs the
539
                       jump normally, then does the exception return when the
540
                       CPU tries to execute code at the magic address.
541
                       This will cause the magic PC value to be pushed to
542
                       the stack if an interrupt occured at the wrong time.
543
                       We avoid this by disabling interrupts when
544
                       pc contains a magic address.  */
545
                    if (interrupt_request & CPU_INTERRUPT_HARD
546
                        && ((IS_M(env) && env->regs[15] < 0xfffffff0)
547
                            || !(env->uncached_cpsr & CPSR_I))) {
548
                        env->exception_index = EXCP_IRQ;
549
                        do_interrupt(env);
550
                        next_tb = 0;
551
                    }
552
#elif defined(TARGET_SH4)
553
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
554
                        do_interrupt(env);
555
                        next_tb = 0;
556
                    }
557
#elif defined(TARGET_ALPHA)
558
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
559
                        do_interrupt(env);
560
                        next_tb = 0;
561
                    }
562
#elif defined(TARGET_CRIS)
563
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
564
                        do_interrupt(env);
565
                        next_tb = 0;
566
                    }
567
#elif defined(TARGET_M68K)
568
                    if (interrupt_request & CPU_INTERRUPT_HARD
569
                        && ((env->sr & SR_I) >> SR_I_SHIFT)
570
                            < env->pending_level) {
571
                        /* Real hardware gets the interrupt vector via an
572
                           IACK cycle at this point.  Current emulated
573
                           hardware doesn't rely on this, so we
574
                           provide/save the vector when the interrupt is
575
                           first signalled.  */
576
                        env->exception_index = env->pending_vector;
577
                        do_interrupt(1);
578
                        next_tb = 0;
579
                    }
580
#endif
581
                   /* Don't use the cached interupt_request value,
582
                      do_interrupt may have updated the EXITTB flag. */
583
                    if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
584
                        env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
585
                        /* ensure that no TB jump will be modified as
586
                           the program flow was changed */
587
                        next_tb = 0;
588
                    }
589
                    if (interrupt_request & CPU_INTERRUPT_EXIT) {
590
                        env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
591
                        env->exception_index = EXCP_INTERRUPT;
592
                        cpu_loop_exit();
593
                    }
594
                }
595
#ifdef DEBUG_EXEC
596
                if ((loglevel & CPU_LOG_TB_CPU)) {
597
                    /* restore flags in standard format */
598
                    regs_to_env();
599
#if defined(TARGET_I386)
600
                    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
601
                    cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
602
                    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
603
#elif defined(TARGET_ARM)
604
                    cpu_dump_state(env, logfile, fprintf, 0);
605
#elif defined(TARGET_SPARC)
606
                    REGWPTR = env->regbase + (env->cwp * 16);
607
                    env->regwptr = REGWPTR;
608
                    cpu_dump_state(env, logfile, fprintf, 0);
609
#elif defined(TARGET_PPC)
610
                    cpu_dump_state(env, logfile, fprintf, 0);
611
#elif defined(TARGET_M68K)
612
                    cpu_m68k_flush_flags(env, env->cc_op);
613
                    env->cc_op = CC_OP_FLAGS;
614
                    env->sr = (env->sr & 0xffe0)
615
                              | env->cc_dest | (env->cc_x << 4);
616
                    cpu_dump_state(env, logfile, fprintf, 0);
617
#elif defined(TARGET_MIPS)
618
                    cpu_dump_state(env, logfile, fprintf, 0);
619
#elif defined(TARGET_SH4)
620
                    cpu_dump_state(env, logfile, fprintf, 0);
621
#elif defined(TARGET_ALPHA)
622
                    cpu_dump_state(env, logfile, fprintf, 0);
623
#elif defined(TARGET_CRIS)
624
                    cpu_dump_state(env, logfile, fprintf, 0);
625
#else
626
#error unsupported target CPU
627
#endif
628
                }
629
#endif
630
                tb = tb_find_fast();
631
#ifdef DEBUG_EXEC
632
                if ((loglevel & CPU_LOG_EXEC)) {
633
                    fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
634
                            (long)tb->tc_ptr, tb->pc,
635
                            lookup_symbol(tb->pc));
636
                }
637
#endif
638
                RESTORE_GLOBALS();
639
                /* see if we can patch the calling TB. When the TB
640
                   spans two pages, we cannot safely do a direct
641
                   jump. */
642
                {
643
                    if (next_tb != 0 &&
644
#ifdef USE_KQEMU
645
                        (env->kqemu_enabled != 2) &&
646
#endif
647
                        tb->page_addr[1] == -1) {
648
                    spin_lock(&tb_lock);
649
                    tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
650
                    spin_unlock(&tb_lock);
651
                }
652
                }
653
                tc_ptr = tb->tc_ptr;
654
                env->current_tb = tb;
655
                /* execute the generated code */
656
                next_tb = tcg_qemu_tb_exec(tc_ptr);
657
                env->current_tb = NULL;
658
                /* reset soft MMU for next block (it can currently
659
                   only be set by a memory fault) */
660
#if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU)
661
                if (env->hflags & HF_SOFTMMU_MASK) {
662
                    env->hflags &= ~HF_SOFTMMU_MASK;
663
                    /* do not allow linking to another block */
664
                    next_tb = 0;
665
                }
666
#endif
667
#if defined(USE_KQEMU)
668
#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
669
                if (kqemu_is_ok(env) &&
670
                    (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
671
                    cpu_loop_exit();
672
                }
673
#endif
674
            } /* for(;;) */
675
        } else {
676
            env_to_regs();
677
        }
678
    } /* for(;;) */
679

    
680

    
681
#if defined(TARGET_I386)
682
    /* restore flags in standard format */
683
    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
684
#elif defined(TARGET_ARM)
685
    /* XXX: Save/restore host fpu exception state?.  */
686
#elif defined(TARGET_SPARC)
687
#if defined(reg_REGWPTR)
688
    REGWPTR = saved_regwptr;
689
#endif
690
#elif defined(TARGET_PPC)
691
#elif defined(TARGET_M68K)
692
    cpu_m68k_flush_flags(env, env->cc_op);
693
    env->cc_op = CC_OP_FLAGS;
694
    env->sr = (env->sr & 0xffe0)
695
              | env->cc_dest | (env->cc_x << 4);
696
#elif defined(TARGET_MIPS)
697
#elif defined(TARGET_SH4)
698
#elif defined(TARGET_ALPHA)
699
#elif defined(TARGET_CRIS)
700
    /* XXXXX */
701
#else
702
#error unsupported target CPU
703
#endif
704

    
705
    /* restore global registers */
706
    RESTORE_GLOBALS();
707
#include "hostregs_helper.h"
708

    
709
    /* fail safe : never use cpu_single_env outside cpu_exec() */
710
    cpu_single_env = NULL;
711
    return ret;
712
}
713

    
714
/* must only be called from the generated code as an exception can be
715
   generated */
716
void tb_invalidate_page_range(target_ulong start, target_ulong end)
717
{
718
    /* XXX: cannot enable it yet because it yields to MMU exception
719
       where NIP != read address on PowerPC */
720
#if 0
721
    target_ulong phys_addr;
722
    phys_addr = get_phys_addr_code(env, start);
723
    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
724
#endif
725
}
726

    
727
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
728

    
729
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
730
{
731
    CPUX86State *saved_env;
732

    
733
    saved_env = env;
734
    env = s;
735
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
736
        selector &= 0xffff;
737
        cpu_x86_load_seg_cache(env, seg_reg, selector,
738
                               (selector << 4), 0xffff, 0);
739
    } else {
740
        load_seg(seg_reg, selector);
741
    }
742
    env = saved_env;
743
}
744

    
745
void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
746
{
747
    CPUX86State *saved_env;
748

    
749
    saved_env = env;
750
    env = s;
751

    
752
    helper_fsave(ptr, data32);
753

    
754
    env = saved_env;
755
}
756

    
757
void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
758
{
759
    CPUX86State *saved_env;
760

    
761
    saved_env = env;
762
    env = s;
763

    
764
    helper_frstor(ptr, data32);
765

    
766
    env = saved_env;
767
}
768

    
769
#endif /* TARGET_I386 */
770

    
771
#if !defined(CONFIG_SOFTMMU)
772

    
773
#if defined(TARGET_I386)
774

    
775
/* 'pc' is the host PC at which the exception was raised. 'address' is
776
   the effective address of the memory exception. 'is_write' is 1 if a
777
   write caused the exception and otherwise 0'. 'old_set' is the
778
   signal set which should be restored */
779
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
780
                                    int is_write, sigset_t *old_set,
781
                                    void *puc)
782
{
783
    TranslationBlock *tb;
784
    int ret;
785

    
786
    if (cpu_single_env)
787
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
788
#if defined(DEBUG_SIGNAL)
789
    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
790
                pc, address, is_write, *(unsigned long *)old_set);
791
#endif
792
    /* XXX: locking issue */
793
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
794
        return 1;
795
    }
796

    
797
    /* see if it is an MMU fault */
798
    ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
799
    if (ret < 0)
800
        return 0; /* not an MMU fault */
801
    if (ret == 0)
802
        return 1; /* the MMU fault was handled without causing real CPU fault */
803
    /* now we have a real cpu fault */
804
    tb = tb_find_pc(pc);
805
    if (tb) {
806
        /* the PC is inside the translated code. It means that we have
807
           a virtual CPU fault */
808
        cpu_restore_state(tb, env, pc, puc);
809
    }
810
    if (ret == 1) {
811
#if 0
812
        printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
813
               env->eip, env->cr[2], env->error_code);
814
#endif
815
        /* we restore the process signal mask as the sigreturn should
816
           do it (XXX: use sigsetjmp) */
817
        sigprocmask(SIG_SETMASK, old_set, NULL);
818
        raise_exception_err(env->exception_index, env->error_code);
819
    } else {
820
        /* activate soft MMU for this block */
821
        env->hflags |= HF_SOFTMMU_MASK;
822
        cpu_resume_from_signal(env, puc);
823
    }
824
    /* never comes here */
825
    return 1;
826
}
827

    
828
#elif defined(TARGET_ARM)
829
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
830
                                    int is_write, sigset_t *old_set,
831
                                    void *puc)
832
{
833
    TranslationBlock *tb;
834
    int ret;
835

    
836
    if (cpu_single_env)
837
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
838
#if defined(DEBUG_SIGNAL)
839
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
840
           pc, address, is_write, *(unsigned long *)old_set);
841
#endif
842
    /* XXX: locking issue */
843
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
844
        return 1;
845
    }
846
    /* see if it is an MMU fault */
847
    ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
848
    if (ret < 0)
849
        return 0; /* not an MMU fault */
850
    if (ret == 0)
851
        return 1; /* the MMU fault was handled without causing real CPU fault */
852
    /* now we have a real cpu fault */
853
    tb = tb_find_pc(pc);
854
    if (tb) {
855
        /* the PC is inside the translated code. It means that we have
856
           a virtual CPU fault */
857
        cpu_restore_state(tb, env, pc, puc);
858
    }
859
    /* we restore the process signal mask as the sigreturn should
860
       do it (XXX: use sigsetjmp) */
861
    sigprocmask(SIG_SETMASK, old_set, NULL);
862
    cpu_loop_exit();
863
    /* never comes here */
864
    return 1;
865
}
866
#elif defined(TARGET_SPARC)
867
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
868
                                    int is_write, sigset_t *old_set,
869
                                    void *puc)
870
{
871
    TranslationBlock *tb;
872
    int ret;
873

    
874
    if (cpu_single_env)
875
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
876
#if defined(DEBUG_SIGNAL)
877
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
878
           pc, address, is_write, *(unsigned long *)old_set);
879
#endif
880
    /* XXX: locking issue */
881
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
882
        return 1;
883
    }
884
    /* see if it is an MMU fault */
885
    ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
886
    if (ret < 0)
887
        return 0; /* not an MMU fault */
888
    if (ret == 0)
889
        return 1; /* the MMU fault was handled without causing real CPU fault */
890
    /* now we have a real cpu fault */
891
    tb = tb_find_pc(pc);
892
    if (tb) {
893
        /* the PC is inside the translated code. It means that we have
894
           a virtual CPU fault */
895
        cpu_restore_state(tb, env, pc, puc);
896
    }
897
    /* we restore the process signal mask as the sigreturn should
898
       do it (XXX: use sigsetjmp) */
899
    sigprocmask(SIG_SETMASK, old_set, NULL);
900
    cpu_loop_exit();
901
    /* never comes here */
902
    return 1;
903
}
904
#elif defined (TARGET_PPC)
905
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
906
                                    int is_write, sigset_t *old_set,
907
                                    void *puc)
908
{
909
    TranslationBlock *tb;
910
    int ret;
911

    
912
    if (cpu_single_env)
913
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
914
#if defined(DEBUG_SIGNAL)
915
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
916
           pc, address, is_write, *(unsigned long *)old_set);
917
#endif
918
    /* XXX: locking issue */
919
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
920
        return 1;
921
    }
922

    
923
    /* see if it is an MMU fault */
924
    ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
925
    if (ret < 0)
926
        return 0; /* not an MMU fault */
927
    if (ret == 0)
928
        return 1; /* the MMU fault was handled without causing real CPU fault */
929

    
930
    /* now we have a real cpu fault */
931
    tb = tb_find_pc(pc);
932
    if (tb) {
933
        /* the PC is inside the translated code. It means that we have
934
           a virtual CPU fault */
935
        cpu_restore_state(tb, env, pc, puc);
936
    }
937
    if (ret == 1) {
938
#if 0
939
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
940
               env->nip, env->error_code, tb);
941
#endif
942
    /* we restore the process signal mask as the sigreturn should
943
       do it (XXX: use sigsetjmp) */
944
        sigprocmask(SIG_SETMASK, old_set, NULL);
945
        do_raise_exception_err(env->exception_index, env->error_code);
946
    } else {
947
        /* activate soft MMU for this block */
948
        cpu_resume_from_signal(env, puc);
949
    }
950
    /* never comes here */
951
    return 1;
952
}
953

    
954
#elif defined(TARGET_M68K)
955
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
956
                                    int is_write, sigset_t *old_set,
957
                                    void *puc)
958
{
959
    TranslationBlock *tb;
960
    int ret;
961

    
962
    if (cpu_single_env)
963
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
964
#if defined(DEBUG_SIGNAL)
965
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
966
           pc, address, is_write, *(unsigned long *)old_set);
967
#endif
968
    /* XXX: locking issue */
969
    if (is_write && page_unprotect(address, pc, puc)) {
970
        return 1;
971
    }
972
    /* see if it is an MMU fault */
973
    ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
974
    if (ret < 0)
975
        return 0; /* not an MMU fault */
976
    if (ret == 0)
977
        return 1; /* the MMU fault was handled without causing real CPU fault */
978
    /* now we have a real cpu fault */
979
    tb = tb_find_pc(pc);
980
    if (tb) {
981
        /* the PC is inside the translated code. It means that we have
982
           a virtual CPU fault */
983
        cpu_restore_state(tb, env, pc, puc);
984
    }
985
    /* we restore the process signal mask as the sigreturn should
986
       do it (XXX: use sigsetjmp) */
987
    sigprocmask(SIG_SETMASK, old_set, NULL);
988
    cpu_loop_exit();
989
    /* never comes here */
990
    return 1;
991
}
992

    
993
#elif defined (TARGET_MIPS)
994
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
995
                                    int is_write, sigset_t *old_set,
996
                                    void *puc)
997
{
998
    TranslationBlock *tb;
999
    int ret;
1000

    
1001
    if (cpu_single_env)
1002
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1003
#if defined(DEBUG_SIGNAL)
1004
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1005
           pc, address, is_write, *(unsigned long *)old_set);
1006
#endif
1007
    /* XXX: locking issue */
1008
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1009
        return 1;
1010
    }
1011

    
1012
    /* see if it is an MMU fault */
1013
    ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1014
    if (ret < 0)
1015
        return 0; /* not an MMU fault */
1016
    if (ret == 0)
1017
        return 1; /* the MMU fault was handled without causing real CPU fault */
1018

    
1019
    /* now we have a real cpu fault */
1020
    tb = tb_find_pc(pc);
1021
    if (tb) {
1022
        /* the PC is inside the translated code. It means that we have
1023
           a virtual CPU fault */
1024
        cpu_restore_state(tb, env, pc, puc);
1025
    }
1026
    if (ret == 1) {
1027
#if 0
1028
        printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
1029
               env->PC, env->error_code, tb);
1030
#endif
1031
    /* we restore the process signal mask as the sigreturn should
1032
       do it (XXX: use sigsetjmp) */
1033
        sigprocmask(SIG_SETMASK, old_set, NULL);
1034
        do_raise_exception_err(env->exception_index, env->error_code);
1035
    } else {
1036
        /* activate soft MMU for this block */
1037
        cpu_resume_from_signal(env, puc);
1038
    }
1039
    /* never comes here */
1040
    return 1;
1041
}
1042

    
1043
#elif defined (TARGET_SH4)
1044
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1045
                                    int is_write, sigset_t *old_set,
1046
                                    void *puc)
1047
{
1048
    TranslationBlock *tb;
1049
    int ret;
1050

    
1051
    if (cpu_single_env)
1052
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1053
#if defined(DEBUG_SIGNAL)
1054
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1055
           pc, address, is_write, *(unsigned long *)old_set);
1056
#endif
1057
    /* XXX: locking issue */
1058
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1059
        return 1;
1060
    }
1061

    
1062
    /* see if it is an MMU fault */
1063
    ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1064
    if (ret < 0)
1065
        return 0; /* not an MMU fault */
1066
    if (ret == 0)
1067
        return 1; /* the MMU fault was handled without causing real CPU fault */
1068

    
1069
    /* now we have a real cpu fault */
1070
    tb = tb_find_pc(pc);
1071
    if (tb) {
1072
        /* the PC is inside the translated code. It means that we have
1073
           a virtual CPU fault */
1074
        cpu_restore_state(tb, env, pc, puc);
1075
    }
1076
#if 0
1077
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1078
               env->nip, env->error_code, tb);
1079
#endif
1080
    /* we restore the process signal mask as the sigreturn should
1081
       do it (XXX: use sigsetjmp) */
1082
    sigprocmask(SIG_SETMASK, old_set, NULL);
1083
    cpu_loop_exit();
1084
    /* never comes here */
1085
    return 1;
1086
}
1087

    
1088
#elif defined (TARGET_ALPHA)
1089
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1090
                                    int is_write, sigset_t *old_set,
1091
                                    void *puc)
1092
{
1093
    TranslationBlock *tb;
1094
    int ret;
1095

    
1096
    if (cpu_single_env)
1097
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1098
#if defined(DEBUG_SIGNAL)
1099
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1100
           pc, address, is_write, *(unsigned long *)old_set);
1101
#endif
1102
    /* XXX: locking issue */
1103
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1104
        return 1;
1105
    }
1106

    
1107
    /* see if it is an MMU fault */
1108
    ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1109
    if (ret < 0)
1110
        return 0; /* not an MMU fault */
1111
    if (ret == 0)
1112
        return 1; /* the MMU fault was handled without causing real CPU fault */
1113

    
1114
    /* now we have a real cpu fault */
1115
    tb = tb_find_pc(pc);
1116
    if (tb) {
1117
        /* the PC is inside the translated code. It means that we have
1118
           a virtual CPU fault */
1119
        cpu_restore_state(tb, env, pc, puc);
1120
    }
1121
#if 0
1122
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1123
               env->nip, env->error_code, tb);
1124
#endif
1125
    /* we restore the process signal mask as the sigreturn should
1126
       do it (XXX: use sigsetjmp) */
1127
    sigprocmask(SIG_SETMASK, old_set, NULL);
1128
    cpu_loop_exit();
1129
    /* never comes here */
1130
    return 1;
1131
}
1132
#elif defined (TARGET_CRIS)
1133
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1134
                                    int is_write, sigset_t *old_set,
1135
                                    void *puc)
1136
{
1137
    TranslationBlock *tb;
1138
    int ret;
1139

    
1140
    if (cpu_single_env)
1141
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1142
#if defined(DEBUG_SIGNAL)
1143
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1144
           pc, address, is_write, *(unsigned long *)old_set);
1145
#endif
1146
    /* XXX: locking issue */
1147
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1148
        return 1;
1149
    }
1150

    
1151
    /* see if it is an MMU fault */
1152
    ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1153
    if (ret < 0)
1154
        return 0; /* not an MMU fault */
1155
    if (ret == 0)
1156
        return 1; /* the MMU fault was handled without causing real CPU fault */
1157

    
1158
    /* now we have a real cpu fault */
1159
    tb = tb_find_pc(pc);
1160
    if (tb) {
1161
        /* the PC is inside the translated code. It means that we have
1162
           a virtual CPU fault */
1163
        cpu_restore_state(tb, env, pc, puc);
1164
    }
1165
    /* we restore the process signal mask as the sigreturn should
1166
       do it (XXX: use sigsetjmp) */
1167
    sigprocmask(SIG_SETMASK, old_set, NULL);
1168
    cpu_loop_exit();
1169
    /* never comes here */
1170
    return 1;
1171
}
1172

    
1173
#else
1174
#error unsupported target CPU
1175
#endif
1176

    
1177
#if defined(__i386__)
1178

    
1179
#if defined(__APPLE__)
1180
# include <sys/ucontext.h>
1181

    
1182
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1183
# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
1184
# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
1185
#else
1186
# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
1187
# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
1188
# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
1189
#endif
1190

    
1191
int cpu_signal_handler(int host_signum, void *pinfo,
1192
                       void *puc)
1193
{
1194
    siginfo_t *info = pinfo;
1195
    struct ucontext *uc = puc;
1196
    unsigned long pc;
1197
    int trapno;
1198

    
1199
#ifndef REG_EIP
1200
/* for glibc 2.1 */
1201
#define REG_EIP    EIP
1202
#define REG_ERR    ERR
1203
#define REG_TRAPNO TRAPNO
1204
#endif
1205
    pc = EIP_sig(uc);
1206
    trapno = TRAP_sig(uc);
1207
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1208
                             trapno == 0xe ?
1209
                             (ERROR_sig(uc) >> 1) & 1 : 0,
1210
                             &uc->uc_sigmask, puc);
1211
}
1212

    
1213
#elif defined(__x86_64__)
1214

    
1215
int cpu_signal_handler(int host_signum, void *pinfo,
1216
                       void *puc)
1217
{
1218
    siginfo_t *info = pinfo;
1219
    struct ucontext *uc = puc;
1220
    unsigned long pc;
1221

    
1222
    pc = uc->uc_mcontext.gregs[REG_RIP];
1223
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1224
                             uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
1225
                             (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1226
                             &uc->uc_sigmask, puc);
1227
}
1228

    
1229
#elif defined(__powerpc__)
1230

    
1231
/***********************************************************************
1232
 * signal context platform-specific definitions
1233
 * From Wine
1234
 */
1235
#ifdef linux
1236
/* All Registers access - only for local access */
1237
# define REG_sig(reg_name, context)                ((context)->uc_mcontext.regs->reg_name)
1238
/* Gpr Registers access  */
1239
# define GPR_sig(reg_num, context)                REG_sig(gpr[reg_num], context)
1240
# define IAR_sig(context)                        REG_sig(nip, context)        /* Program counter */
1241
# define MSR_sig(context)                        REG_sig(msr, context)   /* Machine State Register (Supervisor) */
1242
# define CTR_sig(context)                        REG_sig(ctr, context)   /* Count register */
1243
# define XER_sig(context)                        REG_sig(xer, context) /* User's integer exception register */
1244
# define LR_sig(context)                        REG_sig(link, context) /* Link register */
1245
# define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
1246
/* Float Registers access  */
1247
# define FLOAT_sig(reg_num, context)                (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1248
# define FPSCR_sig(context)                        (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1249
/* Exception Registers access */
1250
# define DAR_sig(context)                        REG_sig(dar, context)
1251
# define DSISR_sig(context)                        REG_sig(dsisr, context)
1252
# define TRAP_sig(context)                        REG_sig(trap, context)
1253
#endif /* linux */
1254

    
1255
#ifdef __APPLE__
1256
# include <sys/ucontext.h>
1257
typedef struct ucontext SIGCONTEXT;
1258
/* All Registers access - only for local access */
1259
# define REG_sig(reg_name, context)                ((context)->uc_mcontext->ss.reg_name)
1260
# define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
1261
# define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
1262
# define VECREG_sig(reg_name, context)                ((context)->uc_mcontext->vs.reg_name)
1263
/* Gpr Registers access */
1264
# define GPR_sig(reg_num, context)                REG_sig(r##reg_num, context)
1265
# define IAR_sig(context)                        REG_sig(srr0, context)        /* Program counter */
1266
# define MSR_sig(context)                        REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
1267
# define CTR_sig(context)                        REG_sig(ctr, context)
1268
# define XER_sig(context)                        REG_sig(xer, context) /* Link register */
1269
# define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
1270
# define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
1271
/* Float Registers access */
1272
# define FLOAT_sig(reg_num, context)                FLOATREG_sig(fpregs[reg_num], context)
1273
# define FPSCR_sig(context)                        ((double)FLOATREG_sig(fpscr, context))
1274
/* Exception Registers access */
1275
# define DAR_sig(context)                        EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
1276
# define DSISR_sig(context)                        EXCEPREG_sig(dsisr, context)
1277
# define TRAP_sig(context)                        EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1278
#endif /* __APPLE__ */
1279

    
1280
int cpu_signal_handler(int host_signum, void *pinfo,
1281
                       void *puc)
1282
{
1283
    siginfo_t *info = pinfo;
1284
    struct ucontext *uc = puc;
1285
    unsigned long pc;
1286
    int is_write;
1287

    
1288
    pc = IAR_sig(uc);
1289
    is_write = 0;
1290
#if 0
1291
    /* ppc 4xx case */
1292
    if (DSISR_sig(uc) & 0x00800000)
1293
        is_write = 1;
1294
#else
1295
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1296
        is_write = 1;
1297
#endif
1298
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1299
                             is_write, &uc->uc_sigmask, puc);
1300
}
1301

    
1302
#elif defined(__alpha__)
1303

    
1304
int cpu_signal_handler(int host_signum, void *pinfo,
1305
                           void *puc)
1306
{
1307
    siginfo_t *info = pinfo;
1308
    struct ucontext *uc = puc;
1309
    uint32_t *pc = uc->uc_mcontext.sc_pc;
1310
    uint32_t insn = *pc;
1311
    int is_write = 0;
1312

    
1313
    /* XXX: need kernel patch to get write flag faster */
1314
    switch (insn >> 26) {
1315
    case 0x0d: // stw
1316
    case 0x0e: // stb
1317
    case 0x0f: // stq_u
1318
    case 0x24: // stf
1319
    case 0x25: // stg
1320
    case 0x26: // sts
1321
    case 0x27: // stt
1322
    case 0x2c: // stl
1323
    case 0x2d: // stq
1324
    case 0x2e: // stl_c
1325
    case 0x2f: // stq_c
1326
        is_write = 1;
1327
    }
1328

    
1329
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1330
                             is_write, &uc->uc_sigmask, puc);
1331
}
1332
#elif defined(__sparc__)
1333

    
1334
int cpu_signal_handler(int host_signum, void *pinfo,
1335
                       void *puc)
1336
{
1337
    siginfo_t *info = pinfo;
1338
    uint32_t *regs = (uint32_t *)(info + 1);
1339
    void *sigmask = (regs + 20);
1340
    unsigned long pc;
1341
    int is_write;
1342
    uint32_t insn;
1343

    
1344
    /* XXX: is there a standard glibc define ? */
1345
    pc = regs[1];
1346
    /* XXX: need kernel patch to get write flag faster */
1347
    is_write = 0;
1348
    insn = *(uint32_t *)pc;
1349
    if ((insn >> 30) == 3) {
1350
      switch((insn >> 19) & 0x3f) {
1351
      case 0x05: // stb
1352
      case 0x06: // sth
1353
      case 0x04: // st
1354
      case 0x07: // std
1355
      case 0x24: // stf
1356
      case 0x27: // stdf
1357
      case 0x25: // stfsr
1358
        is_write = 1;
1359
        break;
1360
      }
1361
    }
1362
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1363
                             is_write, sigmask, NULL);
1364
}
1365

    
1366
#elif defined(__arm__)
1367

    
1368
int cpu_signal_handler(int host_signum, void *pinfo,
1369
                       void *puc)
1370
{
1371
    siginfo_t *info = pinfo;
1372
    struct ucontext *uc = puc;
1373
    unsigned long pc;
1374
    int is_write;
1375

    
1376
    pc = uc->uc_mcontext.arm_pc;
1377
    /* XXX: compute is_write */
1378
    is_write = 0;
1379
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1380
                             is_write,
1381
                             &uc->uc_sigmask, puc);
1382
}
1383

    
1384
#elif defined(__mc68000)
1385

    
1386
int cpu_signal_handler(int host_signum, void *pinfo,
1387
                       void *puc)
1388
{
1389
    siginfo_t *info = pinfo;
1390
    struct ucontext *uc = puc;
1391
    unsigned long pc;
1392
    int is_write;
1393

    
1394
    pc = uc->uc_mcontext.gregs[16];
1395
    /* XXX: compute is_write */
1396
    is_write = 0;
1397
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1398
                             is_write,
1399
                             &uc->uc_sigmask, puc);
1400
}
1401

    
1402
#elif defined(__ia64)
1403

    
1404
#ifndef __ISR_VALID
1405
  /* This ought to be in <bits/siginfo.h>... */
1406
# define __ISR_VALID        1
1407
#endif
1408

    
1409
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1410
{
1411
    siginfo_t *info = pinfo;
1412
    struct ucontext *uc = puc;
1413
    unsigned long ip;
1414
    int is_write = 0;
1415

    
1416
    ip = uc->uc_mcontext.sc_ip;
1417
    switch (host_signum) {
1418
      case SIGILL:
1419
      case SIGFPE:
1420
      case SIGSEGV:
1421
      case SIGBUS:
1422
      case SIGTRAP:
1423
          if (info->si_code && (info->si_segvflags & __ISR_VALID))
1424
              /* ISR.W (write-access) is bit 33:  */
1425
              is_write = (info->si_isr >> 33) & 1;
1426
          break;
1427

    
1428
      default:
1429
          break;
1430
    }
1431
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1432
                             is_write,
1433
                             &uc->uc_sigmask, puc);
1434
}
1435

    
1436
#elif defined(__s390__)
1437

    
1438
int cpu_signal_handler(int host_signum, void *pinfo,
1439
                       void *puc)
1440
{
1441
    siginfo_t *info = pinfo;
1442
    struct ucontext *uc = puc;
1443
    unsigned long pc;
1444
    int is_write;
1445

    
1446
    pc = uc->uc_mcontext.psw.addr;
1447
    /* XXX: compute is_write */
1448
    is_write = 0;
1449
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1450
                             is_write, &uc->uc_sigmask, puc);
1451
}
1452

    
1453
#elif defined(__mips__)
1454

    
1455
int cpu_signal_handler(int host_signum, void *pinfo,
1456
                       void *puc)
1457
{
1458
    siginfo_t *info = pinfo;
1459
    struct ucontext *uc = puc;
1460
    greg_t pc = uc->uc_mcontext.pc;
1461
    int is_write;
1462

    
1463
    /* XXX: compute is_write */
1464
    is_write = 0;
1465
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1466
                             is_write, &uc->uc_sigmask, puc);
1467
}
1468

    
1469
#elif defined(__hppa__)
1470

    
1471
int cpu_signal_handler(int host_signum, void *pinfo,
1472
                       void *puc)
1473
{
1474
    struct siginfo *info = pinfo;
1475
    struct ucontext *uc = puc;
1476
    unsigned long pc;
1477
    int is_write;
1478

    
1479
    pc = uc->uc_mcontext.sc_iaoq[0];
1480
    /* FIXME: compute is_write */
1481
    is_write = 0;
1482
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1483
                             is_write,
1484
                             &uc->uc_sigmask, puc);
1485
}
1486

    
1487
#else
1488

    
1489
#error host CPU specific signal handler needed
1490

    
1491
#endif
1492

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