Annotation of qemu/cpu-exec.c, revision 1.1

1.1     ! root        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_Status & env->CP0_Cause & 0x0000FF00) &&
        !           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: #elif defined(__s390__)
        !          1284: 
        !          1285: int cpu_signal_handler(int host_signum, struct siginfo *info, 
        !          1286:                        void *puc)
        !          1287: {
        !          1288:     struct ucontext *uc = puc;
        !          1289:     unsigned long pc;
        !          1290:     int is_write;
        !          1291:     
        !          1292:     pc = uc->uc_mcontext.psw.addr;
        !          1293:     /* XXX: compute is_write */
        !          1294:     is_write = 0;
        !          1295:     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
        !          1296:                              is_write,
        !          1297:                              &uc->uc_sigmask, puc);
        !          1298: }
        !          1299: 
        !          1300: #else
        !          1301: 
        !          1302: #error host CPU specific signal handler needed
        !          1303: 
        !          1304: #endif
        !          1305: 
        !          1306: #endif /* !defined(CONFIG_SOFTMMU) */

unix.superglobalmegacorp.com