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