7db31220c1692b3d03b3df0dffd6fa51bf7249ce
[picodrive.git] / pico / sound / ym2612_arm.s
1 /*
2  * PicoDrive
3  * (C) notaz, 2006
4  *
5  * This work is licensed under the terms of MAME license.
6  * See COPYING file in the top-level directory.
7  */
8
9 @ this is a rewrite of MAME's ym2612 code, in particular this is only the main sample-generatin loop.
10 @ it does not seem to give much performance increase (if any at all), so don't use it if it causes trouble.
11 @ - notaz, 2006
12
13 @ vim:filetype=armasm
14
15 .equiv SLOT1, 0
16 .equiv SLOT2, 2
17 .equiv SLOT3, 1
18 .equiv SLOT4, 3
19 .equiv SLOT_STRUCT_SIZE, 0x30
20
21 .equiv TL_TAB_LEN, 0x1A00
22
23 .equiv EG_ATT, 4
24 .equiv EG_DEC, 3
25 .equiv EG_SUS, 2
26 .equiv EG_REL, 1
27 .equiv EG_OFF, 0
28
29 .equiv EG_SH,                     16             @ 16.16 fixed point (envelope generator timing)
30 .equiv EG_TIMER_OVERFLOW, (3*(1<<EG_SH)) @ envelope generator timer overflows every 3 samples (on real chip)
31 .equiv LFO_SH,            25  /*  7.25 fixed point (LFO calculations)       */
32
33 .equiv ENV_QUIET,                 (2*13*256/8)/2
34
35
36 @ r5=slot, r1=eg_cnt, trashes: r0,r2,r3
37 @ writes output to routp, but only if vol_out changes
38 .macro update_eg_phase_slot slot
39     ldrb    r2, [r5,#0x17]           @ state
40     mov     r3, #1               @ 1ci
41     cmp     r2, #1
42     blt     5f                   @ EG_OFF
43     beq     3f                   @ EG_REL
44     cmp     r2, #3
45     blt     2f                   @ EG_SUS
46     beq     1f                   @ EG_DEC
47
48 0:  @ EG_ATT
49     ldr     r2, [r5,#0x20]       @ eg_pack_ar (1ci)
50     mov     r0, r2, lsr #24
51     mov     r3, r3, lsl r0
52     sub     r3, r3, #1
53     tst     r1, r3
54     bne     5f                   @ do smth for tl problem (set on init?)
55     mov     r3, r1, lsr r0
56     ldrh    r0, [r5,#0x1a]           @ volume, unsigned (0-1023)
57     and     r3, r3, #7
58     add     r3, r3, r3, lsl #1
59     mov     r3, r2, lsr r3
60     and     r3, r3, #7           @ shift for eg_inc calculation
61     mvn     r2, r0
62     mov     r2, r2, lsl r3
63     add     r0, r0, r2, asr #5
64     cmp     r0, #0               @ if (volume <= MIN_ATT_INDEX)
65     movle   r3, #EG_DEC
66     strleb  r3, [r5,#0x17]       @ state
67     movle   r0, #0
68     b       4f
69
70 1:  @ EG_DEC
71     ldr     r2, [r5,#0x24]       @ eg_pack_d1r (1ci)
72     mov     r0, r2, lsr #24
73     mov     r3, r3, lsl r0
74     sub     r3, r3, #1
75     tst     r1, r3
76     bne     5f                   @ do smth for tl problem (set on init?)
77     mov     r3, r1, lsr r0
78     ldrh    r0, [r5,#0x1a]       @ volume
79     and     r3, r3, #7
80     add     r3, r3, r3, lsl #1
81     mov     r3, r2, lsr r3
82     and     r3, r3, #7           @ shift for eg_inc calculation
83     mov     r2, #1
84     mov     r3, r2, lsl r3
85     ldr     r2, [r5,#0x1c]       @ sl (can be 16bit?)
86     add     r0, r0, r3, asr #1
87     cmp     r0, r2               @ if ( volume >= (INT32) SLOT->sl )
88     movge   r3, #EG_SUS
89     strgeb  r3, [r5,#0x17]       @ state
90     b       4f
91
92 2:  @ EG_SUS
93     ldr     r2, [r5,#0x28]       @ eg_pack_d2r (1ci)
94     mov     r0, r2, lsr #24
95     mov     r3, r3, lsl r0
96     sub     r3, r3, #1
97     tst     r1, r3
98     bne     5f                   @ do smth for tl problem (set on init?)
99     mov     r3, r1, lsr r0
100     ldrh    r0, [r5,#0x1a]       @ volume
101     and     r3, r3, #7
102     add     r3, r3, r3, lsl #1
103     mov     r3, r2, lsr r3
104     and     r3, r3, #7           @ shift for eg_inc calculation
105     mov     r2, #1
106     mov     r3, r2, lsl r3
107     add     r0, r0, r3, asr #1
108     mov     r2, #1024
109     sub     r2, r2, #1           @ r2 = MAX_ATT_INDEX
110     cmp     r0, r2               @ if ( volume >= MAX_ATT_INDEX )
111     movge   r0, r2
112     b       4f
113
114 3:  @ EG_REL
115     ldr     r2, [r5,#0x2c]       @ eg_pack_rr (1ci)
116     mov     r0, r2, lsr #24
117     mov     r3, r3, lsl r0
118     sub     r3, r3, #1
119     tst     r1, r3
120     bne     5f                   @ do smth for tl problem (set on init?)
121     mov     r3, r1, lsr r0
122     ldrh    r0, [r5,#0x1a]       @ volume
123     and     r3, r3, #7
124     add     r3, r3, r3, lsl #1
125     mov     r3, r2, lsr r3
126     and     r3, r3, #7           @ shift for eg_inc calculation
127     mov     r2, #1
128     mov     r3, r2, lsl r3
129     add     r0, r0, r3, asr #1
130     mov     r2, #1024
131     sub     r2, r2, #1           @ r2 = MAX_ATT_INDEX
132     cmp     r0, r2               @ if ( volume >= MAX_ATT_INDEX )
133     movge   r0, r2
134     movge   r3, #EG_OFF
135     strgeb  r3, [r5,#0x17]       @ state
136
137 4:
138     ldrh    r3, [r5,#0x18]       @ tl
139     strh    r0, [r5,#0x1a]       @ volume
140 .if     \slot == SLOT1
141     mov     r6, r6, lsr #16
142     add     r0, r0, r3
143     orr     r6, r0, r6, lsl #16
144 .elseif \slot == SLOT2
145     mov     r6, r6, lsl #16
146     add     r0, r0, r3
147     mov     r0, r0, lsl #16
148     orr     r6, r0, r6, lsr #16
149 .elseif \slot == SLOT3
150     mov     r7, r7, lsr #16
151     add     r0, r0, r3
152     orr     r7, r0, r7, lsl #16
153 .elseif \slot == SLOT4
154     mov     r7, r7, lsl #16
155     add     r0, r0, r3
156     mov     r0, r0, lsl #16
157     orr     r7, r0, r7, lsr #16
158 .endif
159
160 5:
161 .endm
162
163
164 @ r12=lfo_ampm[31:16], r1=lfo_cnt_old, r2=lfo_cnt, r3=scratch
165 .macro advance_lfo_m
166     mov     r2, r2, lsr #LFO_SH
167     cmp     r2, r1, lsr #LFO_SH
168     beq     0f
169     and     r3, r2, #0x3f
170     cmp     r2, #0x40
171     rsbge   r3, r3, #0x3f
172     bic     r12,r12, #0xff000000          @ lfo_ampm &= 0xff
173     orr     r12,r12, r3, lsl #1+24
174
175     mov     r2, r2, lsr #2
176     cmp     r2, r1, lsr #LFO_SH+2
177     bicne   r12,r12, #0xff0000
178     orrne   r12,r12, r2, lsl #16
179
180 0:
181 .endm
182
183
184 @ result goes to r1, trashes r2
185 .macro make_eg_out slot
186     tst     r12, #8
187     tstne   r12, #(1<<(\slot+8))
188 .if     \slot == SLOT1
189     mov     r1, r6, lsl #16
190     mov     r1, r1, lsr #17
191 .elseif \slot == SLOT2
192     mov     r1, r6, lsr #17
193 .elseif \slot == SLOT3
194     mov     r1, r7, lsl #16
195     mov     r1, r1, lsr #17
196 .elseif \slot == SLOT4
197     mov     r1, r7, lsr #17
198 .endif
199     andne   r2, r12, #0xc0
200     movne   r2, r2,  lsr #6
201     addne   r2, r2,  #24
202     addne   r1, r1,  r12, lsr r2
203 .endm
204
205
206 .macro lookup_tl r
207     tst     \r, #0x100
208     eorne   \r, \r, #0xff   @ if (sin & 0x100) sin = 0xff - (sin&0xff);
209     tst     \r, #0x200
210     and     \r, \r, #0xff
211     orr     \r, \r, r1, lsl #8
212     mov     \r, \r, lsl #1
213     ldrh    \r, [r3, \r]    @ 2ci if ne
214     rsbne   \r, \r, #0
215 .endm
216
217
218 @ lr=context, r12=pack (stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16])
219 @ r0-r2=scratch, r3=sin_tab, r5=scratch, r6-r7=vol_out[4], r10=op1_out
220 .macro upd_algo0_m
221
222     @ SLOT3
223     make_eg_out SLOT3
224     cmp     r1, #ENV_QUIET
225     movcs   r0, #0
226     bcs     0f
227     ldr     r2, [lr, #0x18]
228     ldr     r0, [lr, #0x38] @ mem (signed)
229     mov     r2, r2, lsr #16
230     add     r0, r2, r0, lsr #1
231     lookup_tl r0                  @ r0=c2
232
233 0:
234
235     @ SLOT4
236     make_eg_out SLOT4
237     cmp     r1, #ENV_QUIET
238     movcs   r0, #0
239     bcs     1f
240     ldr     r2, [lr, #0x1c]
241     mov     r0, r0, lsr #1
242     add     r0, r0, r2, lsr #16
243     lookup_tl r0                  @ r0=output smp
244
245 1:
246     @ SLOT2
247     make_eg_out SLOT2
248     cmp     r1, #ENV_QUIET
249     movcs   r2, #0
250     bcs     2f
251     ldr     r2, [lr, #0x14]       @ 1ci
252     mov     r5, r10, lsr #17
253     add     r2, r5, r2, lsr #16
254     lookup_tl r2                  @ r2=mem
255
256 2:
257     str     r2, [lr, #0x38] @ mem
258 .endm
259
260
261 .macro upd_algo1_m
262
263     @ SLOT3
264     make_eg_out SLOT3
265     cmp     r1, #ENV_QUIET
266     movcs   r0, #0
267     bcs     0f
268     ldr     r2, [lr, #0x18]
269     ldr     r0, [lr, #0x38] @ mem (signed)
270     mov     r2, r2, lsr #16
271     add     r0, r2, r0, lsr #1
272     lookup_tl r0                 @ r0=c2
273
274 0:
275     @ SLOT4
276     make_eg_out SLOT4
277     cmp     r1, #ENV_QUIET
278     movcs   r0, #0
279     bcs     1f
280     ldr     r2, [lr, #0x1c]
281     mov     r0, r0, lsr #1
282     add     r0, r0, r2, lsr #16
283     lookup_tl r0                 @ r0=output smp
284
285 1:
286     @ SLOT2
287     make_eg_out SLOT2
288     cmp     r1, #ENV_QUIET
289     movcs   r2, #0
290     bcs     2f
291     ldr     r2, [lr, #0x14]      @ 1ci
292     mov     r2, r2, lsr #16
293     lookup_tl r2                 @ r2=mem
294
295 2:
296     add     r2, r2, r10, asr #16
297     str     r2, [lr, #0x38]
298 .endm
299
300
301 .macro upd_algo2_m
302
303     @ SLOT3
304     make_eg_out SLOT3
305     cmp     r1, #ENV_QUIET
306     movcs   r0, #0
307     bcs     0f
308     ldr     r2, [lr, #0x18]
309     ldr     r0, [lr, #0x38] @ mem (signed)
310     mov     r2, r2, lsr #16
311     add     r0, r2, r0, lsr #1
312     lookup_tl r0                 @ r0=c2
313
314 0:
315     add     r0, r0, r10, asr #16
316
317     @ SLOT4
318     make_eg_out SLOT4
319     cmp     r1, #ENV_QUIET
320     movcs   r0, #0
321     bcs     1f
322     ldr     r2, [lr, #0x1c]
323     mov     r0, r0, lsr #1
324     add     r0, r0, r2, lsr #16
325     lookup_tl r0                 @ r0=output smp
326
327 1:
328     @ SLOT2
329     make_eg_out SLOT2
330     cmp     r1, #ENV_QUIET
331     movcs   r2, #0
332     bcs     2f
333     ldr     r2, [lr, #0x14]
334     mov     r2, r2, lsr #16      @ 1ci
335     lookup_tl r2                 @ r2=mem
336
337 2:
338     str     r2, [lr, #0x38] @ mem
339 .endm
340
341
342 .macro upd_algo3_m
343
344     @ SLOT3
345     make_eg_out SLOT3
346     cmp     r1, #ENV_QUIET
347     ldr     r2, [lr, #0x38] @ mem (for future)
348     movcs   r0, r2
349     bcs     0f
350     ldr     r0, [lr, #0x18]      @ 1ci
351     mov     r0, r0, lsr #16
352     lookup_tl r0                 @ r0=c2
353
354 0:
355     add     r0, r0, r2
356
357     @ SLOT4
358     make_eg_out SLOT4
359     cmp     r1, #ENV_QUIET
360     movcs   r0, #0
361     bcs     1f
362     ldr     r2, [lr, #0x1c]
363     mov     r0, r0, lsr #1
364     add     r0, r0, r2, lsr #16
365     lookup_tl r0                 @ r0=output smp
366
367 1:
368     @ SLOT2
369     make_eg_out SLOT2
370     cmp     r1, #ENV_QUIET
371     movcs   r2, #0
372     bcs     2f
373     ldr     r2, [lr, #0x14]
374     mov     r5, r10, lsr #17
375     add     r2, r5, r2, lsr #16
376     lookup_tl r2                 @ r2=mem
377
378 2:
379     str     r2, [lr, #0x38] @ mem
380 .endm
381
382
383 .macro upd_algo4_m
384
385     @ SLOT3
386     make_eg_out SLOT3
387     cmp     r1, #ENV_QUIET
388     movcs   r0, #0
389     bcs     0f
390     ldr     r0, [lr, #0x18]
391     mov     r0, r0, lsr #16      @ 1ci
392     lookup_tl r0                 @ r0=c2
393
394 0:
395     @ SLOT4
396     make_eg_out SLOT4
397     cmp     r1, #ENV_QUIET
398     movcs   r0, #0
399     bcs     1f
400     ldr     r2, [lr, #0x1c]
401     mov     r0, r0, lsr #1
402     add     r0, r0, r2, lsr #16
403     lookup_tl r0                 @ r0=output smp
404
405 1:
406     @ SLOT2
407     make_eg_out SLOT2
408     cmp     r1, #ENV_QUIET
409     bcs     2f
410     ldr     r2, [lr, #0x14]
411     mov     r5, r10, lsr #17
412     add     r2, r5, r2, lsr #16
413     lookup_tl r2
414     add     r0, r0, r2            @ add to smp
415
416 2:
417 .endm
418
419
420 .macro upd_algo5_m
421
422     @ SLOT3
423     make_eg_out SLOT3
424     cmp     r1, #ENV_QUIET
425     movcs   r0, #0
426     bcs     0f
427     ldr     r2, [lr, #0x18]
428     ldr     r0, [lr, #0x38] @ mem (signed)
429     mov     r2, r2, lsr #16
430     add     r0, r2, r0, lsr #1
431     lookup_tl r0                 @ r0=output smp
432
433 0:
434     @ SLOT4
435     make_eg_out SLOT4
436     cmp     r1, #ENV_QUIET
437     bcs     1f
438     ldr     r2, [lr, #0x1c]
439     mov     r5, r10, lsr #17
440     add     r2, r5, r2, lsr #16
441     lookup_tl r2
442     add     r0, r0, r2           @ add to smp
443
444 1:  @ SLOT2
445     make_eg_out SLOT2
446     cmp     r1, #ENV_QUIET
447     bcs     2f
448     ldr     r2, [lr, #0x14]
449     mov     r5, r10, lsr #17
450     add     r2, r5, r2, lsr #16
451     lookup_tl r2
452     add     r0, r0, r2           @ add to smp
453
454 2:
455     mov     r1, r10, asr #16
456     str     r1, [lr, #0x38] @ mem
457 .endm
458
459
460 .macro upd_algo6_m
461
462     @ SLOT3
463     make_eg_out SLOT3
464     cmp     r1, #ENV_QUIET
465     movcs   r0, #0
466     bcs     0f
467     ldr     r0, [lr, #0x18]
468     mov     r0, r0, lsr #16      @ 1ci
469     lookup_tl r0                 @ r0=output smp
470
471 0:
472     @ SLOT4
473     make_eg_out SLOT4
474     cmp     r1, #ENV_QUIET
475     bcs     1f
476     ldr     r2, [lr, #0x1c]
477     mov     r2, r2, lsr #16      @ 1ci
478     lookup_tl r2
479     add     r0, r0, r2           @ add to smp
480
481 1:  @ SLOT2
482     make_eg_out SLOT2
483     cmp     r1, #ENV_QUIET
484     bcs     2f
485     ldr     r2, [lr, #0x14]
486     mov     r5, r10, lsr #17
487     add     r2, r5, r2, lsr #16
488     lookup_tl r2
489     add     r0, r0, r2           @ add to smp
490
491 2:
492 .endm
493
494
495 .macro upd_algo7_m
496
497     @ SLOT3
498     make_eg_out SLOT3
499     cmp     r1, #ENV_QUIET
500     movcs   r0, #0
501     bcs     0f
502     ldr     r0, [lr, #0x18]
503     mov     r0, r0, lsr #16      @ 1ci
504     lookup_tl r0                 @ r0=output smp
505
506 0:
507     add     r0, r0, r10, asr #16
508
509     @ SLOT4
510     make_eg_out SLOT4
511     cmp     r1, #ENV_QUIET
512     bcs     1f
513     ldr     r2, [lr, #0x1c]
514     mov     r2, r2, lsr #16      @ 1ci
515     lookup_tl r2
516     add     r0, r0, r2           @ add to smp
517
518 1:  @ SLOT2
519     make_eg_out SLOT2
520     cmp     r1, #ENV_QUIET
521     bcs     2f
522     ldr     r2, [lr, #0x14]
523     mov     r2, r2, lsr #16      @ 1ci
524     lookup_tl r2
525     add     r0, r0, r2           @ add to smp
526
527 2:
528 .endm
529
530
531 .macro upd_slot1_m
532
533     make_eg_out SLOT1
534     cmp     r1, #ENV_QUIET
535     movcs   r10, r10, lsl #16     @ ct->op1_out <<= 16; // op1_out0 = op1_out1; op1_out1 = 0;
536     bcs     0f
537     ands    r2, r12, #0xf000
538     moveq   r0, #0
539     movne   r2, r2, lsr #12
540     addne   r0, r10, r10, lsl #16
541     movne   r0, r0, asr #16
542     movne   r0, r0, lsl r2
543
544     ldr     r2, [lr, #0x10]
545     mov     r0, r0, lsr #16
546     add     r0, r0, r2, lsr #16
547     lookup_tl r0
548     mov     r10,r10,lsl #16     @ ct->op1_out <<= 16;
549     mov     r0, r0, lsl #16
550     orr     r10,r10, r0, lsr #16
551
552 0:
553 .endm
554
555
556 /*
557 .global update_eg_phase @ FM_SLOT *SLOT, UINT32 eg_cnt
558
559 update_eg_phase:
560     stmfd   sp!, {r5,r6}
561     mov     r5, r0             @ slot
562     ldrh    r3, [r5,#0x18]       @ tl
563     ldrh    r6, [r5,#0x1a]       @ volume
564     add     r6, r6, r3
565     update_eg_phase_slot SLOT1
566     mov     r0, r6
567     ldmfd   sp!, {r5,r6}
568     bx      lr
569 .pool
570
571
572 .global advance_lfo @ int lfo_ampm, UINT32 lfo_cnt_old, UINT32 lfo_cnt
573
574 advance_lfo:
575     mov     r12, r0, lsl #16
576     advance_lfo_m
577     mov     r0, r12, lsr #16
578     bx      lr
579 .pool
580
581
582 .global upd_algo0 @ chan_rend_context *c
583 upd_algo0:
584     stmfd   sp!, {r4-r10,lr}
585     mov     lr, r0
586
587     ldr     r3, =ym_sin_tab
588     ldr     r5, =ym_tl_tab
589     ldmia   lr, {r6-r7}
590     ldr     r10, [lr, #0x54]
591     ldr     r12, [lr, #0x4c]
592
593     upd_algo0_m
594
595     ldmfd   sp!, {r4-r10,pc}
596 .pool
597
598
599 .global upd_algo1 @ chan_rend_context *c
600 upd_algo1:
601     stmfd   sp!, {r4-r10,lr}
602     mov     lr, r0
603
604     ldr     r3, =ym_sin_tab
605     ldr     r5, =ym_tl_tab
606     ldmia   lr, {r6-r7}
607     ldr     r10, [lr, #0x54]
608     ldr     r12, [lr, #0x4c]
609
610     upd_algo1_m
611
612     ldmfd   sp!, {r4-r10,pc}
613 .pool
614
615
616 .global upd_algo2 @ chan_rend_context *c
617 upd_algo2:
618     stmfd   sp!, {r4-r10,lr}
619     mov     lr, r0
620
621     ldr     r3, =ym_sin_tab
622     ldr     r5, =ym_tl_tab
623     ldmia   lr, {r6-r7}
624     ldr     r10, [lr, #0x54]
625     ldr     r12, [lr, #0x4c]
626
627     upd_algo2_m
628
629     ldmfd   sp!, {r4-r10,pc}
630 .pool
631
632
633 .global upd_algo3 @ chan_rend_context *c
634 upd_algo3:
635     stmfd   sp!, {r4-r10,lr}
636     mov     lr, r0
637
638     ldr     r3, =ym_sin_tab
639     ldr     r5, =ym_tl_tab
640     ldmia   lr, {r6-r7}
641     ldr     r10, [lr, #0x54]
642     ldr     r12, [lr, #0x4c]
643
644     upd_algo3_m
645
646     ldmfd   sp!, {r4-r10,pc}
647 .pool
648
649
650 .global upd_algo4 @ chan_rend_context *c
651 upd_algo4:
652     stmfd   sp!, {r4-r10,lr}
653     mov     lr, r0
654
655     ldr     r3, =ym_sin_tab
656     ldr     r5, =ym_tl_tab
657     ldmia   lr, {r6-r7}
658     ldr     r10, [lr, #0x54]
659     ldr     r12, [lr, #0x4c]
660
661     upd_algo4_m
662
663     ldmfd   sp!, {r4-r10,pc}
664 .pool
665
666
667 .global upd_algo5 @ chan_rend_context *c
668 upd_algo5:
669     stmfd   sp!, {r4-r10,lr}
670     mov     lr, r0
671
672     ldr     r3, =ym_sin_tab
673     ldr     r5, =ym_tl_tab
674     ldmia   lr, {r6-r7}
675     ldr     r10, [lr, #0x54]
676     ldr     r12, [lr, #0x4c]
677
678     upd_algo5_m
679
680     ldmfd   sp!, {r4-r10,pc}
681 .pool
682
683
684 .global upd_algo6 @ chan_rend_context *c
685 upd_algo6:
686     stmfd   sp!, {r4-r10,lr}
687     mov     lr, r0
688
689     ldr     r3, =ym_sin_tab
690     ldr     r5, =ym_tl_tab
691     ldmia   lr, {r6-r7}
692     ldr     r10, [lr, #0x54]
693     ldr     r12, [lr, #0x4c]
694
695     upd_algo6_m
696
697     ldmfd   sp!, {r4-r10,pc}
698 .pool
699
700
701 .global upd_algo7 @ chan_rend_context *c
702 upd_algo7:
703     stmfd   sp!, {r4-r10,lr}
704     mov     lr, r0
705
706     ldr     r3, =ym_sin_tab
707     ldr     r5, =ym_tl_tab
708     ldmia   lr, {r6-r7}
709     ldr     r10, [lr, #0x54]
710     ldr     r12, [lr, #0x4c]
711
712     upd_algo7_m
713
714     ldmfd   sp!, {r4-r10,pc}
715 .pool
716
717
718 .global upd_slot1 @ chan_rend_context *c
719 upd_slot1:
720     stmfd   sp!, {r4-r10,lr}
721     mov     lr, r0
722
723     ldr     r3, =ym_sin_tab
724     ldr     r5, =ym_tl_tab
725     ldmia   lr, {r6-r7}
726     ldr     r10, [lr, #0x54]
727     ldr     r12, [lr, #0x4c]
728
729     upd_slot1_m
730     str     r10, [lr, #0x38]
731
732     ldmfd   sp!, {r4-r10,pc}
733 .pool
734 */
735
736
737 @ lr=context, r12=pack (stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16])
738 @ r0-r2=scratch, r3=sin_tab/scratch, r4=(length<<8)|unused[4],was_update,algo[3], r5=tl_tab/slot,
739 @ r6-r7=vol_out[4], r8=eg_timer, r9=eg_timer_add[31:16], r10=op1_out, r11=buffer
740 .global chan_render_loop @ chan_rend_context *ct, int *buffer, int length
741
742 chan_render_loop:
743     stmfd   sp!, {r4-r11,lr}
744     mov     lr,  r0
745     mov     r4,  r2, lsl #8      @ no more 24 bits here
746     ldr     r12, [lr, #0x4c]
747     ldr     r0,  [lr, #0x50]
748     mov     r11, r1
749     and     r0,  r0, #7
750     orr     r4,  r4, r0          @ (length<<8)|algo
751     add     r0,  lr, #0x44
752     ldmia   r0,  {r8,r9}         @ eg_timer, eg_timer_add
753     ldr     r10, [lr, #0x54]     @ op1_out
754     ldmia   lr,  {r6,r7}         @ load volumes
755
756     tst     r12, #8              @ lfo?
757     beq     crl_loop
758
759 crl_loop_lfo:
760     add     r0, lr, #0x30
761     ldmia   r0, {r1,r2}
762     add     r2, r2, r1
763     str     r2, [lr, #0x30]
764     @ r12=lfo_ampm[31:16], r1=lfo_cnt_old, r2=lfo_cnt
765     advance_lfo_m
766
767 crl_loop:
768     subs    r4, r4, #0x100
769     bmi     crl_loop_end
770
771     @ -- EG --
772     add     r8, r8, r9
773     cmp     r8, #EG_TIMER_OVERFLOW
774     bcc     eg_done
775     add     r0, lr, #0x3c
776     ldmia   r0, {r1,r5}         @ eg_cnt, CH
777 eg_loop:
778     sub     r8, r8, #EG_TIMER_OVERFLOW
779     add     r1, r1, #1
780                                         @ SLOT1 (0)
781     @ r5=slot, r1=eg_cnt, trashes: r0,r2,r3
782     update_eg_phase_slot SLOT1
783     add     r5, r5, #SLOT_STRUCT_SIZE*2 @ SLOT2 (2)
784     update_eg_phase_slot SLOT2
785     sub     r5, r5, #SLOT_STRUCT_SIZE   @ SLOT3 (1)
786     update_eg_phase_slot SLOT3
787     add     r5, r5, #SLOT_STRUCT_SIZE*2 @ SLOT4 (3)
788     update_eg_phase_slot SLOT4
789
790     cmp     r8, #EG_TIMER_OVERFLOW
791     subcs   r5, r5, #SLOT_STRUCT_SIZE*3
792     bcs     eg_loop
793     str     r1, [lr, #0x3c]
794
795 eg_done:
796
797     @ -- disabled? --
798     and     r0, r12, #0xC
799     cmp     r0, #0xC
800     beq     crl_loop_lfo
801     cmp     r0, #0x4
802     beq     crl_loop
803
804     @ -- SLOT1 --
805     ldr     r3, =ym_tl_tab
806
807     @ lr=context, r12=pack (stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16])
808     @ r0-r2=scratch, r3=tl_tab, r5=scratch, r6-r7=vol_out[4], r10=op1_out
809     upd_slot1_m
810
811     @ -- SLOT2+ --
812     and     r0, r4, #7
813     ldr     pc, [pc, r0, lsl #2]
814     nop
815     .word   crl_algo0
816     .word   crl_algo1
817     .word   crl_algo2
818     .word   crl_algo3
819     .word   crl_algo4
820     .word   crl_algo5
821     .word   crl_algo6
822     .word   crl_algo7
823     .pool
824
825 crl_algo0:
826     upd_algo0_m
827     b       crl_algo_done
828     .pool
829
830 crl_algo1:
831     upd_algo1_m
832     b       crl_algo_done
833     .pool
834
835 crl_algo2:
836     upd_algo2_m
837     b       crl_algo_done
838     .pool
839
840 crl_algo3:
841     upd_algo3_m
842     b       crl_algo_done
843     .pool
844
845 crl_algo4:
846     upd_algo4_m
847     b       crl_algo_done
848     .pool
849
850 crl_algo5:
851     upd_algo5_m
852     b       crl_algo_done
853     .pool
854
855 crl_algo6:
856     upd_algo6_m
857     b       crl_algo_done
858     .pool
859
860 crl_algo7:
861     upd_algo7_m
862     .pool
863
864
865 crl_algo_done:
866     @ -- WRITE SAMPLE --
867     tst     r0, r0
868     beq     ctl_sample_skip
869     orr     r4, r4, #8              @ have_output
870     tst     r12, #1
871     beq     ctl_sample_mono
872
873     tst     r12, #0x20              @ L
874     ldrne   r1, [r11]
875     addeq   r11, r11, #4
876     addne   r1, r0, r1
877     strne   r1, [r11], #4
878     tst     r12, #0x10              @ R
879     ldrne   r1, [r11]
880     addeq   r11, r11, #4
881     addne   r1, r0, r1
882     strne   r1, [r11], #4
883     b       crl_do_phase
884
885 ctl_sample_skip:
886     and     r1, r12, #1
887     add     r1, r1,  #1
888     add     r11,r11, r1, lsl #2
889     b       crl_do_phase
890
891 ctl_sample_mono:
892     ldr     r1, [r11]
893     add     r1, r0, r1
894     str     r1, [r11], #4
895
896 crl_do_phase:
897     @ -- PHASE UPDATE --
898     add     r5, lr, #0x10
899     ldmia   r5, {r0-r1}
900     add     r5, lr, #0x20
901     ldmia   r5, {r2-r3}
902     add     r5, lr, #0x10
903     add     r0, r0, r2
904     add     r1, r1, r3
905     stmia   r5!,{r0-r1}
906     ldmia   r5, {r0-r1}
907     add     r5, lr, #0x28
908     ldmia   r5, {r2-r3}
909     add     r5, lr, #0x18
910     add     r0, r0, r2
911     add     r1, r1, r3
912     stmia   r5, {r0-r1}
913
914     tst     r12, #8
915     bne     crl_loop_lfo
916     b       crl_loop
917
918
919 crl_loop_end:
920     str     r8,  [lr, #0x44]     @ eg_timer
921     str     r12, [lr, #0x4c]     @ pack (for lfo_ampm)
922     str     r4,  [lr, #0x50]     @ was_update
923     str     r10, [lr, #0x54]     @ op1_out
924     ldmfd   sp!, {r4-r11,pc}
925
926 .pool
927