Fix reset handling, CP0 isn't enabled by default (a fact which doesn't
matter when running in kernel space). git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2228 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
e144966416
commit
aa328addc0
@ -245,7 +245,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
|
|||||||
|
|
||||||
void do_interrupt (CPUState *env)
|
void do_interrupt (CPUState *env)
|
||||||
{
|
{
|
||||||
target_ulong pc, offset;
|
target_ulong offset;
|
||||||
int cause = -1;
|
int cause = -1;
|
||||||
|
|
||||||
if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) {
|
if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) {
|
||||||
@ -284,8 +284,7 @@ void do_interrupt (CPUState *env)
|
|||||||
set_DEPC:
|
set_DEPC:
|
||||||
if (env->hflags & MIPS_HFLAG_BMASK) {
|
if (env->hflags & MIPS_HFLAG_BMASK) {
|
||||||
/* 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_DEPC = env->PC - 4;
|
env->CP0_DEPC = env->PC - 4;
|
||||||
env->hflags &= ~MIPS_HFLAG_BMASK;
|
env->hflags &= ~MIPS_HFLAG_BMASK;
|
||||||
} else {
|
} else {
|
||||||
@ -294,41 +293,29 @@ void do_interrupt (CPUState *env)
|
|||||||
enter_debug_mode:
|
enter_debug_mode:
|
||||||
env->hflags |= MIPS_HFLAG_DM;
|
env->hflags |= MIPS_HFLAG_DM;
|
||||||
/* EJTAG probe trap enable is not implemented... */
|
/* EJTAG probe trap enable is not implemented... */
|
||||||
pc = 0xBFC00480;
|
env->PC = 0xBFC00480;
|
||||||
break;
|
break;
|
||||||
case EXCP_RESET:
|
case EXCP_RESET:
|
||||||
#ifdef MIPS_USES_R4K_TLB
|
cpu_reset(env);
|
||||||
env->CP0_random = MIPS_TLB_NB - 1;
|
break;
|
||||||
#endif
|
|
||||||
env->CP0_Wired = 0;
|
|
||||||
env->CP0_Config0 = MIPS_CONFIG0;
|
|
||||||
env->CP0_Config1 = MIPS_CONFIG1;
|
|
||||||
env->CP0_Config2 = MIPS_CONFIG2;
|
|
||||||
env->CP0_Config3 = MIPS_CONFIG3;
|
|
||||||
env->CP0_WatchLo = 0;
|
|
||||||
env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV);
|
|
||||||
goto set_error_EPC;
|
|
||||||
case EXCP_SRESET:
|
case EXCP_SRESET:
|
||||||
env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV) |
|
env->CP0_Status = (1 << CP0St_SR);
|
||||||
(1 << CP0St_SR);
|
|
||||||
env->CP0_WatchLo = 0;
|
env->CP0_WatchLo = 0;
|
||||||
goto set_error_EPC;
|
goto set_error_EPC;
|
||||||
case EXCP_NMI:
|
case EXCP_NMI:
|
||||||
env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV) |
|
env->CP0_Status = (1 << CP0St_NMI);
|
||||||
(1 << CP0St_NMI);
|
|
||||||
set_error_EPC:
|
set_error_EPC:
|
||||||
if (env->hflags & MIPS_HFLAG_BMASK) {
|
if (env->hflags & MIPS_HFLAG_BMASK) {
|
||||||
/* 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;
|
env->hflags &= ~MIPS_HFLAG_BMASK;
|
||||||
} else {
|
} else {
|
||||||
env->CP0_ErrorEPC = env->PC;
|
env->CP0_ErrorEPC = env->PC;
|
||||||
}
|
}
|
||||||
env->hflags |= MIPS_HFLAG_ERL;
|
env->hflags |= MIPS_HFLAG_ERL;
|
||||||
env->CP0_Status |= (1 << CP0St_ERL);
|
env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
|
||||||
pc = 0xBFC00000;
|
env->PC = 0xBFC00000;
|
||||||
break;
|
break;
|
||||||
case EXCP_MCHECK:
|
case EXCP_MCHECK:
|
||||||
cause = 24;
|
cause = 24;
|
||||||
@ -385,19 +372,9 @@ void do_interrupt (CPUState *env)
|
|||||||
offset = 0x000;
|
offset = 0x000;
|
||||||
goto set_EPC;
|
goto set_EPC;
|
||||||
set_EPC:
|
set_EPC:
|
||||||
if (env->CP0_Status & (1 << CP0St_BEV)) {
|
|
||||||
pc = 0xBFC00200;
|
|
||||||
} else {
|
|
||||||
pc = 0x80000000;
|
|
||||||
}
|
|
||||||
env->hflags |= MIPS_HFLAG_EXL;
|
|
||||||
env->CP0_Status |= (1 << CP0St_EXL);
|
|
||||||
pc += offset;
|
|
||||||
env->CP0_Cause = (env->CP0_Cause & ~0x7C) | (cause << 2);
|
|
||||||
if (env->hflags & MIPS_HFLAG_BMASK) {
|
if (env->hflags & MIPS_HFLAG_BMASK) {
|
||||||
/* 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_EPC = env->PC - 4;
|
env->CP0_EPC = env->PC - 4;
|
||||||
env->CP0_Cause |= 0x80000000;
|
env->CP0_Cause |= 0x80000000;
|
||||||
env->hflags &= ~MIPS_HFLAG_BMASK;
|
env->hflags &= ~MIPS_HFLAG_BMASK;
|
||||||
@ -405,6 +382,15 @@ void do_interrupt (CPUState *env)
|
|||||||
env->CP0_EPC = env->PC;
|
env->CP0_EPC = env->PC;
|
||||||
env->CP0_Cause &= ~0x80000000;
|
env->CP0_Cause &= ~0x80000000;
|
||||||
}
|
}
|
||||||
|
if (env->CP0_Status & (1 << CP0St_BEV)) {
|
||||||
|
env->PC = 0xBFC00200;
|
||||||
|
} else {
|
||||||
|
env->PC = 0x80000000;
|
||||||
|
}
|
||||||
|
env->hflags |= MIPS_HFLAG_EXL;
|
||||||
|
env->CP0_Status |= (1 << CP0St_EXL);
|
||||||
|
env->PC += offset;
|
||||||
|
env->CP0_Cause = (env->CP0_Cause & ~0x7C) | (cause << 2);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (logfile) {
|
if (logfile) {
|
||||||
@ -414,7 +400,6 @@ void do_interrupt (CPUState *env)
|
|||||||
printf("Invalid MIPS exception %d. Exiting\n", env->exception_index);
|
printf("Invalid MIPS exception %d. Exiting\n", env->exception_index);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
env->PC = pc;
|
|
||||||
if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) {
|
if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) {
|
||||||
fprintf(logfile, "%s: PC %08x EPC %08x cause %d excp %d\n"
|
fprintf(logfile, "%s: PC %08x EPC %08x cause %d excp %d\n"
|
||||||
" S %08x C %08x A %08x D %08x\n",
|
" S %08x C %08x A %08x D %08x\n",
|
||||||
|
@ -2817,8 +2817,8 @@ static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd)
|
|||||||
{
|
{
|
||||||
const char *opn = "unk";
|
const char *opn = "unk";
|
||||||
|
|
||||||
if (!(ctx->CP0_Status & (1 << CP0St_CU0)) &&
|
if ((!ctx->CP0_Status & (1 << CP0St_CU0) &&
|
||||||
(ctx->hflags & MIPS_HFLAG_UM) &&
|
(ctx->hflags & MIPS_HFLAG_UM)) &&
|
||||||
!(ctx->hflags & MIPS_HFLAG_ERL) &&
|
!(ctx->hflags & MIPS_HFLAG_ERL) &&
|
||||||
!(ctx->hflags & MIPS_HFLAG_EXL)) {
|
!(ctx->hflags & MIPS_HFLAG_EXL)) {
|
||||||
if (loglevel & CPU_LOG_TB_IN_ASM) {
|
if (loglevel & CPU_LOG_TB_IN_ASM) {
|
||||||
@ -4048,6 +4048,14 @@ void cpu_reset (CPUMIPSState *env)
|
|||||||
tlb_flush(env, 1);
|
tlb_flush(env, 1);
|
||||||
|
|
||||||
/* Minimal init */
|
/* Minimal init */
|
||||||
|
if (env->hflags & MIPS_HFLAG_BMASK) {
|
||||||
|
/* If the exception was raised from a delay slot,
|
||||||
|
* come back to the jump. */
|
||||||
|
env->CP0_ErrorEPC = env->PC - 4;
|
||||||
|
env->hflags &= ~MIPS_HFLAG_BMASK;
|
||||||
|
} else {
|
||||||
|
env->CP0_ErrorEPC = env->PC;
|
||||||
|
}
|
||||||
env->PC = 0xBFC00000;
|
env->PC = 0xBFC00000;
|
||||||
#if defined (MIPS_USES_R4K_TLB)
|
#if defined (MIPS_USES_R4K_TLB)
|
||||||
env->CP0_random = MIPS_TLB_NB - 1;
|
env->CP0_random = MIPS_TLB_NB - 1;
|
||||||
@ -4060,7 +4068,7 @@ void cpu_reset (CPUMIPSState *env)
|
|||||||
env->CP0_Config1 = MIPS_CONFIG1;
|
env->CP0_Config1 = MIPS_CONFIG1;
|
||||||
env->CP0_Config2 = MIPS_CONFIG2;
|
env->CP0_Config2 = MIPS_CONFIG2;
|
||||||
env->CP0_Config3 = MIPS_CONFIG3;
|
env->CP0_Config3 = MIPS_CONFIG3;
|
||||||
env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV);
|
env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
|
||||||
env->CP0_WatchLo = 0;
|
env->CP0_WatchLo = 0;
|
||||||
env->hflags = MIPS_HFLAG_ERL;
|
env->hflags = MIPS_HFLAG_ERL;
|
||||||
/* Count register increments in debug mode, EJTAG version 1 */
|
/* Count register increments in debug mode, EJTAG version 1 */
|
||||||
|
Loading…
Reference in New Issue
Block a user