Statistics
| Branch: | Revision:

root / cpu-exec.c @ 07bf2857

History | View | Annotate | Download (49.2 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
static TranslationBlock *tb_find_slow(target_ulong pc,
86
                                      target_ulong cs_base,
87
                                      uint64_t flags)
88
{
89
    TranslationBlock *tb, **ptb1;
90
    int code_gen_size;
91
    unsigned int h;
92
    target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
93
    uint8_t *tc_ptr;
94

    
95
    tb_invalidated_flag = 0;
96

    
97
    regs_to_env(); /* XXX: do it just before cpu_gen_code() */
98

    
99
    /* find translated block using physical mappings */
100
    phys_pc = get_phys_addr_code(env, pc);
101
    phys_page1 = phys_pc & TARGET_PAGE_MASK;
102
    phys_page2 = -1;
103
    h = tb_phys_hash_func(phys_pc);
104
    ptb1 = &tb_phys_hash[h];
105
    for(;;) {
106
        tb = *ptb1;
107
        if (!tb)
108
            goto not_found;
109
        if (tb->pc == pc &&
110
            tb->page_addr[0] == phys_page1 &&
111
            tb->cs_base == cs_base &&
112
            tb->flags == flags) {
113
            /* check next page if needed */
114
            if (tb->page_addr[1] != -1) {
115
                virt_page2 = (pc & TARGET_PAGE_MASK) +
116
                    TARGET_PAGE_SIZE;
117
                phys_page2 = get_phys_addr_code(env, virt_page2);
118
                if (tb->page_addr[1] == phys_page2)
119
                    goto found;
120
            } else {
121
                goto found;
122
            }
123
        }
124
        ptb1 = &tb->phys_hash_next;
125
    }
126
 not_found:
127
    /* if no translated code available, then translate it now */
128
    tb = tb_alloc(pc);
129
    if (!tb) {
130
        /* flush must be done */
131
        tb_flush(env);
132
        /* cannot fail at this point */
133
        tb = tb_alloc(pc);
134
        /* don't forget to invalidate previous TB info */
135
        tb_invalidated_flag = 1;
136
    }
137
    tc_ptr = code_gen_ptr;
138
    tb->tc_ptr = tc_ptr;
139
    tb->cs_base = cs_base;
140
    tb->flags = flags;
141
    cpu_gen_code(env, tb, &code_gen_size);
142
    code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
143

    
144
    /* check next page if needed */
145
    virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
146
    phys_page2 = -1;
147
    if ((pc & TARGET_PAGE_MASK) != virt_page2) {
148
        phys_page2 = get_phys_addr_code(env, virt_page2);
149
    }
150
    tb_link_phys(tb, phys_pc, phys_page2);
151

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

    
158
static inline TranslationBlock *tb_find_fast(void)
159
{
160
    TranslationBlock *tb;
161
    target_ulong cs_base, pc;
162
    uint64_t flags;
163

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

    
231
/* main execution loop */
232

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

    
242
    if (cpu_halted(env1) == EXCP_HALTED)
243
        return EXCP_HALTED;
244

    
245
    cpu_single_env = env1;
246

    
247
    /* first we save global registers */
248
#define SAVE_HOST_REGS 1
249
#include "hostregs_helper.h"
250
    env = env1;
251

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

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

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

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

    
632

    
633
#if defined(TARGET_I386)
634
    /* restore flags in standard format */
635
    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
636
#elif defined(TARGET_ARM)
637
    /* XXX: Save/restore host fpu exception state?.  */
638
#elif defined(TARGET_SPARC)
639
#elif defined(TARGET_PPC)
640
#elif defined(TARGET_M68K)
641
    cpu_m68k_flush_flags(env, env->cc_op);
642
    env->cc_op = CC_OP_FLAGS;
643
    env->sr = (env->sr & 0xffe0)
644
              | env->cc_dest | (env->cc_x << 4);
645
#elif defined(TARGET_MIPS)
646
#elif defined(TARGET_SH4)
647
#elif defined(TARGET_ALPHA)
648
#elif defined(TARGET_CRIS)
649
    /* XXXXX */
650
#else
651
#error unsupported target CPU
652
#endif
653

    
654
    /* restore global registers */
655
#include "hostregs_helper.h"
656

    
657
    /* fail safe : never use cpu_single_env outside cpu_exec() */
658
    cpu_single_env = NULL;
659
    return ret;
660
}
661

    
662
/* must only be called from the generated code as an exception can be
663
   generated */
664
void tb_invalidate_page_range(target_ulong start, target_ulong end)
665
{
666
    /* XXX: cannot enable it yet because it yields to MMU exception
667
       where NIP != read address on PowerPC */
668
#if 0
669
    target_ulong phys_addr;
670
    phys_addr = get_phys_addr_code(env, start);
671
    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
672
#endif
673
}
674

    
675
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
676

    
677
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
678
{
679
    CPUX86State *saved_env;
680

    
681
    saved_env = env;
682
    env = s;
683
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
684
        selector &= 0xffff;
685
        cpu_x86_load_seg_cache(env, seg_reg, selector,
686
                               (selector << 4), 0xffff, 0);
687
    } else {
688
        helper_load_seg(seg_reg, selector);
689
    }
690
    env = saved_env;
691
}
692

    
693
void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
694
{
695
    CPUX86State *saved_env;
696

    
697
    saved_env = env;
698
    env = s;
699

    
700
    helper_fsave(ptr, data32);
701

    
702
    env = saved_env;
703
}
704

    
705
void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
706
{
707
    CPUX86State *saved_env;
708

    
709
    saved_env = env;
710
    env = s;
711

    
712
    helper_frstor(ptr, data32);
713

    
714
    env = saved_env;
715
}
716

    
717
#endif /* TARGET_I386 */
718

    
719
#if !defined(CONFIG_SOFTMMU)
720

    
721
#if defined(TARGET_I386)
722

    
723
/* 'pc' is the host PC at which the exception was raised. 'address' is
724
   the effective address of the memory exception. 'is_write' is 1 if a
725
   write caused the exception and otherwise 0'. 'old_set' is the
726
   signal set which should be restored */
727
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
728
                                    int is_write, sigset_t *old_set,
729
                                    void *puc)
730
{
731
    TranslationBlock *tb;
732
    int ret;
733

    
734
    if (cpu_single_env)
735
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
736
#if defined(DEBUG_SIGNAL)
737
    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
738
                pc, address, is_write, *(unsigned long *)old_set);
739
#endif
740
    /* XXX: locking issue */
741
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
742
        return 1;
743
    }
744

    
745
    /* see if it is an MMU fault */
746
    ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
747
    if (ret < 0)
748
        return 0; /* not an MMU fault */
749
    if (ret == 0)
750
        return 1; /* the MMU fault was handled without causing real CPU fault */
751
    /* now we have a real cpu fault */
752
    tb = tb_find_pc(pc);
753
    if (tb) {
754
        /* the PC is inside the translated code. It means that we have
755
           a virtual CPU fault */
756
        cpu_restore_state(tb, env, pc, puc);
757
    }
758
    if (ret == 1) {
759
#if 0
760
        printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
761
               env->eip, env->cr[2], env->error_code);
762
#endif
763
        /* we restore the process signal mask as the sigreturn should
764
           do it (XXX: use sigsetjmp) */
765
        sigprocmask(SIG_SETMASK, old_set, NULL);
766
        raise_exception_err(env->exception_index, env->error_code);
767
    } else {
768
        /* activate soft MMU for this block */
769
        env->hflags |= HF_SOFTMMU_MASK;
770
        cpu_resume_from_signal(env, puc);
771
    }
772
    /* never comes here */
773
    return 1;
774
}
775

    
776
#elif defined(TARGET_ARM)
777
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
778
                                    int is_write, sigset_t *old_set,
779
                                    void *puc)
780
{
781
    TranslationBlock *tb;
782
    int ret;
783

    
784
    if (cpu_single_env)
785
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
786
#if defined(DEBUG_SIGNAL)
787
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
788
           pc, address, is_write, *(unsigned long *)old_set);
789
#endif
790
    /* XXX: locking issue */
791
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
792
        return 1;
793
    }
794
    /* see if it is an MMU fault */
795
    ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
796
    if (ret < 0)
797
        return 0; /* not an MMU fault */
798
    if (ret == 0)
799
        return 1; /* the MMU fault was handled without causing real CPU fault */
800
    /* now we have a real cpu fault */
801
    tb = tb_find_pc(pc);
802
    if (tb) {
803
        /* the PC is inside the translated code. It means that we have
804
           a virtual CPU fault */
805
        cpu_restore_state(tb, env, pc, puc);
806
    }
807
    /* we restore the process signal mask as the sigreturn should
808
       do it (XXX: use sigsetjmp) */
809
    sigprocmask(SIG_SETMASK, old_set, NULL);
810
    cpu_loop_exit();
811
    /* never comes here */
812
    return 1;
813
}
814
#elif defined(TARGET_SPARC)
815
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
816
                                    int is_write, sigset_t *old_set,
817
                                    void *puc)
818
{
819
    TranslationBlock *tb;
820
    int ret;
821

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

    
860
    if (cpu_single_env)
861
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
862
#if defined(DEBUG_SIGNAL)
863
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
864
           pc, address, is_write, *(unsigned long *)old_set);
865
#endif
866
    /* XXX: locking issue */
867
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
868
        return 1;
869
    }
870

    
871
    /* see if it is an MMU fault */
872
    ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
873
    if (ret < 0)
874
        return 0; /* not an MMU fault */
875
    if (ret == 0)
876
        return 1; /* the MMU fault was handled without causing real CPU fault */
877

    
878
    /* now we have a real cpu fault */
879
    tb = tb_find_pc(pc);
880
    if (tb) {
881
        /* the PC is inside the translated code. It means that we have
882
           a virtual CPU fault */
883
        cpu_restore_state(tb, env, pc, puc);
884
    }
885
    if (ret == 1) {
886
#if 0
887
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
888
               env->nip, env->error_code, tb);
889
#endif
890
    /* we restore the process signal mask as the sigreturn should
891
       do it (XXX: use sigsetjmp) */
892
        sigprocmask(SIG_SETMASK, old_set, NULL);
893
        do_raise_exception_err(env->exception_index, env->error_code);
894
    } else {
895
        /* activate soft MMU for this block */
896
        cpu_resume_from_signal(env, puc);
897
    }
898
    /* never comes here */
899
    return 1;
900
}
901

    
902
#elif defined(TARGET_M68K)
903
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
904
                                    int is_write, sigset_t *old_set,
905
                                    void *puc)
906
{
907
    TranslationBlock *tb;
908
    int ret;
909

    
910
    if (cpu_single_env)
911
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
912
#if defined(DEBUG_SIGNAL)
913
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
914
           pc, address, is_write, *(unsigned long *)old_set);
915
#endif
916
    /* XXX: locking issue */
917
    if (is_write && page_unprotect(address, pc, puc)) {
918
        return 1;
919
    }
920
    /* see if it is an MMU fault */
921
    ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
922
    if (ret < 0)
923
        return 0; /* not an MMU fault */
924
    if (ret == 0)
925
        return 1; /* the MMU fault was handled without causing real CPU fault */
926
    /* now we have a real cpu fault */
927
    tb = tb_find_pc(pc);
928
    if (tb) {
929
        /* the PC is inside the translated code. It means that we have
930
           a virtual CPU fault */
931
        cpu_restore_state(tb, env, pc, puc);
932
    }
933
    /* we restore the process signal mask as the sigreturn should
934
       do it (XXX: use sigsetjmp) */
935
    sigprocmask(SIG_SETMASK, old_set, NULL);
936
    cpu_loop_exit();
937
    /* never comes here */
938
    return 1;
939
}
940

    
941
#elif defined (TARGET_MIPS)
942
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
943
                                    int is_write, sigset_t *old_set,
944
                                    void *puc)
945
{
946
    TranslationBlock *tb;
947
    int ret;
948

    
949
    if (cpu_single_env)
950
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
951
#if defined(DEBUG_SIGNAL)
952
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
953
           pc, address, is_write, *(unsigned long *)old_set);
954
#endif
955
    /* XXX: locking issue */
956
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
957
        return 1;
958
    }
959

    
960
    /* see if it is an MMU fault */
961
    ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
962
    if (ret < 0)
963
        return 0; /* not an MMU fault */
964
    if (ret == 0)
965
        return 1; /* the MMU fault was handled without causing real CPU fault */
966

    
967
    /* now we have a real cpu fault */
968
    tb = tb_find_pc(pc);
969
    if (tb) {
970
        /* the PC is inside the translated code. It means that we have
971
           a virtual CPU fault */
972
        cpu_restore_state(tb, env, pc, puc);
973
    }
974
    if (ret == 1) {
975
#if 0
976
        printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
977
               env->PC, env->error_code, tb);
978
#endif
979
    /* we restore the process signal mask as the sigreturn should
980
       do it (XXX: use sigsetjmp) */
981
        sigprocmask(SIG_SETMASK, old_set, NULL);
982
        do_raise_exception_err(env->exception_index, env->error_code);
983
    } else {
984
        /* activate soft MMU for this block */
985
        cpu_resume_from_signal(env, puc);
986
    }
987
    /* never comes here */
988
    return 1;
989
}
990

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

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

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

    
1017
    /* now we have a real cpu fault */
1018
    tb = tb_find_pc(pc);
1019
    if (tb) {
1020
        /* the PC is inside the translated code. It means that we have
1021
           a virtual CPU fault */
1022
        cpu_restore_state(tb, env, pc, puc);
1023
    }
1024
#if 0
1025
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1026
               env->nip, env->error_code, tb);
1027
#endif
1028
    /* we restore the process signal mask as the sigreturn should
1029
       do it (XXX: use sigsetjmp) */
1030
    sigprocmask(SIG_SETMASK, old_set, NULL);
1031
    cpu_loop_exit();
1032
    /* never comes here */
1033
    return 1;
1034
}
1035

    
1036
#elif defined (TARGET_ALPHA)
1037
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1038
                                    int is_write, sigset_t *old_set,
1039
                                    void *puc)
1040
{
1041
    TranslationBlock *tb;
1042
    int ret;
1043

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

    
1055
    /* see if it is an MMU fault */
1056
    ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1057
    if (ret < 0)
1058
        return 0; /* not an MMU fault */
1059
    if (ret == 0)
1060
        return 1; /* the MMU fault was handled without causing real CPU fault */
1061

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

    
1088
    if (cpu_single_env)
1089
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1090
#if defined(DEBUG_SIGNAL)
1091
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1092
           pc, address, is_write, *(unsigned long *)old_set);
1093
#endif
1094
    /* XXX: locking issue */
1095
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1096
        return 1;
1097
    }
1098

    
1099
    /* see if it is an MMU fault */
1100
    ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1101
    if (ret < 0)
1102
        return 0; /* not an MMU fault */
1103
    if (ret == 0)
1104
        return 1; /* the MMU fault was handled without causing real CPU fault */
1105

    
1106
    /* now we have a real cpu fault */
1107
    tb = tb_find_pc(pc);
1108
    if (tb) {
1109
        /* the PC is inside the translated code. It means that we have
1110
           a virtual CPU fault */
1111
        cpu_restore_state(tb, env, pc, puc);
1112
    }
1113
    /* we restore the process signal mask as the sigreturn should
1114
       do it (XXX: use sigsetjmp) */
1115
    sigprocmask(SIG_SETMASK, old_set, NULL);
1116
    cpu_loop_exit();
1117
    /* never comes here */
1118
    return 1;
1119
}
1120

    
1121
#else
1122
#error unsupported target CPU
1123
#endif
1124

    
1125
#if defined(__i386__)
1126

    
1127
#if defined(__APPLE__)
1128
# include <sys/ucontext.h>
1129

    
1130
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1131
# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
1132
# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
1133
#else
1134
# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
1135
# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
1136
# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
1137
#endif
1138

    
1139
int cpu_signal_handler(int host_signum, void *pinfo,
1140
                       void *puc)
1141
{
1142
    siginfo_t *info = pinfo;
1143
    struct ucontext *uc = puc;
1144
    unsigned long pc;
1145
    int trapno;
1146

    
1147
#ifndef REG_EIP
1148
/* for glibc 2.1 */
1149
#define REG_EIP    EIP
1150
#define REG_ERR    ERR
1151
#define REG_TRAPNO TRAPNO
1152
#endif
1153
    pc = EIP_sig(uc);
1154
    trapno = TRAP_sig(uc);
1155
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1156
                             trapno == 0xe ?
1157
                             (ERROR_sig(uc) >> 1) & 1 : 0,
1158
                             &uc->uc_sigmask, puc);
1159
}
1160

    
1161
#elif defined(__x86_64__)
1162

    
1163
int cpu_signal_handler(int host_signum, void *pinfo,
1164
                       void *puc)
1165
{
1166
    siginfo_t *info = pinfo;
1167
    struct ucontext *uc = puc;
1168
    unsigned long pc;
1169

    
1170
    pc = uc->uc_mcontext.gregs[REG_RIP];
1171
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1172
                             uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
1173
                             (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1174
                             &uc->uc_sigmask, puc);
1175
}
1176

    
1177
#elif defined(__powerpc__)
1178

    
1179
/***********************************************************************
1180
 * signal context platform-specific definitions
1181
 * From Wine
1182
 */
1183
#ifdef linux
1184
/* All Registers access - only for local access */
1185
# define REG_sig(reg_name, context)                ((context)->uc_mcontext.regs->reg_name)
1186
/* Gpr Registers access  */
1187
# define GPR_sig(reg_num, context)                REG_sig(gpr[reg_num], context)
1188
# define IAR_sig(context)                        REG_sig(nip, context)        /* Program counter */
1189
# define MSR_sig(context)                        REG_sig(msr, context)   /* Machine State Register (Supervisor) */
1190
# define CTR_sig(context)                        REG_sig(ctr, context)   /* Count register */
1191
# define XER_sig(context)                        REG_sig(xer, context) /* User's integer exception register */
1192
# define LR_sig(context)                        REG_sig(link, context) /* Link register */
1193
# define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
1194
/* Float Registers access  */
1195
# define FLOAT_sig(reg_num, context)                (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1196
# define FPSCR_sig(context)                        (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1197
/* Exception Registers access */
1198
# define DAR_sig(context)                        REG_sig(dar, context)
1199
# define DSISR_sig(context)                        REG_sig(dsisr, context)
1200
# define TRAP_sig(context)                        REG_sig(trap, context)
1201
#endif /* linux */
1202

    
1203
#ifdef __APPLE__
1204
# include <sys/ucontext.h>
1205
typedef struct ucontext SIGCONTEXT;
1206
/* All Registers access - only for local access */
1207
# define REG_sig(reg_name, context)                ((context)->uc_mcontext->ss.reg_name)
1208
# define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
1209
# define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
1210
# define VECREG_sig(reg_name, context)                ((context)->uc_mcontext->vs.reg_name)
1211
/* Gpr Registers access */
1212
# define GPR_sig(reg_num, context)                REG_sig(r##reg_num, context)
1213
# define IAR_sig(context)                        REG_sig(srr0, context)        /* Program counter */
1214
# define MSR_sig(context)                        REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
1215
# define CTR_sig(context)                        REG_sig(ctr, context)
1216
# define XER_sig(context)                        REG_sig(xer, context) /* Link register */
1217
# define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
1218
# define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
1219
/* Float Registers access */
1220
# define FLOAT_sig(reg_num, context)                FLOATREG_sig(fpregs[reg_num], context)
1221
# define FPSCR_sig(context)                        ((double)FLOATREG_sig(fpscr, context))
1222
/* Exception Registers access */
1223
# define DAR_sig(context)                        EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
1224
# define DSISR_sig(context)                        EXCEPREG_sig(dsisr, context)
1225
# define TRAP_sig(context)                        EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1226
#endif /* __APPLE__ */
1227

    
1228
int cpu_signal_handler(int host_signum, void *pinfo,
1229
                       void *puc)
1230
{
1231
    siginfo_t *info = pinfo;
1232
    struct ucontext *uc = puc;
1233
    unsigned long pc;
1234
    int is_write;
1235

    
1236
    pc = IAR_sig(uc);
1237
    is_write = 0;
1238
#if 0
1239
    /* ppc 4xx case */
1240
    if (DSISR_sig(uc) & 0x00800000)
1241
        is_write = 1;
1242
#else
1243
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1244
        is_write = 1;
1245
#endif
1246
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1247
                             is_write, &uc->uc_sigmask, puc);
1248
}
1249

    
1250
#elif defined(__alpha__)
1251

    
1252
int cpu_signal_handler(int host_signum, void *pinfo,
1253
                           void *puc)
1254
{
1255
    siginfo_t *info = pinfo;
1256
    struct ucontext *uc = puc;
1257
    uint32_t *pc = uc->uc_mcontext.sc_pc;
1258
    uint32_t insn = *pc;
1259
    int is_write = 0;
1260

    
1261
    /* XXX: need kernel patch to get write flag faster */
1262
    switch (insn >> 26) {
1263
    case 0x0d: // stw
1264
    case 0x0e: // stb
1265
    case 0x0f: // stq_u
1266
    case 0x24: // stf
1267
    case 0x25: // stg
1268
    case 0x26: // sts
1269
    case 0x27: // stt
1270
    case 0x2c: // stl
1271
    case 0x2d: // stq
1272
    case 0x2e: // stl_c
1273
    case 0x2f: // stq_c
1274
        is_write = 1;
1275
    }
1276

    
1277
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1278
                             is_write, &uc->uc_sigmask, puc);
1279
}
1280
#elif defined(__sparc__)
1281

    
1282
int cpu_signal_handler(int host_signum, void *pinfo,
1283
                       void *puc)
1284
{
1285
    siginfo_t *info = pinfo;
1286
    int is_write;
1287
    uint32_t insn;
1288
#if !defined(__arch64__) || defined(HOST_SOLARIS)
1289
    uint32_t *regs = (uint32_t *)(info + 1);
1290
    void *sigmask = (regs + 20);
1291
    /* XXX: is there a standard glibc define ? */
1292
    unsigned long pc = regs[1];
1293
#else
1294
    struct sigcontext *sc = puc;
1295
    unsigned long pc = sc->sigc_regs.tpc;
1296
    void *sigmask = (void *)sc->sigc_mask;
1297
#endif
1298

    
1299
    /* XXX: need kernel patch to get write flag faster */
1300
    is_write = 0;
1301
    insn = *(uint32_t *)pc;
1302
    if ((insn >> 30) == 3) {
1303
      switch((insn >> 19) & 0x3f) {
1304
      case 0x05: // stb
1305
      case 0x06: // sth
1306
      case 0x04: // st
1307
      case 0x07: // std
1308
      case 0x24: // stf
1309
      case 0x27: // stdf
1310
      case 0x25: // stfsr
1311
        is_write = 1;
1312
        break;
1313
      }
1314
    }
1315
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1316
                             is_write, sigmask, NULL);
1317
}
1318

    
1319
#elif defined(__arm__)
1320

    
1321
int cpu_signal_handler(int host_signum, void *pinfo,
1322
                       void *puc)
1323
{
1324
    siginfo_t *info = pinfo;
1325
    struct ucontext *uc = puc;
1326
    unsigned long pc;
1327
    int is_write;
1328

    
1329
#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ =< 3))
1330
    pc = uc->uc_mcontext.gregs[R15];
1331
#else
1332
    pc = uc->uc_mcontext.arm_pc;
1333
#endif
1334
    /* XXX: compute is_write */
1335
    is_write = 0;
1336
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1337
                             is_write,
1338
                             &uc->uc_sigmask, puc);
1339
}
1340

    
1341
#elif defined(__mc68000)
1342

    
1343
int cpu_signal_handler(int host_signum, void *pinfo,
1344
                       void *puc)
1345
{
1346
    siginfo_t *info = pinfo;
1347
    struct ucontext *uc = puc;
1348
    unsigned long pc;
1349
    int is_write;
1350

    
1351
    pc = uc->uc_mcontext.gregs[16];
1352
    /* XXX: compute is_write */
1353
    is_write = 0;
1354
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1355
                             is_write,
1356
                             &uc->uc_sigmask, puc);
1357
}
1358

    
1359
#elif defined(__ia64)
1360

    
1361
#ifndef __ISR_VALID
1362
  /* This ought to be in <bits/siginfo.h>... */
1363
# define __ISR_VALID        1
1364
#endif
1365

    
1366
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1367
{
1368
    siginfo_t *info = pinfo;
1369
    struct ucontext *uc = puc;
1370
    unsigned long ip;
1371
    int is_write = 0;
1372

    
1373
    ip = uc->uc_mcontext.sc_ip;
1374
    switch (host_signum) {
1375
      case SIGILL:
1376
      case SIGFPE:
1377
      case SIGSEGV:
1378
      case SIGBUS:
1379
      case SIGTRAP:
1380
          if (info->si_code && (info->si_segvflags & __ISR_VALID))
1381
              /* ISR.W (write-access) is bit 33:  */
1382
              is_write = (info->si_isr >> 33) & 1;
1383
          break;
1384

    
1385
      default:
1386
          break;
1387
    }
1388
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1389
                             is_write,
1390
                             &uc->uc_sigmask, puc);
1391
}
1392

    
1393
#elif defined(__s390__)
1394

    
1395
int cpu_signal_handler(int host_signum, void *pinfo,
1396
                       void *puc)
1397
{
1398
    siginfo_t *info = pinfo;
1399
    struct ucontext *uc = puc;
1400
    unsigned long pc;
1401
    int is_write;
1402

    
1403
    pc = uc->uc_mcontext.psw.addr;
1404
    /* XXX: compute is_write */
1405
    is_write = 0;
1406
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1407
                             is_write, &uc->uc_sigmask, puc);
1408
}
1409

    
1410
#elif defined(__mips__)
1411

    
1412
int cpu_signal_handler(int host_signum, void *pinfo,
1413
                       void *puc)
1414
{
1415
    siginfo_t *info = pinfo;
1416
    struct ucontext *uc = puc;
1417
    greg_t pc = uc->uc_mcontext.pc;
1418
    int is_write;
1419

    
1420
    /* XXX: compute is_write */
1421
    is_write = 0;
1422
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1423
                             is_write, &uc->uc_sigmask, puc);
1424
}
1425

    
1426
#elif defined(__hppa__)
1427

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

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

    
1444
#else
1445

    
1446
#error host CPU specific signal handler needed
1447

    
1448
#endif
1449

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