Statistics
| Branch: | Revision:

root / cpu-exec.c @ 6af0bf9c

History | View | Annotate | Download (41.4 kB)

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

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

    
38
int tb_invalidated_flag;
39

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

    
43
#if defined(TARGET_ARM) || defined(TARGET_SPARC)
44
/* XXX: unify with i386 target */
45
void cpu_loop_exit(void)
46
{
47
    longjmp(env->jmp_env, 1);
48
}
49
#endif
50
#ifndef TARGET_SPARC
51
#define reg_T2
52
#endif
53

    
54
/* exit the current TB from a signal handler. The host registers are
55
   restored in a state compatible with the CPU emulator
56
 */
57
void cpu_resume_from_signal(CPUState *env1, void *puc) 
58
{
59
#if !defined(CONFIG_SOFTMMU)
60
    struct ucontext *uc = puc;
61
#endif
62

    
63
    env = env1;
64

    
65
    /* XXX: restore cpu registers saved in host registers */
66

    
67
#if !defined(CONFIG_SOFTMMU)
68
    if (puc) {
69
        /* XXX: use siglongjmp ? */
70
        sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
71
    }
72
#endif
73
    longjmp(env->jmp_env, 1);
74
}
75

    
76
/* main execution loop */
77

    
78
int cpu_exec(CPUState *env1)
79
{
80
    int saved_T0, saved_T1;
81
#if defined(reg_T2)
82
    int saved_T2;
83
#endif
84
    CPUState *saved_env;
85
#if defined(TARGET_I386)
86
#ifdef reg_EAX
87
    int saved_EAX;
88
#endif
89
#ifdef reg_ECX
90
    int saved_ECX;
91
#endif
92
#ifdef reg_EDX
93
    int saved_EDX;
94
#endif
95
#ifdef reg_EBX
96
    int saved_EBX;
97
#endif
98
#ifdef reg_ESP
99
    int saved_ESP;
100
#endif
101
#ifdef reg_EBP
102
    int saved_EBP;
103
#endif
104
#ifdef reg_ESI
105
    int saved_ESI;
106
#endif
107
#ifdef reg_EDI
108
    int saved_EDI;
109
#endif
110
#elif defined(TARGET_SPARC)
111
#if defined(reg_REGWPTR)
112
    uint32_t *saved_regwptr;
113
#endif
114
#endif
115
#ifdef __sparc__
116
    int saved_i7, tmp_T0;
117
#endif
118
    int code_gen_size, ret, interrupt_request;
119
    void (*gen_func)(void);
120
    TranslationBlock *tb, **ptb;
121
    target_ulong cs_base, pc;
122
    uint8_t *tc_ptr;
123
    unsigned int flags;
124

    
125
    /* first we save global registers */
126
    saved_env = env;
127
    env = env1;
128
    saved_T0 = T0;
129
    saved_T1 = T1;
130
#if defined(reg_T2)
131
    saved_T2 = T2;
132
#endif
133
#ifdef __sparc__
134
    /* we also save i7 because longjmp may not restore it */
135
    asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
136
#endif
137

    
138
#if defined(TARGET_I386)
139
#ifdef reg_EAX
140
    saved_EAX = EAX;
141
#endif
142
#ifdef reg_ECX
143
    saved_ECX = ECX;
144
#endif
145
#ifdef reg_EDX
146
    saved_EDX = EDX;
147
#endif
148
#ifdef reg_EBX
149
    saved_EBX = EBX;
150
#endif
151
#ifdef reg_ESP
152
    saved_ESP = ESP;
153
#endif
154
#ifdef reg_EBP
155
    saved_EBP = EBP;
156
#endif
157
#ifdef reg_ESI
158
    saved_ESI = ESI;
159
#endif
160
#ifdef reg_EDI
161
    saved_EDI = EDI;
162
#endif
163

    
164
    env_to_regs();
165
    /* put eflags in CPU temporary format */
166
    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
167
    DF = 1 - (2 * ((env->eflags >> 10) & 1));
168
    CC_OP = CC_OP_EFLAGS;
169
    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
170
#elif defined(TARGET_ARM)
171
    {
172
        unsigned int psr;
173
        psr = env->cpsr;
174
        env->CF = (psr >> 29) & 1;
175
        env->NZF = (psr & 0xc0000000) ^ 0x40000000;
176
        env->VF = (psr << 3) & 0x80000000;
177
        env->QF = (psr >> 27) & 1;
178
        env->cpsr = psr & ~CACHED_CPSR_BITS;
179
    }
180
#elif defined(TARGET_SPARC)
181
#if defined(reg_REGWPTR)
182
    saved_regwptr = REGWPTR;
183
#endif
184
#elif defined(TARGET_PPC)
185
#elif defined(TARGET_MIPS)
186
#else
187
#error unsupported target CPU
188
#endif
189
    env->exception_index = -1;
190

    
191
    /* prepare setjmp context for exception handling */
192
    for(;;) {
193
        if (setjmp(env->jmp_env) == 0) {
194
            env->current_tb = NULL;
195
            /* if an exception is pending, we execute it here */
196
            if (env->exception_index >= 0) {
197
                if (env->exception_index >= EXCP_INTERRUPT) {
198
                    /* exit request from the cpu execution loop */
199
                    ret = env->exception_index;
200
                    break;
201
                } else if (env->user_mode_only) {
202
                    /* if user mode only, we simulate a fake exception
203
                       which will be hanlded outside the cpu execution
204
                       loop */
205
#if defined(TARGET_I386)
206
                    do_interrupt_user(env->exception_index, 
207
                                      env->exception_is_int, 
208
                                      env->error_code, 
209
                                      env->exception_next_eip);
210
#endif
211
                    ret = env->exception_index;
212
                    break;
213
                } else {
214
#if defined(TARGET_I386)
215
                    /* simulate a real cpu exception. On i386, it can
216
                       trigger new exceptions, but we do not handle
217
                       double or triple faults yet. */
218
                    do_interrupt(env->exception_index, 
219
                                 env->exception_is_int, 
220
                                 env->error_code, 
221
                                 env->exception_next_eip, 0);
222
#elif defined(TARGET_PPC)
223
                    do_interrupt(env);
224
#elif defined(TARGET_MIPS)
225
                    do_interrupt(env);
226
#elif defined(TARGET_SPARC)
227
                    do_interrupt(env->exception_index);
228
#endif
229
                }
230
                env->exception_index = -1;
231
            } 
232
#ifdef USE_KQEMU
233
            if (kqemu_is_ok(env) && env->interrupt_request == 0) {
234
                int ret;
235
                env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
236
                ret = kqemu_cpu_exec(env);
237
                /* put eflags in CPU temporary format */
238
                CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
239
                DF = 1 - (2 * ((env->eflags >> 10) & 1));
240
                CC_OP = CC_OP_EFLAGS;
241
                env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
242
                if (ret == 1) {
243
                    /* exception */
244
                    longjmp(env->jmp_env, 1);
245
                } else if (ret == 2) {
246
                    /* softmmu execution needed */
247
                } else {
248
                    if (env->interrupt_request != 0) {
249
                        /* hardware interrupt will be executed just after */
250
                    } else {
251
                        /* otherwise, we restart */
252
                        longjmp(env->jmp_env, 1);
253
                    }
254
                }
255
            }
256
#endif
257

    
258
            T0 = 0; /* force lookup of first TB */
259
            for(;;) {
260
#ifdef __sparc__
261
                /* g1 can be modified by some libc? functions */ 
262
                tmp_T0 = T0;
263
#endif            
264
                interrupt_request = env->interrupt_request;
265
                if (__builtin_expect(interrupt_request, 0)) {
266
#if defined(TARGET_I386)
267
                    /* if hardware interrupt pending, we execute it */
268
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
269
                        (env->eflags & IF_MASK) && 
270
                        !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
271
                        int intno;
272
                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
273
                        intno = cpu_get_pic_interrupt(env);
274
                        if (loglevel & CPU_LOG_TB_IN_ASM) {
275
                            fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
276
                        }
277
                        do_interrupt(intno, 0, 0, 0, 1);
278
                        /* ensure that no TB jump will be modified as
279
                           the program flow was changed */
280
#ifdef __sparc__
281
                        tmp_T0 = 0;
282
#else
283
                        T0 = 0;
284
#endif
285
                    }
286
#elif defined(TARGET_PPC)
287
#if 0
288
                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
289
                        cpu_ppc_reset(env);
290
                    }
291
#endif
292
                    if (msr_ee != 0) {
293
                    if ((interrupt_request & CPU_INTERRUPT_HARD)) {
294
                            /* Raise it */
295
                            env->exception_index = EXCP_EXTERNAL;
296
                            env->error_code = 0;
297
                            do_interrupt(env);
298
                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
299
                        } else if ((interrupt_request & CPU_INTERRUPT_TIMER)) {
300
                            /* Raise it */
301
                            env->exception_index = EXCP_DECR;
302
                            env->error_code = 0;
303
                            do_interrupt(env);
304
                            env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
305
                        }
306
                    }
307
#elif defined(TARGET_MIPS)
308
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
309
                        (env->CP0_Status & (1 << CP0St_IE)) &&
310
                        (env->CP0_Cause & 0x0000FC00) &&
311
                        !(env->hflags & MIPS_HFLAG_EXL) &&
312
                        !(env->hflags & MIPS_HFLAG_ERL) &&
313
                        !(env->hflags & MIPS_HFLAG_DM)) {
314
                        /* Raise it */
315
                        env->exception_index = EXCP_EXT_INTERRUPT;
316
                        env->error_code = 0;
317
                        do_interrupt(env);
318
                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
319
                    }
320
#elif defined(TARGET_SPARC)
321
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
322
                        (env->psret != 0)) {
323
                        int pil = env->interrupt_index & 15;
324
                        int type = env->interrupt_index & 0xf0;
325

    
326
                        if (((type == TT_EXTINT) &&
327
                             (pil == 15 || pil > env->psrpil)) ||
328
                            type != TT_EXTINT) {
329
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
330
                            do_interrupt(env->interrupt_index);
331
                            env->interrupt_index = 0;
332
                        }
333
                    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
334
                        //do_interrupt(0, 0, 0, 0, 0);
335
                        env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
336
                    }
337
#endif
338
                    if (interrupt_request & CPU_INTERRUPT_EXITTB) {
339
                        env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
340
                        /* ensure that no TB jump will be modified as
341
                           the program flow was changed */
342
#ifdef __sparc__
343
                        tmp_T0 = 0;
344
#else
345
                        T0 = 0;
346
#endif
347
                    }
348
                    if (interrupt_request & CPU_INTERRUPT_EXIT) {
349
                        env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
350
                        env->exception_index = EXCP_INTERRUPT;
351
                        cpu_loop_exit();
352
                    }
353
                }
354
#ifdef DEBUG_EXEC
355
                if ((loglevel & CPU_LOG_EXEC)) {
356
#if defined(TARGET_I386)
357
                    /* restore flags in standard format */
358
#ifdef reg_EAX
359
                    env->regs[R_EAX] = EAX;
360
#endif
361
#ifdef reg_EBX
362
                    env->regs[R_EBX] = EBX;
363
#endif
364
#ifdef reg_ECX
365
                    env->regs[R_ECX] = ECX;
366
#endif
367
#ifdef reg_EDX
368
                    env->regs[R_EDX] = EDX;
369
#endif
370
#ifdef reg_ESI
371
                    env->regs[R_ESI] = ESI;
372
#endif
373
#ifdef reg_EDI
374
                    env->regs[R_EDI] = EDI;
375
#endif
376
#ifdef reg_EBP
377
                    env->regs[R_EBP] = EBP;
378
#endif
379
#ifdef reg_ESP
380
                    env->regs[R_ESP] = ESP;
381
#endif
382
                    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
383
                    cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
384
                    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
385
#elif defined(TARGET_ARM)
386
                    env->cpsr = compute_cpsr();
387
                    cpu_dump_state(env, logfile, fprintf, 0);
388
                    env->cpsr &= ~CACHED_CPSR_BITS;
389
#elif defined(TARGET_SPARC)
390
                    REGWPTR = env->regbase + (env->cwp * 16);
391
                    env->regwptr = REGWPTR;
392
                    cpu_dump_state(env, logfile, fprintf, 0);
393
#elif defined(TARGET_PPC)
394
                    cpu_dump_state(env, logfile, fprintf, 0);
395
#elif defined(TARGET_MIPS)
396
                    cpu_dump_state(env, logfile, fprintf, 0);
397
#else
398
#error unsupported target CPU 
399
#endif
400
                }
401
#endif
402
                /* we record a subset of the CPU state. It will
403
                   always be the same before a given translated block
404
                   is executed. */
405
#if defined(TARGET_I386)
406
                flags = env->hflags;
407
                flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
408
                cs_base = env->segs[R_CS].base;
409
                pc = cs_base + env->eip;
410
#elif defined(TARGET_ARM)
411
                flags = env->thumb | (env->vfp.vec_len << 1)
412
                        | (env->vfp.vec_stride << 4);
413
                cs_base = 0;
414
                pc = env->regs[15];
415
#elif defined(TARGET_SPARC)
416
#ifdef TARGET_SPARC64
417
                flags = (env->pstate << 2) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
418
#else
419
                flags = env->psrs | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1);
420
#endif
421
                cs_base = env->npc;
422
                pc = env->pc;
423
#elif defined(TARGET_PPC)
424
                flags = (msr_pr << MSR_PR) | (msr_fp << MSR_FP) |
425
                    (msr_se << MSR_SE) | (msr_le << MSR_LE);
426
                cs_base = 0;
427
                pc = env->nip;
428
#elif defined(TARGET_MIPS)
429
                flags = env->hflags & MIPS_HFLAGS_TMASK;
430
                cs_base = NULL;
431
                pc = env->PC;
432
#else
433
#error unsupported CPU
434
#endif
435
                tb = tb_find(&ptb, pc, cs_base, 
436
                             flags);
437
                if (!tb) {
438
                    TranslationBlock **ptb1;
439
                    unsigned int h;
440
                    target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
441
                    
442
                    
443
                    spin_lock(&tb_lock);
444

    
445
                    tb_invalidated_flag = 0;
446
                    
447
                    regs_to_env(); /* XXX: do it just before cpu_gen_code() */
448

    
449
                    /* find translated block using physical mappings */
450
                    phys_pc = get_phys_addr_code(env, pc);
451
                    phys_page1 = phys_pc & TARGET_PAGE_MASK;
452
                    phys_page2 = -1;
453
                    h = tb_phys_hash_func(phys_pc);
454
                    ptb1 = &tb_phys_hash[h];
455
                    for(;;) {
456
                        tb = *ptb1;
457
                        if (!tb)
458
                            goto not_found;
459
                        if (tb->pc == pc && 
460
                            tb->page_addr[0] == phys_page1 &&
461
                            tb->cs_base == cs_base && 
462
                            tb->flags == flags) {
463
                            /* check next page if needed */
464
                            if (tb->page_addr[1] != -1) {
465
                                virt_page2 = (pc & TARGET_PAGE_MASK) + 
466
                                    TARGET_PAGE_SIZE;
467
                                phys_page2 = get_phys_addr_code(env, virt_page2);
468
                                if (tb->page_addr[1] == phys_page2)
469
                                    goto found;
470
                            } else {
471
                                goto found;
472
                            }
473
                        }
474
                        ptb1 = &tb->phys_hash_next;
475
                    }
476
                not_found:
477
                    /* if no translated code available, then translate it now */
478
                    tb = tb_alloc(pc);
479
                    if (!tb) {
480
                        /* flush must be done */
481
                        tb_flush(env);
482
                        /* cannot fail at this point */
483
                        tb = tb_alloc(pc);
484
                        /* don't forget to invalidate previous TB info */
485
                        ptb = &tb_hash[tb_hash_func(pc)];
486
                        T0 = 0;
487
                    }
488
                    tc_ptr = code_gen_ptr;
489
                    tb->tc_ptr = tc_ptr;
490
                    tb->cs_base = cs_base;
491
                    tb->flags = flags;
492
                    cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size);
493
                    code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
494
                    
495
                    /* check next page if needed */
496
                    virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
497
                    phys_page2 = -1;
498
                    if ((pc & TARGET_PAGE_MASK) != virt_page2) {
499
                        phys_page2 = get_phys_addr_code(env, virt_page2);
500
                    }
501
                    tb_link_phys(tb, phys_pc, phys_page2);
502

    
503
                found:
504
                    if (tb_invalidated_flag) {
505
                        /* as some TB could have been invalidated because
506
                           of memory exceptions while generating the code, we
507
                           must recompute the hash index here */
508
                        ptb = &tb_hash[tb_hash_func(pc)];
509
                        while (*ptb != NULL)
510
                            ptb = &(*ptb)->hash_next;
511
                        T0 = 0;
512
                    }
513
                    /* we add the TB in the virtual pc hash table */
514
                    *ptb = tb;
515
                    tb->hash_next = NULL;
516
                    tb_link(tb);
517
                    spin_unlock(&tb_lock);
518
                }
519
#ifdef DEBUG_EXEC
520
                if ((loglevel & CPU_LOG_EXEC)) {
521
                    fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
522
                            (long)tb->tc_ptr, tb->pc,
523
                            lookup_symbol(tb->pc));
524
                }
525
#endif
526
#ifdef __sparc__
527
                T0 = tmp_T0;
528
#endif            
529
                /* see if we can patch the calling TB. */
530
                {
531
                    if (T0 != 0
532
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
533
                    && (tb->cflags & CF_CODE_COPY) == 
534
                    (((TranslationBlock *)(T0 & ~3))->cflags & CF_CODE_COPY)
535
#endif
536
                    ) {
537
                    spin_lock(&tb_lock);
538
                    tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb);
539
#if defined(USE_CODE_COPY)
540
                    /* propagates the FP use info */
541
                    ((TranslationBlock *)(T0 & ~3))->cflags |= 
542
                        (tb->cflags & CF_FP_USED);
543
#endif
544
                    spin_unlock(&tb_lock);
545
                }
546
                }
547
                tc_ptr = tb->tc_ptr;
548
                env->current_tb = tb;
549
                /* execute the generated code */
550
                gen_func = (void *)tc_ptr;
551
#if defined(__sparc__)
552
                __asm__ __volatile__("call        %0\n\t"
553
                                     "mov        %%o7,%%i0"
554
                                     : /* no outputs */
555
                                     : "r" (gen_func) 
556
                                     : "i0", "i1", "i2", "i3", "i4", "i5");
557
#elif defined(__arm__)
558
                asm volatile ("mov pc, %0\n\t"
559
                              ".global exec_loop\n\t"
560
                              "exec_loop:\n\t"
561
                              : /* no outputs */
562
                              : "r" (gen_func)
563
                              : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
564
#elif defined(TARGET_I386) && defined(USE_CODE_COPY)
565
{
566
    if (!(tb->cflags & CF_CODE_COPY)) {
567
        if ((tb->cflags & CF_FP_USED) && env->native_fp_regs) {
568
            save_native_fp_state(env);
569
        }
570
        gen_func();
571
    } else {
572
        if ((tb->cflags & CF_FP_USED) && !env->native_fp_regs) {
573
            restore_native_fp_state(env);
574
        }
575
        /* we work with native eflags */
576
        CC_SRC = cc_table[CC_OP].compute_all();
577
        CC_OP = CC_OP_EFLAGS;
578
        asm(".globl exec_loop\n"
579
            "\n"
580
            "debug1:\n"
581
            "    pushl %%ebp\n"
582
            "    fs movl %10, %9\n"
583
            "    fs movl %11, %%eax\n"
584
            "    andl $0x400, %%eax\n"
585
            "    fs orl %8, %%eax\n"
586
            "    pushl %%eax\n"
587
            "    popf\n"
588
            "    fs movl %%esp, %12\n"
589
            "    fs movl %0, %%eax\n"
590
            "    fs movl %1, %%ecx\n"
591
            "    fs movl %2, %%edx\n"
592
            "    fs movl %3, %%ebx\n"
593
            "    fs movl %4, %%esp\n"
594
            "    fs movl %5, %%ebp\n"
595
            "    fs movl %6, %%esi\n"
596
            "    fs movl %7, %%edi\n"
597
            "    fs jmp *%9\n"
598
            "exec_loop:\n"
599
            "    fs movl %%esp, %4\n"
600
            "    fs movl %12, %%esp\n"
601
            "    fs movl %%eax, %0\n"
602
            "    fs movl %%ecx, %1\n"
603
            "    fs movl %%edx, %2\n"
604
            "    fs movl %%ebx, %3\n"
605
            "    fs movl %%ebp, %5\n"
606
            "    fs movl %%esi, %6\n"
607
            "    fs movl %%edi, %7\n"
608
            "    pushf\n"
609
            "    popl %%eax\n"
610
            "    movl %%eax, %%ecx\n"
611
            "    andl $0x400, %%ecx\n"
612
            "    shrl $9, %%ecx\n"
613
            "    andl $0x8d5, %%eax\n"
614
            "    fs movl %%eax, %8\n"
615
            "    movl $1, %%eax\n"
616
            "    subl %%ecx, %%eax\n"
617
            "    fs movl %%eax, %11\n"
618
            "    fs movl %9, %%ebx\n" /* get T0 value */
619
            "    popl %%ebp\n"
620
            :
621
            : "m" (*(uint8_t *)offsetof(CPUState, regs[0])),
622
            "m" (*(uint8_t *)offsetof(CPUState, regs[1])),
623
            "m" (*(uint8_t *)offsetof(CPUState, regs[2])),
624
            "m" (*(uint8_t *)offsetof(CPUState, regs[3])),
625
            "m" (*(uint8_t *)offsetof(CPUState, regs[4])),
626
            "m" (*(uint8_t *)offsetof(CPUState, regs[5])),
627
            "m" (*(uint8_t *)offsetof(CPUState, regs[6])),
628
            "m" (*(uint8_t *)offsetof(CPUState, regs[7])),
629
            "m" (*(uint8_t *)offsetof(CPUState, cc_src)),
630
            "m" (*(uint8_t *)offsetof(CPUState, tmp0)),
631
            "a" (gen_func),
632
            "m" (*(uint8_t *)offsetof(CPUState, df)),
633
            "m" (*(uint8_t *)offsetof(CPUState, saved_esp))
634
            : "%ecx", "%edx"
635
            );
636
    }
637
}
638
#elif defined(__ia64)
639
                struct fptr {
640
                        void *ip;
641
                        void *gp;
642
                } fp;
643

    
644
                fp.ip = tc_ptr;
645
                fp.gp = code_gen_buffer + 2 * (1 << 20);
646
                (*(void (*)(void)) &fp)();
647
#else
648
                gen_func();
649
#endif
650
                env->current_tb = NULL;
651
                /* reset soft MMU for next block (it can currently
652
                   only be set by a memory fault) */
653
#if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU)
654
                if (env->hflags & HF_SOFTMMU_MASK) {
655
                    env->hflags &= ~HF_SOFTMMU_MASK;
656
                    /* do not allow linking to another block */
657
                    T0 = 0;
658
                }
659
#endif
660
            }
661
        } else {
662
            env_to_regs();
663
        }
664
    } /* for(;;) */
665

    
666

    
667
#if defined(TARGET_I386)
668
#if defined(USE_CODE_COPY)
669
    if (env->native_fp_regs) {
670
        save_native_fp_state(env);
671
    }
672
#endif
673
    /* restore flags in standard format */
674
    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
675

    
676
    /* restore global registers */
677
#ifdef reg_EAX
678
    EAX = saved_EAX;
679
#endif
680
#ifdef reg_ECX
681
    ECX = saved_ECX;
682
#endif
683
#ifdef reg_EDX
684
    EDX = saved_EDX;
685
#endif
686
#ifdef reg_EBX
687
    EBX = saved_EBX;
688
#endif
689
#ifdef reg_ESP
690
    ESP = saved_ESP;
691
#endif
692
#ifdef reg_EBP
693
    EBP = saved_EBP;
694
#endif
695
#ifdef reg_ESI
696
    ESI = saved_ESI;
697
#endif
698
#ifdef reg_EDI
699
    EDI = saved_EDI;
700
#endif
701
#elif defined(TARGET_ARM)
702
    env->cpsr = compute_cpsr();
703
    /* XXX: Save/restore host fpu exception state?.  */
704
#elif defined(TARGET_SPARC)
705
#if defined(reg_REGWPTR)
706
    REGWPTR = saved_regwptr;
707
#endif
708
#elif defined(TARGET_PPC)
709
#elif defined(TARGET_MIPS)
710
#else
711
#error unsupported target CPU
712
#endif
713
#ifdef __sparc__
714
    asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
715
#endif
716
    T0 = saved_T0;
717
    T1 = saved_T1;
718
#if defined(reg_T2)
719
    T2 = saved_T2;
720
#endif
721
    env = saved_env;
722
    return ret;
723
}
724

    
725
/* must only be called from the generated code as an exception can be
726
   generated */
727
void tb_invalidate_page_range(target_ulong start, target_ulong end)
728
{
729
    /* XXX: cannot enable it yet because it yields to MMU exception
730
       where NIP != read address on PowerPC */
731
#if 0
732
    target_ulong phys_addr;
733
    phys_addr = get_phys_addr_code(env, start);
734
    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
735
#endif
736
}
737

    
738
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
739

    
740
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
741
{
742
    CPUX86State *saved_env;
743

    
744
    saved_env = env;
745
    env = s;
746
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
747
        selector &= 0xffff;
748
        cpu_x86_load_seg_cache(env, seg_reg, selector, 
749
                               (selector << 4), 0xffff, 0);
750
    } else {
751
        load_seg(seg_reg, selector);
752
    }
753
    env = saved_env;
754
}
755

    
756
void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32)
757
{
758
    CPUX86State *saved_env;
759

    
760
    saved_env = env;
761
    env = s;
762
    
763
    helper_fsave((target_ulong)ptr, data32);
764

    
765
    env = saved_env;
766
}
767

    
768
void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32)
769
{
770
    CPUX86State *saved_env;
771

    
772
    saved_env = env;
773
    env = s;
774
    
775
    helper_frstor((target_ulong)ptr, data32);
776

    
777
    env = saved_env;
778
}
779

    
780
#endif /* TARGET_I386 */
781

    
782
#if !defined(CONFIG_SOFTMMU)
783

    
784
#if defined(TARGET_I386)
785

    
786
/* 'pc' is the host PC at which the exception was raised. 'address' is
787
   the effective address of the memory exception. 'is_write' is 1 if a
788
   write caused the exception and otherwise 0'. 'old_set' is the
789
   signal set which should be restored */
790
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
791
                                    int is_write, sigset_t *old_set, 
792
                                    void *puc)
793
{
794
    TranslationBlock *tb;
795
    int ret;
796

    
797
    if (cpu_single_env)
798
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
799
#if defined(DEBUG_SIGNAL)
800
    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
801
                pc, address, is_write, *(unsigned long *)old_set);
802
#endif
803
    /* XXX: locking issue */
804
    if (is_write && page_unprotect(address, pc, puc)) {
805
        return 1;
806
    }
807

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

    
840
#elif defined(TARGET_ARM)
841
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
842
                                    int is_write, sigset_t *old_set,
843
                                    void *puc)
844
{
845
    TranslationBlock *tb;
846
    int ret;
847

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

    
884
    if (cpu_single_env)
885
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
886
#if defined(DEBUG_SIGNAL)
887
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
888
           pc, address, is_write, *(unsigned long *)old_set);
889
#endif
890
    /* XXX: locking issue */
891
    if (is_write && page_unprotect(address, pc, puc)) {
892
        return 1;
893
    }
894
    /* see if it is an MMU fault */
895
    ret = cpu_sparc_handle_mmu_fault(env, address, is_write, 1, 0);
896
    if (ret < 0)
897
        return 0; /* not an MMU fault */
898
    if (ret == 0)
899
        return 1; /* the MMU fault was handled without causing real CPU fault */
900
    /* now we have a real cpu fault */
901
    tb = tb_find_pc(pc);
902
    if (tb) {
903
        /* the PC is inside the translated code. It means that we have
904
           a virtual CPU fault */
905
        cpu_restore_state(tb, env, pc, puc);
906
    }
907
    /* we restore the process signal mask as the sigreturn should
908
       do it (XXX: use sigsetjmp) */
909
    sigprocmask(SIG_SETMASK, old_set, NULL);
910
    cpu_loop_exit();
911
}
912
#elif defined (TARGET_PPC)
913
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
914
                                    int is_write, sigset_t *old_set,
915
                                    void *puc)
916
{
917
    TranslationBlock *tb;
918
    int ret;
919
    
920
    if (cpu_single_env)
921
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
922
#if defined(DEBUG_SIGNAL)
923
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
924
           pc, address, is_write, *(unsigned long *)old_set);
925
#endif
926
    /* XXX: locking issue */
927
    if (is_write && page_unprotect(address, pc, puc)) {
928
        return 1;
929
    }
930

    
931
    /* see if it is an MMU fault */
932
    ret = cpu_ppc_handle_mmu_fault(env, address, is_write, msr_pr, 0);
933
    if (ret < 0)
934
        return 0; /* not an MMU fault */
935
    if (ret == 0)
936
        return 1; /* the MMU fault was handled without causing real CPU fault */
937

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

    
962
#elif defined (TARGET_MIPS)
963
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
964
                                    int is_write, sigset_t *old_set,
965
                                    void *puc)
966
{
967
    TranslationBlock *tb;
968
    int ret;
969
    
970
    if (cpu_single_env)
971
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
972
#if defined(DEBUG_SIGNAL)
973
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
974
           pc, address, is_write, *(unsigned long *)old_set);
975
#endif
976
    /* XXX: locking issue */
977
    if (is_write && page_unprotect(address, pc, puc)) {
978
        return 1;
979
    }
980

    
981
    /* see if it is an MMU fault */
982
    ret = cpu_ppc_handle_mmu_fault(env, address, is_write, msr_pr, 0);
983
    if (ret < 0)
984
        return 0; /* not an MMU fault */
985
    if (ret == 0)
986
        return 1; /* the MMU fault was handled without causing real CPU fault */
987

    
988
    /* now we have a real cpu fault */
989
    tb = tb_find_pc(pc);
990
    if (tb) {
991
        /* the PC is inside the translated code. It means that we have
992
           a virtual CPU fault */
993
        cpu_restore_state(tb, env, pc, puc);
994
    }
995
    if (ret == 1) {
996
#if 0
997
        printf("PF exception: NIP=0x%08x error=0x%x %p\n", 
998
               env->nip, env->error_code, tb);
999
#endif
1000
    /* we restore the process signal mask as the sigreturn should
1001
       do it (XXX: use sigsetjmp) */
1002
        sigprocmask(SIG_SETMASK, old_set, NULL);
1003
        do_raise_exception_err(env->exception_index, env->error_code);
1004
    } else {
1005
        /* activate soft MMU for this block */
1006
        cpu_resume_from_signal(env, puc);
1007
    }
1008
    /* never comes here */
1009
    return 1;
1010
}
1011

    
1012
#else
1013
#error unsupported target CPU
1014
#endif
1015

    
1016
#if defined(__i386__)
1017

    
1018
#if defined(USE_CODE_COPY)
1019
static void cpu_send_trap(unsigned long pc, int trap, 
1020
                          struct ucontext *uc)
1021
{
1022
    TranslationBlock *tb;
1023

    
1024
    if (cpu_single_env)
1025
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1026
    /* now we have a real cpu fault */
1027
    tb = tb_find_pc(pc);
1028
    if (tb) {
1029
        /* the PC is inside the translated code. It means that we have
1030
           a virtual CPU fault */
1031
        cpu_restore_state(tb, env, pc, uc);
1032
    }
1033
    sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
1034
    raise_exception_err(trap, env->error_code);
1035
}
1036
#endif
1037

    
1038
int cpu_signal_handler(int host_signum, struct siginfo *info, 
1039
                       void *puc)
1040
{
1041
    struct ucontext *uc = puc;
1042
    unsigned long pc;
1043
    int trapno;
1044

    
1045
#ifndef REG_EIP
1046
/* for glibc 2.1 */
1047
#define REG_EIP    EIP
1048
#define REG_ERR    ERR
1049
#define REG_TRAPNO TRAPNO
1050
#endif
1051
    pc = uc->uc_mcontext.gregs[REG_EIP];
1052
    trapno = uc->uc_mcontext.gregs[REG_TRAPNO];
1053
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
1054
    if (trapno == 0x00 || trapno == 0x05) {
1055
        /* send division by zero or bound exception */
1056
        cpu_send_trap(pc, trapno, uc);
1057
        return 1;
1058
    } else
1059
#endif
1060
        return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1061
                                 trapno == 0xe ? 
1062
                                 (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1063
                                 &uc->uc_sigmask, puc);
1064
}
1065

    
1066
#elif defined(__x86_64__)
1067

    
1068
int cpu_signal_handler(int host_signum, struct siginfo *info,
1069
                       void *puc)
1070
{
1071
    struct ucontext *uc = puc;
1072
    unsigned long pc;
1073

    
1074
    pc = uc->uc_mcontext.gregs[REG_RIP];
1075
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1076
                             uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ? 
1077
                             (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1078
                             &uc->uc_sigmask, puc);
1079
}
1080

    
1081
#elif defined(__powerpc__)
1082

    
1083
/***********************************************************************
1084
 * signal context platform-specific definitions
1085
 * From Wine
1086
 */
1087
#ifdef linux
1088
/* All Registers access - only for local access */
1089
# define REG_sig(reg_name, context)                ((context)->uc_mcontext.regs->reg_name)
1090
/* Gpr Registers access  */
1091
# define GPR_sig(reg_num, context)                REG_sig(gpr[reg_num], context)
1092
# define IAR_sig(context)                        REG_sig(nip, context)        /* Program counter */
1093
# define MSR_sig(context)                        REG_sig(msr, context)   /* Machine State Register (Supervisor) */
1094
# define CTR_sig(context)                        REG_sig(ctr, context)   /* Count register */
1095
# define XER_sig(context)                        REG_sig(xer, context) /* User's integer exception register */
1096
# define LR_sig(context)                        REG_sig(link, context) /* Link register */
1097
# define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
1098
/* Float Registers access  */
1099
# define FLOAT_sig(reg_num, context)                (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1100
# define FPSCR_sig(context)                        (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1101
/* Exception Registers access */
1102
# define DAR_sig(context)                        REG_sig(dar, context)
1103
# define DSISR_sig(context)                        REG_sig(dsisr, context)
1104
# define TRAP_sig(context)                        REG_sig(trap, context)
1105
#endif /* linux */
1106

    
1107
#ifdef __APPLE__
1108
# include <sys/ucontext.h>
1109
typedef struct ucontext SIGCONTEXT;
1110
/* All Registers access - only for local access */
1111
# define REG_sig(reg_name, context)                ((context)->uc_mcontext->ss.reg_name)
1112
# define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
1113
# define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
1114
# define VECREG_sig(reg_name, context)                ((context)->uc_mcontext->vs.reg_name)
1115
/* Gpr Registers access */
1116
# define GPR_sig(reg_num, context)                REG_sig(r##reg_num, context)
1117
# define IAR_sig(context)                        REG_sig(srr0, context)        /* Program counter */
1118
# define MSR_sig(context)                        REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
1119
# define CTR_sig(context)                        REG_sig(ctr, context)
1120
# define XER_sig(context)                        REG_sig(xer, context) /* Link register */
1121
# define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
1122
# define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
1123
/* Float Registers access */
1124
# define FLOAT_sig(reg_num, context)                FLOATREG_sig(fpregs[reg_num], context)
1125
# define FPSCR_sig(context)                        ((double)FLOATREG_sig(fpscr, context))
1126
/* Exception Registers access */
1127
# define DAR_sig(context)                        EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
1128
# define DSISR_sig(context)                        EXCEPREG_sig(dsisr, context)
1129
# define TRAP_sig(context)                        EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1130
#endif /* __APPLE__ */
1131

    
1132
int cpu_signal_handler(int host_signum, struct siginfo *info, 
1133
                       void *puc)
1134
{
1135
    struct ucontext *uc = puc;
1136
    unsigned long pc;
1137
    int is_write;
1138

    
1139
    pc = IAR_sig(uc);
1140
    is_write = 0;
1141
#if 0
1142
    /* ppc 4xx case */
1143
    if (DSISR_sig(uc) & 0x00800000)
1144
        is_write = 1;
1145
#else
1146
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1147
        is_write = 1;
1148
#endif
1149
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1150
                             is_write, &uc->uc_sigmask, puc);
1151
}
1152

    
1153
#elif defined(__alpha__)
1154

    
1155
int cpu_signal_handler(int host_signum, struct siginfo *info, 
1156
                           void *puc)
1157
{
1158
    struct ucontext *uc = puc;
1159
    uint32_t *pc = uc->uc_mcontext.sc_pc;
1160
    uint32_t insn = *pc;
1161
    int is_write = 0;
1162

    
1163
    /* XXX: need kernel patch to get write flag faster */
1164
    switch (insn >> 26) {
1165
    case 0x0d: // stw
1166
    case 0x0e: // stb
1167
    case 0x0f: // stq_u
1168
    case 0x24: // stf
1169
    case 0x25: // stg
1170
    case 0x26: // sts
1171
    case 0x27: // stt
1172
    case 0x2c: // stl
1173
    case 0x2d: // stq
1174
    case 0x2e: // stl_c
1175
    case 0x2f: // stq_c
1176
        is_write = 1;
1177
    }
1178

    
1179
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1180
                             is_write, &uc->uc_sigmask, puc);
1181
}
1182
#elif defined(__sparc__)
1183

    
1184
int cpu_signal_handler(int host_signum, struct siginfo *info, 
1185
                       void *puc)
1186
{
1187
    uint32_t *regs = (uint32_t *)(info + 1);
1188
    void *sigmask = (regs + 20);
1189
    unsigned long pc;
1190
    int is_write;
1191
    uint32_t insn;
1192
    
1193
    /* XXX: is there a standard glibc define ? */
1194
    pc = regs[1];
1195
    /* XXX: need kernel patch to get write flag faster */
1196
    is_write = 0;
1197
    insn = *(uint32_t *)pc;
1198
    if ((insn >> 30) == 3) {
1199
      switch((insn >> 19) & 0x3f) {
1200
      case 0x05: // stb
1201
      case 0x06: // sth
1202
      case 0x04: // st
1203
      case 0x07: // std
1204
      case 0x24: // stf
1205
      case 0x27: // stdf
1206
      case 0x25: // stfsr
1207
        is_write = 1;
1208
        break;
1209
      }
1210
    }
1211
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1212
                             is_write, sigmask, NULL);
1213
}
1214

    
1215
#elif defined(__arm__)
1216

    
1217
int cpu_signal_handler(int host_signum, struct siginfo *info, 
1218
                       void *puc)
1219
{
1220
    struct ucontext *uc = puc;
1221
    unsigned long pc;
1222
    int is_write;
1223
    
1224
    pc = uc->uc_mcontext.gregs[R15];
1225
    /* XXX: compute is_write */
1226
    is_write = 0;
1227
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1228
                             is_write,
1229
                             &uc->uc_sigmask);
1230
}
1231

    
1232
#elif defined(__mc68000)
1233

    
1234
int cpu_signal_handler(int host_signum, struct siginfo *info, 
1235
                       void *puc)
1236
{
1237
    struct ucontext *uc = puc;
1238
    unsigned long pc;
1239
    int is_write;
1240
    
1241
    pc = uc->uc_mcontext.gregs[16];
1242
    /* XXX: compute is_write */
1243
    is_write = 0;
1244
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1245
                             is_write,
1246
                             &uc->uc_sigmask, puc);
1247
}
1248

    
1249
#elif defined(__ia64)
1250

    
1251
#ifndef __ISR_VALID
1252
  /* This ought to be in <bits/siginfo.h>... */
1253
# define __ISR_VALID        1
1254
# define si_flags        _sifields._sigfault._si_pad0
1255
#endif
1256

    
1257
int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc)
1258
{
1259
    struct ucontext *uc = puc;
1260
    unsigned long ip;
1261
    int is_write = 0;
1262

    
1263
    ip = uc->uc_mcontext.sc_ip;
1264
    switch (host_signum) {
1265
      case SIGILL:
1266
      case SIGFPE:
1267
      case SIGSEGV:
1268
      case SIGBUS:
1269
      case SIGTRAP:
1270
          if (info->si_code && (info->si_flags & __ISR_VALID))
1271
              /* ISR.W (write-access) is bit 33:  */
1272
              is_write = (info->si_isr >> 33) & 1;
1273
          break;
1274

    
1275
      default:
1276
          break;
1277
    }
1278
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1279
                             is_write,
1280
                             &uc->uc_sigmask, puc);
1281
}
1282

    
1283
#else
1284

    
1285
#error host CPU specific signal handler needed
1286

    
1287
#endif
1288

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