mirror of https://github.com/proxmox/mirror_qemu
Handle PX/UX status flags correctly, by Aurelien Jarno.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2892 c046a42c-6fe2-441c-8c8c-71466251a162master
parent
85aa199ad7
commit
6e473128b6
|
@ -260,6 +260,7 @@ struct CPUMIPSState {
|
||||||
#define MIPS_HFLAG_UM 0x0001 /* user mode */
|
#define MIPS_HFLAG_UM 0x0001 /* user mode */
|
||||||
#define MIPS_HFLAG_DM 0x0008 /* Debug mode */
|
#define MIPS_HFLAG_DM 0x0008 /* Debug mode */
|
||||||
#define MIPS_HFLAG_SM 0x0010 /* Supervisor mode */
|
#define MIPS_HFLAG_SM 0x0010 /* Supervisor mode */
|
||||||
|
#define MIPS_HFLAG_64 0x0020 /* 64-bit instructions enabled */
|
||||||
#define MIPS_HFLAG_RE 0x0040 /* Reversed endianness */
|
#define MIPS_HFLAG_RE 0x0040 /* Reversed endianness */
|
||||||
/* If translation is interrupted between the branch instruction and
|
/* If translation is interrupted between the branch instruction and
|
||||||
* the delay slot, record what type of branch it is so that we can
|
* the delay slot, record what type of branch it is so that we can
|
||||||
|
|
|
@ -370,6 +370,7 @@ void do_interrupt (CPUState *env)
|
||||||
}
|
}
|
||||||
enter_debug_mode:
|
enter_debug_mode:
|
||||||
env->hflags |= MIPS_HFLAG_DM;
|
env->hflags |= MIPS_HFLAG_DM;
|
||||||
|
env->hflags |= MIPS_HFLAG_64;
|
||||||
env->hflags &= ~MIPS_HFLAG_UM;
|
env->hflags &= ~MIPS_HFLAG_UM;
|
||||||
/* EJTAG probe trap enable is not implemented... */
|
/* EJTAG probe trap enable is not implemented... */
|
||||||
if (!(env->CP0_Status & (1 << CP0St_EXL)))
|
if (!(env->CP0_Status & (1 << CP0St_EXL)))
|
||||||
|
@ -395,6 +396,7 @@ void do_interrupt (CPUState *env)
|
||||||
env->CP0_ErrorEPC = env->PC;
|
env->CP0_ErrorEPC = env->PC;
|
||||||
}
|
}
|
||||||
env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
|
env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
|
||||||
|
env->hflags |= MIPS_HFLAG_64;
|
||||||
env->hflags &= ~MIPS_HFLAG_UM;
|
env->hflags &= ~MIPS_HFLAG_UM;
|
||||||
if (!(env->CP0_Status & (1 << CP0St_EXL)))
|
if (!(env->CP0_Status & (1 << CP0St_EXL)))
|
||||||
env->CP0_Cause &= ~(1 << CP0Ca_BD);
|
env->CP0_Cause &= ~(1 << CP0Ca_BD);
|
||||||
|
@ -493,6 +495,7 @@ void do_interrupt (CPUState *env)
|
||||||
env->CP0_Cause &= ~(1 << CP0Ca_BD);
|
env->CP0_Cause &= ~(1 << CP0Ca_BD);
|
||||||
}
|
}
|
||||||
env->CP0_Status |= (1 << CP0St_EXL);
|
env->CP0_Status |= (1 << CP0St_EXL);
|
||||||
|
env->hflags |= MIPS_HFLAG_64;
|
||||||
env->hflags &= ~MIPS_HFLAG_UM;
|
env->hflags &= ~MIPS_HFLAG_UM;
|
||||||
}
|
}
|
||||||
env->hflags &= ~MIPS_HFLAG_BMASK;
|
env->hflags &= ~MIPS_HFLAG_BMASK;
|
||||||
|
|
|
@ -1358,6 +1358,12 @@ void op_mtc0_status (void)
|
||||||
!(env->hflags & MIPS_HFLAG_DM) &&
|
!(env->hflags & MIPS_HFLAG_DM) &&
|
||||||
(val & (1 << CP0St_UM)))
|
(val & (1 << CP0St_UM)))
|
||||||
env->hflags |= MIPS_HFLAG_UM;
|
env->hflags |= MIPS_HFLAG_UM;
|
||||||
|
#ifdef TARGET_MIPS64
|
||||||
|
if ((env->hflags & MIPS_HFLAG_UM) &&
|
||||||
|
!(val & (1 << CP0St_PX)) &&
|
||||||
|
!(val & (1 << CP0St_UX)))
|
||||||
|
env->hflags &= ~MIPS_HFLAG_64;
|
||||||
|
#endif
|
||||||
env->CP0_Status = (env->CP0_Status & ~mask) | val;
|
env->CP0_Status = (env->CP0_Status & ~mask) | val;
|
||||||
if (loglevel & CPU_LOG_EXEC)
|
if (loglevel & CPU_LOG_EXEC)
|
||||||
CALL_FROM_TB2(do_mtc0_status_debug, old, val);
|
CALL_FROM_TB2(do_mtc0_status_debug, old, val);
|
||||||
|
@ -2338,6 +2344,12 @@ void op_eret (void)
|
||||||
!(env->hflags & MIPS_HFLAG_DM) &&
|
!(env->hflags & MIPS_HFLAG_DM) &&
|
||||||
(env->CP0_Status & (1 << CP0St_UM)))
|
(env->CP0_Status & (1 << CP0St_UM)))
|
||||||
env->hflags |= MIPS_HFLAG_UM;
|
env->hflags |= MIPS_HFLAG_UM;
|
||||||
|
#ifdef TARGET_MIPS64
|
||||||
|
if ((env->hflags & MIPS_HFLAG_UM) &&
|
||||||
|
!(env->CP0_Status & (1 << CP0St_PX)) &&
|
||||||
|
!(env->CP0_Status & (1 << CP0St_UX)))
|
||||||
|
env->hflags &= ~MIPS_HFLAG_64;
|
||||||
|
#endif
|
||||||
if (loglevel & CPU_LOG_EXEC)
|
if (loglevel & CPU_LOG_EXEC)
|
||||||
CALL_FROM_TB0(debug_post_eret);
|
CALL_FROM_TB0(debug_post_eret);
|
||||||
env->CP0_LLAddr = 1;
|
env->CP0_LLAddr = 1;
|
||||||
|
@ -2355,6 +2367,12 @@ void op_deret (void)
|
||||||
!(env->hflags & MIPS_HFLAG_DM) &&
|
!(env->hflags & MIPS_HFLAG_DM) &&
|
||||||
(env->CP0_Status & (1 << CP0St_UM)))
|
(env->CP0_Status & (1 << CP0St_UM)))
|
||||||
env->hflags |= MIPS_HFLAG_UM;
|
env->hflags |= MIPS_HFLAG_UM;
|
||||||
|
#ifdef TARGET_MIPS64
|
||||||
|
if ((env->hflags & MIPS_HFLAG_UM) &&
|
||||||
|
!(env->CP0_Status & (1 << CP0St_PX)) &&
|
||||||
|
!(env->CP0_Status & (1 << CP0St_UX)))
|
||||||
|
env->hflags &= ~MIPS_HFLAG_64;
|
||||||
|
#endif
|
||||||
if (loglevel & CPU_LOG_EXEC)
|
if (loglevel & CPU_LOG_EXEC)
|
||||||
CALL_FROM_TB0(debug_post_eret);
|
CALL_FROM_TB0(debug_post_eret);
|
||||||
env->CP0_LLAddr = 1;
|
env->CP0_LLAddr = 1;
|
||||||
|
|
|
@ -730,9 +730,9 @@ OP_ST_TABLE(dl);
|
||||||
OP_ST_TABLE(dr);
|
OP_ST_TABLE(dr);
|
||||||
OP_LD_TABLE(ld);
|
OP_LD_TABLE(ld);
|
||||||
OP_ST_TABLE(cd);
|
OP_ST_TABLE(cd);
|
||||||
|
OP_LD_TABLE(wu);
|
||||||
#endif
|
#endif
|
||||||
OP_LD_TABLE(w);
|
OP_LD_TABLE(w);
|
||||||
OP_LD_TABLE(wu);
|
|
||||||
OP_LD_TABLE(wl);
|
OP_LD_TABLE(wl);
|
||||||
OP_LD_TABLE(wr);
|
OP_LD_TABLE(wr);
|
||||||
OP_ST_TABLE(w);
|
OP_ST_TABLE(w);
|
||||||
|
@ -773,6 +773,11 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
|
||||||
*/
|
*/
|
||||||
switch (opc) {
|
switch (opc) {
|
||||||
#ifdef TARGET_MIPS64
|
#ifdef TARGET_MIPS64
|
||||||
|
case OPC_LWU:
|
||||||
|
op_ldst(lwu);
|
||||||
|
GEN_STORE_TN_REG(rt, T0);
|
||||||
|
opn = "lwu";
|
||||||
|
break;
|
||||||
case OPC_LD:
|
case OPC_LD:
|
||||||
op_ldst(ld);
|
op_ldst(ld);
|
||||||
GEN_STORE_TN_REG(rt, T0);
|
GEN_STORE_TN_REG(rt, T0);
|
||||||
|
@ -823,11 +828,6 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
|
||||||
GEN_STORE_TN_REG(rt, T0);
|
GEN_STORE_TN_REG(rt, T0);
|
||||||
opn = "lw";
|
opn = "lw";
|
||||||
break;
|
break;
|
||||||
case OPC_LWU:
|
|
||||||
op_ldst(lwu);
|
|
||||||
GEN_STORE_TN_REG(rt, T0);
|
|
||||||
opn = "lwu";
|
|
||||||
break;
|
|
||||||
case OPC_SW:
|
case OPC_SW:
|
||||||
GEN_LOAD_REG_TN(T1, rt);
|
GEN_LOAD_REG_TN(T1, rt);
|
||||||
op_ldst(sw);
|
op_ldst(sw);
|
||||||
|
@ -5377,14 +5377,20 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||||
case OPC_DSRL ... OPC_DSRA:
|
case OPC_DSRL ... OPC_DSRA:
|
||||||
case OPC_DSLL32:
|
case OPC_DSLL32:
|
||||||
case OPC_DSRL32 ... OPC_DSRA32:
|
case OPC_DSRL32 ... OPC_DSRA32:
|
||||||
|
if (!(ctx->hflags & MIPS_HFLAG_64))
|
||||||
|
generate_exception(ctx, EXCP_RI);
|
||||||
gen_arith_imm(ctx, op1, rd, rt, sa);
|
gen_arith_imm(ctx, op1, rd, rt, sa);
|
||||||
break;
|
break;
|
||||||
case OPC_DSLLV:
|
case OPC_DSLLV:
|
||||||
case OPC_DSRLV ... OPC_DSRAV:
|
case OPC_DSRLV ... OPC_DSRAV:
|
||||||
case OPC_DADD ... OPC_DSUBU:
|
case OPC_DADD ... OPC_DSUBU:
|
||||||
|
if (!(ctx->hflags & MIPS_HFLAG_64))
|
||||||
|
generate_exception(ctx, EXCP_RI);
|
||||||
gen_arith(ctx, op1, rd, rs, rt);
|
gen_arith(ctx, op1, rd, rs, rt);
|
||||||
break;
|
break;
|
||||||
case OPC_DMULT ... OPC_DDIVU:
|
case OPC_DMULT ... OPC_DDIVU:
|
||||||
|
if (!(ctx->hflags & MIPS_HFLAG_64))
|
||||||
|
generate_exception(ctx, EXCP_RI);
|
||||||
gen_muldiv(ctx, op1, rs, rt);
|
gen_muldiv(ctx, op1, rs, rt);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
@ -5420,6 +5426,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||||
break;
|
break;
|
||||||
#ifdef TARGET_MIPS64
|
#ifdef TARGET_MIPS64
|
||||||
case OPC_DCLZ ... OPC_DCLO:
|
case OPC_DCLZ ... OPC_DCLO:
|
||||||
|
if (!(ctx->hflags & MIPS_HFLAG_64))
|
||||||
|
generate_exception(ctx, EXCP_RI);
|
||||||
gen_cl(ctx, op1, rd, rs);
|
gen_cl(ctx, op1, rd, rs);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
@ -5491,9 +5499,13 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||||
#ifdef TARGET_MIPS64
|
#ifdef TARGET_MIPS64
|
||||||
case OPC_DEXTM ... OPC_DEXT:
|
case OPC_DEXTM ... OPC_DEXT:
|
||||||
case OPC_DINSM ... OPC_DINS:
|
case OPC_DINSM ... OPC_DINS:
|
||||||
|
if (!(ctx->hflags & MIPS_HFLAG_64))
|
||||||
|
generate_exception(ctx, EXCP_RI);
|
||||||
gen_bitops(ctx, op1, rt, rs, sa, rd);
|
gen_bitops(ctx, op1, rt, rs, sa, rd);
|
||||||
break;
|
break;
|
||||||
case OPC_DBSHFL:
|
case OPC_DBSHFL:
|
||||||
|
if (!(ctx->hflags & MIPS_HFLAG_64))
|
||||||
|
generate_exception(ctx, EXCP_RI);
|
||||||
op2 = MASK_DBSHFL(ctx->opcode);
|
op2 = MASK_DBSHFL(ctx->opcode);
|
||||||
switch (op2) {
|
switch (op2) {
|
||||||
case OPC_DSBH:
|
case OPC_DSBH:
|
||||||
|
@ -5732,9 +5744,13 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||||
case OPC_LD:
|
case OPC_LD:
|
||||||
case OPC_SCD:
|
case OPC_SCD:
|
||||||
case OPC_SD:
|
case OPC_SD:
|
||||||
|
if (!(ctx->hflags & MIPS_HFLAG_64))
|
||||||
|
generate_exception(ctx, EXCP_RI);
|
||||||
gen_ldst(ctx, op, rt, rs, imm);
|
gen_ldst(ctx, op, rt, rs, imm);
|
||||||
break;
|
break;
|
||||||
case OPC_DADDI ... OPC_DADDIU:
|
case OPC_DADDI ... OPC_DADDIU:
|
||||||
|
if (!(ctx->hflags & MIPS_HFLAG_64))
|
||||||
|
generate_exception(ctx, EXCP_RI);
|
||||||
gen_arith_imm(ctx, op, rt, rs, imm);
|
gen_arith_imm(ctx, op, rt, rs, imm);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
@ -6072,11 +6088,14 @@ void cpu_reset (CPUMIPSState *env)
|
||||||
/* If the exception was raised from a delay slot,
|
/* If the exception was raised from a delay slot,
|
||||||
* come back to the jump. */
|
* come back to the jump. */
|
||||||
env->CP0_ErrorEPC = env->PC - 4;
|
env->CP0_ErrorEPC = env->PC - 4;
|
||||||
env->hflags &= ~MIPS_HFLAG_BMASK;
|
|
||||||
} else {
|
} else {
|
||||||
env->CP0_ErrorEPC = env->PC;
|
env->CP0_ErrorEPC = env->PC;
|
||||||
}
|
}
|
||||||
|
#ifdef TARGET_MIPS64
|
||||||
|
env->hflags = MIPS_HFLAG_64;
|
||||||
|
#else
|
||||||
env->hflags = 0;
|
env->hflags = 0;
|
||||||
|
#endif
|
||||||
env->PC = (int32_t)0xBFC00000;
|
env->PC = (int32_t)0xBFC00000;
|
||||||
env->CP0_Wired = 0;
|
env->CP0_Wired = 0;
|
||||||
/* SMP not implemented */
|
/* SMP not implemented */
|
||||||
|
|
Loading…
Reference in New Issue