105 lines
2.5 KiB
ArmAsm
105 lines
2.5 KiB
ArmAsm
/*
|
|
** gint:tmu:inth-etmu - Interrupt handlers for the RTC-bound timers
|
|
*/
|
|
|
|
/* Gates for the extra timers (informally called ETMU) */
|
|
.global _inth_etmu4
|
|
.global _inth_etmux
|
|
|
|
.section .gint.blocks, "ax"
|
|
.align 4
|
|
|
|
/* EXTRA TMU INTERRUPT HANDLERS - 96 BYTES
|
|
To implement the same functionalities as the standard timers, several blocks
|
|
are once again needed. This time, 2 empty blocks after ETMU4 (0xd20, 0xd40)
|
|
are used for convenience.
|
|
|
|
It would be possible to communicate between any interrupt handlers in non-
|
|
consecutive gates. A simple way is to store at runtime a pointer to the
|
|
desired object in one handler. But that costs a lot fo space. If the
|
|
relative position of interrupt handlers is known, the best option left is
|
|
the unnatural @(disp,pc) addressing mode, and it doesn't even work with the
|
|
SH3's compact VBR scheme. */
|
|
|
|
/* FIRST GATE - ETMU4 and two empty blocks */
|
|
_inth_etmu4:
|
|
mova .storage_etmu4, r0
|
|
mov #7, r2
|
|
|
|
.shared:
|
|
mov.l r2, @-r15
|
|
mov.l r8, @-r15
|
|
sts.l pr, @-r15
|
|
mov r0, r1
|
|
|
|
/* Clear interrupt flag in TCR */
|
|
mov.l @(8, r1), r3
|
|
1:
|
|
mov.b @r3, r0
|
|
tst #0x02, r0
|
|
and #0xfd, r0
|
|
bf/s 1b
|
|
mov.b r0, @r3
|
|
|
|
/* Prepare invoking the callback function */
|
|
mov.l .gint_inth_callback, r8
|
|
mov.l @r8, r8
|
|
mov.l @r1, r4
|
|
jsr @r8
|
|
mov.l @(4, r1), r5
|
|
tst r0, r0
|
|
bt 2f
|
|
|
|
/* Invoke callback; if return value is non-zero, stop timer */
|
|
mov.l .timer_stop, r4
|
|
jsr @r8
|
|
mov.l @(8, r15), r5
|
|
|
|
/* Clear the flag and possibly stop the timer */
|
|
2:
|
|
lds.l @r15+, pr
|
|
mov.l @r15+, r8
|
|
rts
|
|
add #4, r15
|
|
|
|
.zero 24
|
|
|
|
.gint_inth_callback:
|
|
.long _gint_inth_callback
|
|
.timer_stop:
|
|
.long _timer_stop
|
|
|
|
.storage_etmu4:
|
|
.long 0 /* Callback: Configured dynamically */
|
|
.long 0 /* Argument: Configured dynamically */
|
|
.long 0 /* TCR: Configured dynamically */
|
|
|
|
/* SECOND GATE - All other ETMU entries, falling back to ETMU2 */
|
|
_inth_etmux:
|
|
/* Dynamically compute the target of the jump */
|
|
stc vbr, r3
|
|
mov.l 1f, r2
|
|
add r2, r3
|
|
|
|
mova .storage_etmux, r0
|
|
mov.w .id_etmux, r2
|
|
jmp @r3
|
|
nop
|
|
|
|
.id_etmux:
|
|
.word 0 /* Timer ID */
|
|
|
|
/* Offset from VBR where extra timer 2 is located:
|
|
* 0x600 to reach the interrupt handlers
|
|
* 0x040 to jump over the entry gate
|
|
* 0x900 to reach the handler of ETMU4
|
|
* Skip over the first instructions
|
|
This is different on SH3 due to the compact scheme so it's edited
|
|
dynamically at install time. */
|
|
1: .long 0xf40 + (.shared - _inth_etmu4)
|
|
|
|
.storage_etmux:
|
|
.long 0 /* Callback: Configured dynamically */
|
|
.long 0 /* Argument: Configured dynamically */
|
|
.long 0 /* TCR: Configured dynamically */
|