diff --git a/desmume/src/MMU.h b/desmume/src/MMU.h index dca37cde2..1f33e8d55 100644 --- a/desmume/src/MMU.h +++ b/desmume/src/MMU.h @@ -586,8 +586,11 @@ inline void SetupMMU(BOOL debugConsole) { } -FORCEINLINE void CheckMemoryDebugEvent(const EDEBUG_EVENT event, const MMU_ACCESS_TYPE type, const u32 procnum, const u32 addr, const u32 size, const u32 val) +FORCEINLINE void CheckMemoryDebugEvent(EDEBUG_EVENT event, const MMU_ACCESS_TYPE type, const u32 procnum, const u32 addr, const u32 size, const u32 val) { + //TODO - ugh work out a better prefetch event system + if(type == MMU_AT_CODE && event == DEBUG_EVENT_READ) + event = DEBUG_EVENT_EXECUTE; if(CheckDebugEvent(event)) { DebugEventData.memAccessType = type; @@ -596,11 +599,6 @@ FORCEINLINE void CheckMemoryDebugEvent(const EDEBUG_EVENT event, const MMU_ACCES DebugEventData.size = size; DebugEventData.val = val; HandleDebugEvent(event); - - if(type == MMU_AT_CODE && event == DEBUG_EVENT_READ) - { - HandleDebugEvent(DEBUG_EVENT_EXECUTE); - } } } @@ -704,6 +702,12 @@ FORCEINLINE u32 _MMU_read32(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u if(addr<0x02000000) return T1ReadLong_guaranteedAligned(MMU.ARM9_ITCM, addr&0x7FFC); + //what happens when we execute from DTCM? nocash makes it look like we get 0xFFFFFFFF but i can't seem to verify it + //historically, desmume would fall through to its old memory map struct + //which would return unused memory (0) + //it seems the hardware returns 0 or something benign because in actuality 0xFFFFFFFF is an undefined opcode + //and we know our handling for that is solid + goto dunno; } diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index 4319959b9..690279e2b 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -45,7 +45,7 @@ //#define LOG_ARM9 //#define LOG_ARM7 -bool dolog = true; +//bool dolog = true; //#define LOG_TO_FILE //#define LOG_TO_FILE_REGS @@ -2127,25 +2127,67 @@ void NDS_Reset() { NDS_ARM9.swi_tab = ARM9_swi_tab; - T1WriteLong(MMU.ARM9_BIOS, 0x0000, 0xEAFFFFFE); // loop for Reset !!! - T1WriteLong(MMU.ARM9_BIOS, 0x0004, 0xEAFFFFFE); // loop for Undef instr expection - T1WriteLong(MMU.ARM9_BIOS, 0x0008, 0xEA00009C); // SWI - T1WriteLong(MMU.ARM9_BIOS, 0x000C, 0xEAFFFFFE); // loop for Prefetch Abort - T1WriteLong(MMU.ARM9_BIOS, 0x0010, 0xEAFFFFFE); // loop for Data Abort + //bios chains data abort to fast irq + + //exception vectors: + T1WriteLong(MMU.ARM9_BIOS, 0x0000, 0xEAFFFFFE); // (infinite loop for) Reset !!! + //T1WriteLong(MMU.ARM9_BIOS, 0x0004, 0xEAFFFFFE); // (infinite loop for) Undefined instruction + T1WriteLong(MMU.ARM9_BIOS, 0x0004, 0xEA000004); // Undefined instruction -> Fast IRQ (just guessing) + T1WriteLong(MMU.ARM9_BIOS, 0x0008, 0xEA00009C); // SWI -> ????? + T1WriteLong(MMU.ARM9_BIOS, 0x000C, 0xEAFFFFFE); // (infinite loop for) Prefetch Abort + T1WriteLong(MMU.ARM9_BIOS, 0x0010, 0xEA000001); // Data Abort -> Fast IRQ T1WriteLong(MMU.ARM9_BIOS, 0x0014, 0x00000000); // Reserved - T1WriteLong(MMU.ARM9_BIOS, 0x0018, 0xEA000095); // Normal IRQ - T1WriteLong(MMU.ARM9_BIOS, 0x001C, 0x00000000); // Fast IRQ - for (int t = 0; t < 156; t++) // logo + T1WriteLong(MMU.ARM9_BIOS, 0x0018, 0xEA000095); // Normal IRQ -> 0x0274 + T1WriteLong(MMU.ARM9_BIOS, 0x001C, 0xEA00009D); // Fast IRQ -> 0x0298 + + // logo (do some games fail to boot without this? example?) + for (int t = 0; t < 0x9C; t++) MMU.ARM9_BIOS[t + 0x20] = logo_data[t]; - T1WriteLong(MMU.ARM9_BIOS, 0x0274, 0xE92D500F); - T1WriteLong(MMU.ARM9_BIOS, 0x0278, 0xEE190F11); - T1WriteLong(MMU.ARM9_BIOS, 0x027C, 0xE1A00620); - T1WriteLong(MMU.ARM9_BIOS, 0x0280, 0xE1A00600); - T1WriteLong(MMU.ARM9_BIOS, 0x0284, 0xE2800C40); - T1WriteLong(MMU.ARM9_BIOS, 0x0288, 0xE28FE000); - T1WriteLong(MMU.ARM9_BIOS, 0x028C, 0xE510F004); - T1WriteLong(MMU.ARM9_BIOS, 0x0290, 0xE8BD500F); - T1WriteLong(MMU.ARM9_BIOS, 0x0294, 0xE25EF004); + + //...0xBC: + + //(now what goes in this gap??) + + //IRQ handler: get dtcm address and jump to a vector in it + T1WriteLong(MMU.ARM9_BIOS, 0x0274, 0xE92D500F); //STMDB SP!, {R0-R3,R12,LR} + T1WriteLong(MMU.ARM9_BIOS, 0x0278, 0xEE190F11); //MRC CP15, 0, R0, CR9, CR1, 0 + T1WriteLong(MMU.ARM9_BIOS, 0x027C, 0xE1A00620); //MOV R0, R0, LSR #C + T1WriteLong(MMU.ARM9_BIOS, 0x0280, 0xE1A00600); //MOV R0, R0, LSL #C + T1WriteLong(MMU.ARM9_BIOS, 0x0284, 0xE2800C40); //ADD R0, R0, #4000 + T1WriteLong(MMU.ARM9_BIOS, 0x0288, 0xE28FE000); //ADD LR, PC, #0 + T1WriteLong(MMU.ARM9_BIOS, 0x028C, 0xE510F004); //LDR PC, [R0, -#4] + + //???? + T1WriteLong(MMU.ARM9_BIOS, 0x0290, 0xE8BD500F); //LDMIA SP!, {R0-R3,R12,LR} + T1WriteLong(MMU.ARM9_BIOS, 0x0294, 0xE25EF004); //SUBS PC, LR, #4 + + //------- + //FIQ and abort exception handler + //TODO - this code is copied from the bios. refactor it + //friendly reminder: to calculate an immediate offset: encoded = (desired_address-cur_address-8) + + T1WriteLong(MMU.ARM9_BIOS, 0x0298, 0xE10FD000); //MRS SP, CPSR + T1WriteLong(MMU.ARM9_BIOS, 0x029C, 0xE38DD0C0); //ORR SP, SP, #C0 + + T1WriteLong(MMU.ARM9_BIOS, 0x02A0, 0xE12FF00D); //MSR CPSR_fsxc, SP + T1WriteLong(MMU.ARM9_BIOS, 0x02A4, 0xE59FD000 | (0x2D4-0x2A4-8)); //LDR SP, [FFFF02D4] + T1WriteLong(MMU.ARM9_BIOS, 0x02A8, 0xE28DD001); //ADD SP, SP, #1 + T1WriteLong(MMU.ARM9_BIOS, 0x02AC, 0xE92D5000); //STMDB SP!, {R12,LR} + + T1WriteLong(MMU.ARM9_BIOS, 0x02B0, 0xE14FE000); //MRS LR, SPSR + T1WriteLong(MMU.ARM9_BIOS, 0x02B4, 0xEE11CF10); //MRC CP15, 0, R12, CR1, CR0, 0 + T1WriteLong(MMU.ARM9_BIOS, 0x02B8, 0xE92D5000); //STMDB SP!, {R12,LR} + T1WriteLong(MMU.ARM9_BIOS, 0x02BC, 0xE3CCC001); //BIC R12, R12, #1 + + T1WriteLong(MMU.ARM9_BIOS, 0x02C0, 0xEE01CF10); //MCR CP15, 0, R12, CR1, CR0, 0 + T1WriteLong(MMU.ARM9_BIOS, 0x02C4, 0xE3CDC001); //BIC R12, SP, #1 + T1WriteLong(MMU.ARM9_BIOS, 0x02C8, 0xE59CC010); //LDR R12, [R12, #10] + T1WriteLong(MMU.ARM9_BIOS, 0x02CC, 0xE35C0000); //CMP R12, #0 + + T1WriteLong(MMU.ARM9_BIOS, 0x02D0, 0x112FFF3C); //BLXNE R12 + T1WriteLong(MMU.ARM9_BIOS, 0x02D4, 0x027FFD9C); //0x027FFD9C + //--------- + } #ifdef LOG_ARM7 @@ -2247,6 +2289,9 @@ void NDS_Reset() NDS_ARM9.R13_svc = 0x00803FC0; NDS_ARM9.R13_irq = 0x00803FA0; NDS_ARM9.R13_usr = 0x00803EC0; + NDS_ARM9.R13_abt = NDS_ARM9.R13_usr; //????? + //I think it is wrong to take gbatek's "SYS" and put it in USR--maybe USR doesnt matter. + //i think SYS is all the misc modes. please verify by setting nonsensical stack values for USR here NDS_ARM9.R[13] = NDS_ARM9.R13_usr; //n.b.: im not sure about all these, I dont know enough about arm9 svc/irq/etc modes //and how theyre named in desmume to match them up correctly. i just guessed. diff --git a/desmume/src/arm_instructions.cpp b/desmume/src/arm_instructions.cpp index 4ba190ea5..28c674d8d 100644 --- a/desmume/src/arm_instructions.cpp +++ b/desmume/src/arm_instructions.cpp @@ -261,28 +261,6 @@ TEMPLATE static u32 FASTCALL OP_UND(const u32 i) return 1; } -#define TRAPUNDEF() \ - LOG("Undefined instruction: %#08X PC = %#08X \n", cpu->instruction, cpu->instruct_adr); \ - \ - if (((cpu->intVector != 0) ^ (PROCNUM == ARMCPU_ARM9))) \ - { \ - Status_Reg tmp = cpu->CPSR; \ - armcpu_switchMode(cpu, UND); /* enter und mode */ \ - cpu->R[14] = cpu->R[15] - 4; /* jump to und Vector */ \ - cpu->SPSR = tmp; /* save old CPSR as new SPSR */ \ - cpu->CPSR.bits.T = 0; /* handle as ARM32 code */ \ - cpu->CPSR.bits.I = cpu->SPSR.bits.I; /* keep int disable flag */ \ - cpu->changeCPSR(); \ - cpu->R[15] = cpu->intVector + 0x04; \ - cpu->next_instruction = cpu->R[15]; \ - return 4; \ - } \ - else \ - { \ - emu_halt(); \ - return 4; \ - } \ - //----------------------------------------------------------------------------- // AND / ANDS // Timing: OK @@ -3176,6 +3154,8 @@ TEMPLATE static u32 FASTCALL OP_BX(const u32 i) u32 tmp = cpu->R[REG_POS(cpu->instruction, 0)]; cpu->CPSR.bits.T = BIT0(tmp); + //zeromus has a little concern about these. shouldnt they be 0xFFFFFFFC? + //can someone refute this or prove it? cpu->R[15] = tmp & 0xFFFFFFFE; cpu->next_instruction = cpu->R[15]; return 3; @@ -3187,6 +3167,8 @@ TEMPLATE static u32 FASTCALL OP_BLX_REG(const u32 i) cpu->R[14] = cpu->next_instruction; cpu->CPSR.bits.T = BIT0(tmp); + //zeromus has a little concern about these. shouldnt they be 0xFFFFFFFC? + //can someone refute this or prove it? cpu->R[15] = tmp & 0xFFFFFFFE; cpu->next_instruction = cpu->R[15]; return 3; @@ -6732,37 +6714,37 @@ TEMPLATE static u32 FASTCALL OP_LDRD_STRD_OFFSET_PRE_INDEX(const u32 i) TEMPLATE static u32 FASTCALL OP_STC_P_IMM_OFF(const u32 i) { - TRAPUNDEF(); + return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_STC_M_IMM_OFF(const u32 i) { - TRAPUNDEF(); + return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_STC_P_PREIND(const u32 i) { - TRAPUNDEF(); + return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_STC_M_PREIND(const u32 i) { - TRAPUNDEF(); + return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_STC_P_POSTIND(const u32 i) { - TRAPUNDEF(); + return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_STC_M_POSTIND(const u32 i) { - TRAPUNDEF(); + return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_STC_OPTION(const u32 i) { - TRAPUNDEF(); + return TRAPUNDEF(cpu); } //----------------------------------------------------------------------------- @@ -6772,38 +6754,37 @@ TEMPLATE static u32 FASTCALL OP_STC_OPTION(const u32 i) TEMPLATE static u32 FASTCALL OP_LDC_P_IMM_OFF(const u32 i) { - TRAPUNDEF(); + return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_LDC_M_IMM_OFF(const u32 i) { - TRAPUNDEF(); + return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_LDC_P_PREIND(const u32 i) { - TRAPUNDEF(); + return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_LDC_M_PREIND(const u32 i) { - TRAPUNDEF(); + return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_LDC_P_POSTIND(const u32 i) { - TRAPUNDEF(); + return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_LDC_M_POSTIND(const u32 i) { - TRAPUNDEF(); + return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_LDC_OPTION(const u32 i) { - TRAPUNDEF(); - return 2; + return TRAPUNDEF(cpu); } //----------------------------------------------------------------------------- @@ -6813,7 +6794,7 @@ TEMPLATE static u32 FASTCALL OP_LDC_OPTION(const u32 i) TEMPLATE static u32 FASTCALL OP_MCR(const u32 i) { u32 cpnum = REG_POS(i, 8); - + if(!cpu->coproc[cpnum]) { emu_halt(); @@ -6911,7 +6892,7 @@ TEMPLATE static u32 FASTCALL OP_BKPT(const u32 i) TEMPLATE static u32 FASTCALL OP_CDP(const u32 i) { LOG("Stopped (OP_CDP) \n"); - TRAPUNDEF(); + return TRAPUNDEF(cpu); } //----------------------------------------------------------------------------- diff --git a/desmume/src/armcpu.cpp b/desmume/src/armcpu.cpp index 7dbe29367..dc1325eb8 100644 --- a/desmume/src/armcpu.cpp +++ b/desmume/src/armcpu.cpp @@ -397,7 +397,7 @@ FORCEINLINE static u32 armcpu_prefetch() armcpu->R[15] = armcpu->next_instruction + 4; } #else - curInstruction &= 0x0FFFFFFC; + curInstruction &= 0xFFFFFFFC; //please don't change this to 0x0FFFFFFC -- the NDS will happily run on 0xF******* addresses all day long armcpu->instruction = _MMU_read32(curInstruction); armcpu->instruct_adr = curInstruction; armcpu->next_instruction = curInstruction + 4; @@ -419,7 +419,7 @@ FORCEINLINE static u32 armcpu_prefetch() armcpu->R[15] = armcpu->next_instruction + 2; } #else - curInstruction &= 0x0FFFFFFE; + curInstruction &= 0xFFFFFFFE; //please don't change this to 0x0FFFFFFE -- the NDS will happily run on 0xF******* addresses all day long armcpu->instruction = _MMU_read16(curInstruction); armcpu->instruct_adr = curInstruction; armcpu->next_instruction = curInstruction + 2; @@ -469,6 +469,37 @@ static BOOL (FASTCALL* test_conditions[])(Status_Reg CPSR)= { (cond<15&&test_conditions[cond](CPSR)) #endif +//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; +} BOOL armcpu_irqException(armcpu_t *armcpu) { @@ -502,6 +533,21 @@ BOOL armcpu_irqException(armcpu_t *armcpu) return TRUE; } +u32 TRAPUNDEF(armcpu_t* cpu) +{ + LOG("Undefined instruction: %#08X PC = %#08X \n", cpu->instruction, cpu->instruct_adr); + if (((cpu->intVector != 0) ^ (cpu->proc_ID == ARMCPU_ARM9))) + { + armcpu_exception(&NDS_ARM9,0x04); + return 4; + } + else + { + emu_halt(); + return 4; + } +} + //BOOL //armcpu_flagIrq( armcpu_t *armcpu) { // if(armcpu->CPSR.bits.I) return FALSE; @@ -524,6 +570,11 @@ u32 armcpu_exec() u32 cFetch = 0; u32 cExecute = 0; + if(NDS_ARM9.instruct_adr == 0x0201125C) + { + int zzz=9; + } + //this assert is annoying. but sometimes it is handy. //assert(ARMPROC.instruct_adr!=0x00000000); #ifdef DEVELOPER @@ -538,18 +589,18 @@ u32 armcpu_exec() break; case 0x00000004: printf("BIOS%c: Undefined instruction\n", PROCNUM?'7':'9'); - emu_halt(); + //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(); + //emu_halt(); break; case 0x00000010: - printf("BIOS%c: Data Abort!!!\n", PROCNUM?'7':'9'); - emu_halt(); + //printf("BIOS%c: Data Abort!!!\n", PROCNUM?'7':'9'); + //emu_halt(); break; case 0x00000014: printf("BIOS%c: Reserved!!!\n", PROCNUM?'7':'9'); diff --git a/desmume/src/armcpu.h b/desmume/src/armcpu.h index 26649939b..4e367eb01 100644 --- a/desmume/src/armcpu.h +++ b/desmume/src/armcpu.h @@ -29,6 +29,15 @@ #define OPCODE(i) (((i)>>21)&0xF) #define SIGNEBIT(i) BIT_N(i,20) +#define EXCEPTION_RESET 0x00 +#define EXCEPTION_UNDEFINED_INSTRUCTION 0x04 +#define EXCEPTION_SWI 0x08 +#define EXCEPTION_PREFETCH_ABORT 0x0C +#define EXCEPTION_DATA_ABORT 0x10 +#define EXCEPTION_RESERVED_0x14 0x14 +#define EXCEPTION_IRQ 0x18 +#define EXCEPTION_FAST_IRQ 0x1C + #define INSTRUCTION_INDEX(i) ((((i)>>16)&0xFF0)|(((i)>>4)&0xF)) inline u32 ROR(u32 i, u32 j) { return ((((u32)(i))>>(j)) | (((u32)(i))<<(32-(j)))); } @@ -216,6 +225,8 @@ template u32 armcpu_exec(); BOOL armcpu_irqException(armcpu_t *armcpu); BOOL armcpu_flagIrq( armcpu_t *armcpu); +void armcpu_exception(armcpu_t *cpu, u32 number); +u32 TRAPUNDEF(armcpu_t* cpu); extern armcpu_t NDS_ARM7; extern armcpu_t NDS_ARM9; diff --git a/desmume/src/debug.cpp b/desmume/src/debug.cpp index 3930c62e3..9f6b6e8da 100644 --- a/desmume/src/debug.cpp +++ b/desmume/src/debug.cpp @@ -36,6 +36,8 @@ #include "lua-engine.h" #endif +armcpu_t* TDebugEventData::cpu() { return procnum==0?&NDS_ARM9:&NDS_ARM7; } + TDebugEventData DebugEventData; u32 debugFlag; @@ -43,25 +45,25 @@ u32 debugFlag; const bool debug_acl = false; static bool acl_check_access(u32 adr, u32 access) { - //tweak the access value with the execution mode. - //user code is USR and every other mode is SYS. - //this is weird logic, but I didn't want to change.. - access |= 1; - if ((NDS_ARM9.CPSR.val & 0x1F) == 0x10) { - // is user mode access - access ^= 1; - } + + //non-user modes get separate access handling, so check that here + if(NDS_ARM9.CPSR.bits.mode != USR) + access |= 1; + if (armcp15_isAccessAllowed((armcp15_t *)NDS_ARM9.coproc[15],adr,access)==FALSE) { HandleDebugEvent(DEBUG_EVENT_ACL_EXCEPTION); } return true; } - +void armcpu_exception(armcpu_t *cpu, u32 number); void HandleDebugEvent_ACL_Exception() { printf("ACL EXCEPTION!\n"); - emu_halt(); + if(DebugEventData.memAccessType == MMU_AT_CODE) + armcpu_exception(DebugEventData.cpu(),EXCEPTION_PREFETCH_ABORT); + else if(DebugEventData.memAccessType == MMU_AT_DATA) + armcpu_exception(DebugEventData.cpu(),EXCEPTION_DATA_ABORT); } void HandleDebugEvent_Read() diff --git a/desmume/src/debug.h b/desmume/src/debug.h index 56bb0e0fc..6b20a3e92 100644 --- a/desmume/src/debug.h +++ b/desmume/src/debug.h @@ -169,12 +169,14 @@ private: }; extern DebugNotify DEBUG_Notify; +struct armcpu_t; //information about a debug event will be stuffed into here by the generator struct TDebugEventData { MMU_ACCESS_TYPE memAccessType; u32 procnum, addr, size, val; + armcpu_t* cpu(); }; extern TDebugEventData DebugEventData; diff --git a/desmume/src/thumb_instructions.cpp b/desmume/src/thumb_instructions.cpp index 16a620611..2d05197ca 100644 --- a/desmume/src/thumb_instructions.cpp +++ b/desmume/src/thumb_instructions.cpp @@ -69,8 +69,8 @@ static bool OverflowFromSUB(s32 alu_out, s32 left, s32 right) TEMPLATE static u32 FASTCALL OP_UND_THUMB(const u32 i) { - INFO("THUMB%c: Undefined instruction: 0x%08X PC=0x%08X. Stopped!!!\n", cpu->proc_ID?'7':'9', cpu->instruction, cpu->instruct_adr); - emu_halt(); + INFO("THUMB%c: Undefined instruction: 0x%08X PC=0x%08X.\n", cpu->proc_ID?'7':'9', cpu->instruction, cpu->instruct_adr); + TRAPUNDEF(cpu); return 1; }