Statistics
| Branch: | Revision:

root / cpu-exec.c @ 551bd27f

History | View | Annotate | Download (50.7 kB)

1
/*
2
 *  i386 emulator main execution loop
3
 *
4
 *  Copyright (c) 2003-2005 Fabrice Bellard
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20
#include "config.h"
21
#define CPU_NO_GLOBAL_REGS
22
#include "exec.h"
23
#include "disas.h"
24
#include "tcg.h"
25

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

    
40
#if defined(__sparc__) && !defined(HOST_SOLARIS)
41
// Work around ugly bugs in glibc that mangle global register contents
42
#undef env
43
#define env cpu_single_env
44
#endif
45

    
46
int tb_invalidated_flag;
47

    
48
//#define DEBUG_EXEC
49
//#define DEBUG_SIGNAL
50

    
51
void cpu_loop_exit(void)
52
{
53
    /* NOTE: the register at this point must be saved by hand because
54
       longjmp restore them */
55
    regs_to_env();
56
    longjmp(env->jmp_env, 1);
57
}
58

    
59
#if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K))
60
#define reg_T2
61
#endif
62

    
63
/* exit the current TB from a signal handler. The host registers are
64
   restored in a state compatible with the CPU emulator
65
 */
66
void cpu_resume_from_signal(CPUState *env1, void *puc)
67
{
68
#if !defined(CONFIG_SOFTMMU)
69
    struct ucontext *uc = puc;
70
#endif
71

    
72
    env = env1;
73

    
74
    /* XXX: restore cpu registers saved in host registers */
75

    
76
#if !defined(CONFIG_SOFTMMU)
77
    if (puc) {
78
        /* XXX: use siglongjmp ? */
79
        sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
80
    }
81
#endif
82
    longjmp(env->jmp_env, 1);
83
}
84

    
85
/* Execute the code without caching the generated code. An interpreter
86
   could be used if available. */
87
static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
88
{
89
    unsigned long next_tb;
90
    TranslationBlock *tb;
91

    
92
    /* Should never happen.
93
       We only end up here when an existing TB is too long.  */
94
    if (max_cycles > CF_COUNT_MASK)
95
        max_cycles = CF_COUNT_MASK;
96

    
97
    tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
98
                     max_cycles);
99
    env->current_tb = tb;
100
    /* execute the generated code */
101
    next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
102

    
103
    if ((next_tb & 3) == 2) {
104
        /* Restore PC.  This may happen if async event occurs before
105
           the TB starts executing.  */
106
        CPU_PC_FROM_TB(env, tb);
107
    }
108
    tb_phys_invalidate(tb, -1);
109
    tb_free(tb);
110
}
111

    
112
static TranslationBlock *tb_find_slow(target_ulong pc,
113
                                      target_ulong cs_base,
114
                                      uint64_t flags)
115
{
116
    TranslationBlock *tb, **ptb1;
117
    unsigned int h;
118
    target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
119

    
120
    tb_invalidated_flag = 0;
121

    
122
    regs_to_env(); /* XXX: do it just before cpu_gen_code() */
123

    
124
    /* find translated block using physical mappings */
125
    phys_pc = get_phys_addr_code(env, pc);
126
    phys_page1 = phys_pc & TARGET_PAGE_MASK;
127
    phys_page2 = -1;
128
    h = tb_phys_hash_func(phys_pc);
129
    ptb1 = &tb_phys_hash[h];
130
    for(;;) {
131
        tb = *ptb1;
132
        if (!tb)
133
            goto not_found;
134
        if (tb->pc == pc &&
135
            tb->page_addr[0] == phys_page1 &&
136
            tb->cs_base == cs_base &&
137
            tb->flags == flags) {
138
            /* check next page if needed */
139
            if (tb->page_addr[1] != -1) {
140
                virt_page2 = (pc & TARGET_PAGE_MASK) +
141
                    TARGET_PAGE_SIZE;
142
                phys_page2 = get_phys_addr_code(env, virt_page2);
143
                if (tb->page_addr[1] == phys_page2)
144
                    goto found;
145
            } else {
146
                goto found;
147
            }
148
        }
149
        ptb1 = &tb->phys_hash_next;
150
    }
151
 not_found:
152
   /* if no translated code available, then translate it now */
153
    tb = tb_gen_code(env, pc, cs_base, flags, 0);
154

    
155
 found:
156
    /* we add the TB in the virtual pc hash table */
157
    env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
158
    return tb;
159
}
160

    
161
static inline TranslationBlock *tb_find_fast(void)
162
{
163
    TranslationBlock *tb;
164
    target_ulong cs_base, pc;
165
    uint64_t flags;
166

    
167
    /* we record a subset of the CPU state. It will
168
       always be the same before a given translated block
169
       is executed. */
170
#if defined(TARGET_I386)
171
    flags = env->hflags;
172
    flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
173
    cs_base = env->segs[R_CS].base;
174
    pc = cs_base + env->eip;
175
#elif defined(TARGET_ARM)
176
    flags = env->thumb | (env->vfp.vec_len << 1)
177
            | (env->vfp.vec_stride << 4);
178
    if ((env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR)
179
        flags |= (1 << 6);
180
    if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
181
        flags |= (1 << 7);
182
    flags |= (env->condexec_bits << 8);
183
    cs_base = 0;
184
    pc = env->regs[15];
185
#elif defined(TARGET_SPARC)
186
#ifdef TARGET_SPARC64
187
    // Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
188
    flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
189
        | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
190
#else
191
    // FPU enable . Supervisor
192
    flags = (env->psref << 4) | env->psrs;
193
#endif
194
    cs_base = env->npc;
195
    pc = env->pc;
196
#elif defined(TARGET_PPC)
197
    flags = env->hflags;
198
    cs_base = 0;
199
    pc = env->nip;
200
#elif defined(TARGET_MIPS)
201
    flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
202
    cs_base = 0;
203
    pc = env->active_tc.PC;
204
#elif defined(TARGET_M68K)
205
    flags = (env->fpcr & M68K_FPCR_PREC)  /* Bit  6 */
206
            | (env->sr & SR_S)            /* Bit  13 */
207
            | ((env->macsr >> 4) & 0xf);  /* Bits 0-3 */
208
    cs_base = 0;
209
    pc = env->pc;
210
#elif defined(TARGET_SH4)
211
    flags = env->flags;
212
    cs_base = 0;
213
    pc = env->pc;
214
#elif defined(TARGET_ALPHA)
215
    flags = env->ps;
216
    cs_base = 0;
217
    pc = env->pc;
218
#elif defined(TARGET_CRIS)
219
    flags = env->pregs[PR_CCS] & (P_FLAG | U_FLAG | X_FLAG);
220
    flags |= env->dslot;
221
    cs_base = 0;
222
    pc = env->pc;
223
#else
224
#error unsupported CPU
225
#endif
226
    tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
227
    if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
228
                 tb->flags != flags)) {
229
        tb = tb_find_slow(pc, cs_base, flags);
230
    }
231
    return tb;
232
}
233

    
234
/* main execution loop */
235

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

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

    
248
    cpu_single_env = env1;
249

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

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

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

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

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

    
665

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

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

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

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

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

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

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

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

    
730
    saved_env = env;
731
    env = s;
732

    
733
    helper_fsave(ptr, data32);
734

    
735
    env = saved_env;
736
}
737

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

    
742
    saved_env = env;
743
    env = s;
744

    
745
    helper_frstor(ptr, data32);
746

    
747
    env = saved_env;
748
}
749

    
750
#endif /* TARGET_I386 */
751

    
752
#if !defined(CONFIG_SOFTMMU)
753

    
754
#if defined(TARGET_I386)
755

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

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

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

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

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

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

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

    
904
    /* see if it is an MMU fault */
905
    ret = cpu_ppc_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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1158
#if defined(__i386__)
1159

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

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

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

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

    
1194
#elif defined(__x86_64__)
1195

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

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

    
1210
#elif defined(__powerpc__)
1211

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

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

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

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

    
1283
#elif defined(__alpha__)
1284

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

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

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

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

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

    
1352
#elif defined(__arm__)
1353

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

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

    
1374
#elif defined(__mc68000)
1375

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

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

    
1392
#elif defined(__ia64)
1393

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

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

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

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

    
1426
#elif defined(__s390__)
1427

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

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

    
1443
#elif defined(__mips__)
1444

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

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

    
1459
#elif defined(__hppa__)
1460

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

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

    
1477
#else
1478

    
1479
#error host CPU specific signal handler needed
1480

    
1481
#endif
1482

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