Statistics
| Branch: | Revision:

root / cpu-exec.c @ 6792a57b

History | View | Annotate | Download (42.9 kB)

1
/*
2
 *  i386 emulator main execution loop
3
 *
4
 *  Copyright (c) 2003-2005 Fabrice Bellard
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 */
19
#include "config.h"
20
#include "exec.h"
21
#include "disas.h"
22
#include "tcg.h"
23
#include "kvm.h"
24
#include "qemu-barrier.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
#ifdef __linux__
38
#include <sys/ucontext.h>
39
#endif
40
#endif
41

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

    
48
int tb_invalidated_flag;
49

    
50
//#define CONFIG_DEBUG_EXEC
51
//#define DEBUG_SIGNAL
52

    
53
int qemu_cpu_has_work(CPUState *env)
54
{
55
    return cpu_has_work(env);
56
}
57

    
58
void cpu_loop_exit(void)
59
{
60
    env->current_tb = NULL;
61
    longjmp(env->jmp_env, 1);
62
}
63

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

    
77
    env = env1;
78

    
79
    /* XXX: restore cpu registers saved in host registers */
80

    
81
#if !defined(CONFIG_SOFTMMU)
82
    if (puc) {
83
        /* XXX: use siglongjmp ? */
84
#ifdef __linux__
85
#ifdef __ia64
86
        sigprocmask(SIG_SETMASK, (sigset_t *)&uc->uc_sigmask, NULL);
87
#else
88
        sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
89
#endif
90
#elif defined(__OpenBSD__)
91
        sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
92
#endif
93
    }
94
#endif
95
    env->exception_index = -1;
96
    longjmp(env->jmp_env, 1);
97
}
98

    
99
/* Execute the code without caching the generated code. An interpreter
100
   could be used if available. */
101
static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
102
{
103
    unsigned long next_tb;
104
    TranslationBlock *tb;
105

    
106
    /* Should never happen.
107
       We only end up here when an existing TB is too long.  */
108
    if (max_cycles > CF_COUNT_MASK)
109
        max_cycles = CF_COUNT_MASK;
110

    
111
    tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
112
                     max_cycles);
113
    env->current_tb = tb;
114
    /* execute the generated code */
115
    next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
116
    env->current_tb = NULL;
117

    
118
    if ((next_tb & 3) == 2) {
119
        /* Restore PC.  This may happen if async event occurs before
120
           the TB starts executing.  */
121
        cpu_pc_from_tb(env, tb);
122
    }
123
    tb_phys_invalidate(tb, -1);
124
    tb_free(tb);
125
}
126

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

    
136
    tb_invalidated_flag = 0;
137

    
138
    /* find translated block using physical mappings */
139
    phys_pc = get_page_addr_code(env, pc);
140
    phys_page1 = phys_pc & TARGET_PAGE_MASK;
141
    phys_page2 = -1;
142
    h = tb_phys_hash_func(phys_pc);
143
    ptb1 = &tb_phys_hash[h];
144
    for(;;) {
145
        tb = *ptb1;
146
        if (!tb)
147
            goto not_found;
148
        if (tb->pc == pc &&
149
            tb->page_addr[0] == phys_page1 &&
150
            tb->cs_base == cs_base &&
151
            tb->flags == flags) {
152
            /* check next page if needed */
153
            if (tb->page_addr[1] != -1) {
154
                virt_page2 = (pc & TARGET_PAGE_MASK) +
155
                    TARGET_PAGE_SIZE;
156
                phys_page2 = get_page_addr_code(env, virt_page2);
157
                if (tb->page_addr[1] == phys_page2)
158
                    goto found;
159
            } else {
160
                goto found;
161
            }
162
        }
163
        ptb1 = &tb->phys_hash_next;
164
    }
165
 not_found:
166
   /* if no translated code available, then translate it now */
167
    tb = tb_gen_code(env, pc, cs_base, flags, 0);
168

    
169
 found:
170
    /* Move the last found TB to the head of the list */
171
    if (likely(*ptb1)) {
172
        *ptb1 = tb->phys_hash_next;
173
        tb->phys_hash_next = tb_phys_hash[h];
174
        tb_phys_hash[h] = tb;
175
    }
176
    /* we add the TB in the virtual pc hash table */
177
    env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
178
    return tb;
179
}
180

    
181
static inline TranslationBlock *tb_find_fast(void)
182
{
183
    TranslationBlock *tb;
184
    target_ulong cs_base, pc;
185
    int flags;
186

    
187
    /* we record a subset of the CPU state. It will
188
       always be the same before a given translated block
189
       is executed. */
190
    cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
191
    tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
192
    if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
193
                 tb->flags != flags)) {
194
        tb = tb_find_slow(pc, cs_base, flags);
195
    }
196
    return tb;
197
}
198

    
199
/* main execution loop */
200

    
201
volatile sig_atomic_t exit_request;
202

    
203
int cpu_exec(CPUState *env1)
204
{
205
    volatile host_reg_t saved_env_reg;
206
    int ret, interrupt_request;
207
    TranslationBlock *tb;
208
    uint8_t *tc_ptr;
209
    unsigned long next_tb;
210

    
211
    if (cpu_halted(env1) == EXCP_HALTED)
212
        return EXCP_HALTED;
213

    
214
    cpu_single_env = env1;
215

    
216
    /* the access to env below is actually saving the global register's
217
       value, so that files not including target-xyz/exec.h are free to
218
       use it.  */
219
    QEMU_BUILD_BUG_ON (sizeof (saved_env_reg) != sizeof (env));
220
    saved_env_reg = (host_reg_t) env;
221
    barrier();
222
    env = env1;
223

    
224
    if (unlikely(exit_request)) {
225
        env->exit_request = 1;
226
    }
227

    
228
#if defined(TARGET_I386)
229
    /* put eflags in CPU temporary format */
230
    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
231
    DF = 1 - (2 * ((env->eflags >> 10) & 1));
232
    CC_OP = CC_OP_EFLAGS;
233
    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
234
#elif defined(TARGET_SPARC)
235
#elif defined(TARGET_M68K)
236
    env->cc_op = CC_OP_FLAGS;
237
    env->cc_dest = env->sr & 0xf;
238
    env->cc_x = (env->sr >> 4) & 1;
239
#elif defined(TARGET_ALPHA)
240
#elif defined(TARGET_ARM)
241
#elif defined(TARGET_PPC)
242
#elif defined(TARGET_MICROBLAZE)
243
#elif defined(TARGET_MIPS)
244
#elif defined(TARGET_SH4)
245
#elif defined(TARGET_CRIS)
246
#elif defined(TARGET_S390X)
247
    /* XXXXX */
248
#else
249
#error unsupported target CPU
250
#endif
251
    env->exception_index = -1;
252

    
253
    /* prepare setjmp context for exception handling */
254
    for(;;) {
255
        if (setjmp(env->jmp_env) == 0) {
256
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
257
#undef env
258
            env = cpu_single_env;
259
#define env cpu_single_env
260
#endif
261
            /* if an exception is pending, we execute it here */
262
            if (env->exception_index >= 0) {
263
                if (env->exception_index >= EXCP_INTERRUPT) {
264
                    /* exit request from the cpu execution loop */
265
                    ret = env->exception_index;
266
                    break;
267
                } else {
268
#if defined(CONFIG_USER_ONLY)
269
                    /* if user mode only, we simulate a fake exception
270
                       which will be handled outside the cpu execution
271
                       loop */
272
#if defined(TARGET_I386)
273
                    do_interrupt_user(env->exception_index,
274
                                      env->exception_is_int,
275
                                      env->error_code,
276
                                      env->exception_next_eip);
277
                    /* successfully delivered */
278
                    env->old_exception = -1;
279
#endif
280
                    ret = env->exception_index;
281
                    break;
282
#else
283
#if defined(TARGET_I386)
284
                    /* simulate a real cpu exception. On i386, it can
285
                       trigger new exceptions, but we do not handle
286
                       double or triple faults yet. */
287
                    do_interrupt(env->exception_index,
288
                                 env->exception_is_int,
289
                                 env->error_code,
290
                                 env->exception_next_eip, 0);
291
                    /* successfully delivered */
292
                    env->old_exception = -1;
293
#elif defined(TARGET_PPC)
294
                    do_interrupt(env);
295
#elif defined(TARGET_MICROBLAZE)
296
                    do_interrupt(env);
297
#elif defined(TARGET_MIPS)
298
                    do_interrupt(env);
299
#elif defined(TARGET_SPARC)
300
                    do_interrupt(env);
301
#elif defined(TARGET_ARM)
302
                    do_interrupt(env);
303
#elif defined(TARGET_SH4)
304
                    do_interrupt(env);
305
#elif defined(TARGET_ALPHA)
306
                    do_interrupt(env);
307
#elif defined(TARGET_CRIS)
308
                    do_interrupt(env);
309
#elif defined(TARGET_M68K)
310
                    do_interrupt(0);
311
#endif
312
                    env->exception_index = -1;
313
#endif
314
                }
315
            }
316

    
317
            next_tb = 0; /* force lookup of first TB */
318
            for(;;) {
319
                interrupt_request = env->interrupt_request;
320
                if (unlikely(interrupt_request)) {
321
                    if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
322
                        /* Mask out external interrupts for this step. */
323
                        interrupt_request &= ~(CPU_INTERRUPT_HARD |
324
                                               CPU_INTERRUPT_FIQ |
325
                                               CPU_INTERRUPT_SMI |
326
                                               CPU_INTERRUPT_NMI);
327
                    }
328
                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {
329
                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
330
                        env->exception_index = EXCP_DEBUG;
331
                        cpu_loop_exit();
332
                    }
333
#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
334
    defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
335
    defined(TARGET_MICROBLAZE)
336
                    if (interrupt_request & CPU_INTERRUPT_HALT) {
337
                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
338
                        env->halted = 1;
339
                        env->exception_index = EXCP_HLT;
340
                        cpu_loop_exit();
341
                    }
342
#endif
343
#if defined(TARGET_I386)
344
                    if (interrupt_request & CPU_INTERRUPT_INIT) {
345
                            svm_check_intercept(SVM_EXIT_INIT);
346
                            do_cpu_init(env);
347
                            env->exception_index = EXCP_HALTED;
348
                            cpu_loop_exit();
349
                    } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
350
                            do_cpu_sipi(env);
351
                    } else if (env->hflags2 & HF2_GIF_MASK) {
352
                        if ((interrupt_request & CPU_INTERRUPT_SMI) &&
353
                            !(env->hflags & HF_SMM_MASK)) {
354
                            svm_check_intercept(SVM_EXIT_SMI);
355
                            env->interrupt_request &= ~CPU_INTERRUPT_SMI;
356
                            do_smm_enter();
357
                            next_tb = 0;
358
                        } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
359
                                   !(env->hflags2 & HF2_NMI_MASK)) {
360
                            env->interrupt_request &= ~CPU_INTERRUPT_NMI;
361
                            env->hflags2 |= HF2_NMI_MASK;
362
                            do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
363
                            next_tb = 0;
364
                        } else if (interrupt_request & CPU_INTERRUPT_MCE) {
365
                            env->interrupt_request &= ~CPU_INTERRUPT_MCE;
366
                            do_interrupt(EXCP12_MCHK, 0, 0, 0, 0);
367
                            next_tb = 0;
368
                        } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
369
                                   (((env->hflags2 & HF2_VINTR_MASK) && 
370
                                     (env->hflags2 & HF2_HIF_MASK)) ||
371
                                    (!(env->hflags2 & HF2_VINTR_MASK) && 
372
                                     (env->eflags & IF_MASK && 
373
                                      !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
374
                            int intno;
375
                            svm_check_intercept(SVM_EXIT_INTR);
376
                            env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
377
                            intno = cpu_get_pic_interrupt(env);
378
                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
379
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
380
#undef env
381
                    env = cpu_single_env;
382
#define env cpu_single_env
383
#endif
384
                            do_interrupt(intno, 0, 0, 0, 1);
385
                            /* ensure that no TB jump will be modified as
386
                               the program flow was changed */
387
                            next_tb = 0;
388
#if !defined(CONFIG_USER_ONLY)
389
                        } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
390
                                   (env->eflags & IF_MASK) && 
391
                                   !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
392
                            int intno;
393
                            /* FIXME: this should respect TPR */
394
                            svm_check_intercept(SVM_EXIT_VINTR);
395
                            intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
396
                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
397
                            do_interrupt(intno, 0, 0, 0, 1);
398
                            env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
399
                            next_tb = 0;
400
#endif
401
                        }
402
                    }
403
#elif defined(TARGET_PPC)
404
#if 0
405
                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
406
                        cpu_reset(env);
407
                    }
408
#endif
409
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
410
                        ppc_hw_interrupt(env);
411
                        if (env->pending_interrupts == 0)
412
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
413
                        next_tb = 0;
414
                    }
415
#elif defined(TARGET_MICROBLAZE)
416
                    if ((interrupt_request & CPU_INTERRUPT_HARD)
417
                        && (env->sregs[SR_MSR] & MSR_IE)
418
                        && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
419
                        && !(env->iflags & (D_FLAG | IMM_FLAG))) {
420
                        env->exception_index = EXCP_IRQ;
421
                        do_interrupt(env);
422
                        next_tb = 0;
423
                    }
424
#elif defined(TARGET_MIPS)
425
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
426
                        cpu_mips_hw_interrupts_pending(env)) {
427
                        /* Raise it */
428
                        env->exception_index = EXCP_EXT_INTERRUPT;
429
                        env->error_code = 0;
430
                        do_interrupt(env);
431
                        next_tb = 0;
432
                    }
433
#elif defined(TARGET_SPARC)
434
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
435
                        if (cpu_interrupts_enabled(env) &&
436
                            env->interrupt_index > 0) {
437
                            int pil = env->interrupt_index & 0xf;
438
                            int type = env->interrupt_index & 0xf0;
439

    
440
                            if (((type == TT_EXTINT) &&
441
                                  cpu_pil_allowed(env, pil)) ||
442
                                  type != TT_EXTINT) {
443
                                env->exception_index = env->interrupt_index;
444
                                do_interrupt(env);
445
                                next_tb = 0;
446
                            }
447
                        }
448
                    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
449
                        //do_interrupt(0, 0, 0, 0, 0);
450
                        env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
451
                    }
452
#elif defined(TARGET_ARM)
453
                    if (interrupt_request & CPU_INTERRUPT_FIQ
454
                        && !(env->uncached_cpsr & CPSR_F)) {
455
                        env->exception_index = EXCP_FIQ;
456
                        do_interrupt(env);
457
                        next_tb = 0;
458
                    }
459
                    /* ARMv7-M interrupt return works by loading a magic value
460
                       into the PC.  On real hardware the load causes the
461
                       return to occur.  The qemu implementation performs the
462
                       jump normally, then does the exception return when the
463
                       CPU tries to execute code at the magic address.
464
                       This will cause the magic PC value to be pushed to
465
                       the stack if an interrupt occured at the wrong time.
466
                       We avoid this by disabling interrupts when
467
                       pc contains a magic address.  */
468
                    if (interrupt_request & CPU_INTERRUPT_HARD
469
                        && ((IS_M(env) && env->regs[15] < 0xfffffff0)
470
                            || !(env->uncached_cpsr & CPSR_I))) {
471
                        env->exception_index = EXCP_IRQ;
472
                        do_interrupt(env);
473
                        next_tb = 0;
474
                    }
475
#elif defined(TARGET_SH4)
476
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
477
                        do_interrupt(env);
478
                        next_tb = 0;
479
                    }
480
#elif defined(TARGET_ALPHA)
481
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
482
                        do_interrupt(env);
483
                        next_tb = 0;
484
                    }
485
#elif defined(TARGET_CRIS)
486
                    if (interrupt_request & CPU_INTERRUPT_HARD
487
                        && (env->pregs[PR_CCS] & I_FLAG)
488
                        && !env->locked_irq) {
489
                        env->exception_index = EXCP_IRQ;
490
                        do_interrupt(env);
491
                        next_tb = 0;
492
                    }
493
                    if (interrupt_request & CPU_INTERRUPT_NMI
494
                        && (env->pregs[PR_CCS] & M_FLAG)) {
495
                        env->exception_index = EXCP_NMI;
496
                        do_interrupt(env);
497
                        next_tb = 0;
498
                    }
499
#elif defined(TARGET_M68K)
500
                    if (interrupt_request & CPU_INTERRUPT_HARD
501
                        && ((env->sr & SR_I) >> SR_I_SHIFT)
502
                            < env->pending_level) {
503
                        /* Real hardware gets the interrupt vector via an
504
                           IACK cycle at this point.  Current emulated
505
                           hardware doesn't rely on this, so we
506
                           provide/save the vector when the interrupt is
507
                           first signalled.  */
508
                        env->exception_index = env->pending_vector;
509
                        do_interrupt(1);
510
                        next_tb = 0;
511
                    }
512
#endif
513
                   /* Don't use the cached interupt_request value,
514
                      do_interrupt may have updated the EXITTB flag. */
515
                    if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
516
                        env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
517
                        /* ensure that no TB jump will be modified as
518
                           the program flow was changed */
519
                        next_tb = 0;
520
                    }
521
                }
522
                if (unlikely(env->exit_request)) {
523
                    env->exit_request = 0;
524
                    env->exception_index = EXCP_INTERRUPT;
525
                    cpu_loop_exit();
526
                }
527
#if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
528
                if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
529
                    /* restore flags in standard format */
530
#if defined(TARGET_I386)
531
                    env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
532
                    log_cpu_state(env, X86_DUMP_CCOP);
533
                    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
534
#elif defined(TARGET_M68K)
535
                    cpu_m68k_flush_flags(env, env->cc_op);
536
                    env->cc_op = CC_OP_FLAGS;
537
                    env->sr = (env->sr & 0xffe0)
538
                              | env->cc_dest | (env->cc_x << 4);
539
                    log_cpu_state(env, 0);
540
#else
541
                    log_cpu_state(env, 0);
542
#endif
543
                }
544
#endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
545
                spin_lock(&tb_lock);
546
                tb = tb_find_fast();
547
                /* Note: we do it here to avoid a gcc bug on Mac OS X when
548
                   doing it in tb_find_slow */
549
                if (tb_invalidated_flag) {
550
                    /* as some TB could have been invalidated because
551
                       of memory exceptions while generating the code, we
552
                       must recompute the hash index here */
553
                    next_tb = 0;
554
                    tb_invalidated_flag = 0;
555
                }
556
#ifdef CONFIG_DEBUG_EXEC
557
                qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
558
                             (long)tb->tc_ptr, tb->pc,
559
                             lookup_symbol(tb->pc));
560
#endif
561
                /* see if we can patch the calling TB. When the TB
562
                   spans two pages, we cannot safely do a direct
563
                   jump. */
564
                if (next_tb != 0 && tb->page_addr[1] == -1) {
565
                    tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
566
                }
567
                spin_unlock(&tb_lock);
568

    
569
                /* cpu_interrupt might be called while translating the
570
                   TB, but before it is linked into a potentially
571
                   infinite loop and becomes env->current_tb. Avoid
572
                   starting execution if there is a pending interrupt. */
573
                env->current_tb = tb;
574
                barrier();
575
                if (likely(!env->exit_request)) {
576
                    tc_ptr = tb->tc_ptr;
577
                /* execute the generated code */
578
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
579
#undef env
580
                    env = cpu_single_env;
581
#define env cpu_single_env
582
#endif
583
                    next_tb = tcg_qemu_tb_exec(tc_ptr);
584
                    if ((next_tb & 3) == 2) {
585
                        /* Instruction counter expired.  */
586
                        int insns_left;
587
                        tb = (TranslationBlock *)(long)(next_tb & ~3);
588
                        /* Restore PC.  */
589
                        cpu_pc_from_tb(env, tb);
590
                        insns_left = env->icount_decr.u32;
591
                        if (env->icount_extra && insns_left >= 0) {
592
                            /* Refill decrementer and continue execution.  */
593
                            env->icount_extra += insns_left;
594
                            if (env->icount_extra > 0xffff) {
595
                                insns_left = 0xffff;
596
                            } else {
597
                                insns_left = env->icount_extra;
598
                            }
599
                            env->icount_extra -= insns_left;
600
                            env->icount_decr.u16.low = insns_left;
601
                        } else {
602
                            if (insns_left > 0) {
603
                                /* Execute remaining instructions.  */
604
                                cpu_exec_nocache(insns_left, tb);
605
                            }
606
                            env->exception_index = EXCP_INTERRUPT;
607
                            next_tb = 0;
608
                            cpu_loop_exit();
609
                        }
610
                    }
611
                }
612
                env->current_tb = NULL;
613
                /* reset soft MMU for next block (it can currently
614
                   only be set by a memory fault) */
615
            } /* for(;;) */
616
        }
617
    } /* for(;;) */
618

    
619

    
620
#if defined(TARGET_I386)
621
    /* restore flags in standard format */
622
    env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
623
#elif defined(TARGET_ARM)
624
    /* XXX: Save/restore host fpu exception state?.  */
625
#elif defined(TARGET_SPARC)
626
#elif defined(TARGET_PPC)
627
#elif defined(TARGET_M68K)
628
    cpu_m68k_flush_flags(env, env->cc_op);
629
    env->cc_op = CC_OP_FLAGS;
630
    env->sr = (env->sr & 0xffe0)
631
              | env->cc_dest | (env->cc_x << 4);
632
#elif defined(TARGET_MICROBLAZE)
633
#elif defined(TARGET_MIPS)
634
#elif defined(TARGET_SH4)
635
#elif defined(TARGET_ALPHA)
636
#elif defined(TARGET_CRIS)
637
#elif defined(TARGET_S390X)
638
    /* XXXXX */
639
#else
640
#error unsupported target CPU
641
#endif
642

    
643
    /* restore global registers */
644
    barrier();
645
    env = (void *) saved_env_reg;
646

    
647
    /* fail safe : never use cpu_single_env outside cpu_exec() */
648
    cpu_single_env = NULL;
649
    return ret;
650
}
651

    
652
/* must only be called from the generated code as an exception can be
653
   generated */
654
void tb_invalidate_page_range(target_ulong start, target_ulong end)
655
{
656
    /* XXX: cannot enable it yet because it yields to MMU exception
657
       where NIP != read address on PowerPC */
658
#if 0
659
    target_ulong phys_addr;
660
    phys_addr = get_phys_addr_code(env, start);
661
    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
662
#endif
663
}
664

    
665
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
666

    
667
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
668
{
669
    CPUX86State *saved_env;
670

    
671
    saved_env = env;
672
    env = s;
673
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
674
        selector &= 0xffff;
675
        cpu_x86_load_seg_cache(env, seg_reg, selector,
676
                               (selector << 4), 0xffff, 0);
677
    } else {
678
        helper_load_seg(seg_reg, selector);
679
    }
680
    env = saved_env;
681
}
682

    
683
void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
684
{
685
    CPUX86State *saved_env;
686

    
687
    saved_env = env;
688
    env = s;
689

    
690
    helper_fsave(ptr, data32);
691

    
692
    env = saved_env;
693
}
694

    
695
void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
696
{
697
    CPUX86State *saved_env;
698

    
699
    saved_env = env;
700
    env = s;
701

    
702
    helper_frstor(ptr, data32);
703

    
704
    env = saved_env;
705
}
706

    
707
#endif /* TARGET_I386 */
708

    
709
#if !defined(CONFIG_SOFTMMU)
710

    
711
#if defined(TARGET_I386)
712
#define EXCEPTION_ACTION raise_exception_err(env->exception_index, env->error_code)
713
#else
714
#define EXCEPTION_ACTION cpu_loop_exit()
715
#endif
716

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

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

    
739
    /* see if it is an MMU fault */
740
    ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
741
    if (ret < 0)
742
        return 0; /* not an MMU fault */
743
    if (ret == 0)
744
        return 1; /* the MMU fault was handled without causing real CPU fault */
745
    /* now we have a real cpu fault */
746
    tb = tb_find_pc(pc);
747
    if (tb) {
748
        /* the PC is inside the translated code. It means that we have
749
           a virtual CPU fault */
750
        cpu_restore_state(tb, env, pc, puc);
751
    }
752

    
753
    /* we restore the process signal mask as the sigreturn should
754
       do it (XXX: use sigsetjmp) */
755
    sigprocmask(SIG_SETMASK, old_set, NULL);
756
    EXCEPTION_ACTION;
757

    
758
    /* never comes here */
759
    return 1;
760
}
761

    
762
#if defined(__i386__)
763

    
764
#if defined(__APPLE__)
765
# include <sys/ucontext.h>
766

    
767
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
768
# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
769
# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
770
# define MASK_sig(context)    ((context)->uc_sigmask)
771
#elif defined (__NetBSD__)
772
# include <ucontext.h>
773

    
774
# define EIP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_EIP])
775
# define TRAP_sig(context)    ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
776
# define ERROR_sig(context)   ((context)->uc_mcontext.__gregs[_REG_ERR])
777
# define MASK_sig(context)    ((context)->uc_sigmask)
778
#elif defined (__FreeBSD__) || defined(__DragonFly__)
779
# include <ucontext.h>
780

    
781
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_eip))
782
# define TRAP_sig(context)    ((context)->uc_mcontext.mc_trapno)
783
# define ERROR_sig(context)   ((context)->uc_mcontext.mc_err)
784
# define MASK_sig(context)    ((context)->uc_sigmask)
785
#elif defined(__OpenBSD__)
786
# define EIP_sig(context)     ((context)->sc_eip)
787
# define TRAP_sig(context)    ((context)->sc_trapno)
788
# define ERROR_sig(context)   ((context)->sc_err)
789
# define MASK_sig(context)    ((context)->sc_mask)
790
#else
791
# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
792
# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
793
# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
794
# define MASK_sig(context)    ((context)->uc_sigmask)
795
#endif
796

    
797
int cpu_signal_handler(int host_signum, void *pinfo,
798
                       void *puc)
799
{
800
    siginfo_t *info = pinfo;
801
#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
802
    ucontext_t *uc = puc;
803
#elif defined(__OpenBSD__)
804
    struct sigcontext *uc = puc;
805
#else
806
    struct ucontext *uc = puc;
807
#endif
808
    unsigned long pc;
809
    int trapno;
810

    
811
#ifndef REG_EIP
812
/* for glibc 2.1 */
813
#define REG_EIP    EIP
814
#define REG_ERR    ERR
815
#define REG_TRAPNO TRAPNO
816
#endif
817
    pc = EIP_sig(uc);
818
    trapno = TRAP_sig(uc);
819
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
820
                             trapno == 0xe ?
821
                             (ERROR_sig(uc) >> 1) & 1 : 0,
822
                             &MASK_sig(uc), puc);
823
}
824

    
825
#elif defined(__x86_64__)
826

    
827
#ifdef __NetBSD__
828
#define PC_sig(context)       _UC_MACHINE_PC(context)
829
#define TRAP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
830
#define ERROR_sig(context)    ((context)->uc_mcontext.__gregs[_REG_ERR])
831
#define MASK_sig(context)     ((context)->uc_sigmask)
832
#elif defined(__OpenBSD__)
833
#define PC_sig(context)       ((context)->sc_rip)
834
#define TRAP_sig(context)     ((context)->sc_trapno)
835
#define ERROR_sig(context)    ((context)->sc_err)
836
#define MASK_sig(context)     ((context)->sc_mask)
837
#elif defined (__FreeBSD__) || defined(__DragonFly__)
838
#include <ucontext.h>
839

    
840
#define PC_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_rip))
841
#define TRAP_sig(context)     ((context)->uc_mcontext.mc_trapno)
842
#define ERROR_sig(context)    ((context)->uc_mcontext.mc_err)
843
#define MASK_sig(context)     ((context)->uc_sigmask)
844
#else
845
#define PC_sig(context)       ((context)->uc_mcontext.gregs[REG_RIP])
846
#define TRAP_sig(context)     ((context)->uc_mcontext.gregs[REG_TRAPNO])
847
#define ERROR_sig(context)    ((context)->uc_mcontext.gregs[REG_ERR])
848
#define MASK_sig(context)     ((context)->uc_sigmask)
849
#endif
850

    
851
int cpu_signal_handler(int host_signum, void *pinfo,
852
                       void *puc)
853
{
854
    siginfo_t *info = pinfo;
855
    unsigned long pc;
856
#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
857
    ucontext_t *uc = puc;
858
#elif defined(__OpenBSD__)
859
    struct sigcontext *uc = puc;
860
#else
861
    struct ucontext *uc = puc;
862
#endif
863

    
864
    pc = PC_sig(uc);
865
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
866
                             TRAP_sig(uc) == 0xe ?
867
                             (ERROR_sig(uc) >> 1) & 1 : 0,
868
                             &MASK_sig(uc), puc);
869
}
870

    
871
#elif defined(_ARCH_PPC)
872

    
873
/***********************************************************************
874
 * signal context platform-specific definitions
875
 * From Wine
876
 */
877
#ifdef linux
878
/* All Registers access - only for local access */
879
# define REG_sig(reg_name, context)                ((context)->uc_mcontext.regs->reg_name)
880
/* Gpr Registers access  */
881
# define GPR_sig(reg_num, context)                REG_sig(gpr[reg_num], context)
882
# define IAR_sig(context)                        REG_sig(nip, context)        /* Program counter */
883
# define MSR_sig(context)                        REG_sig(msr, context)   /* Machine State Register (Supervisor) */
884
# define CTR_sig(context)                        REG_sig(ctr, context)   /* Count register */
885
# define XER_sig(context)                        REG_sig(xer, context) /* User's integer exception register */
886
# define LR_sig(context)                        REG_sig(link, context) /* Link register */
887
# define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
888
/* Float Registers access  */
889
# define FLOAT_sig(reg_num, context)                (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
890
# define FPSCR_sig(context)                        (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
891
/* Exception Registers access */
892
# define DAR_sig(context)                        REG_sig(dar, context)
893
# define DSISR_sig(context)                        REG_sig(dsisr, context)
894
# define TRAP_sig(context)                        REG_sig(trap, context)
895
#endif /* linux */
896

    
897
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
898
#include <ucontext.h>
899
# define IAR_sig(context)                ((context)->uc_mcontext.mc_srr0)
900
# define MSR_sig(context)                ((context)->uc_mcontext.mc_srr1)
901
# define CTR_sig(context)                ((context)->uc_mcontext.mc_ctr)
902
# define XER_sig(context)                ((context)->uc_mcontext.mc_xer)
903
# define LR_sig(context)                ((context)->uc_mcontext.mc_lr)
904
# define CR_sig(context)                ((context)->uc_mcontext.mc_cr)
905
/* Exception Registers access */
906
# define DAR_sig(context)                ((context)->uc_mcontext.mc_dar)
907
# define DSISR_sig(context)                ((context)->uc_mcontext.mc_dsisr)
908
# define TRAP_sig(context)                ((context)->uc_mcontext.mc_exc)
909
#endif /* __FreeBSD__|| __FreeBSD_kernel__ */
910

    
911
#ifdef __APPLE__
912
# include <sys/ucontext.h>
913
typedef struct ucontext SIGCONTEXT;
914
/* All Registers access - only for local access */
915
# define REG_sig(reg_name, context)                ((context)->uc_mcontext->ss.reg_name)
916
# define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
917
# define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
918
# define VECREG_sig(reg_name, context)                ((context)->uc_mcontext->vs.reg_name)
919
/* Gpr Registers access */
920
# define GPR_sig(reg_num, context)                REG_sig(r##reg_num, context)
921
# define IAR_sig(context)                        REG_sig(srr0, context)        /* Program counter */
922
# define MSR_sig(context)                        REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
923
# define CTR_sig(context)                        REG_sig(ctr, context)
924
# define XER_sig(context)                        REG_sig(xer, context) /* Link register */
925
# define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
926
# define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
927
/* Float Registers access */
928
# define FLOAT_sig(reg_num, context)                FLOATREG_sig(fpregs[reg_num], context)
929
# define FPSCR_sig(context)                        ((double)FLOATREG_sig(fpscr, context))
930
/* Exception Registers access */
931
# define DAR_sig(context)                        EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
932
# define DSISR_sig(context)                        EXCEPREG_sig(dsisr, context)
933
# define TRAP_sig(context)                        EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
934
#endif /* __APPLE__ */
935

    
936
int cpu_signal_handler(int host_signum, void *pinfo,
937
                       void *puc)
938
{
939
    siginfo_t *info = pinfo;
940
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
941
    ucontext_t *uc = puc;
942
#else
943
    struct ucontext *uc = puc;
944
#endif
945
    unsigned long pc;
946
    int is_write;
947

    
948
    pc = IAR_sig(uc);
949
    is_write = 0;
950
#if 0
951
    /* ppc 4xx case */
952
    if (DSISR_sig(uc) & 0x00800000)
953
        is_write = 1;
954
#else
955
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
956
        is_write = 1;
957
#endif
958
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
959
                             is_write, &uc->uc_sigmask, puc);
960
}
961

    
962
#elif defined(__alpha__)
963

    
964
int cpu_signal_handler(int host_signum, void *pinfo,
965
                           void *puc)
966
{
967
    siginfo_t *info = pinfo;
968
    struct ucontext *uc = puc;
969
    uint32_t *pc = uc->uc_mcontext.sc_pc;
970
    uint32_t insn = *pc;
971
    int is_write = 0;
972

    
973
    /* XXX: need kernel patch to get write flag faster */
974
    switch (insn >> 26) {
975
    case 0x0d: // stw
976
    case 0x0e: // stb
977
    case 0x0f: // stq_u
978
    case 0x24: // stf
979
    case 0x25: // stg
980
    case 0x26: // sts
981
    case 0x27: // stt
982
    case 0x2c: // stl
983
    case 0x2d: // stq
984
    case 0x2e: // stl_c
985
    case 0x2f: // stq_c
986
        is_write = 1;
987
    }
988

    
989
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
990
                             is_write, &uc->uc_sigmask, puc);
991
}
992
#elif defined(__sparc__)
993

    
994
int cpu_signal_handler(int host_signum, void *pinfo,
995
                       void *puc)
996
{
997
    siginfo_t *info = pinfo;
998
    int is_write;
999
    uint32_t insn;
1000
#if !defined(__arch64__) || defined(CONFIG_SOLARIS)
1001
    uint32_t *regs = (uint32_t *)(info + 1);
1002
    void *sigmask = (regs + 20);
1003
    /* XXX: is there a standard glibc define ? */
1004
    unsigned long pc = regs[1];
1005
#else
1006
#ifdef __linux__
1007
    struct sigcontext *sc = puc;
1008
    unsigned long pc = sc->sigc_regs.tpc;
1009
    void *sigmask = (void *)sc->sigc_mask;
1010
#elif defined(__OpenBSD__)
1011
    struct sigcontext *uc = puc;
1012
    unsigned long pc = uc->sc_pc;
1013
    void *sigmask = (void *)(long)uc->sc_mask;
1014
#endif
1015
#endif
1016

    
1017
    /* XXX: need kernel patch to get write flag faster */
1018
    is_write = 0;
1019
    insn = *(uint32_t *)pc;
1020
    if ((insn >> 30) == 3) {
1021
      switch((insn >> 19) & 0x3f) {
1022
      case 0x05: // stb
1023
      case 0x15: // stba
1024
      case 0x06: // sth
1025
      case 0x16: // stha
1026
      case 0x04: // st
1027
      case 0x14: // sta
1028
      case 0x07: // std
1029
      case 0x17: // stda
1030
      case 0x0e: // stx
1031
      case 0x1e: // stxa
1032
      case 0x24: // stf
1033
      case 0x34: // stfa
1034
      case 0x27: // stdf
1035
      case 0x37: // stdfa
1036
      case 0x26: // stqf
1037
      case 0x36: // stqfa
1038
      case 0x25: // stfsr
1039
      case 0x3c: // casa
1040
      case 0x3e: // casxa
1041
        is_write = 1;
1042
        break;
1043
      }
1044
    }
1045
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1046
                             is_write, sigmask, NULL);
1047
}
1048

    
1049
#elif defined(__arm__)
1050

    
1051
int cpu_signal_handler(int host_signum, void *pinfo,
1052
                       void *puc)
1053
{
1054
    siginfo_t *info = pinfo;
1055
    struct ucontext *uc = puc;
1056
    unsigned long pc;
1057
    int is_write;
1058

    
1059
#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
1060
    pc = uc->uc_mcontext.gregs[R15];
1061
#else
1062
    pc = uc->uc_mcontext.arm_pc;
1063
#endif
1064
    /* XXX: compute is_write */
1065
    is_write = 0;
1066
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1067
                             is_write,
1068
                             &uc->uc_sigmask, puc);
1069
}
1070

    
1071
#elif defined(__mc68000)
1072

    
1073
int cpu_signal_handler(int host_signum, void *pinfo,
1074
                       void *puc)
1075
{
1076
    siginfo_t *info = pinfo;
1077
    struct ucontext *uc = puc;
1078
    unsigned long pc;
1079
    int is_write;
1080

    
1081
    pc = uc->uc_mcontext.gregs[16];
1082
    /* XXX: compute is_write */
1083
    is_write = 0;
1084
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1085
                             is_write,
1086
                             &uc->uc_sigmask, puc);
1087
}
1088

    
1089
#elif defined(__ia64)
1090

    
1091
#ifndef __ISR_VALID
1092
  /* This ought to be in <bits/siginfo.h>... */
1093
# define __ISR_VALID        1
1094
#endif
1095

    
1096
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1097
{
1098
    siginfo_t *info = pinfo;
1099
    struct ucontext *uc = puc;
1100
    unsigned long ip;
1101
    int is_write = 0;
1102

    
1103
    ip = uc->uc_mcontext.sc_ip;
1104
    switch (host_signum) {
1105
      case SIGILL:
1106
      case SIGFPE:
1107
      case SIGSEGV:
1108
      case SIGBUS:
1109
      case SIGTRAP:
1110
          if (info->si_code && (info->si_segvflags & __ISR_VALID))
1111
              /* ISR.W (write-access) is bit 33:  */
1112
              is_write = (info->si_isr >> 33) & 1;
1113
          break;
1114

    
1115
      default:
1116
          break;
1117
    }
1118
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1119
                             is_write,
1120
                             (sigset_t *)&uc->uc_sigmask, puc);
1121
}
1122

    
1123
#elif defined(__s390__)
1124

    
1125
int cpu_signal_handler(int host_signum, void *pinfo,
1126
                       void *puc)
1127
{
1128
    siginfo_t *info = pinfo;
1129
    struct ucontext *uc = puc;
1130
    unsigned long pc;
1131
    uint16_t *pinsn;
1132
    int is_write = 0;
1133

    
1134
    pc = uc->uc_mcontext.psw.addr;
1135

    
1136
    /* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
1137
       of the normal 2 arguments.  The 3rd argument contains the "int_code"
1138
       from the hardware which does in fact contain the is_write value.
1139
       The rt signal handler, as far as I can tell, does not give this value
1140
       at all.  Not that we could get to it from here even if it were.  */
1141
    /* ??? This is not even close to complete, since it ignores all
1142
       of the read-modify-write instructions.  */
1143
    pinsn = (uint16_t *)pc;
1144
    switch (pinsn[0] >> 8) {
1145
    case 0x50: /* ST */
1146
    case 0x42: /* STC */
1147
    case 0x40: /* STH */
1148
        is_write = 1;
1149
        break;
1150
    case 0xc4: /* RIL format insns */
1151
        switch (pinsn[0] & 0xf) {
1152
        case 0xf: /* STRL */
1153
        case 0xb: /* STGRL */
1154
        case 0x7: /* STHRL */
1155
            is_write = 1;
1156
        }
1157
        break;
1158
    case 0xe3: /* RXY format insns */
1159
        switch (pinsn[2] & 0xff) {
1160
        case 0x50: /* STY */
1161
        case 0x24: /* STG */
1162
        case 0x72: /* STCY */
1163
        case 0x70: /* STHY */
1164
        case 0x8e: /* STPQ */
1165
        case 0x3f: /* STRVH */
1166
        case 0x3e: /* STRV */
1167
        case 0x2f: /* STRVG */
1168
            is_write = 1;
1169
        }
1170
        break;
1171
    }
1172
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1173
                             is_write, &uc->uc_sigmask, puc);
1174
}
1175

    
1176
#elif defined(__mips__)
1177

    
1178
int cpu_signal_handler(int host_signum, void *pinfo,
1179
                       void *puc)
1180
{
1181
    siginfo_t *info = pinfo;
1182
    struct ucontext *uc = puc;
1183
    greg_t pc = uc->uc_mcontext.pc;
1184
    int is_write;
1185

    
1186
    /* XXX: compute is_write */
1187
    is_write = 0;
1188
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1189
                             is_write, &uc->uc_sigmask, puc);
1190
}
1191

    
1192
#elif defined(__hppa__)
1193

    
1194
int cpu_signal_handler(int host_signum, void *pinfo,
1195
                       void *puc)
1196
{
1197
    struct siginfo *info = pinfo;
1198
    struct ucontext *uc = puc;
1199
    unsigned long pc = uc->uc_mcontext.sc_iaoq[0];
1200
    uint32_t insn = *(uint32_t *)pc;
1201
    int is_write = 0;
1202

    
1203
    /* XXX: need kernel patch to get write flag faster.  */
1204
    switch (insn >> 26) {
1205
    case 0x1a: /* STW */
1206
    case 0x19: /* STH */
1207
    case 0x18: /* STB */
1208
    case 0x1b: /* STWM */
1209
        is_write = 1;
1210
        break;
1211

    
1212
    case 0x09: /* CSTWX, FSTWX, FSTWS */
1213
    case 0x0b: /* CSTDX, FSTDX, FSTDS */
1214
        /* Distinguish from coprocessor load ... */
1215
        is_write = (insn >> 9) & 1;
1216
        break;
1217

    
1218
    case 0x03:
1219
        switch ((insn >> 6) & 15) {
1220
        case 0xa: /* STWS */
1221
        case 0x9: /* STHS */
1222
        case 0x8: /* STBS */
1223
        case 0xe: /* STWAS */
1224
        case 0xc: /* STBYS */
1225
            is_write = 1;
1226
        }
1227
        break;
1228
    }
1229

    
1230
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1231
                             is_write, &uc->uc_sigmask, puc);
1232
}
1233

    
1234
#else
1235

    
1236
#error host CPU specific signal handler needed
1237

    
1238
#endif
1239

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