new version
[Chiptunes.git] / foo.c
CommitLineData
61fab018 1#include <stdio.h>
da32ed67 2#include "fakeasm.h"
61fab018 3typedef unsigned char u8;
da32ed67 4
61592bdd
TG
5u8 zero; //r16
6u8 acc; //r17
7u8 i0; //r18
8u8 i1; //r19
9u8 i2; //r20
10u8 i3; //r21
11u8 n; //r22
12u8 s; //r23
13u8 _; //r24
0f3f4522 14 //r25
e8142e8f
TG
15u8 x;/*==Ml*/ //r26 (Xlo)
16u8 t;/*==Mh*/ //r27 (Xhi)
61592bdd
TG
17 //r28
18 //r29
e8142e8f
TG
19void *Z; //r30 (Zlo)
20/*...*/ //r31 (Zhi)
37bf20ea 21#define Mh x //mod3 vars
dbf91c38 22#define Ml t // -"-
4466dd8b
TG
23
24// .section .data
25u8 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
e98ab46f 32//http://homepage.divms.uiowa.edu/~jones/bcd/mod.shtml
8d8c00e4
TG
33void mod3(void) {
34 // mod3(Mh.Ml) -> t
35 #define tmp _
5b1c6cc5
TG
36 ADD (Ml, Mh)
37 CLR (Mh)
3d517d8a
TG
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)
0e3d0279 44 ANDI (Ml, 0x0f)
2a69999d 45 ADD (Ml, tmp)
0fc1d6d3
TG
46 MOV (tmp, Ml)
47 LSR (tmp)
48 LSR (tmp)
6c72d3c1 49 ANDI (Ml, 0x03)
2a69999d
TG
50 ADD (Ml, tmp)
51 MOV (tmp, Ml)
52 LSR (tmp)
53 LSR (tmp)
54 ANDI (Ml, 0x03)
55 ADD (Ml, tmp)
c3639d5b
TG
56 CPI (Ml, 3)
57 BRPL (skip)
197a5418 58 SUBI (Ml, 3)
c3639d5b 59 skip:;
4283632d 60 RET
8d8c00e4 61 #undef tmp
e98ab46f 62}
4466dd8b
TG
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)
d35c3d70
TG
84void 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)
02f61e33 92 CPSE (tmp, zero)
d35c3d70 93 SUBI (t, -8)
02f61e33 94 #undef tmp
4466dd8b
TG
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
cc428230
TG
107 #define a1 x
108 #define a2 _
109 #define a0 t
110 CLR (a2)
111 CLR (a1)
d0324785 112
4466dd8b
TG
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
d0324785 144
4466dd8b
TG
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
d0324785 155
4466dd8b
TG
156 m__100: add_shift16
157 test (3, m_1100)
158 m_0100: shift16
159 RJMP (upper_8) //'ll calc 0x84
d0324785 160
4466dd8b
TG
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
d0324785 172
4466dd8b
TG
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
d0324785 189
4466dd8b
TG
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
d0324785 202
4466dd8b
TG
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
d0324785 213
4466dd8b 214 end_mul:
be76bfa8 215 LSR (a1) //final shift is a common operation for all
4466dd8b 216
02f61e33 217 MOV (t, a1) //TODO: use a1 in main() directly
d0324785
TG
218 #undef a0
219 #undef a1
220 #undef a2
be76bfa8 221 RET //TODO: replace CALL/RET with IJMP? (requires undoing goto-mul-hack)
61fab018
TG
222};
223
224int main(void) {
23e66ca4
TG
225 CLR (zero)
226 CLR (i0)
227 CLR (i1)
228 CLR (i2)
229 CLR (i3)
5dd8b8ff 230 for (;;) {
7874ed03
TG
231 MOV (n, i2)
232 LSL (n)
233 LSL (n)
8ee3310e 234 #define tmp _
bc7680e3 235 MOV (tmp, i1)
5d4207f9
TG
236 SWAP (tmp)
237 ANDI (tmp, 0x0f)
3eef1ade
TG
238 LSR (tmp)
239 LSR (tmp)
128ff01a 240 OR (n, tmp)
bc7680e3 241 #undef tmp
df192822 242 MOV (s, i3)
2bbe001f 243 LSR (s)
27b03017
TG
244 ROR (s)
245 ANDI (s, 0x80)
8ee3310e 246 #define tmp _
a582bbc3
TG
247 MOV (tmp, i2)
248 LSR (tmp)
e389879f 249 OR (s, tmp)
df192822 250 #undef tmp
3b86ca43
TG
251
252 //voice 1:
3b86ca43 253 MOV (t, n)
965274e2 254 RCALL g();
c09a6ed8 255 SWAP (t)
9e62fea4 256 ANDI (t, 1)
46a8d83c 257 MOV (acc, t)
3b86ca43
TG
258
259 //voice 2:
37bf20ea 260 #define tmp _
94c4920f
TG
261 MOV (tmp, i2)
262 LSL (tmp)
263 LSL (tmp)
264 LSL (tmp)
265 MOV (t, i1)
4b0b7dc5
TG
266 SWAP (t)
267 ANDI (t, 0xf)
268 LSR (t)
94c4920f 269 OR (t, tmp)
1b023e92 270 #undef tmp
23872091 271 EOR (t, n)
965274e2 272 RCALL g();
7716b427
TG
273 LSR (t)
274 LSR (t)
275 ANDI (t, 3)
f28def6a 276 AND (t, s)
46a8d83c 277 ADD (acc, t)
3b86ca43
TG
278
279 //voice 3:
500692e4
TG
280 MOV (Ml, i2)
281 SWAP (Ml)
282 ANDI (Ml, 0xf0)
283 LSL (Ml)
8ee3310e 284 #define tmp _
500692e4
TG
285 MOV (tmp, i1)
286 LSR (tmp)
287 LSR (tmp)
288 LSR (tmp)
289 OR (Ml, tmp)
290 #undef tmp
d39a46f5
TG
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
dbf91c38 302 RCALL mod3();
18570947 303 ADD (t, n)
965274e2 304 RCALL g();
c6c6cbe5
TG
305 LSR (t)
306 LSR (t)
307 ANDI (t, 3)
f28def6a
TG
308 MOV (x, s)
309 INC (x)
37bf20ea 310 #define tmp _
f28def6a
TG
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)
51f43293 323 AND (t, tmp)
f28def6a 324 #undef tmp
46a8d83c 325 ADD (acc, t)
3b86ca43
TG
326
327 //voice 4:
649bb224
TG
328 MOV (Ml, i2)
329 SWAP (Ml)
330 ANDI (Ml, 0xf0)
331 LSL (Ml)
332 LSL (Ml)
8ee3310e 333 #define tmp _
649bb224
TG
334 MOV (tmp, i1)
335 LSR (tmp)
336 LSR (tmp)
337 OR (Ml, tmp)
338 #undef tmp
18426c43
TG
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
dbf91c38 350 RCALL mod3();
e4f7baf0
TG
351 SUB (t, n)
352 NEG (t)
902cfdea 353 SUBI (t, -8)
965274e2 354 RCALL g();
c6c6cbe5
TG
355 LSR (t)
356 ANDI (t, 3)
9548359d 357 INC (s)
37bf20ea 358 #define tmp _
9548359d 359 MOV (tmp, s)
d8af0686 360 LSR (tmp)
9548359d 361 ADD (tmp, s)
d8af0686
TG
362 ROR (tmp)
363 LSR (tmp)
364 LSR (tmp)
9548359d 365 ADD (tmp, s)
d8af0686 366 ROR (tmp)
9548359d 367 ADD (tmp, s)
d8af0686
TG
368 ROR (tmp)
369 LSR (tmp)
370 LSR (tmp)
51f43293 371 AND (t, tmp)
d8af0686 372 #undef tmp
46a8d83c 373 ADD (acc, t)
bfce2f8c 374
95fa231f 375 putchar(acc<<4); //TODO
89f35588 376 SUBI (i0, -1)
02f61e33
TG
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
fe9a76e4 380 }
61fab018 381}
Imprint / Impressum