32x: simplify logging a bit
[picodrive.git] / pico / sound / mix_arm.s
1 /*
2  * Generic routines for mixing audio samples
3  * (C) notaz, 2007,2008
4  *
5  * This work is licensed under the terms of MAME license.
6  * See COPYING file in the top-level directory.
7  */
8
9 .text
10 .align 4
11
12 @ this assumes src is word aligned
13 .global mix_16h_to_32 @ int *dest, short *src, int count
14
15 mix_16h_to_32:
16     stmfd   sp!, {r4-r6,lr}
17 /*
18     tst     r1, #2
19     beq     m16_32_mo_unalw
20     ldrsh   r4, [r1], #2
21     ldr     r3, [r0]
22     sub     r2, r2, #1
23     add     r3, r3, r4, asr #1
24     str     r3, [r0], #4
25 */
26 m16_32_mo_unalw:
27     subs    r2, r2, #4
28     bmi     m16_32_end
29
30 m16_32_loop:
31     ldmia   r0, {r3-r6}
32     ldmia   r1!,{r12,lr}
33     subs    r2, r2, #4
34     add     r4, r4, r12,asr #17 @ we use half volume
35     mov     r12,r12,lsl #16
36     add     r3, r3, r12,asr #17
37     add     r6, r6, lr, asr #17
38     mov     lr, lr, lsl #16
39     add     r5, r5, lr, asr #17
40     stmia   r0!,{r3-r6}
41     bpl     m16_32_loop
42
43 m16_32_end:
44     tst     r2, #2
45     beq     m16_32_no_unal2
46     ldr     r5, [r1], #4
47     ldmia   r0, {r3,r4}
48     mov     r12,r5, lsl #16
49     add     r3, r3, r12,asr #17
50     add     r4, r4, r5, asr #17
51     stmia   r0!,{r3,r4}
52
53 m16_32_no_unal2:
54     tst     r2, #1
55     ldmeqfd sp!, {r4-r6,pc}
56     ldrsh   r4, [r1], #2
57     ldr     r3, [r0]
58     add     r3, r3, r4, asr #1
59     str     r3, [r0], #4
60
61     ldmfd   sp!, {r4-r6,lr}
62     bx      lr
63
64
65
66 .global mix_16h_to_32_s1 @ int *dest, short *src, int count
67
68 mix_16h_to_32_s1:
69     stmfd   sp!, {r4-r6,lr}
70
71     subs    r2, r2, #4
72     bmi     m16_32_s1_end
73
74 m16_32_s1_loop:
75     ldmia   r0, {r3-r6}
76     ldr     r12,[r1], #8
77     ldr     lr, [r1], #8
78     subs    r2, r2, #4
79     add     r4, r4, r12,asr #17
80     mov     r12,r12,lsl #16
81     add     r3, r3, r12,asr #17 @ we use half volume
82     add     r6, r6, lr, asr #17
83     mov     lr, lr, lsl #16
84     add     r5, r5, lr, asr #17
85     stmia   r0!,{r3-r6}
86     bpl     m16_32_s1_loop
87
88 m16_32_s1_end:
89     tst     r2, #2
90     beq     m16_32_s1_no_unal2
91     ldr     r5, [r1], #8
92     ldmia   r0, {r3,r4}
93     mov     r12,r5, lsl #16
94     add     r3, r3, r12,asr #17
95     add     r4, r4, r5, asr #17
96     stmia   r0!,{r3,r4}
97
98 m16_32_s1_no_unal2:
99     tst     r2, #1
100     ldmeqfd sp!, {r4-r6,pc}
101     ldrsh   r4, [r1], #2
102     ldr     r3, [r0]
103     add     r3, r3, r4, asr #1
104     str     r3, [r0], #4
105
106     ldmfd   sp!, {r4-r6,lr}
107     bx      lr
108
109
110
111 .global mix_16h_to_32_s2 @ int *dest, short *src, int count
112
113 mix_16h_to_32_s2:
114     stmfd   sp!, {r4-r6,lr}
115
116     subs    r2, r2, #4
117     bmi     m16_32_s2_end
118
119 m16_32_s2_loop:
120     ldmia   r0, {r3-r6}
121     ldr     r12,[r1], #16
122     ldr     lr, [r1], #16
123     subs    r2, r2, #4
124     add     r4, r4, r12,asr #17
125     mov     r12,r12,lsl #16
126     add     r3, r3, r12,asr #17 @ we use half volume
127     add     r6, r6, lr, asr #17
128     mov     lr, lr, lsl #16
129     add     r5, r5, lr, asr #17
130     stmia   r0!,{r3-r6}
131     bpl     m16_32_s2_loop
132
133 m16_32_s2_end:
134     tst     r2, #2
135     beq     m16_32_s2_no_unal2
136     ldr     r5, [r1], #16
137     ldmia   r0, {r3,r4}
138     mov     r12,r5, lsl #16
139     add     r3, r3, r12,asr #17
140     add     r4, r4, r5, asr #17
141     stmia   r0!,{r3,r4}
142
143 m16_32_s2_no_unal2:
144     tst     r2, #1
145     ldmeqfd sp!, {r4-r6,pc}
146     ldrsh   r4, [r1], #2
147     ldr     r3, [r0]
148     add     r3, r3, r4, asr #1
149     str     r3, [r0], #4
150
151     ldmfd   sp!, {r4-r6,lr}
152     bx      lr
153
154
155
156 @ limit
157 @ reg=int_sample, lr=1, r3=tmp, kills flags
158 .macro Limit reg
159     add     r3, lr, \reg, asr #15
160     bics    r3, r3, #1                  @ in non-overflow conditions r3 is 0 or 1
161     movne   \reg, #0x8000
162     subpl   \reg, \reg, #1
163 .endm
164
165
166 @ limit and shift up by 16
167 @ reg=int_sample, lr=1, r3=tmp, kills flags
168 .macro Limitsh reg
169 @    movs    r4, r3, asr #16
170 @    cmnne   r4, #1
171 @    beq     c32_16_no_overflow
172 @    tst     r4, r4
173 @    mov     r3, #0x8000
174 @    subpl   r3, r3, #1
175
176     add     r3, lr, \reg, asr #15
177     bics    r3, r3, #1                  @ in non-overflow conditions r3 is 0 or 1
178     moveq   \reg, \reg, lsl #16
179     movne   \reg, #0x80000000
180     subpl   \reg, \reg, #0x00010000
181 .endm
182
183
184 @ mix 32bit audio (with 16bits really used, upper bits indicate overflow) with normal 16 bit audio with left channel only
185 @ warning: this function assumes dest is word aligned
186 .global mix_32_to_16l_stereo @ short *dest, int *src, int count
187
188 mix_32_to_16l_stereo:
189     stmfd   sp!, {r4-r8,lr}
190
191     mov     lr, #1
192
193     mov     r2, r2, lsl #1
194     subs    r2, r2, #4
195     bmi     m32_16l_st_end
196
197 m32_16l_st_loop:
198     ldmia   r0,  {r8,r12}
199     ldmia   r1!, {r4-r7}
200     mov     r8, r8, lsl #16
201     mov     r12,r12,lsl #16
202     add     r4, r4, r8, asr #16
203     add     r5, r5, r8, asr #16
204     add     r6, r6, r12,asr #16
205     add     r7, r7, r12,asr #16
206     Limitsh r4
207     Limitsh r5
208     Limitsh r6
209     Limitsh r7
210     subs    r2, r2, #4
211     orr     r4, r5, r4, lsr #16
212     orr     r5, r7, r6, lsr #16
213     stmia   r0!, {r4,r5}
214     bpl     m32_16l_st_loop
215
216 m32_16l_st_end:
217     @ check for remaining bytes to convert
218     tst     r2, #2
219     beq     m32_16l_st_no_unal2
220     ldrsh   r6, [r0]
221     ldmia   r1!,{r4,r5}
222     add     r4, r4, r6
223     add     r5, r5, r6
224     Limitsh r4
225     Limitsh r5
226     orr     r4, r5, r4, lsr #16
227     str     r4, [r0], #4
228
229 m32_16l_st_no_unal2:
230     ldmfd   sp!, {r4-r8,lr}
231     bx      lr
232
233
234 @ mix 32bit audio (with 16bits really used, upper bits indicate overflow) with normal 16 bit audio (for mono sound)
235 .global mix_32_to_16_mono @ short *dest, int *src, int count
236
237 mix_32_to_16_mono:
238     stmfd   sp!, {r4-r8,lr}
239
240     mov     lr, #1
241
242     @ check if dest is word aligned
243     tst     r0, #2
244     beq     m32_16_mo_no_unalw
245     ldrsh   r5, [r0]
246     ldr     r4, [r1], #4
247     sub     r2, r2, #1
248     add     r4, r4, r5
249     Limit   r4
250     strh    r4, [r0], #2
251
252 m32_16_mo_no_unalw:
253     subs    r2, r2, #4
254     bmi     m32_16_mo_end
255
256 m32_16_mo_loop:
257     ldmia   r0,  {r8,r12}
258     ldmia   r1!, {r4-r7}
259     add     r5, r5, r8, asr #16
260     mov     r8, r8, lsl #16
261     add     r4, r4, r8, asr #16
262     add     r7, r7, r12,asr #16
263     mov     r12,r12,lsl #16
264     add     r6, r6, r12,asr #16
265     Limitsh r4
266     Limitsh r5
267     Limitsh r6
268     Limitsh r7
269     subs    r2, r2, #4
270     orr     r4, r5, r4, lsr #16
271     orr     r5, r7, r6, lsr #16
272     stmia   r0!, {r4,r5}
273     bpl     m32_16_mo_loop
274
275 m32_16_mo_end:
276     @ check for remaining bytes to convert
277     tst     r2, #2
278     beq     m32_16_mo_no_unal2
279     ldr     r6, [r0]
280     ldmia   r1!,{r4,r5}
281     add     r5, r5, r6, asr #16
282     mov     r6, r6, lsl #16
283     add     r4, r4, r6, asr #16
284     Limitsh r4
285     Limitsh r5
286     orr     r4, r5, r4, lsr #16
287     str     r4, [r0], #4
288
289 m32_16_mo_no_unal2:
290     tst     r2, #1
291     ldmeqfd sp!, {r4-r8,pc}
292     ldrsh   r5, [r0]
293     ldr     r4, [r1], #4
294     add     r4, r4, r5
295     Limit   r4
296     strh    r4, [r0], #2
297
298     ldmfd   sp!, {r4-r8,lr}
299     bx      lr
300
301
302
303 .data
304 .align 4
305
306 .global mix_32_to_16l_level
307 mix_32_to_16l_level:
308     .word   0
309
310 .text
311 .align 4
312
313 @ same as mix_32_to_16l_stereo, but with additional shift
314 .global mix_32_to_16l_stereo_lvl @ short *dest, int *src, int count
315
316 mix_32_to_16l_stereo_lvl:
317     stmfd   sp!, {r4-r9,lr}
318
319     ldr     r9, =mix_32_to_16l_level
320     mov     lr, #1
321     ldr     r9, [r9]
322
323     mov     r2, r2, lsl #1
324     subs    r2, r2, #4
325     bmi     m32_16l_st_l_end
326
327 m32_16l_st_l_loop:
328     ldmia   r0,  {r8,r12}
329     ldmia   r1!, {r4-r7}
330     mov     r8, r8, lsl #16
331     mov     r12,r12,lsl #16
332     add     r4, r4, r8, asr #16
333     add     r5, r5, r8, asr #16
334     add     r6, r6, r12,asr #16
335     add     r7, r7, r12,asr #16
336     mov     r4, r4, asr r9
337     mov     r5, r5, asr r9
338     mov     r6, r6, asr r9
339     mov     r7, r7, asr r9
340     Limitsh r4
341     Limitsh r5
342     Limitsh r6
343     Limitsh r7
344     subs    r2, r2, #4
345     orr     r4, r5, r4, lsr #16
346     orr     r5, r7, r6, lsr #16
347     stmia   r0!, {r4,r5}
348     bpl     m32_16l_st_l_loop
349
350 m32_16l_st_l_end:
351     @ check for remaining bytes to convert
352     tst     r2, #2
353     beq     m32_16l_st_l_no_unal2
354     ldrsh   r6, [r0]
355     ldmia   r1!,{r4,r5}
356     add     r4, r4, r6
357     add     r5, r5, r6
358     mov     r4, r4, asr r9
359     mov     r5, r5, asr r9
360     Limitsh r4
361     Limitsh r5
362     orr     r4, r5, r4, lsr #16
363     str     r4, [r0], #4
364
365 m32_16l_st_l_no_unal2:
366     ldmfd   sp!, {r4-r9,lr}
367     bx      lr
368
369 @ vim:filetype=armasm