File: interrupt.s

package info (click to toggle)
cc65 2.19-2
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 20,268 kB
  • sloc: ansic: 117,151; asm: 66,339; pascal: 4,248; makefile: 1,009; perl: 607
file content (119 lines) | stat: -rw-r--r-- 2,479 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
;
; 2012-01-18, Oliver Schmidt
; 2015-08-22, Greg King
;
; void __fastcall__ set_irq (irq_handler f, void *stack_addr, size_t stack_size);
; void reset_irq (void);
;

        .export         _set_irq, _reset_irq
        .interruptor    clevel_irq, 1           ; Export as low priority IRQ handler
        .import         popax, __ZP_START__, jmpvec

        .include        "zeropage.inc"

        .macpack        generic


; ---------------------------------------------------------------------------

.data

irqvec: jmp     $00FF           ; Patched at runtime

; ---------------------------------------------------------------------------

.bss

irqsp:  .res    2

zpsave: .res    zpsavespace

; ---------------------------------------------------------------------------

.code

.proc   _set_irq

        ; Keep clevel_irq from being called right now
        sei

        ; Set irq stack pointer to stack_addr + stack_size
        sta     irqsp
        stx     irqsp+1
        jsr     popax
        add     irqsp
        sta     irqsp
        txa
        adc     irqsp+1
        sta     irqsp+1

        ; Set irq vector to irq_handler
        jsr     popax
        sta     irqvec+1
        stx     irqvec+2        ; Set the user vector

        ; Restore interrupt requests and return
        cli
        rts

.endproc


.proc   _reset_irq

        lda     #$00
        sta     irqvec+2        ; High byte is enough
        rts

.endproc


.proc   clevel_irq

        ; Is C level interrupt request vector set?
        lda     irqvec+2        ; High byte is enough
        bne     @L1
        clc                     ; Interrupt not handled
        rts

        ; Save our zero page locations
@L1:    ldx     #.sizeof(::zpsave)-1
@L2:    lda     <__ZP_START__,x
        sta     zpsave,x
        dex
        bpl     @L2

        ; Save jmpvec
        lda     jmpvec+1
        pha
        lda     jmpvec+2
        pha

        ; Set C level interrupt stack
        lda     irqsp
        ldx     irqsp+1
        sta     sp
        stx     sp+1

        ; Call C level interrupt request handler
        jsr     irqvec

        ; Mark interrupt handled / not handled
        lsr

        ; Restore our zero page content
        ldx     #.sizeof(::zpsave)-1
@L3:    lda     zpsave,x
        sta     <__ZP_START__,x
        dex
        bpl     @L3

        ; Restore jmpvec and return
        pla
        sta     jmpvec+2
        pla
        sta     jmpvec+1
        rts

.endproc