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