diff options
author | blueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-08-29 20:50:21 +0000 |
---|---|---|
committer | blueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-08-29 20:50:21 +0000 |
commit | 91736d378b9bc6a9d7e16556216c919ba21dc5ca (patch) | |
tree | a85752641060c96d1fc88e5b74aeaa090363d9c9 /target-sparc/op_helper.c | |
parent | a46256129e80d993d23ed9d95566c79bcfa65e2d (diff) | |
download | hqemu-91736d378b9bc6a9d7e16556216c919ba21dc5ca.zip hqemu-91736d378b9bc6a9d7e16556216c919ba21dc5ca.tar.gz |
Fix Sparc64 boot on i386 host:
- move do_interrupt() back to op_helper.c
- move non-helper prototypes from helper.h to exec.h
- move some prototypes from cpu.h to exec.h
- do not export either set_cwp() or cpu_set_cwp() from op_helper.c,
but instead provide inline functions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5109 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-sparc/op_helper.c')
-rw-r--r-- | target-sparc/op_helper.c | 249 |
1 files changed, 233 insertions, 16 deletions
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index 8c2551f..47cd998 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -68,6 +68,11 @@ void helper_trapcc(target_ulong nb_trap, target_ulong do_trap) } } +static inline void set_cwp(int new_cwp) +{ + cpu_set_cwp(env, new_cwp); +} + void helper_check_align(target_ulong addr, uint32_t align) { if (addr & align) { @@ -2668,7 +2673,7 @@ static inline uint64_t *get_gregset(uint64_t pstate) } } -void change_pstate(uint64_t new_pstate) +static inline void change_pstate(uint64_t new_pstate) { uint64_t pstate_regs, new_pstate_regs; uint64_t *src, *dst; @@ -2716,28 +2721,240 @@ void helper_retry(void) } #endif -void cpu_set_cwp(CPUState *env1, int new_cwp) +void helper_flush(target_ulong addr) { - /* put the modified wrap registers at their proper location */ - if (env1->cwp == env1->nwindows - 1) - memcpy32(env1->regbase, env1->regbase + env1->nwindows * 16); - env1->cwp = new_cwp; - /* put the wrap registers at their temporary location */ - if (new_cwp == env1->nwindows - 1) - memcpy32(env1->regbase + env1->nwindows * 16, env1->regbase); - env1->regwptr = env1->regbase + (new_cwp * 16); + addr &= ~7; + tb_invalidate_page_range(addr, addr + 8); } -void set_cwp(int new_cwp) -{ - cpu_set_cwp(env, new_cwp); +#ifdef TARGET_SPARC64 +#ifdef DEBUG_PCALL +static const char * const excp_names[0x80] = { + [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) + 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 >= env->maxtl) { + cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d)," + " Error state", env->exception_index, env->tl, env->maxtl); + return; + } +#endif + if (env->tl < env->maxtl - 1) { + env->tl++; + } else { + env->pstate |= PS_RED; + if (env->tl < env->maxtl) + env->tl++; + } + env->tsptr = &env->ts[env->tl & MAXTL_MASK]; + 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; + if (!(env->def->features & CPU_FEATURE_GL)) { + switch (intno) { + case TT_IVEC: + change_pstate(PS_PEF | PS_PRIV | PS_IG); + break; + case TT_TFAULT: + case TT_TMISS: + case TT_DFAULT: + case TT_DMISS: + case TT_DPROT: + change_pstate(PS_PEF | PS_PRIV | PS_MG); + break; + default: + change_pstate(PS_PEF | PS_PRIV | PS_AG); + break; + } + } + if (intno == TT_CLRWIN) + cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1)); + else if ((intno & 0x1c0) == TT_SPILL) + cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2)); + else if ((intno & 0x1c0) == TT_FILL) + cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1)); + env->tbr &= ~0x7fffULL; + env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5); + 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 helper_flush(target_ulong addr) +void do_interrupt(CPUState *env) { - addr &= ~7; - tb_invalidate_page_range(addr, addr + 8); + 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 = cpu_cwp_dec(env, env->cwp - 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 #if !defined(CONFIG_USER_ONLY) |