get some gp2x stuff out of the way for others
[picodrive.git] / pico / sound / mix_arm.S
CommitLineData
cff531af 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 */
4f265db7 8
4a32f01f 9.text
10.align 4
11
4f265db7 12@ this assumes src is word aligned
13.global mix_16h_to_32 @ int *dest, short *src, int count
14
15mix_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*/
26m16_32_mo_unalw:
27 subs r2, r2, #4
28 bmi m16_32_end
29
30m16_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
43m16_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
53m16_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
68mix_16h_to_32_s1:
69 stmfd sp!, {r4-r6,lr}
70
71 subs r2, r2, #4
72 bmi m16_32_s1_end
73
74m16_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
88m16_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
98m16_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
113mix_16h_to_32_s2:
114 stmfd sp!, {r4-r6,lr}
115
116 subs r2, r2, #4
117 bmi m16_32_s2_end
118
119m16_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
133m16_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
143m16_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
7a93adeb 159 add r3, lr, \reg, asr #15
4f265db7 160 bics r3, r3, #1 @ in non-overflow conditions r3 is 0 or 1
161 movne \reg, #0x8000
7a93adeb 162 subpl \reg, \reg, #1
4f265db7 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
7a93adeb 176 add r3, lr, \reg, asr #15
4f265db7 177 bics r3, r3, #1 @ in non-overflow conditions r3 is 0 or 1
178 moveq \reg, \reg, lsl #16
179 movne \reg, #0x80000000
7a93adeb 180 subpl \reg, \reg, #0x00010000
4f265db7 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
188mix_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
197m32_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
216m32_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
229m32_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
237mix_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
7a93adeb 245 ldrsh r5, [r0]
4f265db7 246 ldr r4, [r1], #4
247 sub r2, r2, #1
248 add r4, r4, r5
249 Limit r4
250 strh r4, [r0], #2
251
252m32_16_mo_no_unalw:
253 subs r2, r2, #4
254 bmi m32_16_mo_end
255
256m32_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
275m32_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
289m32_16_mo_no_unal2:
290 tst r2, #1
291 ldmeqfd sp!, {r4-r8,pc}
7a93adeb 292 ldrsh r5, [r0]
4f265db7 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
4a32f01f 301
006e9add 302#ifdef __GP2X__
4a32f01f 303
304.data
305.align 4
306
307.global mix_32_to_16l_level
308mix_32_to_16l_level:
309 .word 0
310
311.text
312.align 4
313
314@ same as mix_32_to_16l_stereo, but with additional shift
315.global mix_32_to_16l_stereo_lvl @ short *dest, int *src, int count
316
317mix_32_to_16l_stereo_lvl:
318 stmfd sp!, {r4-r9,lr}
319
320 ldr r9, =mix_32_to_16l_level
321 mov lr, #1
322 ldr r9, [r9]
323
324 mov r2, r2, lsl #1
325 subs r2, r2, #4
326 bmi m32_16l_st_l_end
327
328m32_16l_st_l_loop:
329 ldmia r0, {r8,r12}
330 ldmia r1!, {r4-r7}
331 mov r8, r8, lsl #16
332 mov r12,r12,lsl #16
333 add r4, r4, r8, asr #16
334 add r5, r5, r8, asr #16
335 add r6, r6, r12,asr #16
336 add r7, r7, r12,asr #16
337 mov r4, r4, asr r9
338 mov r5, r5, asr r9
339 mov r6, r6, asr r9
340 mov r7, r7, asr r9
341 Limitsh r4
342 Limitsh r5
343 Limitsh r6
344 Limitsh r7
345 subs r2, r2, #4
346 orr r4, r5, r4, lsr #16
347 orr r5, r7, r6, lsr #16
348 stmia r0!, {r4,r5}
349 bpl m32_16l_st_l_loop
350
351m32_16l_st_l_end:
352 @ check for remaining bytes to convert
353 tst r2, #2
354 beq m32_16l_st_l_no_unal2
355 ldrsh r6, [r0]
356 ldmia r1!,{r4,r5}
357 add r4, r4, r6
358 add r5, r5, r6
359 mov r4, r4, asr r9
360 mov r5, r5, asr r9
361 Limitsh r4
362 Limitsh r5
363 orr r4, r5, r4, lsr #16
364 str r4, [r0], #4
365
366m32_16l_st_l_no_unal2:
367 ldmfd sp!, {r4-r9,lr}
368 bx lr
369
006e9add 370#endif /* __GP2X__ */
371
cff531af 372@ vim:filetype=armasm