diff options
author | Igor Kovalenko <igor.v.kovalenko@gmail.com> | 2009-07-12 12:35:31 +0400 |
---|---|---|
committer | Blue Swirl <blauwirbel@gmail.com> | 2009-07-12 08:46:54 +0000 |
commit | 5210977a8511fc0c4a8a1a68c01fa3b65e29edc0 (patch) | |
tree | dd12f3bcc62297f325c30718c6d42764dff0afd6 /target-sparc | |
parent | 49e6637386acb8824114ed10308ed7869472ec0f (diff) |
sparc64: trap handling corrections
On Sun, Jul 12, 2009 at 12:09 PM, Blue Swirl<blauwirbel@gmail.com> wrote:
> On 7/12/09, Igor Kovalenko <igor.v.kovalenko@gmail.com> wrote:
>> Good trap handling is required to process interrupts.
>> This patch fixes the following:
>>
>> - sparc64 has no wim register
>> - sparc64 has no psret register, use IE bit of pstate
>> extract IE checking code to cpu_interrupts_enabled
>> - alternate globals are not available if cpu has GL feature
>> in this case bit AG of pstate is constant zero
>> - write to pstate must actually write pstate
>> even if cpu has GL feature
>>
>> Also timer interrupt is handled using do_interrupt.
>
> A bit too much for one patch. Please also remove the code instead of
> commenting out.
I now excluded timer interrupt related part.
To my mind other changes are essentially tied together.
> PUT_PSR for Sparc64 needs CC_OP = CC_OP_FLAGS; like Sparc32.
Fixed, please find attached the updated version.
--
Kind regards,
Igor V. Kovalenko
Diffstat (limited to 'target-sparc')
-rw-r--r-- | target-sparc/cpu.h | 40 | ||||
-rw-r--r-- | target-sparc/exec.h | 15 | ||||
-rw-r--r-- | target-sparc/helper.c | 4 | ||||
-rw-r--r-- | target-sparc/op_helper.c | 41 |
4 files changed, 75 insertions, 25 deletions
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index d592bea360..76e1e796ba 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -115,15 +115,18 @@ enum { #define TBR_BASE_MASK 0xfffff000 #if defined(TARGET_SPARC64) -#define PS_IG (1<<11) -#define PS_MG (1<<10) +#define PS_TCT (1<<12) /* UA2007, impl.dep. trap on control transfer */ +#define PS_IG (1<<11) /* v9, zero on UA2007 */ +#define PS_MG (1<<10) /* v9, zero on UA2007 */ +#define PS_CLE (1<<9) /* UA2007 */ +#define PS_TLE (1<<8) /* UA2007 */ #define PS_RMO (1<<7) -#define PS_RED (1<<5) -#define PS_PEF (1<<4) -#define PS_AM (1<<3) +#define PS_RED (1<<5) /* v9, zero on UA2007 */ +#define PS_PEF (1<<4) /* enable fpu */ +#define PS_AM (1<<3) /* address mask */ #define PS_PRIV (1<<2) #define PS_IE (1<<1) -#define PS_AG (1<<0) +#define PS_AG (1<<0) /* v9, zero on UA2007 */ #define FPRS_FEF (1<<2) @@ -291,11 +294,15 @@ typedef struct CPUSPARCState { float32 fpr[TARGET_FPREGS]; /* floating point registers */ uint32_t cwp; /* index of current register window (extracted from PSR) */ +#if !defined(TARGET_SPARC64) || defined(TARGET_ABI32) uint32_t wim; /* window invalid mask */ +#endif target_ulong tbr; /* trap base register */ int psrs; /* supervisor mode (extracted from PSR) */ int psrps; /* previous supervisor mode */ +#if !defined(TARGET_SPARC64) int psret; /* enable traps */ +#endif uint32_t psrpil; /* interrupt blocking level */ uint32_t pil_in; /* incoming interrupt level bitmap */ int psref; /* enable fpu */ @@ -378,12 +385,21 @@ void gen_intermediate_code_init(CPUSPARCState *env); /* cpu-exec.c */ int cpu_sparc_exec(CPUSPARCState *s); +#if !defined (TARGET_SPARC64) #define GET_PSR(env) (env->version | (env->psr & PSR_ICC) | \ (env->psref? PSR_EF : 0) | \ (env->psrpil << 8) | \ (env->psrs? PSR_S : 0) | \ (env->psrps? PSR_PS : 0) | \ (env->psret? PSR_ET : 0) | env->cwp) +#else +#define GET_PSR(env) (env->version | (env->psr & PSR_ICC) | \ + (env->psref? PSR_EF : 0) | \ + (env->psrpil << 8) | \ + (env->psrs? PSR_S : 0) | \ + (env->psrps? PSR_PS : 0) | \ + env->cwp) +#endif #ifndef NO_CPU_IO_DEFS static inline void memcpy32(target_ulong *dst, const target_ulong *src) @@ -425,6 +441,7 @@ static inline int cpu_cwp_dec(CPUSPARCState *env1, int cwp) } #endif +#if !defined (TARGET_SPARC64) #define PUT_PSR(env, val) do { int _tmp = val; \ env->psr = _tmp & PSR_ICC; \ env->psref = (_tmp & PSR_EF)? 1 : 0; \ @@ -435,6 +452,17 @@ static inline int cpu_cwp_dec(CPUSPARCState *env1, int cwp) cpu_set_cwp(env, _tmp & PSR_CWP); \ CC_OP = CC_OP_FLAGS; \ } while (0) +#else +#define PUT_PSR(env, val) do { int _tmp = val; \ + env->psr = _tmp & PSR_ICC; \ + env->psref = (_tmp & PSR_EF)? 1 : 0; \ + env->psrpil = (_tmp & PSR_PIL) >> 8; \ + env->psrs = (_tmp & PSR_S)? 1 : 0; \ + env->psrps = (_tmp & PSR_PS)? 1 : 0; \ + cpu_set_cwp(env, _tmp & PSR_CWP); \ + CC_OP = CC_OP_FLAGS; \ + } while (0) +#endif #ifdef TARGET_SPARC64 #define GET_CCR(env) (((env->xcc >> 20) << 4) | ((env->psr & PSR_ICC) >> 20)) diff --git a/target-sparc/exec.h b/target-sparc/exec.h index f37c8ad994..e120d6fed4 100644 --- a/target-sparc/exec.h +++ b/target-sparc/exec.h @@ -24,10 +24,23 @@ static inline void regs_to_env(void) /* op_helper.c */ void do_interrupt(CPUState *env); +static inline int cpu_interrupts_enabled(CPUState *env1) +{ +#if !defined (TARGET_SPARC64) + if (env1->psret != 0) + return 1; +#else + if (env1->pstate & PS_IE) + return 1; +#endif + + return 0; +} + static inline int cpu_has_work(CPUState *env1) { return (env1->interrupt_request & CPU_INTERRUPT_HARD) && - (env1->psret != 0); + cpu_interrupts_enabled(env1); } diff --git a/target-sparc/helper.c b/target-sparc/helper.c index d133294edd..5f9ad409ed 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -667,7 +667,9 @@ void cpu_reset(CPUSPARCState *env) tlb_flush(env, 1); env->cwp = 0; +#ifndef TARGET_SPARC64 env->wim = 1; +#endif env->regwptr = env->regbase + (env->cwp * 16); #if defined(CONFIG_USER_ONLY) #ifdef TARGET_SPARC64 @@ -677,7 +679,9 @@ void cpu_reset(CPUSPARCState *env) env->asi = 0x82; // Primary no-fault #endif #else +#if !defined(TARGET_SPARC64) env->psret = 0; +#endif env->psrs = 1; env->psrps = 1; CC_OP = CC_OP_FLAGS; diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index 2449fc717b..d25b642c06 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -3225,8 +3225,14 @@ static inline void change_pstate(uint64_t new_pstate) uint64_t pstate_regs, new_pstate_regs; uint64_t *src, *dst; + if (env->def->features & CPU_FEATURE_GL) { + // PS_AG is not implemented in this case + new_pstate &= ~PS_AG; + } + pstate_regs = env->pstate & 0xc01; new_pstate_regs = new_pstate & 0xc01; + if (new_pstate_regs != pstate_regs) { // Switch global register bank src = get_gregset(new_pstate_regs); @@ -3239,8 +3245,7 @@ static inline void change_pstate(uint64_t new_pstate) void helper_wrpstate(target_ulong new_state) { - if (!(env->def->features & CPU_FEATURE_GL)) - change_pstate(new_state & 0xf3f); + change_pstate(new_state & 0xf3f); } void helper_done(void) @@ -3392,23 +3397,23 @@ void do_interrupt(CPUState *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; - } + + 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) |