transcribe fakeasm into realasm (IV)
[Chiptunes.git] / foo.S
1 /* REGISTER NAMES */
2 #define zero r16
3 #define acc r17
4 #define i0 r18
5 #define i1 r19
6 #define i2 r20
7 #define i3 r21
8 #define n r22
9 #define s r23
10 #define _ r24
11 ; r25
12 #define x r26 //==Xlo==Mh
13 #define t r27 //==Xhi==Ml
14 ; r28
15 ; r29
16 ; r30 Zlo
17 ; r31 Zhi
18 ; aliases:
19 #define Xlo r26
20 #define Xhi r27
21 #define Mh r26 //mod3 vars
22 #define Ml r27 // -"-
23
24 /* I/O REGISTERS */
25 OCR0AL = 0x26
26 DDRB = 0x01
27 PUEB = 0x03
28 SPL = 0x3D
29 SPH = 0x3E
30 CCP = 0x3C
31 CLKPSR = 0x36
32 SMCR = 0x3A
33 TCCR0A = 0x2E
34 TCCR0B = 0x2D
35 TIMSK0 = 0x2B
36 TIFR0 = 0x2A
37
38 .section .data
39 data:
40 .byte 0x84, 0x9d, 0xb0, 0x69, 0x9d, 0x84, 0x69, 0x58
41 .byte 0x75, 0x8c, 0xb0, 0x69, 0x8c, 0x75, 0x69, 0x58
42
43 .section .text
44
45 mod3: ; mod3(Mh.Ml) -> t
46 #define tmp _
47 ADD Ml, Mh
48 CLR Mh
49 ADC Mh, zero
50 MOV tmp, Ml
51 SWAP tmp
52 ANDI tmp, 0x0f
53 SWAP Mh
54 OR tmp, Mh
55 ANDI Ml, 0x0f
56 ADD Ml, tmp
57 MOV tmp, Ml
58 LSR tmp
59 LSR tmp
60 ANDI Ml, 0x03
61 ADD Ml, tmp
62 MOV tmp, Ml
63 LSR tmp
64 LSR tmp
65 ANDI Ml, 0x03
66 ADD Ml, tmp
67 CPI Ml, 3
68 BRPL skip
69 SUBI Ml, 3
70 skip:
71 RET
72 #undef tmp
73
74 ; definitions to mul-tree readable:
75 #define a1 x
76 #define a2 _
77 .macro always _bit ; nop; for when a test() is not necessary (see tree)
78 .endm
79 .macro never _bit ; nop; for when a test() is not necessary (see tree)
80 .endm
81 .macro test _bit,_jmpto
82 SBRC t, \_bit
83 RJMP \_jmpto
84 .endm
85 .macro shift16
86 LSR a2
87 ROR a1
88 .endm
89 .macro shift8 ; top three bits don't need to be corrrect, so save cycles by not carrying
90 LSR a1
91 .endm
92 .macro shift0 ; nop; last shift is common
93 .endm
94 .macro add_shift16
95 ADD a1, i0
96 ADC a2, i1
97 shift16
98 .endm
99 .macro add_shift8 ; ditto with carrying
100 ADD a1, i0
101 shift8
102 .endm
103 .macro add_shift0 ; last shift is common
104 ADD a1, i0
105 .endm
106 #undef a2
107 #undef a1
108
109 g: ; g(i, t) -> t
110 #define tmp _
111 ANDI t, 0x07
112 MOV tmp, i2
113 ANDI tmp, 3
114 TST tmp
115 CPSE tmp, zero
116 SUBI t, -8
117 #undef tmp
118
119 #define tmp _
120 MOV tmp, t ; NOTE: must move value away from `t`, as that is also hi(X)
121 LDI Xhi, hi8(data) ; TODO: can skip if &data < 0xff (it is)
122 LDI Xlo, lo8(data)
123 ADD Xlo, tmp ;<-- the offset (formerly `t`) into data[]
124 ADC Xhi, zero ; ditto skip
125 LD tmp, X
126 MOV t, tmp
127 #undef tmp
128
129 #define a1 x
130 #define a2 _
131 #define a0 t
132 CLR a2
133 CLR a1
134
135 /* decision tree multiplication saves cycles and (hopefully) reduces code size
136 _xxx?
137 / \
138 _xx?0 _xx1?
139 | |
140 _x?00 _x?01
141 / \ / \
142 _?000 _?100 _?001 _?101
143 / \ / \ | / \
144 _0000 _1000 _0100 _1100 _1001 _0101 _1101
145 | | | | | | |
146 ... ... ... ... ... ... ...
147 | | | | | | |
148 B0 58 84 8C 69 75 9D */
149 test 0, m____1
150 m____0: shift16
151 never 1
152 m___00: shift16
153 test 2, m__100
154 m__000: shift16
155 test 3, m_1000
156 m_0000: shift16
157 always 4
158 add_shift16
159 always 5
160 add_shift8
161 never 6
162 shift8
163 always 7
164 add_shift0
165 RJMP end_mul ; calc'd 0xb0
166
167 m_1000: add_shift16
168 always 4
169 add_shift16
170 never 5
171 shift8
172 always 6
173 add_shift8
174 never 7
175 shift0
176 RJMP end_mul ; calc'd 0x58
177
178 m__100: add_shift16
179 test 3, m_1100
180 m_0100: shift16
181 RJMP upper_8 ;'ll calc 0x84
182
183 m_1100: add_shift16
184 upper_8: ; used twice, so deduplicated
185 never 4
186 shift16
187 never 5
188 shift8
189 never 6
190 shift8
191 always 7
192 add_shift0
193 RJMP end_mul ; calc'd 0x8c
194
195 m____1: add_shift16
196 never 1
197 m___01: shift16
198 test 2, m__101
199 m__001: shift16
200 always 3
201 m_1001: add_shift16
202 never 4
203 shift16
204 always 5
205 add_shift8
206 always 6
207 add_shift8
208 never 7
209 shift0
210 RJMP end_mul ; calc'd 0x69
211
212 m__101: add_shift16
213 test 3, m_1101
214 m_0101: shift16
215 always 4
216 add_shift16
217 always 5
218 add_shift8
219 always 6
220 add_shift8
221 never 7
222 shift0
223 RJMP end_mul ; calc'd 0x75
224
225 m_1101: add_shift16
226 always 4
227 add_shift16
228 never 5
229 shift8
230 never 6
231 shift8
232 always 7
233 add_shift0
234 ; calc'd 0x9d
235
236 end_mul:
237 LSR a1 ;final shift is a common operation for all
238
239 MOV t, a1 ;;TODO: use a1 in main() directly
240 #undef a0
241 #undef a1
242 #undef a2
243 RET ; TODO: replace CALL/RET with IJMP?
244
245 main:
246 CLR zero
247 CLR i0
248 CLR i1
249 CLR i2
250 CLR i3
251 ;;TODO: setup stack pointer, portb, clock, sleep mode, timer0
252 RJMP sample
253 sample: ;;TODO: this will probably become the timer0 overflow interrupt handler
254 MOV n, i2
255 LSL n
256 LSL n
257 #define tmp _
258 MOV tmp, i1
259 SWAP tmp
260 ANDI tmp, 0x0f
261 LSR tmp
262 LSR tmp
263 OR n, tmp
264 #undef tmp
265 MOV s, i3
266 LSR s
267 ROR s
268 ANDI s, 0x80
269 #define tmp _
270 MOV tmp, i2
271 LSR tmp
272 OR s, tmp
273 #undef tmp
274
275 ; voice 1:
276 MOV t, n
277 RCALL g
278 SWAP t
279 ANDI t, 1
280 MOV acc, t
281
282 ; voice 2:
283 #define tmp _
284 MOV tmp, i2
285 LSL tmp
286 LSL tmp
287 LSL tmp
288 MOV t, i1
289 SWAP t
290 ANDI t, 0xf
291 LSR t
292 OR t, tmp
293 #undef tmp
294 EOR t, n
295 RCALL g
296 LSR t
297 LSR t
298 ANDI t, 3
299 AND t, s
300 ADD acc, t
301
302 ; voice 3:
303 MOV Ml, i2
304 SWAP Ml
305 ANDI Ml, 0xf0
306 LSL Ml
307 #define tmp _
308 MOV tmp, i1
309 LSR tmp
310 LSR tmp
311 LSR tmp
312 OR Ml, tmp
313 #undef tmp
314 MOV Mh, i3
315 SWAP Mh
316 ANDI Mh, 0xf0
317 LSL Mh
318 #define tmp _
319 MOV tmp, i2
320 LSR tmp
321 LSR tmp
322 LSR tmp
323 OR Mh, tmp
324 #undef tmp
325 RCALL mod3
326 ADD t, n
327 RCALL g
328 LSR t
329 LSR t
330 ANDI t, 3
331 MOV x, s
332 INC x
333 #define tmp _
334 MOV tmp, x
335 LSR tmp
336 LSR tmp
337 ADD tmp, x
338 ROR tmp
339 LSR tmp
340 ADD tmp, x
341 ROR tmp
342 LSR tmp
343 ADD tmp, x
344 ROR tmp
345 LSR tmp
346 AND t, tmp
347 #undef tmp
348 ADD acc, t
349
350 ; voice 4:
351 MOV Ml, i2
352 SWAP Ml
353 ANDI Ml, 0xf0
354 LSL Ml
355 LSL Ml
356 #define tmp _
357 MOV tmp, i1
358 LSR tmp
359 LSR tmp
360 OR Ml, tmp
361 #undef tmp
362 MOV Mh, i3
363 SWAP Mh
364 ANDI Mh, 0xf0
365 LSL Mh
366 LSL Mh
367 #define tmp _
368 MOV tmp, i2
369 LSR tmp
370 LSR tmp
371 OR Mh, tmp
372 #undef tmp
373 RCALL mod3
374 SUB t, n
375 NEG t
376 SUBI t, -8
377 RCALL g
378 LSR t
379 ANDI t, 3
380 INC s
381 #define tmp _
382 MOV tmp, s
383 LSR tmp
384 ADD tmp, s
385 ROR tmp
386 LSR tmp
387 LSR tmp
388 ADD tmp, s
389 ROR tmp
390 ADD tmp, s
391 ROR tmp
392 LSR tmp
393 LSR tmp
394 AND t, tmp
395 #undef tmp
396 ADD acc, t
397
398 SWAP acc
399 OUT OCR0AL, acc
400 SUBI i0, -1
401 SBCI i1, -1
402 SBCI i2, -1
403 SBCI i3, -1
404
405 rjmp sample ;;TODO: -> RETI
Imprint / Impressum