nuclear@0: @ vi:set filetype=armasm: nuclear@0: .section ".crt0","ax" nuclear@0: .global _start nuclear@0: .align 4 nuclear@0: .arm nuclear@0: _start: nuclear@0: mov r0, #0x04000000 @ IME = 0; nuclear@0: mov r1, #0 nuclear@0: str r1, [r0, #0x208] nuclear@0: nuclear@0: mov r0, #0x12 @ Switch to IRQ Mode nuclear@0: msr cpsr, r0 nuclear@0: ldr sp, =__sp_irq @ Set IRQ stack nuclear@0: nuclear@0: mov r0, #0x13 @ Switch to SVC Mode nuclear@0: msr cpsr, r0 nuclear@0: ldr sp, =__sp_svc @ Set SVC stack nuclear@0: nuclear@0: mov r0, #0x1F @ Switch to System Mode nuclear@0: msr cpsr, r0 nuclear@0: ldr sp, =__sp_usr @ Set user stack nuclear@0: nuclear@0: #ifndef VRAM nuclear@0: adr r1, __sync_start @ Perform ARM7<->ARM9 sync code nuclear@0: ldr r2, =__arm7_start__ nuclear@0: mov r3, #(__sync_end-__sync_start) nuclear@0: mov r8, r2 nuclear@0: bl CopyMem nuclear@0: mov r3, r8 nuclear@0: bl _blx_r3_stub nuclear@0: nuclear@0: @ Copy arm7 binary from LMA to VMA (EWRAM to IWRAM) nuclear@0: adr r0, arm7lma @ Calculate ARM7 LMA nuclear@0: ldr r1, [r0] nuclear@0: add r1, r1, r0 nuclear@0: ldr r2, =__arm7_start__ nuclear@0: ldr r4, =__arm7_end__ nuclear@0: bl CopyMemCheck nuclear@0: nuclear@0: #else nuclear@0: bl __sync_start nuclear@0: #endif nuclear@0: nuclear@0: ldr r0, =__bss_start__ @ Clear BSS section to 0x00 nuclear@0: ldr r1, =__bss_end__ nuclear@0: sub r1, r1, r0 nuclear@0: bl ClearMem nuclear@0: nuclear@0: #ifndef VRAM nuclear@0: cmp r10, #1 nuclear@0: bne NotTWL nuclear@0: ldr r1, =__dsimode @ set DSi mode flag nuclear@0: strb r10, [r1] nuclear@0: nuclear@0: ldr r1, =0x02ffe1d8 @ Get ARM7i LMA from header nuclear@0: ldr r1, [r1] nuclear@0: ldr r2, =__arm7i_start__ nuclear@0: ldr r4, =__arm7i_end__ nuclear@0: bl CopyMemCheck nuclear@0: nuclear@0: ldr r0, =__twl_bss_start__ @ Clear TWL BSS section to 0x00 nuclear@0: ldr r1, =__twl_bss_end__ nuclear@0: sub r1, r1, r0 nuclear@0: bl ClearMem nuclear@0: #endif nuclear@0: nuclear@0: NotTWL: nuclear@0: mov r0, #0 @ int argc nuclear@0: mov r1, #0 @ char *argv[] nuclear@0: ldr r3, =main nuclear@0: mov r12, #0x4000000 @ tell arm9 we are ready nuclear@0: mov r9, #0 nuclear@0: str r9, [r12, #0x180] nuclear@0: _blx_r3_stub: nuclear@0: bx r3 nuclear@0: infloop: nuclear@0: b infloop nuclear@0: nuclear@0: #ifndef VRAM nuclear@0: arm7lma: nuclear@0: .word __arm7_lma__ - . nuclear@0: #endif nuclear@0: .pool nuclear@0: nuclear@0: @--------------------------------------------------------------------------------- nuclear@0: @ ARM7<->ARM9 synchronization code nuclear@0: @--------------------------------------------------------------------------------- nuclear@0: nuclear@0: __sync_start: nuclear@0: push {lr} nuclear@0: mov r12, #0x4000000 nuclear@0: mov r9, #0x0 nuclear@0: bl IPCSync nuclear@0: mov r9, #(0x9<<8) nuclear@0: str r9, [r12, #0x180] nuclear@0: mov r9, #0xA nuclear@0: bl IPCSync nuclear@0: mov r9, #(0xB<<8) nuclear@0: str r9, [r12, #0x180] nuclear@0: mov r9, #0xC nuclear@0: bl IPCSync nuclear@0: mov r9, #(0xD<<8) nuclear@0: str r9, [r12, #0x180] nuclear@0: IPCRecvFlag: nuclear@0: ldr r10, [r12, #0x180] nuclear@0: and r10, r10, #0xF nuclear@0: cmp r10, #0xC nuclear@0: beq IPCRecvFlag nuclear@0: pop {pc} nuclear@0: IPCSync: nuclear@0: ldr r10, [r12, #0x180] nuclear@0: and r10, r10, #0xF nuclear@0: cmp r10, r9 nuclear@0: bne IPCSync nuclear@0: bx lr nuclear@0: __sync_end: nuclear@0: nuclear@0: @--------------------------------------------------------------------------------- nuclear@0: @ Clear memory to 0x00 if length != 0 nuclear@0: @ r0 = Start Address nuclear@0: @ r1 = Length nuclear@0: @--------------------------------------------------------------------------------- nuclear@0: ClearMem: nuclear@0: @--------------------------------------------------------------------------------- nuclear@0: mov r2, #3 @ Round down to nearest word boundary nuclear@0: add r1, r1, r2 @ Shouldn't be needed nuclear@0: bics r1, r1, r2 @ Clear 2 LSB (and set Z) nuclear@0: bxeq lr @ Quit if copy size is 0 nuclear@0: nuclear@0: mov r2, #0 nuclear@0: ClrLoop: nuclear@0: stmia r0!, {r2} nuclear@0: subs r1, r1, #4 nuclear@0: bne ClrLoop nuclear@0: bx lr nuclear@0: nuclear@0: @--------------------------------------------------------------------------------- nuclear@0: @ Copy memory if length != 0 nuclear@0: @ r1 = Source Address nuclear@0: @ r2 = Dest Address nuclear@0: @ r4 = Dest Address + Length nuclear@0: @--------------------------------------------------------------------------------- nuclear@0: CopyMemCheck: nuclear@0: @--------------------------------------------------------------------------------- nuclear@0: cmp r1, r2 nuclear@0: bxeq lr nuclear@0: nuclear@0: sub r3, r4, r2 @ Is there any data to copy? nuclear@0: @--------------------------------------------------------------------------------- nuclear@0: @ Copy memory nuclear@0: @ r1 = Source Address nuclear@0: @ r2 = Dest Address nuclear@0: @ r3 = Length nuclear@0: @--------------------------------------------------------------------------------- nuclear@0: CopyMem: nuclear@0: @--------------------------------------------------------------------------------- nuclear@0: mov r0, #3 @ These commands are used in cases where nuclear@0: add r3, r3, r0 @ the length is not a multiple of 4, nuclear@0: bics r3, r3, r0 @ even though it should be. nuclear@0: bxeq lr @ Length is zero, so exit nuclear@0: CIDLoop: nuclear@0: ldmia r1!, {r0} nuclear@0: stmia r2!, {r0} nuclear@0: subs r3, r3, #4 nuclear@0: bne CIDLoop nuclear@0: bx lr nuclear@0: nuclear@0: @--------------------------------------------------------------------------------- nuclear@0: .align nuclear@0: .pool nuclear@0: nuclear@0: .global __dsimode nuclear@0: __dsimode: .word nuclear@0: .end nuclear@0: @---------------------------------------------------------------------------------