Skip to content

Commit

Permalink
target-mips: add microMIPS exception handler support
Browse files Browse the repository at this point in the history
Unlike MIPS16, microMIPS lets you choose the ISA mode for your exception
handlers.  The ISA mode is selectable via a user-writable CP0.Config3
flag.

Signed-off-by: Nathan Froyd <[email protected]>
Signed-off-by: Aurelien Jarno <[email protected]>
  • Loading branch information
Nathan Froyd authored and aurel32 committed Jun 9, 2010
1 parent 3c82410 commit bbfa8f7
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 6 deletions.
1 change: 1 addition & 0 deletions target-mips/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ struct CPUMIPSState {
#define CP0C2_SA 0
int32_t CP0_Config3;
#define CP0C3_M 31
#define CP0C3_ISA_ON_EXC 16
#define CP0C3_DSPP 10
#define CP0C3_LPA 7
#define CP0C3_VEIC 6
Expand Down
21 changes: 15 additions & 6 deletions target-mips/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,18 @@ static target_ulong exception_resume_pc (CPUState *env)

return bad_pc;
}

static void set_hflags_for_handler (CPUState *env)
{
/* Exception handlers are entered in 32-bit mode. */
env->hflags &= ~(MIPS_HFLAG_M16);
/* ...except that microMIPS lets you choose. */
if (env->insn_flags & ASE_MICROMIPS) {
env->hflags |= (!!(env->CP0_Config3
& (1 << CP0C3_ISA_ON_EXC))
<< MIPS_HFLAG_M16_SHIFT);
}
}
#endif

void do_interrupt (CPUState *env)
Expand Down Expand Up @@ -440,8 +452,7 @@ 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->hflags &= ~(MIPS_HFLAG_M16);
set_hflags_for_handler(env);
break;
case EXCP_RESET:
cpu_reset(env);
Expand All @@ -461,8 +472,7 @@ void do_interrupt (CPUState *env)
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->hflags &= ~(MIPS_HFLAG_M16);
set_hflags_for_handler(env);
break;
case EXCP_EXT_INTERRUPT:
cause = 0;
Expand Down Expand Up @@ -581,8 +591,7 @@ 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->hflags &= ~(MIPS_HFLAG_M16);
set_hflags_for_handler(env);
env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC);
break;
default:
Expand Down

0 comments on commit bbfa8f7

Please sign in to comment.