Annotation of qemu/user-exec.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *  User emulator execution
                      3:  *
                      4:  *  Copyright (c) 2003-2005 Fabrice Bellard
                      5:  *
                      6:  * This library is free software; you can redistribute it and/or
                      7:  * modify it under the terms of the GNU Lesser General Public
                      8:  * License as published by the Free Software Foundation; either
                      9:  * version 2 of the License, or (at your option) any later version.
                     10:  *
                     11:  * This library is distributed in the hope that it will be useful,
                     12:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     14:  * Lesser General Public License for more details.
                     15:  *
                     16:  * You should have received a copy of the GNU Lesser General Public
                     17:  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
                     18:  */
                     19: #include "config.h"
                     20: #include "exec.h"
                     21: #include "disas.h"
                     22: #include "tcg.h"
                     23: 
                     24: #undef EAX
                     25: #undef ECX
                     26: #undef EDX
                     27: #undef EBX
                     28: #undef ESP
                     29: #undef EBP
                     30: #undef ESI
                     31: #undef EDI
                     32: #undef EIP
                     33: #include <signal.h>
                     34: #ifdef __linux__
                     35: #include <sys/ucontext.h>
                     36: #endif
                     37: 
                     38: //#define DEBUG_SIGNAL
                     39: 
                     40: static void exception_action(CPUState *env1)
                     41: {
                     42: #if defined(TARGET_I386)
                     43:     raise_exception_err(env1->exception_index, env1->error_code);
                     44: #else
                     45:     cpu_loop_exit(env1);
                     46: #endif
                     47: }
                     48: 
                     49: /* exit the current TB from a signal handler. The host registers are
                     50:    restored in a state compatible with the CPU emulator
                     51:  */
                     52: void cpu_resume_from_signal(CPUState *env1, void *puc)
                     53: {
                     54: #ifdef __linux__
                     55:     struct ucontext *uc = puc;
                     56: #elif defined(__OpenBSD__)
                     57:     struct sigcontext *uc = puc;
                     58: #endif
                     59: 
                     60:     env = env1;
                     61: 
                     62:     /* XXX: restore cpu registers saved in host registers */
                     63: 
                     64:     if (puc) {
                     65:         /* XXX: use siglongjmp ? */
                     66: #ifdef __linux__
                     67: #ifdef __ia64
                     68:         sigprocmask(SIG_SETMASK, (sigset_t *)&uc->uc_sigmask, NULL);
                     69: #else
                     70:         sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
                     71: #endif
                     72: #elif defined(__OpenBSD__)
                     73:         sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
                     74: #endif
                     75:     }
                     76:     env->exception_index = -1;
                     77:     longjmp(env->jmp_env, 1);
                     78: }
                     79: 
                     80: /* 'pc' is the host PC at which the exception was raised. 'address' is
                     81:    the effective address of the memory exception. 'is_write' is 1 if a
                     82:    write caused the exception and otherwise 0'. 'old_set' is the
                     83:    signal set which should be restored */
                     84: static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                     85:                                     int is_write, sigset_t *old_set,
                     86:                                     void *puc)
                     87: {
                     88:     TranslationBlock *tb;
                     89:     int ret;
                     90: 
                     91:     if (cpu_single_env) {
                     92:         env = cpu_single_env; /* XXX: find a correct solution for multithread */
                     93:     }
                     94: #if defined(DEBUG_SIGNAL)
                     95:     qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
                     96:                 pc, address, is_write, *(unsigned long *)old_set);
                     97: #endif
                     98:     /* XXX: locking issue */
                     99:     if (is_write && page_unprotect(h2g(address), pc, puc)) {
                    100:         return 1;
                    101:     }
                    102: 
                    103:     /* see if it is an MMU fault */
                    104:     ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
                    105:     if (ret < 0) {
                    106:         return 0; /* not an MMU fault */
                    107:     }
                    108:     if (ret == 0) {
                    109:         return 1; /* the MMU fault was handled without causing real CPU fault */
                    110:     }
                    111:     /* now we have a real cpu fault */
                    112:     tb = tb_find_pc(pc);
                    113:     if (tb) {
                    114:         /* the PC is inside the translated code. It means that we have
                    115:            a virtual CPU fault */
                    116:         cpu_restore_state(tb, env, pc);
                    117:     }
                    118: 
                    119:     /* we restore the process signal mask as the sigreturn should
                    120:        do it (XXX: use sigsetjmp) */
                    121:     sigprocmask(SIG_SETMASK, old_set, NULL);
                    122:     exception_action(env);
                    123: 
                    124:     /* never comes here */
                    125:     return 1;
                    126: }
                    127: 
                    128: #if defined(__i386__)
                    129: 
                    130: #if defined(__APPLE__)
                    131: #include <sys/ucontext.h>
                    132: 
                    133: #define EIP_sig(context)  (*((unsigned long *)&(context)->uc_mcontext->ss.eip))
                    134: #define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
                    135: #define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
                    136: #define MASK_sig(context)    ((context)->uc_sigmask)
                    137: #elif defined(__NetBSD__)
                    138: #include <ucontext.h>
                    139: 
                    140: #define EIP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_EIP])
                    141: #define TRAP_sig(context)    ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
                    142: #define ERROR_sig(context)   ((context)->uc_mcontext.__gregs[_REG_ERR])
                    143: #define MASK_sig(context)    ((context)->uc_sigmask)
                    144: #elif defined(__FreeBSD__) || defined(__DragonFly__)
                    145: #include <ucontext.h>
                    146: 
                    147: #define EIP_sig(context)  (*((unsigned long *)&(context)->uc_mcontext.mc_eip))
                    148: #define TRAP_sig(context)    ((context)->uc_mcontext.mc_trapno)
                    149: #define ERROR_sig(context)   ((context)->uc_mcontext.mc_err)
                    150: #define MASK_sig(context)    ((context)->uc_sigmask)
                    151: #elif defined(__OpenBSD__)
                    152: #define EIP_sig(context)     ((context)->sc_eip)
                    153: #define TRAP_sig(context)    ((context)->sc_trapno)
                    154: #define ERROR_sig(context)   ((context)->sc_err)
                    155: #define MASK_sig(context)    ((context)->sc_mask)
                    156: #else
                    157: #define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
                    158: #define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
                    159: #define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
                    160: #define MASK_sig(context)    ((context)->uc_sigmask)
                    161: #endif
                    162: 
                    163: int cpu_signal_handler(int host_signum, void *pinfo,
                    164:                        void *puc)
                    165: {
                    166:     siginfo_t *info = pinfo;
                    167: #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
                    168:     ucontext_t *uc = puc;
                    169: #elif defined(__OpenBSD__)
                    170:     struct sigcontext *uc = puc;
                    171: #else
                    172:     struct ucontext *uc = puc;
                    173: #endif
                    174:     unsigned long pc;
                    175:     int trapno;
                    176: 
                    177: #ifndef REG_EIP
                    178: /* for glibc 2.1 */
                    179: #define REG_EIP    EIP
                    180: #define REG_ERR    ERR
                    181: #define REG_TRAPNO TRAPNO
                    182: #endif
                    183:     pc = EIP_sig(uc);
                    184:     trapno = TRAP_sig(uc);
                    185:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                    186:                              trapno == 0xe ?
                    187:                              (ERROR_sig(uc) >> 1) & 1 : 0,
                    188:                              &MASK_sig(uc), puc);
                    189: }
                    190: 
                    191: #elif defined(__x86_64__)
                    192: 
                    193: #ifdef __NetBSD__
                    194: #define PC_sig(context)       _UC_MACHINE_PC(context)
                    195: #define TRAP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
                    196: #define ERROR_sig(context)    ((context)->uc_mcontext.__gregs[_REG_ERR])
                    197: #define MASK_sig(context)     ((context)->uc_sigmask)
                    198: #elif defined(__OpenBSD__)
                    199: #define PC_sig(context)       ((context)->sc_rip)
                    200: #define TRAP_sig(context)     ((context)->sc_trapno)
                    201: #define ERROR_sig(context)    ((context)->sc_err)
                    202: #define MASK_sig(context)     ((context)->sc_mask)
                    203: #elif defined(__FreeBSD__) || defined(__DragonFly__)
                    204: #include <ucontext.h>
                    205: 
                    206: #define PC_sig(context)  (*((unsigned long *)&(context)->uc_mcontext.mc_rip))
                    207: #define TRAP_sig(context)     ((context)->uc_mcontext.mc_trapno)
                    208: #define ERROR_sig(context)    ((context)->uc_mcontext.mc_err)
                    209: #define MASK_sig(context)     ((context)->uc_sigmask)
                    210: #else
                    211: #define PC_sig(context)       ((context)->uc_mcontext.gregs[REG_RIP])
                    212: #define TRAP_sig(context)     ((context)->uc_mcontext.gregs[REG_TRAPNO])
                    213: #define ERROR_sig(context)    ((context)->uc_mcontext.gregs[REG_ERR])
                    214: #define MASK_sig(context)     ((context)->uc_sigmask)
                    215: #endif
                    216: 
                    217: int cpu_signal_handler(int host_signum, void *pinfo,
                    218:                        void *puc)
                    219: {
                    220:     siginfo_t *info = pinfo;
                    221:     unsigned long pc;
                    222: #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
                    223:     ucontext_t *uc = puc;
                    224: #elif defined(__OpenBSD__)
                    225:     struct sigcontext *uc = puc;
                    226: #else
                    227:     struct ucontext *uc = puc;
                    228: #endif
                    229: 
                    230:     pc = PC_sig(uc);
                    231:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                    232:                              TRAP_sig(uc) == 0xe ?
                    233:                              (ERROR_sig(uc) >> 1) & 1 : 0,
                    234:                              &MASK_sig(uc), puc);
                    235: }
                    236: 
                    237: #elif defined(_ARCH_PPC)
                    238: 
                    239: /***********************************************************************
                    240:  * signal context platform-specific definitions
                    241:  * From Wine
                    242:  */
                    243: #ifdef linux
                    244: /* All Registers access - only for local access */
                    245: #define REG_sig(reg_name, context)              \
                    246:     ((context)->uc_mcontext.regs->reg_name)
                    247: /* Gpr Registers access  */
                    248: #define GPR_sig(reg_num, context)              REG_sig(gpr[reg_num], context)
                    249: /* Program counter */
                    250: #define IAR_sig(context)                       REG_sig(nip, context)
                    251: /* Machine State Register (Supervisor) */
                    252: #define MSR_sig(context)                       REG_sig(msr, context)
                    253: /* Count register */
                    254: #define CTR_sig(context)                       REG_sig(ctr, context)
                    255: /* User's integer exception register */
                    256: #define XER_sig(context)                       REG_sig(xer, context)
                    257: /* Link register */
                    258: #define LR_sig(context)                        REG_sig(link, context)
                    259: /* Condition register */
                    260: #define CR_sig(context)                        REG_sig(ccr, context)
                    261: 
                    262: /* Float Registers access  */
                    263: #define FLOAT_sig(reg_num, context)                                     \
                    264:     (((double *)((char *)((context)->uc_mcontext.regs + 48 * 4)))[reg_num])
                    265: #define FPSCR_sig(context) \
                    266:     (*(int *)((char *)((context)->uc_mcontext.regs + (48 + 32 * 2) * 4)))
                    267: /* Exception Registers access */
                    268: #define DAR_sig(context)                       REG_sig(dar, context)
                    269: #define DSISR_sig(context)                     REG_sig(dsisr, context)
                    270: #define TRAP_sig(context)                      REG_sig(trap, context)
                    271: #endif /* linux */
                    272: 
                    273: #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
                    274: #include <ucontext.h>
                    275: #define IAR_sig(context)               ((context)->uc_mcontext.mc_srr0)
                    276: #define MSR_sig(context)               ((context)->uc_mcontext.mc_srr1)
                    277: #define CTR_sig(context)               ((context)->uc_mcontext.mc_ctr)
                    278: #define XER_sig(context)               ((context)->uc_mcontext.mc_xer)
                    279: #define LR_sig(context)                ((context)->uc_mcontext.mc_lr)
                    280: #define CR_sig(context)                ((context)->uc_mcontext.mc_cr)
                    281: /* Exception Registers access */
                    282: #define DAR_sig(context)               ((context)->uc_mcontext.mc_dar)
                    283: #define DSISR_sig(context)             ((context)->uc_mcontext.mc_dsisr)
                    284: #define TRAP_sig(context)              ((context)->uc_mcontext.mc_exc)
                    285: #endif /* __FreeBSD__|| __FreeBSD_kernel__ */
                    286: 
                    287: #ifdef __APPLE__
                    288: #include <sys/ucontext.h>
                    289: typedef struct ucontext SIGCONTEXT;
                    290: /* All Registers access - only for local access */
                    291: #define REG_sig(reg_name, context)              \
                    292:     ((context)->uc_mcontext->ss.reg_name)
                    293: #define FLOATREG_sig(reg_name, context)         \
                    294:     ((context)->uc_mcontext->fs.reg_name)
                    295: #define EXCEPREG_sig(reg_name, context)         \
                    296:     ((context)->uc_mcontext->es.reg_name)
                    297: #define VECREG_sig(reg_name, context)           \
                    298:     ((context)->uc_mcontext->vs.reg_name)
                    299: /* Gpr Registers access */
                    300: #define GPR_sig(reg_num, context)              REG_sig(r##reg_num, context)
                    301: /* Program counter */
                    302: #define IAR_sig(context)                       REG_sig(srr0, context)
                    303: /* Machine State Register (Supervisor) */
                    304: #define MSR_sig(context)                       REG_sig(srr1, context)
                    305: #define CTR_sig(context)                       REG_sig(ctr, context)
                    306: /* Link register */
                    307: #define XER_sig(context)                       REG_sig(xer, context)
                    308: /* User's integer exception register */
                    309: #define LR_sig(context)                        REG_sig(lr, context)
                    310: /* Condition register */
                    311: #define CR_sig(context)                        REG_sig(cr, context)
                    312: /* Float Registers access */
                    313: #define FLOAT_sig(reg_num, context)             \
                    314:     FLOATREG_sig(fpregs[reg_num], context)
                    315: #define FPSCR_sig(context)                      \
                    316:     ((double)FLOATREG_sig(fpscr, context))
                    317: /* Exception Registers access */
                    318: /* Fault registers for coredump */
                    319: #define DAR_sig(context)                       EXCEPREG_sig(dar, context)
                    320: #define DSISR_sig(context)                     EXCEPREG_sig(dsisr, context)
                    321: /* number of powerpc exception taken */
                    322: #define TRAP_sig(context)                      EXCEPREG_sig(exception, context)
                    323: #endif /* __APPLE__ */
                    324: 
                    325: int cpu_signal_handler(int host_signum, void *pinfo,
                    326:                        void *puc)
                    327: {
                    328:     siginfo_t *info = pinfo;
                    329: #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
                    330:     ucontext_t *uc = puc;
                    331: #else
                    332:     struct ucontext *uc = puc;
                    333: #endif
                    334:     unsigned long pc;
                    335:     int is_write;
                    336: 
                    337:     pc = IAR_sig(uc);
                    338:     is_write = 0;
                    339: #if 0
                    340:     /* ppc 4xx case */
                    341:     if (DSISR_sig(uc) & 0x00800000) {
                    342:         is_write = 1;
                    343:     }
                    344: #else
                    345:     if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000)) {
                    346:         is_write = 1;
                    347:     }
                    348: #endif
                    349:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                    350:                              is_write, &uc->uc_sigmask, puc);
                    351: }
                    352: 
                    353: #elif defined(__alpha__)
                    354: 
                    355: int cpu_signal_handler(int host_signum, void *pinfo,
                    356:                            void *puc)
                    357: {
                    358:     siginfo_t *info = pinfo;
                    359:     struct ucontext *uc = puc;
                    360:     uint32_t *pc = uc->uc_mcontext.sc_pc;
                    361:     uint32_t insn = *pc;
                    362:     int is_write = 0;
                    363: 
                    364:     /* XXX: need kernel patch to get write flag faster */
                    365:     switch (insn >> 26) {
                    366:     case 0x0d: /* stw */
                    367:     case 0x0e: /* stb */
                    368:     case 0x0f: /* stq_u */
                    369:     case 0x24: /* stf */
                    370:     case 0x25: /* stg */
                    371:     case 0x26: /* sts */
                    372:     case 0x27: /* stt */
                    373:     case 0x2c: /* stl */
                    374:     case 0x2d: /* stq */
                    375:     case 0x2e: /* stl_c */
                    376:     case 0x2f: /* stq_c */
                    377:         is_write = 1;
                    378:     }
                    379: 
                    380:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                    381:                              is_write, &uc->uc_sigmask, puc);
                    382: }
                    383: #elif defined(__sparc__)
                    384: 
                    385: int cpu_signal_handler(int host_signum, void *pinfo,
                    386:                        void *puc)
                    387: {
                    388:     siginfo_t *info = pinfo;
                    389:     int is_write;
                    390:     uint32_t insn;
                    391: #if !defined(__arch64__) || defined(CONFIG_SOLARIS)
                    392:     uint32_t *regs = (uint32_t *)(info + 1);
                    393:     void *sigmask = (regs + 20);
                    394:     /* XXX: is there a standard glibc define ? */
                    395:     unsigned long pc = regs[1];
                    396: #else
                    397: #ifdef __linux__
                    398:     struct sigcontext *sc = puc;
                    399:     unsigned long pc = sc->sigc_regs.tpc;
                    400:     void *sigmask = (void *)sc->sigc_mask;
                    401: #elif defined(__OpenBSD__)
                    402:     struct sigcontext *uc = puc;
                    403:     unsigned long pc = uc->sc_pc;
                    404:     void *sigmask = (void *)(long)uc->sc_mask;
                    405: #endif
                    406: #endif
                    407: 
                    408:     /* XXX: need kernel patch to get write flag faster */
                    409:     is_write = 0;
                    410:     insn = *(uint32_t *)pc;
                    411:     if ((insn >> 30) == 3) {
                    412:         switch ((insn >> 19) & 0x3f) {
                    413:         case 0x05: /* stb */
                    414:         case 0x15: /* stba */
                    415:         case 0x06: /* sth */
                    416:         case 0x16: /* stha */
                    417:         case 0x04: /* st */
                    418:         case 0x14: /* sta */
                    419:         case 0x07: /* std */
                    420:         case 0x17: /* stda */
                    421:         case 0x0e: /* stx */
                    422:         case 0x1e: /* stxa */
                    423:         case 0x24: /* stf */
                    424:         case 0x34: /* stfa */
                    425:         case 0x27: /* stdf */
                    426:         case 0x37: /* stdfa */
                    427:         case 0x26: /* stqf */
                    428:         case 0x36: /* stqfa */
                    429:         case 0x25: /* stfsr */
                    430:         case 0x3c: /* casa */
                    431:         case 0x3e: /* casxa */
                    432:             is_write = 1;
                    433:             break;
                    434:         }
                    435:     }
                    436:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                    437:                              is_write, sigmask, NULL);
                    438: }
                    439: 
                    440: #elif defined(__arm__)
                    441: 
                    442: int cpu_signal_handler(int host_signum, void *pinfo,
                    443:                        void *puc)
                    444: {
                    445:     siginfo_t *info = pinfo;
                    446:     struct ucontext *uc = puc;
                    447:     unsigned long pc;
                    448:     int is_write;
                    449: 
                    450: #if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
                    451:     pc = uc->uc_mcontext.gregs[R15];
                    452: #else
                    453:     pc = uc->uc_mcontext.arm_pc;
                    454: #endif
                    455:     /* XXX: compute is_write */
                    456:     is_write = 0;
                    457:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                    458:                              is_write,
                    459:                              &uc->uc_sigmask, puc);
                    460: }
                    461: 
                    462: #elif defined(__mc68000)
                    463: 
                    464: int cpu_signal_handler(int host_signum, void *pinfo,
                    465:                        void *puc)
                    466: {
                    467:     siginfo_t *info = pinfo;
                    468:     struct ucontext *uc = puc;
                    469:     unsigned long pc;
                    470:     int is_write;
                    471: 
                    472:     pc = uc->uc_mcontext.gregs[16];
                    473:     /* XXX: compute is_write */
                    474:     is_write = 0;
                    475:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                    476:                              is_write,
                    477:                              &uc->uc_sigmask, puc);
                    478: }
                    479: 
                    480: #elif defined(__ia64)
                    481: 
                    482: #ifndef __ISR_VALID
                    483:   /* This ought to be in <bits/siginfo.h>... */
                    484: # define __ISR_VALID    1
                    485: #endif
                    486: 
                    487: int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
                    488: {
                    489:     siginfo_t *info = pinfo;
                    490:     struct ucontext *uc = puc;
                    491:     unsigned long ip;
                    492:     int is_write = 0;
                    493: 
                    494:     ip = uc->uc_mcontext.sc_ip;
                    495:     switch (host_signum) {
                    496:     case SIGILL:
                    497:     case SIGFPE:
                    498:     case SIGSEGV:
                    499:     case SIGBUS:
                    500:     case SIGTRAP:
                    501:         if (info->si_code && (info->si_segvflags & __ISR_VALID)) {
                    502:             /* ISR.W (write-access) is bit 33:  */
                    503:             is_write = (info->si_isr >> 33) & 1;
                    504:         }
                    505:         break;
                    506: 
                    507:     default:
                    508:         break;
                    509:     }
                    510:     return handle_cpu_signal(ip, (unsigned long)info->si_addr,
                    511:                              is_write,
                    512:                              (sigset_t *)&uc->uc_sigmask, puc);
                    513: }
                    514: 
                    515: #elif defined(__s390__)
                    516: 
                    517: int cpu_signal_handler(int host_signum, void *pinfo,
                    518:                        void *puc)
                    519: {
                    520:     siginfo_t *info = pinfo;
                    521:     struct ucontext *uc = puc;
                    522:     unsigned long pc;
                    523:     uint16_t *pinsn;
                    524:     int is_write = 0;
                    525: 
                    526:     pc = uc->uc_mcontext.psw.addr;
                    527: 
                    528:     /* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
                    529:        of the normal 2 arguments.  The 3rd argument contains the "int_code"
                    530:        from the hardware which does in fact contain the is_write value.
                    531:        The rt signal handler, as far as I can tell, does not give this value
                    532:        at all.  Not that we could get to it from here even if it were.  */
                    533:     /* ??? This is not even close to complete, since it ignores all
                    534:        of the read-modify-write instructions.  */
                    535:     pinsn = (uint16_t *)pc;
                    536:     switch (pinsn[0] >> 8) {
                    537:     case 0x50: /* ST */
                    538:     case 0x42: /* STC */
                    539:     case 0x40: /* STH */
                    540:         is_write = 1;
                    541:         break;
                    542:     case 0xc4: /* RIL format insns */
                    543:         switch (pinsn[0] & 0xf) {
                    544:         case 0xf: /* STRL */
                    545:         case 0xb: /* STGRL */
                    546:         case 0x7: /* STHRL */
                    547:             is_write = 1;
                    548:         }
                    549:         break;
                    550:     case 0xe3: /* RXY format insns */
                    551:         switch (pinsn[2] & 0xff) {
                    552:         case 0x50: /* STY */
                    553:         case 0x24: /* STG */
                    554:         case 0x72: /* STCY */
                    555:         case 0x70: /* STHY */
                    556:         case 0x8e: /* STPQ */
                    557:         case 0x3f: /* STRVH */
                    558:         case 0x3e: /* STRV */
                    559:         case 0x2f: /* STRVG */
                    560:             is_write = 1;
                    561:         }
                    562:         break;
                    563:     }
                    564:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                    565:                              is_write, &uc->uc_sigmask, puc);
                    566: }
                    567: 
                    568: #elif defined(__mips__)
                    569: 
                    570: int cpu_signal_handler(int host_signum, void *pinfo,
                    571:                        void *puc)
                    572: {
                    573:     siginfo_t *info = pinfo;
                    574:     struct ucontext *uc = puc;
                    575:     greg_t pc = uc->uc_mcontext.pc;
                    576:     int is_write;
                    577: 
                    578:     /* XXX: compute is_write */
                    579:     is_write = 0;
                    580:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                    581:                              is_write, &uc->uc_sigmask, puc);
                    582: }
                    583: 
                    584: #elif defined(__hppa__)
                    585: 
                    586: int cpu_signal_handler(int host_signum, void *pinfo,
                    587:                        void *puc)
                    588: {
                    589:     struct siginfo *info = pinfo;
                    590:     struct ucontext *uc = puc;
                    591:     unsigned long pc = uc->uc_mcontext.sc_iaoq[0];
                    592:     uint32_t insn = *(uint32_t *)pc;
                    593:     int is_write = 0;
                    594: 
                    595:     /* XXX: need kernel patch to get write flag faster.  */
                    596:     switch (insn >> 26) {
                    597:     case 0x1a: /* STW */
                    598:     case 0x19: /* STH */
                    599:     case 0x18: /* STB */
                    600:     case 0x1b: /* STWM */
                    601:         is_write = 1;
                    602:         break;
                    603: 
                    604:     case 0x09: /* CSTWX, FSTWX, FSTWS */
                    605:     case 0x0b: /* CSTDX, FSTDX, FSTDS */
                    606:         /* Distinguish from coprocessor load ... */
                    607:         is_write = (insn >> 9) & 1;
                    608:         break;
                    609: 
                    610:     case 0x03:
                    611:         switch ((insn >> 6) & 15) {
                    612:         case 0xa: /* STWS */
                    613:         case 0x9: /* STHS */
                    614:         case 0x8: /* STBS */
                    615:         case 0xe: /* STWAS */
                    616:         case 0xc: /* STBYS */
                    617:             is_write = 1;
                    618:         }
                    619:         break;
                    620:     }
                    621: 
                    622:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                    623:                              is_write, &uc->uc_sigmask, puc);
                    624: }
                    625: 
                    626: #else
                    627: 
                    628: #error host CPU specific signal handler needed
                    629: 
                    630: #endif
                    631: 
                    632: #if defined(TARGET_I386)
                    633: 
                    634: void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
                    635: {
                    636:     CPUX86State *saved_env;
                    637: 
                    638:     saved_env = env;
                    639:     env = s;
                    640:     if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
                    641:         selector &= 0xffff;
                    642:         cpu_x86_load_seg_cache(env, seg_reg, selector,
                    643:                                (selector << 4), 0xffff, 0);
                    644:     } else {
                    645:         helper_load_seg(seg_reg, selector);
                    646:     }
                    647:     env = saved_env;
                    648: }
                    649: 
                    650: void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
                    651: {
                    652:     CPUX86State *saved_env;
                    653: 
                    654:     saved_env = env;
                    655:     env = s;
                    656: 
                    657:     helper_fsave(ptr, data32);
                    658: 
                    659:     env = saved_env;
                    660: }
                    661: 
                    662: void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
                    663: {
                    664:     CPUX86State *saved_env;
                    665: 
                    666:     saved_env = env;
                    667:     env = s;
                    668: 
                    669:     helper_frstor(ptr, data32);
                    670: 
                    671:     env = saved_env;
                    672: }
                    673: 
                    674: #endif /* TARGET_I386 */

unix.superglobalmegacorp.com