paul@0 | 1 | ; A task switcher for the Acorn Electron. |
paul@0 | 2 | |
paul@0 | 3 | ; Copyright (C) 2015 Paul Boddie <paul@boddie.org.uk> |
paul@0 | 4 | |
paul@0 | 5 | ; This program is free software; you can redistribute it and/or modify it under |
paul@0 | 6 | ; the terms of the GNU General Public License as published by the Free Software |
paul@0 | 7 | ; Foundation; either version 3 of the License, or (at your option) any later |
paul@0 | 8 | ; version. |
paul@0 | 9 | |
paul@0 | 10 | ; This program is distributed in the hope that it will be useful, but WITHOUT |
paul@0 | 11 | ; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
paul@0 | 12 | ; FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
paul@0 | 13 | ; details. |
paul@0 | 14 | |
paul@0 | 15 | ; You should have received a copy of the GNU General Public License along with |
paul@0 | 16 | ; this program. If not, see <http://www.gnu.org/licenses/>. |
paul@0 | 17 | |
paul@0 | 18 | .include "macros.oph" |
paul@0 | 19 | |
paul@0 | 20 | .org $2000 |
paul@0 | 21 | .text |
paul@0 | 22 | |
paul@0 | 23 | main: |
paul@0 | 24 | jsr install_handler |
paul@0 | 25 | rts |
paul@0 | 26 | |
paul@0 | 27 | ; install the interrupt handler address in IRQ1V |
paul@0 | 28 | ; |
paul@0 | 29 | ; affects: A |
paul@0 | 30 | |
paul@0 | 31 | install_handler: |
paul@0 | 32 | sei |
paul@0 | 33 | .invoke mov16 $204, old_handler |
paul@0 | 34 | .invoke store16 handler, $204 |
paul@0 | 35 | cli |
paul@0 | 36 | rts |
paul@0 | 37 | |
paul@0 | 38 | ; handle interrupts |
paul@0 | 39 | ; |
paul@0 | 40 | ; affects: (temporary stack usage) |
paul@0 | 41 | |
paul@0 | 42 | handler: |
paul@0 | 43 | pha ; A -> stack |
paul@0 | 44 | txa |
paul@0 | 45 | pha ; X -> stack |
paul@0 | 46 | tya |
paul@0 | 47 | pha ; Y -> stack |
paul@0 | 48 | .invoke push16 $70 |
paul@0 | 49 | |
paul@0 | 50 | ; test PC for execution of ROM routines |
paul@0 | 51 | ; these are probably not re-entrant |
paul@0 | 52 | |
paul@0 | 53 | ; obtain the stack location of the stored PC MSB |
paul@0 | 54 | tsx |
paul@0 | 55 | txa |
paul@0 | 56 | clc |
paul@0 | 57 | adc #6 ; offset of MSB (<empty>, Y, X, A, F, LSB, MSB) |
paul@0 | 58 | sta $70 |
paul@0 | 59 | lda #$01 ; $01xx |
paul@0 | 60 | sta $71 |
paul@0 | 61 | |
paul@0 | 62 | ldx #0 |
paul@0 | 63 | lda ($70, x) |
paul@0 | 64 | |
paul@0 | 65 | ; reference the stack location and compute PC MSB & $80 |
paul@0 | 66 | and #$80 |
paul@0 | 67 | cmp #$80 |
paul@0 | 68 | |
paul@0 | 69 | ; exit if PC MSB & $80 != 0 |
paul@0 | 70 | beq exit_handler |
paul@0 | 71 | |
paul@0 | 72 | ; increment a counter |
paul@0 | 73 | .invoke add16 1, $7000 |
paul@0 | 74 | |
paul@0 | 75 | exit_handler: |
paul@0 | 76 | .invoke pull16 $70 |
paul@0 | 77 | pla |
paul@0 | 78 | tay ; stack -> Y |
paul@0 | 79 | pla |
paul@0 | 80 | tax ; stack -> X |
paul@0 | 81 | pla ; stack -> A |
paul@0 | 82 | jmp (old_handler) |
paul@0 | 83 | |
paul@0 | 84 | old_handler: .word 0 |
paul@0 | 85 | |
paul@0 | 86 | ; vim: tabstop=4 expandtab shiftwidth=4 |