1Calling conventions, stack frame and zero page:
2
3The variables that normally are placed on the stack or in registers in C
4are instead allocated in the zero page and saved on a (fictive) stack
5when calling functions. Some locations have predefined functions though.
6Arrays allocated as automatics are stored on the stack with a pointer
7in zero page to its destination.
8
90-7 Unused (by us)
1010 Stack pointer
1111 Frame pointer
1212-14 Unused
1315 Prolog private word
1416 Prolog address, written in crt0
1517 Epilog address, written in crt0
1620-27 (Auto-increment), scratch
1730-37 (Auto-decrement), scratch
1840-47 Used by HW stack and MMPU
1950-77 Permanent, save before use.
20100-377 Addresses for subroutines, written by the linker
21
22The normal registers (AC0-AC3) are all considered scratch registers.
23
24Register classes are assigned as:
25 AC0-AC3: AREGs.
26 AC2-AC3: BREGs.
27 ...and eventually register pairs/floats as EREGs, double in FREGs.
28
29In byte code the left half of a word is the first byte (big-endian).
30This is bit 0-7 in Nova syntax.
31The stack is growing towards lower adresses (as opposed to the Eclipse stack).
32Stack pointer points to the last used stack entry, which means:
33PUSH: dec sp, store value
34POP: fetch val, inc sp
35
36Note that internally is the first 24 words stored in loc 50-77!
37So an offset is subtracted in adrput().
38
39Stack layout:
40
41 ! arg1 ! 1
42 fp -> ! arg0 ! 0
43 ! old pc! -1
44 ! old fp! -2
45 sp -> ! saved ! -3
46
47
48Stack references to zero page are converted to NAMEs, using word addresses.
49References to the stack itself are using byte offsets.
50
51Arguments are transferred on the stack. To avoid unneccessary double instructions
52they are copied to the zp use area initially. XXX? Need tests here.
53Return values in ac0 and ac1.
54
55A reference to a struct member in assembler, a = b->c; b is in ZP 50 (or on stack)
56+ is zeropage-addressing
57* is fp-adressing, assume fp in ac3
58
59# offset 0
60+ lda 0,@50 # load value from indirect ZP 50 into ac0
61or
62* lda 2,,3 # load value from (ac3) into ac2
63* lda 0,,2 # load value from (ac2) into ac0
64
65# offset 12
66+ lda 2,50 # load value from ZP 50 into ac2
67+ lda 0,12,2 # load value from (ac2+12) into ac0
68or
69* lda 2,,3 # load value from (ac3) into ac2
70* lda 0,12,2 # load value from 12(ac2) into ac0
71
72# offset 517
73+ lda %2,50 # load value from ZP 50 into ac2
74+ lda %0,.L42-.,%1 # load offset from .L42 PC-indexed
75+ addz %0,%2,skp # add offset to ac2 and skip
76+.L42: .word 517 # offset value
77+ lda %0,,%2 # load value from (ac2) into ac0
78or
79
80The prolog/epilog; they are implemented as subroutines.
81Both can be omitted if the function do not need it.
82
83
84 .word 012 # total words that needs to be saved
85func:
86 mov 3,0 # avoid trashing return address
87 jsr @prolog # go to prolog
88 ...
89 jmp @epilog # jump to epilog
90
91#ifdef prolog
92 lda 0,sp
93 sta 3,@sp
94 lda 1,fp
95 sta 1,@sp
96 sta 0,fp
97 lda 1,[Css]
98 sub 1,0
99 sta 0,sp
100#endif
101
102...
103
104 lda 2,fp
105 lda 3,-1,2
106 lda 0,-2,2
107 sta 0,fp
108 sta 2,sp
109 jmp 0,3
110
111
112#
113# decrement from stack, and save permanent registers.
114# push retreg
115# push fp
116# mov sp,fp
117# sub $w,sp
118#
119# prolog: return in ac3, fun in ac0.
120prolog: lda 1,sp
121 sta 0,@sp
122 lda 0,fp
123 sta 0,@sp
124 sta 1,fp
125 lda 0,-3,3
126 sub 0,1
127 sta 1,sp
128 jmp 0,3
129
130epilog: lda 3,fp
131 sta 3,sp
132 lda 3,@fp
133 lda 2,@fp
134 sta 2,fp
135 jmp 0,3
136
137
138
139
140
141
142
143prolog:
144 lda 2,sp # sp points to the first argument
145 sta 2,30 # store at auto-dec location
146 sta 0,@30 # store fun return address
147 lda 0,fp # fetch old fp
148 sta 0,@30 # store saved fp
149 sta 2,fp # save frame pointer
150
151 lda 0,-3,3 # stack size to subtract
152 neg 0,0,snr # Any words?
153 jmp 1f # no, get away
154 lda 1,$51 # fetch zp offset
155 sub 0,1 # get highest word
156 sta 1,31 # at auto-dec location
157
1582: lda 1,@31 # fetch word to copy
159 sta 1,@30 # on stack
160 inc 0,0,szr # count words
161 jmp 1b # more to go
162
1631: lda 0,30 # finished, get stackptr
164 sta 0,sp #
165 jmp 0,3 # get back!
166
167# epilog, need save frame pointer in ac3
168epilog:
169 lda 0,-3,3 # get words to save
170 neg 0,0,snr # any words to save?
171 jmp 1f # No, get out
172
173 lda 1,$51 # get zp offset
174 sub 0,1 # Highest word
175 sta 1,31 # auto-dec loc
176
177 lda 2,fp # get fp
178 adczl 1,1 # -2
179 add 1,2 # 2 now offset
180 sta 2,30 # auto-dec loc
181
1822: lda 1,@30
183 sta 1,@31
184 inc 0,0,szr
185 jmp 2b
186
1871: lda 2,fp # fetch current fp
188 lda 3,-1,2 # return pc
189 lda 0,-2,2 # fetch old fp
190 sta 0,fp # restore fp
191 sta 2,sp # stack pointer restored
192 jmp 0,3 # Done!
193
194#if 0
195Assembler syntax and functions.
196
197The assembler syntax mimics the DG assembler but uses AT&T syntax.
198Load and store to addresses is written "lda 0,foo" to load from address foo.
199If foo is not in zero page then the assembler will put the lda in the
200text area close to the instruction and do an indirect pc-relative load.
201
202Arithmetic instruction:
203 subsl# %0,%1,snr skip code may be omitted
204 subsl# %0,%1
205
206Load/store/jmp/jsr/isz/dsz:
207 lda %1,@disp,2 or
208 mov *disp(%2),%1
209 index may be omitted if 0 (ZP)
210 disp can only be +-127 words.
211
212 It's allowed to write "mov $32,%0" which will be converted
213 to an indirect load by the assembler.
214
215 Example of AT&T arguments:
216 01234 - Zero-page
217 L11 - Relative. Will be converted to
218 indirect + addr if distance too long
219 (%2) - indexed
220 012(%2) - indexed with offset
221 * in front of any of these will generate indirection
222#endif
223
224lbyte: movr 2,2 # get byte ID into C bit
225 lda 0,,2 # word into ac0
226 mov 2,2,snc # skip if right byte
227 movs 0,0 # swap bytes
228 jmp 0,3 # get back
229
230sbyte: sta 3,@sp
231
232 movr 2,2 # get byte ID into C bit
233 lda 1,,2 # get word
234 lda 3,[377] # get mask
235 and 3,0,snc # clear left input + skip if right byte
236 movs 1,1 # swap bytes
237 and 3,1 # clear old bits
238 add 0,1,snc # swap back if necessary
239 movs 1,1 # swap
240 sta 1,2
241
242 lda 3,sp
243 isz sp
244 jmp @0,3
245
246