gbasys
view 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 source
1 @********************************************************************
2 @* crt0.S v1.28 by Jeff Frohwein *
3 @********************************************************************
5 @ v1.0 - Original release
6 @ v1.1 - Added proper .data section support
7 @ v1.2 - Added support for c++, overlays, interrupts, and
8 @ far calls (__FarFunction & __FarProcedure).
9 @ - Some ideas from Jason Wilkins & Mike Heckenbach.
10 @ v1.21- Killed the dumb test bug left in the code.
11 @ v1.22- Killed dumb bug "numero dos" in multiple interrupts routine. Thanks Mike H. :)
12 @ v1.23- Now correctly handles zero length .bss section.
13 @ v1.24- Loop back to start_vector now works if main {} exits.
14 @ v1.25- __FarProcedure now works. It was missing a .thumb_func directive.
15 @ v1.26- Added missing Serial Interrupt processing to __MultipleInterrupts section.
16 @ Added __FastInterrupt option for minimal interrupt processing.
17 @ Optimized __MultipleInterrupts section to save 4 bytes of stack space.
18 @ Added __ISRinIWRAM option that puts interrupt processing in IWRAM by default.
19 @ Options passed to main() or AgbMain() are now set to 0. (Thanks to DarkFader)
20 @ v1.27- Even though it might not cause any problems for anyone "as is",
21 @ changed .SECTION .iwram to .SECTION .iwram,"ax",%progbits
22 @ just to be safe. That is the more correct description/definition.
23 @ Added warning below about small default interrupt stack.
24 @ v1.28- Added force alignment (align 4) to CopyMem & ClearMem to
25 @ prevent infinite loops in cases where LD (buggy?) fails
26 @ to align(4). (Thanks to Mark Price & others.)
27 @
28 @ This file is released into the public domain for commercial
29 @ or non-commercial usage with no restrictions placed upon it.
31 .TEXT
33 @ Comment out the next line ONLY if you plan to never support
34 @ multiboot mode and want to save a few bytes by removing
35 @ multiboot support code. Otherwise, leave it alone. It wont
36 @ disturb code designed to run only on flash carts.
37 @
38 @ The normal way to enable generating code that works with
39 @ both multiboot and flash carts is to add the following to
40 @ your C code in your main project file AS A GLOBAL VARIABLE:
41 @
42 @ #define MULTIBOOT int __gba_multiboot;
43 @ Then use it like this : MULTIBOOT
44 @
45 @ IT MUST BE A GLOBAL VARIABLE OR IT WILL NOT WORK!
46 @ If this variable is not defined somewhere in your project
47 @ then code will be generated to run out of ROM instead of
48 @ EXRAM. The value of this variable is not important.
50 .equ __MultiBootInclude, 1
52 @ If you are compiling for multiboot dedicated (will not
53 @ run in a cart) code then uncomment the following. Normally
54 @ you should leave this commented out so that a multiboot
55 @ image will run in a cart as well (by copying from ROM to RAM).
56 @
57 @ This sets the maker code to "MB " which is a key that
58 @ some emulators look for to know to load the rom image
59 @ at 0x2000000 instead of the standard 0x8000000.
61 @ .equ __MultibootDedicated, 1
63 @ There are two methods for clearing memory and
64 @ copying appropriate setup data. The fast & bulky
65 @ method is GBA DMA copy/clear but some emulators
66 @ do not accurately do DMA. If you have an inaccurate
67 @ emulator or want to conserve ROM space then comment
68 @ out the following line. There is not much advantage
69 @ gained by doing DMA copy/clear.
71 @ .equ __DMACopyClear, 1
73 @ Uncomment the following line to support C++ development.
74 @ You also need to name your main C function the following:
75 @ int main (void) ...instead of... int AgbMain (void)
76 @ Doing so will cause ~5500 bytes of c++ support code to be
77 @ linked in with your project so do not enable c++ support
78 @ unless you plan to use it.
80 .equ __CPPSupport, 1
82 @ Comment out the following line to disable interrupt support
83 @ in your code and to save some space in this file.
85 @ .equ __InterruptSupport, 1
88 @ Comment out the following line to put interrupt support in
89 @ ROM instead of IWRAM. Interrupt support in ROM will slow
90 @ down interrupt execution and has no advantage other than
91 @ saving a little bit of IWRAM.
93 .equ __ISRinIWRAM, 1
95 @ NOTE: Only ONE of the following 3 interrupt options may be
96 @ uncommented. Also, __InterruptSupport above must be uncommented
97 @ for any of the following to have an effect.
98 @ If __InterruptSupport is uncommented then you MUST select ONE
99 @ AND ONLY ONE of the following 3 interrupt options.
100 @
101 @ __FastInterrupts
102 @ Uncomment this line for minimal interrupt processing.
103 @ This allows 160 bytes of interrupt stack space with the
104 @ default lnkscript.
105 @
106 @ __SingleInterrupts
107 @ Uncomment this line if you wish to use a table of function
108 @ pointers to process specific interrupts. This allows 160
109 @ bytes of interrupt stack space with the default lnkscript.
110 @
111 @ __MultipleInterrupts
112 @ Uncomment this line to allow multiple-interrupts-at-once
113 @ support. If you have several interrupts where one can
114 @ occur while another is being serviced then you need to
115 @ enable this option. This option uses the main stack instead
116 @ of the interrupt stack so you have access to a larger stack.
118 .equ __FastInterrupts, 1
119 @ .equ __SingleInterrupts, 1
120 @ .equ __MultipleInterrupts, 1
123 @ Uncomment the following line to disable sound and enter an
124 @ infinite loop if cart is removed during game play. You
125 @ must have the cart interrupt enabled for this to work and
126 @ __ISRinIWRAM, above, must be enabled (not commented out.)
128 @ .equ __HandleCartInterrupt, 1
130 @ The following prevents IRQ stack overflow by switching to
131 @ System mode (User stack) when handling multiple interrupts.
132 @ To force use of IRQ stack only, comment out the following line.
134 .equ __SwitchToUserStack, 1
136 @ !!!! NOTE: THE COPY ROUTINES IN THIS FILE WORK ON 4 BYTE
137 @ BOUNDARIES. YOUR LINKER SCRIPT MUST ALIGN SECTION STARTS
138 @ AND SECTION ENDS FOR SECTIONS THAT GET COPIED TO RAM WITH
139 @ ALIGN(4) !!!!
141 .GLOBAL _start
142 _start:
143 .ALIGN
144 .CODE 32
145 @ Start Vector
147 b rom_header_end
149 @ Nintendo Logo Character Data (8000004h)
150 @ .fill 156,1,0
151 .long 0x51aeff24,0x21a29a69,0x0a82843d
152 .long 0xad09e484,0x988b2411,0x217f81c0,0x19be52a3
153 .long 0x20ce0993,0x4a4a4610,0xec3127f8,0x33e8c758
154 .long 0xbfcee382,0x94dff485,0xc1094bce,0xc08a5694
155 .long 0xfca77213,0x734d849f,0x619acaa3,0x27a39758
156 .long 0x769803fc,0x61c71d23,0x56ae0403,0x008438bf
157 .long 0xfd0ea740,0x03fe52ff,0xf130956f,0x85c0fb97
158 .long 0x2580d660,0x03be63a9,0xe2384e01,0xff34a2f9
159 .long 0x44033ebb,0xcb900078,0x943a1188,0x637cc065
160 .long 0xaf3cf087,0x8be425d6,0x72ac0a38,0x07f8d421
162 @ Game Title (80000A0h)
163 .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
164 .byte 0x00,0x00,0x00,0x00
166 .ifdef __MultibootDedicated
167 @ Game Code (80000ACh)
168 .ascii "MB "
169 .else
170 @ Game Code (80000ACh)
171 .byte 0x00,0x00,0x00,0x00
172 .endif
174 @ Maker Code (80000B0h)
175 .byte 0x30,0x31
177 @ Fixed Value (80000B2h)
178 .byte 0x96
180 @ Main Unit Code (80000B3h)
181 .byte 0x00
183 @ Device Type (80000B4h)
184 .byte 0x00
186 @ Unused Data (7Byte) (80000B5h)
187 .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00
189 @ Software Version No (80000BCh)
190 .byte 0x00
192 @ Complement Check (80000BDh)
193 .byte 0xf0
195 @ Checksum (80000BEh)
196 .byte 0x00,0x00
198 .ALIGN
199 .ARM @ ..or you can use CODE 32 here
201 rom_header_end:
202 b start_vector @ This branch must be here for proper
203 @ positioning of the following header.
204 @ DO NOT REMOVE IT.
206 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
207 @ The following reserved bytes are used if the code is compiled for @
208 @ multiboot mode. It does not hurt anything to leave this header in
209 @ even if the code is not compiled for multiboot. The GBA BIOS will
210 @ auto-patch the first two bytes with 0x03 and 0x01, respectively,
211 @ before running any code if it is executed as multiboot.
212 @
214 @ The following two bytes are included even for non-multiboot supporting
215 @ builds to guarantee that any generic library code that depends on them
216 @ will still be functional.
218 .GLOBAL __boot_method, __slave_number
220 __boot_method:
221 .byte 0 @ boot method (0=ROM boot, 3=Multiplay boot)
222 __slave_number:
223 .byte 0 @ slave # (1=slave#1, 2=slave#2, 3=slave#3)
225 .ifdef __MultiBootInclude
227 .byte 0 @ reserved
228 .byte 0 @ reserved
229 .word 0 @ reserved
230 .word 0 @ reserved
231 .word 0 @ reserved
232 .word 0 @ reserved
233 .word 0 @ reserved
234 .word 0 @ reserved
235 .endif
236 @ @
237 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
240 @@@@@@@@@@@@@@@@@@@@@@
241 @ Reset @
242 @@@@@@@@@@@@@@@@@@@@@@
244 .GLOBAL start_vector
245 .ALIGN
246 .ARM @ ..or you can use CODE 32 here
247 start_vector:
248 mov r0, #0x12 @ Switch to IRQ Mode
249 msr cpsr, r0
250 ldr sp,=__sp_irq @ Set SP_irq
251 mov r0, #0x1f @ Switch to System Mode
252 msr cpsr, r0
253 ldr sp,=__sp_usr @ Set SP_usr
255 @ Enter Thumb mode
256 adr r0,1f + 1 @ add r0,pc,#1 also works here
257 @ for those that want to conserve labels.
258 bx r0
260 .THUMB @ ..or you can use .CODE 16 here
261 1:
263 .ifdef __InterruptSupport
264 ldr r1, =__intr_vector_buf @ Set Interrupt Address
265 ldr r0, =intr_main
266 str r0, [r1]
267 .endif
269 .ifdef __MultiBootInclude
271 @ *** Multiboot Copy Routine ***
272 @ Check the Program Counter to see if code is running
273 @ at 0x2000000 or 0x8000000. If it is running at 0x8000000
274 @ then copy 256K bytes of it to 0x2000000 and then branch
275 @ to 0x2000000.
276 @ The reason for all this is to allow a program to be used
277 @ "as is" with an flash cart/emulator or with an MBV2-style
278 @ multiboot cable.
279 @ NOTE: You can also detect if this ROM is running from
280 @ 0x2000000 by checking the multiboot header above.
282 ldr r0,=__text_start
283 lsl r0,#5 @ Was code compiled at 0x08000000 or higher?
284 bcs DoEWRAMClear @ yes, you can not run it in external WRAM
286 @ Make sure we are in ExWRAM
288 mov r0,pc
289 lsl r0,#5 @ Are we running from ROM (0x8000000 or higher) ?
290 bcc SkipEWRAMClear @ No, so no need to do a copy.
292 @ We were started in ROM, silly emulators. :P
293 @ So we need to copy to ExWRAM.
295 mov r3,#0x40
296 lsl r3,#12 @ r3 = 0x40000
297 lsl r2,r3,#7 @ r2 = 0x2000000
298 mov r6,r2 @ r6 = 0x2000000
299 lsl r1,r2,#2 @ r1 = 0x8000000
301 bl CopyMem
303 @ Jump to the code to execute
305 bx r6
306 .endif
308 DoEWRAMClear:
309 @ Clear External WRAM to 0x00
311 mov r1,#0x40
312 lsl r1,#12 @ r1 = 0x40000
313 lsl r0,r1,#7 @ r0 = 0x2000000
314 bl ClearMem
316 SkipEWRAMClear:
317 @ ldr r0,=AgbMain
318 @ bx r0
320 @ Clear Internal WRAM to 0x00
321 mov r0,#3
322 lsl r0,#24 @ r0 = 0x3000000
323 ldr r1,=__sp_usr_offset - 16
324 bl ClearMem
326 .ifdef __MultiBootInclude
327 @ Clear BSS section to 0x00
328 @ (Sometimes BSS may be in External WRAM)
329 ldr r0,=__bss_start
330 ldr r1,=__bss_end
331 sub r1,r0
332 bl ClearMem
333 .endif
335 @ Copy initialized data (data section) from LMA to VMA (ROM to RAM)
336 ldr r1,=__data_lma
337 ldr r2,=__data_start
338 ldr r4,=__data_end
339 bl CopyMemChk
341 @ Copy internal work ram (iwram section) from LMA to VMA (ROM to RAM)
342 ldr r1,=__iwram_lma
343 ldr r2,=__iwram_start
344 ldr r4,=__iwram_end
345 bl CopyMemChk
347 @ Copy internal work ram overlay 0 (iwram0 section) from LMA to VMA (ROM to RAM)
348 ldr r2,=__load_stop_iwram0
349 ldr r1,=__load_start_iwram0
350 sub r3,r2,r1 @ Is there any data to copy?
351 beq CIW0Skip @ no
353 ldr r2,=__iwram_overlay_start
354 bl CopyMem
355 CIW0Skip:
357 @ Copy external work ram (ewram section) from LMA to VMA (ROM to RAM)
358 ldr r1,=__ewram_lma
359 ldr r2,=__ewram_start
360 ldr r4,=__ewram_end
361 bl CopyMemChk
363 @ Copy external work ram overlay 0 (ewram0 section) from LMA to VMA (ROM to RAM)
364 ldr r2,=__load_stop_ewram0
365 ldr r1,=__load_start_ewram0
366 sub r3,r2,r1 @ Is there any data to copy?
367 beq CEW0Skip @ no
369 ldr r2,=__ewram_overlay_start
370 bl CopyMem
371 CEW0Skip:
373 @ Jump to user code
375 mov r0,#0 @ int argc
376 mov r1,#0 @ char *argv[]
378 ldr r3,=start_vector
379 mov lr,r3 @ Set start_vector as return address
381 .ifdef __CPPSupport
382 ldr r3,=main
383 .else
384 ldr r3,=AgbMain
385 .endif
386 bx r3
389 .GLOBAL __FarFunction,__FarProcedure
390 .THUMB_FUNC
391 __FarFunction:
392 .THUMB_FUNC
393 __FarProcedure:
394 bx r0
395 nop
396 nop @ This nop is here to allow unmapped memory to be used as
397 @ as a delay of almost 1 sec with a 1 cycle resolution.
398 @ Read this for technical info:
399 @ http://www.devrs.com/gba/files/gbadevfaqs.php#RepeatUses
401 @ Clear memory to 0x00 if length != 0
402 @ r0 = Start Address
403 @ r1 = Length
405 ClearMem:
406 @ cmp r1,#0 @ Is length zero?
407 @ beq ClearMX @ yes, exit
409 mov r2,#3 @ These commands are used in cases where
410 add r1,r2 @ the length is not a multiple of 4,
411 bic r1,r2 @ even though it should be.
413 beq ClearMX @ Length is zero so exit
415 .ifdef __DMACopyClear
416 ldr r2,reg_base
417 lsr r1,#2 @ r1 = (length/4) & 0xffff
419 adr r3,fill_val
420 str r3,[r2,#0x4] @ Set source address (fill value)
421 str r0,[r2,#0x8] @ Set destination address (fill dest address)
422 strh r1,[r2,#0xc] @ Set DMA length
423 ldr r1,=0x8500 @ dma_clrb
424 strh r1,[r2,#0xe] @ Start DMA
425 .else
426 mov r2,#0
427 ClrLoop:
428 stmia r0!,{r2}
429 sub r1,#4
430 bne ClrLoop
431 .endif
432 ClearMX:
433 bx lr
435 @ Copy memory if length != 0
436 @ r1 = Source Address
437 @ r2 = Dest Address
438 @ r4 = Dest Address + Length
440 CopyMemChk:
441 sub r3,r4,r2 @ Is there any data to copy?
442 @ beq CIDExit @ no
444 @ Copy memory
445 @ r1 = Source Address
446 @ r2 = Dest Address
447 @ r3 = Length
449 CopyMem:
450 mov r0,#3 @ These commands are used in cases where
451 add r3,r0 @ the length is not a multiple of 4,
452 bic r3,r0 @ even though it should be.
454 beq CIDExit @ Length is zero so exit
456 .ifdef __DMACopyClear
457 ldr r0,reg_base
458 lsr r3,#2 @ r3 = (length/4) & 0xffff
460 str r1,[r0,#0x4] @ Set source address
461 str r2,[r0,#0x8] @ Set destination address
462 strh r3,[r0,#0xc] @ Set DMA length
463 ldr r3,=0x8400 @ dma_copy
464 strh r3,[r0,#0xe] @ Start DMA
465 .else
466 CIDLoop:
467 ldmia r1!,{r0}
468 stmia r2!,{r0}
469 sub r3,#4
470 bne CIDLoop
471 .endif
472 CIDExit:
473 If_Undefined_Reference__rename_main_or_AgbMain_to_each_other_in_your_C_file:
474 bx lr
476 .ALIGN
478 .ifdef __DMACopyClear
479 fill_val: .word 0
480 reg_base: .word 0x040000d0
481 .endif
483 .ALIGN
484 .POOL
486 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
487 @ Interrupt Processing @
488 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
490 .ifdef __ISRinIWRAM
491 .SECTION .iwram,"ax",%progbits
492 .endif
494 .EXTERN IntrTable
495 .EXTERN InterruptProcess
496 .GLOBAL intr_main
497 .ALIGN
498 .ARM
500 @ NOTE: Ifyou copy the following code (start: intr_main -
501 @ end: intr_main_end) to internal WRAM then do not forget
502 @ to copy everything between these two labels. The .POOL
503 @ data must be copied since it is used by intr_main.
505 @ NOTE2: If __ISRinIWRAM is defined then the copy to
506 @ IWRAM is done automatically for you.
508 .ifdef __InterruptSupport
510 .ifdef __FastInterrupts
511 intr_main:
512 ldr r0,=InterruptProcess
513 bx r0
514 .endif
516 .ifdef __SingleInterrupts
517 intr_main:
518 @ Single interrupts support
519 mov r3, #0x4000000 @ REG_BASE
520 ldr r2, [r3,#0x200]! @ Read REG_IE
521 and r1, r2, r2, lsr #16 @ r1 = IE & IF
522 ldr r2, =IntrTable
524 ands r0, r1, #1 @ V-Blank Interrupt
525 bne jump_intr
526 add r2, r2, #4
527 ands r0, r1, #2 @ H-Blank Interrupt
528 bne jump_intr
529 add r2, r2, #4
530 ands r0, r1, #4 @ V Counter Interrupt
531 bne jump_intr
532 add r2, r2, #4
533 ands r0, r1, #8 @ Timer 0 Interrupt
534 bne jump_intr
535 add r2, r2, #4
536 ands r0, r1, #0x10 @ Timer 1 Interrupt
537 bne jump_intr
538 add r2, r2, #4
539 ands r0, r1, #0x20 @ Timer 2 Interrupt
540 bne jump_intr
541 add r2, r2, #4
542 ands r0, r1, #0x40 @ Timer 3 Interrupt
543 bne jump_intr
544 add r2, r2, #4
545 ands r0, r1, #0x80 @ Serial Communication Interrupt
546 bne jump_intr
547 add r2, r2, #4
548 ands r0, r1, #0x100 @ DMA0 Interrupt
549 bne jump_intr
550 add r2, r2, #4
551 ands r0, r1, #0x200 @ DMA1 Interrupt
552 bne jump_intr
553 add r2, r2, #4
554 ands r0, r1, #0x400 @ DMA2 Interrupt
555 bne jump_intr
556 add r2, r2, #4
557 ands r0, r1, #0x800 @ DMA3 Interrupt
558 bne jump_intr
559 add r2, r2, #4
560 ands r0, r1, #0x1000 @ Key Interrupt
561 bne jump_intr
562 add r2, r2, #4
563 ands r0, r1, #0x2000 @ Cart Interrupt
565 .ifdef __HandleCartInterrupt
566 strneb r0, [r3, #0x84 - 0x200] @ Stop sound if cart removed (REG_SOUNDCNT_X)
567 loop: bne loop @ Infinite loop if cart removed
568 .endif
570 jump_intr:
571 strh r0, [r3, #2] @ IF Clear
572 ldr r0, [r2] @ Jump to user IRQ process
573 bx r0
574 .endif
576 .ifdef __MultipleInterrupts
577 intr_main:
578 @ Multiple interrupts support
579 mov r2, #0x4000000 @ REG_BASE
580 ldr r3, [r2,#0x200]! @ r2 = IE : r3 = IF|IE
581 ldrh r1, [r2, #0x8] @ r1 = IME
582 mrs r0, spsr
583 stmfd sp!, {r0-r2,lr} @ {spsr, IME, REG_IE, lr} // IF|IE
585 mov r0, #1 @ IME = 1 (To permit multiple interrupts if
586 @ an interrupt occurs)
587 strh r0, [r2, #0x8]
588 and r1, r3, r3, lsr #16 @ r1 = IE & IF
589 ldr r12, =IntrTable
591 ands r0, r1, #1 @ V-blank interrupt
592 bne jump_intr
593 add r12,r12, #4
594 ands r0, r1, #2 @ H-blank interrupt
595 bne jump_intr
596 add r12,r12, #4
597 ands r0, r1, #4 @ V-counter interrupt
598 bne jump_intr
599 add r12,r12, #4
600 ands r0, r1, #8 @ Timer 0 interrupt
601 bne jump_intr
602 add r12,r12, #4
603 ands r0, r1, #0x10 @ Timer 1 interrupt
604 bne jump_intr
605 add r12,r12, #4
606 ands r0, r1, #0x20 @ Timer 2 interrupt
607 bne jump_intr
608 add r12,r12, #4
609 ands r0, r1, #0x40 @ Timer 3 interrupt
610 bne jump_intr
611 add r12,r12, #4
612 ands r0, r1, #0x80 @ Serial Communication Interrupt
613 bne jump_intr
614 add r12,r12, #4
615 ands r0, r1, #0x100 @ DMA 0 interrupt
616 bne jump_intr
617 add r12,r12, #4
618 ands r0, r1, #0x200 @ DMA 1 interrupt
619 bne jump_intr
620 add r12,r12, #4
621 ands r0, r1, #0x400 @ DMA 2 interrupt
622 bne jump_intr
623 add r12,r12, #4
624 ands r0, r1, #0x800 @ DMA 3 interrupt
625 bne jump_intr
626 add r12,r12, #4
627 ands r0, r1, #0x1000 @ Key interrupt
628 bne jump_intr
629 add r12,r12, #4
630 ands r0, r1, #0x2000 @ Cart interrupt
632 .ifdef __HandleCartInterrupt
633 strneb r0, [r2, #0x84 - 0x200] @ Stop sound if cart removed (REG_SOUNDCNT_X)
634 loop: bne loop @ Infinite loop if cart removed
635 .endif
637 jump_intr:
638 strh r0, [r2, #2] @ Clear IF
640 @ Enable multiple interrupts & switch to system
641 @ mode if __SwitchToUserStack is defined.
643 mrs r3, cpsr
644 .ifdef __SwitchToUserStack
645 bic r3, r3, #0xdf @ \__
646 orr r3, r3, #0x1f @ / --> Enable IRQ & FIQ. Set CPU mode to System.
647 .else
648 bic r3, r3, #0xc0 @ Enable IRQ & FIQ
649 .endif
650 msr cpsr, r3
652 ldr r0, [r12]
654 stmfd sp!, {lr}
655 adr lr, IntrRet
656 bx r0
657 IntrRet:
658 ldmfd sp!, {lr}
660 @ Disable multiple interrupts & switch to IRQ Mode
661 @ if __SwitchToUserStack is defined.
663 mrs r3, cpsr
664 .ifdef __SwitchToUserStack
665 bic r3, r3, #0xdf @ \__
666 orr r3, r3, #0x92 @ / --> Disable IRQ. Enable FIQ. Set CPU mode to IRQ.
667 .else
668 orr r3, r3, #0x80 @ Disable IRQ.
669 .endif
670 msr cpsr, r3
672 ldmfd sp!, {r0-r2,lr} @ {spsr, IME, REG_IE, lr} //IF|IE
673 @ strh r3, [r2] @ set IE
674 strh r1, [r2, #0x8] @ restore REG_IME
675 msr spsr, r0 @ restore spsr
676 bx lr
678 .endif
680 .ALIGN
681 .POOL @ Ifyou copy the intr_main routine, above, to internal
682 @ RAM then copy the pool data as well because IntrTable
683 @ address is stored here. Use intr_main_end as last address+1.
684 intr_main_end:
685 .endif
687 .ALIGN
688 .POOL
691 .END