245 |
245 |
|
246 |
246 |
void do_interrupt (CPUState *env)
|
247 |
247 |
{
|
248 |
|
target_ulong pc, offset;
|
|
248 |
target_ulong offset;
|
249 |
249 |
int cause = -1;
|
250 |
250 |
|
251 |
251 |
if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) {
|
... | ... | |
284 |
284 |
set_DEPC:
|
285 |
285 |
if (env->hflags & MIPS_HFLAG_BMASK) {
|
286 |
286 |
/* If the exception was raised from a delay slot,
|
287 |
|
* come back to the jump
|
288 |
|
*/
|
|
287 |
come back to the jump. */
|
289 |
288 |
env->CP0_DEPC = env->PC - 4;
|
290 |
289 |
env->hflags &= ~MIPS_HFLAG_BMASK;
|
291 |
290 |
} else {
|
... | ... | |
294 |
293 |
enter_debug_mode:
|
295 |
294 |
env->hflags |= MIPS_HFLAG_DM;
|
296 |
295 |
/* EJTAG probe trap enable is not implemented... */
|
297 |
|
pc = 0xBFC00480;
|
|
296 |
env->PC = 0xBFC00480;
|
298 |
297 |
break;
|
299 |
298 |
case EXCP_RESET:
|
300 |
|
#ifdef MIPS_USES_R4K_TLB
|
301 |
|
env->CP0_random = MIPS_TLB_NB - 1;
|
302 |
|
#endif
|
303 |
|
env->CP0_Wired = 0;
|
304 |
|
env->CP0_Config0 = MIPS_CONFIG0;
|
305 |
|
env->CP0_Config1 = MIPS_CONFIG1;
|
306 |
|
env->CP0_Config2 = MIPS_CONFIG2;
|
307 |
|
env->CP0_Config3 = MIPS_CONFIG3;
|
308 |
|
env->CP0_WatchLo = 0;
|
309 |
|
env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV);
|
310 |
|
goto set_error_EPC;
|
|
299 |
cpu_reset(env);
|
|
300 |
break;
|
311 |
301 |
case EXCP_SRESET:
|
312 |
|
env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV) |
|
313 |
|
(1 << CP0St_SR);
|
|
302 |
env->CP0_Status = (1 << CP0St_SR);
|
314 |
303 |
env->CP0_WatchLo = 0;
|
315 |
304 |
goto set_error_EPC;
|
316 |
305 |
case EXCP_NMI:
|
317 |
|
env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV) |
|
318 |
|
(1 << CP0St_NMI);
|
|
306 |
env->CP0_Status = (1 << CP0St_NMI);
|
319 |
307 |
set_error_EPC:
|
320 |
308 |
if (env->hflags & MIPS_HFLAG_BMASK) {
|
321 |
309 |
/* If the exception was raised from a delay slot,
|
322 |
|
* come back to the jump
|
323 |
|
*/
|
|
310 |
come back to the jump. */
|
324 |
311 |
env->CP0_ErrorEPC = env->PC - 4;
|
325 |
312 |
env->hflags &= ~MIPS_HFLAG_BMASK;
|
326 |
313 |
} else {
|
327 |
314 |
env->CP0_ErrorEPC = env->PC;
|
328 |
315 |
}
|
329 |
316 |
env->hflags |= MIPS_HFLAG_ERL;
|
330 |
|
env->CP0_Status |= (1 << CP0St_ERL);
|
331 |
|
pc = 0xBFC00000;
|
|
317 |
env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
|
|
318 |
env->PC = 0xBFC00000;
|
332 |
319 |
break;
|
333 |
320 |
case EXCP_MCHECK:
|
334 |
321 |
cause = 24;
|
... | ... | |
385 |
372 |
offset = 0x000;
|
386 |
373 |
goto set_EPC;
|
387 |
374 |
set_EPC:
|
388 |
|
if (env->CP0_Status & (1 << CP0St_BEV)) {
|
389 |
|
pc = 0xBFC00200;
|
390 |
|
} else {
|
391 |
|
pc = 0x80000000;
|
392 |
|
}
|
393 |
|
env->hflags |= MIPS_HFLAG_EXL;
|
394 |
|
env->CP0_Status |= (1 << CP0St_EXL);
|
395 |
|
pc += offset;
|
396 |
|
env->CP0_Cause = (env->CP0_Cause & ~0x7C) | (cause << 2);
|
397 |
375 |
if (env->hflags & MIPS_HFLAG_BMASK) {
|
398 |
376 |
/* If the exception was raised from a delay slot,
|
399 |
|
* come back to the jump
|
400 |
|
*/
|
|
377 |
come back to the jump. */
|
401 |
378 |
env->CP0_EPC = env->PC - 4;
|
402 |
379 |
env->CP0_Cause |= 0x80000000;
|
403 |
380 |
env->hflags &= ~MIPS_HFLAG_BMASK;
|
... | ... | |
405 |
382 |
env->CP0_EPC = env->PC;
|
406 |
383 |
env->CP0_Cause &= ~0x80000000;
|
407 |
384 |
}
|
|
385 |
if (env->CP0_Status & (1 << CP0St_BEV)) {
|
|
386 |
env->PC = 0xBFC00200;
|
|
387 |
} else {
|
|
388 |
env->PC = 0x80000000;
|
|
389 |
}
|
|
390 |
env->hflags |= MIPS_HFLAG_EXL;
|
|
391 |
env->CP0_Status |= (1 << CP0St_EXL);
|
|
392 |
env->PC += offset;
|
|
393 |
env->CP0_Cause = (env->CP0_Cause & ~0x7C) | (cause << 2);
|
408 |
394 |
break;
|
409 |
395 |
default:
|
410 |
396 |
if (logfile) {
|
... | ... | |
414 |
400 |
printf("Invalid MIPS exception %d. Exiting\n", env->exception_index);
|
415 |
401 |
exit(1);
|
416 |
402 |
}
|
417 |
|
env->PC = pc;
|
418 |
403 |
if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) {
|
419 |
404 |
fprintf(logfile, "%s: PC %08x EPC %08x cause %d excp %d\n"
|
420 |
405 |
" S %08x C %08x A %08x D %08x\n",
|