int user_mode_only; /* user mode only simulation */
uint32_t hflags; /* CPU State */
/* TMASK defines different execution modes */
-#define MIPS_HFLAG_TMASK 0x007F
+#define MIPS_HFLAG_TMASK 0x00FF
#define MIPS_HFLAG_MODE 0x0007 /* execution modes */
#define MIPS_HFLAG_UM 0x0001 /* user mode */
#define MIPS_HFLAG_DM 0x0002 /* Debug mode */
#define MIPS_HFLAG_SM 0x0004 /* Supervisor mode */
#define MIPS_HFLAG_64 0x0008 /* 64-bit instructions enabled */
-#define MIPS_HFLAG_FPU 0x0010 /* FPU enabled */
-#define MIPS_HFLAG_F64 0x0020 /* 64-bit FPU enabled */
-#define MIPS_HFLAG_RE 0x0040 /* Reversed endianness */
+#define MIPS_HFLAG_CP0 0x0010 /* CP0 enabled */
+#define MIPS_HFLAG_FPU 0x0020 /* FPU enabled */
+#define MIPS_HFLAG_F64 0x0040 /* 64-bit FPU enabled */
+#define MIPS_HFLAG_RE 0x0080 /* Reversed endianness */
/* If translation is interrupted between the branch instruction and
* the delay slot, record what type of branch it is so that we can
* resume translation properly. It might be possible to reduce
* this from three bits to two. */
-#define MIPS_HFLAG_BMASK 0x0380
-#define MIPS_HFLAG_B 0x0080 /* Unconditional branch */
-#define MIPS_HFLAG_BC 0x0100 /* Conditional branch */
-#define MIPS_HFLAG_BL 0x0180 /* Likely branch */
-#define MIPS_HFLAG_BR 0x0200 /* branch to register (can't link TB) */
+#define MIPS_HFLAG_BMASK 0x0700
+#define MIPS_HFLAG_B 0x0100 /* Unconditional branch */
+#define MIPS_HFLAG_BC 0x0200 /* Conditional branch */
+#define MIPS_HFLAG_BL 0x0300 /* Likely branch */
+#define MIPS_HFLAG_BR 0x0400 /* branch to register (can't link TB) */
target_ulong btarget; /* Jump / branch target */
int bcond; /* Branch condition (if needed) */
env->hflags |= MIPS_HFLAG_DM;
env->hflags |= MIPS_HFLAG_64;
env->hflags &= ~MIPS_HFLAG_UM;
+ env->hflags |= MIPS_HFLAG_CP0;
/* EJTAG probe trap enable is not implemented... */
if (!(env->CP0_Status & (1 << CP0St_EXL)))
env->CP0_Cause &= ~(1 << CP0Ca_BD);
env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
env->hflags |= MIPS_HFLAG_64;
env->hflags &= ~MIPS_HFLAG_UM;
+ env->hflags |= MIPS_HFLAG_CP0;
if (!(env->CP0_Status & (1 << CP0St_EXL)))
env->CP0_Cause &= ~(1 << CP0Ca_BD);
env->PC[env->current_tc] = (int32_t)0xBFC00000;
env->CP0_Status |= (1 << CP0St_EXL);
env->hflags |= MIPS_HFLAG_64;
env->hflags &= ~MIPS_HFLAG_UM;
+ env->hflags |= MIPS_HFLAG_CP0;
}
env->hflags &= ~MIPS_HFLAG_BMASK;
if (env->CP0_Status & (1 << CP0St_BEV)) {
!(val & (1 << CP0St_UX)))
env->hflags &= ~MIPS_HFLAG_64;
#endif
+ if ((val & (1 << CP0St_CU0)) || !(env->hflags & MIPS_HFLAG_UM))
+ env->hflags |= MIPS_HFLAG_CP0;
+ else
+ env->hflags &= ~MIPS_HFLAG_CP0;
if (val & (1 << CP0St_CU1))
env->hflags |= MIPS_HFLAG_FPU;
else
# define DEBUG_FPU_STATE() do { } while(0)
#endif
-void op_cp0_enabled(void)
-{
- if (!(env->CP0_Status & (1 << CP0St_CU0)) &&
- (env->hflags & MIPS_HFLAG_UM)) {
- CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 0);
- }
- RETURN();
-}
-
void op_cfc1 (void)
{
CALL_FROM_TB1(do_cfc1, PARAM1);
!(env->CP0_Status & (1 << CP0St_UX)))
env->hflags &= ~MIPS_HFLAG_64;
#endif
+ if ((env->CP0_Status & (1 << CP0St_CU0)) || !(env->hflags & MIPS_HFLAG_UM))
+ env->hflags |= MIPS_HFLAG_CP0;
+ else
+ env->hflags &= ~MIPS_HFLAG_CP0;
if (loglevel & CPU_LOG_EXEC)
CALL_FROM_TB0(debug_post_eret);
env->CP0_LLAddr = 1;
!(env->CP0_Status & (1 << CP0St_UX)))
env->hflags &= ~MIPS_HFLAG_64;
#endif
+ if ((env->CP0_Status & (1 << CP0St_CU0)) || !(env->hflags & MIPS_HFLAG_UM))
+ env->hflags |= MIPS_HFLAG_CP0;
+ else
+ env->hflags &= ~MIPS_HFLAG_CP0;
if (loglevel & CPU_LOG_EXEC)
CALL_FROM_TB0(debug_post_eret);
env->CP0_LLAddr = 1;
void op_rdhwr_cpunum(void)
{
- if (!(env->hflags & MIPS_HFLAG_UM) ||
- (env->CP0_HWREna & (1 << 0)) ||
- (env->CP0_Status & (1 << CP0St_CU0)))
+ if ((env->hflags & MIPS_HFLAG_CP0) ||
+ (env->CP0_HWREna & (1 << 0)))
T0 = env->CP0_EBase & 0x3ff;
else
CALL_FROM_TB1(do_raise_exception, EXCP_RI);
void op_rdhwr_synci_step(void)
{
- if (!(env->hflags & MIPS_HFLAG_UM) ||
- (env->CP0_HWREna & (1 << 1)) ||
- (env->CP0_Status & (1 << CP0St_CU0)))
+ if ((env->hflags & MIPS_HFLAG_CP0) ||
+ (env->CP0_HWREna & (1 << 1)))
T0 = env->SYNCI_Step;
else
CALL_FROM_TB1(do_raise_exception, EXCP_RI);
void op_rdhwr_cc(void)
{
- if (!(env->hflags & MIPS_HFLAG_UM) ||
- (env->CP0_HWREna & (1 << 2)) ||
- (env->CP0_Status & (1 << CP0St_CU0)))
+ if ((env->hflags & MIPS_HFLAG_CP0) ||
+ (env->CP0_HWREna & (1 << 2)))
T0 = env->CP0_Count;
else
CALL_FROM_TB1(do_raise_exception, EXCP_RI);
void op_rdhwr_ccres(void)
{
- if (!(env->hflags & MIPS_HFLAG_UM) ||
- (env->CP0_HWREna & (1 << 3)) ||
- (env->CP0_Status & (1 << CP0St_CU0)))
+ if ((env->hflags & MIPS_HFLAG_CP0) ||
+ (env->CP0_HWREna & (1 << 3)))
T0 = env->CCRes;
else
CALL_FROM_TB1(do_raise_exception, EXCP_RI);
generate_exception_err (ctx, excp, 0);
}
+static inline void check_cp0_enabled(DisasContext *ctx)
+{
+ if (!(ctx->hflags & MIPS_HFLAG_CP0))
+ generate_exception_err(ctx, EXCP_CpU, 1);
+}
+
static inline void check_cp1_enabled(DisasContext *ctx)
{
if (!(ctx->hflags & MIPS_HFLAG_FPU))
break;
case OPC_MTC0:
GEN_LOAD_REG_TN(T0, rt);
+ save_cpu_state(ctx, 1);
gen_mtc0(env, ctx, rd, ctx->opcode & 0x7);
opn = "mtc0";
break;
case OPC_DMTC0:
check_insn(env, ctx, ISA_MIPS3);
GEN_LOAD_REG_TN(T0, rt);
+ save_cpu_state(ctx, 1);
gen_dmtc0(env, ctx, rd, ctx->opcode & 0x7);
opn = "dmtc0";
break;
case OPC_ERET:
opn = "eret";
check_insn(env, ctx, ISA_MIPS2);
+ save_cpu_state(ctx, 1);
gen_op_eret();
ctx->bstate = BS_EXCP;
break;
MIPS_INVAL(opn);
generate_exception(ctx, EXCP_RI);
} else {
+ save_cpu_state(ctx, 1);
gen_op_deret();
ctx->bstate = BS_EXCP;
}
}
break;
case OPC_CP0:
- save_cpu_state(ctx, 1);
- gen_op_cp0_enabled();
+ check_cp0_enabled(ctx);
op1 = MASK_CP0(ctx->opcode);
switch (op1) {
case OPC_MFC0:
break;
case OPC_DI:
check_insn(env, ctx, ISA_MIPS32R2);
+ save_cpu_state(ctx, 1);
gen_op_di();
/* Stop translation as we may have switched the execution mode */
ctx->bstate = BS_STOP;
break;
case OPC_EI:
check_insn(env, ctx, ISA_MIPS32R2);
+ save_cpu_state(ctx, 1);
gen_op_ei();
/* Stop translation as we may have switched the execution mode */
ctx->bstate = BS_STOP;
} else {
env->CP0_ErrorEPC = env->PC[env->current_tc];
}
- env->hflags = 0;
env->PC[env->current_tc] = (int32_t)0xBFC00000;
env->CP0_Wired = 0;
/* SMP not implemented */
#endif
env->exception_index = EXCP_NONE;
#if defined(CONFIG_USER_ONLY)
- env->hflags |= MIPS_HFLAG_UM;
+ env->hflags = MIPS_HFLAG_UM;
env->user_mode_only = 1;
+#else
+ env->hflags = MIPS_HFLAG_CP0;
#endif
}