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 +