]> git.sur5r.net Git - cc65/blob - libsrc/plus4/crt0.s
Added a serial driver for the builtin 6551 of the Plus/4 (untested, but taken
[cc65] / libsrc / plus4 / crt0.s
1 ;
2 ; Startup code for cc65 (Plus/4 version)
3 ;
4 ; This must be the *first* file on the linker command line
5 ;
6
7         .export         _exit
8         .export         brk_jmp
9
10         .import         condes, initlib, donelib
11         .import         push0, callmain, zerobss
12         .import         __IRQFUNC_TABLE__, __IRQFUNC_COUNT__
13
14         .include        "zeropage.inc"
15         .include        "plus4.inc"
16
17
18 ; ------------------------------------------------------------------------
19 ; Constants
20
21 IRQInd          = $500  ; JMP $0000 - used as indirect IRQ vector
22
23 ; ------------------------------------------------------------------------
24 ; Place the startup code in a special segment to cope with the quirks of
25 ; plus/4 banking.
26
27 .segment        "STARTUP"
28
29         .word   Head            ; Load address
30 Head:   .word   @Next
31         .word   1000            ; Line number
32         .byte   $9E,"4109"      ; SYS 4109
33         .byte   $00             ; End of BASIC line
34 @Next:  .word   0               ; BASIC end marker
35
36 ; ------------------------------------------------------------------------
37 ; Actual code
38
39         sei                     ; No interrupts since we're banking out the ROM
40         sta     ENABLE_RAM
41         ldx     #zpspace-1
42 L1:     lda     sp,x
43         sta     zpsave,x        ; save the zero page locations we need
44         dex
45         bpl     L1
46         sta     ENABLE_ROM
47         cli
48
49 ; Close open files
50
51         jsr     $FFCC           ; CLRCH
52
53 ; Switch to second charset
54
55         lda     #14
56         jsr     $FFD2           ; BSOUT
57
58 ; Save system stuff and setup the stack. The stack starts at the top of the
59 ; usable RAM.
60
61         tsx
62         stx     spsave          ; save system stk ptr
63
64         lda     #<$FD00
65         sta     sp
66         lda     #>$FD00
67         sta     sp+1
68
69 ; Setup the IRQ vector in the banked RAM and switch off the ROM
70
71         ldx     #<IRQ
72         ldy     #>IRQ
73         sei                     ; No ints, handler not yet in place
74         sta     ENABLE_RAM
75         stx     $FFFE           ; Install interrupt handler
76         sty     $FFFF
77         cli                     ; Allow interrupts
78
79 ; Clear the BSS data
80
81         jsr     zerobss
82
83 ; Call module constructors
84
85         jsr     initlib
86
87 ; Initialize irqcount, which means that from now own custom linked in IRQ
88 ; handlers (via condes) will be called.
89
90         lda     #.lobyte(__IRQFUNC_COUNT__*2)
91         sta     irqcount
92
93 ; Push arguments and call main()
94
95         jsr     callmain
96
97 ; Back from main (this is also the _exit entry). Run module destructors.
98
99 _exit:  lda     #0
100         sta     irqcount        ; Disable custom IRQ handlers
101         jsr     donelib         ; Run module destructors
102
103 ; Restore system stuff
104
105         ldx     spsave
106         txs
107
108 ; Copy back the zero page stuff
109
110         ldx     #zpspace-1
111 L2:     lda     zpsave,x
112         sta     sp,x
113         dex
114         bpl     L2
115
116 ; Enable the ROM, reset changed vectors and return to BASIC
117
118         sta     ENABLE_ROM
119         jmp     $FF8A           ; RESTOR
120
121
122 ; ------------------------------------------------------------------------
123 ; IRQ handler. The handler in the ROM enables the kernal and jumps to
124 ; $CE00, where the ROM code checks for a BRK or IRQ and branches via the
125 ; indirect vectors at $314/$316.
126 ; To make our stub as fast as possible, we skip the whole part of the ROM
127 ; handler and jump to the indirect vectors directly. We do also call our
128 ; own interrupt handlers if we have any, so they need not use $314.
129
130 .segment        "LOWCODE"
131
132 IRQ:    cld                     ; Just to be sure
133         pha
134         txa
135         pha
136         tya
137         pha
138         tsx                     ; Get the stack pointer
139         lda     $0104,x         ; Get the saved status register
140         and     #$10            ; Test for BRK bit
141         bne     dobreak
142
143 ; It's an IRQ and RAM is enabled. If we have handlers, call them. We will use
144 ; a flag here instead of loading __IRQFUNC_COUNT__ directly, since the condes
145 ; function is not reentrant. The irqcount flag will be set/reset from the main
146 ; code, to avoid races.
147
148         ldy     irqcount
149         beq     @L1
150         lda     #<__IRQFUNC_TABLE__
151         ldx     #>__IRQFUNC_TABLE__
152         jsr     condes                  ; Call the IRQ functions
153
154 ; Since the ROM handler will end with an RTI, we have to fake an IRQ return
155 ; on stack, so we get control of the CPU after the ROM handler and can switch
156 ; back to RAM.
157
158 @L1:    lda     #>irq_ret       ; Push new return address
159         pha
160         lda     #<irq_ret
161         pha
162         php                     ; Push faked IRQ frame on stack
163         pha                     ; Push faked A register
164         pha                     ; Push faked X register
165         pha                     ; Push faked Y register
166         sta     ENABLE_ROM      ; Switch to ROM
167         jmp     (IRQVec)        ; Jump indirect to kernal irq handler
168
169 irq_ret:
170         sta     ENABLE_RAM      ; Switch back to RAM
171         pla
172         tay
173         pla
174         tax
175         pla
176         rti
177
178 dobreak:
179         lda     brk_jmp+2       ; Check high byte of address
180         beq     nohandler
181         jmp     brk_jmp         ; Jump to the handler
182
183 ; No break handler installed, jump to ROM
184
185 nohandler:
186         sta     ENABLE_ROM
187         jmp     (BRKVec)        ; Jump indirect to the break vector
188
189 ; ------------------------------------------------------------------------
190 ; Data
191
192 .data
193 zpsave:         .res    zpspace
194
195 ; BRK handling
196 brk_jmp:        jmp     $0000
197
198 spsave:         .res    1
199
200 .bss
201 irqcount:       .byte   0
202