diff --git a/arm11/Makefile b/arm11/Makefile index a47d520..c7ed07b 100644 --- a/arm11/Makefile +++ b/arm11/Makefile @@ -5,7 +5,7 @@ TARGET := $(shell basename $(CURDIR)) SOURCE := source BUILD := build -SUBARCH := -D$(PROCESSOR) -mcpu=mpcore -mtune=mpcore -mfloat-abi=soft -marm +SUBARCH := -D$(PROCESSOR) -marm -march=armv6k -mtune=mpcore -mfloat-abi=hard -mfpu=vfpv2 -mtp=soft INCDIRS := source INCLUDE := $(foreach dir,$(INCDIRS),-I"$(shell pwd)/$(dir)") diff --git a/arm11/source/boot.s b/arm11/source/boot.s index 0698330..4cb35d2 100644 --- a/arm11/source/boot.s +++ b/arm11/source/boot.s @@ -25,7 +25,8 @@ .global __boot __boot: - cpsid aif, #SR_SVC_MODE + cpsid aif, #SR_SVC_MODE + clrex @ Writeback and invalidate all DCache @ Invalidate all caches @@ -44,6 +45,18 @@ __boot: mcr p15, 0, r1, c1, c0, 1 mcr p15, 0, r2, c1, c0, 2 + @ VFPv2 init + @ https://github.com/derrekr/fastboot3DS/blob/f63c967369451b1fd0078e649cf0010fe10a62fd/source/arm11/start.s#L195 + mov r0, #0 + mov r1, #0xF00000 @ Give full access to cp10/11 in user and privileged mode + mov r2, #0x40000000 @ Clear exception bits and enable VFP11 + mov r3, #0x3C00000 @ Round towards zero (RZ) mode, flush-to-zero mode, default NaN mode + mcr p15, 0, r1, c1, c0, 2 @ Write Coprocessor Access Control Register + mcr p15, 0, r0, c7, c5, 4 @ Flush Prefetch Buffer + fmxr fpexc, r2 @ Write Floating-point exception register + fmxr fpscr, r3 @ Write Floating-Point Status and Control Register + + @ Get CPU ID mrc p15, 0, r12, c0, c0, 5 ands r12, r12, #3 diff --git a/arm9/Makefile b/arm9/Makefile index ea19d7d..9bed11d 100644 --- a/arm9/Makefile +++ b/arm9/Makefile @@ -5,7 +5,7 @@ TARGET := $(shell basename $(CURDIR)) SOURCE := source BUILD := build -SUBARCH := -D$(PROCESSOR) -mcpu=arm946e-s -mtune=arm946e-s -mfloat-abi=soft -mno-thumb-interwork -marm +SUBARCH := -D$(PROCESSOR) -marm -march=armv5te -mtune=arm946e-s -mfloat-abi=soft -mno-thumb-interwork INCDIRS := source source/common source/filesys source/crypto source/fatfs source/nand source/virtual source/game source/gamecart source/lodepng source/qrcodegen source/system source/utils INCLUDE := $(foreach dir,$(INCDIRS),-I"$(shell pwd)/$(dir)") diff --git a/arm9/link.ld b/arm9/link.ld index e6df812..e9f0a08 100644 --- a/arm9/link.ld +++ b/arm9/link.ld @@ -2,19 +2,46 @@ OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") OUTPUT_ARCH(arm) ENTRY(_start) +MEMORY +{ + AHBWRAM (RWX) : ORIGIN = 0x08006000, LENGTH = 512K + VECTORS (RX) : ORIGIN = 0x08000000, LENGTH = 64 +} + SECTIONS { - . = 0x08006000; - __start__ = ABSOLUTE(.); + .vectors : ALIGN(4) { + __vectors_lma = LOADADDR(.vectors); + __vectors_vma = ABSOLUTE(.); + KEEP(*(.vectors)); + . = ALIGN(4); + __vectors_len = ABSOLUTE(.) - __vectors_vma; + } >VECTORS AT>AHBWRAM - .text.start : ALIGN(4) { *(.text.start) } - .text : ALIGN(4) { *(.text*) } - .rodata : ALIGN(4) { *(.rodata*) } - .data : ALIGN(4) { *(.data*) } - .bss : ALIGN(4) { __bss_start = .; *(.bss* COMMON); __bss_end = .;} + .text : ALIGN(4) { + __text_s = ABSOLUTE(.); + *(.text.start); + *(.text*); + . = ALIGN(4); + __text_e = ABSOLUTE(.); + } >AHBWRAM - . = ALIGN(4); + .rodata : ALIGN(4) { + *(.rodata*); + . = ALIGN(4); + } >AHBWRAM + + .data : ALIGN(4) { + *(.data*); + . = ALIGN(4); + } >AHBWRAM + + .bss : ALIGN(4) { + __bss_start = .; + *(.bss*); + . = ALIGN(4); + __bss_end = .; + } >AHBWRAM __end__ = ABSOLUTE(.); - __code_size__ = __end__ - __start__; } diff --git a/arm9/source/start.s b/arm9/source/start.s index 8304f7a..7d3fc05 100644 --- a/arm9/source/start.s +++ b/arm9/source/start.s @@ -32,18 +32,18 @@ _start: ldr r0, =BRF_INVALIDATE_ICACHE blx r0 @ Invalidate Instruction Cache - @ Disable caches / DTCM / MPU - ldr r1, =(CR_MPU | CR_CACHES | CR_DTCM | CR_TCM_LOAD) - ldr r2, =(CR_ITCM) + @ Disable caches / TCMs / MPU + ldr r1, =(CR_MPU | CR_CACHES | CR_DTCM | CR_ITCM | CR_TCM_LOAD) mrc p15, 0, r0, c1, c0, 0 bic r0, r1 - orr r0, r2 mcr p15, 0, r0, c1, c0, 0 - @ Give full access to defined memory regions - ldr r0, =0x33333333 - mcr p15, 0, r0, c5, c0, 2 @ write data access - mcr p15, 0, r0, c5, c0, 3 @ write instruction access + @ Set access permissions + ldr r0, =0x11111115 @ RO data access for BootROM, RW otherwise + ldr r1, =0x00505005 @ Can only execute code from ARM9 RAM, FCRAM and BootROM + + mcr p15, 0, r0, c5, c0, 2 + mcr p15, 0, r1, c5, c0, 3 @ Set MPU regions and cache settings ldr r0, =__mpu_regions @@ -64,15 +64,12 @@ _start: mcr p15, 0, r0, c2, c0, 0 @ Data cacheable mcr p15, 0, r0, c2, c0, 1 @ Inst cacheable - @ Enable DTCM + @ Configure TCMs ldr r0, =0x3000800A - mcr p15, 0, r0, c9, c1, 0 @ set the DTCM Region Register + ldr r1, =0x00000024 + mcr p15, 0, r0, c9, c1, 0 @ DTCM + mcr p15, 0, r1, c9, c1, 1 @ ITCM - @ Fix SDMC mounting - @ (this is done in sdmmc.c instead) - @ mov r0, #0x10000000 - @ mov r1, #0x340 - @ strh r1, [r0, #0x20] @ Setup heap ldr r0, =fake_heap_start @@ -84,18 +81,18 @@ _start: str r1, [r0] @ Install exception handlers - ldr r0, =XRQ_Start - ldr r1, =XRQ_End - ldr r2, =0x00000000 + ldr r0, =__vectors_lma + ldr r1, =__vectors_len + ldr r2, =XRQ_Start + add r1, r0, r1 .LXRQ_Install: cmp r0, r1 ldrlo r3, [r0], #4 strlo r3, [r2], #4 blo .LXRQ_Install - @ Enable caches / DTCM / select low exception vectors - ldr r1, =(CR_ALT_VECTORS | CR_V4TLD) - ldr r2, =(CR_MPU | CR_CACHES | CR_DTCM) + @ Enable caches / TCMs / select high exception vectors + ldr r2, =(CR_MPU | CR_CACHES | CR_ITCM | CR_DTCM | CR_ALT_VECTORS) mrc p15, 0, r0, c1, c0, 0 bic r0, r1 orr r0, r2 @@ -162,7 +159,7 @@ _start: __mpu_regions: .word 0xFFFF001F @ FFFF0000 64k | bootrom (unprotected / protected) .word 0x3000801B @ 30008000 16k | dtcm - .word 0x00000035 @ 00000000 128M | itcm (+ mirrors) + .word 0x01FF8035 @ 01FF8000 32k | itcm (+ mirrors) .word 0x08000029 @ 08000000 2M | arm9 mem (O3DS / N3DS) .word 0x10000029 @ 10000000 2M | io mem (ARM9 / first 2MB) .word 0x20000037 @ 20000000 256M | fcram (O3DS / N3DS) diff --git a/arm9/source/system/xrq.c b/arm9/source/system/xrq.c index 8e977f7..0f60100 100644 --- a/arm9/source/system/xrq.c +++ b/arm9/source/system/xrq.c @@ -15,23 +15,45 @@ #include -#define PC_DUMPRAD (0x30) -#define SP_DUMPLEN (0x60) +#define PC_DUMPRAD (0x40) +#define SP_DUMPLEN (0x30) +extern u32 __text_s, __text_e; + +static bool sp_dumpable(u32 sp, u32 *sp_lower, u32 *sp_upper) +{ + if ((sp >= __STACK_TOP) || (sp < (__STACK_TOP - __STACK_LEN))) + return false; + *sp_lower = sp; + *sp_upper = min(sp + SP_DUMPLEN, __STACK_TOP); + return true; +} + +static bool pc_dumpable(u32 pc, u32 *pc_lower, u32 *pc_upper) +{ + u32 code_start = (u32)(&__text_s), code_end = (u32)(&__text_e); + + if ((pc >= code_end) || (pc < code_start)) + return false; + + *pc_lower = max(pc - PC_DUMPRAD, code_start); + *pc_upper = min(pc + PC_DUMPRAD, code_end); + return true; +} #define XRQ_DUMPDATAFUNC(type, size) \ -int XRQ_DumpData_##type(char *b, u32 s, u32 e) \ +static unsigned XRQ_DumpData_##type(char *b, u32 s, u32 e) \ { \ char *c = b; \ while(s #include #include "memmap.h" -.macro XRQ_FATAL id=0 - ldr sp, =__STACK_ABT_TOP - sub sp, sp, #(18*4) @ Reserve space for registers - stmia sp, {r0-r12} - mov r11, #\id - b XRQ_MainHandler +.macro TRAP_ENTRY xrq_id + msr cpsr_f, #(\xrq_id << 29) @ preserve xrq id (idea grabbed from fb3ds) .endm +.section .vectors, "ax" .global XRQ_Start XRQ_Start: -XRQ_Vectors: - b XRQ_Reset - b XRQ_Undefined - b XRQ_SWI - b XRQ_PAbort - b XRQ_DAbort - b . @ Reserved exception vector - subs pc, lr, #4 @ IRQs are unhandled - b . @ FIQs are unused (except for debug?) + ldr pc, IRQ_Vector + IRQ_Vector: .word IRQ_Handler + ldr pc, FIQ_Vector + FIQ_Vector: .word FIQ_Handler + ldr pc, SVC_Vector + SVC_Vector: .word SVC_Handler + ldr pc, UND_Vector + UND_Vector: .word UND_Handler + ldr pc, PABT_Vector + PABT_Vector: .word PABT_Handler + ldr pc, DABT_Vector + DABT_Vector: .word DABT_Handler +.global XRQ_End +XRQ_End: -XRQ_Reset: - msr cpsr_c, #(SR_ABT_MODE | SR_NOINT) - XRQ_FATAL 0 -XRQ_Undefined: - XRQ_FATAL 1 +.section .text.xrqs +IRQ_Handler: + TRAP_ENTRY 6 + b XRQ_Fatal -XRQ_SWI: - XRQ_FATAL 2 +FIQ_Handler: + TRAP_ENTRY 7 + b XRQ_Fatal -XRQ_PAbort: - XRQ_FATAL 3 +SVC_Handler: + TRAP_ENTRY 2 + b XRQ_Fatal -XRQ_DAbort: - XRQ_FATAL 4 +UND_Handler: + TRAP_ENTRY 1 + b XRQ_Fatal -@ r11 = exception number -XRQ_MainHandler: - mrs r10, cpsr - mrs r9, spsr - mov r8, lr +PABT_Handler: + TRAP_ENTRY 3 + b XRQ_Fatal - @ Disable mpu / caches - ldr r4, =BRF_WB_INV_DCACHE - ldr r5, =BRF_INVALIDATE_ICACHE - ldr r6, =BRF_RESETCP15 - blx r4 - blx r5 - blx r6 +DABT_Handler: + sub lr, lr, #4 @ R14_abt = PC + 8, so it needs a small additional fixup + TRAP_ENTRY 4 + @b XRQ_Fatal - @ Retrieve banked registers - ands r0, r9, #(SR_PMODE_MASK & (0x0F)) - orreq r0, #(SR_SYS_MODE) - orr r0, #(0x10 | SR_NOINT) +XRQ_Fatal: + sub lr, lr, #4 @ PC exception fixup - msr cpsr_c, r0 @ Switch to previous mode - mov r0, sp - mov r1, lr - msr cpsr_c, r10 @ Return to abort + ldr sp, =(__STACK_ABT_TOP - 18*4) @ Set up abort stack, 8 byte aligned + stmia sp, {r0-r7} @ Preserve non-banked GPRs - add r2, sp, #(13*4) - stmia r2, {r0, r1, r8, r9} + mrs r1, cpsr + orr r0, r1, #SR_NOINT + msr cpsr_c, r0 @ Disable interrupts - @ Give read/write access to all the memory regions - ldr r0, =0x33333333 - mcr p15, 0, r0, c5, c0, 2 @ write data access - mcr p15, 0, r0, c5, c0, 3 @ write instruction access + lsr r0, r1, #29 @ Retrieve exception source - @ Sets MPU regions and cache settings - adr r0, __abt_mpu_regions - ldmia r0, {r1-r8} - mov r0, #0b00110010 @ bootrom, arm9 mem and fcram are cacheable/bufferable - mcr p15, 0, r1, c6, c0, 0 - mcr p15, 0, r2, c6, c1, 0 - mcr p15, 0, r3, c6, c2, 0 - mcr p15, 0, r4, c6, c3, 0 - mcr p15, 0, r5, c6, c4, 0 - mcr p15, 0, r6, c6, c5, 0 - mcr p15, 0, r7, c6, c6, 0 - mcr p15, 0, r8, c6, c7, 0 - mcr p15, 0, r0, c3, c0, 0 @ Write bufferable 0, 2, 5 - mcr p15, 0, r0, c2, c0, 0 @ Data cacheable 0, 2, 5 - mcr p15, 0, r0, c2, c0, 1 @ Inst cacheable 0, 2, 5 + mrs r2, spsr + str lr, [sp, #15*4] + str r2, [sp, #16*4] @ Preserve exception PC and CPSR - @ Enable mpu/caches - ldr r1, =(CR_MPU | CR_CACHES | CR_DTCM) - mrc p15, 0, r0, c1, c0, 0 - orr r0, r0, r1 - mcr p15, 0, r0, c1, c0, 0 + ands r2, r2, #SR_PMODE_MASK + orreq r2, r2, #SR_SYS_MODE @ Force a switch to system mode if + @ the exception happened in user mode + orr r2, r2, #(0x10 | SR_NOINT) @ With interrupts disabled + + add r3, sp, #8*4 + msr cpsr_c, r2 + nop + nop + stmia r3, {r8-r14} @ Preserve banked GPRs (R8-R12, SP_xrq, LR_xrq) + nop + nop + msr cpsr_c, r1 - ldr r2, =XRQ_DumpRegisters @ void XRQ_DumpRegisters(u32 xrq_id, u32 *regs) mov r1, sp - mov r0, r11 - blx r2 + bl XRQ_DumpRegisters @ XRQ_DumpRegisters(exception_number, saved_regs); - msr cpsr, #(SR_SVC_MODE | SR_NOINT) mov r0, #0 1: mcr p15, 0, r0, c7, c0, 4 b 1b - -.pool - -__abt_mpu_regions: - .word 0x0000003F @ 00000000 4G | background region (includes IO regs) - .word 0xFFFF001F @ FFFF0000 64k | bootrom (unprotected / protected) - .word 0x3000801B @ 30008000 16k | dtcm - .word 0x00000035 @ 00000000 128M | itcm - .word 0x08000029 @ 08000000 2M | arm9 mem (O3DS / N3DS) - .word 0x20000037 @ 20000000 256M | fcram (O3DS / N3DS) - .word 0x1FF00027 @ 1FF00000 1M | dsp / axi wram - .word 0x1800002D @ 18000000 8M | vram (+ 2MB) - -.global XRQ_End -XRQ_End: