diff options
-rw-r--r-- | cpu-exec.c | 5 | ||||
-rw-r--r-- | target-sparc/exec.h | 2 | ||||
-rw-r--r-- | target-sparc/helper.c | 221 | ||||
-rw-r--r-- | target-sparc/helper.h | 1 | ||||
-rw-r--r-- | target-sparc/op_helper.c | 247 |
5 files changed, 233 insertions, 243 deletions
diff --git a/cpu-exec.c b/cpu-exec.c index 65af9a6d87..5e64fa43ca 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -333,7 +333,7 @@ int cpu_exec(CPUState *env1) #elif defined(TARGET_MIPS) do_interrupt(env); #elif defined(TARGET_SPARC) - do_interrupt(env->exception_index); + do_interrupt(env); #elif defined(TARGET_ARM) do_interrupt(env); #elif defined(TARGET_SH4) @@ -474,7 +474,8 @@ int cpu_exec(CPUState *env1) (pil == 15 || pil > env->psrpil)) || type != TT_EXTINT) { env->interrupt_request &= ~CPU_INTERRUPT_HARD; - do_interrupt(env->interrupt_index); + env->exception_index = env->interrupt_index; + do_interrupt(env); env->interrupt_index = 0; #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) cpu_check_irqs(env); diff --git a/target-sparc/exec.h b/target-sparc/exec.h index 19d1732e7c..3ef0cf9aca 100644 --- a/target-sparc/exec.h +++ b/target-sparc/exec.h @@ -30,7 +30,7 @@ static inline void regs_to_env(void) int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw, int mmu_idx, int is_softmmu); -void do_interrupt(int intno); +void do_interrupt(CPUState *env); static inline int cpu_halted(CPUState *env1) { if (!env1->halted) diff --git a/target-sparc/helper.c b/target-sparc/helper.c index 1bc2fededa..8bf40e4aea 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -32,6 +32,7 @@ //#define DEBUG_MMU //#define DEBUG_FEATURES +//#define DEBUG_PCALL typedef struct sparc_def_t sparc_def_t; @@ -651,6 +652,220 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) } #endif +#ifdef TARGET_SPARC64 +#ifdef DEBUG_PCALL +static const char * const excp_names[0x50] = { + [TT_TFAULT] = "Instruction Access Fault", + [TT_TMISS] = "Instruction Access MMU Miss", + [TT_CODE_ACCESS] = "Instruction Access Error", + [TT_ILL_INSN] = "Illegal Instruction", + [TT_PRIV_INSN] = "Privileged Instruction", + [TT_NFPU_INSN] = "FPU Disabled", + [TT_FP_EXCP] = "FPU Exception", + [TT_TOVF] = "Tag Overflow", + [TT_CLRWIN] = "Clean Windows", + [TT_DIV_ZERO] = "Division By Zero", + [TT_DFAULT] = "Data Access Fault", + [TT_DMISS] = "Data Access MMU Miss", + [TT_DATA_ACCESS] = "Data Access Error", + [TT_DPROT] = "Data Protection Error", + [TT_UNALIGNED] = "Unaligned Memory Access", + [TT_PRIV_ACT] = "Privileged Action", + [TT_EXTINT | 0x1] = "External Interrupt 1", + [TT_EXTINT | 0x2] = "External Interrupt 2", + [TT_EXTINT | 0x3] = "External Interrupt 3", + [TT_EXTINT | 0x4] = "External Interrupt 4", + [TT_EXTINT | 0x5] = "External Interrupt 5", + [TT_EXTINT | 0x6] = "External Interrupt 6", + [TT_EXTINT | 0x7] = "External Interrupt 7", + [TT_EXTINT | 0x8] = "External Interrupt 8", + [TT_EXTINT | 0x9] = "External Interrupt 9", + [TT_EXTINT | 0xa] = "External Interrupt 10", + [TT_EXTINT | 0xb] = "External Interrupt 11", + [TT_EXTINT | 0xc] = "External Interrupt 12", + [TT_EXTINT | 0xd] = "External Interrupt 13", + [TT_EXTINT | 0xe] = "External Interrupt 14", + [TT_EXTINT | 0xf] = "External Interrupt 15", +}; +#endif + +void do_interrupt(CPUState *env) +{ + int intno = env->exception_index; + +#ifdef DEBUG_PCALL + if (loglevel & CPU_LOG_INT) { + static int count; + const char *name; + + if (intno < 0 || intno >= 0x180 || (intno > 0x4f && intno < 0x80)) + name = "Unknown"; + else if (intno >= 0x100) + name = "Trap Instruction"; + else if (intno >= 0xc0) + name = "Window Fill"; + else if (intno >= 0x80) + name = "Window Spill"; + else { + name = excp_names[intno]; + if (!name) + name = "Unknown"; + } + + fprintf(logfile, "%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64 + " SP=%016" PRIx64 "\n", + count, name, intno, + env->pc, + env->npc, env->regwptr[6]); + cpu_dump_state(env, logfile, fprintf, 0); +#if 0 + { + int i; + uint8_t *ptr; + + fprintf(logfile, " code="); + ptr = (uint8_t *)env->pc; + for(i = 0; i < 16; i++) { + fprintf(logfile, " %02x", ldub(ptr + i)); + } + fprintf(logfile, "\n"); + } +#endif + count++; + } +#endif +#if !defined(CONFIG_USER_ONLY) + if (env->tl == MAXTL) { + cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", + env->exception_index); + return; + } +#endif + env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) | + ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) | + GET_CWP64(env); + env->tsptr->tpc = env->pc; + env->tsptr->tnpc = env->npc; + env->tsptr->tt = intno; + change_pstate(PS_PEF | PS_PRIV | PS_AG); + + if (intno == TT_CLRWIN) + cpu_set_cwp(env, (env->cwp - 1) & (NWINDOWS - 1)); + else if ((intno & 0x1c0) == TT_SPILL) + cpu_set_cwp(env, (env->cwp - env->cansave - 2) & (NWINDOWS - 1)); + else if ((intno & 0x1c0) == TT_FILL) + cpu_set_cwp(env, (env->cwp + 1) & (NWINDOWS - 1)); + env->tbr &= ~0x7fffULL; + env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5); + if (env->tl < MAXTL - 1) { + env->tl++; + } else { + env->pstate |= PS_RED; + if (env->tl != MAXTL) + env->tl++; + } + env->tsptr = &env->ts[env->tl]; + env->pc = env->tbr; + env->npc = env->pc + 4; + env->exception_index = 0; +} +#else +#ifdef DEBUG_PCALL +static const char * const excp_names[0x80] = { + [TT_TFAULT] = "Instruction Access Fault", + [TT_ILL_INSN] = "Illegal Instruction", + [TT_PRIV_INSN] = "Privileged Instruction", + [TT_NFPU_INSN] = "FPU Disabled", + [TT_WIN_OVF] = "Window Overflow", + [TT_WIN_UNF] = "Window Underflow", + [TT_UNALIGNED] = "Unaligned Memory Access", + [TT_FP_EXCP] = "FPU Exception", + [TT_DFAULT] = "Data Access Fault", + [TT_TOVF] = "Tag Overflow", + [TT_EXTINT | 0x1] = "External Interrupt 1", + [TT_EXTINT | 0x2] = "External Interrupt 2", + [TT_EXTINT | 0x3] = "External Interrupt 3", + [TT_EXTINT | 0x4] = "External Interrupt 4", + [TT_EXTINT | 0x5] = "External Interrupt 5", + [TT_EXTINT | 0x6] = "External Interrupt 6", + [TT_EXTINT | 0x7] = "External Interrupt 7", + [TT_EXTINT | 0x8] = "External Interrupt 8", + [TT_EXTINT | 0x9] = "External Interrupt 9", + [TT_EXTINT | 0xa] = "External Interrupt 10", + [TT_EXTINT | 0xb] = "External Interrupt 11", + [TT_EXTINT | 0xc] = "External Interrupt 12", + [TT_EXTINT | 0xd] = "External Interrupt 13", + [TT_EXTINT | 0xe] = "External Interrupt 14", + [TT_EXTINT | 0xf] = "External Interrupt 15", + [TT_TOVF] = "Tag Overflow", + [TT_CODE_ACCESS] = "Instruction Access Error", + [TT_DATA_ACCESS] = "Data Access Error", + [TT_DIV_ZERO] = "Division By Zero", + [TT_NCP_INSN] = "Coprocessor Disabled", +}; +#endif + +void do_interrupt(CPUState *env) +{ + int cwp, intno = env->exception_index; + +#ifdef DEBUG_PCALL + if (loglevel & CPU_LOG_INT) { + static int count; + const char *name; + + if (intno < 0 || intno >= 0x100) + name = "Unknown"; + else if (intno >= 0x80) + name = "Trap Instruction"; + else { + name = excp_names[intno]; + if (!name) + name = "Unknown"; + } + + fprintf(logfile, "%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n", + count, name, intno, + env->pc, + env->npc, env->regwptr[6]); + cpu_dump_state(env, logfile, fprintf, 0); +#if 0 + { + int i; + uint8_t *ptr; + + fprintf(logfile, " code="); + ptr = (uint8_t *)env->pc; + for(i = 0; i < 16; i++) { + fprintf(logfile, " %02x", ldub(ptr + i)); + } + fprintf(logfile, "\n"); + } +#endif + count++; + } +#endif +#if !defined(CONFIG_USER_ONLY) + if (env->psret == 0) { + cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", + env->exception_index); + return; + } +#endif + env->psret = 0; + cwp = (env->cwp - 1) & (NWINDOWS - 1); + cpu_set_cwp(env, cwp); + 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); + env->pc = env->tbr; + env->npc = env->pc + 4; + env->exception_index = 0; +} +#endif + void memcpy32(target_ulong *dst, const target_ulong *src) { dst[0] = src[0]; @@ -663,12 +878,6 @@ void memcpy32(target_ulong *dst, const target_ulong *src) dst[7] = src[7]; } -void helper_flush(target_ulong addr) -{ - addr &= ~7; - tb_invalidate_page_range(addr, addr + 8); -} - void cpu_reset(CPUSPARCState *env) { tlb_flush(env, 1); diff --git a/target-sparc/helper.h b/target-sparc/helper.h index c64ffe8513..b490c77f0d 100644 --- a/target-sparc/helper.h +++ b/target-sparc/helper.h @@ -183,6 +183,7 @@ void cpu_lock(void); void cpu_unlock(void); void cpu_loop_exit(void); void set_cwp(int new_cwp); +void change_pstate(uint64_t new_pstate); void memcpy32(target_ulong *dst, const target_ulong *src); target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev); void dump_mmu(CPUState *env); diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index 250f719623..2aae95507b 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -5,7 +5,6 @@ #include "softmmu_exec.h" #endif /* !defined(CONFIG_USER_ONLY) */ -//#define DEBUG_PCALL //#define DEBUG_MMU //#define DEBUG_MXCC //#define DEBUG_UNALIGNED @@ -2573,7 +2572,7 @@ static inline uint64_t *get_gregset(uint64_t pstate) } } -static inline void change_pstate(uint64_t new_pstate) +void change_pstate(uint64_t new_pstate) { uint64_t pstate_regs, new_pstate_regs; uint64_t *src, *dst; @@ -2620,249 +2619,29 @@ void helper_retry(void) } #endif -void set_cwp(int new_cwp) +void cpu_set_cwp(CPUState *env1, int new_cwp) { /* put the modified wrap registers at their proper location */ - if (env->cwp == (NWINDOWS - 1)) - memcpy32(env->regbase, env->regbase + NWINDOWS * 16); - env->cwp = new_cwp; + if (env1->cwp == (NWINDOWS - 1)) + memcpy32(env1->regbase, env1->regbase + NWINDOWS * 16); + env1->cwp = new_cwp; /* put the wrap registers at their temporary location */ if (new_cwp == (NWINDOWS - 1)) - memcpy32(env->regbase + NWINDOWS * 16, env->regbase); - env->regwptr = env->regbase + (new_cwp * 16); - REGWPTR = env->regwptr; + memcpy32(env1->regbase + NWINDOWS * 16, env1->regbase); + env1->regwptr = env1->regbase + (new_cwp * 16); + REGWPTR = env1->regwptr; } -void cpu_set_cwp(CPUState *env1, int new_cwp) +void set_cwp(int new_cwp) { - CPUState *saved_env; -#ifdef reg_REGWPTR - target_ulong *saved_regwptr; -#endif - - saved_env = env; -#ifdef reg_REGWPTR - saved_regwptr = REGWPTR; -#endif - env = env1; - set_cwp(new_cwp); - env = saved_env; -#ifdef reg_REGWPTR - REGWPTR = saved_regwptr; -#endif -} - -#ifdef TARGET_SPARC64 -#ifdef DEBUG_PCALL -static const char * const excp_names[0x50] = { - [TT_TFAULT] = "Instruction Access Fault", - [TT_TMISS] = "Instruction Access MMU Miss", - [TT_CODE_ACCESS] = "Instruction Access Error", - [TT_ILL_INSN] = "Illegal Instruction", - [TT_PRIV_INSN] = "Privileged Instruction", - [TT_NFPU_INSN] = "FPU Disabled", - [TT_FP_EXCP] = "FPU Exception", - [TT_TOVF] = "Tag Overflow", - [TT_CLRWIN] = "Clean Windows", - [TT_DIV_ZERO] = "Division By Zero", - [TT_DFAULT] = "Data Access Fault", - [TT_DMISS] = "Data Access MMU Miss", - [TT_DATA_ACCESS] = "Data Access Error", - [TT_DPROT] = "Data Protection Error", - [TT_UNALIGNED] = "Unaligned Memory Access", - [TT_PRIV_ACT] = "Privileged Action", - [TT_EXTINT | 0x1] = "External Interrupt 1", - [TT_EXTINT | 0x2] = "External Interrupt 2", - [TT_EXTINT | 0x3] = "External Interrupt 3", - [TT_EXTINT | 0x4] = "External Interrupt 4", - [TT_EXTINT | 0x5] = "External Interrupt 5", - [TT_EXTINT | 0x6] = "External Interrupt 6", - [TT_EXTINT | 0x7] = "External Interrupt 7", - [TT_EXTINT | 0x8] = "External Interrupt 8", - [TT_EXTINT | 0x9] = "External Interrupt 9", - [TT_EXTINT | 0xa] = "External Interrupt 10", - [TT_EXTINT | 0xb] = "External Interrupt 11", - [TT_EXTINT | 0xc] = "External Interrupt 12", - [TT_EXTINT | 0xd] = "External Interrupt 13", - [TT_EXTINT | 0xe] = "External Interrupt 14", - [TT_EXTINT | 0xf] = "External Interrupt 15", -}; -#endif - -void do_interrupt(int intno) -{ -#ifdef DEBUG_PCALL - if (loglevel & CPU_LOG_INT) { - static int count; - const char *name; - - if (intno < 0 || intno >= 0x180 || (intno > 0x4f && intno < 0x80)) - name = "Unknown"; - else if (intno >= 0x100) - name = "Trap Instruction"; - else if (intno >= 0xc0) - name = "Window Fill"; - else if (intno >= 0x80) - name = "Window Spill"; - else { - name = excp_names[intno]; - if (!name) - name = "Unknown"; - } - - fprintf(logfile, "%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64 - " SP=%016" PRIx64 "\n", - count, name, intno, - env->pc, - env->npc, env->regwptr[6]); - cpu_dump_state(env, logfile, fprintf, 0); -#if 0 - { - int i; - uint8_t *ptr; - - fprintf(logfile, " code="); - ptr = (uint8_t *)env->pc; - for(i = 0; i < 16; i++) { - fprintf(logfile, " %02x", ldub(ptr + i)); - } - fprintf(logfile, "\n"); - } -#endif - count++; - } -#endif -#if !defined(CONFIG_USER_ONLY) - if (env->tl == MAXTL) { - cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", - env->exception_index); - return; - } -#endif - env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) | - ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) | - GET_CWP64(env); - env->tsptr->tpc = env->pc; - env->tsptr->tnpc = env->npc; - env->tsptr->tt = intno; - change_pstate(PS_PEF | PS_PRIV | PS_AG); - - if (intno == TT_CLRWIN) - set_cwp((env->cwp - 1) & (NWINDOWS - 1)); - else if ((intno & 0x1c0) == TT_SPILL) - set_cwp((env->cwp - env->cansave - 2) & (NWINDOWS - 1)); - else if ((intno & 0x1c0) == TT_FILL) - set_cwp((env->cwp + 1) & (NWINDOWS - 1)); - env->tbr &= ~0x7fffULL; - env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5); - if (env->tl < MAXTL - 1) { - env->tl++; - } else { - env->pstate |= PS_RED; - if (env->tl != MAXTL) - env->tl++; - } - env->tsptr = &env->ts[env->tl]; - env->pc = env->tbr; - env->npc = env->pc + 4; - env->exception_index = 0; + cpu_set_cwp(env, new_cwp); } -#else -#ifdef DEBUG_PCALL -static const char * const excp_names[0x80] = { - [TT_TFAULT] = "Instruction Access Fault", - [TT_ILL_INSN] = "Illegal Instruction", - [TT_PRIV_INSN] = "Privileged Instruction", - [TT_NFPU_INSN] = "FPU Disabled", - [TT_WIN_OVF] = "Window Overflow", - [TT_WIN_UNF] = "Window Underflow", - [TT_UNALIGNED] = "Unaligned Memory Access", - [TT_FP_EXCP] = "FPU Exception", - [TT_DFAULT] = "Data Access Fault", - [TT_TOVF] = "Tag Overflow", - [TT_EXTINT | 0x1] = "External Interrupt 1", - [TT_EXTINT | 0x2] = "External Interrupt 2", - [TT_EXTINT | 0x3] = "External Interrupt 3", - [TT_EXTINT | 0x4] = "External Interrupt 4", - [TT_EXTINT | 0x5] = "External Interrupt 5", - [TT_EXTINT | 0x6] = "External Interrupt 6", - [TT_EXTINT | 0x7] = "External Interrupt 7", - [TT_EXTINT | 0x8] = "External Interrupt 8", - [TT_EXTINT | 0x9] = "External Interrupt 9", - [TT_EXTINT | 0xa] = "External Interrupt 10", - [TT_EXTINT | 0xb] = "External Interrupt 11", - [TT_EXTINT | 0xc] = "External Interrupt 12", - [TT_EXTINT | 0xd] = "External Interrupt 13", - [TT_EXTINT | 0xe] = "External Interrupt 14", - [TT_EXTINT | 0xf] = "External Interrupt 15", - [TT_TOVF] = "Tag Overflow", - [TT_CODE_ACCESS] = "Instruction Access Error", - [TT_DATA_ACCESS] = "Data Access Error", - [TT_DIV_ZERO] = "Division By Zero", - [TT_NCP_INSN] = "Coprocessor Disabled", -}; -#endif -void do_interrupt(int intno) +void helper_flush(target_ulong addr) { - int cwp; - -#ifdef DEBUG_PCALL - if (loglevel & CPU_LOG_INT) { - static int count; - const char *name; - - if (intno < 0 || intno >= 0x100) - name = "Unknown"; - else if (intno >= 0x80) - name = "Trap Instruction"; - else { - name = excp_names[intno]; - if (!name) - name = "Unknown"; - } - - fprintf(logfile, "%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n", - count, name, intno, - env->pc, - env->npc, env->regwptr[6]); - cpu_dump_state(env, logfile, fprintf, 0); -#if 0 - { - int i; - uint8_t *ptr; - - fprintf(logfile, " code="); - ptr = (uint8_t *)env->pc; - for(i = 0; i < 16; i++) { - fprintf(logfile, " %02x", ldub(ptr + i)); - } - fprintf(logfile, "\n"); - } -#endif - count++; - } -#endif -#if !defined(CONFIG_USER_ONLY) - if (env->psret == 0) { - cpu_abort(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); - 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); - env->pc = env->tbr; - env->npc = env->pc + 4; - env->exception_index = 0; + addr &= ~7; + tb_invalidate_page_range(addr, addr + 8); } -#endif #if !defined(CONFIG_USER_ONLY) |