1
0
mirror of https://github.com/cc65/cc65.git synced 2024-07-04 13:29:35 +00:00
cc65/libsrc/runtime/callirq.s
cuz cbdcab4fdb Change the sematics of callirq and the existing interruptors: The interrupts
must now return carry set if the interrupt has been handled, and carry clear
if not. The callirq routine will stop calling handlers with the first handler
that claims to have handled the interrupt. callirq will return the carry flag
to the caller as it came from the last interruptor called.


git-svn-id: svn://svn.cc65.org/cc65/trunk@3491 b7a2c559-68d2-44c3-8de9-860c34a00d81
2005-04-25 20:10:10 +00:00

61 lines
2.2 KiB
ArmAsm

;
; Ullrich von Bassewitz, 2004-04-04
;
; CC65 runtime: Support for calling special irq routines declared as condes
; type 2.
;
; There are two reasons, why this is a separate routine, and the generic
; condes routine in condes.s is not used:
;
; 1. Speed. Having several things hardcoded makes it faster. This is
; important if it is called in each interrupt.
;
; 2. Reentrancy. The condes routines must use self modyfiying code, which
; means it is not reentrant. An IRQ using condes, that interrupts
; another use of condes will cause unpredicatble behaviour. The current
; code avoids this by using locking mechanisms, but it's complex and
; has a size and performance penalty.
;
; 3. Special semantics: An interruptor called by callirq must tell by
; setting or resetting the carry flag if the interrupt has been handled
; (which means that the interrupt is no longer active at the interrupt
; source). callirq will call no other interruptors if this happens.
;
; As the normal condes routine, this one has the limitation of 127 table
; entries.
;
.export callirq
.export callirq_y ; Same but with Y preloaded
.import __INTERRUPTOR_TABLE__, __INTERRUPTOR_COUNT__
.code
; --------------------------------------------------------------------------
; Call all IRQ routines. The function needs to use self modifying code and
; is thereforce placed in the data segment. It will return carry set if the
; interrupt was handled and carry clear if not. The caller may choose to
; ignore this at will.
; NOTE: The routine must not be called if the table is empty!
.data
callirq:
ldy #.lobyte(__INTERRUPTOR_COUNT__*2)
callirq_y:
dey
lda __INTERRUPTOR_TABLE__,y
sta jmpvec+2 ; Modify code below
dey
lda __INTERRUPTOR_TABLE__,y
sta jmpvec+1 ; Modify code below
sty index+1 ; Modify code below
jmpvec: jsr $FFFF ; Patched at runtime
bcs done ; Bail out if interrupt handled
index: ldy #$FF ; Patched at runtime
bne callirq_y
done: rts