
Delay slot handling
-------------------
 
 The MIPS virtual CPU could be in a delay state of DELAYING, DELAYSLOT,
 or NORMAL at the beginning of the call to one_instr(), which state could
 change after PC address translation and instruction fetching had occurred
 (i.e., right before instruction emulation.)  The value of the delay state
 has an effect on the exception PC calculation. In all but extraordinary
 circumstances the EPC should be the address of the instruction which
 caused the exception; however, if the instruction is executing in a
 delay slot, and it causes an exception, the EPC should be reported as the
 address of the immediately-preceding branch instruction. The following
 are the (myriad) different possible ways this is accomplished with the
 current code.

 The two possible sources of exceptions that an instruction can cause
 to occur before that instruction is actually emulated are the call to
 CPZero::address_trans() and the call to Mapper::fetch_word(), which are
 roughly equivalent to PC address translation and instruction fetching,
 respectively.
 
 If the delay state was DELAYING at the beginning of the call to
 one_instr(), it meant that the previous instruction was a branch that
 was taken. The action required would be to execute the instruction
 immediately after the branch (i.e., the instruction in the delay slot),
 whose address would be given by the PC. After PC address translation
 and instruction fetching, the PC would be saved in branch_pc (which was
 actually the address of the instruction in the delay slot, NOT that of
 the branch), the PC would be loaded with the target of the branch, which
 was computed earlier and saved in delay_pc, and the delay state would be
 set to DELAYSLOT for the duration of the emulation of the instruction in
 the delay slot. If an exception was taken during address translation or
 instruction fetching, the delay state was DELAYING, and the EPC would be
 calculated as PC - 4, which is the address of the branch. If an exception
 was taken during instruction emulation, the delay state was DELAYSLOT,
 and the EPC would be calculated as branch_pc - 4, which is the address
 of the branch.
 
 If the delay state was DELAYSLOT at the beginning of the call to
 one_instr(), it meant that the *previous* instruction was executed in a
 delay slot; that is, the current PC was calculated by taking a branch. The
 problem with the current code is that if the address translation or
 instruction fetch of the instruction to which the branch was taken
 results in an exception, the delay state will still be DELAYSLOT when
 exception() is called, and the EPC would be calculated as branch_pc -
 4, which is the address of the branch that got us to the current PC,
 not the instruction that caused the exception. If, on the other hand,
 the exception was caused by the instruction emulation, and not by the
 instruction fetch or the PC address translation, the delay state would
 be NORMAL, and the exception PC would be calculated as PC - 4, which
 is correct because as the delay state was set to NORMAL from DELAYSLOT,
 the PC was incremented by 4.
 
 If the delay slot was NORMAL at the beginning of the call to one_instr(),
 the EPC was correctly calculated if the exception resulted from instruction
 emulation; otherwise, it was off by one instruction (because PC - 4 was
 the instruction prior to the current one.) This could be easily demonstrated
 by having a four-byte ROM with one valid instruction, and watching the EPC
 calculated when it tried to run off the end...
 
 XXX This should be revised for accuracy and completeness; no one cares about
 what this bug was.

