transcribe fakeasm into realasm (I)
[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
7874ed03
TG
250 MOV (n, i2)
251 LSL (n)
252 LSL (n)
8ee3310e 253 #define tmp _
bc7680e3 254 MOV (tmp, i1)
5d4207f9
TG
255 SWAP (tmp)
256 ANDI (tmp, 0x0f)
3eef1ade
TG
257 LSR (tmp)
258 LSR (tmp)
128ff01a 259 OR (n, tmp)
bc7680e3 260 #undef tmp
df192822 261 MOV (s, i3)
2bbe001f 262 LSR (s)
27b03017
TG
263 ROR (s)
264 ANDI (s, 0x80)
8ee3310e 265 #define tmp _
a582bbc3
TG
266 MOV (tmp, i2)
267 LSR (tmp)
e389879f 268 OR (s, tmp)
df192822 269 #undef tmp
3b86ca43
TG
270
271 //voice 1:
3b86ca43 272 MOV (t, n)
965274e2 273 RCALL g();
c09a6ed8 274 SWAP (t)
9e62fea4 275 ANDI (t, 1)
46a8d83c 276 MOV (acc, t)
3b86ca43
TG
277
278 //voice 2:
37bf20ea 279 #define tmp _
94c4920f
TG
280 MOV (tmp, i2)
281 LSL (tmp)
282 LSL (tmp)
283 LSL (tmp)
284 MOV (t, i1)
4b0b7dc5
TG
285 SWAP (t)
286 ANDI (t, 0xf)
287 LSR (t)
94c4920f 288 OR (t, tmp)
1b023e92 289 #undef tmp
23872091 290 EOR (t, n)
965274e2 291 RCALL g();
7716b427
TG
292 LSR (t)
293 LSR (t)
294 ANDI (t, 3)
f28def6a 295 AND (t, s)
46a8d83c 296 ADD (acc, t)
3b86ca43
TG
297
298 //voice 3:
500692e4
TG
299 MOV (Ml, i2)
300 SWAP (Ml)
301 ANDI (Ml, 0xf0)
302 LSL (Ml)
8ee3310e 303 #define tmp _
500692e4
TG
304 MOV (tmp, i1)
305 LSR (tmp)
306 LSR (tmp)
307 LSR (tmp)
308 OR (Ml, tmp)
309 #undef tmp
d39a46f5
TG
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
dbf91c38 321 RCALL mod3();
18570947 322 ADD (t, n)
965274e2 323 RCALL g();
c6c6cbe5
TG
324 LSR (t)
325 LSR (t)
326 ANDI (t, 3)
f28def6a
TG
327 MOV (x, s)
328 INC (x)
37bf20ea 329 #define tmp _
f28def6a
TG
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)
51f43293 342 AND (t, tmp)
f28def6a 343 #undef tmp
46a8d83c 344 ADD (acc, t)
3b86ca43
TG
345
346 //voice 4:
649bb224
TG
347 MOV (Ml, i2)
348 SWAP (Ml)
349 ANDI (Ml, 0xf0)
350 LSL (Ml)
351 LSL (Ml)
8ee3310e 352 #define tmp _
649bb224
TG
353 MOV (tmp, i1)
354 LSR (tmp)
355 LSR (tmp)
356 OR (Ml, tmp)
357 #undef tmp
18426c43
TG
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
dbf91c38 369 RCALL mod3();
e4f7baf0
TG
370 SUB (t, n)
371 NEG (t)
902cfdea 372 SUBI (t, -8)
965274e2 373 RCALL g();
c6c6cbe5
TG
374 LSR (t)
375 ANDI (t, 3)
9548359d 376 INC (s)
37bf20ea 377 #define tmp _
9548359d 378 MOV (tmp, s)
d8af0686 379 LSR (tmp)
9548359d 380 ADD (tmp, s)
d8af0686
TG
381 ROR (tmp)
382 LSR (tmp)
383 LSR (tmp)
9548359d 384 ADD (tmp, s)
d8af0686 385 ROR (tmp)
9548359d 386 ADD (tmp, s)
d8af0686
TG
387 ROR (tmp)
388 LSR (tmp)
389 LSR (tmp)
51f43293 390 AND (t, tmp)
d8af0686 391 #undef tmp
46a8d83c 392 ADD (acc, t)
bfce2f8c 393
95fa231f 394 putchar(acc<<4); //TODO
89f35588 395 SUBI (i0, -1)
02f61e33
TG
396 ADC (i1, zero, !i0) //XXX: must use "sbci i1,-1" in the assembly version
397 ADC (i2, zero, !i0&&!i1) // sbci i2,-1
398 ADC (i3, zero, !i0&&!i1&&!i2) // sbci i3,-1
Imprint / Impressum