diff options
Diffstat (limited to 'apps/dsp_arm.S')
-rw-r--r-- | apps/dsp_arm.S | 561 |
1 files changed, 0 insertions, 561 deletions
diff --git a/apps/dsp_arm.S b/apps/dsp_arm.S deleted file mode 100644 index 7e360749a3..0000000000 --- a/apps/dsp_arm.S +++ /dev/null | |||
@@ -1,561 +0,0 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2006-2007 Thom Johansen | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #include "config.h" | ||
22 | |||
23 | /**************************************************************************** | ||
24 | * void channels_process_sound_chan_mono(int count, int32_t *buf[]) | ||
25 | */ | ||
26 | |||
27 | #include "config.h" | ||
28 | |||
29 | .section .icode, "ax", %progbits | ||
30 | .align 2 | ||
31 | .global channels_process_sound_chan_mono | ||
32 | .type channels_process_sound_chan_mono, %function | ||
33 | channels_process_sound_chan_mono: | ||
34 | @ input: r0 = count, r1 = buf | ||
35 | stmfd sp!, { r4, lr } @ | ||
36 | @ | ||
37 | ldmia r1, { r1, r2 } @ r1 = buf[0], r2 = buf[1] | ||
38 | subs r0, r0, #1 @ odd: end at 0; even: end at -1 | ||
39 | beq .mono_singlesample @ Zero? Only one sample! | ||
40 | @ | ||
41 | .monoloop: @ | ||
42 | ldmia r1, { r3, r4 } @ r3, r4 = Li0, Li1 | ||
43 | ldmia r2, { r12, r14 } @ r12, r14 = Ri0, Ri1 | ||
44 | mov r3, r3, asr #1 @ Mo0 = Li0 / 2 + Ri0 / 2 | ||
45 | mov r4, r4, asr #1 @ Mo1 = Li1 / 2 + Ri1 / 2 | ||
46 | add r12, r3, r12, asr #1 @ | ||
47 | add r14, r4, r14, asr #1 @ | ||
48 | subs r0, r0, #2 @ | ||
49 | stmia r1!, { r12, r14 } @ store Mo0, Mo1 | ||
50 | stmia r2!, { r12, r14 } @ store Mo0, Mo1 | ||
51 | bgt .monoloop @ | ||
52 | @ | ||
53 | ldmpc cond=lt, regs=r4 @ if count was even, we're done | ||
54 | @ | ||
55 | .mono_singlesample: @ | ||
56 | ldr r3, [r1] @ r3 = Ls | ||
57 | ldr r12, [r2] @ r12 = Rs | ||
58 | mov r3, r3, asr #1 @ Mo = Ls / 2 + Rs / 2 | ||
59 | add r12, r3, r12, asr #1 @ | ||
60 | str r12, [r1] @ store Mo | ||
61 | str r12, [r2] @ store Mo | ||
62 | @ | ||
63 | ldmpc regs=r4 @ | ||
64 | .size channels_process_sound_chan_mono, \ | ||
65 | .-channels_process_sound_chan_mono | ||
66 | |||
67 | /**************************************************************************** | ||
68 | * void channels_process_sound_chan_custom(int count, int32_t *buf[]) | ||
69 | */ | ||
70 | .section .icode, "ax", %progbits | ||
71 | .align 2 | ||
72 | .global channels_process_sound_chan_custom | ||
73 | .type channels_process_sound_chan_custom, %function | ||
74 | channels_process_sound_chan_custom: | ||
75 | stmfd sp!, { r4-r10, lr } | ||
76 | |||
77 | ldr r3, =dsp_sw_gain | ||
78 | ldr r4, =dsp_sw_cross | ||
79 | |||
80 | ldmia r1, { r1, r2 } @ r1 = buf[0], r2 = buf[1] | ||
81 | ldr r3, [r3] @ r3 = dsp_sw_gain | ||
82 | ldr r4, [r4] @ r4 = dsp_sw_cross | ||
83 | |||
84 | subs r0, r0, #1 | ||
85 | beq .custom_single_sample @ Zero? Only one sample! | ||
86 | |||
87 | .custom_loop: | ||
88 | ldmia r1, { r5, r6 } @ r5 = Li0, r6 = Li1 | ||
89 | ldmia r2, { r7, r8 } @ r7 = Ri0, r8 = Ri1 | ||
90 | |||
91 | subs r0, r0, #2 | ||
92 | |||
93 | smull r9, r10, r5, r3 @ Lc0 = Li0*gain | ||
94 | smull r12, r14, r7, r3 @ Rc0 = Ri0*gain | ||
95 | smlal r9, r10, r7, r4 @ Lc0 += Ri0*cross | ||
96 | smlal r12, r14, r5, r4 @ Rc0 += Li0*cross | ||
97 | |||
98 | mov r9, r9, lsr #31 @ Convert to s0.31 | ||
99 | mov r12, r12, lsr #31 | ||
100 | orr r5, r9, r10, asl #1 | ||
101 | orr r7, r12, r14, asl #1 | ||
102 | |||
103 | smull r9, r10, r6, r3 @ Lc1 = Li1*gain | ||
104 | smull r12, r14, r8, r3 @ Rc1 = Ri1*gain | ||
105 | smlal r9, r10, r8, r4 @ Lc1 += Ri1*cross | ||
106 | smlal r12, r14, r6, r4 @ Rc1 += Li1*cross | ||
107 | |||
108 | mov r9, r9, lsr #31 @ Convert to s0.31 | ||
109 | mov r12, r12, lsr #31 | ||
110 | orr r6, r9, r10, asl #1 | ||
111 | orr r8, r12, r14, asl #1 | ||
112 | |||
113 | stmia r1!, { r5, r6 } @ Store Lc0, Lc1 | ||
114 | stmia r2!, { r7, r8 } @ Store Rc0, Rc1 | ||
115 | |||
116 | bgt .custom_loop | ||
117 | |||
118 | ldmpc cond=lt, regs=r4-r10 @ < 0? even count | ||
119 | |||
120 | .custom_single_sample: | ||
121 | ldr r5, [r1] @ handle odd sample | ||
122 | ldr r7, [r2] | ||
123 | |||
124 | smull r9, r10, r5, r3 @ Lc0 = Li0*gain | ||
125 | smull r12, r14, r7, r3 @ Rc0 = Ri0*gain | ||
126 | smlal r9, r10, r7, r4 @ Lc0 += Ri0*cross | ||
127 | smlal r12, r14, r5, r4 @ Rc0 += Li0*cross | ||
128 | |||
129 | mov r9, r9, lsr #31 @ Convert to s0.31 | ||
130 | mov r12, r12, lsr #31 | ||
131 | orr r5, r9, r10, asl #1 | ||
132 | orr r7, r12, r14, asl #1 | ||
133 | |||
134 | str r5, [r1] @ Store Lc0 | ||
135 | str r7, [r2] @ Store Rc0 | ||
136 | |||
137 | ldmpc regs=r4-r10 | ||
138 | .size channels_process_sound_chan_custom, \ | ||
139 | .-channels_process_sound_chan_custom | ||
140 | |||
141 | /**************************************************************************** | ||
142 | * void channels_process_sound_chan_karaoke(int count, int32_t *buf[]) | ||
143 | */ | ||
144 | .section .icode, "ax", %progbits | ||
145 | .align 2 | ||
146 | .global channels_process_sound_chan_karaoke | ||
147 | .type channels_process_sound_chan_karaoke, %function | ||
148 | channels_process_sound_chan_karaoke: | ||
149 | @ input: r0 = count, r1 = buf | ||
150 | stmfd sp!, { r4, lr } @ | ||
151 | @ | ||
152 | ldmia r1, { r1, r2 } @ r1 = buf[0], r2 = buf[1] | ||
153 | subs r0, r0, #1 @ odd: end at 0; even: end at -1 | ||
154 | beq .karaoke_singlesample @ Zero? Only one sample! | ||
155 | @ | ||
156 | .karaokeloop: @ | ||
157 | ldmia r1, { r3, r4 } @ r3, r4 = Li0, Li1 | ||
158 | ldmia r2, { r12, r14 } @ r12, r14 = Ri0, Ri1 | ||
159 | mov r3, r3, asr #1 @ Lo0 = Li0 / 2 - Ri0 / 2 | ||
160 | mov r4, r4, asr #1 @ Lo1 = Li1 / 2 - Ri1 / 2 | ||
161 | sub r3, r3, r12, asr #1 @ | ||
162 | sub r4, r4, r14, asr #1 @ | ||
163 | rsb r12, r3, #0 @ Ro0 = -Lk0 = Rs0 / 2 - Ls0 / 2 | ||
164 | rsb r14, r4, #0 @ Ro1 = -Lk1 = Ri1 / 2 - Li1 / 2 | ||
165 | subs r0, r0, #2 @ | ||
166 | stmia r1!, { r3, r4 } @ store Lo0, Lo1 | ||
167 | stmia r2!, { r12, r14 } @ store Ro0, Ro1 | ||
168 | bgt .karaokeloop @ | ||
169 | @ | ||
170 | ldmpc cond=lt, regs=r4 @ if count was even, we're done | ||
171 | @ | ||
172 | .karaoke_singlesample: @ | ||
173 | ldr r3, [r1] @ r3 = Li | ||
174 | ldr r12, [r2] @ r12 = Ri | ||
175 | mov r3, r3, asr #1 @ Lk = Li / 2 - Ri /2 | ||
176 | sub r3, r3, r12, asr #1 @ | ||
177 | rsb r12, r3, #0 @ Rk = -Lo = Ri / 2 - Li / 2 | ||
178 | str r3, [r1] @ store Lo | ||
179 | str r12, [r2] @ store Ro | ||
180 | @ | ||
181 | ldmpc regs=r4 @ | ||
182 | .size channels_process_sound_chan_karaoke, \ | ||
183 | .-channels_process_sound_chan_karaoke | ||
184 | |||
185 | #if ARM_ARCH < 6 | ||
186 | /**************************************************************************** | ||
187 | * void sample_output_mono(int count, struct dsp_data *data, | ||
188 | * const int32_t *src[], int16_t *dst) | ||
189 | */ | ||
190 | .section .icode, "ax", %progbits | ||
191 | .align 2 | ||
192 | .global sample_output_mono | ||
193 | .type sample_output_mono, %function | ||
194 | sample_output_mono: | ||
195 | @ input: r0 = count, r1 = data, r2 = src, r3 = dst | ||
196 | stmfd sp!, { r4-r6, lr } | ||
197 | |||
198 | ldr r1, [r1] @ lr = data->output_scale | ||
199 | ldr r2, [r2] @ r2 = src[0] | ||
200 | |||
201 | mov r4, #1 | ||
202 | mov r4, r4, lsl r1 @ r4 = 1 << (scale-1) | ||
203 | mov r4, r4, lsr #1 | ||
204 | mvn r14, #0x8000 @ r14 = 0xffff7fff, needed for | ||
205 | @ clipping and masking | ||
206 | subs r0, r0, #1 @ | ||
207 | beq .som_singlesample @ Zero? Only one sample! | ||
208 | |||
209 | .somloop: | ||
210 | ldmia r2!, { r5, r6 } | ||
211 | add r5, r5, r4 @ r6 = (r6 + 1<<(scale-1)) >> scale | ||
212 | mov r5, r5, asr r1 | ||
213 | mov r12, r5, asr #15 | ||
214 | teq r12, r12, asr #31 | ||
215 | eorne r5, r14, r5, asr #31 @ Clip (-32768...+32767) | ||
216 | add r6, r6, r4 | ||
217 | mov r6, r6, asr r1 @ r7 = (r7 + 1<<(scale-1)) >> scale | ||
218 | mov r12, r6, asr #15 | ||
219 | teq r12, r12, asr #31 | ||
220 | eorne r6, r14, r6, asr #31 @ Clip (-32768...+32767) | ||
221 | |||
222 | and r5, r5, r14, lsr #16 | ||
223 | and r6, r6, r14, lsr #16 | ||
224 | orr r5, r5, r5, lsl #16 @ pack first 2 halfwords into 1 word | ||
225 | orr r6, r6, r6, lsl #16 @ pack last 2 halfwords into 1 word | ||
226 | stmia r3!, { r5, r6 } | ||
227 | |||
228 | subs r0, r0, #2 | ||
229 | bgt .somloop | ||
230 | |||
231 | ldmpc cond=lt, regs=r4-r6 @ even 'count'? return | ||
232 | |||
233 | .som_singlesample: | ||
234 | ldr r5, [r2] @ do odd sample | ||
235 | add r5, r5, r4 | ||
236 | mov r5, r5, asr r1 | ||
237 | mov r12, r5, asr #15 | ||
238 | teq r12, r12, asr #31 | ||
239 | eorne r5, r14, r5, asr #31 | ||
240 | |||
241 | and r5, r5, r14, lsr #16 @ pack 2 halfwords into 1 word | ||
242 | orr r5, r5, r5, lsl #16 | ||
243 | str r5, [r3] | ||
244 | |||
245 | ldmpc regs=r4-r6 | ||
246 | .size sample_output_mono, .-sample_output_mono | ||
247 | |||
248 | /**************************************************************************** | ||
249 | * void sample_output_stereo(int count, struct dsp_data *data, | ||
250 | * const int32_t *src[], int16_t *dst) | ||
251 | */ | ||
252 | .section .icode, "ax", %progbits | ||
253 | .align 2 | ||
254 | .global sample_output_stereo | ||
255 | .type sample_output_stereo, %function | ||
256 | sample_output_stereo: | ||
257 | @ input: r0 = count, r1 = data, r2 = src, r3 = dst | ||
258 | stmfd sp!, { r4-r9, lr } | ||
259 | |||
260 | ldr r1, [r1] @ r1 = data->output_scale | ||
261 | ldmia r2, { r2, r5 } @ r2 = src[0], r5 = src[1] | ||
262 | |||
263 | mov r4, #1 | ||
264 | mov r4, r4, lsl r1 @ r4 = 1 << (scale-1) | ||
265 | mov r4, r4, lsr #1 @ | ||
266 | |||
267 | mvn r14, #0x8000 @ r14 = 0xffff7fff, needed for | ||
268 | @ clipping and masking | ||
269 | subs r0, r0, #1 @ | ||
270 | beq .sos_singlesample @ Zero? Only one sample! | ||
271 | |||
272 | .sosloop: | ||
273 | ldmia r2!, { r6, r7 } @ 2 left | ||
274 | ldmia r5!, { r8, r9 } @ 2 right | ||
275 | |||
276 | add r6, r6, r4 @ r6 = (r6 + 1<<(scale-1)) >> scale | ||
277 | mov r6, r6, asr r1 | ||
278 | mov r12, r6, asr #15 | ||
279 | teq r12, r12, asr #31 | ||
280 | eorne r6, r14, r6, asr #31 @ Clip (-32768...+32767) | ||
281 | add r7, r7, r4 | ||
282 | mov r7, r7, asr r1 @ r7 = (r7 + 1<<(scale-1)) >> scale | ||
283 | mov r12, r7, asr #15 | ||
284 | teq r12, r12, asr #31 | ||
285 | eorne r7, r14, r7, asr #31 @ Clip (-32768...+32767) | ||
286 | |||
287 | add r8, r8, r4 @ r8 = (r8 + 1<<(scale-1)) >> scale | ||
288 | mov r8, r8, asr r1 | ||
289 | mov r12, r8, asr #15 | ||
290 | teq r12, r12, asr #31 | ||
291 | eorne r8, r14, r8, asr #31 @ Clip (-32768...+32767) | ||
292 | add r9, r9, r4 @ r9 = (r9 + 1<<(scale-1)) >> scale | ||
293 | mov r9, r9, asr r1 | ||
294 | mov r12, r9, asr #15 | ||
295 | teq r12, r12, asr #31 | ||
296 | eorne r9, r14, r9, asr #31 @ Clip (-32768...+32767) | ||
297 | |||
298 | and r6, r6, r14, lsr #16 @ pack first 2 halfwords into 1 word | ||
299 | orr r8, r6, r8, asl #16 | ||
300 | and r7, r7, r14, lsr #16 @ pack last 2 halfwords into 1 word | ||
301 | orr r9, r7, r9, asl #16 | ||
302 | |||
303 | stmia r3!, { r8, r9 } | ||
304 | |||
305 | subs r0, r0, #2 | ||
306 | bgt .sosloop | ||
307 | |||
308 | ldmpc cond=lt, regs=r4-r9 @ even 'count'? return | ||
309 | |||
310 | .sos_singlesample: | ||
311 | ldr r6, [r2] @ left odd sample | ||
312 | ldr r8, [r5] @ right odd sample | ||
313 | |||
314 | add r6, r6, r4 @ r6 = (r7 + 1<<(scale-1)) >> scale | ||
315 | mov r6, r6, asr r1 | ||
316 | mov r12, r6, asr #15 | ||
317 | teq r12, r12, asr #31 | ||
318 | eorne r6, r14, r6, asr #31 @ Clip (-32768...+32767) | ||
319 | add r8, r8, r4 @ r8 = (r8 + 1<<(scale-1)) >> scale | ||
320 | mov r8, r8, asr r1 | ||
321 | mov r12, r8, asr #15 | ||
322 | teq r12, r12, asr #31 | ||
323 | eorne r8, r14, r8, asr #31 @ Clip (-32768...+32767) | ||
324 | |||
325 | and r6, r6, r14, lsr #16 @ pack 2 halfwords into 1 word | ||
326 | orr r8, r6, r8, asl #16 | ||
327 | |||
328 | str r8, [r3] | ||
329 | |||
330 | ldmpc regs=r4-r9 | ||
331 | .size sample_output_stereo, .-sample_output_stereo | ||
332 | #endif /* ARM_ARCH < 6 */ | ||
333 | |||
334 | /**************************************************************************** | ||
335 | * void apply_crossfeed(int count, int32_t* src[]) | ||
336 | */ | ||
337 | .section .text | ||
338 | .global apply_crossfeed | ||
339 | apply_crossfeed: | ||
340 | @ unfortunately, we ended up in a bit of a register squeeze here, and need | ||
341 | @ to keep the count on the stack :/ | ||
342 | stmdb sp!, { r4-r11, lr } @ stack modified regs | ||
343 | ldmia r1, { r2-r3 } @ r2 = src[0], r3 = src[1] | ||
344 | |||
345 | ldr r1, =crossfeed_data | ||
346 | ldmia r1!, { r4-r11 } @ load direct gain and filter data | ||
347 | mov r12, r0 @ better to ldm delay + count later | ||
348 | add r0, r1, #13*4*2 @ calculate end of delay | ||
349 | stmdb sp!, { r0, r12 } @ stack end of delay adr and count | ||
350 | ldr r0, [r1, #13*4*2] @ fetch current delay line address | ||
351 | |||
352 | /* Register usage in loop: | ||
353 | * r0 = &delay[index][0], r1 = accumulator high, r2 = src[0], r3 = src[1], | ||
354 | * r4 = direct gain, r5-r7 = b0, b1, a1 (filter coefs), | ||
355 | * r8-r11 = filter history, r12 = temp, r14 = accumulator low | ||
356 | */ | ||
357 | .cfloop: | ||
358 | smull r14, r1, r6, r8 @ acc = b1*dr[n - 1] | ||
359 | smlal r14, r1, r7, r9 @ acc += a1*y_l[n - 1] | ||
360 | ldr r8, [r0, #4] @ r8 = dr[n] | ||
361 | smlal r14, r1, r5, r8 @ acc += b0*dr[n] | ||
362 | mov r9, r1, lsl #1 @ fix format for filter history | ||
363 | ldr r12, [r2] @ load left input | ||
364 | smlal r14, r1, r4, r12 @ acc += gain*x_l[n] | ||
365 | mov r1, r1, lsl #1 @ fix format | ||
366 | str r1, [r2], #4 @ save result | ||
367 | |||
368 | smull r14, r1, r6, r10 @ acc = b1*dl[n - 1] | ||
369 | smlal r14, r1, r7, r11 @ acc += a1*y_r[n - 1] | ||
370 | ldr r10, [r0] @ r10 = dl[n] | ||
371 | str r12, [r0], #4 @ save left input to delay line | ||
372 | smlal r14, r1, r5, r10 @ acc += b0*dl[n] | ||
373 | mov r11, r1, lsl #1 @ fix format for filter history | ||
374 | ldr r12, [r3] @ load right input | ||
375 | smlal r14, r1, r4, r12 @ acc += gain*x_r[n] | ||
376 | str r12, [r0], #4 @ save right input to delay line | ||
377 | mov r1, r1, lsl #1 @ fix format | ||
378 | ldmia sp, { r12, r14 } @ fetch delay line end addr and count from stack | ||
379 | str r1, [r3], #4 @ save result | ||
380 | |||
381 | cmp r0, r12 @ need to wrap to start of delay? | ||
382 | subeq r0, r0, #13*4*2 @ wrap back delay line ptr to start | ||
383 | |||
384 | subs r14, r14, #1 @ are we finished? | ||
385 | strne r14, [sp, #4] @ nope, save count back to stack | ||
386 | bne .cfloop | ||
387 | |||
388 | @ save data back to struct | ||
389 | ldr r12, =crossfeed_data + 4*4 | ||
390 | stmia r12, { r8-r11 } @ save filter history | ||
391 | str r0, [r12, #30*4] @ save delay line index | ||
392 | add sp, sp, #8 @ remove temp variables from stack | ||
393 | ldmpc regs=r4-r11 | ||
394 | .size apply_crossfeed, .-apply_crossfeed | ||
395 | |||
396 | /**************************************************************************** | ||
397 | * int dsp_downsample(int count, struct dsp_data *data, | ||
398 | * in32_t *src[], int32_t *dst[]) | ||
399 | */ | ||
400 | .section .text | ||
401 | .global dsp_downsample | ||
402 | dsp_downsample: | ||
403 | stmdb sp!, { r4-r11, lr } @ stack modified regs | ||
404 | ldmib r1, { r5-r6 } @ r5 = num_channels,r6 = resample_data.delta | ||
405 | sub r5, r5, #1 @ pre-decrement num_channels for use | ||
406 | add r4, r1, #12 @ r4 = &resample_data.phase | ||
407 | mov r12, #0xff | ||
408 | orr r12, r12, #0xff00 @ r12 = 0xffff | ||
409 | .dschannel_loop: | ||
410 | ldr r1, [r4] @ r1 = resample_data.phase | ||
411 | ldr r7, [r2, r5, lsl #2] @ r7 = s = src[ch - 1] | ||
412 | ldr r8, [r3, r5, lsl #2] @ r8 = d = dst[ch - 1] | ||
413 | add r9, r4, #4 @ r9 = &last_sample[0] | ||
414 | ldr r10, [r9, r5, lsl #2] @ r10 = last_sample[ch - 1] | ||
415 | sub r11, r0, #1 | ||
416 | ldr r14, [r7, r11, lsl #2] @ load last sample in s[] ... | ||
417 | str r14, [r9, r5, lsl #2] @ and write as next frame's last_sample | ||
418 | movs r9, r1, lsr #16 @ r9 = pos = phase >> 16 | ||
419 | ldreq r11, [r7] @ if pos = 0, load src[0] and jump into loop | ||
420 | beq .dsuse_last_start | ||
421 | cmp r9, r0 @ if pos >= count, we're already done | ||
422 | bge .dsloop_skip | ||
423 | |||
424 | @ Register usage in loop: | ||
425 | @ r0 = count, r1 = phase, r4 = &resample_data.phase, r5 = cur_channel, | ||
426 | @ r6 = delta, r7 = s, r8 = d, r9 = pos, r10 = s[pos - 1], r11 = s[pos] | ||
427 | .dsloop: | ||
428 | add r9, r7, r9, lsl #2 @ r9 = &s[pos] | ||
429 | ldmda r9, { r10, r11 } @ r10 = s[pos - 1], r11 = s[pos] | ||
430 | .dsuse_last_start: | ||
431 | sub r11, r11, r10 @ r11 = diff = s[pos] - s[pos - 1] | ||
432 | @ keep frac in lower bits to take advantage of multiplier early termination | ||
433 | and r9, r1, r12 @ frac = phase & 0xffff | ||
434 | smull r9, r14, r11, r9 | ||
435 | add r1, r1, r6 @ phase += delta | ||
436 | add r10, r10, r9, lsr #16 @ r10 = out = s[pos - 1] + frac*diff | ||
437 | add r10, r10, r14, lsl #16 | ||
438 | str r10, [r8], #4 @ *d++ = out | ||
439 | mov r9, r1, lsr #16 @ pos = phase >> 16 | ||
440 | cmp r9, r0 @ pos < count? | ||
441 | blt .dsloop @ yup, do more samples | ||
442 | .dsloop_skip: | ||
443 | subs r5, r5, #1 | ||
444 | bpl .dschannel_loop @ if (--ch) >= 0, do another channel | ||
445 | sub r1, r1, r0, lsl #16 @ wrap phase back to start | ||
446 | str r1, [r4] @ store back | ||
447 | ldr r1, [r3] @ r1 = &dst[0] | ||
448 | sub r8, r8, r1 @ dst - &dst[0] | ||
449 | mov r0, r8, lsr #2 @ convert bytes->samples | ||
450 | ldmpc regs=r4-r11 @ ... and we're out | ||
451 | .size dsp_downsample, .-dsp_downsample | ||
452 | |||
453 | /**************************************************************************** | ||
454 | * int dsp_upsample(int count, struct dsp_data *dsp, | ||
455 | * in32_t *src[], int32_t *dst[]) | ||
456 | */ | ||
457 | .section .text | ||
458 | .global dsp_upsample | ||
459 | dsp_upsample: | ||
460 | stmfd sp!, { r4-r11, lr } @ stack modified regs | ||
461 | ldmib r1, { r5-r6 } @ r5 = num_channels,r6 = resample_data.delta | ||
462 | sub r5, r5, #1 @ pre-decrement num_channels for use | ||
463 | add r4, r1, #12 @ r4 = &resample_data.phase | ||
464 | mov r6, r6, lsl #16 @ we'll use carry to detect pos increments | ||
465 | stmfd sp!, { r0, r4 } @ stack count and &resample_data.phase | ||
466 | .uschannel_loop: | ||
467 | ldr r12, [r4] @ r12 = resample_data.phase | ||
468 | ldr r7, [r2, r5, lsl #2] @ r7 = s = src[ch - 1] | ||
469 | ldr r8, [r3, r5, lsl #2] @ r8 = d = dst[ch - 1] | ||
470 | add r9, r4, #4 @ r9 = &last_sample[0] | ||
471 | mov r1, r12, lsl #16 @ we'll use carry to detect pos increments | ||
472 | sub r11, r0, #1 | ||
473 | ldr r14, [r7, r11, lsl #2] @ load last sample in s[] ... | ||
474 | ldr r10, [r9, r5, lsl #2] @ r10 = last_sample[ch - 1] | ||
475 | str r14, [r9, r5, lsl #2] @ and write as next frame's last_sample | ||
476 | movs r14, r12, lsr #16 @ pos = resample_data.phase >> 16 | ||
477 | beq .usstart_0 @ pos = 0 | ||
478 | cmp r14, r0 @ if pos >= count, we're already done | ||
479 | bge .usloop_skip | ||
480 | add r7, r7, r14, lsl #2 @ r7 = &s[pos] | ||
481 | ldr r10, [r7, #-4] @ r11 = s[pos - 1] | ||
482 | b .usstart_0 | ||
483 | |||
484 | @ Register usage in loop: | ||
485 | @ r0 = count, r1 = phase, r4 = &resample_data.phase, r5 = cur_channel, | ||
486 | @ r6 = delta, r7 = s, r8 = d, r9 = diff, r10 = s[pos - 1], r11 = s[pos] | ||
487 | .usloop_1: | ||
488 | mov r10, r11 @ r10 = previous sample | ||
489 | .usstart_0: | ||
490 | ldr r11, [r7], #4 @ r11 = next sample | ||
491 | mov r4, r1, lsr #16 @ r4 = frac = phase >> 16 | ||
492 | sub r9, r11, r10 @ r9 = diff = s[pos] - s[pos - 1] | ||
493 | .usloop_0: | ||
494 | smull r12, r14, r4, r9 | ||
495 | adds r1, r1, r6 @ phase += delta << 16 | ||
496 | mov r4, r1, lsr #16 @ r4 = frac = phase >> 16 | ||
497 | add r14, r10, r14, lsl #16 | ||
498 | add r14, r14, r12, lsr #16 @ r14 = out = s[pos - 1] + frac*diff | ||
499 | str r14, [r8], #4 @ *d++ = out | ||
500 | bcc .usloop_0 @ if carry is set, pos is incremented | ||
501 | subs r0, r0, #1 @ if count > 0, do another sample | ||
502 | bgt .usloop_1 | ||
503 | .usloop_skip: | ||
504 | subs r5, r5, #1 | ||
505 | ldmfd sp, { r0, r4 } @ reload count and &resample_data.phase | ||
506 | bpl .uschannel_loop @ if (--ch) >= 0, do another channel | ||
507 | mov r1, r1, lsr #16 @ wrap phase back to start of next frame | ||
508 | ldr r2, [r3] @ r1 = &dst[0] | ||
509 | str r1, [r4] @ store phase | ||
510 | sub r8, r8, r2 @ dst - &dst[0] | ||
511 | mov r0, r8, lsr #2 @ convert bytes->samples | ||
512 | add sp, sp, #8 @ adjust stack for temp variables | ||
513 | ldmpc regs=r4-r11 @ ... and we're out | ||
514 | .size dsp_upsample, .-dsp_upsample | ||
515 | |||
516 | /**************************************************************************** | ||
517 | * void dsp_apply_gain(int count, struct dsp_data *data, int32_t *buf[]) | ||
518 | */ | ||
519 | .section .icode, "ax", %progbits | ||
520 | .align 2 | ||
521 | .global dsp_apply_gain | ||
522 | .type dsp_apply_gain, %function | ||
523 | dsp_apply_gain: | ||
524 | @ input: r0 = count, r1 = data, r2 = buf[] | ||
525 | stmfd sp!, { r4-r8, lr } | ||
526 | |||
527 | ldr r3, [r1, #4] @ r3 = data->num_channels | ||
528 | ldr r4, [r1, #32] @ r5 = data->gain | ||
529 | |||
530 | .dag_outerloop: | ||
531 | ldr r1, [r2], #4 @ r1 = buf[0] and increment index of buf[] | ||
532 | subs r12, r0, #1 @ r12 = r0 = count - 1 | ||
533 | beq .dag_singlesample @ Zero? Only one sample! | ||
534 | |||
535 | .dag_innerloop: | ||
536 | ldmia r1, { r5, r6 } @ load r5, r6 from r1 | ||
537 | smull r7, r8, r5, r4 @ r7 = FRACMUL_SHL(r5, r4, 8) | ||
538 | smull r14, r5, r6, r4 @ r14 = FRACMUL_SHL(r6, r4, 8) | ||
539 | subs r12, r12, #2 | ||
540 | mov r7, r7, lsr #23 | ||
541 | mov r14, r14, lsr #23 | ||
542 | orr r7, r7, r8, asl #9 | ||
543 | orr r14, r14, r5, asl #9 | ||
544 | stmia r1!, { r7, r14 } @ save r7, r14 to [r1] and increment r1 | ||
545 | bgt .dag_innerloop @ end of inner loop | ||
546 | |||
547 | blt .dag_evencount @ < 0? even count | ||
548 | |||
549 | .dag_singlesample: | ||
550 | ldr r5, [r1] @ handle odd sample | ||
551 | smull r7, r8, r5, r4 @ r7 = FRACMUL_SHL(r5, r4, 8) | ||
552 | mov r7, r7, lsr #23 | ||
553 | orr r7, r7, r8, asl #9 | ||
554 | str r7, [r1] | ||
555 | |||
556 | .dag_evencount: | ||
557 | subs r3, r3, #1 | ||
558 | bgt .dag_outerloop @ end of outer loop | ||
559 | |||
560 | ldmpc regs=r4-r8 | ||
561 | .size dsp_apply_gain, .-dsp_apply_gain | ||