Message ID | 1259009409-2755-4-git-send-email-froydnj@codesourcery.com |
---|---|
State | New |
Headers | show |
On Mon, Nov 23, 2009 at 12:50:01PM -0800, Nathan Froyd wrote: > > Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> > --- > target-mips/helper.c | 47 ++++++++++++++++++++++++++--------------------- > target-mips/op_helper.c | 10 +++++++--- > 2 files changed, 33 insertions(+), 24 deletions(-) > > diff --git a/target-mips/helper.c b/target-mips/helper.c > index 4a37277..e54a31a 100644 > --- a/target-mips/helper.c > +++ b/target-mips/helper.c > @@ -339,6 +339,20 @@ static const char * const excp_names[EXCP_LAST + 1] = { > [EXCP_CACHE] = "cache error", > }; > > +static target_ulong exception_resume_pc (CPUState *env) > +{ > + target_ulong bad_pc; > + > + bad_pc = env->active_tc.PC | env->active_tc.ISAMode; > + if (env->hflags & MIPS_HFLAG_BMASK) { > + /* If the exception was raised from a delay slot, come back to > + the jump. */ > + bad_pc -= (env->hflags & MIPS_HFLAG_BDS16 ? 2 : 4); > + } > + > + return bad_pc; > +} This function is only used on softmmu target. This breaks compilation of linux-user targets, it should be protected with: #if !defined(CONFIG_USER_ONLY) #endif > void do_interrupt (CPUState *env) > { > #if !defined(CONFIG_USER_ONLY) > @@ -366,7 +380,7 @@ void do_interrupt (CPUState *env) > resume will always occur on the next instruction > (but we assume the pc has always been updated during > code translation). */ > - env->CP0_DEPC = env->active_tc.PC; > + env->CP0_DEPC = env->active_tc.PC | env->active_tc.ISAMode; > goto enter_debug_mode; > case EXCP_DINT: > env->CP0_Debug |= 1 << CP0DB_DINT; > @@ -383,14 +397,8 @@ void do_interrupt (CPUState *env) > case EXCP_DDBL: > env->CP0_Debug |= 1 << CP0DB_DDBL; > set_DEPC: > - if (env->hflags & MIPS_HFLAG_BMASK) { > - /* If the exception was raised from a delay slot, > - come back to the jump. */ > - env->CP0_DEPC = env->active_tc.PC - 4; > - env->hflags &= ~MIPS_HFLAG_BMASK; > - } else { > - env->CP0_DEPC = env->active_tc.PC; > - } > + env->CP0_DEPC = exception_resume_pc(env); > + env->hflags &= ~MIPS_HFLAG_BMASK; > enter_debug_mode: > env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0; > env->hflags &= ~(MIPS_HFLAG_KSU); > @@ -398,6 +406,8 @@ void do_interrupt (CPUState *env) > if (!(env->CP0_Status & (1 << CP0St_EXL))) > env->CP0_Cause &= ~(1 << CP0Ca_BD); > env->active_tc.PC = (int32_t)0xBFC00480; > + /* Exception handlers are entered in 32-bit mode. */ > + env->active_tc.ISAMode = 0; > break; > case EXCP_RESET: > cpu_reset(env); > @@ -409,20 +419,16 @@ void do_interrupt (CPUState *env) > case EXCP_NMI: > env->CP0_Status |= (1 << CP0St_NMI); > set_error_EPC: > - if (env->hflags & MIPS_HFLAG_BMASK) { > - /* If the exception was raised from a delay slot, > - come back to the jump. */ > - env->CP0_ErrorEPC = env->active_tc.PC - 4; > - env->hflags &= ~MIPS_HFLAG_BMASK; > - } else { > - env->CP0_ErrorEPC = env->active_tc.PC; > - } > + env->CP0_ErrorEPC = exception_resume_pc(env); > + env->hflags &= ~MIPS_HFLAG_BMASK; > env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); > env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0; > env->hflags &= ~(MIPS_HFLAG_KSU); > if (!(env->CP0_Status & (1 << CP0St_EXL))) > env->CP0_Cause &= ~(1 << CP0Ca_BD); > env->active_tc.PC = (int32_t)0xBFC00000; > + /* Exception handlers are entered in 32-bit mode. */ > + env->active_tc.ISAMode = 0; > break; > case EXCP_EXT_INTERRUPT: > cause = 0; > @@ -524,13 +530,10 @@ void do_interrupt (CPUState *env) > } > set_EPC: > if (!(env->CP0_Status & (1 << CP0St_EXL))) { > + env->CP0_EPC = exception_resume_pc(env); > if (env->hflags & MIPS_HFLAG_BMASK) { > - /* If the exception was raised from a delay slot, > - come back to the jump. */ > - env->CP0_EPC = env->active_tc.PC - 4; > env->CP0_Cause |= (1 << CP0Ca_BD); > } else { > - env->CP0_EPC = env->active_tc.PC; > env->CP0_Cause &= ~(1 << CP0Ca_BD); > } > env->CP0_Status |= (1 << CP0St_EXL); > @@ -544,6 +547,8 @@ void do_interrupt (CPUState *env) > env->active_tc.PC = (int32_t)(env->CP0_EBase & ~0x3ff); > } > env->active_tc.PC += offset; > + /* Exception handlers are entered in 32-bit mode. */ > + env->active_tc.ISAMode = 0; > env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC); > break; > default: > diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c > index 52d687d..d585d65 100644 > --- a/target-mips/op_helper.c > +++ b/target-mips/op_helper.c > @@ -1701,10 +1701,12 @@ void helper_eret (void) > { > debug_pre_eret(); > if (env->CP0_Status & (1 << CP0St_ERL)) { > - env->active_tc.PC = env->CP0_ErrorEPC; > + env->active_tc.PC = env->CP0_ErrorEPC & ~(target_ulong)1; > + env->active_tc.ISAMode = env->CP0_ErrorEPC & 1; > env->CP0_Status &= ~(1 << CP0St_ERL); > } else { > - env->active_tc.PC = env->CP0_EPC; > + env->active_tc.PC = env->CP0_EPC & ~(target_ulong)1; > + env->active_tc.ISAMode = env->CP0_EPC & 1; > env->CP0_Status &= ~(1 << CP0St_EXL); > } > compute_hflags(env); > @@ -1715,7 +1717,9 @@ void helper_eret (void) > void helper_deret (void) > { > debug_pre_eret(); > - env->active_tc.PC = env->CP0_DEPC; > + env->active_tc.PC = env->CP0_DEPC & ~(target_ulong)1; > + env->active_tc.ISAMode = env->CP0_DEPC & 1; > + > env->hflags &= MIPS_HFLAG_DM; > compute_hflags(env); > debug_post_eret(); > -- > 1.6.3.2 > > > >
diff --git a/target-mips/helper.c b/target-mips/helper.c index 4a37277..e54a31a 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -339,6 +339,20 @@ static const char * const excp_names[EXCP_LAST + 1] = { [EXCP_CACHE] = "cache error", }; +static target_ulong exception_resume_pc (CPUState *env) +{ + target_ulong bad_pc; + + bad_pc = env->active_tc.PC | env->active_tc.ISAMode; + if (env->hflags & MIPS_HFLAG_BMASK) { + /* If the exception was raised from a delay slot, come back to + the jump. */ + bad_pc -= (env->hflags & MIPS_HFLAG_BDS16 ? 2 : 4); + } + + return bad_pc; +} + void do_interrupt (CPUState *env) { #if !defined(CONFIG_USER_ONLY) @@ -366,7 +380,7 @@ void do_interrupt (CPUState *env) resume will always occur on the next instruction (but we assume the pc has always been updated during code translation). */ - env->CP0_DEPC = env->active_tc.PC; + env->CP0_DEPC = env->active_tc.PC | env->active_tc.ISAMode; goto enter_debug_mode; case EXCP_DINT: env->CP0_Debug |= 1 << CP0DB_DINT; @@ -383,14 +397,8 @@ void do_interrupt (CPUState *env) case EXCP_DDBL: env->CP0_Debug |= 1 << CP0DB_DDBL; set_DEPC: - if (env->hflags & MIPS_HFLAG_BMASK) { - /* If the exception was raised from a delay slot, - come back to the jump. */ - env->CP0_DEPC = env->active_tc.PC - 4; - env->hflags &= ~MIPS_HFLAG_BMASK; - } else { - env->CP0_DEPC = env->active_tc.PC; - } + env->CP0_DEPC = exception_resume_pc(env); + env->hflags &= ~MIPS_HFLAG_BMASK; enter_debug_mode: env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0; env->hflags &= ~(MIPS_HFLAG_KSU); @@ -398,6 +406,8 @@ void do_interrupt (CPUState *env) if (!(env->CP0_Status & (1 << CP0St_EXL))) env->CP0_Cause &= ~(1 << CP0Ca_BD); env->active_tc.PC = (int32_t)0xBFC00480; + /* Exception handlers are entered in 32-bit mode. */ + env->active_tc.ISAMode = 0; break; case EXCP_RESET: cpu_reset(env); @@ -409,20 +419,16 @@ void do_interrupt (CPUState *env) case EXCP_NMI: env->CP0_Status |= (1 << CP0St_NMI); set_error_EPC: - if (env->hflags & MIPS_HFLAG_BMASK) { - /* If the exception was raised from a delay slot, - come back to the jump. */ - env->CP0_ErrorEPC = env->active_tc.PC - 4; - env->hflags &= ~MIPS_HFLAG_BMASK; - } else { - env->CP0_ErrorEPC = env->active_tc.PC; - } + env->CP0_ErrorEPC = exception_resume_pc(env); + env->hflags &= ~MIPS_HFLAG_BMASK; env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0; env->hflags &= ~(MIPS_HFLAG_KSU); if (!(env->CP0_Status & (1 << CP0St_EXL))) env->CP0_Cause &= ~(1 << CP0Ca_BD); env->active_tc.PC = (int32_t)0xBFC00000; + /* Exception handlers are entered in 32-bit mode. */ + env->active_tc.ISAMode = 0; break; case EXCP_EXT_INTERRUPT: cause = 0; @@ -524,13 +530,10 @@ void do_interrupt (CPUState *env) } set_EPC: if (!(env->CP0_Status & (1 << CP0St_EXL))) { + env->CP0_EPC = exception_resume_pc(env); if (env->hflags & MIPS_HFLAG_BMASK) { - /* If the exception was raised from a delay slot, - come back to the jump. */ - env->CP0_EPC = env->active_tc.PC - 4; env->CP0_Cause |= (1 << CP0Ca_BD); } else { - env->CP0_EPC = env->active_tc.PC; env->CP0_Cause &= ~(1 << CP0Ca_BD); } env->CP0_Status |= (1 << CP0St_EXL); @@ -544,6 +547,8 @@ void do_interrupt (CPUState *env) env->active_tc.PC = (int32_t)(env->CP0_EBase & ~0x3ff); } env->active_tc.PC += offset; + /* Exception handlers are entered in 32-bit mode. */ + env->active_tc.ISAMode = 0; env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC); break; default: diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 52d687d..d585d65 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -1701,10 +1701,12 @@ void helper_eret (void) { debug_pre_eret(); if (env->CP0_Status & (1 << CP0St_ERL)) { - env->active_tc.PC = env->CP0_ErrorEPC; + env->active_tc.PC = env->CP0_ErrorEPC & ~(target_ulong)1; + env->active_tc.ISAMode = env->CP0_ErrorEPC & 1; env->CP0_Status &= ~(1 << CP0St_ERL); } else { - env->active_tc.PC = env->CP0_EPC; + env->active_tc.PC = env->CP0_EPC & ~(target_ulong)1; + env->active_tc.ISAMode = env->CP0_EPC & 1; env->CP0_Status &= ~(1 << CP0St_EXL); } compute_hflags(env); @@ -1715,7 +1717,9 @@ void helper_eret (void) void helper_deret (void) { debug_pre_eret(); - env->active_tc.PC = env->CP0_DEPC; + env->active_tc.PC = env->CP0_DEPC & ~(target_ulong)1; + env->active_tc.ISAMode = env->CP0_DEPC & 1; + env->hflags &= MIPS_HFLAG_DM; compute_hflags(env); debug_post_eret();
Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> --- target-mips/helper.c | 47 ++++++++++++++++++++++++++--------------------- target-mips/op_helper.c | 10 +++++++--- 2 files changed, 33 insertions(+), 24 deletions(-)