Statistics
| Branch: | Revision:

root / cpu-exec.c @ e62b5b13

History | View | Annotate | Download (49.9 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
#include "exec.h"
22
#include "disas.h"
23

    
24
#if !defined(CONFIG_SOFTMMU)
25
#undef EAX
26
#undef ECX
27
#undef EDX
28
#undef EBX
29
#undef ESP
30
#undef EBP
31
#undef ESI
32
#undef EDI
33
#undef EIP
34
#include <signal.h>
35
#include <sys/ucontext.h>
36
#endif
37

    
38
int tb_invalidated_flag;
39

    
40
//#define DEBUG_EXEC
41
//#define DEBUG_SIGNAL
42

    
43
#define SAVE_GLOBALS()
44
#define RESTORE_GLOBALS()
45

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

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

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

    
68
static int sparc_setjmp(jmp_buf buf)
69
{
70
    int ret;
71

    
72
    SAVE_GLOBALS();
73
    ret = setjmp(buf);
74
    RESTORE_GLOBALS();
75
    return ret;
76
}
77
#undef setjmp
78
#define setjmp(jmp_buf) sparc_setjmp(jmp_buf)
79

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

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

    
97
#if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K))
98
#define reg_T2
99
#endif
100

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

    
110
    env = env1;
111

    
112
    /* XXX: restore cpu registers saved in host registers */
113

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

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

    
133
    spin_lock(&tb_lock);
134

    
135
    tb_invalidated_flag = 0;
136

    
137
    regs_to_env(); /* XXX: do it just before cpu_gen_code() */
138

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

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

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

    
201
static inline TranslationBlock *tb_find_fast(void)
202
{
203
    TranslationBlock *tb;
204
    target_ulong cs_base, pc;
205
    uint64_t flags;
206

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

    
282
#define BREAK_CHAIN T0 = 0
283

    
284
/* main execution loop */
285

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

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

    
303
    cpu_single_env = env1;
304

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

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

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

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

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

    
673
                fp.ip = tc_ptr;
674
                fp.gp = code_gen_buffer + 2 * (1 << 20);
675
                (*(void (*)(void)) &fp)();
676
#else
677
                T0 = gen_func();
678
#endif
679
                env->current_tb = NULL;
680
                /* reset soft MMU for next block (it can currently
681
                   only be set by a memory fault) */
682
#if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU)
683
                if (env->hflags & HF_SOFTMMU_MASK) {
684
                    env->hflags &= ~HF_SOFTMMU_MASK;
685
                    /* do not allow linking to another block */
686
                    T0 = 0;
687
                }
688
#endif
689
#if defined(USE_KQEMU)
690
#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
691
                if (kqemu_is_ok(env) &&
692
                    (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
693
                    cpu_loop_exit();
694
                }
695
#endif
696
            } /* for(;;) */
697
        } else {
698
            env_to_regs();
699
        }
700
    } /* for(;;) */
701

    
702

    
703
#if defined(TARGET_I386)
704
    /* restore flags in standard format */
705
    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
706
#elif defined(TARGET_ARM)
707
    /* XXX: Save/restore host fpu exception state?.  */
708
#elif defined(TARGET_SPARC)
709
#if defined(reg_REGWPTR)
710
    REGWPTR = saved_regwptr;
711
#endif
712
#elif defined(TARGET_PPC)
713
#elif defined(TARGET_M68K)
714
    cpu_m68k_flush_flags(env, env->cc_op);
715
    env->cc_op = CC_OP_FLAGS;
716
    env->sr = (env->sr & 0xffe0)
717
              | env->cc_dest | (env->cc_x << 4);
718
#elif defined(TARGET_MIPS)
719
#elif defined(TARGET_SH4)
720
#elif defined(TARGET_ALPHA)
721
#elif defined(TARGET_CRIS)
722
    /* XXXXX */
723
#else
724
#error unsupported target CPU
725
#endif
726

    
727
    /* restore global registers */
728
    RESTORE_GLOBALS();
729
#include "hostregs_helper.h"
730

    
731
    /* fail safe : never use cpu_single_env outside cpu_exec() */
732
    cpu_single_env = NULL;
733
    return ret;
734
}
735

    
736
/* must only be called from the generated code as an exception can be
737
   generated */
738
void tb_invalidate_page_range(target_ulong start, target_ulong end)
739
{
740
    /* XXX: cannot enable it yet because it yields to MMU exception
741
       where NIP != read address on PowerPC */
742
#if 0
743
    target_ulong phys_addr;
744
    phys_addr = get_phys_addr_code(env, start);
745
    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
746
#endif
747
}
748

    
749
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
750

    
751
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
752
{
753
    CPUX86State *saved_env;
754

    
755
    saved_env = env;
756
    env = s;
757
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
758
        selector &= 0xffff;
759
        cpu_x86_load_seg_cache(env, seg_reg, selector,
760
                               (selector << 4), 0xffff, 0);
761
    } else {
762
        load_seg(seg_reg, selector);
763
    }
764
    env = saved_env;
765
}
766

    
767
void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
768
{
769
    CPUX86State *saved_env;
770

    
771
    saved_env = env;
772
    env = s;
773

    
774
    helper_fsave(ptr, data32);
775

    
776
    env = saved_env;
777
}
778

    
779
void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
780
{
781
    CPUX86State *saved_env;
782

    
783
    saved_env = env;
784
    env = s;
785

    
786
    helper_frstor(ptr, data32);
787

    
788
    env = saved_env;
789
}
790

    
791
#endif /* TARGET_I386 */
792

    
793
#if !defined(CONFIG_SOFTMMU)
794

    
795
#if defined(TARGET_I386)
796

    
797
/* 'pc' is the host PC at which the exception was raised. 'address' is
798
   the effective address of the memory exception. 'is_write' is 1 if a
799
   write caused the exception and otherwise 0'. 'old_set' is the
800
   signal set which should be restored */
801
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
802
                                    int is_write, sigset_t *old_set,
803
                                    void *puc)
804
{
805
    TranslationBlock *tb;
806
    int ret;
807

    
808
    if (cpu_single_env)
809
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
810
#if defined(DEBUG_SIGNAL)
811
    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
812
                pc, address, is_write, *(unsigned long *)old_set);
813
#endif
814
    /* XXX: locking issue */
815
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
816
        return 1;
817
    }
818

    
819
    /* see if it is an MMU fault */
820
    ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
821
    if (ret < 0)
822
        return 0; /* not an MMU fault */
823
    if (ret == 0)
824
        return 1; /* the MMU fault was handled without causing real CPU fault */
825
    /* now we have a real cpu fault */
826
    tb = tb_find_pc(pc);
827
    if (tb) {
828
        /* the PC is inside the translated code. It means that we have
829
           a virtual CPU fault */
830
        cpu_restore_state(tb, env, pc, puc);
831
    }
832
    if (ret == 1) {
833
#if 0
834
        printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
835
               env->eip, env->cr[2], env->error_code);
836
#endif
837
        /* we restore the process signal mask as the sigreturn should
838
           do it (XXX: use sigsetjmp) */
839
        sigprocmask(SIG_SETMASK, old_set, NULL);
840
        raise_exception_err(env->exception_index, env->error_code);
841
    } else {
842
        /* activate soft MMU for this block */
843
        env->hflags |= HF_SOFTMMU_MASK;
844
        cpu_resume_from_signal(env, puc);
845
    }
846
    /* never comes here */
847
    return 1;
848
}
849

    
850
#elif defined(TARGET_ARM)
851
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
852
                                    int is_write, sigset_t *old_set,
853
                                    void *puc)
854
{
855
    TranslationBlock *tb;
856
    int ret;
857

    
858
    if (cpu_single_env)
859
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
860
#if defined(DEBUG_SIGNAL)
861
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
862
           pc, address, is_write, *(unsigned long *)old_set);
863
#endif
864
    /* XXX: locking issue */
865
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
866
        return 1;
867
    }
868
    /* see if it is an MMU fault */
869
    ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
870
    if (ret < 0)
871
        return 0; /* not an MMU fault */
872
    if (ret == 0)
873
        return 1; /* the MMU fault was handled without causing real CPU fault */
874
    /* now we have a real cpu fault */
875
    tb = tb_find_pc(pc);
876
    if (tb) {
877
        /* the PC is inside the translated code. It means that we have
878
           a virtual CPU fault */
879
        cpu_restore_state(tb, env, pc, puc);
880
    }
881
    /* we restore the process signal mask as the sigreturn should
882
       do it (XXX: use sigsetjmp) */
883
    sigprocmask(SIG_SETMASK, old_set, NULL);
884
    cpu_loop_exit();
885
}
886
#elif defined(TARGET_SPARC)
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
    /* see if it is an MMU fault */
905
    ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
906
    if (ret < 0)
907
        return 0; /* not an MMU fault */
908
    if (ret == 0)
909
        return 1; /* the MMU fault was handled without causing real CPU fault */
910
    /* now we have a real cpu fault */
911
    tb = tb_find_pc(pc);
912
    if (tb) {
913
        /* the PC is inside the translated code. It means that we have
914
           a virtual CPU fault */
915
        cpu_restore_state(tb, env, pc, puc);
916
    }
917
    /* we restore the process signal mask as the sigreturn should
918
       do it (XXX: use sigsetjmp) */
919
    sigprocmask(SIG_SETMASK, old_set, NULL);
920
    cpu_loop_exit();
921
}
922
#elif defined (TARGET_PPC)
923
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
924
                                    int is_write, sigset_t *old_set,
925
                                    void *puc)
926
{
927
    TranslationBlock *tb;
928
    int ret;
929

    
930
    if (cpu_single_env)
931
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
932
#if defined(DEBUG_SIGNAL)
933
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
934
           pc, address, is_write, *(unsigned long *)old_set);
935
#endif
936
    /* XXX: locking issue */
937
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
938
        return 1;
939
    }
940

    
941
    /* see if it is an MMU fault */
942
    ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
943
    if (ret < 0)
944
        return 0; /* not an MMU fault */
945
    if (ret == 0)
946
        return 1; /* the MMU fault was handled without causing real CPU fault */
947

    
948
    /* now we have a real cpu fault */
949
    tb = tb_find_pc(pc);
950
    if (tb) {
951
        /* the PC is inside the translated code. It means that we have
952
           a virtual CPU fault */
953
        cpu_restore_state(tb, env, pc, puc);
954
    }
955
    if (ret == 1) {
956
#if 0
957
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
958
               env->nip, env->error_code, tb);
959
#endif
960
    /* we restore the process signal mask as the sigreturn should
961
       do it (XXX: use sigsetjmp) */
962
        sigprocmask(SIG_SETMASK, old_set, NULL);
963
        do_raise_exception_err(env->exception_index, env->error_code);
964
    } else {
965
        /* activate soft MMU for this block */
966
        cpu_resume_from_signal(env, puc);
967
    }
968
    /* never comes here */
969
    return 1;
970
}
971

    
972
#elif defined(TARGET_M68K)
973
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
974
                                    int is_write, sigset_t *old_set,
975
                                    void *puc)
976
{
977
    TranslationBlock *tb;
978
    int ret;
979

    
980
    if (cpu_single_env)
981
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
982
#if defined(DEBUG_SIGNAL)
983
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
984
           pc, address, is_write, *(unsigned long *)old_set);
985
#endif
986
    /* XXX: locking issue */
987
    if (is_write && page_unprotect(address, pc, puc)) {
988
        return 1;
989
    }
990
    /* see if it is an MMU fault */
991
    ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
992
    if (ret < 0)
993
        return 0; /* not an MMU fault */
994
    if (ret == 0)
995
        return 1; /* the MMU fault was handled without causing real CPU fault */
996
    /* now we have a real cpu fault */
997
    tb = tb_find_pc(pc);
998
    if (tb) {
999
        /* the PC is inside the translated code. It means that we have
1000
           a virtual CPU fault */
1001
        cpu_restore_state(tb, env, pc, puc);
1002
    }
1003
    /* we restore the process signal mask as the sigreturn should
1004
       do it (XXX: use sigsetjmp) */
1005
    sigprocmask(SIG_SETMASK, old_set, NULL);
1006
    cpu_loop_exit();
1007
    /* never comes here */
1008
    return 1;
1009
}
1010

    
1011
#elif defined (TARGET_MIPS)
1012
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1013
                                    int is_write, sigset_t *old_set,
1014
                                    void *puc)
1015
{
1016
    TranslationBlock *tb;
1017
    int ret;
1018

    
1019
    if (cpu_single_env)
1020
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1021
#if defined(DEBUG_SIGNAL)
1022
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1023
           pc, address, is_write, *(unsigned long *)old_set);
1024
#endif
1025
    /* XXX: locking issue */
1026
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1027
        return 1;
1028
    }
1029

    
1030
    /* see if it is an MMU fault */
1031
    ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1032
    if (ret < 0)
1033
        return 0; /* not an MMU fault */
1034
    if (ret == 0)
1035
        return 1; /* the MMU fault was handled without causing real CPU fault */
1036

    
1037
    /* now we have a real cpu fault */
1038
    tb = tb_find_pc(pc);
1039
    if (tb) {
1040
        /* the PC is inside the translated code. It means that we have
1041
           a virtual CPU fault */
1042
        cpu_restore_state(tb, env, pc, puc);
1043
    }
1044
    if (ret == 1) {
1045
#if 0
1046
        printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
1047
               env->PC, env->error_code, tb);
1048
#endif
1049
    /* we restore the process signal mask as the sigreturn should
1050
       do it (XXX: use sigsetjmp) */
1051
        sigprocmask(SIG_SETMASK, old_set, NULL);
1052
        do_raise_exception_err(env->exception_index, env->error_code);
1053
    } else {
1054
        /* activate soft MMU for this block */
1055
        cpu_resume_from_signal(env, puc);
1056
    }
1057
    /* never comes here */
1058
    return 1;
1059
}
1060

    
1061
#elif defined (TARGET_SH4)
1062
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1063
                                    int is_write, sigset_t *old_set,
1064
                                    void *puc)
1065
{
1066
    TranslationBlock *tb;
1067
    int ret;
1068

    
1069
    if (cpu_single_env)
1070
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1071
#if defined(DEBUG_SIGNAL)
1072
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1073
           pc, address, is_write, *(unsigned long *)old_set);
1074
#endif
1075
    /* XXX: locking issue */
1076
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1077
        return 1;
1078
    }
1079

    
1080
    /* see if it is an MMU fault */
1081
    ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1082
    if (ret < 0)
1083
        return 0; /* not an MMU fault */
1084
    if (ret == 0)
1085
        return 1; /* the MMU fault was handled without causing real CPU fault */
1086

    
1087
    /* now we have a real cpu fault */
1088
    tb = tb_find_pc(pc);
1089
    if (tb) {
1090
        /* the PC is inside the translated code. It means that we have
1091
           a virtual CPU fault */
1092
        cpu_restore_state(tb, env, pc, puc);
1093
    }
1094
#if 0
1095
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1096
               env->nip, env->error_code, tb);
1097
#endif
1098
    /* we restore the process signal mask as the sigreturn should
1099
       do it (XXX: use sigsetjmp) */
1100
    sigprocmask(SIG_SETMASK, old_set, NULL);
1101
    cpu_loop_exit();
1102
    /* never comes here */
1103
    return 1;
1104
}
1105

    
1106
#elif defined (TARGET_ALPHA)
1107
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1108
                                    int is_write, sigset_t *old_set,
1109
                                    void *puc)
1110
{
1111
    TranslationBlock *tb;
1112
    int ret;
1113

    
1114
    if (cpu_single_env)
1115
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1116
#if defined(DEBUG_SIGNAL)
1117
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1118
           pc, address, is_write, *(unsigned long *)old_set);
1119
#endif
1120
    /* XXX: locking issue */
1121
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1122
        return 1;
1123
    }
1124

    
1125
    /* see if it is an MMU fault */
1126
    ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1127
    if (ret < 0)
1128
        return 0; /* not an MMU fault */
1129
    if (ret == 0)
1130
        return 1; /* the MMU fault was handled without causing real CPU fault */
1131

    
1132
    /* now we have a real cpu fault */
1133
    tb = tb_find_pc(pc);
1134
    if (tb) {
1135
        /* the PC is inside the translated code. It means that we have
1136
           a virtual CPU fault */
1137
        cpu_restore_state(tb, env, pc, puc);
1138
    }
1139
#if 0
1140
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1141
               env->nip, env->error_code, tb);
1142
#endif
1143
    /* we restore the process signal mask as the sigreturn should
1144
       do it (XXX: use sigsetjmp) */
1145
    sigprocmask(SIG_SETMASK, old_set, NULL);
1146
    cpu_loop_exit();
1147
    /* never comes here */
1148
    return 1;
1149
}
1150
#elif defined (TARGET_CRIS)
1151
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1152
                                    int is_write, sigset_t *old_set,
1153
                                    void *puc)
1154
{
1155
    TranslationBlock *tb;
1156
    int ret;
1157

    
1158
    if (cpu_single_env)
1159
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1160
#if defined(DEBUG_SIGNAL)
1161
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1162
           pc, address, is_write, *(unsigned long *)old_set);
1163
#endif
1164
    /* XXX: locking issue */
1165
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1166
        return 1;
1167
    }
1168

    
1169
    /* see if it is an MMU fault */
1170
    ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1171
    if (ret < 0)
1172
        return 0; /* not an MMU fault */
1173
    if (ret == 0)
1174
        return 1; /* the MMU fault was handled without causing real CPU fault */
1175

    
1176
    /* now we have a real cpu fault */
1177
    tb = tb_find_pc(pc);
1178
    if (tb) {
1179
        /* the PC is inside the translated code. It means that we have
1180
           a virtual CPU fault */
1181
        cpu_restore_state(tb, env, pc, puc);
1182
    }
1183
    /* we restore the process signal mask as the sigreturn should
1184
       do it (XXX: use sigsetjmp) */
1185
    sigprocmask(SIG_SETMASK, old_set, NULL);
1186
    cpu_loop_exit();
1187
    /* never comes here */
1188
    return 1;
1189
}
1190

    
1191
#else
1192
#error unsupported target CPU
1193
#endif
1194

    
1195
#if defined(__i386__)
1196

    
1197
#if defined(__APPLE__)
1198
# include <sys/ucontext.h>
1199

    
1200
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1201
# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
1202
# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
1203
#else
1204
# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
1205
# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
1206
# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
1207
#endif
1208

    
1209
int cpu_signal_handler(int host_signum, void *pinfo,
1210
                       void *puc)
1211
{
1212
    siginfo_t *info = pinfo;
1213
    struct ucontext *uc = puc;
1214
    unsigned long pc;
1215
    int trapno;
1216

    
1217
#ifndef REG_EIP
1218
/* for glibc 2.1 */
1219
#define REG_EIP    EIP
1220
#define REG_ERR    ERR
1221
#define REG_TRAPNO TRAPNO
1222
#endif
1223
    pc = EIP_sig(uc);
1224
    trapno = TRAP_sig(uc);
1225
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1226
                             trapno == 0xe ?
1227
                             (ERROR_sig(uc) >> 1) & 1 : 0,
1228
                             &uc->uc_sigmask, puc);
1229
}
1230

    
1231
#elif defined(__x86_64__)
1232

    
1233
int cpu_signal_handler(int host_signum, void *pinfo,
1234
                       void *puc)
1235
{
1236
    siginfo_t *info = pinfo;
1237
    struct ucontext *uc = puc;
1238
    unsigned long pc;
1239

    
1240
    pc = uc->uc_mcontext.gregs[REG_RIP];
1241
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1242
                             uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
1243
                             (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1244
                             &uc->uc_sigmask, puc);
1245
}
1246

    
1247
#elif defined(__powerpc__)
1248

    
1249
/***********************************************************************
1250
 * signal context platform-specific definitions
1251
 * From Wine
1252
 */
1253
#ifdef linux
1254
/* All Registers access - only for local access */
1255
# define REG_sig(reg_name, context)                ((context)->uc_mcontext.regs->reg_name)
1256
/* Gpr Registers access  */
1257
# define GPR_sig(reg_num, context)                REG_sig(gpr[reg_num], context)
1258
# define IAR_sig(context)                        REG_sig(nip, context)        /* Program counter */
1259
# define MSR_sig(context)                        REG_sig(msr, context)   /* Machine State Register (Supervisor) */
1260
# define CTR_sig(context)                        REG_sig(ctr, context)   /* Count register */
1261
# define XER_sig(context)                        REG_sig(xer, context) /* User's integer exception register */
1262
# define LR_sig(context)                        REG_sig(link, context) /* Link register */
1263
# define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
1264
/* Float Registers access  */
1265
# define FLOAT_sig(reg_num, context)                (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1266
# define FPSCR_sig(context)                        (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1267
/* Exception Registers access */
1268
# define DAR_sig(context)                        REG_sig(dar, context)
1269
# define DSISR_sig(context)                        REG_sig(dsisr, context)
1270
# define TRAP_sig(context)                        REG_sig(trap, context)
1271
#endif /* linux */
1272

    
1273
#ifdef __APPLE__
1274
# include <sys/ucontext.h>
1275
typedef struct ucontext SIGCONTEXT;
1276
/* All Registers access - only for local access */
1277
# define REG_sig(reg_name, context)                ((context)->uc_mcontext->ss.reg_name)
1278
# define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
1279
# define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
1280
# define VECREG_sig(reg_name, context)                ((context)->uc_mcontext->vs.reg_name)
1281
/* Gpr Registers access */
1282
# define GPR_sig(reg_num, context)                REG_sig(r##reg_num, context)
1283
# define IAR_sig(context)                        REG_sig(srr0, context)        /* Program counter */
1284
# define MSR_sig(context)                        REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
1285
# define CTR_sig(context)                        REG_sig(ctr, context)
1286
# define XER_sig(context)                        REG_sig(xer, context) /* Link register */
1287
# define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
1288
# define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
1289
/* Float Registers access */
1290
# define FLOAT_sig(reg_num, context)                FLOATREG_sig(fpregs[reg_num], context)
1291
# define FPSCR_sig(context)                        ((double)FLOATREG_sig(fpscr, context))
1292
/* Exception Registers access */
1293
# define DAR_sig(context)                        EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
1294
# define DSISR_sig(context)                        EXCEPREG_sig(dsisr, context)
1295
# define TRAP_sig(context)                        EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1296
#endif /* __APPLE__ */
1297

    
1298
int cpu_signal_handler(int host_signum, void *pinfo,
1299
                       void *puc)
1300
{
1301
    siginfo_t *info = pinfo;
1302
    struct ucontext *uc = puc;
1303
    unsigned long pc;
1304
    int is_write;
1305

    
1306
    pc = IAR_sig(uc);
1307
    is_write = 0;
1308
#if 0
1309
    /* ppc 4xx case */
1310
    if (DSISR_sig(uc) & 0x00800000)
1311
        is_write = 1;
1312
#else
1313
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1314
        is_write = 1;
1315
#endif
1316
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1317
                             is_write, &uc->uc_sigmask, puc);
1318
}
1319

    
1320
#elif defined(__alpha__)
1321

    
1322
int cpu_signal_handler(int host_signum, void *pinfo,
1323
                           void *puc)
1324
{
1325
    siginfo_t *info = pinfo;
1326
    struct ucontext *uc = puc;
1327
    uint32_t *pc = uc->uc_mcontext.sc_pc;
1328
    uint32_t insn = *pc;
1329
    int is_write = 0;
1330

    
1331
    /* XXX: need kernel patch to get write flag faster */
1332
    switch (insn >> 26) {
1333
    case 0x0d: // stw
1334
    case 0x0e: // stb
1335
    case 0x0f: // stq_u
1336
    case 0x24: // stf
1337
    case 0x25: // stg
1338
    case 0x26: // sts
1339
    case 0x27: // stt
1340
    case 0x2c: // stl
1341
    case 0x2d: // stq
1342
    case 0x2e: // stl_c
1343
    case 0x2f: // stq_c
1344
        is_write = 1;
1345
    }
1346

    
1347
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1348
                             is_write, &uc->uc_sigmask, puc);
1349
}
1350
#elif defined(__sparc__)
1351

    
1352
int cpu_signal_handler(int host_signum, void *pinfo,
1353
                       void *puc)
1354
{
1355
    siginfo_t *info = pinfo;
1356
    uint32_t *regs = (uint32_t *)(info + 1);
1357
    void *sigmask = (regs + 20);
1358
    unsigned long pc;
1359
    int is_write;
1360
    uint32_t insn;
1361

    
1362
    /* XXX: is there a standard glibc define ? */
1363
    pc = regs[1];
1364
    /* XXX: need kernel patch to get write flag faster */
1365
    is_write = 0;
1366
    insn = *(uint32_t *)pc;
1367
    if ((insn >> 30) == 3) {
1368
      switch((insn >> 19) & 0x3f) {
1369
      case 0x05: // stb
1370
      case 0x06: // sth
1371
      case 0x04: // st
1372
      case 0x07: // std
1373
      case 0x24: // stf
1374
      case 0x27: // stdf
1375
      case 0x25: // stfsr
1376
        is_write = 1;
1377
        break;
1378
      }
1379
    }
1380
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1381
                             is_write, sigmask, NULL);
1382
}
1383

    
1384
#elif defined(__arm__)
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[R15];
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(__mc68000)
1403

    
1404
int cpu_signal_handler(int host_signum, void *pinfo,
1405
                       void *puc)
1406
{
1407
    siginfo_t *info = pinfo;
1408
    struct ucontext *uc = puc;
1409
    unsigned long pc;
1410
    int is_write;
1411

    
1412
    pc = uc->uc_mcontext.gregs[16];
1413
    /* XXX: compute is_write */
1414
    is_write = 0;
1415
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1416
                             is_write,
1417
                             &uc->uc_sigmask, puc);
1418
}
1419

    
1420
#elif defined(__ia64)
1421

    
1422
#ifndef __ISR_VALID
1423
  /* This ought to be in <bits/siginfo.h>... */
1424
# define __ISR_VALID        1
1425
#endif
1426

    
1427
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1428
{
1429
    siginfo_t *info = pinfo;
1430
    struct ucontext *uc = puc;
1431
    unsigned long ip;
1432
    int is_write = 0;
1433

    
1434
    ip = uc->uc_mcontext.sc_ip;
1435
    switch (host_signum) {
1436
      case SIGILL:
1437
      case SIGFPE:
1438
      case SIGSEGV:
1439
      case SIGBUS:
1440
      case SIGTRAP:
1441
          if (info->si_code && (info->si_segvflags & __ISR_VALID))
1442
              /* ISR.W (write-access) is bit 33:  */
1443
              is_write = (info->si_isr >> 33) & 1;
1444
          break;
1445

    
1446
      default:
1447
          break;
1448
    }
1449
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1450
                             is_write,
1451
                             &uc->uc_sigmask, puc);
1452
}
1453

    
1454
#elif defined(__s390__)
1455

    
1456
int cpu_signal_handler(int host_signum, void *pinfo,
1457
                       void *puc)
1458
{
1459
    siginfo_t *info = pinfo;
1460
    struct ucontext *uc = puc;
1461
    unsigned long pc;
1462
    int is_write;
1463

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

    
1471
#elif defined(__mips__)
1472

    
1473
int cpu_signal_handler(int host_signum, void *pinfo,
1474
                       void *puc)
1475
{
1476
    siginfo_t *info = pinfo;
1477
    struct ucontext *uc = puc;
1478
    greg_t pc = uc->uc_mcontext.pc;
1479
    int is_write;
1480

    
1481
    /* XXX: compute is_write */
1482
    is_write = 0;
1483
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1484
                             is_write, &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) */