Line 136... |
Line 136... |
case EXCEPT_ITLBMISS:
|
case EXCEPT_ITLBMISS:
|
case EXCEPT_IPF:
|
case EXCEPT_IPF:
|
#if DYNAMIC_EXECUTION
|
#if DYNAMIC_EXECUTION
|
/* In immu_translate except_handle is called with except_handle(..., virtaddr) */
|
/* In immu_translate except_handle is called with except_handle(..., virtaddr) */
|
/* Add the immu miss delay to the cycle counter */
|
/* Add the immu miss delay to the cycle counter */
|
if(!immu_ex_from_insn)
|
if(!immu_ex_from_insn) {
|
mtspr(SPR_EPCR_BASE, get_pc() - (cpu_state.delay_insn ? 4 : 0));
|
mtspr(SPR_EPCR_BASE, get_pc() - (cpu_state.delay_insn ? 4 : 0));
|
else
|
} else
|
/* This exception came from an l.mtspr instruction in which case the pc
|
/* This exception came from an l.mtspr instruction in which case the pc
|
* points to the l.mtspr instruction when in acutal fact, it is the next
|
* points to the l.mtspr instruction when in acutal fact, it is the next
|
* instruction that would have faulted/missed. ea is used instead of
|
* instruction that would have faulted/missed. ea is used instead of
|
* cpu_state.pc + 4 because in the event that the l.mtspr instruction is
|
* cpu_state.pc + 4 because in the event that the l.mtspr instruction is
|
* in the delay slot of a page local jump the fault must happen on the
|
* in the delay slot of a page local jump the fault must happen on the
|
* instruction that was jumped to. This is handled in recheck_immu. */
|
* instruction that was jumped to. This is handled in recheck_immu. */
|
mtspr(SPR_EPCR_BASE, ea);
|
mtspr(SPR_EPCR_BASE, ea);
|
run_sched_out_of_line(immu_ex_from_insn);
|
run_sched_out_of_line(immu_ex_from_insn);
|
|
/* Save the registers that are in the temporaries */
|
|
if(!cpu_state.ts_current)
|
|
upd_reg_from_t(cpu_state.pc, !immu_ex_from_insn);
|
immu_ex_from_insn = 0;
|
immu_ex_from_insn = 0;
|
break;
|
break;
|
#endif
|
#endif
|
/* All these exceptions happen during a simulated instruction */
|
/* All these exceptions happen during a simulated instruction */
|
case EXCEPT_BUSERR:
|
case EXCEPT_BUSERR:
|
Line 163... |
Line 166... |
#if DYNAMIC_EXECUTION
|
#if DYNAMIC_EXECUTION
|
/* Since these exceptions happen during a simulated instruction and this
|
/* Since these exceptions happen during a simulated instruction and this
|
* function jumps out to the exception vector the scheduler would never have
|
* function jumps out to the exception vector the scheduler would never have
|
* a chance to run, therefore run it now */
|
* a chance to run, therefore run it now */
|
run_sched_out_of_line(1);
|
run_sched_out_of_line(1);
|
|
/* Save the registers that are in the temporaries */
|
|
if(!cpu_state.ts_current) {
|
|
if(cpu_state.delay_insn &&
|
|
(ADDR_PAGE(cpu_state.pc) == ADDR_PAGE(cpu_state.pc - 4)))
|
|
upd_reg_from_t(cpu_state.pc - 4, 0);
|
|
else
|
|
upd_reg_from_t(cpu_state.pc, 0);
|
|
}
|
#endif
|
#endif
|
mtspr(SPR_EPCR_BASE, cpu_state.pc - (cpu_state.delay_insn ? 4 : 0));
|
mtspr(SPR_EPCR_BASE, cpu_state.pc - (cpu_state.delay_insn ? 4 : 0));
|
break;
|
break;
|
/* EPCR is loaded with address of next not-yet-executed instruction */
|
/* EPCR is loaded with address of next not-yet-executed instruction */
|
case EXCEPT_SYSCALL:
|
case EXCEPT_SYSCALL:
|
Line 186... |
Line 197... |
#else
|
#else
|
/* except_handle() mucks around with the temporaries, which are in the state
|
/* except_handle() mucks around with the temporaries, which are in the state
|
* of the last instruction executed and not the next one, to which the pc
|
* of the last instruction executed and not the next one, to which the pc
|
* now points to */
|
* now points to */
|
cpu_state.pc -= 4;
|
cpu_state.pc -= 4;
|
|
|
|
/* Save the registers that are in the temporaries */
|
|
if(!cpu_state.ts_current)
|
|
upd_reg_from_t(cpu_state.pc, 1);
|
#endif
|
#endif
|
break;
|
break;
|
}
|
}
|
|
|
/* Address trnaslation is here because run_sched_out_of_line calls
|
/* Address trnaslation is here because run_sched_out_of_line calls
|
Line 197... |
Line 212... |
* if it would be disabled above then there would be not much point... */
|
* if it would be disabled above then there would be not much point... */
|
cpu_state.sprs[SPR_SR] &= ~SPR_SR_IME;
|
cpu_state.sprs[SPR_SR] &= ~SPR_SR_IME;
|
|
|
/* Complex/simple execution strictly don't need this because of the
|
/* Complex/simple execution strictly don't need this because of the
|
* next_delay_insn thingy but in the dynamic execution modell that doesn't
|
* next_delay_insn thingy but in the dynamic execution modell that doesn't
|
* exist and thus cpu_state.insn_delay would stick in the exception handler
|
* exist and thus cpu_state.delay_insn would stick in the exception handler
|
* causeing grief if the first instruction of the exception handler is also in
|
* causeing grief if the first instruction of the exception handler is also in
|
* the delay slot of the previous instruction */
|
* the delay slot of the previous instruction */
|
cpu_state.delay_insn = 0;
|
cpu_state.delay_insn = 0;
|
|
|
#if DYNAMIC_EXECUTION
|
#if DYNAMIC_EXECUTION
|
/* Save the registers that are in the temporaries */
|
|
if(!cpu_state.ts_current)
|
|
upd_reg_from_t(cpu_state.pc);
|
|
|
|
cpu_state.pc = except_vector;
|
cpu_state.pc = except_vector;
|
cpu_state.ts_current = 0;
|
cpu_state.ts_current = 0;
|
jump_dyn_code(except_vector);
|
jump_dyn_code(except_vector);
|
#endif
|
#endif
|
}
|
}
|