diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index a4b6c730f385e72ebb62a08951571f06585a9de9..f07464deb9dea400369cfb10488f254170a745d6 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -18,15 +18,17 @@ /*#define EXCP_INTERRUPT 0x100*/ /* trap definitions */ +#define TT_TFAULT 0x01 #define TT_ILL_INSN 0x02 #define TT_PRIV_INSN 0x03 #define TT_NFPU_INSN 0x04 #define TT_WIN_OVF 0x05 #define TT_WIN_UNF 0x06 #define TT_FP_EXCP 0x08 +#define TT_DFAULT 0x09 +#define TT_EXTINT 0x10 #define TT_DIV_ZERO 0x2a #define TT_TRAP 0x80 -#define TT_EXTINT 0x10 #define PSR_NEG (1<<23) #define PSR_ZERO (1<<22) @@ -142,7 +144,6 @@ typedef struct CPUSPARCState { /* 0 = kernel, 1 = user (may have 2 = kernel code, 3 = user code ?) */ CPUTLBEntry tlb_read[2][CPU_TLB_SIZE]; CPUTLBEntry tlb_write[2][CPU_TLB_SIZE]; - int error_code; /* MMU regs */ uint32_t mmuregs[16]; /* temporary float registers */ diff --git a/target-sparc/exec.h b/target-sparc/exec.h index f905bdfe1dbe62d1ef03c868db9cc4b0f4cfe612..5e6c06214b2525c1bf63258d98d1eb201d38fa1b 100644 --- a/target-sparc/exec.h +++ b/target-sparc/exec.h @@ -41,7 +41,7 @@ void do_fcmpd(void); void do_ldd_kernel(target_ulong addr); void do_ldd_user(target_ulong addr); void do_ldd_raw(target_ulong addr); -void do_interrupt(int intno, int error_code); +void do_interrupt(int intno); void raise_exception(int tt); void memcpy32(target_ulong *dst, const target_ulong *src); target_ulong mmu_probe(target_ulong address, int mmulev); diff --git a/target-sparc/helper.c b/target-sparc/helper.c index b23be7cee7864d67c5bc059059ccf0edd77d2e4c..671d2f9b628d365629118623ecabd84b5112f916 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -44,8 +44,10 @@ int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw, int is_user, int is_softmmu) { env->mmuregs[4] = address; - env->exception_index = 0; /* XXX: must be incorrect */ - env->error_code = -2; /* XXX: is it really used ! */ + if (rw & 2) + env->exception_index = TT_TFAULT; + else + env->exception_index = TT_DFAULT; return 1; } @@ -95,7 +97,7 @@ void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr) cpu_restore_state(tb, env, pc, NULL); } } - raise_exception(ret); + cpu_loop_exit(); } env = saved_env; } @@ -229,7 +231,6 @@ int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, int is_user, int is_softmmu) { - int exception = 0; target_ulong virt_addr; target_phys_addr_t paddr; unsigned long vaddr; @@ -248,11 +249,15 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, env->mmuregs[3] |= (access_index << 5) | (error_code << 2) | 2; env->mmuregs[4] = address; /* Fault address register */ - if (env->mmuregs[0] & MMU_NF || env->psret == 0) // No fault - return 0; - env->exception_index = exception; - env->error_code = error_code; - return error_code; + if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) { + // No fault + cpu_abort(env, "Unsupported MMU no fault case"); + } + if (rw & 2) + env->exception_index = TT_TFAULT; + else + env->exception_index = TT_DFAULT; + return 1; } #endif @@ -289,15 +294,15 @@ void cpu_set_cwp(CPUState *env1, int new_cwp) env = saved_env; } -void do_interrupt(int intno, int error_code) +void do_interrupt(int intno) { int cwp; #ifdef DEBUG_PCALL if (loglevel & CPU_LOG_INT) { static int count; - fprintf(logfile, "%6d: v=%02x e=%04x pc=%08x npc=%08x SP=%08x\n", - count, intno, error_code, + fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n", + count, intno, env->pc, env->npc, env->regwptr[6]); #if 1 @@ -319,22 +324,15 @@ void do_interrupt(int intno, int error_code) #endif #if !defined(CONFIG_USER_ONLY) if (env->psret == 0) { - cpu_abort(cpu_single_env, "Trap while interrupts disabled, Error state"); + cpu_abort(cpu_single_env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index); return; } #endif env->psret = 0; cwp = (env->cwp - 1) & (NWINDOWS - 1); set_cwp(cwp); - if (intno & 0x80) { - env->regwptr[9] = env->pc; - env->regwptr[10] = env->npc; - } else { - /* XXX: this code is clearly incorrect - npc should have the - incorrect value */ - env->regwptr[9] = env->pc - 4; // XXX? - env->regwptr[10] = env->pc; - } + env->regwptr[9] = env->pc; + env->regwptr[10] = env->npc; env->psrps = env->psrs; env->psrs = 1; env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);