@--------------------------------------------------------------------------------- .section ".init" @--------------------------------------------------------------------------------- .global _start .type _start STT_FUNC .align 4 .arm @--------------------------------------------------------------------------------- _start: @--------------------------------------------------------------------------------- b reset_vector @ 0x00 Reset b reserved_vector @ 0x04 Undefined b swi_vector @ 0x08 SWI b reserved_vector @ 0x0C Abort Prefetch b reserved_vector @ 0x10 Abort Data b reserved_vector @ 0x14 Reserved b irq_vector @ 0x18 IRQ b irq_vector @ 0x1C FIQ @--------------------------------------------------------------------------------- irq_vector: @--------------------------------------------------------------------------------- @ Save these registers, IRQ functions will be allowed to modify them w/o @ saving. stmdb sp!, { r0 - r3, r12, lr } @ Pointer to IRQ handler is at 0x03FFFFFC (mirrored WRAM) mov r0, #0x04000000 @ Store return address and branch to handler mov lr, pc ldr pc, [ r0, #-4 ] @ Return from IRQ ldmia sp!, { r0 - r3, r12, lr } subs pc, lr, #4 @--------------------------------------------------------------------------------- reset_vector: @This isn't required if not booting from bios @--------------------------------------------------------------------------------- mov r0, #0xDF msr cpsr_cf, r0 @Disable Interrupts IME=0 mov r3, #0x04000000 strb r3, [r3,#0x208] @Setup stacks bl init mov r2, #1 strb r2, [r3,#0x208] ldr r0, =DrawLogo ldr lr, =swi_SoftReset bx r0 @--------------------------------------------------------------------------------- reserved_vector: @Lets just infinite loop for now @--------------------------------------------------------------------------------- b reserved_vector @ SWI calling convention: @ Parameters are passed in via r0 - r3 @ Called SWI can modify r0 - r3 (and return things here), r12, and r14. @ They can't modify anything else. @--------------------------------------------------------------------------------- swi_vector: @--------------------------------------------------------------------------------- @ Save these as temporaries stmdb sp!, { r11, r12, lr } @ Load comment from SWI instruction, which indicates which SWI @ to use. ldrb r12, [lr,#-2] adr r11, swi_branch_table ldr r12, [r11,r12,lsl#2] @ get SPSR and enter system mode, interrupts on MRS R11, SPSR @ This must be stacked and not just saved, because otherwise SWI won't @ be reentrant, which can happen if you're waiting for interrupts and the @ interrupt handler triggers the SWI. stmfd sp!, {r11} @ Set up new CPSR value and r11, r11, #0x80 orr r11, r11, #0x1f msr cpsr_cf, r11 @ We have to now save system-mode lr register as well stmfd sp!, {r2, r3, lr} @ Set return address adr lr, swi_complete @ Branch to SWI handler bx r12 swi_complete: @ Restore system mode lr ldmfd sp!, {r2, r3, lr} @ Go back to supervisor mode to get back to that stack mov r12, #0xD3 msr cpsr_cf, r12 @ SPSR has to be restored because the transition to system mode broke it ldmfd sp!, {r11} msr spsr_cf, r11 @ Restore stuff we saved ldmfd sp!, {r11,r12,lr} @ Return from exception handler movs pc, lr @--------------------------------------------------------------------------------- swi_branch_table: @--------------------------------------------------------------------------------- .word swi_SoftReset @ 0x00_SoftReset .word swi_RegisterRamReset @ 0x01_RegisterRAMReset .word swi_Halt @ 0x02_Halt .word swi_Stop @ 0x03_Stop .word swi_IntrWait @ 0x04_IntrWait .word swi_VBlankIntrWait @ 0x05_VBlankIntrWait .word swi_Div @ 0x06_Div .word swi_DivARM @ 0x07_DivARM .word swi_Sqrt @ 0x08_Sqrt .word swi_ArcTan @ 0x09_ArcTan .word swi_ArcTan2 @ 0x0A_ArcTan2 .word swi_CpuSet @ 0x0B_CPUSet .word swi_CpuFastSet @ 0x0C_CPUFastSet .word swi_GetBiosChecksum @ 0x0D_GetBiosChecksum .word swi_BgAffineSet @ 0x0E_BgAffineSet .word swi_ObjAffineSet @ 0x0F_ObjAffineSet .word swi_BitUnPack @ 0x10_BitUnPack .word swi_LZ77UnCompWram @ 0x11_LZ77UnCompWram .word swi_LZ77UnCompVram @ 0x12_LZ77UnCompVram .word swi_HuffUnComp @ 0x13_HuffUnComp .word swi_RLUnCompWram @ 0x14_RLUnCompWram .word swi_RLUnCompVram @ 0x15_RLUnCompVram .word swi_Diff8bitUnFilterWram @ 0x16_Diff8bitUnFilterWram .word swi_Diff8bitUnFilterVram @ 0x17_Diff8bitUnFilterVram .word swi_Diff16bitUnFilter @ 0x18_Diff16bitUnFilter .word swi_Invalid @ 0x19_SoundBiasChange .word swi_Invalid @ 0x1A_SoundDriverInit .word swi_Invalid @ 0x1B_SoundDriverMode .word swi_Invalid @ 0x1C_SoundDriverMain @ .word swi_SoundDriverMain @ 0x1C_SoundDriverMain .word swi_Invalid @ 0x1D_SoundDriverVSync .word swi_Invalid @ 0x1E_SoundChannelClear .word swi_MidiKey2Freq @ 0x1F_MidiKey2Freq .word swi_Invalid @ 0x20_MusicPlayerOpen .word swi_Invalid @ 0x21_MusicPlayerStart .word swi_Invalid @ 0x22_MusicPlayerStop .word swi_MusicPlayerContinue @ 0x23_MusicPlayerContinue .word swi_MusicPlayerFadeOut @ 0x24_MusicPlayerFadeOut .word swi_Invalid @ 0x25_MultiBoot .word swi_Invalid @ 0x26_HardReset .word swi_CustomHalt @ 0x27_CustomHalt .word swi_Invalid @ 0x28_SoundDriverVSyncOff .word swi_Invalid @ 0x29_SoundDriverVSyncOn .word swi_SoundGetJumpList @ 0x2A_SoundGetJumpList @--------------------------------------------------------------------------------- .global swi_Invalid .type swi_Invalid STT_FUNC swi_Invalid: @--------------------------------------------------------------------------------- @ Infinite loop for now @b swi_Invalid @ Do nothing for release builds bx lr @---------------------------------------------------------------------------------