gbasys

diff samples/fonts/crt0.s @ 0:875ef6085efc

gbasys mercurial repository
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 04 Mar 2012 04:04:25 +0200
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/samples/fonts/crt0.s	Sun Mar 04 04:04:25 2012 +0200
     1.3 @@ -0,0 +1,692 @@
     1.4 +@********************************************************************
     1.5 +@*   crt0.S v1.28 by Jeff Frohwein                                  *
     1.6 +@********************************************************************
     1.7 +
     1.8 +@ v1.0 - Original release
     1.9 +@ v1.1 - Added proper .data section support
    1.10 +@ v1.2 - Added support for c++, overlays, interrupts, and
    1.11 +@        far calls (__FarFunction & __FarProcedure).
    1.12 +@      - Some ideas from Jason Wilkins & Mike Heckenbach.
    1.13 +@ v1.21- Killed the dumb test bug left in the code.
    1.14 +@ v1.22- Killed dumb bug "numero dos" in multiple interrupts routine. Thanks Mike H. :)
    1.15 +@ v1.23- Now correctly handles zero length .bss section.
    1.16 +@ v1.24- Loop back to start_vector now works if main {} exits.
    1.17 +@ v1.25- __FarProcedure now works. It was missing a .thumb_func directive.
    1.18 +@ v1.26- Added missing Serial Interrupt processing to __MultipleInterrupts section.
    1.19 +@        Added __FastInterrupt option for minimal interrupt processing.
    1.20 +@        Optimized __MultipleInterrupts section to save 4 bytes of stack space.
    1.21 +@        Added __ISRinIWRAM option that puts interrupt processing in IWRAM by default.
    1.22 +@        Options passed to main() or AgbMain() are now set to 0. (Thanks to DarkFader)
    1.23 +@ v1.27- Even though it might not cause any problems for anyone "as is",
    1.24 +@        changed .SECTION .iwram to .SECTION .iwram,"ax",%progbits
    1.25 +@        just to be safe. That is the more correct description/definition.
    1.26 +@        Added warning below about small default interrupt stack.
    1.27 +@ v1.28- Added force alignment (align 4) to CopyMem & ClearMem to
    1.28 +@        prevent infinite loops in cases where LD (buggy?) fails
    1.29 +@        to align(4). (Thanks to Mark Price & others.)
    1.30 +@
    1.31 +@ This file is released into the public domain for commercial
    1.32 +@ or non-commercial usage with no restrictions placed upon it.
    1.33 +
    1.34 +    .TEXT
    1.35 +
    1.36 +@ Comment out the next line ONLY if you plan to never support
    1.37 +@ multiboot mode and want to save a few bytes by removing
    1.38 +@ multiboot support code. Otherwise, leave it alone. It wont
    1.39 +@ disturb code designed to run only on flash carts.
    1.40 +@
    1.41 +@ The normal way to enable generating code that works with
    1.42 +@ both multiboot and flash carts is to add the following to
    1.43 +@ your C code in your main project file AS A GLOBAL VARIABLE:
    1.44 +@
    1.45 +@   #define MULTIBOOT int __gba_multiboot;
    1.46 +@ Then use it like this : MULTIBOOT
    1.47 +@
    1.48 +@ IT MUST BE A GLOBAL VARIABLE OR IT WILL NOT WORK!
    1.49 +@ If this variable is not defined somewhere in your project
    1.50 +@ then code will be generated to run out of ROM instead of
    1.51 +@ EXRAM. The value of this variable is not important.
    1.52 +
    1.53 + .equ __MultiBootInclude, 1
    1.54 +
    1.55 +@ If you are compiling for multiboot dedicated (will not
    1.56 +@ run in a cart) code then uncomment the following. Normally
    1.57 +@ you should leave this commented out so that a multiboot
    1.58 +@ image will run in a cart as well (by copying from ROM to RAM).
    1.59 +@
    1.60 +@ This sets the maker code to "MB  " which is a key that
    1.61 +@ some emulators look for to know to load the rom image
    1.62 +@ at 0x2000000 instead of the standard 0x8000000.
    1.63 +
    1.64 +@ .equ __MultibootDedicated, 1
    1.65 +
    1.66 +@ There are two methods for clearing memory and
    1.67 +@ copying appropriate setup data. The fast & bulky
    1.68 +@ method is GBA DMA copy/clear but some emulators
    1.69 +@ do not accurately do DMA. If you have an inaccurate
    1.70 +@ emulator or want to conserve ROM space then comment
    1.71 +@ out the following line. There is not much advantage
    1.72 +@ gained by doing DMA copy/clear.
    1.73 +
    1.74 +@ .equ __DMACopyClear, 1
    1.75 +
    1.76 +@ Uncomment the following line to support C++ development.
    1.77 +@ You also need to name your main C function the following:
    1.78 +@    int main (void)  ...instead of... int AgbMain (void)
    1.79 +@ Doing so will cause ~5500 bytes of c++ support code to be
    1.80 +@ linked in with your project so do not enable c++ support
    1.81 +@ unless you plan to use it.
    1.82 +
    1.83 +.equ __CPPSupport, 1
    1.84 +
    1.85 +@ Comment out the following line to disable interrupt support
    1.86 +@ in your code and to save some space in this file.
    1.87 +
    1.88 +@ .equ __InterruptSupport, 1
    1.89 +
    1.90 +
    1.91 +@ Comment out the following line to put interrupt support in
    1.92 +@ ROM instead of IWRAM. Interrupt support in ROM will slow
    1.93 +@ down interrupt execution and has no advantage other than
    1.94 +@ saving a little bit of IWRAM.
    1.95 +
    1.96 + .equ __ISRinIWRAM, 1
    1.97 +
    1.98 +@ NOTE: Only ONE of the following 3 interrupt options may be
    1.99 +@ uncommented. Also, __InterruptSupport above must be uncommented
   1.100 +@ for any of the following to have an effect.
   1.101 +@  If __InterruptSupport is uncommented then you MUST select ONE
   1.102 +@ AND ONLY ONE of the following 3 interrupt options.
   1.103 +@
   1.104 +@ __FastInterrupts
   1.105 +@   Uncomment this line for minimal interrupt processing.
   1.106 +@   This allows 160 bytes of interrupt stack space with the
   1.107 +@   default lnkscript.
   1.108 +@
   1.109 +@ __SingleInterrupts
   1.110 +@   Uncomment this line if you wish to use a table of function
   1.111 +@   pointers to process specific interrupts. This allows 160
   1.112 +@   bytes of interrupt stack space with the default lnkscript.
   1.113 +@
   1.114 +@ __MultipleInterrupts
   1.115 +@   Uncomment this line to allow multiple-interrupts-at-once
   1.116 +@   support. If you have several interrupts where one can
   1.117 +@   occur while another is being serviced then you need to
   1.118 +@   enable this option. This option uses the main stack instead
   1.119 +@   of the interrupt stack so you have access to a larger stack.
   1.120 +
   1.121 +.equ __FastInterrupts, 1
   1.122 +@ .equ __SingleInterrupts, 1
   1.123 +@ .equ __MultipleInterrupts, 1
   1.124 +
   1.125 +
   1.126 +@ Uncomment the following line to disable sound and enter an
   1.127 +@ infinite loop if cart is removed during game play. You
   1.128 +@ must have the cart interrupt enabled for this to work and
   1.129 +@ __ISRinIWRAM, above, must be enabled (not commented out.)
   1.130 +
   1.131 +@ .equ __HandleCartInterrupt, 1
   1.132 +
   1.133 +@ The following prevents IRQ stack overflow by switching to
   1.134 +@ System mode (User stack) when handling multiple interrupts.
   1.135 +@ To force use of IRQ stack only, comment out the following line.
   1.136 +
   1.137 + .equ __SwitchToUserStack, 1
   1.138 +
   1.139 +@ !!!! NOTE: THE COPY ROUTINES IN THIS FILE WORK ON 4 BYTE
   1.140 +@ BOUNDARIES. YOUR LINKER SCRIPT MUST ALIGN SECTION STARTS
   1.141 +@ AND SECTION ENDS FOR SECTIONS THAT GET COPIED TO RAM WITH
   1.142 +@ ALIGN(4) !!!!
   1.143 +
   1.144 +    .GLOBAL     _start
   1.145 +_start:
   1.146 +        .ALIGN
   1.147 +        .CODE 32
   1.148 +    @ Start Vector
   1.149 +
   1.150 +        b       rom_header_end
   1.151 +
   1.152 +    @ Nintendo Logo Character Data (8000004h)
   1.153 +@        .fill   156,1,0
   1.154 +	.long 0x51aeff24,0x21a29a69,0x0a82843d
   1.155 +	.long 0xad09e484,0x988b2411,0x217f81c0,0x19be52a3
   1.156 +	.long 0x20ce0993,0x4a4a4610,0xec3127f8,0x33e8c758
   1.157 +	.long 0xbfcee382,0x94dff485,0xc1094bce,0xc08a5694
   1.158 +	.long 0xfca77213,0x734d849f,0x619acaa3,0x27a39758
   1.159 +	.long 0x769803fc,0x61c71d23,0x56ae0403,0x008438bf
   1.160 +	.long 0xfd0ea740,0x03fe52ff,0xf130956f,0x85c0fb97
   1.161 +	.long 0x2580d660,0x03be63a9,0xe2384e01,0xff34a2f9
   1.162 +	.long 0x44033ebb,0xcb900078,0x943a1188,0x637cc065
   1.163 +	.long 0xaf3cf087,0x8be425d6,0x72ac0a38,0x07f8d421
   1.164 +
   1.165 +    @ Game Title (80000A0h)
   1.166 +        .byte   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
   1.167 +        .byte   0x00,0x00,0x00,0x00
   1.168 +
   1.169 + .ifdef __MultibootDedicated
   1.170 +    @ Game Code (80000ACh)
   1.171 +        .ascii  "MB  "
   1.172 + .else
   1.173 +    @ Game Code (80000ACh)
   1.174 +        .byte   0x00,0x00,0x00,0x00
   1.175 + .endif
   1.176 +
   1.177 +    @ Maker Code (80000B0h)
   1.178 +        .byte   0x30,0x31
   1.179 +
   1.180 +    @ Fixed Value (80000B2h)
   1.181 +        .byte   0x96
   1.182 +
   1.183 +    @ Main Unit Code (80000B3h)
   1.184 +        .byte   0x00
   1.185 +
   1.186 +    @ Device Type (80000B4h)
   1.187 +        .byte   0x00
   1.188 +
   1.189 +    @ Unused Data (7Byte) (80000B5h)
   1.190 +        .byte   0x00,0x00,0x00,0x00,0x00,0x00,0x00
   1.191 +
   1.192 +    @ Software Version No (80000BCh)
   1.193 +        .byte   0x00
   1.194 +
   1.195 +    @ Complement Check (80000BDh)
   1.196 +        .byte   0xf0
   1.197 +
   1.198 +    @ Checksum (80000BEh)
   1.199 +        .byte   0x00,0x00
   1.200 +
   1.201 +    .ALIGN
   1.202 +    .ARM                                @ ..or you can use CODE 32 here
   1.203 +
   1.204 +rom_header_end:
   1.205 +        b       start_vector        @ This branch must be here for proper
   1.206 +                                    @ positioning of the following header.
   1.207 +                                    @ DO NOT REMOVE IT.
   1.208 +
   1.209 +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   1.210 +@ The following reserved bytes are used if the code is compiled for      @
   1.211 +@ multiboot mode. It does not hurt anything to leave this header in
   1.212 +@ even if the code is not compiled for multiboot. The GBA BIOS will
   1.213 +@ auto-patch the first two bytes with 0x03 and 0x01, respectively,
   1.214 +@ before running any code if it is executed as multiboot.
   1.215 +@
   1.216 +
   1.217 +@ The following two bytes are included even for non-multiboot supporting
   1.218 +@ builds to guarantee that any generic library code that depends on them
   1.219 +@ will still be functional.
   1.220 +
   1.221 +    .GLOBAL     __boot_method, __slave_number
   1.222 +
   1.223 +__boot_method:
   1.224 +        .byte   0       @ boot method (0=ROM boot, 3=Multiplay boot)
   1.225 +__slave_number:
   1.226 +        .byte   0       @ slave # (1=slave#1, 2=slave#2, 3=slave#3)
   1.227 +
   1.228 + .ifdef __MultiBootInclude
   1.229 +
   1.230 +        .byte   0       @ reserved
   1.231 +        .byte   0       @ reserved
   1.232 +        .word   0       @ reserved
   1.233 +        .word   0       @ reserved
   1.234 +        .word   0       @ reserved
   1.235 +        .word   0       @ reserved
   1.236 +        .word   0       @ reserved
   1.237 +        .word   0       @ reserved
   1.238 + .endif
   1.239 +@                                                                        @
   1.240 +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   1.241 +
   1.242 +
   1.243 +@@@@@@@@@@@@@@@@@@@@@@
   1.244 +@        Reset       @
   1.245 +@@@@@@@@@@@@@@@@@@@@@@
   1.246 +
   1.247 +    .GLOBAL     start_vector
   1.248 +    .ALIGN
   1.249 +    .ARM                                @ ..or you can use CODE 32 here
   1.250 +start_vector:
   1.251 +        mov     r0, #0x12               @ Switch to IRQ Mode
   1.252 +        msr     cpsr, r0
   1.253 +        ldr     sp,=__sp_irq            @ Set SP_irq
   1.254 +        mov     r0, #0x1f               @ Switch to System Mode
   1.255 +        msr     cpsr, r0
   1.256 +        ldr     sp,=__sp_usr            @ Set SP_usr
   1.257 +
   1.258 +@ Enter Thumb mode
   1.259 +        adr    r0,1f + 1                @ add r0,pc,#1 also works here
   1.260 +                                        @  for those that want to conserve labels.
   1.261 +        bx     r0
   1.262 +
   1.263 +        .THUMB                          @ ..or you can use .CODE 16 here
   1.264 +1:
   1.265 +
   1.266 + .ifdef __InterruptSupport
   1.267 +        ldr     r1, =__intr_vector_buf  @ Set Interrupt Address
   1.268 +        ldr     r0, =intr_main
   1.269 +        str     r0, [r1]
   1.270 + .endif
   1.271 +
   1.272 + .ifdef __MultiBootInclude
   1.273 +
   1.274 +@ *** Multiboot Copy Routine ***
   1.275 +@   Check the Program Counter to see if code is running
   1.276 +@ at 0x2000000 or 0x8000000. If it is running at 0x8000000
   1.277 +@ then copy 256K bytes of it to 0x2000000 and then branch
   1.278 +@ to 0x2000000.
   1.279 +@   The reason for all this is to allow a program to be used
   1.280 +@ "as is" with an flash cart/emulator or with an MBV2-style
   1.281 +@ multiboot cable.
   1.282 +@   NOTE: You can also detect if this ROM is running from
   1.283 +@ 0x2000000 by checking the multiboot header above.
   1.284 +
   1.285 +        ldr     r0,=__text_start
   1.286 +        lsl     r0,#5           @ Was code compiled at 0x08000000 or higher?
   1.287 +        bcs     DoEWRAMClear    @ yes, you can not run it in external WRAM
   1.288 +
   1.289 +@ Make sure we are in ExWRAM
   1.290 +
   1.291 +        mov     r0,pc
   1.292 +        lsl     r0,#5           @ Are we running from ROM (0x8000000 or higher) ?
   1.293 +        bcc     SkipEWRAMClear  @ No, so no need to do a copy.
   1.294 +
   1.295 +@ We were started in ROM, silly emulators. :P
   1.296 +@ So we need to copy to ExWRAM.
   1.297 +
   1.298 +        mov     r3,#0x40
   1.299 +        lsl     r3,#12          @ r3 = 0x40000
   1.300 +        lsl     r2,r3,#7        @ r2 = 0x2000000
   1.301 +        mov     r6,r2           @ r6 = 0x2000000
   1.302 +        lsl     r1,r2,#2        @ r1 = 0x8000000
   1.303 +
   1.304 +        bl      CopyMem
   1.305 +
   1.306 +@ Jump to the code to execute
   1.307 +
   1.308 +        bx      r6
   1.309 + .endif
   1.310 +
   1.311 +DoEWRAMClear:
   1.312 +@ Clear External WRAM to 0x00
   1.313 +
   1.314 +        mov     r1,#0x40
   1.315 +        lsl     r1,#12          @ r1 = 0x40000
   1.316 +        lsl     r0,r1,#7        @ r0 = 0x2000000
   1.317 +        bl      ClearMem
   1.318 +
   1.319 +SkipEWRAMClear:
   1.320 +@        ldr     r0,=AgbMain
   1.321 +@        bx r0
   1.322 +
   1.323 +@ Clear Internal WRAM to 0x00
   1.324 +        mov     r0,#3
   1.325 +        lsl     r0,#24          @ r0 = 0x3000000
   1.326 +        ldr     r1,=__sp_usr_offset - 16
   1.327 +        bl      ClearMem
   1.328 +
   1.329 + .ifdef __MultiBootInclude
   1.330 +@ Clear BSS section to 0x00
   1.331 +@ (Sometimes BSS may be in External WRAM)
   1.332 +        ldr     r0,=__bss_start
   1.333 +        ldr     r1,=__bss_end
   1.334 +        sub     r1,r0
   1.335 +        bl      ClearMem
   1.336 + .endif
   1.337 +
   1.338 +@ Copy initialized data (data section) from LMA to VMA (ROM to RAM)
   1.339 +        ldr     r1,=__data_lma
   1.340 +        ldr     r2,=__data_start
   1.341 +        ldr     r4,=__data_end
   1.342 +        bl      CopyMemChk
   1.343 +
   1.344 +@ Copy internal work ram (iwram section) from LMA to VMA (ROM to RAM)
   1.345 +        ldr     r1,=__iwram_lma
   1.346 +        ldr     r2,=__iwram_start
   1.347 +        ldr     r4,=__iwram_end
   1.348 +        bl      CopyMemChk
   1.349 +
   1.350 +@ Copy internal work ram overlay 0 (iwram0 section) from LMA to VMA (ROM to RAM)
   1.351 +        ldr     r2,=__load_stop_iwram0
   1.352 +        ldr     r1,=__load_start_iwram0
   1.353 +        sub     r3,r2,r1         @ Is there any data to copy?
   1.354 +        beq     CIW0Skip         @ no
   1.355 +
   1.356 +        ldr     r2,=__iwram_overlay_start
   1.357 +        bl      CopyMem
   1.358 +CIW0Skip:
   1.359 +
   1.360 +@ Copy external work ram (ewram section) from LMA to VMA (ROM to RAM)
   1.361 +        ldr     r1,=__ewram_lma
   1.362 +        ldr     r2,=__ewram_start
   1.363 +        ldr     r4,=__ewram_end
   1.364 +        bl      CopyMemChk
   1.365 +
   1.366 +@ Copy external work ram overlay 0 (ewram0 section) from LMA to VMA (ROM to RAM)
   1.367 +        ldr     r2,=__load_stop_ewram0
   1.368 +        ldr     r1,=__load_start_ewram0
   1.369 +        sub     r3,r2,r1         @ Is there any data to copy?
   1.370 +        beq     CEW0Skip         @ no
   1.371 +
   1.372 +        ldr     r2,=__ewram_overlay_start
   1.373 +        bl      CopyMem
   1.374 +CEW0Skip:
   1.375 +
   1.376 +@ Jump to user code
   1.377 +
   1.378 +        mov     r0,#0            @ int argc
   1.379 +        mov     r1,#0            @ char *argv[]
   1.380 +
   1.381 +        ldr     r3,=start_vector
   1.382 +        mov     lr,r3            @ Set start_vector as return address
   1.383 +
   1.384 +.ifdef __CPPSupport
   1.385 +        ldr     r3,=main
   1.386 +.else
   1.387 +        ldr     r3,=AgbMain
   1.388 +.endif
   1.389 +        bx      r3
   1.390 +
   1.391 +
   1.392 +    .GLOBAL     __FarFunction,__FarProcedure
   1.393 +    .THUMB_FUNC
   1.394 +__FarFunction:
   1.395 +    .THUMB_FUNC
   1.396 +__FarProcedure:
   1.397 +        bx      r0
   1.398 +        nop
   1.399 +        nop          @ This nop is here to allow unmapped memory to be used as
   1.400 +                     @ as a delay of almost 1 sec with a 1 cycle resolution.
   1.401 +                     @ Read this for technical info:
   1.402 +                     @  http://www.devrs.com/gba/files/gbadevfaqs.php#RepeatUses
   1.403 +
   1.404 +@ Clear memory to 0x00 if length != 0
   1.405 +@ r0 = Start Address
   1.406 +@ r1 = Length
   1.407 +
   1.408 +ClearMem:
   1.409 +@        cmp     r1,#0           @ Is length zero?
   1.410 +@        beq     ClearMX         @ yes, exit
   1.411 +
   1.412 +        mov     r2,#3            @ These commands are used in cases where
   1.413 +        add     r1,r2            @ the length is not a multiple of 4,
   1.414 +        bic     r1,r2            @ even though it should be.
   1.415 +
   1.416 +        beq     ClearMX         @ Length is zero so exit
   1.417 +
   1.418 +.ifdef __DMACopyClear
   1.419 +        ldr     r2,reg_base
   1.420 +        lsr     r1,#2           @ r1 = (length/4) & 0xffff
   1.421 +
   1.422 +        adr     r3,fill_val
   1.423 +        str     r3,[r2,#0x4]    @ Set source address (fill value)
   1.424 +        str     r0,[r2,#0x8]    @ Set destination address (fill dest address)
   1.425 +        strh    r1,[r2,#0xc]    @ Set DMA length
   1.426 +        ldr     r1,=0x8500      @ dma_clrb
   1.427 +        strh    r1,[r2,#0xe]    @ Start DMA
   1.428 +.else
   1.429 +        mov     r2,#0
   1.430 +ClrLoop:
   1.431 +        stmia   r0!,{r2}
   1.432 +        sub     r1,#4
   1.433 +        bne     ClrLoop
   1.434 +.endif
   1.435 +ClearMX:
   1.436 +        bx      lr
   1.437 +
   1.438 +@ Copy memory if length != 0
   1.439 +@ r1 = Source Address
   1.440 +@ r2 = Dest Address
   1.441 +@ r4 = Dest Address + Length
   1.442 +
   1.443 +CopyMemChk:
   1.444 +        sub     r3,r4,r2         @ Is there any data to copy?
   1.445 +@        beq     CIDExit          @ no
   1.446 +
   1.447 +@ Copy memory
   1.448 +@ r1 = Source Address
   1.449 +@ r2 = Dest Address
   1.450 +@ r3 = Length
   1.451 +
   1.452 +CopyMem:
   1.453 +        mov     r0,#3            @ These commands are used in cases where
   1.454 +        add     r3,r0            @ the length is not a multiple of 4,
   1.455 +        bic     r3,r0            @ even though it should be.
   1.456 +
   1.457 +        beq     CIDExit          @ Length is zero so exit
   1.458 +
   1.459 +.ifdef __DMACopyClear
   1.460 +        ldr     r0,reg_base
   1.461 +        lsr     r3,#2           @ r3 = (length/4) & 0xffff
   1.462 +
   1.463 +        str     r1,[r0,#0x4]    @ Set source address
   1.464 +        str     r2,[r0,#0x8]    @ Set destination address
   1.465 +        strh    r3,[r0,#0xc]    @ Set DMA length
   1.466 +        ldr     r3,=0x8400      @ dma_copy
   1.467 +        strh    r3,[r0,#0xe]    @ Start DMA
   1.468 +.else
   1.469 +CIDLoop:
   1.470 +        ldmia   r1!,{r0}
   1.471 +        stmia   r2!,{r0}
   1.472 +        sub     r3,#4
   1.473 +        bne     CIDLoop
   1.474 +.endif
   1.475 +CIDExit:
   1.476 +If_Undefined_Reference__rename_main_or_AgbMain_to_each_other_in_your_C_file:
   1.477 +        bx      lr
   1.478 +
   1.479 +        .ALIGN
   1.480 +
   1.481 +.ifdef __DMACopyClear
   1.482 +fill_val: .word  0
   1.483 +reg_base: .word  0x040000d0
   1.484 +.endif
   1.485 +
   1.486 +        .ALIGN
   1.487 +        .POOL
   1.488 +
   1.489 +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   1.490 +@                  Interrupt Processing                  @
   1.491 +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   1.492 +
   1.493 + .ifdef __ISRinIWRAM
   1.494 +    .SECTION    .iwram,"ax",%progbits
   1.495 + .endif
   1.496 +
   1.497 +    .EXTERN     IntrTable
   1.498 +    .EXTERN     InterruptProcess
   1.499 +    .GLOBAL     intr_main
   1.500 +    .ALIGN
   1.501 +    .ARM
   1.502 +
   1.503 +@ NOTE: Ifyou copy the following code (start: intr_main -
   1.504 +@ end: intr_main_end) to internal WRAM then do not forget
   1.505 +@ to copy everything between these two labels. The .POOL
   1.506 +@ data must be copied since it is used by intr_main.
   1.507 +
   1.508 +@ NOTE2: If __ISRinIWRAM is defined then the copy to
   1.509 +@ IWRAM is done automatically for you.
   1.510 +
   1.511 + .ifdef __InterruptSupport
   1.512 +
   1.513 +  .ifdef __FastInterrupts
   1.514 +intr_main:
   1.515 +        ldr     r0,=InterruptProcess
   1.516 +        bx      r0
   1.517 +  .endif
   1.518 +
   1.519 +  .ifdef __SingleInterrupts
   1.520 +intr_main:
   1.521 +                                         @ Single interrupts support
   1.522 +        mov     r3, #0x4000000           @ REG_BASE
   1.523 +        ldr     r2, [r3,#0x200]!         @ Read REG_IE
   1.524 +        and     r1, r2, r2, lsr #16      @ r1 = IE & IF
   1.525 +        ldr     r2, =IntrTable
   1.526 +
   1.527 +        ands    r0, r1, #1               @ V-Blank Interrupt
   1.528 +        bne     jump_intr
   1.529 +        add     r2, r2, #4
   1.530 +        ands    r0, r1, #2               @ H-Blank Interrupt
   1.531 +        bne     jump_intr
   1.532 +        add     r2, r2, #4
   1.533 +        ands    r0, r1, #4               @ V Counter Interrupt
   1.534 +        bne     jump_intr
   1.535 +        add     r2, r2, #4
   1.536 +        ands    r0, r1, #8               @ Timer 0 Interrupt
   1.537 +        bne     jump_intr
   1.538 +        add     r2, r2, #4
   1.539 +        ands    r0, r1, #0x10            @ Timer 1 Interrupt
   1.540 +        bne     jump_intr
   1.541 +        add     r2, r2, #4
   1.542 +        ands    r0, r1, #0x20            @ Timer 2 Interrupt
   1.543 +        bne     jump_intr
   1.544 +        add     r2, r2, #4
   1.545 +        ands    r0, r1, #0x40            @ Timer 3 Interrupt
   1.546 +        bne     jump_intr
   1.547 +        add     r2, r2, #4
   1.548 +        ands    r0, r1, #0x80            @ Serial Communication Interrupt
   1.549 +        bne     jump_intr
   1.550 +        add     r2, r2, #4
   1.551 +        ands    r0, r1, #0x100           @ DMA0 Interrupt
   1.552 +        bne     jump_intr
   1.553 +        add     r2, r2, #4
   1.554 +        ands    r0, r1, #0x200           @ DMA1 Interrupt
   1.555 +        bne     jump_intr
   1.556 +        add     r2, r2, #4
   1.557 +        ands    r0, r1, #0x400           @ DMA2 Interrupt
   1.558 +        bne     jump_intr
   1.559 +        add     r2, r2, #4
   1.560 +        ands    r0, r1, #0x800           @ DMA3 Interrupt
   1.561 +        bne     jump_intr
   1.562 +        add     r2, r2, #4
   1.563 +        ands    r0, r1, #0x1000          @ Key Interrupt
   1.564 +        bne     jump_intr
   1.565 +        add     r2, r2, #4
   1.566 +        ands    r0, r1, #0x2000          @ Cart Interrupt
   1.567 +
   1.568 +   .ifdef __HandleCartInterrupt
   1.569 +        strneb  r0, [r3, #0x84 - 0x200]  @ Stop sound if cart removed (REG_SOUNDCNT_X)
   1.570 +loop:   bne     loop                     @ Infinite loop if cart removed
   1.571 +   .endif
   1.572 +
   1.573 +jump_intr:
   1.574 +        strh    r0, [r3, #2]             @ IF Clear
   1.575 +        ldr     r0, [r2]                 @ Jump to user IRQ process
   1.576 +        bx      r0
   1.577 +  .endif
   1.578 +
   1.579 +  .ifdef __MultipleInterrupts
   1.580 +intr_main:
   1.581 +                                         @ Multiple interrupts support
   1.582 +        mov     r2, #0x4000000           @ REG_BASE
   1.583 +        ldr     r3, [r2,#0x200]!         @ r2 = IE : r3 = IF|IE
   1.584 +        ldrh    r1, [r2, #0x8]           @ r1 = IME
   1.585 +        mrs     r0, spsr
   1.586 +        stmfd   sp!, {r0-r2,lr}          @ {spsr, IME, REG_IE, lr}  // IF|IE
   1.587 +
   1.588 +        mov     r0, #1                   @ IME = 1 (To permit multiple interrupts if
   1.589 +                                         @ an interrupt occurs)
   1.590 +        strh    r0, [r2, #0x8]
   1.591 +        and     r1, r3, r3, lsr #16      @ r1 = IE & IF
   1.592 +        ldr     r12, =IntrTable
   1.593 +
   1.594 +        ands    r0, r1, #1               @ V-blank interrupt
   1.595 +        bne     jump_intr
   1.596 +        add     r12,r12, #4
   1.597 +        ands    r0, r1, #2               @ H-blank interrupt
   1.598 +        bne     jump_intr
   1.599 +        add     r12,r12, #4
   1.600 +        ands    r0, r1, #4               @ V-counter interrupt
   1.601 +        bne     jump_intr
   1.602 +        add     r12,r12, #4
   1.603 +        ands    r0, r1, #8               @ Timer 0 interrupt
   1.604 +        bne     jump_intr
   1.605 +        add     r12,r12, #4
   1.606 +        ands    r0, r1, #0x10            @ Timer 1 interrupt
   1.607 +        bne     jump_intr
   1.608 +        add     r12,r12, #4
   1.609 +        ands    r0, r1, #0x20            @ Timer 2 interrupt
   1.610 +        bne     jump_intr
   1.611 +        add     r12,r12, #4
   1.612 +        ands    r0, r1, #0x40            @ Timer 3 interrupt
   1.613 +        bne     jump_intr
   1.614 +        add     r12,r12, #4
   1.615 +        ands    r0, r1, #0x80            @ Serial Communication Interrupt
   1.616 +        bne     jump_intr
   1.617 +        add     r12,r12, #4
   1.618 +        ands    r0, r1, #0x100           @ DMA 0 interrupt
   1.619 +        bne     jump_intr
   1.620 +        add     r12,r12, #4
   1.621 +        ands    r0, r1, #0x200           @ DMA 1 interrupt
   1.622 +        bne     jump_intr
   1.623 +        add     r12,r12, #4
   1.624 +        ands    r0, r1, #0x400           @ DMA 2 interrupt
   1.625 +        bne     jump_intr
   1.626 +        add     r12,r12, #4
   1.627 +        ands    r0, r1, #0x800           @ DMA 3 interrupt
   1.628 +        bne     jump_intr
   1.629 +        add     r12,r12, #4
   1.630 +        ands    r0, r1, #0x1000          @ Key interrupt
   1.631 +        bne     jump_intr
   1.632 +        add     r12,r12, #4
   1.633 +        ands    r0, r1, #0x2000          @ Cart interrupt
   1.634 +
   1.635 +   .ifdef __HandleCartInterrupt
   1.636 +        strneb  r0, [r2, #0x84 - 0x200]  @ Stop sound if cart removed (REG_SOUNDCNT_X)
   1.637 +loop:   bne     loop                     @ Infinite loop if cart removed
   1.638 +   .endif
   1.639 +
   1.640 +jump_intr:
   1.641 +        strh    r0, [r2, #2]             @ Clear IF
   1.642 +
   1.643 +@ Enable multiple interrupts & switch to system
   1.644 +@ mode if __SwitchToUserStack is defined.
   1.645 +
   1.646 +        mrs     r3, cpsr
   1.647 +   .ifdef __SwitchToUserStack
   1.648 +        bic     r3, r3, #0xdf            @ \__
   1.649 +        orr     r3, r3, #0x1f            @ /  --> Enable IRQ & FIQ. Set CPU mode to System.
   1.650 +   .else
   1.651 +        bic     r3, r3, #0xc0            @ Enable IRQ & FIQ
   1.652 +   .endif
   1.653 +        msr     cpsr, r3
   1.654 +
   1.655 +        ldr     r0, [r12]
   1.656 +
   1.657 +        stmfd   sp!, {lr}
   1.658 +        adr     lr, IntrRet
   1.659 +        bx      r0
   1.660 +IntrRet:
   1.661 +        ldmfd   sp!, {lr}
   1.662 +
   1.663 +@ Disable multiple interrupts & switch to IRQ Mode
   1.664 +@ if __SwitchToUserStack is defined.
   1.665 +
   1.666 +        mrs     r3, cpsr
   1.667 +   .ifdef __SwitchToUserStack
   1.668 +        bic     r3, r3, #0xdf            @ \__
   1.669 +        orr     r3, r3, #0x92            @ /  --> Disable IRQ. Enable FIQ. Set CPU mode to IRQ.
   1.670 +   .else
   1.671 +        orr     r3, r3, #0x80            @ Disable IRQ.
   1.672 +   .endif
   1.673 +        msr     cpsr, r3
   1.674 +
   1.675 +        ldmfd   sp!, {r0-r2,lr}          @ {spsr, IME, REG_IE, lr}  //IF|IE
   1.676 +@        strh    r3,  [r2]                @ set IE
   1.677 +        strh    r1,  [r2, #0x8]          @ restore REG_IME
   1.678 +        msr     spsr, r0                 @ restore spsr
   1.679 +        bx      lr
   1.680 +
   1.681 +  .endif
   1.682 +
   1.683 +    .ALIGN
   1.684 +    .POOL               @ Ifyou copy the intr_main routine, above, to internal
   1.685 +                        @ RAM then copy the pool data as well because IntrTable
   1.686 +                        @ address is stored here. Use intr_main_end as last address+1.
   1.687 +intr_main_end:
   1.688 + .endif
   1.689 +
   1.690 +    .ALIGN
   1.691 +    .POOL
   1.692 +
   1.693 +
   1.694 +    .END
   1.695 +