X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/a90b7318ba55b1aed71e299ec965bbd8f393b9b3..560f92cc34865f1f552079240d630a524a76c084:/cpu-exec.c diff --git a/cpu-exec.c b/cpu-exec.c index 4777babd2a..65af9a6d87 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -1,6 +1,6 @@ /* * i386 emulator main execution loop - * + * * Copyright (c) 2003-2005 Fabrice Bellard * * This library is free software; you can redistribute it and/or @@ -18,8 +18,10 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" +#define CPU_NO_GLOBAL_REGS #include "exec.h" #include "disas.h" +#include "tcg.h" #if !defined(CONFIG_SOFTMMU) #undef EAX @@ -35,19 +37,26 @@ #include #endif +#if defined(__sparc__) && !defined(HOST_SOLARIS) +// Work around ugly bugs in glibc that mangle global register contents +#undef env +#define env cpu_single_env +#endif + int tb_invalidated_flag; +static unsigned long next_tb; //#define DEBUG_EXEC //#define DEBUG_SIGNAL -#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_M68K) || \ - defined(TARGET_ALPHA) -/* XXX: unify with i386 target */ 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); } -#endif + #if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K)) #define reg_T2 #endif @@ -55,7 +64,7 @@ void cpu_loop_exit(void) /* exit the current TB from a signal handler. The host registers are restored in a state compatible with the CPU emulator */ -void cpu_resume_from_signal(CPUState *env1, void *puc) +void cpu_resume_from_signal(CPUState *env1, void *puc) { #if !defined(CONFIG_SOFTMMU) struct ucontext *uc = puc; @@ -74,23 +83,22 @@ void cpu_resume_from_signal(CPUState *env1, void *puc) longjmp(env->jmp_env, 1); } - static TranslationBlock *tb_find_slow(target_ulong pc, target_ulong cs_base, - unsigned int flags) + uint64_t flags) { TranslationBlock *tb, **ptb1; int code_gen_size; unsigned int h; target_ulong phys_pc, phys_page1, phys_page2, virt_page2; uint8_t *tc_ptr; - + spin_lock(&tb_lock); tb_invalidated_flag = 0; - + regs_to_env(); /* XXX: do it just before cpu_gen_code() */ - + /* find translated block using physical mappings */ phys_pc = get_phys_addr_code(env, pc); phys_page1 = phys_pc & TARGET_PAGE_MASK; @@ -101,13 +109,13 @@ static TranslationBlock *tb_find_slow(target_ulong pc, tb = *ptb1; if (!tb) goto not_found; - if (tb->pc == pc && + if (tb->pc == pc && tb->page_addr[0] == phys_page1 && - tb->cs_base == cs_base && + tb->cs_base == cs_base && tb->flags == flags) { /* check next page if needed */ if (tb->page_addr[1] != -1) { - virt_page2 = (pc & TARGET_PAGE_MASK) + + virt_page2 = (pc & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; phys_page2 = get_phys_addr_code(env, virt_page2); if (tb->page_addr[1] == phys_page2) @@ -133,9 +141,9 @@ static TranslationBlock *tb_find_slow(target_ulong pc, tb->tc_ptr = tc_ptr; tb->cs_base = cs_base; tb->flags = flags; - cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size); + cpu_gen_code(env, tb, &code_gen_size); 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 */ virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK; phys_page2 = -1; @@ -143,7 +151,7 @@ static TranslationBlock *tb_find_slow(target_ulong pc, phys_page2 = get_phys_addr_code(env, virt_page2); } tb_link_phys(tb, phys_pc, phys_page2); - + found: /* we add the TB in the virtual pc hash table */ env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb; @@ -155,7 +163,7 @@ static inline TranslationBlock *tb_find_fast(void) { TranslationBlock *tb; target_ulong cs_base, pc; - unsigned int flags; + uint64_t flags; /* we record a subset of the CPU state. It will always be the same before a given translated block @@ -163,6 +171,7 @@ static inline TranslationBlock *tb_find_fast(void) #if defined(TARGET_I386) flags = env->hflags; flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK)); + flags |= env->intercept; cs_base = env->segs[R_CS].base; pc = cs_base + env->eip; #elif defined(TARGET_ARM) @@ -172,6 +181,7 @@ static inline TranslationBlock *tb_find_fast(void) flags |= (1 << 6); if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) flags |= (1 << 7); + flags |= (env->condexec_bits << 8); cs_base = 0; pc = env->regs[15]; #elif defined(TARGET_SPARC) @@ -180,33 +190,38 @@ static inline TranslationBlock *tb_find_fast(void) flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2)) | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2); #else - // FPU enable . MMU enabled . MMU no-fault . Supervisor - flags = (env->psref << 3) | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1) - | env->psrs; + // FPU enable . Supervisor + flags = (env->psref << 4) | env->psrs; #endif cs_base = env->npc; pc = env->pc; #elif defined(TARGET_PPC) - flags = (msr_pr << MSR_PR) | (msr_fp << MSR_FP) | - (msr_se << MSR_SE) | (msr_le << MSR_LE); + flags = env->hflags; cs_base = 0; pc = env->nip; #elif defined(TARGET_MIPS) flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK); cs_base = 0; - pc = env->PC; + pc = env->PC[env->current_tc]; #elif defined(TARGET_M68K) - flags = env->fpcr & M68K_FPCR_PREC; + 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) - flags = env->sr & (SR_MD | SR_RB); - cs_base = 0; /* XXXXX */ + flags = env->flags; + cs_base = 0; pc = env->pc; #elif defined(TARGET_ALPHA) flags = env->ps; cs_base = 0; pc = env->pc; +#elif defined(TARGET_CRIS) + flags = env->pregs[PR_CCS] & U_FLAG; + flags |= env->dslot; + cs_base = 0; + pc = env->pc; #else #error unsupported CPU #endif @@ -220,13 +235,12 @@ static inline TranslationBlock *tb_find_fast(void) /* as some TB could have been invalidated because of memory exceptions while generating the code, we must recompute the hash index here */ - T0 = 0; + next_tb = 0; } } return tb; } - /* main execution loop */ int cpu_exec(CPUState *env1) @@ -237,109 +251,43 @@ int cpu_exec(CPUState *env1) #if defined(reg_REGWPTR) uint32_t *saved_regwptr; #endif -#endif -#if defined(__sparc__) && !defined(HOST_SOLARIS) - int saved_i7; - target_ulong tmp_T0; #endif int ret, interrupt_request; - void (*gen_func)(void); TranslationBlock *tb; uint8_t *tc_ptr; -#if defined(TARGET_I386) - /* handle exit of HALTED state */ - 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)) { - 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. We use EXITTB to silently wake CPU without causing an - actual interrupt. */ - if (env1->interrupt_request & - (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB)) { - 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; - } - } -#elif defined(TARGET_ALPHA) - if (env1->halted) { - if (env1->interrupt_request & CPU_INTERRUPT_HARD) { - env1->halted = 0; - } else { - return EXCP_HALTED; - } - } -#endif + if (cpu_halted(env1) == EXCP_HALTED) + return EXCP_HALTED; - cpu_single_env = env1; + cpu_single_env = env1; /* first we save global registers */ #define SAVE_HOST_REGS 1 #include "hostregs_helper.h" env = env1; -#if defined(__sparc__) && !defined(HOST_SOLARIS) - /* we also save i7 because longjmp may not restore it */ - asm volatile ("mov %%i7, %0" : "=r" (saved_i7)); -#endif -#if defined(TARGET_I386) env_to_regs(); +#if defined(TARGET_I386) /* put eflags in CPU temporary format */ CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); DF = 1 - (2 * ((env->eflags >> 10) & 1)); CC_OP = CC_OP_EFLAGS; env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); -#elif defined(TARGET_ARM) #elif defined(TARGET_SPARC) #if defined(reg_REGWPTR) saved_regwptr = REGWPTR; #endif -#elif defined(TARGET_PPC) #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_MIPS) #elif defined(TARGET_SH4) +#elif defined(TARGET_CRIS) /* XXXXX */ -#elif defined(TARGET_ALPHA) - env_to_regs(); #else #error unsupported target CPU #endif @@ -360,10 +308,12 @@ int cpu_exec(CPUState *env1) which will be handled outside the cpu execution loop */ #if defined(TARGET_I386) - do_interrupt_user(env->exception_index, - env->exception_is_int, - env->error_code, + do_interrupt_user(env->exception_index, + env->exception_is_int, + env->error_code, env->exception_next_eip); + /* successfully delivered */ + env->old_exception = -1; #endif ret = env->exception_index; break; @@ -372,9 +322,9 @@ int cpu_exec(CPUState *env1) /* simulate a real cpu exception. On i386, it can trigger new exceptions, but we do not handle double or triple faults yet. */ - do_interrupt(env->exception_index, - env->exception_is_int, - env->error_code, + do_interrupt(env->exception_index, + env->exception_is_int, + env->error_code, env->exception_next_eip, 0); /* successfully delivered */ env->old_exception = -1; @@ -390,10 +340,14 @@ int cpu_exec(CPUState *env1) 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 } env->exception_index = -1; - } + } #ifdef USE_KQEMU if (kqemu_is_ok(env) && env->interrupt_request == 0) { int ret; @@ -420,21 +374,21 @@ int cpu_exec(CPUState *env1) } #endif - T0 = 0; /* force lookup of first TB */ + next_tb = 0; /* force lookup of first TB */ for(;;) { -#if defined(__sparc__) && !defined(HOST_SOLARIS) - /* g1 can be modified by some libc? functions */ - tmp_T0 = T0; -#endif interrupt_request = env->interrupt_request; - if (__builtin_expect(interrupt_request, 0)) { + if (__builtin_expect(interrupt_request, 0) +#if defined(TARGET_I386) + && env->hflags & HF_GIF_MASK +#endif + && likely(!(env->singlestep_enabled & SSTEP_NOIRQ))) { 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_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) if (interrupt_request & CPU_INTERRUPT_HALT) { env->interrupt_request &= ~CPU_INTERRUPT_HALT; env->halted = 1; @@ -445,18 +399,22 @@ int cpu_exec(CPUState *env1) #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(); -#if defined(__sparc__) && !defined(HOST_SOLARIS) - tmp_T0 = 0; -#else - T0 = 0; -#endif + next_tb = 0; + } else if ((interrupt_request & CPU_INTERRUPT_NMI) && + !(env->hflags & HF_NMI_MASK)) { + env->interrupt_request &= ~CPU_INTERRUPT_NMI; + env->hflags |= HF_NMI_MASK; + do_interrupt(EXCP02_NMI, 0, 0, 0, 1); + next_tb = 0; } else if ((interrupt_request & CPU_INTERRUPT_HARD) && - (env->eflags & IF_MASK) && + (env->eflags & IF_MASK || env->hflags & HF_HIF_MASK) && !(env->hflags & HF_INHIBIT_IRQ_MASK)) { 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); if (loglevel & CPU_LOG_TB_IN_ASM) { fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno); @@ -464,10 +422,21 @@ int cpu_exec(CPUState *env1) do_interrupt(intno, 0, 0, 0, 1); /* ensure that no TB jump will be modified as the program flow was changed */ -#if defined(__sparc__) && !defined(HOST_SOLARIS) - tmp_T0 = 0; -#else - T0 = 0; + next_tb = 0; +#if !defined(CONFIG_USER_ONLY) + } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) && + (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); + next_tb = 0; #endif } #elif defined(TARGET_PPC) @@ -480,11 +449,7 @@ int cpu_exec(CPUState *env1) ppc_hw_interrupt(env); if (env->pending_interrupts == 0) env->interrupt_request &= ~CPU_INTERRUPT_HARD; -#if defined(__sparc__) && !defined(HOST_SOLARIS) - tmp_T0 = 0; -#else - T0 = 0; -#endif + next_tb = 0; } #elif defined(TARGET_MIPS) if ((interrupt_request & CPU_INTERRUPT_HARD) && @@ -497,11 +462,7 @@ int cpu_exec(CPUState *env1) env->exception_index = EXCP_EXT_INTERRUPT; env->error_code = 0; do_interrupt(env); -#if defined(__sparc__) && !defined(HOST_SOLARIS) - tmp_T0 = 0; -#else - T0 = 0; -#endif + next_tb = 0; } #elif defined(TARGET_SPARC) if ((interrupt_request & CPU_INTERRUPT_HARD) && @@ -515,11 +476,10 @@ int cpu_exec(CPUState *env1) env->interrupt_request &= ~CPU_INTERRUPT_HARD; do_interrupt(env->interrupt_index); env->interrupt_index = 0; -#if defined(__sparc__) && !defined(HOST_SOLARIS) - tmp_T0 = 0; -#else - T0 = 0; +#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) + cpu_check_irqs(env); #endif + next_tb = 0; } } else if (interrupt_request & CPU_INTERRUPT_TIMER) { //do_interrupt(0, 0, 0, 0, 0); @@ -530,17 +490,51 @@ int cpu_exec(CPUState *env1) && !(env->uncached_cpsr & CPSR_F)) { env->exception_index = EXCP_FIQ; do_interrupt(env); + next_tb = 0; } + /* 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 - && !(env->uncached_cpsr & CPSR_I)) { + && ((IS_M(env) && env->regs[15] < 0xfffffff0) + || !(env->uncached_cpsr & CPSR_I))) { env->exception_index = EXCP_IRQ; do_interrupt(env); + next_tb = 0; } #elif defined(TARGET_SH4) - /* XXXXX */ + if (interrupt_request & CPU_INTERRUPT_HARD) { + do_interrupt(env); + next_tb = 0; + } #elif defined(TARGET_ALPHA) if (interrupt_request & CPU_INTERRUPT_HARD) { do_interrupt(env); + next_tb = 0; + } +#elif defined(TARGET_CRIS) + if (interrupt_request & CPU_INTERRUPT_HARD) { + do_interrupt(env); + next_tb = 0; + } +#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); + next_tb = 0; } #endif /* Don't use the cached interupt_request value, @@ -549,11 +543,7 @@ int cpu_exec(CPUState *env1) env->interrupt_request &= ~CPU_INTERRUPT_EXITTB; /* ensure that no TB jump will be modified as the program flow was changed */ -#if defined(__sparc__) && !defined(HOST_SOLARIS) - tmp_T0 = 0; -#else - T0 = 0; -#endif + next_tb = 0; } if (interrupt_request & CPU_INTERRUPT_EXIT) { env->interrupt_request &= ~CPU_INTERRUPT_EXIT; @@ -563,32 +553,9 @@ int cpu_exec(CPUState *env1) } #ifdef DEBUG_EXEC if ((loglevel & CPU_LOG_TB_CPU)) { -#if defined(TARGET_I386) /* restore flags in standard format */ -#ifdef reg_EAX - env->regs[R_EAX] = EAX; -#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 + regs_to_env(); +#if defined(TARGET_I386) env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK); 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); @@ -612,8 +579,10 @@ int cpu_exec(CPUState *env1) 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 -#error unsupported target CPU +#error unsupported target CPU #endif } #endif @@ -625,139 +594,29 @@ int cpu_exec(CPUState *env1) lookup_symbol(tb->pc)); } #endif -#if defined(__sparc__) && !defined(HOST_SOLARIS) - T0 = tmp_T0; -#endif /* see if we can patch the calling TB. When the TB spans two pages, we cannot safely do a direct jump. */ { - if (T0 != 0 && -#if USE_KQEMU + if (next_tb != 0 && +#ifdef USE_KQEMU (env->kqemu_enabled != 2) && #endif - 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 - ) { + tb->page_addr[1] == -1) { spin_lock(&tb_lock); - 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 + tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb); spin_unlock(&tb_lock); } } tc_ptr = tb->tc_ptr; env->current_tb = tb; /* execute the generated code */ - gen_func = (void *)tc_ptr; -#if defined(__sparc__) - __asm__ __volatile__("call %0\n\t" - "mov %%o7,%%i0" - : /* no outputs */ - : "r" (gen_func) - : "i0", "i1", "i2", "i3", "i4", "i5", - "o0", "o1", "o2", "o3", "o4", "o5", - "l0", "l1", "l2", "l3", "l4", "l5", - "l6", "l7"); -#elif defined(__arm__) - asm volatile ("mov pc, %0\n\t" - ".global exec_loop\n\t" - "exec_loop:\n\t" - : /* no outputs */ - : "r" (gen_func) - : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14"); -#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) - struct fptr { - void *ip; - void *gp; - } fp; - - fp.ip = tc_ptr; - fp.gp = code_gen_buffer + 2 * (1 << 20); - (*(void (*)(void)) &fp)(); -#else - gen_func(); +#if defined(__sparc__) && !defined(HOST_SOLARIS) +#undef env + env = cpu_single_env; +#define env cpu_single_env #endif + next_tb = tcg_qemu_tb_exec(tc_ptr); env->current_tb = NULL; /* reset soft MMU for next block (it can currently only be set by a memory fault) */ @@ -765,7 +624,7 @@ int cpu_exec(CPUState *env1) if (env->hflags & HF_SOFTMMU_MASK) { env->hflags &= ~HF_SOFTMMU_MASK; /* do not allow linking to another block */ - T0 = 0; + next_tb = 0; } #endif #if defined(USE_KQEMU) @@ -775,7 +634,7 @@ int cpu_exec(CPUState *env1) cpu_loop_exit(); } #endif - } + } /* for(;;) */ } else { env_to_regs(); } @@ -783,11 +642,6 @@ int cpu_exec(CPUState *env1) #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 */ env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK); #elif defined(TARGET_ARM) @@ -805,19 +659,17 @@ int cpu_exec(CPUState *env1) #elif defined(TARGET_MIPS) #elif defined(TARGET_SH4) #elif defined(TARGET_ALPHA) +#elif defined(TARGET_CRIS) /* XXXXX */ #else #error unsupported target CPU #endif /* restore global registers */ -#if defined(__sparc__) && !defined(HOST_SOLARIS) - asm volatile ("mov %0, %%i7" : : "r" (saved_i7)); -#endif #include "hostregs_helper.h" /* fail safe : never use cpu_single_env outside cpu_exec() */ - cpu_single_env = NULL; + cpu_single_env = NULL; return ret; } @@ -844,34 +696,34 @@ void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector) env = s; if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) { selector &= 0xffff; - cpu_x86_load_seg_cache(env, seg_reg, selector, + cpu_x86_load_seg_cache(env, seg_reg, selector, (selector << 4), 0xffff, 0); } else { - load_seg(seg_reg, selector); + helper_load_seg(seg_reg, selector); } 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; saved_env = env; env = s; - - helper_fsave((target_ulong)ptr, data32); + + helper_fsave(ptr, data32); 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; saved_env = env; env = s; - - helper_frstor((target_ulong)ptr, data32); + + helper_frstor(ptr, data32); env = saved_env; } @@ -887,7 +739,7 @@ void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32) write caused the exception and otherwise 0'. 'old_set' is the signal set which should be restored */ 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) { TranslationBlock *tb; @@ -896,7 +748,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, if (cpu_single_env) env = cpu_single_env; /* XXX: find a correct solution for multithread */ #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); #endif /* XXX: locking issue */ @@ -905,8 +757,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, } /* see if it is an MMU fault */ - ret = cpu_x86_handle_mmu_fault(env, address, is_write, - ((env->hflags & HF_CPL_MASK) == 3), 0); + ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); if (ret < 0) return 0; /* not an MMU fault */ if (ret == 0) @@ -920,7 +771,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, } if (ret == 1) { #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); #endif /* we restore the process signal mask as the sigreturn should @@ -947,7 +798,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, 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", + 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 */ @@ -955,7 +806,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, return 1; } /* 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) return 0; /* not an MMU fault */ if (ret == 0) @@ -971,6 +822,8 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, do it (XXX: use sigsetjmp) */ sigprocmask(SIG_SETMASK, old_set, NULL); cpu_loop_exit(); + /* never comes here */ + return 1; } #elif defined(TARGET_SPARC) static inline int handle_cpu_signal(unsigned long pc, unsigned long address, @@ -983,7 +836,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, 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", + 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 */ @@ -991,7 +844,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, return 1; } /* 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) return 0; /* not an MMU fault */ if (ret == 0) @@ -1007,6 +860,8 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, do it (XXX: use sigsetjmp) */ sigprocmask(SIG_SETMASK, old_set, NULL); cpu_loop_exit(); + /* never comes here */ + return 1; } #elif defined (TARGET_PPC) static inline int handle_cpu_signal(unsigned long pc, unsigned long address, @@ -1015,11 +870,11 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, { 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", + 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 */ @@ -1028,7 +883,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, } /* 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) return 0; /* not an MMU fault */ if (ret == 0) @@ -1043,7 +898,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, } if (ret == 1) { #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); #endif /* we restore the process signal mask as the sigreturn should @@ -1069,7 +924,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, 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", + 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 */ @@ -1077,7 +932,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, return 1; } /* see if it is an MMU fault */ - ret = cpu_m68k_handle_mmu_fault(env, address, is_write, 1, 0); + 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) @@ -1104,11 +959,11 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, { 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", + 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 */ @@ -1117,7 +972,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, } /* 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) return 0; /* not an MMU fault */ if (ret == 0) @@ -1132,8 +987,8 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, } if (ret == 1) { #if 0 - printf("PF exception: NIP=0x%08x error=0x%x %p\n", - env->nip, env->error_code, tb); + printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n", + env->PC, env->error_code, tb); #endif /* we restore the process signal mask as the sigreturn should do it (XXX: use sigsetjmp) */ @@ -1154,11 +1009,11 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, { 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", + 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 */ @@ -1167,7 +1022,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, } /* 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) return 0; /* not an MMU fault */ if (ret == 0) @@ -1181,7 +1036,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, cpu_restore_state(tb, env, pc, puc); } #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); #endif /* we restore the process signal mask as the sigreturn should @@ -1199,11 +1054,11 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, { 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", + 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 */ @@ -1212,7 +1067,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, } /* see if it is an MMU fault */ - ret = cpu_alpha_handle_mmu_fault(env, address, is_write, 1, 0); + 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) @@ -1226,7 +1081,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, cpu_restore_state(tb, env, pc, puc); } #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); #endif /* we restore the process signal mask as the sigreturn should @@ -1236,6 +1091,47 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, /* 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; + 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(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 */ + 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; +} + #else #error unsupported target CPU #endif @@ -1254,27 +1150,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, # define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR]) #endif -#if defined(USE_CODE_COPY) -static void cpu_send_trap(unsigned long pc, int trap, - struct ucontext *uc) -{ - TranslationBlock *tb; - - if (cpu_single_env) - env = cpu_single_env; /* XXX: find a correct solution for multithread */ - /* now we have a real cpu fault */ - tb = tb_find_pc(pc); - if (tb) { - /* the PC is inside the translated code. It means that we have - a virtual CPU fault */ - cpu_restore_state(tb, env, pc, uc); - } - sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL); - raise_exception_err(trap, env->error_code); -} -#endif - -int cpu_signal_handler(int host_signum, void *pinfo, +int cpu_signal_handler(int host_signum, void *pinfo, void *puc) { siginfo_t *info = pinfo; @@ -1290,17 +1166,10 @@ int cpu_signal_handler(int host_signum, void *pinfo, #endif pc = EIP_sig(uc); trapno = TRAP_sig(uc); -#if defined(TARGET_I386) && defined(USE_CODE_COPY) - if (trapno == 0x00 || trapno == 0x05) { - /* send division by zero or bound exception */ - cpu_send_trap(pc, trapno, uc); - return 1; - } else -#endif - return handle_cpu_signal(pc, (unsigned long)info->si_addr, - trapno == 0xe ? - (ERROR_sig(uc) >> 1) & 1 : 0, - &uc->uc_sigmask, puc); + return handle_cpu_signal(pc, (unsigned long)info->si_addr, + trapno == 0xe ? + (ERROR_sig(uc) >> 1) & 1 : 0, + &uc->uc_sigmask, puc); } #elif defined(__x86_64__) @@ -1313,8 +1182,8 @@ int cpu_signal_handler(int host_signum, void *pinfo, unsigned long pc; pc = uc->uc_mcontext.gregs[REG_RIP]; - return handle_cpu_signal(pc, (unsigned long)info->si_addr, - uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ? + return handle_cpu_signal(pc, (unsigned long)info->si_addr, + uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ? (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0, &uc->uc_sigmask, puc); } @@ -1370,7 +1239,7 @@ typedef struct ucontext SIGCONTEXT; # define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */ #endif /* __APPLE__ */ -int cpu_signal_handler(int host_signum, void *pinfo, +int cpu_signal_handler(int host_signum, void *pinfo, void *puc) { siginfo_t *info = pinfo; @@ -1388,13 +1257,13 @@ int cpu_signal_handler(int host_signum, void *pinfo, if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000)) is_write = 1; #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); } #elif defined(__alpha__) -int cpu_signal_handler(int host_signum, void *pinfo, +int cpu_signal_handler(int host_signum, void *pinfo, void *puc) { siginfo_t *info = pinfo; @@ -1419,23 +1288,28 @@ int cpu_signal_handler(int host_signum, void *pinfo, 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); } #elif defined(__sparc__) -int cpu_signal_handler(int host_signum, void *pinfo, +int cpu_signal_handler(int host_signum, void *pinfo, void *puc) { siginfo_t *info = pinfo; - uint32_t *regs = (uint32_t *)(info + 1); - void *sigmask = (regs + 20); - unsigned long pc; int is_write; uint32_t insn; - +#if !defined(__arch64__) || defined(HOST_SOLARIS) + uint32_t *regs = (uint32_t *)(info + 1); + void *sigmask = (regs + 20); /* XXX: is there a standard glibc define ? */ - pc = regs[1]; + unsigned long pc = regs[1]; +#else + struct sigcontext *sc = puc; + unsigned long pc = sc->sigc_regs.tpc; + void *sigmask = (void *)sc->sigc_mask; +#endif + /* XXX: need kernel patch to get write flag faster */ is_write = 0; insn = *(uint32_t *)pc; @@ -1452,42 +1326,42 @@ int cpu_signal_handler(int host_signum, void *pinfo, 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); } #elif defined(__arm__) -int cpu_signal_handler(int host_signum, void *pinfo, +int cpu_signal_handler(int host_signum, void *pinfo, void *puc) { siginfo_t *info = pinfo; struct ucontext *uc = puc; unsigned long pc; int is_write; - - pc = uc->uc_mcontext.gregs[R15]; + + pc = uc->uc_mcontext.arm_pc; /* XXX: compute is_write */ 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, &uc->uc_sigmask, puc); } #elif defined(__mc68000) -int cpu_signal_handler(int host_signum, void *pinfo, +int cpu_signal_handler(int host_signum, void *pinfo, void *puc) { siginfo_t *info = pinfo; struct ucontext *uc = puc; unsigned long pc; int is_write; - + pc = uc->uc_mcontext.gregs[16]; /* XXX: compute is_write */ is_write = 0; - return handle_cpu_signal(pc, (unsigned long)info->si_addr, + return handle_cpu_signal(pc, (unsigned long)info->si_addr, is_write, &uc->uc_sigmask, puc); } @@ -1528,17 +1402,50 @@ int cpu_signal_handler(int host_signum, void *pinfo, void *puc) #elif defined(__s390__) -int cpu_signal_handler(int host_signum, void *pinfo, +int cpu_signal_handler(int host_signum, void *pinfo, void *puc) { siginfo_t *info = pinfo; struct ucontext *uc = puc; unsigned long pc; int is_write; - + pc = uc->uc_mcontext.psw.addr; /* XXX: compute is_write */ is_write = 0; + return handle_cpu_signal(pc, (unsigned long)info->si_addr, + is_write, &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); +} + +#elif defined(__hppa__) + +int cpu_signal_handler(int host_signum, void *pinfo, + void *puc) +{ + struct siginfo *info = pinfo; + struct ucontext *uc = puc; + unsigned long pc; + int is_write; + + pc = uc->uc_mcontext.sc_iaoq[0]; + /* FIXME: compute is_write */ + is_write = 0; return handle_cpu_signal(pc, (unsigned long)info->si_addr, is_write, &uc->uc_sigmask, puc);