]> Chaos Git - corbenik/corbenik.git/commitdiff
Fix up start.s for libctr9_io exception handling
authorchaoskagami <chaos.kagami@gmail.com>
Fri, 15 Jul 2016 04:11:22 +0000 (00:11 -0400)
committerchaoskagami <chaos.kagami@gmail.com>
Fri, 15 Jul 2016 04:11:22 +0000 (00:11 -0400)
linker.ld
source/start.s

index 802a17dba2cd163ada2015274fda90e6ad132feb..aba1eaada27fc1b868083c3d1c759cc0271969e0 100644 (file)
--- a/linker.ld
+++ b/linker.ld
@@ -1,37 +1,31 @@
+OUTPUT_ARCH(arm)
 ENTRY(_start)
 SECTIONS
 {
     . = 0x23F00000;
 
-    START_SECTION = .;
-      .text.start : {
-          *(.text.start)
-      }
-    START_SECTION_END = .;
+    .text.start : {
+        *(.text.start)
+    }
 
-    TEXT_SECTION = .;
-      .text : {
-          *(.text)
-      }
-    TEXT_SECTION_END = .;
+    .text : {
+        *(.text)
+    }
 
-    DATA_SECTION = .;
-      .data : {
-          *(.data)
-      }
-    DATA_SECTION_END = .;
+    .data : {
+        *(.data)
+    }
 
-    BSS_SECTION = .;
-      .bss : {
-          *(.bss COMMON)
-      }
-    BSS_SECTION_END = .;
+    .bss : {
+        __bss_start = .;
+        *(.bss COMMON)
+    }
+    __bss_end = .;
 
-    RODATA_SECTION = .;
-      .rodata : {
-          *(.rodata)
-      }
-    RODATA_SECTION_END = .;
+    .rodata : {
+        *(.rodata)
+    }
 
     . = ALIGN(4);
+    __end__ = 0x20400000;
 }
index 04e29d199ff0c728e86ce518bd1d6709b04910d6..659380558e0463f4088ef874a4384522e49b4c81 100644 (file)
@@ -1,6 +1,6 @@
-.section .text.start
 .align 4
 .global _start
+.section .text.start, "x"
 _start:
     ldr r2, =argc
     str r0, [r2]
@@ -8,74 +8,249 @@ _start:
     ldr r2, =argv
     str r1, [r2]
 
-    b mpu
+    b init
 
 argc: .int 0x00000000
 argv: .int 0x00000000
 
-mpu:
-    // Change the stack pointer
-    mov sp, #0x27000000
-
-    // Disable caches / mpu
-    mrc p15, 0, r4, c1, c0, 0  // read control register
-    bic r4, #(1<<12)           // - instruction cache disable
-    bic r4, #(1<<2)            // - data cache disable
-    bic r4, #(1<<0)            // - mpu disable
-    mcr p15, 0, r4, c1, c0, 0  // write control register
-
-    // Give read/write access to all the memory regions
-    ldr r5, =0x33333333
-    mcr p15, 0, r5, c5, c0, 2 // write data access
-    mcr p15, 0, r5, c5, c0, 3 // write instruction access
-
-    // Sets MPU permissions and cache settings
-    ldr r0, =0xFFFF001D        // ffff0000 32k
-    ldr r1, =0x01FF801D        // 01ff8000 32k
-    ldr r2, =0x08000027        // 08000000 1M
-    ldr r3, =0x10000021        // 10000000 128k
-    ldr r4, =0x10100025        // 10100000 512k
-    ldr r5, =0x20000035        // 20000000 128M
-    ldr r6, =0x1FF00027        // 1FF00000 1M
-    ldr r7, =0x1800002D        // 18000000 8M
-    mov r10, #0x25
-    mov r11, #0x25
-    mov r12, #0x25
-    mcr p15, 0, r0, c6, c0, 0
-    mcr p15, 0, r1, c6, c1, 0
-    mcr p15, 0, r2, c6, c2, 0
-    mcr p15, 0, r3, c6, c3, 0
-    mcr p15, 0, r4, c6, c4, 0
-    mcr p15, 0, r5, c6, c5, 0
-    mcr p15, 0, r6, c6, c6, 0
-    mcr p15, 0, r7, c6, c7, 0
-    mcr p15, 0, r10, c3, c0, 0 // Write bufferable 0, 2, 5
-    mcr p15, 0, r11, c2, c0, 0 // Data cacheable 0, 2, 5
-    mcr p15, 0, r12, c2, c0, 1 // Inst cacheable 0, 2, 5
-
-    // Enable caches
-    mrc p15, 0, r4, c1, c0, 0  // read control register
-    orr r4, r4, #(1<<18)       // - itcm enable
-    orr r4, r4, #(1<<12)       // - instruction cache enable
-    orr r4, r4, #(1<<2)        // - data cache enable
-    orr r4, r4, #(1<<0)        // - mpu enable
-    mcr p15, 0, r4, c1, c0, 0  // write control register
-
-    // Flush caches
-    mov r5, #0
-    mcr p15, 0, r5, c7, c5, 0  // flush I-cache
-    mcr p15, 0, r5, c7, c6, 0  // flush D-cache
-    mcr p15, 0, r5, c7, c10, 4 // drain write buffer
-
-    // Fixes mounting of SDMC
+init:
+       // Disable IRQ
+       mrs r0, cpsr
+       orr r0, r0, #0x80
+       msr cpsr_c, r0
+
+       // Flush caches, make sure to sync memory with what's on the cache before
+       // turning off the MPU
+       adr r0, flush_all_caches_offset
+       ldr r1, [r0]
+       add r0, r1, r0
+       blx r0
+
+       // Disable caches and MPU
+       adr r0, disable_mpu_and_caching_offset
+       ldr r1, [r0]
+       add r0, r1, r0
+       blx r0
+
+       // Flush caches, for good measure. Makes sure there is nothing in the caches
+       // when the MPU is brought back online.
+       adr r0, flush_all_caches_offset
+       ldr r1, [r0]
+       add r0, r1, r0
+       blx r0
+
+       // FIXME should we attempt to save the last stack?
+       // Setup stacks
+       adr r0, setup_stacks_offset
+       ldr r1, [r0]
+       add r0, r1, r0
+       blx r0
+
+       // Switch to system mode
+       mrs r0, cpsr
+       orr r1, r0, #0x1F
+       msr cpsr_c, r1
+
+       // Change the stack pointer
+       ldr sp, =0x27F00000
+
+       // make sure ITCM is accessible
+       mrc p15, 0, r0, c1, c0, 0
+       orr r0, r0, #(1<<18)
+       mcr p15, 0, r0, c1, c0, 0
+
+       // clear bss
+       adr r0, clear_bss_offset
+       ldr r1, [r0]
+       add r0, r1, r0
+       blx r0
+
+       // 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
+
+       // Set MPU permissions and cache settings
+       ldr r0, =0xFFFF001D // ffff0000 32k   | bootrom unprotected
+       ldr r1, =0x3000801B // 30000000 16k   | dtcm
+       ldr r2, =0x00000035 // 00000000 128MB | itcm
+       ldr r3, =0x08000029 // 08000000 2M    | arm9 mem
+       ldr r4, =0x10000029 // 10000000 2M    | io mem
+       ldr r5, =0x20000037 // 20000000 256M  | fcram
+       ldr r6, =0x1FF00027 // 1FF00000 1M
+       ldr r7, =0x1800002D // 18000000 8M
+       mcr p15, 0, r0, c6, c0, 0
+       mcr p15, 0, r1, c6, c1, 0
+       mcr p15, 0, r2, c6, c2, 0
+       mcr p15, 0, r3, c6, c3, 0
+       mcr p15, 0, r4, c6, c4, 0
+       mcr p15, 0, r5, c6, c5, 0
+       mcr p15, 0, r6, c6, c6, 0
+       mcr p15, 0, r7, c6, c7, 0
+       mov r0, #0xA5 // FIXME which sections does this do... stuff to?
+       mcr p15, 0, r0, c2, c0, 0  // data cacheable
+       mcr p15, 0, r0, c2, c0, 1  // instruction cacheable
+       mcr p15, 0, r0, c3, c0, 0  // data bufferable
+
+       // Enable caches and MPU
+       adr r0, enable_mpu_and_caching_offset
+       ldr r1, [r0]
+       add r0, r1, r0
+       blx r0
+
+       // Fix mounting of SDMC
        ldr r0, =0x10000020
        mov r1, #0x340
        str r1, [r0]
 
+       // Reload argc and argv.
     ldr r0, argc
     ldr r1, argv
 
-    bl main
+       // Launch main(argc, argv)
+       adr r2, main_offset
+       ldr r3, [r2]
+       add r2, r3, r2
+       blx r2
+       bx lr
+
+       die:
+       b die //if we return, just forcibly hang (should we attempt to call the rest vector???)
+
+disable_mpu_and_caching_offset:
+.word disable_mpu_and_caching-.
+
+enable_mpu_and_caching_offset:
+.word enable_mpu_and_caching-.
+
+relocate_section_offset:
+.word relocate_section-.
+
+flush_all_caches_offset:
+.word flush_all_caches-.
+
+setup_stacks_offset:
+.word setup_stacks-.
+
+__bss_start_offset:
+.word __bss_start-.
+
+__bss_end_offset:
+.word __bss_end-.
+
+clear_bss_offset:
+.word clear_bss-.
+
+main_offset:
+.word main-.
+
+clear_bss:
+       //clear bss
+       adr r0, __bss_start_offset
+       ldr r1, [r0]
+       add r0, r1, r0
+
+       adr r1, __bss_end_offset
+       ldr r2, [r1]
+       add r1, r2, r1
+       mov r2, #0
+       .Lclear_bss_loop:
+               cmp r0, r1
+               beq .Lclear_bss_loop_done
+               str r2, [r0], #4
+               b .Lclear_bss_loop
+       .Lclear_bss_loop_done:
+       blx lr
+
+setup_stacks:
+       // Set up the stacks for all CPU modes
+       // start by clearing mode bits
+       mrs r0, cpsr
+       mov r2, r0 // preserve current mode
+       bic r0, r0, #0x1F
+
+       // System mode
+       orr r1, r0, #0x1F
+       msr cpsr_c, r1
+       ldr sp, =0x8000
+
+       // Abort mode
+       orr r1, r0, #0x17
+       msr cpsr_c, r1
+       ldr sp, =0x8000
+
+       // IRQ mode
+       orr r1, r0, #0x12
+       msr cpsr_c, r1
+       ldr sp, =0x8000
+
+       // FIQ mode
+       orr r1, r0, #0x11
+       msr cpsr_c, r1
+       ldr sp, =0x8000
+
+       // Supervisor mode
+       orr r1, r0, #0x13
+       msr cpsr_c, r1
+       ldr sp, =0x8000
+
+       // Restore prvious mode
+       msr cpsr_c, r2
+
+       blx lr
+
+disable_mpu_and_caching:
+       // Disable caches and MPU
+       mrc p15, 0, r0, c1, c0, 0  // read control register
+       bic r0, r0, #(1<<12)       // - instruction cache enable
+       bic r0, r0, #(1<<2)             // - data cache enable
+       bic r0, r0, #(1<<0)             // - mpu enable
+       mcr p15, 0, r0, c1, c0, 0  // write control register
+
+       bx lr
+
+enable_mpu_and_caching:
+       // Enable caches and MPU
+       mrc p15, 0, r0, c1, c0, 0  // read control register
+       orr r0, r0, #(1<<12)       // - instruction cache enable
+       orr r0, r0, #(1<<2)             // - data cache enable
+       orr r0, r0, #(1<<0)             // - mpu enable
+       mcr p15, 0, r0, c1, c0, 0  // write control register
+
+       bx lr
+
+// r0 - region start
+// r1 - region end
+// r2 - relocation base (usually starting PC address)
+relocate_section:
+
+       adr r2, relocation_base_offset
+       ldr r3, [r2]
+       add r2, r3, r2
+
+       .Lreloc_init:
+       cmp r0, r1
+       beq .Lrelocinit_done
+       ldr r3, [r0]
+       add r3, r2, r3
+       str r3, [r0], #4
+       b .Lreloc_init
+       .Lrelocinit_done:
+
+       bx lr
+
+relocation_base_offset:
+.word _start-.
+
+flush_all_caches:
+
+       // flush instruction cache, it's not flushed by Nintendo's function
+       mov r0, #0
+       mcr p15, 0, r0, c7, c5, 0
+
+       // Nintendo's function uses r0-r2, r12, all registers that don't need
+       // to be saved, just be aware that they are changed
+       // use Nintendo's bx lr to return
+       ldr r0, =0xFFFF0830 // Nintendo's flush function in unprot. bootrom
+       bx r0
 
-.die:
-    b .die