Refactor arm9 exception handling code

This commit is contained in:
TuxSH 2016-05-06 15:45:25 +02:00
parent c6cb97ae30
commit 4340c326dc
2 changed files with 42 additions and 33 deletions

View File

@ -5,12 +5,24 @@
@ This is part of Luma3DS, see LICENSE.txt for details @ This is part of Luma3DS, see LICENSE.txt for details
@ @
.macro GEN_HANDLER name, addr_offset .macro GEN_HANDLER name
.global \name .global \name
.type \name, %function .type \name, %function
\name: \name:
stmfd sp!, {r0-r7} @ FIQ has its own r8-r14 regs stmfd sp!, {r0-r7} @ FIQ has its own r8-r14 regs
ldr r0, =\addr_offset 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 sub r0, lr, r0 @ address of instruction that triggered the exception; we will handle the undef+Thumb case later
mrs r2, spsr mrs r2, spsr
@ -25,23 +37,15 @@
msr cpsr_c, r3 @ restore processor mode msr cpsr_c, r3 @ restore processor mode
mov sp, r6 mov sp, r6
stmfd sp!, {r0,r2} @ it's a bit of a mess, but we will fix that later stmfd sp!, {r2,lr} @ it's a bit of a mess, but we will fix that later
@ order of regs now: pc, spsr, r8-r14, r0-r7 @ order of saved regs now: cpsr, pc + (2/4/8), r8-r14, r0-r7
mov r0, sp mov r0, sp
ldr r1, =\@ @ macro expansion counter
b mainHandler b mainHandler
.size \name, . - \name GEN_HANDLER FIQHandler
.endm GEN_HANDLER undefinedInstructionHandler
GEN_HANDLER prefetchAbortHandler
.text GEN_HANDLER dataAbortHandler
.arm
.align 4
GEN_HANDLER FIQHandler, 4
GEN_HANDLER undefinedInstructionHandler, 4
GEN_HANDLER prefetchAbortHandler, 4
GEN_HANDLER dataAbortHandler, 8
.global setupStack .global setupStack
.type setupStack, %function .type setupStack, %function

View File

@ -9,32 +9,37 @@
#include "i2c.h" #include "i2c.h"
#include "handlers.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 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 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) 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[0] = 0xDEADC0DE; //Magic
dump[1] = 0xDEADCAFE; //Magic dump[1] = 0xDEADCAFE; //Magic
dump[2] = (1 << 16) | 0; //Dump format version number dump[2] = (1 << 16) | 0; //Dump format version number
dump[3] = 9; //Processor dump[3] = 9; //Processor
dump[4] = type; //Exception type dump[4] = type; //Exception type
dump[6] = 4 * 17; //Register dump size (r0-r12, sp, lr, pc, cpsr) dump[6] = REG_DUMP_SIZE; //Register dump size (r0-r12, sp, lr, pc, cpsr)
dump[7] = 40; //Code dump size (10 ARM instructions, up to 20 Thumb instructions). 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[8] = STACK_DUMP_SIZE; //Stack dump size
dump[9] = 0; //Other data size dump[9] = OTHER_DATA_SIZE; //Other data size
dump[5] = 40 + dump[6] + dump[7] + dump[8] + dump[9]; //Total size dump[5] = sizeof(dump); //Total size
//Dump registers //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; vu32 *regdump = dump + 10;
u32 cpsr = regs[1]; u32 cpsr = regs[0];
u32 pc = regs[0] + (((cpsr & 0x20) != 0 && type == 1) ? 2 : 0); u32 pc = regs[1] - ((type < 3) ? (((cpsr & 0x20) != 0 && type == 1) ? 2 : 4) : 8);
regdump[15] = pc; regdump[15] = pc;
regdump[16] = cpsr; regdump[16] = cpsr;
@ -60,7 +65,7 @@ void __attribute__((noreturn)) mainHandler(u32 regs[17], u32 type)
stackdump[i] = sp[i]; stackdump[i] = sp[i];
vu32 *final = (u32 *)FINAL_BUFFER; 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]; final[i] = dump[i];
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2); //Reboot i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2); //Reboot