📄 exception.cc
字号:
#include "koala.hh"// Exception processing functions. Before handling the exception, these// functions check for a higher- priority exception occuring elsewhere in the// pipeline, and handle those instead if necessary.// Process a reset, soft reset and nmi exceptions as specified by the (events)// field. These are the highest-priority exceptions handled in the D pipeline// stage, so handling them is fairly easy.//// The system state is set as follows://// if ColdReset then// Random = tlb_size - 1// Wired = 0// Config = 0 || EC || EP || 0{8} || BE || 110010010110xxx// endif// ErrorEPC = PC// SR = SR[31:23] || 10 || sr || SR[19:3] || 1 || SR[1:0]// PC = 0xFFFF FFFF BFC0 0000//// Where (sr) is cleared for a cold reset and set otherwise.// For both cold and soft reset, the caches and the TLB are also reset.// WARNING: Because resets and interrupts are detected in the D pipeline// stage, one instruction should complete before they are detected and the// interrupt is taken. This effect is currently NOT simulated: it is unlikely// that the detail will cause any problems as interrupts are typically driven// by a clock many times slower than the pipeline anyway. The same effect can// also be achieved by scheduling the interrupts one cycle after the actual// event time (for example, by ignoring the fact that the events are guranteed// to be invoked *after* the scheduled time.)voidKoala::process_reset(){ if (trace_level >= report_exceptions) log("[%lx] Handling reset exception", pc); now += 5; if (events & cold_reset_event) { cp0[Random] = tlb_size - 1; random_seed = now; cp0[Wired] = 0; reset_icache(); reset_dcache(); reset_tlb(); } cp0[ErrorEPC] = branch_delay_slot() ? pc - 4 : pc; cp0[SR] = set_bit(cp0[SR], SR_BEV); cp0[SR] = set_bit(cp0[SR], SR_ERL); if (events & (soft_reset_event | nmi_event)) cp0[SR] = set_bit(cp0[SR], SR_SR); else cp0[SR] = clear_bit(cp0[SR], SR_SR); pc = reset_vector_base + reset_vector; pipeline = nothing_special; enter_kernel_mode(); events = 0;}// Process a general exception.// The system state is set as follows://// Cause = BD || 0 || CE || 0{12} || Cause[15:8] || 0 || exc || 0{2}// if SR[1] = 0 then// EPC = PC// endif// SR = SR[31:2] || 1 || SR[0]// if SR[22] = 1 then// PC = 0xFFFF FFFF BFC0 0200 + vec// else// PC = 0xFFFF FFFF 8000 0000 + vec// endif//// Because the IP field in the Cause register is actually stored in the// (events) word, Cause may be set directly to the exception code, adjusted// for exceptions in a branch-delay slot. Any additional changes to the// machine state are handled in inline wrappers on process_exception() (see// "koala.hh".) Exceptions are serviced when the corresponding instruction// enters the W pipeline stage: at this stage. Hence, there are always// exactly five dead clock cycles after an exception: these are simulated// simply by incrementing the clock by five.voidKoala::process_exception(UInt32 cause, int vec){ if (trace_level >= report_exceptions) { static const char* name[] = { "Int", "Mod", "TLBL", "TLBS", "AdEL", "AdES", "IBE", "DBE", "Sys", "Bp", "RI", "CpU", "Ov", "Tr", "reserved", "FPE" }; log("[%lx] Handling exception %s (#%d)", pc, (cause / 4 < sizeof(name) / sizeof(name[0])) ? name[cause / 4] : "reserved", cause / 4); dump_gpr_registers(); } now += 5; VA epc; if (!branch_delay_slot()) epc = pc; else { epc = pc - 4; cause = set_bit(cause, Cause_BD); } cp0[Cause] = cause; if (!bit(cp0[SR], SR_EXL)) { cp0[EPC] = epc; cp0[SR] = set_bit(cp0[SR], SR_EXL); } pc = vec + (bit(cp0[SR], SR_BEV) ? general_vector_base : boot_vector_base); pipeline = nothing_special; enter_kernel_mode(); longjmp(env, 1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -