cbdcab4fdb
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
60 lines
2.2 KiB
ArmAsm
60 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
|
|
|
|
|