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