cpu-exec.c 36.6 KB
Newer Older
B
bellard 已提交
1 2 3 4 5
/*
 *  i386 emulator main execution loop
 * 
 *  Copyright (c) 2003 Fabrice Bellard
 *
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 207
#elif defined(TARGET_SPARC)
                    do_interrupt(env->exception_index, 
B
bellard 已提交
208
                                 env->error_code);
B
bellard 已提交
209
#endif
210 211
                }
                env->exception_index = -1;
B
bellard 已提交
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
            } 
#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);
                    }
                }
236
            }
B
bellard 已提交
237 238
#endif

239 240
            T0 = 0; /* force lookup of first TB */
            for(;;) {
241
#ifdef __sparc__
242 243
                /* g1 can be modified by some libc? functions */ 
                tmp_T0 = T0;
244
#endif	    
B
bellard 已提交
245
                interrupt_request = env->interrupt_request;
246
                if (__builtin_expect(interrupt_request, 0)) {
B
bellard 已提交
247 248 249
#if defined(TARGET_I386)
                    /* if hardware interrupt pending, we execute it */
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
250 251
                        (env->eflags & IF_MASK) && 
                        !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
B
bellard 已提交
252
                        int intno;
253
                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
254
                        intno = cpu_get_pic_interrupt(env);
255
                        if (loglevel & CPU_LOG_TB_IN_ASM) {
B
bellard 已提交
256 257
                            fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
                        }
B
bellard 已提交
258
                        do_interrupt(intno, 0, 0, 0, 1);
B
bellard 已提交
259 260 261 262 263 264 265
                        /* 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 已提交
266
                    }
267
#elif defined(TARGET_PPC)
268 269 270 271 272 273
#if 0
                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
                        cpu_ppc_reset(env);
                    }
#endif
                    if (msr_ee != 0) {
274
                    if ((interrupt_request & CPU_INTERRUPT_HARD)) {
275 276 277
			    /* Raise it */
			    env->exception_index = EXCP_EXTERNAL;
			    env->error_code = 0;
278 279
                            do_interrupt(env);
                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
280 281 282 283 284 285 286
			} 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;
			}
287
                    }
288 289
#elif defined(TARGET_SPARC)
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
B
bellard 已提交
290
			do_interrupt(env->interrupt_index, 0);
291 292 293 294 295
                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
		    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
			//do_interrupt(0, 0, 0, 0, 0);
			env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
		    }
B
bellard 已提交
296
#endif
297 298 299 300 301 302 303 304 305 306
                    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 已提交
307 308 309 310 311
                    if (interrupt_request & CPU_INTERRUPT_EXIT) {
                        env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
                        env->exception_index = EXCP_INTERRUPT;
                        cpu_loop_exit();
                    }
312
                }
B
bellard 已提交
313
#ifdef DEBUG_EXEC
B
bellard 已提交
314
                if ((loglevel & CPU_LOG_EXEC)) {
B
bellard 已提交
315
#if defined(TARGET_I386)
316 317 318 319 320 321 322 323 324 325
                    /* 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 已提交
326
                    cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
327
                    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
B
bellard 已提交
328
#elif defined(TARGET_ARM)
B
bellard 已提交
329
                    env->cpsr = compute_cpsr();
B
bellard 已提交
330
                    cpu_dump_state(env, logfile, fprintf, 0);
B
bellard 已提交
331
                    env->cpsr &= ~CACHED_CPSR_BITS;
332
#elif defined(TARGET_SPARC)
B
bellard 已提交
333
                    cpu_dump_state (env, logfile, fprintf, 0);
334
#elif defined(TARGET_PPC)
B
bellard 已提交
335
                    cpu_dump_state(env, logfile, fprintf, 0);
B
bellard 已提交
336 337 338
#else
#error unsupported target CPU 
#endif
339
                }
B
bellard 已提交
340
#endif
341 342 343
                /* we record a subset of the CPU state. It will
                   always be the same before a given translated block
                   is executed. */
B
bellard 已提交
344
#if defined(TARGET_I386)
345
                flags = env->hflags;
346
                flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
347 348
                cs_base = env->segs[R_CS].base;
                pc = cs_base + env->eip;
B
bellard 已提交
349
#elif defined(TARGET_ARM)
B
bellard 已提交
350
                flags = env->thumb;
351
                cs_base = 0;
B
bellard 已提交
352
                pc = env->regs[15];
353
#elif defined(TARGET_SPARC)
354
                flags = 0;
B
bellard 已提交
355 356
                cs_base = env->npc;
                pc = env->pc;
357 358 359
#elif defined(TARGET_PPC)
                flags = 0;
                cs_base = 0;
B
bellard 已提交
360
                pc = env->nip;
B
bellard 已提交
361 362 363
#else
#error unsupported CPU
#endif
B
bellard 已提交
364
                tb = tb_find(&ptb, pc, cs_base, 
365
                             flags);
B
bellard 已提交
366
                if (!tb) {
B
bellard 已提交
367 368 369 370 371
                    TranslationBlock **ptb1;
                    unsigned int h;
                    target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
                    
                    
372
                    spin_lock(&tb_lock);
B
bellard 已提交
373 374

                    tb_invalidated_flag = 0;
B
bellard 已提交
375 376
                    
                    regs_to_env(); /* XXX: do it just before cpu_gen_code() */
B
bellard 已提交
377 378

                    /* find translated block using physical mappings */
B
bellard 已提交
379
                    phys_pc = get_phys_addr_code(env, pc);
B
bellard 已提交
380 381 382 383 384 385 386 387
                    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 已提交
388
                        if (tb->pc == pc && 
B
bellard 已提交
389
                            tb->page_addr[0] == phys_page1 &&
B
bellard 已提交
390
                            tb->cs_base == cs_base && 
B
bellard 已提交
391 392
                            tb->flags == flags) {
                            /* check next page if needed */
393
                            if (tb->page_addr[1] != -1) {
B
bellard 已提交
394
                                virt_page2 = (pc & TARGET_PAGE_MASK) + 
395
                                    TARGET_PAGE_SIZE;
B
bellard 已提交
396 397 398 399 400 401 402 403 404 405
                                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:
406
                    /* if no translated code available, then translate it now */
B
bellard 已提交
407
                    tb = tb_alloc(pc);
408 409
                    if (!tb) {
                        /* flush must be done */
B
bellard 已提交
410
                        tb_flush(env);
411
                        /* cannot fail at this point */
B
bellard 已提交
412
                        tb = tb_alloc(pc);
413
                        /* don't forget to invalidate previous TB info */
B
bellard 已提交
414
                        ptb = &tb_hash[tb_hash_func(pc)];
415 416 417 418
                        T0 = 0;
                    }
                    tc_ptr = code_gen_ptr;
                    tb->tc_ptr = tc_ptr;
B
bellard 已提交
419
                    tb->cs_base = cs_base;
420
                    tb->flags = flags;
B
bellard 已提交
421
                    cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size);
B
bellard 已提交
422 423 424
                    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 已提交
425
                    virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
B
bellard 已提交
426
                    phys_page2 = -1;
B
bellard 已提交
427
                    if ((pc & TARGET_PAGE_MASK) != virt_page2) {
B
bellard 已提交
428 429 430 431 432
                        phys_page2 = get_phys_addr_code(env, virt_page2);
                    }
                    tb_link_phys(tb, phys_pc, phys_page2);

                found:
433 434 435 436
                    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 已提交
437
                        ptb = &tb_hash[tb_hash_func(pc)];
438 439 440 441
                        while (*ptb != NULL)
                            ptb = &(*ptb)->hash_next;
                        T0 = 0;
                    }
B
bellard 已提交
442
                    /* we add the TB in the virtual pc hash table */
443 444 445
                    *ptb = tb;
                    tb->hash_next = NULL;
                    tb_link(tb);
446
                    spin_unlock(&tb_lock);
B
bellard 已提交
447
                }
448
#ifdef DEBUG_EXEC
B
bellard 已提交
449
                if ((loglevel & CPU_LOG_EXEC)) {
B
bellard 已提交
450 451 452
                    fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
                            (long)tb->tc_ptr, tb->pc,
                            lookup_symbol(tb->pc));
453
                }
454
#endif
455
#ifdef __sparc__
456
                T0 = tmp_T0;
457
#endif	    
B
bellard 已提交
458
                /* see if we can patch the calling TB. */
B
bellard 已提交
459 460
                {
                    if (T0 != 0
461 462 463 464 465
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
                    && (tb->cflags & CF_CODE_COPY) == 
                    (((TranslationBlock *)(T0 & ~3))->cflags & CF_CODE_COPY)
#endif
                    ) {
466
                    spin_lock(&tb_lock);
B
bellard 已提交
467
                    tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb);
B
bellard 已提交
468 469 470 471 472
#if defined(USE_CODE_COPY)
                    /* propagates the FP use info */
                    ((TranslationBlock *)(T0 & ~3))->cflags |= 
                        (tb->cflags & CF_FP_USED);
#endif
473 474
                    spin_unlock(&tb_lock);
                }
B
bellard 已提交
475
                }
476
                tc_ptr = tb->tc_ptr;
B
bellard 已提交
477
                env->current_tb = tb;
478 479
                /* execute the generated code */
                gen_func = (void *)tc_ptr;
480
#if defined(__sparc__)
481 482 483 484 485
                __asm__ __volatile__("call	%0\n\t"
                                     "mov	%%o7,%%i0"
                                     : /* no outputs */
                                     : "r" (gen_func) 
                                     : "i0", "i1", "i2", "i3", "i4", "i5");
486
#elif defined(__arm__)
487 488 489 490 491 492
                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");
493 494 495
#elif defined(TARGET_I386) && defined(USE_CODE_COPY)
{
    if (!(tb->cflags & CF_CODE_COPY)) {
B
bellard 已提交
496 497 498
        if ((tb->cflags & CF_FP_USED) && env->native_fp_regs) {
            save_native_fp_state(env);
        }
499 500
        gen_func();
    } else {
B
bellard 已提交
501 502 503
        if ((tb->cflags & CF_FP_USED) && !env->native_fp_regs) {
            restore_native_fp_state(env);
        }
504 505 506 507 508 509 510 511 512 513 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
        /* 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 已提交
567
#else
568
                gen_func();
B
bellard 已提交
569
#endif
B
bellard 已提交
570
                env->current_tb = NULL;
B
bellard 已提交
571 572 573
                /* reset soft MMU for next block (it can currently
                   only be set by a memory fault) */
#if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU)
574 575
                if (env->hflags & HF_SOFTMMU_MASK) {
                    env->hflags &= ~HF_SOFTMMU_MASK;
B
bellard 已提交
576 577 578 579
                    /* do not allow linking to another block */
                    T0 = 0;
                }
#endif
580 581
            }
        } else {
B
bellard 已提交
582
            env_to_regs();
B
bellard 已提交
583
        }
584 585
    } /* for(;;) */

B
bellard 已提交
586

B
bellard 已提交
587
#if defined(TARGET_I386)
B
bellard 已提交
588 589 590 591 592
#if defined(USE_CODE_COPY)
    if (env->native_fp_regs) {
        save_native_fp_state(env);
    }
#endif
B
bellard 已提交
593
    /* restore flags in standard format */
B
bellard 已提交
594
    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
B
bellard 已提交
595

B
bellard 已提交
596
    /* restore global registers */
B
bellard 已提交
597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619
#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;
620
#endif
B
bellard 已提交
621
#elif defined(TARGET_ARM)
B
bellard 已提交
622
    env->cpsr = compute_cpsr();
623
#elif defined(TARGET_SPARC)
624
#elif defined(TARGET_PPC)
B
bellard 已提交
625 626 627
#else
#error unsupported target CPU
#endif
628 629
#ifdef __sparc__
    asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
B
bellard 已提交
630
#endif
B
bellard 已提交
631 632
    T0 = saved_T0;
    T1 = saved_T1;
B
bellard 已提交
633
    T2 = saved_T2;
B
bellard 已提交
634 635 636
    env = saved_env;
    return ret;
}
B
bellard 已提交
637

638 639 640 641
/* 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)
{
642 643 644
    /* XXX: cannot enable it yet because it yields to MMU exception
       where NIP != read address on PowerPC */
#if 0
645 646 647
    target_ulong phys_addr;
    phys_addr = get_phys_addr_code(env, start);
    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
648
#endif
649 650
}

B
bellard 已提交
651
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
B
bellard 已提交
652

B
bellard 已提交
653 654 655 656 657 658
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
{
    CPUX86State *saved_env;

    saved_env = env;
    env = s;
B
bellard 已提交
659
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
B
bellard 已提交
660
        selector &= 0xffff;
661
        cpu_x86_load_seg_cache(env, seg_reg, selector, 
B
bellard 已提交
662
                               (selector << 4), 0xffff, 0);
B
bellard 已提交
663
    } else {
B
bellard 已提交
664
        load_seg(seg_reg, selector);
B
bellard 已提交
665
    }
B
bellard 已提交
666 667
    env = saved_env;
}
B
bellard 已提交
668

669 670 671 672 673 674 675
void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32)
{
    CPUX86State *saved_env;

    saved_env = env;
    env = s;
    
B
bellard 已提交
676
    helper_fsave((target_ulong)ptr, data32);
677 678 679 680 681 682 683 684 685 686 687

    env = saved_env;
}

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

    saved_env = env;
    env = s;
    
B
bellard 已提交
688
    helper_frstor((target_ulong)ptr, data32);
689 690 691 692

    env = saved_env;
}

B
bellard 已提交
693 694
#endif /* TARGET_I386 */

B
bellard 已提交
695 696
#if !defined(CONFIG_SOFTMMU)

697 698
#if defined(TARGET_I386)

699
/* 'pc' is the host PC at which the exception was raised. 'address' is
B
bellard 已提交
700 701 702
   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 已提交
703
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
704 705
                                    int is_write, sigset_t *old_set, 
                                    void *puc)
B
bellard 已提交
706
{
B
bellard 已提交
707 708
    TranslationBlock *tb;
    int ret;
B
bellard 已提交
709

B
bellard 已提交
710 711
    if (cpu_single_env)
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
B
bellard 已提交
712
#if defined(DEBUG_SIGNAL)
713 714
    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 已提交
715
#endif
716
    /* XXX: locking issue */
717
    if (is_write && page_unprotect(address, pc, puc)) {
B
bellard 已提交
718 719
        return 1;
    }
720

721
    /* see if it is an MMU fault */
B
bellard 已提交
722 723
    ret = cpu_x86_handle_mmu_fault(env, address, is_write, 
                                   ((env->hflags & HF_CPL_MASK) == 3), 0);
724 725 726 727 728
    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 已提交
729 730
    tb = tb_find_pc(pc);
    if (tb) {
B
bellard 已提交
731 732
        /* the PC is inside the translated code. It means that we have
           a virtual CPU fault */
733
        cpu_restore_state(tb, env, pc, puc);
734
    }
B
bellard 已提交
735
    if (ret == 1) {
736
#if 0
B
bellard 已提交
737 738
        printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n", 
               env->eip, env->cr[2], env->error_code);
739
#endif
B
bellard 已提交
740 741 742 743 744 745
        /* 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 */
746
        env->hflags |= HF_SOFTMMU_MASK;
747
        cpu_resume_from_signal(env, puc);
B
bellard 已提交
748
    }
749 750 751 752
    /* never comes here */
    return 1;
}

B
bellard 已提交
753
#elif defined(TARGET_ARM)
754
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
755 756
                                    int is_write, sigset_t *old_set,
                                    void *puc)
757
{
B
bellard 已提交
758 759 760 761 762 763 764 765 766
    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 已提交
767 768 769 770
    /* XXX: locking issue */
    if (is_write && page_unprotect(address, pc, puc)) {
        return 1;
    }
B
bellard 已提交
771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787
    /* 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();
788
}
789 790
#elif defined(TARGET_SPARC)
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
791 792
                                    int is_write, sigset_t *old_set,
                                    void *puc)
793
{
B
bellard 已提交
794 795 796 797 798 799 800 801 802
    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 已提交
803
    /* XXX: locking issue */
804
    if (is_write && page_unprotect(address, pc, puc)) {
B
bellard 已提交
805 806
        return 1;
    }
B
bellard 已提交
807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823
    /* 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();
824
}
825 826
#elif defined (TARGET_PPC)
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
827 828
                                    int is_write, sigset_t *old_set,
                                    void *puc)
829 830
{
    TranslationBlock *tb;
831
    int ret;
832 833 834 835 836 837 838 839
    
    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 */
840
    if (is_write && page_unprotect(address, pc, puc)) {
841 842 843
        return 1;
    }

844
    /* see if it is an MMU fault */
B
bellard 已提交
845
    ret = cpu_ppc_handle_mmu_fault(env, address, is_write, msr_pr, 0);
846 847 848 849 850
    if (ret < 0)
        return 0; /* not an MMU fault */
    if (ret == 0)
        return 1; /* the MMU fault was handled without causing real CPU fault */

851 852 853 854 855
    /* 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 */
856
        cpu_restore_state(tb, env, pc, puc);
857
    }
858
    if (ret == 1) {
859
#if 0
860 861
        printf("PF exception: NIP=0x%08x error=0x%x %p\n", 
               env->nip, env->error_code, tb);
862 863 864
#endif
    /* we restore the process signal mask as the sigreturn should
       do it (XXX: use sigsetjmp) */
865
        sigprocmask(SIG_SETMASK, old_set, NULL);
866
        do_raise_exception_err(env->exception_index, env->error_code);
867 868
    } else {
        /* activate soft MMU for this block */
869
        cpu_resume_from_signal(env, puc);
870
    }
871 872 873
    /* never comes here */
    return 1;
}
B
bellard 已提交
874 875 876
#else
#error unsupported target CPU
#endif
B
bellard 已提交
877

B
bellard 已提交
878 879
#if defined(__i386__)

880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899
#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 已提交
900 901
int cpu_signal_handler(int host_signum, struct siginfo *info, 
                       void *puc)
B
bellard 已提交
902 903 904
{
    struct ucontext *uc = puc;
    unsigned long pc;
905
    int trapno;
B
bellard 已提交
906

907 908
#ifndef REG_EIP
/* for glibc 2.1 */
B
bellard 已提交
909 910 911
#define REG_EIP    EIP
#define REG_ERR    ERR
#define REG_TRAPNO TRAPNO
912
#endif
B
bellard 已提交
913
    pc = uc->uc_mcontext.gregs[REG_EIP];
914 915 916 917 918 919 920 921 922 923 924 925
    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 已提交
926 927
}

928 929 930 931 932 933 934 935 936 937 938 939 940 941 942
#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);
}

943
#elif defined(__powerpc__)
B
bellard 已提交
944

945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 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
/***********************************************************************
 * 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 已提交
994
int cpu_signal_handler(int host_signum, struct siginfo *info, 
B
bellard 已提交
995
                       void *puc)
B
bellard 已提交
996
{
997 998 999 1000
    struct ucontext *uc = puc;
    unsigned long pc;
    int is_write;

1001
    pc = IAR_sig(uc);
1002 1003 1004
    is_write = 0;
#if 0
    /* ppc 4xx case */
1005
    if (DSISR_sig(uc) & 0x00800000)
1006 1007
        is_write = 1;
#else
1008
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1009 1010 1011
        is_write = 1;
#endif
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1012
                             is_write, &uc->uc_sigmask, puc);
B
bellard 已提交
1013 1014
}

B
bellard 已提交
1015 1016
#elif defined(__alpha__)

B
bellard 已提交
1017
int cpu_signal_handler(int host_signum, struct siginfo *info, 
B
bellard 已提交
1018 1019 1020 1021 1022 1023 1024
                           void *puc)
{
    struct ucontext *uc = puc;
    uint32_t *pc = uc->uc_mcontext.sc_pc;
    uint32_t insn = *pc;
    int is_write = 0;

1025
    /* XXX: need kernel patch to get write flag faster */
B
bellard 已提交
1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041
    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, 
1042
                             is_write, &uc->uc_sigmask, puc);
B
bellard 已提交
1043
}
1044 1045
#elif defined(__sparc__)

B
bellard 已提交
1046 1047
int cpu_signal_handler(int host_signum, struct siginfo *info, 
                       void *puc)
1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073
{
    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, 
1074
                             is_write, sigmask, NULL);
1075 1076 1077 1078
}

#elif defined(__arm__)

B
bellard 已提交
1079 1080
int cpu_signal_handler(int host_signum, struct siginfo *info, 
                       void *puc)
1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093
{
    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 已提交
1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107
#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,
1108
                             &uc->uc_sigmask, puc);
B
bellard 已提交
1109 1110
}

B
bellard 已提交
1111
#else
B
bellard 已提交
1112

1113
#error host CPU specific signal handler needed
B
bellard 已提交
1114

B
bellard 已提交
1115
#endif
B
bellard 已提交
1116 1117

#endif /* !defined(CONFIG_SOFTMMU) */