diff --git a/include/mem_map.h b/include/mem_map.h index f9f35b8..2885dc1 100644 --- a/include/mem_map.h +++ b/include/mem_map.h @@ -107,8 +107,8 @@ #define A9_STUB_SIZE (0x200) #define A9_HEAP_END (A9_RAM_BASE + A9_RAM_SIZE) #define A9_STACK_START (DTCM_BASE) -#define A9_STACK_END (DTCM_BASE + DTCM_SIZE - 0x1000) -#define A9_IRQ_STACK_START (DTCM_BASE + DTCM_SIZE - 0x1000) +#define A9_STACK_END (DTCM_BASE + DTCM_SIZE - 0x800) +#define A9_IRQ_STACK_START (DTCM_BASE + DTCM_SIZE - 0x800) #define A9_IRQ_STACK_END (DTCM_BASE + DTCM_SIZE) #define A9_EXC_STACK_START (ITCM_KERNEL_MIRROR + (ITCM_SIZE / 2)) #define A9_EXC_STACK_END (ITCM_KERNEL_MIRROR + ITCM_SIZE) diff --git a/source/arm9/debug.c b/source/arm9/debug.c index 1fb3a5e..839d921 100644 --- a/source/arm9/debug.c +++ b/source/arm9/debug.c @@ -62,11 +62,10 @@ } // Expects the registers in the exception stack to be in the following order: -// cpsr, pc (unmodified), r0-r14 -noreturn void guruMeditation(u8 type, u32 *excStack) +// r0-r14, pc (unmodified), cpsr +noreturn void guruMeditation(u8 type, const u32 *excStack) { - const char *typeStr[3] = {"Undefined instruction", "Prefetch abort", "Data abort"}; - const size_t maxStackWords = 15 * 2; + const char *const typeStr[3] = {"Undefined instruction", "Prefetch abort", "Data abort"}; u32 realPc, instSize = 4; bool codeChanged = false; @@ -79,9 +78,9 @@ consoleInit(0, NULL, true); - if(excStack[0] & 0x20) instSize = 2; // Processor was in Thumb mode? - if(type == 2) realPc = excStack[1] - (instSize * 2); // Data abort - else realPc = excStack[1] - instSize; // Other + if(excStack[16] & 0x20) instSize = 2; // Processor was in Thumb mode? + if(type == 2) realPc = excStack[15] - (instSize * 2); // Data abort + else realPc = excStack[15] - instSize; // Other printf("\x1b[41m\x1b[0J\x1b[9CGuru Meditation Error!\n\n%s:\n", typeStr[type]); printf("CPSR: 0x%08" PRIX32 "\n" @@ -93,26 +92,29 @@ "r5 = 0x%08" PRIX32 " sp = 0x%08" PRIX32 "\n" "r6 = 0x%08" PRIX32 " lr = 0x%08" PRIX32 "\n" "r7 = 0x%08" PRIX32 " pc = 0x%08" PRIX32 "\n\n", - excStack[0], + excStack[16], + excStack[0], excStack[8], + excStack[1], excStack[9], excStack[2], excStack[10], excStack[3], excStack[11], excStack[4], excStack[12], excStack[5], excStack[13], excStack[6], excStack[14], - excStack[7], excStack[15], - excStack[8], excStack[16], - excStack[9], realPc); + excStack[7], realPc); - // make sure we can actually dump the stack without triggering another fault. - if((excStack[15] >= (u32)A9_STACK_START) && (excStack[15] < (u32)A9_STACK_END) && - (excStack[15] + maxStackWords * 4 < (u32)A9_STACK_END)) + puts("Stack dump:"); + + u32 sp = excStack[13]; + if(sp >= DTCM_BASE && sp < DTCM_BASE + DTCM_SIZE && !(sp & 3u)) { - puts("Stack dump:"); - for(u32 i = 0; i < maxStackWords / 2; i++) + u32 stackWords = ((DTCM_BASE + DTCM_SIZE - sp) / 4 > 45 ? 45 : (DTCM_BASE + DTCM_SIZE - sp) / 4); + + u32 newlineCounter = 0; + for(u32 i = 0; i < stackWords; i++) { - printf("0x%08" PRIX32 ": %08" PRIX32 " %08" PRIX32 "\n", excStack[15], - ((u32*)excStack[15])[0], ((u32*)excStack[15])[1]); - excStack[15] += 8; + if(newlineCounter == 3) {printf("\n"); newlineCounter = 0;} + printf("0x%08" PRIX32 " ", ((u32*)sp)[i]); + newlineCounter++; } } @@ -124,7 +126,7 @@ PXI_sendWord(PXI_CMD_ALLOW_POWER_OFF); - for(;;) waitForIrq(); + while(1) waitForIrq(); } void dumpMem(u8 *mem, u32 size, char *filepath) diff --git a/source/arm9/exception.s b/source/arm9/exception.s index 6d2b894..7b815e9 100644 --- a/source/arm9/exception.s +++ b/source/arm9/exception.s @@ -20,19 +20,29 @@ ASM_FUNC dataAbortHandler msr cpsr_f, #(2<<29) ASM_FUNC exceptionHandler - mov sp, #A9_EXC_STACK_END - stmfd sp!, {r0-r14}^ @ Save all user/system mode regs except pc - mrs r4, cpsr - lsr r4, r4, #29 @ Get back the exception type from cpsr - mrs r1, spsr @ Get saved cpsr - stmfd sp!, {r1, lr} @ Save spsr and lr (pc) on exception stack + sub sp, #68 + stmia sp, {r0-r14}^ @ Save all user/system mode regs except pc + mrs r2, spsr @ Get saved cpsr + mrs r3, cpsr + lsr r0, r3, #29 @ Get back the exception type from cpsr + and r1, r2, #0x1F + cmp r1, #0x10 @ User mode + beq exceptionHandler_skip_other_mode + add r4, sp, #32 + msr cpsr_c, r2 + stmia r4!, {r8-r14} @ Some regs are written twice but we don't care + msr cpsr_c, r3 +exceptionHandler_skip_other_mode: + str lr, [sp, #60] @ Save lr (pc) on exception stack + str r2, [sp, #64] @ Save spsr (cpsr) on exception stack + mov r4, r0 mov r5, sp - msr cpsr_cxsf, #0xDF @ Disable all interrupts, system mode + msr cpsr, #0xDF @ Disable all interrupts, system mode bl deinitCpu mov r0, r4 mov sp, r5 mov r1, r5 - b guruMeditation @ r0 = exception type, r1 = reg dump ptr {cpsr, pc (unmodified), r0-r14} + b guruMeditation @ r0 = exception type, r1 = reg dump ptr {r0-r14, pc (unmodified), cpsr} ASM_FUNC irqHandler @@ -50,7 +60,15 @@ rsb r2, r0, #31 @ r2 = 31 - r0 ldr r1, =irqHandlerTable ldr r0, [r1, r2, lsl #2] + mrs r2, spsr + str r2, [sp, #-4]! + msr cpsr_c, #0x5F @ Interrupts enabled, system mode + str lr, [sp, #-4]! cmp r0, #0 blxne r0 + ldr lr, [sp], #4 + msr cpsr_c, #0xD2 @ Interrupts disabled, IRQ mode + ldr r2, [sp], #4 + msr spsr, r2 ldmfd sp!, {r0-r3, r12, lr} subs pc, lr, #4 diff --git a/source/arm9/main.c b/source/arm9/main.c index 93ee530..f49858a 100644 --- a/source/arm9/main.c +++ b/source/arm9/main.c @@ -101,7 +101,7 @@ enter_menu(MENU_STATE_MAIN); -finish_firmlaunch: +finish_firmlaunch: uiPrintIfVerbose("Unmounting FS...\n"); diff --git a/source/arm9/start.s b/source/arm9/start.s index 33dc39d..11e83a6 100644 --- a/source/arm9/start.s +++ b/source/arm9/start.s @@ -38,7 +38,7 @@ .word (VERS_MAJOR<<16 | VERS_MINOR) _start: - msr cpsr_cxsf, #0xD3 @ Disable all interrupts, SVC mode + msr cpsr, #0xD3 @ Disable all interrupts, SVC mode @ Control register: @ [19] ITCM load mode : disabled @@ -63,9 +63,13 @@ bl setupExceptionVectors @ Setup the vectors in ARM9 mem bootrom vectors jump to mov sp, #0 @ SVC mode sp (Unused, aborts) - msr cpsr_cxsf, #0xD2 @ IRQ mode + msr cpsr, #0xD7 @ Abort mode + mov sp, #A9_EXC_STACK_END + msr cpsr, #0xDB @ Undefined mode + mov sp, #A9_EXC_STACK_END + msr cpsr, #0xD2 @ IRQ mode ldr sp, =A9_IRQ_STACK_END - msr cpsr_cxsf, #0xDF @ System mode + msr cpsr, #0xDF @ System mode ldr sp, =A9_STACK_END bl setupTcms @ Setup and enable DTCM and ITCM