//TODO - merge with armcpu_irqException? //http://www.ethernut.de/en/documents/arm-exceptions.html //http://docs.google.com/viewer?a=v&q=cache:V4ht1YkxprMJ:www.cs.nctu.edu.tw/~wjtsai/EmbeddedSystemDesign/Ch3-1.pdf+arm+exception+handling&hl=en&gl=us&pid=bl&srcid=ADGEEShx9VTHbUhWdDOrTVRzLkcCsVfJiijncNDkkgkrlJkLa7D0LCpO8fQ_hhU3DTcgZh9rcZWWQq4TYhhCovJ625h41M0ZUX3WGasyzWQFxYzDCB-VS6bsUmpoJnRxAc-bdkD0qmsu&sig=AHIEtbR9VHvDOCRmZFQDUVwy53iJDjoSPQ void armcpu_exception(armcpu_t *cpu, u32 number) { Mode cpumode = USR; switch(number) { case EXCEPTION_RESET: cpumode = SVC; break; case EXCEPTION_UNDEFINED_INSTRUCTION: cpumode = UND; break; case EXCEPTION_SWI: cpumode = SVC; break; case EXCEPTION_PREFETCH_ABORT: cpumode = ABT; break; case EXCEPTION_DATA_ABORT: cpumode = ABT; break; case EXCEPTION_RESERVED_0x14: emu_halt(); break; case EXCEPTION_IRQ: cpumode = IRQ; break; case EXCEPTION_FAST_IRQ: cpumode = FIQ; break; } Status_Reg tmp = cpu->CPSR; armcpu_switchMode(cpu, cpumode); //enter new mode cpu->R[14] = cpu->next_instruction; cpu->SPSR = tmp; //save old CPSR as new SPSR cpu->CPSR.bits.T = 0; //handle as ARM32 code cpu->CPSR.bits.I = 1; cpu->changeCPSR(); cpu->R[15] = cpu->intVector + number; cpu->next_instruction = cpu->R[15]; printf("armcpu_exception!\n"); //extern bool dolog; //dolog=true; //HOW DOES THIS WORTK WITHOUT A PREFETCH, LIKE IRQ BELOW? //I REALLY WISH WE DIDNT PREFETCH BEFORE EXECUTING }
bool NDS_Pause(bool showMsg = true) { if(paused) return false; emu_halt(); paused = TRUE; SPU_Pause(1); while (!paused) {} if (showMsg) INFO("Emulation paused\n"); return true; }
u32 TRAPUNDEF(armcpu_t* cpu) { INFO("ARM%c: Undefined instruction: 0x%08X (%s) PC=0x%08X\n", cpu->proc_ID?'7':'9', cpu->instruction, decodeIntruction(false, cpu->instruction), cpu->instruct_adr); if (((cpu->intVector != 0) ^ (cpu->proc_ID == ARMCPU_ARM9))) { armcpu_exception(&NDS_ARM9,EXCEPTION_UNDEFINED_INSTRUCTION); return 4; } else { emu_halt(); return 4; } }
u32 armcpu_exec() { // Usually, fetching and executing are processed parallelly. // So this function stores the cycles of each process to // the variables below, and returns appropriate cycle count. u32 cFetch = 0; u32 cExecute = 0; //this assert is annoying. but sometimes it is handy. //assert(ARMPROC.instruct_adr!=0x00000000); //#ifdef DEVELOPER #if 0 if ((((ARMPROC.instruct_adr & 0x0F000000) == 0x0F000000) && (PROCNUM == 0)) || (((ARMPROC.instruct_adr & 0x0F000000) == 0x00000000) && (PROCNUM == 1))) { switch (ARMPROC.instruct_adr & 0xFFFF) { case 0x00000000: printf("BIOS%c: Reset!!!\n", PROCNUM?'7':'9'); emu_halt(); break; case 0x00000004: printf("BIOS%c: Undefined instruction\n", PROCNUM?'7':'9'); //emu_halt(); break; case 0x00000008: //printf("BIOS%c: SWI\n", PROCNUM?'7':'9'); break; case 0x0000000C: printf("BIOS%c: Prefetch Abort!!!\n", PROCNUM?'7':'9'); //emu_halt(); break; case 0x00000010: //printf("BIOS%c: Data Abort!!!\n", PROCNUM?'7':'9'); //emu_halt(); break; case 0x00000014: printf("BIOS%c: Reserved!!!\n", PROCNUM?'7':'9'); break; case 0x00000018: //printf("BIOS%c: IRQ\n", PROCNUM?'7':'9'); break; case 0x0000001C: printf("BIOS%c: Fast IRQ\n", PROCNUM?'7':'9'); break; } } #endif #if 0 //#ifdef GDB_STUB if (ARMPROC.stalled) { return STALLED_CYCLE_COUNT; } /* check for interrupts */ if (ARMPROC.irq_flag) { armcpu_irqException(&ARMPROC); } cFetch = armcpu_prefetch(&ARMPROC); if (ARMPROC.stalled) { return MMU_fetchExecuteCycles<PROCNUM>(cExecute, cFetch); } #endif //cFetch = armcpu_prefetch(&ARMPROC); //printf("%d: %08X\n",PROCNUM,ARMPROC.instruct_adr); if(ARMPROC.CPSR.bits.T == 0) { const u32 condition = CONDITION(ARMPROC.instruction); if( condition == 0x0E //fast path for unconditional instructions || (TEST_COND(condition, CODE(ARMPROC.instruction), ARMPROC.CPSR)) //handles any condition ) { #ifdef HAVE_LUA CallRegisteredLuaMemHook(ARMPROC.instruct_adr, 4, ARMPROC.instruction, LUAMEMHOOK_EXEC); // should report even if condition=false? #endif if(PROCNUM==0) { #ifdef DEVELOPER DEBUG_statistics.instructionHits[0].arm[INSTRUCTION_INDEX(ARMPROC.instruction)]++; #endif cExecute = arm_instructions_set_0[INSTRUCTION_INDEX(ARMPROC.instruction)](ARMPROC.instruction); } else { #ifdef DEVELOPER DEBUG_statistics.instructionHits[1].arm[INSTRUCTION_INDEX(ARMPROC.instruction)]++; #endif cExecute = arm_instructions_set_1[INSTRUCTION_INDEX(ARMPROC.instruction)](ARMPROC.instruction); } } else cExecute = 1; // If condition=false: 1S cycle #ifdef GDB_STUB if ( ARMPROC.post_ex_fn != NULL) { /* call the external post execute function */ ARMPROC.post_ex_fn(ARMPROC.post_ex_fn_data, ARMPROC.instruct_adr, 0); } ARMPROC.mem_if->prefetch32( ARMPROC.mem_if->data, ARMPROC.next_instruction); #endif cFetch = armcpu_prefetch<PROCNUM>(); return MMU_fetchExecuteCycles<PROCNUM>(cExecute, cFetch); } #ifdef HAVE_LUA CallRegisteredLuaMemHook(ARMPROC.instruct_adr, 2, ARMPROC.instruction, LUAMEMHOOK_EXEC); #endif if(PROCNUM==0) { #ifdef DEVELOPER DEBUG_statistics.instructionHits[0].thumb[ARMPROC.instruction>>6]++; #endif cExecute = thumb_instructions_set_0[ARMPROC.instruction>>6](ARMPROC.instruction); }
static void nds4droid_throttle(bool allowSleep = true, int forceFrameSkip = -1) { int skipRate = (forceFrameSkip < 0) ? frameskiprate : forceFrameSkip; int ffSkipRate = (forceFrameSkip < 0) ? 9 : forceFrameSkip; if(lastskiprate != skipRate) { lastskiprate = skipRate; mainLoopData.framestoskip = 0; // otherwise switches to lower frameskip rates will lag behind } if(!mainLoopData.skipnextframe || forceFrameSkip == 0 || frameAdvance || (continuousframeAdvancing && !FastForward)) { mainLoopData.framesskipped = 0; if (mainLoopData.framestoskip > 0) mainLoopData.skipnextframe = 1; } else { mainLoopData.framestoskip--; if (mainLoopData.framestoskip < 1) mainLoopData.skipnextframe = 0; else mainLoopData.skipnextframe = 1; mainLoopData.framesskipped++; NDS_SkipNextFrame(); } if(FastForward) { if(mainLoopData.framesskipped < ffSkipRate) { mainLoopData.skipnextframe = 1; mainLoopData.framestoskip = 1; } if (mainLoopData.framestoskip < 1) mainLoopData.framestoskip += ffSkipRate; } else if((/*autoframeskipenab && frameskiprate ||*/ FrameLimit) && allowSleep) { SpeedThrottle(); } if (autoframeskipenab && frameskiprate) { if(!frameAdvance && !continuousframeAdvancing) { AutoFrameSkip_NextFrame(); if (mainLoopData.framestoskip < 1) mainLoopData.framestoskip += AutoFrameSkip_GetSkipAmount(0,skipRate); } } else { if (mainLoopData.framestoskip < 1) mainLoopData.framestoskip += skipRate; } if (frameAdvance && allowSleep) { frameAdvance = false; emu_halt(); SPU_Pause(1); } if(execute && emu_paused && !frameAdvance) { // safety net against running out of control in case this ever happens. NDS_UnPause(); NDS_Pause(); } //ServiceDisplayThreadInvocations(); }
TEMPLATE static u32 FASTCALL OP_UND_THUMB(const u32 i) { emu_halt(); return 1; }