 sttl ROM Interrupt Handling
 pag
*
* Interrupt handling code - all in high rom
*

* Return from interrupt level 0
*
* If 'chpflg' is set, call guy to change tasks.  This is the
* only place a task change occurs.
*

userti lda chpflg check for task change
 beq unmap
 jsr [chtask] go change tasks

* Rewrite the entire user map

unmap seti mask ints
 lbsr reset_map reset map as needed
 lbra user_exit exit to interrupt context

* Process a SWI type interrupt

swi ldx #swivec get vector
 bra process process the int

* Process a "Hardware Fault" interrupt

fault ldx #nmivec get vector
 bra process go process int

* Process an IRQ type interrupt

irq ldx #irqvec get vector
 bra process go process int

* Process a SWI3 - System Call

swi3 clc clear the carry bit
 tfr cc,dp save cc
 seti mask ints
 std userd save d register
 stx userx save x register
 clra
 exg dp,a
 sta usercc save user cc
 clr kernal
* Fetch the System call opcode
 lda #DMA_SCR>>8 -- shorten addressing
 tfr a,dp
 setdp DMA_SCR>>8
 leax 10,s point at saved PC
 stx DMA_SAR
 ldd #2 copy 2 bytes
 std DMA_CNT
 ldx #SWI3_tmp
 stx DMA_DAR
 lda umapno
 sta DMA_SCR
 lda #$40
 sta DMA_DCR
 nop
 ldd 0,x get PC value
 std DMA_SAR fetch from there
 addd #1
 std userpc save updated PC
 stx DMA_DAR
 ldd #1
 std DMA_CNT
 lda umapno
 sta DMA_SCR
 lda #$40
 sta DMA_DCR
 nop
 lda 0,x get system call opcode
 sta userpb
* Map in User Block (System Stack)
 ldb usrtop get user block page
 clra
 lslb
 rola
 std datbox+((usrseg*2)+0)*2
 addd #1
 std datbox+((usrseg*2)+1)*2
* Setup the system stack and invoke the interrupt routine
 sts usp save users stack
 lds #sysstk set up system stack
 clra -- reset DP
 tfr a,dp
 setdp $00
 clri
 lda #$08 allow interrupts/write enable TOD clock
 sta TSR
 jsr [swi3vec] invoke the interrupt routine
* Switch tasks if necessary here
 lda chpflg check for task change
 beq 00f
 jsr [chtask] go change tasks
* Update memory map if needed
00 seti mask ints
 bsr reset_map
* Update user registers CC, D, X & PC
 lda #DMA_SCR>>8 -- shorten addressing
 tfr a,dp
 setdp DMA_SCR>>8
 ldy usp user stack pointer
 sty DMA_SAR
 ldd #12
 std DMA_CNT
 ldx #SWI3_tmp
 stx DMA_DAR
 lda umapno
 sta DMA_SCR
 lda #$40
 sta DMA_DCR
 nop
 lda usercc
 sta 0,x
 ldd userd
 std 1,x
 ldd userx
 std 4,x
 ldd userpc
 std 10,x
 stx DMA_SAR
 sty DMA_DAR
 ldd #12
 std DMA_CNT
 sta DMA_SCR A=0
 ldb umapno
 orb #$40
 stb DMA_DCR
 nop
 setdp $00 reset addressing
user_exit
* Illegal Memory Protection, Watchdog Timer, TOD Write enable
 lda umapno get memory map #
 ora #$D8 select user task
 sta TSR
 lds usp reset user stack pointer
 lda #6 *** C A U T I O N ! ! ! ! ! ***
 sta FUSE
 rti return to user
*
* Reset map as needed
*
reset_map
 dec kernal dec the interrupt level
 tst urelod need to reload mapping regs?
 beq 10f no - skip
 ldx #usrmap set to map user space
 lda umapno get memory map #
 ldb #64 size of each map
 mul
 ldy #datbox
 leay d,y
 lbsr setmap
 clr urelod reset load flag
10 rts

 if (*>$FFEF)|((*>>12)=0)
 err ROM Overflow
 endif
