2004-04-04 14:15:45 +00:00
|
|
|
;
|
|
|
|
; 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.
|
|
|
|
;
|
2005-04-25 20:10:10 +00:00
|
|
|
; 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
|
2005-05-05 10:07:17 +00:00
|
|
|
; source). callirq will call no other interruptors if this happens. To
|
|
|
|
; simplify code, all interrupt routines will be called with carry clear
|
|
|
|
; on entry.
|
2005-04-25 20:10:10 +00:00
|
|
|
;
|
2004-04-04 14:29:10 +00:00
|
|
|
; As the normal condes routine, this one has the limitation of 127 table
|
2004-04-04 14:15:45 +00:00
|
|
|
; entries.
|
|
|
|
;
|
|
|
|
|
|
|
|
.export callirq
|
2004-04-04 14:29:10 +00:00
|
|
|
.export callirq_y ; Same but with Y preloaded
|
2004-04-04 14:15:45 +00:00
|
|
|
|
2004-09-20 10:24:59 +00:00
|
|
|
.import __INTERRUPTOR_TABLE__, __INTERRUPTOR_COUNT__
|
2004-04-04 14:15:45 +00:00
|
|
|
|
|
|
|
.code
|
|
|
|
|
|
|
|
; --------------------------------------------------------------------------
|
|
|
|
; Call all IRQ routines. The function needs to use self modifying code and
|
2005-04-25 20:10:10 +00:00
|
|
|
; 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.
|
2004-04-04 14:15:45 +00:00
|
|
|
; NOTE: The routine must not be called if the table is empty!
|
|
|
|
|
|
|
|
.data
|
|
|
|
|
2004-04-04 14:29:10 +00:00
|
|
|
callirq:
|
2004-09-20 10:24:59 +00:00
|
|
|
ldy #.lobyte(__INTERRUPTOR_COUNT__*2)
|
2004-04-04 14:29:10 +00:00
|
|
|
callirq_y:
|
2005-05-05 10:07:17 +00:00
|
|
|
clc ; Preset carry flag
|
|
|
|
loop: dey
|
2004-09-20 10:24:59 +00:00
|
|
|
lda __INTERRUPTOR_TABLE__,y
|
2004-04-04 14:15:45 +00:00
|
|
|
sta jmpvec+2 ; Modify code below
|
|
|
|
dey
|
2004-09-20 10:24:59 +00:00
|
|
|
lda __INTERRUPTOR_TABLE__,y
|
2004-04-04 14:15:45 +00:00
|
|
|
sta jmpvec+1 ; Modify code below
|
|
|
|
sty index+1 ; Modify code below
|
|
|
|
jmpvec: jsr $FFFF ; Patched at runtime
|
2005-04-25 20:10:10 +00:00
|
|
|
bcs done ; Bail out if interrupt handled
|
2004-04-04 14:15:45 +00:00
|
|
|
index: ldy #$FF ; Patched at runtime
|
2005-05-05 10:07:17 +00:00
|
|
|
bne loop
|
2005-04-25 20:10:10 +00:00
|
|
|
done: rts
|
2004-04-04 14:15:45 +00:00
|
|
|
|
|
|
|
|