Diff for /qemu/cpu-exec.c between versions 1.1.1.3 and 1.1.1.6

version 1.1.1.3, 2018/04/24 16:40:34 version 1.1.1.6, 2018/04/24 16:47:11
Line 1 Line 1
 /*  /*
  *  i386 emulator main execution loop   *  i386 emulator main execution loop
  *    *
  *  Copyright (c) 2003-2005 Fabrice Bellard   *  Copyright (c) 2003-2005 Fabrice Bellard
  *   *
  * This library is free software; you can redistribute it and/or   * This library is free software; you can redistribute it and/or
Line 40  int tb_invalidated_flag; Line 40  int tb_invalidated_flag;
 //#define DEBUG_EXEC  //#define DEBUG_EXEC
 //#define DEBUG_SIGNAL  //#define DEBUG_SIGNAL
   
 #if defined(TARGET_ARM) || defined(TARGET_SPARC)  #define SAVE_GLOBALS()
 /* XXX: unify with i386 target */  #define RESTORE_GLOBALS()
   
   #if defined(__sparc__) && !defined(HOST_SOLARIS)
   #include <features.h>
   #if defined(__GLIBC__) && ((__GLIBC__ < 2) || \
                              ((__GLIBC__ == 2) && (__GLIBC_MINOR__ <= 90)))
   // Work around ugly bugs in glibc that mangle global register contents
   
   static volatile void *saved_env;
   static volatile unsigned long saved_t0, saved_i7;
   #undef SAVE_GLOBALS
   #define SAVE_GLOBALS() do {                                     \
           saved_env = env;                                        \
           saved_t0 = T0;                                          \
           asm volatile ("st %%i7, [%0]" : : "r" (&saved_i7));     \
       } while(0)
   
   #undef RESTORE_GLOBALS
   #define RESTORE_GLOBALS() do {                                  \
           env = (void *)saved_env;                                \
           T0 = saved_t0;                                          \
           asm volatile ("ld [%0], %%i7" : : "r" (&saved_i7));     \
       } while(0)
   
   static int sparc_setjmp(jmp_buf buf)
   {
       int ret;
   
       SAVE_GLOBALS();
       ret = setjmp(buf);
       RESTORE_GLOBALS();
       return ret;
   }
   #undef setjmp
   #define setjmp(jmp_buf) sparc_setjmp(jmp_buf)
   
   static void sparc_longjmp(jmp_buf buf, int val)
   {
       SAVE_GLOBALS();
       longjmp(buf, val);
   }
   #define longjmp(jmp_buf, val) sparc_longjmp(jmp_buf, val)
   #endif
   #endif
   
 void cpu_loop_exit(void)  void cpu_loop_exit(void)
 {  {
       /* NOTE: the register at this point must be saved by hand because
          longjmp restore them */
       regs_to_env();
     longjmp(env->jmp_env, 1);      longjmp(env->jmp_env, 1);
 }  }
 #endif  
 #ifndef TARGET_SPARC  #if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K))
 #define reg_T2  #define reg_T2
 #endif  #endif
   
 /* exit the current TB from a signal handler. The host registers are  /* exit the current TB from a signal handler. The host registers are
    restored in a state compatible with the CPU emulator     restored in a state compatible with the CPU emulator
  */   */
 void cpu_resume_from_signal(CPUState *env1, void *puc)   void cpu_resume_from_signal(CPUState *env1, void *puc)
 {  {
 #if !defined(CONFIG_SOFTMMU)  #if !defined(CONFIG_SOFTMMU)
     struct ucontext *uc = puc;      struct ucontext *uc = puc;
Line 76  void cpu_resume_from_signal(CPUState *en Line 123  void cpu_resume_from_signal(CPUState *en
   
 static TranslationBlock *tb_find_slow(target_ulong pc,  static TranslationBlock *tb_find_slow(target_ulong pc,
                                       target_ulong cs_base,                                        target_ulong cs_base,
                                       unsigned int flags)                                        uint64_t flags)
 {  {
     TranslationBlock *tb, **ptb1;      TranslationBlock *tb, **ptb1;
     int code_gen_size;      int code_gen_size;
     unsigned int h;      unsigned int h;
     target_ulong phys_pc, phys_page1, phys_page2, virt_page2;      target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
     uint8_t *tc_ptr;      uint8_t *tc_ptr;
       
     spin_lock(&tb_lock);      spin_lock(&tb_lock);
   
     tb_invalidated_flag = 0;      tb_invalidated_flag = 0;
       
     regs_to_env(); /* XXX: do it just before cpu_gen_code() */      regs_to_env(); /* XXX: do it just before cpu_gen_code() */
       
     /* find translated block using physical mappings */      /* find translated block using physical mappings */
     phys_pc = get_phys_addr_code(env, pc);      phys_pc = get_phys_addr_code(env, pc);
     phys_page1 = phys_pc & TARGET_PAGE_MASK;      phys_page1 = phys_pc & TARGET_PAGE_MASK;
Line 100  static TranslationBlock *tb_find_slow(ta Line 147  static TranslationBlock *tb_find_slow(ta
         tb = *ptb1;          tb = *ptb1;
         if (!tb)          if (!tb)
             goto not_found;              goto not_found;
         if (tb->pc == pc &&           if (tb->pc == pc &&
             tb->page_addr[0] == phys_page1 &&              tb->page_addr[0] == phys_page1 &&
             tb->cs_base == cs_base &&               tb->cs_base == cs_base &&
             tb->flags == flags) {              tb->flags == flags) {
             /* check next page if needed */              /* check next page if needed */
             if (tb->page_addr[1] != -1) {              if (tb->page_addr[1] != -1) {
                 virt_page2 = (pc & TARGET_PAGE_MASK) +                   virt_page2 = (pc & TARGET_PAGE_MASK) +
                     TARGET_PAGE_SIZE;                      TARGET_PAGE_SIZE;
                 phys_page2 = get_phys_addr_code(env, virt_page2);                  phys_page2 = get_phys_addr_code(env, virt_page2);
                 if (tb->page_addr[1] == phys_page2)                  if (tb->page_addr[1] == phys_page2)
Line 132  static TranslationBlock *tb_find_slow(ta Line 179  static TranslationBlock *tb_find_slow(ta
     tb->tc_ptr = tc_ptr;      tb->tc_ptr = tc_ptr;
     tb->cs_base = cs_base;      tb->cs_base = cs_base;
     tb->flags = flags;      tb->flags = flags;
     cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size);      SAVE_GLOBALS();
       cpu_gen_code(env, tb, &code_gen_size);
       RESTORE_GLOBALS();
     code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));      code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
       
     /* check next page if needed */      /* check next page if needed */
     virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;      virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
     phys_page2 = -1;      phys_page2 = -1;
Line 142  static TranslationBlock *tb_find_slow(ta Line 191  static TranslationBlock *tb_find_slow(ta
         phys_page2 = get_phys_addr_code(env, virt_page2);          phys_page2 = get_phys_addr_code(env, virt_page2);
     }      }
     tb_link_phys(tb, phys_pc, phys_page2);      tb_link_phys(tb, phys_pc, phys_page2);
       
  found:   found:
     /* we add the TB in the virtual pc hash table */      /* we add the TB in the virtual pc hash table */
     env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;      env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
Line 154  static inline TranslationBlock *tb_find_ Line 203  static inline TranslationBlock *tb_find_
 {  {
     TranslationBlock *tb;      TranslationBlock *tb;
     target_ulong cs_base, pc;      target_ulong cs_base, pc;
     unsigned int flags;      uint64_t flags;
   
     /* we record a subset of the CPU state. It will      /* we record a subset of the CPU state. It will
        always be the same before a given translated block         always be the same before a given translated block
Line 162  static inline TranslationBlock *tb_find_ Line 211  static inline TranslationBlock *tb_find_
 #if defined(TARGET_I386)  #if defined(TARGET_I386)
     flags = env->hflags;      flags = env->hflags;
     flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));      flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
       flags |= env->intercept;
     cs_base = env->segs[R_CS].base;      cs_base = env->segs[R_CS].base;
     pc = cs_base + env->eip;      pc = cs_base + env->eip;
 #elif defined(TARGET_ARM)  #elif defined(TARGET_ARM)
Line 171  static inline TranslationBlock *tb_find_ Line 221  static inline TranslationBlock *tb_find_
         flags |= (1 << 6);          flags |= (1 << 6);
     if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))      if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
         flags |= (1 << 7);          flags |= (1 << 7);
       flags |= (env->condexec_bits << 8);
     cs_base = 0;      cs_base = 0;
     pc = env->regs[15];      pc = env->regs[15];
 #elif defined(TARGET_SPARC)  #elif defined(TARGET_SPARC)
 #ifdef TARGET_SPARC64  #ifdef TARGET_SPARC64
     flags = (env->pstate << 2) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);      // Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
       flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
           | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
 #else  #else
     flags = env->psrs | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1);      // FPU enable . Supervisor
       flags = (env->psref << 4) | env->psrs;
 #endif  #endif
     cs_base = env->npc;      cs_base = env->npc;
     pc = env->pc;      pc = env->pc;
 #elif defined(TARGET_PPC)  #elif defined(TARGET_PPC)
     flags = (msr_pr << MSR_PR) | (msr_fp << MSR_FP) |      flags = env->hflags;
         (msr_se << MSR_SE) | (msr_le << MSR_LE);  
     cs_base = 0;      cs_base = 0;
     pc = env->nip;      pc = env->nip;
 #elif defined(TARGET_MIPS)  #elif defined(TARGET_MIPS)
     flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);      flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
     cs_base = 0;      cs_base = 0;
     pc = env->PC;      pc = env->PC[env->current_tc];
   #elif defined(TARGET_M68K)
       flags = (env->fpcr & M68K_FPCR_PREC)  /* Bit  6 */
               | (env->sr & SR_S)            /* Bit  13 */
               | ((env->macsr >> 4) & 0xf);  /* Bits 0-3 */
       cs_base = 0;
       pc = env->pc;
 #elif defined(TARGET_SH4)  #elif defined(TARGET_SH4)
     flags = env->sr & (SR_MD | SR_RB);      flags = env->flags;
     cs_base = 0;         /* XXXXX */      cs_base = 0;
       pc = env->pc;
   #elif defined(TARGET_ALPHA)
       flags = env->ps;
       cs_base = 0;
       pc = env->pc;
   #elif defined(TARGET_CRIS)
       flags = 0;
       cs_base = 0;
     pc = env->pc;      pc = env->pc;
 #else  #else
 #error unsupported CPU  #error unsupported CPU
Line 213  static inline TranslationBlock *tb_find_ Line 280  static inline TranslationBlock *tb_find_
     return tb;      return tb;
 }  }
   
   #define BREAK_CHAIN T0 = 0
   
 /* main execution loop */  /* main execution loop */
   
 int cpu_exec(CPUState *env1)  int cpu_exec(CPUState *env1)
 {  {
     int saved_T0, saved_T1;  #define DECLARE_HOST_REGS 1
 #if defined(reg_T2)  #include "hostregs_helper.h"
     int saved_T2;  #if defined(TARGET_SPARC)
 #endif  
     CPUState *saved_env;  
 #if defined(TARGET_I386)  
 #ifdef reg_EAX  
     int saved_EAX;  
 #endif  
 #ifdef reg_ECX  
     int saved_ECX;  
 #endif  
 #ifdef reg_EDX  
     int saved_EDX;  
 #endif  
 #ifdef reg_EBX  
     int saved_EBX;  
 #endif  
 #ifdef reg_ESP  
     int saved_ESP;  
 #endif  
 #ifdef reg_EBP  
     int saved_EBP;  
 #endif  
 #ifdef reg_ESI  
     int saved_ESI;  
 #endif  
 #ifdef reg_EDI  
     int saved_EDI;  
 #endif  
 #elif defined(TARGET_SPARC)  
 #if defined(reg_REGWPTR)  #if defined(reg_REGWPTR)
     uint32_t *saved_regwptr;      uint32_t *saved_regwptr;
 #endif  #endif
 #endif  #endif
 #ifdef __sparc__  
     int saved_i7, tmp_T0;  
 #endif  
     int ret, interrupt_request;      int ret, interrupt_request;
     void (*gen_func)(void);      void (*gen_func)(void);
     TranslationBlock *tb;      TranslationBlock *tb;
     uint8_t *tc_ptr;      uint8_t *tc_ptr;
   
 #if defined(TARGET_I386)      if (cpu_halted(env1) == EXCP_HALTED)
     /* handle exit of HALTED state */          return EXCP_HALTED;
     if (env1->hflags & HF_HALTED_MASK) {  
         /* disable halt condition */  
         if ((env1->interrupt_request & CPU_INTERRUPT_HARD) &&  
             (env1->eflags & IF_MASK)) {  
             env1->hflags &= ~HF_HALTED_MASK;  
         } else {  
             return EXCP_HALTED;  
         }  
     }  
 #elif defined(TARGET_PPC)  
     if (env1->halted) {  
         if (env1->msr[MSR_EE] &&   
             (env1->interrupt_request &   
              (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER))) {  
             env1->halted = 0;  
         } else {  
             return EXCP_HALTED;  
         }  
     }  
 #elif defined(TARGET_SPARC)  
     if (env1->halted) {  
         if ((env1->interrupt_request & CPU_INTERRUPT_HARD) &&  
             (env1->psret != 0)) {  
             env1->halted = 0;  
         } else {  
             return EXCP_HALTED;  
         }  
     }  
 #elif defined(TARGET_ARM)  
     if (env1->halted) {  
         /* An interrupt wakes the CPU even if the I and F CPSR bits are  
            set.  */  
         if (env1->interrupt_request  
             & (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD)) {  
             env1->halted = 0;  
         } else {  
             return EXCP_HALTED;  
         }  
     }  
 #elif defined(TARGET_MIPS)  
     if (env1->halted) {  
         if (env1->interrupt_request &  
             (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER)) {  
             env1->halted = 0;  
         } else {  
             return EXCP_HALTED;  
         }  
     }  
 #endif  
   
     cpu_single_env = env1;       cpu_single_env = env1;
   
     /* first we save global registers */      /* first we save global registers */
     saved_env = env;  #define SAVE_HOST_REGS 1
   #include "hostregs_helper.h"
     env = env1;      env = env1;
     saved_T0 = T0;      SAVE_GLOBALS();
     saved_T1 = T1;  
 #if defined(reg_T2)  
     saved_T2 = T2;  
 #endif  
 #ifdef __sparc__  
     /* we also save i7 because longjmp may not restore it */  
     asm volatile ("mov %%i7, %0" : "=r" (saved_i7));  
 #endif  
   
 #if defined(TARGET_I386)  
 #ifdef reg_EAX  
     saved_EAX = EAX;  
 #endif  
 #ifdef reg_ECX  
     saved_ECX = ECX;  
 #endif  
 #ifdef reg_EDX  
     saved_EDX = EDX;  
 #endif  
 #ifdef reg_EBX  
     saved_EBX = EBX;  
 #endif  
 #ifdef reg_ESP  
     saved_ESP = ESP;  
 #endif  
 #ifdef reg_EBP  
     saved_EBP = EBP;  
 #endif  
 #ifdef reg_ESI  
     saved_ESI = ESI;  
 #endif  
 #ifdef reg_EDI  
     saved_EDI = EDI;  
 #endif  
   
     env_to_regs();      env_to_regs();
   #if defined(TARGET_I386)
     /* put eflags in CPU temporary format */      /* put eflags in CPU temporary format */
     CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);      CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
     DF = 1 - (2 * ((env->eflags >> 10) & 1));      DF = 1 - (2 * ((env->eflags >> 10) & 1));
     CC_OP = CC_OP_EFLAGS;      CC_OP = CC_OP_EFLAGS;
     env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);      env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
 #elif defined(TARGET_ARM)  
 #elif defined(TARGET_SPARC)  #elif defined(TARGET_SPARC)
 #if defined(reg_REGWPTR)  #if defined(reg_REGWPTR)
     saved_regwptr = REGWPTR;      saved_regwptr = REGWPTR;
 #endif  #endif
   #elif defined(TARGET_M68K)
       env->cc_op = CC_OP_FLAGS;
       env->cc_dest = env->sr & 0xf;
       env->cc_x = (env->sr >> 4) & 1;
   #elif defined(TARGET_ALPHA)
   #elif defined(TARGET_ARM)
 #elif defined(TARGET_PPC)  #elif defined(TARGET_PPC)
 #elif defined(TARGET_MIPS)  #elif defined(TARGET_MIPS)
 #elif defined(TARGET_SH4)  #elif defined(TARGET_SH4)
   #elif defined(TARGET_CRIS)
     /* XXXXX */      /* XXXXX */
 #else  #else
 #error unsupported target CPU  #error unsupported target CPU
Line 386  int cpu_exec(CPUState *env1) Line 348  int cpu_exec(CPUState *env1)
                     break;                      break;
                 } else if (env->user_mode_only) {                  } else if (env->user_mode_only) {
                     /* if user mode only, we simulate a fake exception                      /* if user mode only, we simulate a fake exception
                        which will be hanlded outside the cpu execution                         which will be handled outside the cpu execution
                        loop */                         loop */
 #if defined(TARGET_I386)  #if defined(TARGET_I386)
                     do_interrupt_user(env->exception_index,                       do_interrupt_user(env->exception_index,
                                       env->exception_is_int,                                         env->exception_is_int,
                                       env->error_code,                                         env->error_code,
                                       env->exception_next_eip);                                        env->exception_next_eip);
 #endif  #endif
                     ret = env->exception_index;                      ret = env->exception_index;
Line 401  int cpu_exec(CPUState *env1) Line 363  int cpu_exec(CPUState *env1)
                     /* simulate a real cpu exception. On i386, it can                      /* simulate a real cpu exception. On i386, it can
                        trigger new exceptions, but we do not handle                         trigger new exceptions, but we do not handle
                        double or triple faults yet. */                         double or triple faults yet. */
                     do_interrupt(env->exception_index,                       do_interrupt(env->exception_index,
                                  env->exception_is_int,                                    env->exception_is_int,
                                  env->error_code,                                    env->error_code,
                                  env->exception_next_eip, 0);                                   env->exception_next_eip, 0);
                       /* successfully delivered */
                       env->old_exception = -1;
 #elif defined(TARGET_PPC)  #elif defined(TARGET_PPC)
                     do_interrupt(env);                      do_interrupt(env);
 #elif defined(TARGET_MIPS)  #elif defined(TARGET_MIPS)
Line 415  int cpu_exec(CPUState *env1) Line 379  int cpu_exec(CPUState *env1)
                     do_interrupt(env);                      do_interrupt(env);
 #elif defined(TARGET_SH4)  #elif defined(TARGET_SH4)
                     do_interrupt(env);                      do_interrupt(env);
   #elif defined(TARGET_ALPHA)
                       do_interrupt(env);
   #elif defined(TARGET_CRIS)
                       do_interrupt(env);
   #elif defined(TARGET_M68K)
                       do_interrupt(0);
 #endif  #endif
                 }                  }
                 env->exception_index = -1;                  env->exception_index = -1;
             }               }
 #ifdef USE_KQEMU  #ifdef USE_KQEMU
             if (kqemu_is_ok(env) && env->interrupt_request == 0) {              if (kqemu_is_ok(env) && env->interrupt_request == 0) {
                 int ret;                  int ret;
Line 447  int cpu_exec(CPUState *env1) Line 417  int cpu_exec(CPUState *env1)
   
             T0 = 0; /* force lookup of first TB */              T0 = 0; /* force lookup of first TB */
             for(;;) {              for(;;) {
 #ifdef __sparc__                  SAVE_GLOBALS();
                 /* g1 can be modified by some libc? functions */   
                 tmp_T0 = T0;  
 #endif        
                 interrupt_request = env->interrupt_request;                  interrupt_request = env->interrupt_request;
                 if (__builtin_expect(interrupt_request, 0)) {                  if (__builtin_expect(interrupt_request, 0)
 #if defined(TARGET_I386)  #if defined(TARGET_I386)
                     /* if hardware interrupt pending, we execute it */                          && env->hflags & HF_GIF_MASK
                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&  #endif
                         (env->eflags & IF_MASK) &&                                   ) {
                       if (interrupt_request & CPU_INTERRUPT_DEBUG) {
                           env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
                           env->exception_index = EXCP_DEBUG;
                           cpu_loop_exit();
                       }
   #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
       defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS)
                       if (interrupt_request & CPU_INTERRUPT_HALT) {
                           env->interrupt_request &= ~CPU_INTERRUPT_HALT;
                           env->halted = 1;
                           env->exception_index = EXCP_HLT;
                           cpu_loop_exit();
                       }
   #endif
   #if defined(TARGET_I386)
                       if ((interrupt_request & CPU_INTERRUPT_SMI) &&
                           !(env->hflags & HF_SMM_MASK)) {
                           svm_check_intercept(SVM_EXIT_SMI);
                           env->interrupt_request &= ~CPU_INTERRUPT_SMI;
                           do_smm_enter();
                           BREAK_CHAIN;
                       } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
                           (env->eflags & IF_MASK || env->hflags & HF_HIF_MASK) &&
                         !(env->hflags & HF_INHIBIT_IRQ_MASK)) {                          !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
                         int intno;                          int intno;
                         env->interrupt_request &= ~CPU_INTERRUPT_HARD;                          svm_check_intercept(SVM_EXIT_INTR);
                           env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
                         intno = cpu_get_pic_interrupt(env);                          intno = cpu_get_pic_interrupt(env);
                         if (loglevel & CPU_LOG_TB_IN_ASM) {                          if (loglevel & CPU_LOG_TB_IN_ASM) {
                             fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);                              fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
Line 467  int cpu_exec(CPUState *env1) Line 458  int cpu_exec(CPUState *env1)
                         do_interrupt(intno, 0, 0, 0, 1);                          do_interrupt(intno, 0, 0, 0, 1);
                         /* ensure that no TB jump will be modified as                          /* ensure that no TB jump will be modified as
                            the program flow was changed */                             the program flow was changed */
 #ifdef __sparc__                          BREAK_CHAIN;
                         tmp_T0 = 0;  #if !defined(CONFIG_USER_ONLY)
 #else                      } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
                         T0 = 0;                          (env->eflags & IF_MASK) && !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
                            int intno;
                            /* FIXME: this should respect TPR */
                            env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
                            svm_check_intercept(SVM_EXIT_VINTR);
                            intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
                            if (loglevel & CPU_LOG_TB_IN_ASM)
                                fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
                            do_interrupt(intno, 0, 0, -1, 1);
                            stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl),
                                     ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK);
                           BREAK_CHAIN;
 #endif  #endif
                     }                      }
 #elif defined(TARGET_PPC)  #elif defined(TARGET_PPC)
Line 479  int cpu_exec(CPUState *env1) Line 481  int cpu_exec(CPUState *env1)
                         cpu_ppc_reset(env);                          cpu_ppc_reset(env);
                     }                      }
 #endif  #endif
                     if (msr_ee != 0) {                      if (interrupt_request & CPU_INTERRUPT_HARD) {
                         if ((interrupt_request & CPU_INTERRUPT_HARD)) {                          ppc_hw_interrupt(env);
                             /* Raise it */                          if (env->pending_interrupts == 0)
                             env->exception_index = EXCP_EXTERNAL;  
                             env->error_code = 0;  
                             do_interrupt(env);  
                             env->interrupt_request &= ~CPU_INTERRUPT_HARD;                              env->interrupt_request &= ~CPU_INTERRUPT_HARD;
 #ifdef __sparc__                          BREAK_CHAIN;
                             tmp_T0 = 0;  
 #else  
                             T0 = 0;  
 #endif  
                         } else if ((interrupt_request & CPU_INTERRUPT_TIMER)) {  
                             /* Raise it */  
                             env->exception_index = EXCP_DECR;  
                             env->error_code = 0;  
                             do_interrupt(env);  
                             env->interrupt_request &= ~CPU_INTERRUPT_TIMER;  
 #ifdef __sparc__  
                             tmp_T0 = 0;  
 #else  
                             T0 = 0;  
 #endif  
                         }  
                     }                      }
 #elif defined(TARGET_MIPS)  #elif defined(TARGET_MIPS)
                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&                      if ((interrupt_request & CPU_INTERRUPT_HARD) &&
                           (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
                         (env->CP0_Status & (1 << CP0St_IE)) &&                          (env->CP0_Status & (1 << CP0St_IE)) &&
                         (env->CP0_Status & env->CP0_Cause & 0x0000FF00) &&                          !(env->CP0_Status & (1 << CP0St_EXL)) &&
                         !(env->hflags & MIPS_HFLAG_EXL) &&                          !(env->CP0_Status & (1 << CP0St_ERL)) &&
                         !(env->hflags & MIPS_HFLAG_ERL) &&  
                         !(env->hflags & MIPS_HFLAG_DM)) {                          !(env->hflags & MIPS_HFLAG_DM)) {
                         /* Raise it */                          /* Raise it */
                         env->exception_index = EXCP_EXT_INTERRUPT;                          env->exception_index = EXCP_EXT_INTERRUPT;
                         env->error_code = 0;                          env->error_code = 0;
                         do_interrupt(env);                          do_interrupt(env);
                         env->interrupt_request &= ~CPU_INTERRUPT_HARD;                          BREAK_CHAIN;
 #ifdef __sparc__  
                         tmp_T0 = 0;  
 #else  
                         T0 = 0;  
 #endif  
                     }                      }
 #elif defined(TARGET_SPARC)  #elif defined(TARGET_SPARC)
                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&                      if ((interrupt_request & CPU_INTERRUPT_HARD) &&
Line 534  int cpu_exec(CPUState *env1) Line 512  int cpu_exec(CPUState *env1)
                             env->interrupt_request &= ~CPU_INTERRUPT_HARD;                              env->interrupt_request &= ~CPU_INTERRUPT_HARD;
                             do_interrupt(env->interrupt_index);                              do_interrupt(env->interrupt_index);
                             env->interrupt_index = 0;                              env->interrupt_index = 0;
 #ifdef __sparc__  #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
                             tmp_T0 = 0;                              cpu_check_irqs(env);
 #else  
                             T0 = 0;  
 #endif  #endif
                           BREAK_CHAIN;
                         }                          }
                     } else if (interrupt_request & CPU_INTERRUPT_TIMER) {                      } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
                         //do_interrupt(0, 0, 0, 0, 0);                          //do_interrupt(0, 0, 0, 0, 0);
                         env->interrupt_request &= ~CPU_INTERRUPT_TIMER;                          env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
                     } else if (interrupt_request & CPU_INTERRUPT_HALT) {                      }
                         env1->halted = 1;  
                         return EXCP_HALTED;  
                     }  
 #elif defined(TARGET_ARM)  #elif defined(TARGET_ARM)
                     if (interrupt_request & CPU_INTERRUPT_FIQ                      if (interrupt_request & CPU_INTERRUPT_FIQ
                         && !(env->uncached_cpsr & CPSR_F)) {                          && !(env->uncached_cpsr & CPSR_F)) {
                         env->exception_index = EXCP_FIQ;                          env->exception_index = EXCP_FIQ;
                         do_interrupt(env);                          do_interrupt(env);
                           BREAK_CHAIN;
                     }                      }
                       /* ARMv7-M interrupt return works by loading a magic value
                          into the PC.  On real hardware the load causes the
                          return to occur.  The qemu implementation performs the
                          jump normally, then does the exception return when the
                          CPU tries to execute code at the magic address.
                          This will cause the magic PC value to be pushed to
                          the stack if an interrupt occured at the wrong time.
                          We avoid this by disabling interrupts when
                          pc contains a magic address.  */
                     if (interrupt_request & CPU_INTERRUPT_HARD                      if (interrupt_request & CPU_INTERRUPT_HARD
                         && !(env->uncached_cpsr & CPSR_I)) {                          && ((IS_M(env) && env->regs[15] < 0xfffffff0)
                               || !(env->uncached_cpsr & CPSR_I))) {
                         env->exception_index = EXCP_IRQ;                          env->exception_index = EXCP_IRQ;
                         do_interrupt(env);                          do_interrupt(env);
                           BREAK_CHAIN;
                     }                      }
 #elif defined(TARGET_SH4)  #elif defined(TARGET_SH4)
                     /* XXXXX */                      if (interrupt_request & CPU_INTERRUPT_HARD) {
                           do_interrupt(env);
                           BREAK_CHAIN;
                       }
   #elif defined(TARGET_ALPHA)
                       if (interrupt_request & CPU_INTERRUPT_HARD) {
                           do_interrupt(env);
                           BREAK_CHAIN;
                       }
   #elif defined(TARGET_CRIS)
                       if (interrupt_request & CPU_INTERRUPT_HARD) {
                           do_interrupt(env);
                           env->interrupt_request &= ~CPU_INTERRUPT_HARD;
                           BREAK_CHAIN;
                       }
   #elif defined(TARGET_M68K)
                       if (interrupt_request & CPU_INTERRUPT_HARD
                           && ((env->sr & SR_I) >> SR_I_SHIFT)
                               < env->pending_level) {
                           /* Real hardware gets the interrupt vector via an
                              IACK cycle at this point.  Current emulated
                              hardware doesn't rely on this, so we
                              provide/save the vector when the interrupt is
                              first signalled.  */
                           env->exception_index = env->pending_vector;
                           do_interrupt(1);
                           BREAK_CHAIN;
                       }
 #endif  #endif
                      /* Don't use the cached interupt_request value,
                         do_interrupt may have updated the EXITTB flag. */
                     if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {                      if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
                         env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;                          env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
                         /* ensure that no TB jump will be modified as                          /* ensure that no TB jump will be modified as
                            the program flow was changed */                             the program flow was changed */
 #ifdef __sparc__                          BREAK_CHAIN;
                         tmp_T0 = 0;  
 #else  
                         T0 = 0;  
 #endif  
                     }                      }
                     if (interrupt_request & CPU_INTERRUPT_EXIT) {                      if (interrupt_request & CPU_INTERRUPT_EXIT) {
                         env->interrupt_request &= ~CPU_INTERRUPT_EXIT;                          env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
Line 579  int cpu_exec(CPUState *env1) Line 590  int cpu_exec(CPUState *env1)
                 }                  }
 #ifdef DEBUG_EXEC  #ifdef DEBUG_EXEC
                 if ((loglevel & CPU_LOG_TB_CPU)) {                  if ((loglevel & CPU_LOG_TB_CPU)) {
 #if defined(TARGET_I386)  
                     /* restore flags in standard format */                      /* restore flags in standard format */
 #ifdef reg_EAX                      regs_to_env();
                     env->regs[R_EAX] = EAX;  #if defined(TARGET_I386)
 #endif  
 #ifdef reg_EBX  
                     env->regs[R_EBX] = EBX;  
 #endif  
 #ifdef reg_ECX  
                     env->regs[R_ECX] = ECX;  
 #endif  
 #ifdef reg_EDX  
                     env->regs[R_EDX] = EDX;  
 #endif  
 #ifdef reg_ESI  
                     env->regs[R_ESI] = ESI;  
 #endif  
 #ifdef reg_EDI  
                     env->regs[R_EDI] = EDI;  
 #endif  
 #ifdef reg_EBP  
                     env->regs[R_EBP] = EBP;  
 #endif  
 #ifdef reg_ESP  
                     env->regs[R_ESP] = ESP;  
 #endif  
                     env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);                      env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
                     cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);                      cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
                     env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);                      env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
Line 616  int cpu_exec(CPUState *env1) Line 604  int cpu_exec(CPUState *env1)
                     cpu_dump_state(env, logfile, fprintf, 0);                      cpu_dump_state(env, logfile, fprintf, 0);
 #elif defined(TARGET_PPC)  #elif defined(TARGET_PPC)
                     cpu_dump_state(env, logfile, fprintf, 0);                      cpu_dump_state(env, logfile, fprintf, 0);
   #elif defined(TARGET_M68K)
                       cpu_m68k_flush_flags(env, env->cc_op);
                       env->cc_op = CC_OP_FLAGS;
                       env->sr = (env->sr & 0xffe0)
                                 | env->cc_dest | (env->cc_x << 4);
                       cpu_dump_state(env, logfile, fprintf, 0);
 #elif defined(TARGET_MIPS)  #elif defined(TARGET_MIPS)
                     cpu_dump_state(env, logfile, fprintf, 0);                      cpu_dump_state(env, logfile, fprintf, 0);
 #elif defined(TARGET_SH4)  #elif defined(TARGET_SH4)
                     cpu_dump_state(env, logfile, fprintf, 0);                      cpu_dump_state(env, logfile, fprintf, 0);
   #elif defined(TARGET_ALPHA)
                       cpu_dump_state(env, logfile, fprintf, 0);
   #elif defined(TARGET_CRIS)
                       cpu_dump_state(env, logfile, fprintf, 0);
 #else  #else
 #error unsupported target CPU   #error unsupported target CPU
 #endif  #endif
                 }                  }
 #endif  #endif
Line 633  int cpu_exec(CPUState *env1) Line 631  int cpu_exec(CPUState *env1)
                             lookup_symbol(tb->pc));                              lookup_symbol(tb->pc));
                 }                  }
 #endif  #endif
 #ifdef __sparc__                  RESTORE_GLOBALS();
                 T0 = tmp_T0;  
 #endif        
                 /* see if we can patch the calling TB. When the TB                  /* see if we can patch the calling TB. When the TB
                    spans two pages, we cannot safely do a direct                     spans two pages, we cannot safely do a direct
                    jump. */                     jump. */
Line 644  int cpu_exec(CPUState *env1) Line 640  int cpu_exec(CPUState *env1)
 #if USE_KQEMU  #if USE_KQEMU
                         (env->kqemu_enabled != 2) &&                          (env->kqemu_enabled != 2) &&
 #endif  #endif
                         tb->page_addr[1] == -1                          tb->page_addr[1] == -1) {
 #if defined(TARGET_I386) && defined(USE_CODE_COPY)  
                     && (tb->cflags & CF_CODE_COPY) ==   
                     (((TranslationBlock *)(T0 & ~3))->cflags & CF_CODE_COPY)  
 #endif  
                     ) {  
                     spin_lock(&tb_lock);                      spin_lock(&tb_lock);
                     tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb);                      tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb);
 #if defined(USE_CODE_COPY)  
                     /* propagates the FP use info */  
                     ((TranslationBlock *)(T0 & ~3))->cflags |=   
                         (tb->cflags & CF_FP_USED);  
 #endif  
                     spin_unlock(&tb_lock);                      spin_unlock(&tb_lock);
                 }                  }
                 }                  }
Line 668  int cpu_exec(CPUState *env1) Line 654  int cpu_exec(CPUState *env1)
                 __asm__ __volatile__("call      %0\n\t"                  __asm__ __volatile__("call      %0\n\t"
                                      "mov       %%o7,%%i0"                                       "mov       %%o7,%%i0"
                                      : /* no outputs */                                       : /* no outputs */
                                      : "r" (gen_func)                                        : "r" (gen_func)
                                      : "i0", "i1", "i2", "i3", "i4", "i5");                                       : "i0", "i1", "i2", "i3", "i4", "i5",
                                          "o0", "o1", "o2", "o3", "o4", "o5",
                                          "l0", "l1", "l2", "l3", "l4", "l5",
                                          "l6", "l7");
 #elif defined(__arm__)  #elif defined(__arm__)
                 asm volatile ("mov pc, %0\n\t"                  asm volatile ("mov pc, %0\n\t"
                               ".global exec_loop\n\t"                                ".global exec_loop\n\t"
Line 677  int cpu_exec(CPUState *env1) Line 666  int cpu_exec(CPUState *env1)
                               : /* no outputs */                                : /* no outputs */
                               : "r" (gen_func)                                : "r" (gen_func)
                               : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");                                : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
 #elif defined(TARGET_I386) && defined(USE_CODE_COPY)  
 {  
     if (!(tb->cflags & CF_CODE_COPY)) {  
         if ((tb->cflags & CF_FP_USED) && env->native_fp_regs) {  
             save_native_fp_state(env);  
         }  
         gen_func();  
     } else {  
         if ((tb->cflags & CF_FP_USED) && !env->native_fp_regs) {  
             restore_native_fp_state(env);  
         }  
         /* we work with native eflags */  
         CC_SRC = cc_table[CC_OP].compute_all();  
         CC_OP = CC_OP_EFLAGS;  
         asm(".globl exec_loop\n"  
             "\n"  
             "debug1:\n"  
             "    pushl %%ebp\n"  
             "    fs movl %10, %9\n"  
             "    fs movl %11, %%eax\n"  
             "    andl $0x400, %%eax\n"  
             "    fs orl %8, %%eax\n"  
             "    pushl %%eax\n"  
             "    popf\n"  
             "    fs movl %%esp, %12\n"  
             "    fs movl %0, %%eax\n"  
             "    fs movl %1, %%ecx\n"  
             "    fs movl %2, %%edx\n"  
             "    fs movl %3, %%ebx\n"  
             "    fs movl %4, %%esp\n"  
             "    fs movl %5, %%ebp\n"  
             "    fs movl %6, %%esi\n"  
             "    fs movl %7, %%edi\n"  
             "    fs jmp *%9\n"  
             "exec_loop:\n"  
             "    fs movl %%esp, %4\n"  
             "    fs movl %12, %%esp\n"  
             "    fs movl %%eax, %0\n"  
             "    fs movl %%ecx, %1\n"  
             "    fs movl %%edx, %2\n"  
             "    fs movl %%ebx, %3\n"  
             "    fs movl %%ebp, %5\n"  
             "    fs movl %%esi, %6\n"  
             "    fs movl %%edi, %7\n"  
             "    pushf\n"  
             "    popl %%eax\n"  
             "    movl %%eax, %%ecx\n"  
             "    andl $0x400, %%ecx\n"  
             "    shrl $9, %%ecx\n"  
             "    andl $0x8d5, %%eax\n"  
             "    fs movl %%eax, %8\n"  
             "    movl $1, %%eax\n"  
             "    subl %%ecx, %%eax\n"  
             "    fs movl %%eax, %11\n"  
             "    fs movl %9, %%ebx\n" /* get T0 value */  
             "    popl %%ebp\n"  
             :  
             : "m" (*(uint8_t *)offsetof(CPUState, regs[0])),  
             "m" (*(uint8_t *)offsetof(CPUState, regs[1])),  
             "m" (*(uint8_t *)offsetof(CPUState, regs[2])),  
             "m" (*(uint8_t *)offsetof(CPUState, regs[3])),  
             "m" (*(uint8_t *)offsetof(CPUState, regs[4])),  
             "m" (*(uint8_t *)offsetof(CPUState, regs[5])),  
             "m" (*(uint8_t *)offsetof(CPUState, regs[6])),  
             "m" (*(uint8_t *)offsetof(CPUState, regs[7])),  
             "m" (*(uint8_t *)offsetof(CPUState, cc_src)),  
             "m" (*(uint8_t *)offsetof(CPUState, tmp0)),  
             "a" (gen_func),  
             "m" (*(uint8_t *)offsetof(CPUState, df)),  
             "m" (*(uint8_t *)offsetof(CPUState, saved_esp))  
             : "%ecx", "%edx"  
             );  
     }  
 }  
 #elif defined(__ia64)  #elif defined(__ia64)
                 struct fptr {                  struct fptr {
                         void *ip;                          void *ip;
Line 780  int cpu_exec(CPUState *env1) Line 695  int cpu_exec(CPUState *env1)
                     cpu_loop_exit();                      cpu_loop_exit();
                 }                  }
 #endif  #endif
             }              } /* for(;;) */
         } else {          } else {
             env_to_regs();              env_to_regs();
         }          }
Line 788  int cpu_exec(CPUState *env1) Line 703  int cpu_exec(CPUState *env1)
   
   
 #if defined(TARGET_I386)  #if defined(TARGET_I386)
 #if defined(USE_CODE_COPY)  
     if (env->native_fp_regs) {  
         save_native_fp_state(env);  
     }  
 #endif  
     /* restore flags in standard format */      /* restore flags in standard format */
     env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);      env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
   
     /* restore global registers */  
 #ifdef reg_EAX  
     EAX = saved_EAX;  
 #endif  
 #ifdef reg_ECX  
     ECX = saved_ECX;  
 #endif  
 #ifdef reg_EDX  
     EDX = saved_EDX;  
 #endif  
 #ifdef reg_EBX  
     EBX = saved_EBX;  
 #endif  
 #ifdef reg_ESP  
     ESP = saved_ESP;  
 #endif  
 #ifdef reg_EBP  
     EBP = saved_EBP;  
 #endif  
 #ifdef reg_ESI  
     ESI = saved_ESI;  
 #endif  
 #ifdef reg_EDI  
     EDI = saved_EDI;  
 #endif  
 #elif defined(TARGET_ARM)  #elif defined(TARGET_ARM)
     /* XXX: Save/restore host fpu exception state?.  */      /* XXX: Save/restore host fpu exception state?.  */
 #elif defined(TARGET_SPARC)  #elif defined(TARGET_SPARC)
Line 828  int cpu_exec(CPUState *env1) Line 712  int cpu_exec(CPUState *env1)
     REGWPTR = saved_regwptr;      REGWPTR = saved_regwptr;
 #endif  #endif
 #elif defined(TARGET_PPC)  #elif defined(TARGET_PPC)
   #elif defined(TARGET_M68K)
       cpu_m68k_flush_flags(env, env->cc_op);
       env->cc_op = CC_OP_FLAGS;
       env->sr = (env->sr & 0xffe0)
                 | env->cc_dest | (env->cc_x << 4);
 #elif defined(TARGET_MIPS)  #elif defined(TARGET_MIPS)
 #elif defined(TARGET_SH4)  #elif defined(TARGET_SH4)
   #elif defined(TARGET_ALPHA)
   #elif defined(TARGET_CRIS)
     /* XXXXX */      /* XXXXX */
 #else  #else
 #error unsupported target CPU  #error unsupported target CPU
 #endif  #endif
 #ifdef __sparc__  
     asm volatile ("mov %0, %%i7" : : "r" (saved_i7));      /* restore global registers */
 #endif      RESTORE_GLOBALS();
     T0 = saved_T0;  #include "hostregs_helper.h"
     T1 = saved_T1;  
 #if defined(reg_T2)  
     T2 = saved_T2;  
 #endif  
     env = saved_env;  
     /* fail safe : never use cpu_single_env outside cpu_exec() */      /* fail safe : never use cpu_single_env outside cpu_exec() */
     cpu_single_env = NULL;       cpu_single_env = NULL;
     return ret;      return ret;
 }  }
   
Line 871  void cpu_x86_load_seg(CPUX86State *s, in Line 758  void cpu_x86_load_seg(CPUX86State *s, in
     env = s;      env = s;
     if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {      if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
         selector &= 0xffff;          selector &= 0xffff;
         cpu_x86_load_seg_cache(env, seg_reg, selector,           cpu_x86_load_seg_cache(env, seg_reg, selector,
                                (selector << 4), 0xffff, 0);                                 (selector << 4), 0xffff, 0);
     } else {      } else {
         load_seg(seg_reg, selector);          load_seg(seg_reg, selector);
Line 879  void cpu_x86_load_seg(CPUX86State *s, in Line 766  void cpu_x86_load_seg(CPUX86State *s, in
     env = saved_env;      env = saved_env;
 }  }
   
 void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32)  void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
 {  {
     CPUX86State *saved_env;      CPUX86State *saved_env;
   
     saved_env = env;      saved_env = env;
     env = s;      env = s;
       
     helper_fsave((target_ulong)ptr, data32);      helper_fsave(ptr, data32);
   
     env = saved_env;      env = saved_env;
 }  }
   
 void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32)  void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
 {  {
     CPUX86State *saved_env;      CPUX86State *saved_env;
   
     saved_env = env;      saved_env = env;
     env = s;      env = s;
       
     helper_frstor((target_ulong)ptr, data32);      helper_frstor(ptr, data32);
   
     env = saved_env;      env = saved_env;
 }  }
Line 914  void cpu_x86_frstor(CPUX86State *s, uint Line 801  void cpu_x86_frstor(CPUX86State *s, uint
    write caused the exception and otherwise 0'. 'old_set' is the     write caused the exception and otherwise 0'. 'old_set' is the
    signal set which should be restored */     signal set which should be restored */
 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,  static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                                     int is_write, sigset_t *old_set,                                       int is_write, sigset_t *old_set,
                                     void *puc)                                      void *puc)
 {  {
     TranslationBlock *tb;      TranslationBlock *tb;
Line 923  static inline int handle_cpu_signal(unsi Line 810  static inline int handle_cpu_signal(unsi
     if (cpu_single_env)      if (cpu_single_env)
         env = cpu_single_env; /* XXX: find a correct solution for multithread */          env = cpu_single_env; /* XXX: find a correct solution for multithread */
 #if defined(DEBUG_SIGNAL)  #if defined(DEBUG_SIGNAL)
     qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",       qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
                 pc, address, is_write, *(unsigned long *)old_set);                  pc, address, is_write, *(unsigned long *)old_set);
 #endif  #endif
     /* XXX: locking issue */      /* XXX: locking issue */
Line 932  static inline int handle_cpu_signal(unsi Line 819  static inline int handle_cpu_signal(unsi
     }      }
   
     /* see if it is an MMU fault */      /* see if it is an MMU fault */
     ret = cpu_x86_handle_mmu_fault(env, address, is_write,       ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
                                    ((env->hflags & HF_CPL_MASK) == 3), 0);  
     if (ret < 0)      if (ret < 0)
         return 0; /* not an MMU fault */          return 0; /* not an MMU fault */
     if (ret == 0)      if (ret == 0)
Line 947  static inline int handle_cpu_signal(unsi Line 833  static inline int handle_cpu_signal(unsi
     }      }
     if (ret == 1) {      if (ret == 1) {
 #if 0  #if 0
         printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",           printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
                env->eip, env->cr[2], env->error_code);                 env->eip, env->cr[2], env->error_code);
 #endif  #endif
         /* we restore the process signal mask as the sigreturn should          /* we restore the process signal mask as the sigreturn should
Line 974  static inline int handle_cpu_signal(unsi Line 860  static inline int handle_cpu_signal(unsi
     if (cpu_single_env)      if (cpu_single_env)
         env = cpu_single_env; /* XXX: find a correct solution for multithread */          env = cpu_single_env; /* XXX: find a correct solution for multithread */
 #if defined(DEBUG_SIGNAL)  #if defined(DEBUG_SIGNAL)
     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",       printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
            pc, address, is_write, *(unsigned long *)old_set);             pc, address, is_write, *(unsigned long *)old_set);
 #endif  #endif
     /* XXX: locking issue */      /* XXX: locking issue */
Line 982  static inline int handle_cpu_signal(unsi Line 868  static inline int handle_cpu_signal(unsi
         return 1;          return 1;
     }      }
     /* see if it is an MMU fault */      /* see if it is an MMU fault */
     ret = cpu_arm_handle_mmu_fault(env, address, is_write, 1, 0);      ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
     if (ret < 0)      if (ret < 0)
         return 0; /* not an MMU fault */          return 0; /* not an MMU fault */
     if (ret == 0)      if (ret == 0)
Line 1010  static inline int handle_cpu_signal(unsi Line 896  static inline int handle_cpu_signal(unsi
     if (cpu_single_env)      if (cpu_single_env)
         env = cpu_single_env; /* XXX: find a correct solution for multithread */          env = cpu_single_env; /* XXX: find a correct solution for multithread */
 #if defined(DEBUG_SIGNAL)  #if defined(DEBUG_SIGNAL)
     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",       printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
            pc, address, is_write, *(unsigned long *)old_set);             pc, address, is_write, *(unsigned long *)old_set);
 #endif  #endif
     /* XXX: locking issue */      /* XXX: locking issue */
Line 1018  static inline int handle_cpu_signal(unsi Line 904  static inline int handle_cpu_signal(unsi
         return 1;          return 1;
     }      }
     /* see if it is an MMU fault */      /* see if it is an MMU fault */
     ret = cpu_sparc_handle_mmu_fault(env, address, is_write, 1, 0);      ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
     if (ret < 0)      if (ret < 0)
         return 0; /* not an MMU fault */          return 0; /* not an MMU fault */
     if (ret == 0)      if (ret == 0)
Line 1042  static inline int handle_cpu_signal(unsi Line 928  static inline int handle_cpu_signal(unsi
 {  {
     TranslationBlock *tb;      TranslationBlock *tb;
     int ret;      int ret;
       
     if (cpu_single_env)      if (cpu_single_env)
         env = cpu_single_env; /* XXX: find a correct solution for multithread */          env = cpu_single_env; /* XXX: find a correct solution for multithread */
 #if defined(DEBUG_SIGNAL)  #if defined(DEBUG_SIGNAL)
     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",       printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
            pc, address, is_write, *(unsigned long *)old_set);             pc, address, is_write, *(unsigned long *)old_set);
 #endif  #endif
     /* XXX: locking issue */      /* XXX: locking issue */
Line 1055  static inline int handle_cpu_signal(unsi Line 941  static inline int handle_cpu_signal(unsi
     }      }
   
     /* see if it is an MMU fault */      /* see if it is an MMU fault */
     ret = cpu_ppc_handle_mmu_fault(env, address, is_write, msr_pr, 0);      ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
     if (ret < 0)      if (ret < 0)
         return 0; /* not an MMU fault */          return 0; /* not an MMU fault */
     if (ret == 0)      if (ret == 0)
Line 1070  static inline int handle_cpu_signal(unsi Line 956  static inline int handle_cpu_signal(unsi
     }      }
     if (ret == 1) {      if (ret == 1) {
 #if 0  #if 0
         printf("PF exception: NIP=0x%08x error=0x%x %p\n",           printf("PF exception: NIP=0x%08x error=0x%x %p\n",
                env->nip, env->error_code, tb);                 env->nip, env->error_code, tb);
 #endif  #endif
     /* we restore the process signal mask as the sigreturn should      /* we restore the process signal mask as the sigreturn should
Line 1085  static inline int handle_cpu_signal(unsi Line 971  static inline int handle_cpu_signal(unsi
     return 1;      return 1;
 }  }
   
   #elif defined(TARGET_M68K)
   static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                                       int is_write, sigset_t *old_set,
                                       void *puc)
   {
       TranslationBlock *tb;
       int ret;
   
       if (cpu_single_env)
           env = cpu_single_env; /* XXX: find a correct solution for multithread */
   #if defined(DEBUG_SIGNAL)
       printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
              pc, address, is_write, *(unsigned long *)old_set);
   #endif
       /* XXX: locking issue */
       if (is_write && page_unprotect(address, pc, puc)) {
           return 1;
       }
       /* see if it is an MMU fault */
       ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
       if (ret < 0)
           return 0; /* not an MMU fault */
       if (ret == 0)
           return 1; /* the MMU fault was handled without causing real CPU fault */
       /* now we have a real cpu fault */
       tb = tb_find_pc(pc);
       if (tb) {
           /* the PC is inside the translated code. It means that we have
              a virtual CPU fault */
           cpu_restore_state(tb, env, pc, puc);
       }
       /* we restore the process signal mask as the sigreturn should
          do it (XXX: use sigsetjmp) */
       sigprocmask(SIG_SETMASK, old_set, NULL);
       cpu_loop_exit();
       /* never comes here */
       return 1;
   }
   
 #elif defined (TARGET_MIPS)  #elif defined (TARGET_MIPS)
 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,  static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                                     int is_write, sigset_t *old_set,                                      int is_write, sigset_t *old_set,
Line 1092  static inline int handle_cpu_signal(unsi Line 1017  static inline int handle_cpu_signal(unsi
 {  {
     TranslationBlock *tb;      TranslationBlock *tb;
     int ret;      int ret;
       
     if (cpu_single_env)      if (cpu_single_env)
         env = cpu_single_env; /* XXX: find a correct solution for multithread */          env = cpu_single_env; /* XXX: find a correct solution for multithread */
 #if defined(DEBUG_SIGNAL)  #if defined(DEBUG_SIGNAL)
     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",       printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
            pc, address, is_write, *(unsigned long *)old_set);             pc, address, is_write, *(unsigned long *)old_set);
 #endif  #endif
     /* XXX: locking issue */      /* XXX: locking issue */
Line 1105  static inline int handle_cpu_signal(unsi Line 1030  static inline int handle_cpu_signal(unsi
     }      }
   
     /* see if it is an MMU fault */      /* see if it is an MMU fault */
     ret = cpu_mips_handle_mmu_fault(env, address, is_write, 1, 0);      ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
     if (ret < 0)      if (ret < 0)
         return 0; /* not an MMU fault */          return 0; /* not an MMU fault */
     if (ret == 0)      if (ret == 0)
Line 1120  static inline int handle_cpu_signal(unsi Line 1045  static inline int handle_cpu_signal(unsi
     }      }
     if (ret == 1) {      if (ret == 1) {
 #if 0  #if 0
         printf("PF exception: NIP=0x%08x error=0x%x %p\n",           printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
                env->nip, env->error_code, tb);                 env->PC, env->error_code, tb);
 #endif  #endif
     /* we restore the process signal mask as the sigreturn should      /* we restore the process signal mask as the sigreturn should
        do it (XXX: use sigsetjmp) */         do it (XXX: use sigsetjmp) */
Line 1142  static inline int handle_cpu_signal(unsi Line 1067  static inline int handle_cpu_signal(unsi
 {  {
     TranslationBlock *tb;      TranslationBlock *tb;
     int ret;      int ret;
       
     if (cpu_single_env)      if (cpu_single_env)
         env = cpu_single_env; /* XXX: find a correct solution for multithread */          env = cpu_single_env; /* XXX: find a correct solution for multithread */
 #if defined(DEBUG_SIGNAL)  #if defined(DEBUG_SIGNAL)
     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",       printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
            pc, address, is_write, *(unsigned long *)old_set);             pc, address, is_write, *(unsigned long *)old_set);
 #endif  #endif
     /* XXX: locking issue */      /* XXX: locking issue */
Line 1155  static inline int handle_cpu_signal(unsi Line 1080  static inline int handle_cpu_signal(unsi
     }      }
   
     /* see if it is an MMU fault */      /* see if it is an MMU fault */
     ret = cpu_sh4_handle_mmu_fault(env, address, is_write, 1, 0);      ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
     if (ret < 0)      if (ret < 0)
         return 0; /* not an MMU fault */          return 0; /* not an MMU fault */
     if (ret == 0)      if (ret == 0)
Line 1168  static inline int handle_cpu_signal(unsi Line 1093  static inline int handle_cpu_signal(unsi
            a virtual CPU fault */             a virtual CPU fault */
         cpu_restore_state(tb, env, pc, puc);          cpu_restore_state(tb, env, pc, puc);
     }      }
     if (ret == 1) {  
 #if 0  #if 0
         printf("PF exception: NIP=0x%08x error=0x%x %p\n",           printf("PF exception: NIP=0x%08x error=0x%x %p\n",
                env->nip, env->error_code, tb);                 env->nip, env->error_code, tb);
 #endif  #endif
     /* we restore the process signal mask as the sigreturn should      /* we restore the process signal mask as the sigreturn should
        do it (XXX: use sigsetjmp) */         do it (XXX: use sigsetjmp) */
         sigprocmask(SIG_SETMASK, old_set, NULL);      sigprocmask(SIG_SETMASK, old_set, NULL);
         //        do_raise_exception_err(env->exception_index, env->error_code);      cpu_loop_exit();
     } else {  
         /* activate soft MMU for this block */  
         cpu_resume_from_signal(env, puc);  
     }  
     /* never comes here */      /* never comes here */
     return 1;      return 1;
 }  }
 #else  
 #error unsupported target CPU  #elif defined (TARGET_ALPHA)
   static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                                       int is_write, sigset_t *old_set,
                                       void *puc)
   {
       TranslationBlock *tb;
       int ret;
   
       if (cpu_single_env)
           env = cpu_single_env; /* XXX: find a correct solution for multithread */
   #if defined(DEBUG_SIGNAL)
       printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
              pc, address, is_write, *(unsigned long *)old_set);
 #endif  #endif
       /* XXX: locking issue */
       if (is_write && page_unprotect(h2g(address), pc, puc)) {
           return 1;
       }
   
 #if defined(__i386__)      /* see if it is an MMU fault */
       ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
       if (ret < 0)
           return 0; /* not an MMU fault */
       if (ret == 0)
           return 1; /* the MMU fault was handled without causing real CPU fault */
   
 #if defined(USE_CODE_COPY)      /* now we have a real cpu fault */
 static void cpu_send_trap(unsigned long pc, int trap,       tb = tb_find_pc(pc);
                           struct ucontext *uc)      if (tb) {
           /* the PC is inside the translated code. It means that we have
              a virtual CPU fault */
           cpu_restore_state(tb, env, pc, puc);
       }
   #if 0
           printf("PF exception: NIP=0x%08x error=0x%x %p\n",
                  env->nip, env->error_code, tb);
   #endif
       /* we restore the process signal mask as the sigreturn should
          do it (XXX: use sigsetjmp) */
       sigprocmask(SIG_SETMASK, old_set, NULL);
       cpu_loop_exit();
       /* never comes here */
       return 1;
   }
   #elif defined (TARGET_CRIS)
   static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                                       int is_write, sigset_t *old_set,
                                       void *puc)
 {  {
     TranslationBlock *tb;      TranslationBlock *tb;
       int ret;
   
     if (cpu_single_env)      if (cpu_single_env)
         env = cpu_single_env; /* XXX: find a correct solution for multithread */          env = cpu_single_env; /* XXX: find a correct solution for multithread */
   #if defined(DEBUG_SIGNAL)
       printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
              pc, address, is_write, *(unsigned long *)old_set);
   #endif
       /* XXX: locking issue */
       if (is_write && page_unprotect(h2g(address), pc, puc)) {
           return 1;
       }
   
       /* see if it is an MMU fault */
       ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
       if (ret < 0)
           return 0; /* not an MMU fault */
       if (ret == 0)
           return 1; /* the MMU fault was handled without causing real CPU fault */
   
     /* now we have a real cpu fault */      /* now we have a real cpu fault */
     tb = tb_find_pc(pc);      tb = tb_find_pc(pc);
     if (tb) {      if (tb) {
         /* the PC is inside the translated code. It means that we have          /* the PC is inside the translated code. It means that we have
            a virtual CPU fault */             a virtual CPU fault */
         cpu_restore_state(tb, env, pc, uc);          cpu_restore_state(tb, env, pc, puc);
     }      }
     sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);  #if 0
     raise_exception_err(trap, env->error_code);          printf("PF exception: NIP=0x%08x error=0x%x %p\n",
                  env->nip, env->error_code, tb);
   #endif
       /* we restore the process signal mask as the sigreturn should
          do it (XXX: use sigsetjmp) */
       sigprocmask(SIG_SETMASK, old_set, NULL);
       cpu_loop_exit();
       /* never comes here */
       return 1;
 }  }
   
   #else
   #error unsupported target CPU
 #endif  #endif
   
 int cpu_signal_handler(int host_signum, struct siginfo *info,   #if defined(__i386__)
   
   #if defined(__APPLE__)
   # include <sys/ucontext.h>
   
   # define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
   # define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
   # define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
   #else
   # define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
   # define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
   # define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
   #endif
   
   int cpu_signal_handler(int host_signum, void *pinfo,
                        void *puc)                         void *puc)
 {  {
       siginfo_t *info = pinfo;
     struct ucontext *uc = puc;      struct ucontext *uc = puc;
     unsigned long pc;      unsigned long pc;
     int trapno;      int trapno;
Line 1223  int cpu_signal_handler(int host_signum,  Line 1226  int cpu_signal_handler(int host_signum, 
 #define REG_ERR    ERR  #define REG_ERR    ERR
 #define REG_TRAPNO TRAPNO  #define REG_TRAPNO TRAPNO
 #endif  #endif
     pc = uc->uc_mcontext.gregs[REG_EIP];      pc = EIP_sig(uc);
     trapno = uc->uc_mcontext.gregs[REG_TRAPNO];      trapno = TRAP_sig(uc);
 #if defined(TARGET_I386) && defined(USE_CODE_COPY)      return handle_cpu_signal(pc, (unsigned long)info->si_addr,
     if (trapno == 0x00 || trapno == 0x05) {                               trapno == 0xe ?
         /* send division by zero or bound exception */                               (ERROR_sig(uc) >> 1) & 1 : 0,
         cpu_send_trap(pc, trapno, uc);                               &uc->uc_sigmask, puc);
         return 1;  
     } else  
 #endif  
         return handle_cpu_signal(pc, (unsigned long)info->si_addr,   
                                  trapno == 0xe ?   
                                  (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,  
                                  &uc->uc_sigmask, puc);  
 }  }
   
 #elif defined(__x86_64__)  #elif defined(__x86_64__)
   
 int cpu_signal_handler(int host_signum, struct siginfo *info,  int cpu_signal_handler(int host_signum, void *pinfo,
                        void *puc)                         void *puc)
 {  {
       siginfo_t *info = pinfo;
     struct ucontext *uc = puc;      struct ucontext *uc = puc;
     unsigned long pc;      unsigned long pc;
   
     pc = uc->uc_mcontext.gregs[REG_RIP];      pc = uc->uc_mcontext.gregs[REG_RIP];
     return handle_cpu_signal(pc, (unsigned long)info->si_addr,       return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                              uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?                                uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
                              (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,                               (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
                              &uc->uc_sigmask, puc);                               &uc->uc_sigmask, puc);
 }  }
Line 1304  typedef struct ucontext SIGCONTEXT; Line 1301  typedef struct ucontext SIGCONTEXT;
 # define TRAP_sig(context)                      EXCEPREG_sig(exception, context) /* number of powerpc exception taken */  # define TRAP_sig(context)                      EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
 #endif /* __APPLE__ */  #endif /* __APPLE__ */
   
 int cpu_signal_handler(int host_signum, struct siginfo *info,   int cpu_signal_handler(int host_signum, void *pinfo,
                        void *puc)                         void *puc)
 {  {
       siginfo_t *info = pinfo;
     struct ucontext *uc = puc;      struct ucontext *uc = puc;
     unsigned long pc;      unsigned long pc;
     int is_write;      int is_write;
Line 1321  int cpu_signal_handler(int host_signum,  Line 1319  int cpu_signal_handler(int host_signum, 
     if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))      if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
         is_write = 1;          is_write = 1;
 #endif  #endif
     return handle_cpu_signal(pc, (unsigned long)info->si_addr,       return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                              is_write, &uc->uc_sigmask, puc);                               is_write, &uc->uc_sigmask, puc);
 }  }
   
 #elif defined(__alpha__)  #elif defined(__alpha__)
   
 int cpu_signal_handler(int host_signum, struct siginfo *info,   int cpu_signal_handler(int host_signum, void *pinfo,
                            void *puc)                             void *puc)
 {  {
       siginfo_t *info = pinfo;
     struct ucontext *uc = puc;      struct ucontext *uc = puc;
     uint32_t *pc = uc->uc_mcontext.sc_pc;      uint32_t *pc = uc->uc_mcontext.sc_pc;
     uint32_t insn = *pc;      uint32_t insn = *pc;
Line 1351  int cpu_signal_handler(int host_signum,  Line 1350  int cpu_signal_handler(int host_signum, 
         is_write = 1;          is_write = 1;
     }      }
   
     return handle_cpu_signal(pc, (unsigned long)info->si_addr,       return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                              is_write, &uc->uc_sigmask, puc);                               is_write, &uc->uc_sigmask, puc);
 }  }
 #elif defined(__sparc__)  #elif defined(__sparc__)
   
 int cpu_signal_handler(int host_signum, struct siginfo *info,   int cpu_signal_handler(int host_signum, void *pinfo,
                        void *puc)                         void *puc)
 {  {
       siginfo_t *info = pinfo;
     uint32_t *regs = (uint32_t *)(info + 1);      uint32_t *regs = (uint32_t *)(info + 1);
     void *sigmask = (regs + 20);      void *sigmask = (regs + 20);
     unsigned long pc;      unsigned long pc;
     int is_write;      int is_write;
     uint32_t insn;      uint32_t insn;
       
     /* XXX: is there a standard glibc define ? */      /* XXX: is there a standard glibc define ? */
     pc = regs[1];      pc = regs[1];
     /* XXX: need kernel patch to get write flag faster */      /* XXX: need kernel patch to get write flag faster */
Line 1383  int cpu_signal_handler(int host_signum,  Line 1383  int cpu_signal_handler(int host_signum, 
         break;          break;
       }        }
     }      }
     return handle_cpu_signal(pc, (unsigned long)info->si_addr,       return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                              is_write, sigmask, NULL);                               is_write, sigmask, NULL);
 }  }
   
 #elif defined(__arm__)  #elif defined(__arm__)
   
 int cpu_signal_handler(int host_signum, struct siginfo *info,   int cpu_signal_handler(int host_signum, void *pinfo,
                        void *puc)                         void *puc)
 {  {
       siginfo_t *info = pinfo;
     struct ucontext *uc = puc;      struct ucontext *uc = puc;
     unsigned long pc;      unsigned long pc;
     int is_write;      int is_write;
       
     pc = uc->uc_mcontext.gregs[R15];      pc = uc->uc_mcontext.gregs[R15];
     /* XXX: compute is_write */      /* XXX: compute is_write */
     is_write = 0;      is_write = 0;
     return handle_cpu_signal(pc, (unsigned long)info->si_addr,       return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                              is_write,                               is_write,
                              &uc->uc_sigmask);                               &uc->uc_sigmask, puc);
 }  }
   
 #elif defined(__mc68000)  #elif defined(__mc68000)
   
 int cpu_signal_handler(int host_signum, struct siginfo *info,   int cpu_signal_handler(int host_signum, void *pinfo,
                        void *puc)                         void *puc)
 {  {
       siginfo_t *info = pinfo;
     struct ucontext *uc = puc;      struct ucontext *uc = puc;
     unsigned long pc;      unsigned long pc;
     int is_write;      int is_write;
       
     pc = uc->uc_mcontext.gregs[16];      pc = uc->uc_mcontext.gregs[16];
     /* XXX: compute is_write */      /* XXX: compute is_write */
     is_write = 0;      is_write = 0;
     return handle_cpu_signal(pc, (unsigned long)info->si_addr,       return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                              is_write,                               is_write,
                              &uc->uc_sigmask, puc);                               &uc->uc_sigmask, puc);
 }  }
Line 1428  int cpu_signal_handler(int host_signum,  Line 1430  int cpu_signal_handler(int host_signum, 
 # define __ISR_VALID    1  # define __ISR_VALID    1
 #endif  #endif
   
 int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc)  int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
 {  {
       siginfo_t *info = pinfo;
     struct ucontext *uc = puc;      struct ucontext *uc = puc;
     unsigned long ip;      unsigned long ip;
     int is_write = 0;      int is_write = 0;
Line 1456  int cpu_signal_handler(int host_signum,  Line 1459  int cpu_signal_handler(int host_signum, 
   
 #elif defined(__s390__)  #elif defined(__s390__)
   
 int cpu_signal_handler(int host_signum, struct siginfo *info,   int cpu_signal_handler(int host_signum, void *pinfo,
                        void *puc)                         void *puc)
 {  {
       siginfo_t *info = pinfo;
     struct ucontext *uc = puc;      struct ucontext *uc = puc;
     unsigned long pc;      unsigned long pc;
     int is_write;      int is_write;
       
     pc = uc->uc_mcontext.psw.addr;      pc = uc->uc_mcontext.psw.addr;
     /* XXX: compute is_write */      /* XXX: compute is_write */
     is_write = 0;      is_write = 0;
     return handle_cpu_signal(pc, (unsigned long)info->si_addr,       return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                              is_write,                               is_write, &uc->uc_sigmask, puc);
                              &uc->uc_sigmask, puc);  }
   
   #elif defined(__mips__)
   
   int cpu_signal_handler(int host_signum, void *pinfo,
                          void *puc)
   {
       siginfo_t *info = pinfo;
       struct ucontext *uc = puc;
       greg_t pc = uc->uc_mcontext.pc;
       int is_write;
   
       /* XXX: compute is_write */
       is_write = 0;
       return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                                is_write, &uc->uc_sigmask, puc);
 }  }
   
 #else  #else

Removed from v.1.1.1.3  
changed lines
  Added in v.1.1.1.6


unix.superglobalmegacorp.com