void cpuSetUpInterrupt(ULO new_interrupt_level) { UWO vector_offset = (UWO) (0x60 + new_interrupt_level*4); ULO vector_address = memoryReadLong(cpuGetVbr() + vector_offset); cpuActivateSSP(); // Switch to using ssp or msp. Loads a7 and preserves usp if we came from user-mode. cpuStackFrameGenerate(vector_offset, cpuGetPC()); // This will end up on msp if master is enabled, or on the ssp/isp if not. cpuSetSR(cpuGetSR() & 0x38ff); // Clear interrupt level cpuSetSR(cpuGetSR() | 0x2000); // Set supervisor mode cpuSetSR(cpuGetSR() | (UWO)(new_interrupt_level << 8)); // Set interrupt level #ifdef CPU_INSTRUCTION_LOGGING cpuCallInterruptLoggingFunc(new_interrupt_level, vector_address); #endif if (cpuGetModelMajor() >= 2 && cpuGetModelMajor() < 6) { if (cpuGetFlagMaster()) { // If the cpu was in master mode, preserve msp, and switch to using ssp (isp) in a7. ULO oldA7 = cpuGetAReg(7); cpuSetMspDirect(oldA7); cpuSetAReg(7, cpuGetSspDirect()); cpuFrame1(vector_offset, cpuGetPC()); // Make the throwaway frame on ssp/isp cpuSetSR(cpuGetSR() & 0xefff); // Clear master bit } } cpuInitializeFromNewPC(vector_address); cpuSetStop(FALSE); cpuSetRaiseInterrupt(FALSE); }
static void cpuThrowResetException010(void) { cpuSetSR(cpuGetSR() & 0x271f); /* T = 0 */ cpuSetSR(cpuGetSR() | 0x2700); /* S = 1, ilvl = 7 */ cpuSetVbr(0); cpuSetSspDirect(cpuGetInitialSP()); /* ssp = fake vector 0 */ cpuInitializeFromNewPC(cpuGetInitialPC()); /* pc = fake vector 1 */ }
static void cpuThrowResetException030(void) { cpuSetSR(cpuGetSR() & 0x271f); /* T1T0 = 0, M = 0 */ cpuSetSR(cpuGetSR() | 0x2700); /* S = 1, ilvl = 7 */ cpuSetVbr(0); cpuSetCacr(0); /* E = 0, F = 0 */ cpuSetCaar(0); /* Invalidate cache, we don't have one */ cpuSetSspDirect(cpuGetInitialSP()); /* ssp = fake vector 0 */ cpuInitializeFromNewPC(cpuGetInitialPC()); /* pc = fake vector 1 */ }
void cpuThrowException(ULO vector_offset, ULO pc, BOOLE executejmp) { ULO vector_address; #ifdef CPU_INSTRUCTION_LOGGING cpuCallExceptionLoggingFunc(cpuGetExceptionName(vector_offset), cpuGetOriginalPC(), cpuGetCurrentOpcode()); #endif cpuActivateSSP(); cpuStackFrameGenerate((UWO) vector_offset, pc); // read a memory position vector_address = memoryReadLong(cpuGetVbr() + vector_offset); if (cpuGetModelMajor() < 2 && vector_address & 0x1 && vector_offset == 0xc) { // Avoid endless loop that will crash the emulator. // The (odd) address error exception vector contained an odd address. cpuCallResetExceptionFunc(); cpuHardReset(); cpuSetInstructionTime(132); } else { // set supervisor modus cpuSetSR(cpuGetSR() | 0x2000); cpuSetSR(cpuGetSR() & 0x3fff); // restart cpu, if needed cpuSetStop(FALSE); cpuInitializeFromNewPC(vector_address); cpuSetInstructionTime(40); } // If the exception happened mid-instruction... if (executejmp) { cpuCallMidInstructionExceptionFunc(); // Supposed to be doing setjmp/longjmp back to machine emulator code } }