gint-with-thread/src/tmu/inth-etmu.s

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 */