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

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

38 39
int tb_invalidated_flag;

B
bellard 已提交
40
//#define DEBUG_EXEC
B
bellard 已提交
41
//#define DEBUG_SIGNAL
B
bellard 已提交
42

43
#if defined(TARGET_ARM) || defined(TARGET_SPARC)
B
bellard 已提交
44 45 46 47 48 49 50
/* XXX: unify with i386 target */
void cpu_loop_exit(void)
{
    longjmp(env->jmp_env, 1);
}
#endif

51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
/* exit the current TB from a signal handler. The host registers are
   restored in a state compatible with the CPU emulator
 */
void cpu_resume_from_signal(CPUState *env1, void *puc) 
{
#if !defined(CONFIG_SOFTMMU)
    struct ucontext *uc = puc;
#endif

    env = env1;

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

#if !defined(CONFIG_SOFTMMU)
    if (puc) {
        /* XXX: use siglongjmp ? */
        sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
    }
#endif
    longjmp(env->jmp_env, 1);
}

B
bellard 已提交
73 74
/* main execution loop */

B
bellard 已提交
75
int cpu_exec(CPUState *env1)
B
bellard 已提交
76
{
B
bellard 已提交
77 78
    int saved_T0, saved_T1, saved_T2;
    CPUState *saved_env;
B
bellard 已提交
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
#ifdef reg_EAX
    int saved_EAX;
#endif
#ifdef reg_ECX
    int saved_ECX;
#endif
#ifdef reg_EDX
    int saved_EDX;
#endif
#ifdef reg_EBX
    int saved_EBX;
#endif
#ifdef reg_ESP
    int saved_ESP;
#endif
#ifdef reg_EBP
    int saved_EBP;
#endif
#ifdef reg_ESI
    int saved_ESI;
#endif
#ifdef reg_EDI
    int saved_EDI;
102 103 104
#endif
#ifdef __sparc__
    int saved_i7, tmp_T0;
B
bellard 已提交
105
#endif
B
bellard 已提交
106
    int code_gen_size, ret, interrupt_request;
B
bellard 已提交
107
    void (*gen_func)(void);
B
bellard 已提交
108
    TranslationBlock *tb, **ptb;
B
bellard 已提交
109 110
    target_ulong cs_base, pc;
    uint8_t *tc_ptr;
B
bellard 已提交
111
    unsigned int flags;
112

B
bellard 已提交
113
    /* first we save global registers */
B
bellard 已提交
114 115
    saved_env = env;
    env = env1;
B
bellard 已提交
116 117
    saved_T0 = T0;
    saved_T1 = T1;
B
bellard 已提交
118 119 120 121 122 123 124
    saved_T2 = T2;
#ifdef __sparc__
    /* we also save i7 because longjmp may not restore it */
    asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
#endif

#if defined(TARGET_I386)
B
bellard 已提交
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
#ifdef reg_EAX
    saved_EAX = EAX;
#endif
#ifdef reg_ECX
    saved_ECX = ECX;
#endif
#ifdef reg_EDX
    saved_EDX = EDX;
#endif
#ifdef reg_EBX
    saved_EBX = EBX;
#endif
#ifdef reg_ESP
    saved_ESP = ESP;
#endif
#ifdef reg_EBP
    saved_EBP = EBP;
#endif
#ifdef reg_ESI
    saved_ESI = ESI;
#endif
#ifdef reg_EDI
    saved_EDI = EDI;
#endif
B
bellard 已提交
149 150

    env_to_regs();
B
bellard 已提交
151
    /* put eflags in CPU temporary format */
B
bellard 已提交
152 153
    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
    DF = 1 - (2 * ((env->eflags >> 10) & 1));
B
bellard 已提交
154
    CC_OP = CC_OP_EFLAGS;
B
bellard 已提交
155
    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
B
bellard 已提交
156 157 158 159 160 161 162
#elif defined(TARGET_ARM)
    {
        unsigned int psr;
        psr = env->cpsr;
        env->CF = (psr >> 29) & 1;
        env->NZF = (psr & 0xc0000000) ^ 0x40000000;
        env->VF = (psr << 3) & 0x80000000;
B
bellard 已提交
163 164
        env->QF = (psr >> 27) & 1;
        env->cpsr = psr & ~CACHED_CPSR_BITS;
B
bellard 已提交
165
    }
166
#elif defined(TARGET_SPARC)
167
#elif defined(TARGET_PPC)
B
bellard 已提交
168 169 170
#else
#error unsupported target CPU
#endif
171
    env->exception_index = -1;
172

B
bellard 已提交
173
    /* prepare setjmp context for exception handling */
174 175
    for(;;) {
        if (setjmp(env->jmp_env) == 0) {
176
            env->current_tb = NULL;
177 178 179 180 181 182 183 184 185 186
            /* if an exception is pending, we execute it here */
            if (env->exception_index >= 0) {
                if (env->exception_index >= EXCP_INTERRUPT) {
                    /* exit request from the cpu execution loop */
                    ret = env->exception_index;
                    break;
                } else if (env->user_mode_only) {
                    /* if user mode only, we simulate a fake exception
                       which will be hanlded outside the cpu execution
                       loop */
B
bellard 已提交
187
#if defined(TARGET_I386)
188 189 190 191
                    do_interrupt_user(env->exception_index, 
                                      env->exception_is_int, 
                                      env->error_code, 
                                      env->exception_next_eip);
B
bellard 已提交
192
#endif
193 194 195
                    ret = env->exception_index;
                    break;
                } else {
B
bellard 已提交
196
#if defined(TARGET_I386)
197 198 199 200 201 202
                    /* simulate a real cpu exception. On i386, it can
                       trigger new exceptions, but we do not handle
                       double or triple faults yet. */
                    do_interrupt(env->exception_index, 
                                 env->exception_is_int, 
                                 env->error_code, 
B
bellard 已提交
203
                                 env->exception_next_eip, 0);
204 205
#elif defined(TARGET_PPC)
                    do_interrupt(env);
206
#elif defined(TARGET_SPARC)
B
bellard 已提交
207
                    do_interrupt(env->exception_index);
B
bellard 已提交
208
#endif
209 210
                }
                env->exception_index = -1;
B
bellard 已提交
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
            } 
#ifdef USE_KQEMU
            if (kqemu_is_ok(env) && env->interrupt_request == 0) {
                int ret;
                env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
                ret = kqemu_cpu_exec(env);
                /* put eflags in CPU temporary format */
                CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
                DF = 1 - (2 * ((env->eflags >> 10) & 1));
                CC_OP = CC_OP_EFLAGS;
                env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
                if (ret == 1) {
                    /* exception */
                    longjmp(env->jmp_env, 1);
                } else if (ret == 2) {
                    /* softmmu execution needed */
                } else {
                    if (env->interrupt_request != 0) {
                        /* hardware interrupt will be executed just after */
                    } else {
                        /* otherwise, we restart */
                        longjmp(env->jmp_env, 1);
                    }
                }
235
            }
B
bellard 已提交
236 237
#endif

238 239
            T0 = 0; /* force lookup of first TB */
            for(;;) {
240
#ifdef __sparc__
241 242
                /* g1 can be modified by some libc? functions */ 
                tmp_T0 = T0;
243
#endif	    
B
bellard 已提交
244
                interrupt_request = env->interrupt_request;
245
                if (__builtin_expect(interrupt_request, 0)) {
B
bellard 已提交
246 247 248
#if defined(TARGET_I386)
                    /* if hardware interrupt pending, we execute it */
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
249 250
                        (env->eflags & IF_MASK) && 
                        !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
B
bellard 已提交
251
                        int intno;
252
                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
253
                        intno = cpu_get_pic_interrupt(env);
254
                        if (loglevel & CPU_LOG_TB_IN_ASM) {
B
bellard 已提交
255 256
                            fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
                        }
B
bellard 已提交
257
                        do_interrupt(intno, 0, 0, 0, 1);
B
bellard 已提交
258 259 260 261 262 263 264
                        /* ensure that no TB jump will be modified as
                           the program flow was changed */
#ifdef __sparc__
                        tmp_T0 = 0;
#else
                        T0 = 0;
#endif
B
bellard 已提交
265
                    }
266
#elif defined(TARGET_PPC)
267 268 269 270 271 272
#if 0
                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
                        cpu_ppc_reset(env);
                    }
#endif
                    if (msr_ee != 0) {
273
                    if ((interrupt_request & CPU_INTERRUPT_HARD)) {
274 275 276
			    /* Raise it */
			    env->exception_index = EXCP_EXTERNAL;
			    env->error_code = 0;
277 278
                            do_interrupt(env);
                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
279 280 281 282 283 284 285
			} else if ((interrupt_request & CPU_INTERRUPT_TIMER)) {
			    /* Raise it */
			    env->exception_index = EXCP_DECR;
			    env->error_code = 0;
			    do_interrupt(env);
                            env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
			}
286
                    }
287
#elif defined(TARGET_SPARC)
B
bellard 已提交
288 289 290 291 292 293 294 295 296 297 298 299
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
			(env->psret != 0)) {
			int pil = env->interrupt_index & 15;
			int type = env->interrupt_index & 0xf0;

			if (((type == TT_EXTINT) &&
			     (pil == 15 || pil > env->psrpil)) ||
			    type != TT_EXTINT) {
			    env->interrupt_request &= ~CPU_INTERRUPT_HARD;
			    do_interrupt(env->interrupt_index);
			    env->interrupt_index = 0;
			}
300 301 302 303
		    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
			//do_interrupt(0, 0, 0, 0, 0);
			env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
		    }
B
bellard 已提交
304
#endif
305 306 307 308 309 310 311 312 313 314
                    if (interrupt_request & CPU_INTERRUPT_EXITTB) {
                        env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
                        /* ensure that no TB jump will be modified as
                           the program flow was changed */
#ifdef __sparc__
                        tmp_T0 = 0;
#else
                        T0 = 0;
#endif
                    }
B
bellard 已提交
315 316 317 318 319
                    if (interrupt_request & CPU_INTERRUPT_EXIT) {
                        env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
                        env->exception_index = EXCP_INTERRUPT;
                        cpu_loop_exit();
                    }
320
                }
B
bellard 已提交
321
#ifdef DEBUG_EXEC
B
bellard 已提交
322
                if ((loglevel & CPU_LOG_EXEC)) {
B
bellard 已提交
323
#if defined(TARGET_I386)
324 325 326 327 328 329 330 331 332 333
                    /* restore flags in standard format */
                    env->regs[R_EAX] = EAX;
                    env->regs[R_EBX] = EBX;
                    env->regs[R_ECX] = ECX;
                    env->regs[R_EDX] = EDX;
                    env->regs[R_ESI] = ESI;
                    env->regs[R_EDI] = EDI;
                    env->regs[R_EBP] = EBP;
                    env->regs[R_ESP] = ESP;
                    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
B
bellard 已提交
334
                    cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
335
                    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
B
bellard 已提交
336
#elif defined(TARGET_ARM)
B
bellard 已提交
337
                    env->cpsr = compute_cpsr();
B
bellard 已提交
338
                    cpu_dump_state(env, logfile, fprintf, 0);
B
bellard 已提交
339
                    env->cpsr &= ~CACHED_CPSR_BITS;
340
#elif defined(TARGET_SPARC)
B
bellard 已提交
341
                    cpu_dump_state (env, logfile, fprintf, 0);
342
#elif defined(TARGET_PPC)
B
bellard 已提交
343
                    cpu_dump_state(env, logfile, fprintf, 0);
B
bellard 已提交
344 345 346
#else
#error unsupported target CPU 
#endif
347
                }
B
bellard 已提交
348
#endif
349 350 351
                /* we record a subset of the CPU state. It will
                   always be the same before a given translated block
                   is executed. */
B
bellard 已提交
352
#if defined(TARGET_I386)
353
                flags = env->hflags;
354
                flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
355 356
                cs_base = env->segs[R_CS].base;
                pc = cs_base + env->eip;
B
bellard 已提交
357
#elif defined(TARGET_ARM)
B
bellard 已提交
358 359
                flags = env->thumb | (env->vfp.vec_len << 1)
                        | (env->vfp.vec_stride << 4);
360
                cs_base = 0;
B
bellard 已提交
361
                pc = env->regs[15];
362
#elif defined(TARGET_SPARC)
363
                flags = 0;
B
bellard 已提交
364 365
                cs_base = env->npc;
                pc = env->pc;
366
#elif defined(TARGET_PPC)
367 368
                flags = (msr_pr << MSR_PR) | (msr_fp << MSR_FP) |
                    (msr_se << MSR_SE) | (msr_le << MSR_LE);
369
                cs_base = 0;
B
bellard 已提交
370
                pc = env->nip;
B
bellard 已提交
371 372 373
#else
#error unsupported CPU
#endif
B
bellard 已提交
374
                tb = tb_find(&ptb, pc, cs_base, 
375
                             flags);
B
bellard 已提交
376
                if (!tb) {
B
bellard 已提交
377 378 379 380 381
                    TranslationBlock **ptb1;
                    unsigned int h;
                    target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
                    
                    
382
                    spin_lock(&tb_lock);
B
bellard 已提交
383 384

                    tb_invalidated_flag = 0;
B
bellard 已提交
385 386
                    
                    regs_to_env(); /* XXX: do it just before cpu_gen_code() */
B
bellard 已提交
387 388

                    /* find translated block using physical mappings */
B
bellard 已提交
389
                    phys_pc = get_phys_addr_code(env, pc);
B
bellard 已提交
390 391 392 393 394 395 396 397
                    phys_page1 = phys_pc & TARGET_PAGE_MASK;
                    phys_page2 = -1;
                    h = tb_phys_hash_func(phys_pc);
                    ptb1 = &tb_phys_hash[h];
                    for(;;) {
                        tb = *ptb1;
                        if (!tb)
                            goto not_found;
B
bellard 已提交
398
                        if (tb->pc == pc && 
B
bellard 已提交
399
                            tb->page_addr[0] == phys_page1 &&
B
bellard 已提交
400
                            tb->cs_base == cs_base && 
B
bellard 已提交
401 402
                            tb->flags == flags) {
                            /* check next page if needed */
403
                            if (tb->page_addr[1] != -1) {
B
bellard 已提交
404
                                virt_page2 = (pc & TARGET_PAGE_MASK) + 
405
                                    TARGET_PAGE_SIZE;
B
bellard 已提交
406 407 408 409 410 411 412 413 414 415
                                phys_page2 = get_phys_addr_code(env, virt_page2);
                                if (tb->page_addr[1] == phys_page2)
                                    goto found;
                            } else {
                                goto found;
                            }
                        }
                        ptb1 = &tb->phys_hash_next;
                    }
                not_found:
416
                    /* if no translated code available, then translate it now */
B
bellard 已提交
417
                    tb = tb_alloc(pc);
418 419
                    if (!tb) {
                        /* flush must be done */
B
bellard 已提交
420
                        tb_flush(env);
421
                        /* cannot fail at this point */
B
bellard 已提交
422
                        tb = tb_alloc(pc);
423
                        /* don't forget to invalidate previous TB info */
B
bellard 已提交
424
                        ptb = &tb_hash[tb_hash_func(pc)];
425 426 427 428
                        T0 = 0;
                    }
                    tc_ptr = code_gen_ptr;
                    tb->tc_ptr = tc_ptr;
B
bellard 已提交
429
                    tb->cs_base = cs_base;
430
                    tb->flags = flags;
B
bellard 已提交
431
                    cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size);
B
bellard 已提交
432 433 434
                    code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
                    
                    /* check next page if needed */
B
bellard 已提交
435
                    virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
B
bellard 已提交
436
                    phys_page2 = -1;
B
bellard 已提交
437
                    if ((pc & TARGET_PAGE_MASK) != virt_page2) {
B
bellard 已提交
438 439 440 441 442
                        phys_page2 = get_phys_addr_code(env, virt_page2);
                    }
                    tb_link_phys(tb, phys_pc, phys_page2);

                found:
443 444 445 446
                    if (tb_invalidated_flag) {
                        /* as some TB could have been invalidated because
                           of memory exceptions while generating the code, we
                           must recompute the hash index here */
B
bellard 已提交
447
                        ptb = &tb_hash[tb_hash_func(pc)];
448 449 450 451
                        while (*ptb != NULL)
                            ptb = &(*ptb)->hash_next;
                        T0 = 0;
                    }
B
bellard 已提交
452
                    /* we add the TB in the virtual pc hash table */
453 454 455
                    *ptb = tb;
                    tb->hash_next = NULL;
                    tb_link(tb);
456
                    spin_unlock(&tb_lock);
B
bellard 已提交
457
                }
458
#ifdef DEBUG_EXEC
B
bellard 已提交
459
                if ((loglevel & CPU_LOG_EXEC)) {
B
bellard 已提交
460 461 462
                    fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
                            (long)tb->tc_ptr, tb->pc,
                            lookup_symbol(tb->pc));
463
                }
464
#endif
465
#ifdef __sparc__
466
                T0 = tmp_T0;
467
#endif	    
B
bellard 已提交
468
                /* see if we can patch the calling TB. */
B
bellard 已提交
469 470
                {
                    if (T0 != 0
471 472 473 474 475
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
                    && (tb->cflags & CF_CODE_COPY) == 
                    (((TranslationBlock *)(T0 & ~3))->cflags & CF_CODE_COPY)
#endif
                    ) {
476
                    spin_lock(&tb_lock);
B
bellard 已提交
477
                    tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb);
B
bellard 已提交
478 479 480 481 482
#if defined(USE_CODE_COPY)
                    /* propagates the FP use info */
                    ((TranslationBlock *)(T0 & ~3))->cflags |= 
                        (tb->cflags & CF_FP_USED);
#endif
483 484
                    spin_unlock(&tb_lock);
                }
B
bellard 已提交
485
                }
486
                tc_ptr = tb->tc_ptr;
B
bellard 已提交
487
                env->current_tb = tb;
488 489
                /* execute the generated code */
                gen_func = (void *)tc_ptr;
490
#if defined(__sparc__)
491 492 493 494 495
                __asm__ __volatile__("call	%0\n\t"
                                     "mov	%%o7,%%i0"
                                     : /* no outputs */
                                     : "r" (gen_func) 
                                     : "i0", "i1", "i2", "i3", "i4", "i5");
496
#elif defined(__arm__)
497 498 499 500 501 502
                asm volatile ("mov pc, %0\n\t"
                              ".global exec_loop\n\t"
                              "exec_loop:\n\t"
                              : /* no outputs */
                              : "r" (gen_func)
                              : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
503 504 505
#elif defined(TARGET_I386) && defined(USE_CODE_COPY)
{
    if (!(tb->cflags & CF_CODE_COPY)) {
B
bellard 已提交
506 507 508
        if ((tb->cflags & CF_FP_USED) && env->native_fp_regs) {
            save_native_fp_state(env);
        }
509 510
        gen_func();
    } else {
B
bellard 已提交
511 512 513
        if ((tb->cflags & CF_FP_USED) && !env->native_fp_regs) {
            restore_native_fp_state(env);
        }
514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576
        /* we work with native eflags */
        CC_SRC = cc_table[CC_OP].compute_all();
        CC_OP = CC_OP_EFLAGS;
        asm(".globl exec_loop\n"
            "\n"
            "debug1:\n"
            "    pushl %%ebp\n"
            "    fs movl %10, %9\n"
            "    fs movl %11, %%eax\n"
            "    andl $0x400, %%eax\n"
            "    fs orl %8, %%eax\n"
            "    pushl %%eax\n"
            "    popf\n"
            "    fs movl %%esp, %12\n"
            "    fs movl %0, %%eax\n"
            "    fs movl %1, %%ecx\n"
            "    fs movl %2, %%edx\n"
            "    fs movl %3, %%ebx\n"
            "    fs movl %4, %%esp\n"
            "    fs movl %5, %%ebp\n"
            "    fs movl %6, %%esi\n"
            "    fs movl %7, %%edi\n"
            "    fs jmp *%9\n"
            "exec_loop:\n"
            "    fs movl %%esp, %4\n"
            "    fs movl %12, %%esp\n"
            "    fs movl %%eax, %0\n"
            "    fs movl %%ecx, %1\n"
            "    fs movl %%edx, %2\n"
            "    fs movl %%ebx, %3\n"
            "    fs movl %%ebp, %5\n"
            "    fs movl %%esi, %6\n"
            "    fs movl %%edi, %7\n"
            "    pushf\n"
            "    popl %%eax\n"
            "    movl %%eax, %%ecx\n"
            "    andl $0x400, %%ecx\n"
            "    shrl $9, %%ecx\n"
            "    andl $0x8d5, %%eax\n"
            "    fs movl %%eax, %8\n"
            "    movl $1, %%eax\n"
            "    subl %%ecx, %%eax\n"
            "    fs movl %%eax, %11\n"
            "    fs movl %9, %%ebx\n" /* get T0 value */
            "    popl %%ebp\n"
            :
            : "m" (*(uint8_t *)offsetof(CPUState, regs[0])),
            "m" (*(uint8_t *)offsetof(CPUState, regs[1])),
            "m" (*(uint8_t *)offsetof(CPUState, regs[2])),
            "m" (*(uint8_t *)offsetof(CPUState, regs[3])),
            "m" (*(uint8_t *)offsetof(CPUState, regs[4])),
            "m" (*(uint8_t *)offsetof(CPUState, regs[5])),
            "m" (*(uint8_t *)offsetof(CPUState, regs[6])),
            "m" (*(uint8_t *)offsetof(CPUState, regs[7])),
            "m" (*(uint8_t *)offsetof(CPUState, cc_src)),
            "m" (*(uint8_t *)offsetof(CPUState, tmp0)),
            "a" (gen_func),
            "m" (*(uint8_t *)offsetof(CPUState, df)),
            "m" (*(uint8_t *)offsetof(CPUState, saved_esp))
            : "%ecx", "%edx"
            );
    }
}
B
bellard 已提交
577 578 579 580 581 582 583 584 585
#elif defined(__ia64)
		struct fptr {
			void *ip;
			void *gp;
		} fp;

		fp.ip = tc_ptr;
		fp.gp = code_gen_buffer + 2 * (1 << 20);
		(*(void (*)(void)) &fp)();
B
bellard 已提交
586
#else
587
                gen_func();
B
bellard 已提交
588
#endif
B
bellard 已提交
589
                env->current_tb = NULL;
B
bellard 已提交
590 591 592
                /* reset soft MMU for next block (it can currently
                   only be set by a memory fault) */
#if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU)
593 594
                if (env->hflags & HF_SOFTMMU_MASK) {
                    env->hflags &= ~HF_SOFTMMU_MASK;
B
bellard 已提交
595 596 597 598
                    /* do not allow linking to another block */
                    T0 = 0;
                }
#endif
599 600
            }
        } else {
B
bellard 已提交
601
            env_to_regs();
B
bellard 已提交
602
        }
603 604
    } /* for(;;) */

B
bellard 已提交
605

B
bellard 已提交
606
#if defined(TARGET_I386)
B
bellard 已提交
607 608 609 610 611
#if defined(USE_CODE_COPY)
    if (env->native_fp_regs) {
        save_native_fp_state(env);
    }
#endif
B
bellard 已提交
612
    /* restore flags in standard format */
B
bellard 已提交
613
    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
B
bellard 已提交
614

B
bellard 已提交
615
    /* restore global registers */
B
bellard 已提交
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638
#ifdef reg_EAX
    EAX = saved_EAX;
#endif
#ifdef reg_ECX
    ECX = saved_ECX;
#endif
#ifdef reg_EDX
    EDX = saved_EDX;
#endif
#ifdef reg_EBX
    EBX = saved_EBX;
#endif
#ifdef reg_ESP
    ESP = saved_ESP;
#endif
#ifdef reg_EBP
    EBP = saved_EBP;
#endif
#ifdef reg_ESI
    ESI = saved_ESI;
#endif
#ifdef reg_EDI
    EDI = saved_EDI;
639
#endif
B
bellard 已提交
640
#elif defined(TARGET_ARM)
B
bellard 已提交
641
    env->cpsr = compute_cpsr();
B
bellard 已提交
642
    /* XXX: Save/restore host fpu exception state?.  */
643
#elif defined(TARGET_SPARC)
644
#elif defined(TARGET_PPC)
B
bellard 已提交
645 646 647
#else
#error unsupported target CPU
#endif
648 649
#ifdef __sparc__
    asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
B
bellard 已提交
650
#endif
B
bellard 已提交
651 652
    T0 = saved_T0;
    T1 = saved_T1;
B
bellard 已提交
653
    T2 = saved_T2;
B
bellard 已提交
654 655 656
    env = saved_env;
    return ret;
}
B
bellard 已提交
657

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

B
bellard 已提交
671
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
B
bellard 已提交
672

B
bellard 已提交
673 674 675 676 677 678
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
{
    CPUX86State *saved_env;

    saved_env = env;
    env = s;
B
bellard 已提交
679
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
B
bellard 已提交
680
        selector &= 0xffff;
681
        cpu_x86_load_seg_cache(env, seg_reg, selector, 
B
bellard 已提交
682
                               (selector << 4), 0xffff, 0);
B
bellard 已提交
683
    } else {
B
bellard 已提交
684
        load_seg(seg_reg, selector);
B
bellard 已提交
685
    }
B
bellard 已提交
686 687
    env = saved_env;
}
B
bellard 已提交
688

689 690 691 692 693 694 695
void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32)
{
    CPUX86State *saved_env;

    saved_env = env;
    env = s;
    
B
bellard 已提交
696
    helper_fsave((target_ulong)ptr, data32);
697 698 699 700 701 702 703 704 705 706 707

    env = saved_env;
}

void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32)
{
    CPUX86State *saved_env;

    saved_env = env;
    env = s;
    
B
bellard 已提交
708
    helper_frstor((target_ulong)ptr, data32);
709 710 711 712

    env = saved_env;
}

B
bellard 已提交
713 714
#endif /* TARGET_I386 */

B
bellard 已提交
715 716
#if !defined(CONFIG_SOFTMMU)

717 718
#if defined(TARGET_I386)

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

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

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

B
bellard 已提交
773
#elif defined(TARGET_ARM)
774
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
775 776
                                    int is_write, sigset_t *old_set,
                                    void *puc)
777
{
B
bellard 已提交
778 779 780 781 782 783 784 785 786
    TranslationBlock *tb;
    int ret;

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

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

864
    /* see if it is an MMU fault */
B
bellard 已提交
865
    ret = cpu_ppc_handle_mmu_fault(env, address, is_write, msr_pr, 0);
866 867 868 869 870
    if (ret < 0)
        return 0; /* not an MMU fault */
    if (ret == 0)
        return 1; /* the MMU fault was handled without causing real CPU fault */

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

B
bellard 已提交
898 899
#if defined(__i386__)

900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919
#if defined(USE_CODE_COPY)
static void cpu_send_trap(unsigned long pc, int trap, 
                          struct ucontext *uc)
{
    TranslationBlock *tb;

    if (cpu_single_env)
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
    /* now we have a real cpu fault */
    tb = tb_find_pc(pc);
    if (tb) {
        /* the PC is inside the translated code. It means that we have
           a virtual CPU fault */
        cpu_restore_state(tb, env, pc, uc);
    }
    sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
    raise_exception_err(trap, env->error_code);
}
#endif

B
bellard 已提交
920 921
int cpu_signal_handler(int host_signum, struct siginfo *info, 
                       void *puc)
B
bellard 已提交
922 923 924
{
    struct ucontext *uc = puc;
    unsigned long pc;
925
    int trapno;
B
bellard 已提交
926

927 928
#ifndef REG_EIP
/* for glibc 2.1 */
B
bellard 已提交
929 930 931
#define REG_EIP    EIP
#define REG_ERR    ERR
#define REG_TRAPNO TRAPNO
932
#endif
B
bellard 已提交
933
    pc = uc->uc_mcontext.gregs[REG_EIP];
934 935 936 937 938 939 940 941 942 943 944 945
    trapno = uc->uc_mcontext.gregs[REG_TRAPNO];
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
    if (trapno == 0x00 || trapno == 0x05) {
        /* send division by zero or bound exception */
        cpu_send_trap(pc, trapno, uc);
        return 1;
    } else
#endif
        return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
                                 trapno == 0xe ? 
                                 (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
                                 &uc->uc_sigmask, puc);
B
bellard 已提交
946 947
}

948 949 950 951 952 953 954 955 956 957 958 959 960 961 962
#elif defined(__x86_64__)

int cpu_signal_handler(int host_signum, struct siginfo *info,
                       void *puc)
{
    struct ucontext *uc = puc;
    unsigned long pc;

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

963
#elif defined(__powerpc__)
B
bellard 已提交
964

965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013
/***********************************************************************
 * signal context platform-specific definitions
 * From Wine
 */
#ifdef linux
/* All Registers access - only for local access */
# define REG_sig(reg_name, context)		((context)->uc_mcontext.regs->reg_name)
/* Gpr Registers access  */
# define GPR_sig(reg_num, context)		REG_sig(gpr[reg_num], context)
# define IAR_sig(context)			REG_sig(nip, context)	/* Program counter */
# define MSR_sig(context)			REG_sig(msr, context)   /* Machine State Register (Supervisor) */
# define CTR_sig(context)			REG_sig(ctr, context)   /* Count register */
# define XER_sig(context)			REG_sig(xer, context) /* User's integer exception register */
# define LR_sig(context)			REG_sig(link, context) /* Link register */
# define CR_sig(context)			REG_sig(ccr, context) /* Condition register */
/* Float Registers access  */
# define FLOAT_sig(reg_num, context)		(((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
# define FPSCR_sig(context)			(*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
/* Exception Registers access */
# define DAR_sig(context)			REG_sig(dar, context)
# define DSISR_sig(context)			REG_sig(dsisr, context)
# define TRAP_sig(context)			REG_sig(trap, context)
#endif /* linux */

#ifdef __APPLE__
# include <sys/ucontext.h>
typedef struct ucontext SIGCONTEXT;
/* All Registers access - only for local access */
# define REG_sig(reg_name, context)		((context)->uc_mcontext->ss.reg_name)
# define FLOATREG_sig(reg_name, context)	((context)->uc_mcontext->fs.reg_name)
# define EXCEPREG_sig(reg_name, context)	((context)->uc_mcontext->es.reg_name)
# define VECREG_sig(reg_name, context)		((context)->uc_mcontext->vs.reg_name)
/* Gpr Registers access */
# define GPR_sig(reg_num, context)		REG_sig(r##reg_num, context)
# define IAR_sig(context)			REG_sig(srr0, context)	/* Program counter */
# define MSR_sig(context)			REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
# define CTR_sig(context)			REG_sig(ctr, context)
# define XER_sig(context)			REG_sig(xer, context) /* Link register */
# define LR_sig(context)			REG_sig(lr, context)  /* User's integer exception register */
# define CR_sig(context)			REG_sig(cr, context)  /* Condition register */
/* Float Registers access */
# define FLOAT_sig(reg_num, context)		FLOATREG_sig(fpregs[reg_num], context)
# define FPSCR_sig(context)			((double)FLOATREG_sig(fpscr, context))
/* Exception Registers access */
# define DAR_sig(context)			EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
# define DSISR_sig(context)			EXCEPREG_sig(dsisr, context)
# define TRAP_sig(context)			EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
#endif /* __APPLE__ */

B
bellard 已提交
1014
int cpu_signal_handler(int host_signum, struct siginfo *info, 
B
bellard 已提交
1015
                       void *puc)
B
bellard 已提交
1016
{
1017 1018 1019 1020
    struct ucontext *uc = puc;
    unsigned long pc;
    int is_write;

1021
    pc = IAR_sig(uc);
1022 1023 1024
    is_write = 0;
#if 0
    /* ppc 4xx case */
1025
    if (DSISR_sig(uc) & 0x00800000)
1026 1027
        is_write = 1;
#else
1028
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1029 1030 1031
        is_write = 1;
#endif
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1032
                             is_write, &uc->uc_sigmask, puc);
B
bellard 已提交
1033 1034
}

B
bellard 已提交
1035 1036
#elif defined(__alpha__)

B
bellard 已提交
1037
int cpu_signal_handler(int host_signum, struct siginfo *info, 
B
bellard 已提交
1038 1039 1040 1041 1042 1043 1044
                           void *puc)
{
    struct ucontext *uc = puc;
    uint32_t *pc = uc->uc_mcontext.sc_pc;
    uint32_t insn = *pc;
    int is_write = 0;

1045
    /* XXX: need kernel patch to get write flag faster */
B
bellard 已提交
1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
    switch (insn >> 26) {
    case 0x0d: // stw
    case 0x0e: // stb
    case 0x0f: // stq_u
    case 0x24: // stf
    case 0x25: // stg
    case 0x26: // sts
    case 0x27: // stt
    case 0x2c: // stl
    case 0x2d: // stq
    case 0x2e: // stl_c
    case 0x2f: // stq_c
	is_write = 1;
    }

    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1062
                             is_write, &uc->uc_sigmask, puc);
B
bellard 已提交
1063
}
1064 1065
#elif defined(__sparc__)

B
bellard 已提交
1066 1067
int cpu_signal_handler(int host_signum, struct siginfo *info, 
                       void *puc)
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093
{
    uint32_t *regs = (uint32_t *)(info + 1);
    void *sigmask = (regs + 20);
    unsigned long pc;
    int is_write;
    uint32_t insn;
    
    /* XXX: is there a standard glibc define ? */
    pc = regs[1];
    /* XXX: need kernel patch to get write flag faster */
    is_write = 0;
    insn = *(uint32_t *)pc;
    if ((insn >> 30) == 3) {
      switch((insn >> 19) & 0x3f) {
      case 0x05: // stb
      case 0x06: // sth
      case 0x04: // st
      case 0x07: // std
      case 0x24: // stf
      case 0x27: // stdf
      case 0x25: // stfsr
	is_write = 1;
	break;
      }
    }
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1094
                             is_write, sigmask, NULL);
1095 1096 1097 1098
}

#elif defined(__arm__)

B
bellard 已提交
1099 1100
int cpu_signal_handler(int host_signum, struct siginfo *info, 
                       void *puc)
1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113
{
    struct ucontext *uc = puc;
    unsigned long pc;
    int is_write;
    
    pc = uc->uc_mcontext.gregs[R15];
    /* XXX: compute is_write */
    is_write = 0;
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
                             is_write,
                             &uc->uc_sigmask);
}

B
bellard 已提交
1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127
#elif defined(__mc68000)

int cpu_signal_handler(int host_signum, struct siginfo *info, 
                       void *puc)
{
    struct ucontext *uc = puc;
    unsigned long pc;
    int is_write;
    
    pc = uc->uc_mcontext.gregs[16];
    /* XXX: compute is_write */
    is_write = 0;
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
                             is_write,
1128
                             &uc->uc_sigmask, puc);
B
bellard 已提交
1129 1130
}

B
bellard 已提交
1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164
#elif defined(__ia64)

#ifndef __ISR_VALID
  /* This ought to be in <bits/siginfo.h>... */
# define __ISR_VALID	1
# define si_flags	_sifields._sigfault._si_pad0
#endif

int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc)
{
    struct ucontext *uc = puc;
    unsigned long ip;
    int is_write = 0;

    ip = uc->uc_mcontext.sc_ip;
    switch (host_signum) {
      case SIGILL:
      case SIGFPE:
      case SIGSEGV:
      case SIGBUS:
      case SIGTRAP:
	  if (info->si_code && (info->si_flags & __ISR_VALID))
	      /* ISR.W (write-access) is bit 33:  */
	      is_write = (info->si_isr >> 33) & 1;
	  break;

      default:
	  break;
    }
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
                             is_write,
                             &uc->uc_sigmask, puc);
}

B
bellard 已提交
1165
#else
B
bellard 已提交
1166

1167
#error host CPU specific signal handler needed
B
bellard 已提交
1168

B
bellard 已提交
1169
#endif
B
bellard 已提交
1170 1171

#endif /* !defined(CONFIG_SOFTMMU) */