mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2025-01-04 07:53:34 +01:00
c37f150600
* Change gint_inth_callback() * Add intc_handler_function() to use C functions as handlers instead of writing assembler, and use it in the RTC and USB * Revisit the TMU handlers, which after moving out the callbacks, now fit into 3 gates (great!), and adapt the ETMU handler * Improve the timer driver (less code = better code, removed magic constants assuming the VBR layout on SH3/SH4, etc.) * Remove 2 gates and a gap from the compact scheme on SH3 * Define timer_configure() to replace timer_setup(), which could not be cleanly updated to support GINT_CALL() * Replace rtc_start/stop_timer with rtc_periodic_enable/disable, which is less confusing because of ETMU being "RTC timers"
96 lines
2.1 KiB
ArmAsm
96 lines
2.1 KiB
ArmAsm
/*
|
|
** gint:tmu:inth-etmu - Interrupt handlers for the RTC-bound timers
|
|
**
|
|
** This handler uses 3 consecutive blocks like the TMU handler. However this
|
|
** time 2 empty blocks after ETMU4 (0xd20, 0xd40) are used because blocks for
|
|
** ETMU are not consecutive in memory.
|
|
**
|
|
** 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 of 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.
|
|
*/
|
|
|
|
/* Gates for the extra timers (informally called ETMU) */
|
|
.global _inth_etmu4 /* 96 bytes */
|
|
.global _inth_etmux /* 32 bytes */
|
|
|
|
.section .gint.blocks, "ax"
|
|
.align 4
|
|
|
|
/* 3-block handler installed at the ETMU4 gate. */
|
|
_inth_etmu4:
|
|
mova .storage_etmu4, r0
|
|
mov #7, r2
|
|
|
|
.shared:
|
|
mov.l r8, @-r15
|
|
sts.l pr, @-r15
|
|
|
|
/* Prepare an indirect call to timer_stop(<id>) */
|
|
add #-20, r15
|
|
mov.l r2, @(4, r15)
|
|
|
|
/* Clear interrupt flag in TCR */
|
|
mov r0, r1
|
|
mov.l @(4, r1), r3
|
|
1: mov.b @r3, r0
|
|
tst #0x02, r0
|
|
and #0xfd, r0
|
|
bf/s 1b
|
|
mov.b r0, @r3
|
|
|
|
/* Invoke callback */
|
|
mov.l .gint_inth_callback, r8
|
|
mov.l @r8, r8
|
|
jsr @r8
|
|
mov.l @r1, r4
|
|
tst r0, r0
|
|
bt 2f
|
|
|
|
/* If return value is non-zero, stop the timer with another callback */
|
|
mov.l .timer_stop, r0
|
|
mov.l r0, @r15
|
|
jsr @r8
|
|
mov r15, r4
|
|
|
|
2: add #20, r15
|
|
lds.l @r15+, pr
|
|
rts
|
|
mov.l @r15+, r8
|
|
|
|
.zero 26
|
|
|
|
.timer_stop:
|
|
.long _timer_stop
|
|
.gint_inth_callback:
|
|
.long _gint_inth_callback
|
|
.storage_etmu4:
|
|
.long _tmu_callbacks + 140
|
|
.long 0xa44d00bc /* RTCR4 */
|
|
|
|
/* Generic gate for all other ETMU handlers, falling back to ETMU4. */
|
|
_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
|
|
nop
|
|
nop
|
|
|
|
.id_etmux:
|
|
.word 0 /* Timer ID */
|
|
|
|
/* Offset from VBR where ETMU4 is located; set during configure */
|
|
1: .long (.shared - _inth_etmu4)
|
|
|
|
.storage_etmux:
|
|
.long _tmu_callbacks
|
|
.long 0 /* TCR address */
|