diff --git a/exceptions/arm9/source/handlers.s b/exceptions/arm9/source/handlers.s index 14643b6..d999317 100644 --- a/exceptions/arm9/source/handlers.s +++ b/exceptions/arm9/source/handlers.s @@ -5,12 +5,24 @@ @ This is part of Luma3DS, see LICENSE.txt for details @ -.macro GEN_HANDLER name, addr_offset +.macro GEN_HANDLER name .global \name .type \name, %function -\name: - stmfd sp!, {r0-r7} @ FIQ has its own r8-r14 regs - ldr r0, =\addr_offset + \name: + stmfd sp!, {r0-r7} @ FIQ has its own r8-r14 regs + ldr r1, =\@ @ macro expansion counter + b _commonHandler + + .size \name, . - \name +.endm + +.text +.arm +.align 4 + +.global _commonHandler +.type _commonHandler, %function +_commonHandler: sub r0, lr, r0 @ address of instruction that triggered the exception; we will handle the undef+Thumb case later mrs r2, spsr @@ -25,26 +37,18 @@ msr cpsr_c, r3 @ restore processor mode mov sp, r6 - stmfd sp!, {r0,r2} @ it's a bit of a mess, but we will fix that later - @ order of regs now: pc, spsr, r8-r14, r0-r7 + stmfd sp!, {r2,lr} @ it's a bit of a mess, but we will fix that later + @ order of saved regs now: cpsr, pc + (2/4/8), r8-r14, r0-r7 mov r0, sp - ldr r1, =\@ @ macro expansion counter b mainHandler - .size \name, . - \name -.endm - -.text -.arm -.align 4 - - GEN_HANDLER FIQHandler, 4 - GEN_HANDLER undefinedInstructionHandler, 4 - GEN_HANDLER prefetchAbortHandler, 4 - GEN_HANDLER dataAbortHandler, 8 +GEN_HANDLER FIQHandler +GEN_HANDLER undefinedInstructionHandler +GEN_HANDLER prefetchAbortHandler +GEN_HANDLER dataAbortHandler .global setupStack -.type setupStack, %function +.type setupStack, %function setupStack: cmp r0, #0 moveq r0, #0xf @ usr => sys diff --git a/exceptions/arm9/source/main.c b/exceptions/arm9/source/main.c index 9639baf..a1a6f02 100644 --- a/exceptions/arm9/source/main.c +++ b/exceptions/arm9/source/main.c @@ -9,32 +9,37 @@ #include "i2c.h" #include "handlers.h" -#define TEMP_BUFFER 0x1FF80000 //We choose AXIWRAM as tmp buffer since it's usually ARM11 payloads running there #define FINAL_BUFFER 0x25000000 +#define SP ((void *)0x02000000) //We make the (full descending) stack point to the end of ITCM for our exception handlers. + //It doesn't matter if we're overwriting stuff, since we're going to reboot. + +#define REG_DUMP_SIZE (4*17) +#define CODE_DUMP_SIZE 48 #define STACK_DUMP_SIZE 0x2000 -#define SP ((void *)(TEMP_BUFFER + 4 * STACK_DUMP_SIZE)) +#define OTHER_DATA_SIZE 0 void __attribute__((noreturn)) mainHandler(u32 regs[17], u32 type) { - vu32 *dump = (u32 *)TEMP_BUFFER; - + //vu32 *dump = (u32 *)TEMP_BUFFER; + u32 dump[(40 + REG_DUMP_SIZE + CODE_DUMP_SIZE + STACK_DUMP_SIZE + OTHER_DATA_SIZE) / 4]; + dump[0] = 0xDEADC0DE; //Magic dump[1] = 0xDEADCAFE; //Magic dump[2] = (1 << 16) | 0; //Dump format version number dump[3] = 9; //Processor dump[4] = type; //Exception type - dump[6] = 4 * 17; //Register dump size (r0-r12, sp, lr, pc, cpsr) - dump[7] = 40; //Code dump size (10 ARM instructions, up to 20 Thumb instructions). + dump[6] = REG_DUMP_SIZE; //Register dump size (r0-r12, sp, lr, pc, cpsr) + dump[7] = CODE_DUMP_SIZE; //Code dump size (10 ARM instructions, up to 20 Thumb instructions). dump[8] = STACK_DUMP_SIZE; //Stack dump size - dump[9] = 0; //Other data size - dump[5] = 40 + dump[6] + dump[7] + dump[8] + dump[9]; //Total size + dump[9] = OTHER_DATA_SIZE; //Other data size + dump[5] = sizeof(dump); //Total size //Dump registers - //Current order of regs: pc, spsr, r8-r12, sp, lr, r0-r7 + //Current order of saved regs: cpsr, pc, r8-r12, sp, lr, r0-r7 vu32 *regdump = dump + 10; - u32 cpsr = regs[1]; - u32 pc = regs[0] + (((cpsr & 0x20) != 0 && type == 1) ? 2 : 0); + u32 cpsr = regs[0]; + u32 pc = regs[1] - ((type < 3) ? (((cpsr & 0x20) != 0 && type == 1) ? 2 : 4) : 8); regdump[15] = pc; regdump[16] = cpsr; @@ -60,7 +65,7 @@ void __attribute__((noreturn)) mainHandler(u32 regs[17], u32 type) stackdump[i] = sp[i]; vu32 *final = (u32 *)FINAL_BUFFER; - for(u32 i = 0; i < dump[5] / 4; i++) + for(u32 i = 0; i < sizeof(dump) / 4; i++) final[i] = dump[i]; i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2); //Reboot @@ -73,11 +78,11 @@ void main(void) setupStack(7, SP); //Abort setupStack(11, SP); //Undefined - //IRQHandler is at 0x08000000, but we won't handle it for obvious reasons + //IRQHandler is at 0x08000000, but we won't handle it for obvious reasons *(vu32 *)0x08000008 = 0xE51FF004; *(vu32 *)0x0800000C = (u32)FIQHandler; //svcHandler is at 0x08000010, but we won't handle svc either - *(vu32 *)0x08000018 = 0xE51FF004; + *(vu32 *)0x08000018 = 0xE51FF004; *(vu32 *)0x0800001C = (u32)undefinedInstructionHandler; *(vu32 *)0x08000020 = 0xE51FF004; *(vu32 *)0x08000024 = (u32)prefetchAbortHandler;