summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/libspc/cpu/spc_dsp_armv4.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2013-05-18 01:45:03 -0400
committerMichael Sevakis <jethead71@rockbox.org>2013-05-21 00:02:14 -0400
commit87021f7c0ac4620eafd185ff11905ee643f72b6c (patch)
tree03ae48f3d999cd8743af40cc5df933f64f6df2d2 /lib/rbcodec/codecs/libspc/cpu/spc_dsp_armv4.c
parenta17d6de5bc727b0bb55764ecef2605ae689e8dab (diff)
downloadrockbox-87021f7c0ac4620eafd185ff11905ee643f72b6c.tar.gz
rockbox-87021f7c0ac4620eafd185ff11905ee643f72b6c.zip
SPC Codec: Refactor for CPU and clean up some things.
CPU optimization gets its own files in which to fill-in optimizable routines. Some pointless #if 0's for profiling need removal. Those macros are empty if not profiling. Force some functions that are undesirable to be force-inlined by the compiler to be not inlined. Change-Id: Ia7b7e45380d7efb20c9b1a4d52e05db3ef6bbaab
Diffstat (limited to 'lib/rbcodec/codecs/libspc/cpu/spc_dsp_armv4.c')
-rw-r--r--lib/rbcodec/codecs/libspc/cpu/spc_dsp_armv4.c253
1 files changed, 253 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/libspc/cpu/spc_dsp_armv4.c b/lib/rbcodec/codecs/libspc/cpu/spc_dsp_armv4.c
new file mode 100644
index 0000000000..7eacc3baf9
--- /dev/null
+++ b/lib/rbcodec/codecs/libspc/cpu/spc_dsp_armv4.c
@@ -0,0 +1,253 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007-2010 Michael Sevakis (jhMikeS)
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#if !SPC_NOINTERP
22
23#define SPC_GAUSSIAN_FAST_INTERP
24static inline int gaussian_fast_interp( int16_t const* samples,
25 int32_t position,
26 int16_t const* fwd,
27 int16_t const* rev )
28{
29 int output;
30 int t0, t1, t2, t3;
31
32 asm volatile (
33 "ldrsh %[t0], [%[samp]] \n"
34 "ldrsh %[t2], [%[fwd]] \n"
35 "ldrsh %[t1], [%[samp], #2] \n"
36 "ldrsh %[t3], [%[fwd], #2] \n"
37 "mul %[out], %[t0], %[t2] \n" /* out= fwd[0]*samp[0] */
38 "ldrsh %[t0], [%[samp], #4] \n"
39 "ldrsh %[t2], [%[rev], #2] \n"
40 "mla %[out], %[t1], %[t3], %[out] \n" /* out+=fwd[1]*samp[1] */
41 "ldrsh %[t1], [%[samp], #6] \n"
42 "ldrsh %[t3], [%[rev]] \n"
43 "mla %[out], %[t0], %[t2], %[out] \n" /* out+=rev[1]*samp[2] */
44 "mla %[out], %[t1], %[t3], %[out] \n" /* out+=rev[0]*samp[3] */
45 : [out]"=&r"(output),
46 [t0]"=&r"(t0), [t1]"=&r"(t1), [t2]"=&r"(t2), [t3]"=&r"(t3)
47 : [fwd]"r"(fwd), [rev]"r"(rev),
48 [samp]"r"(samples + (position >> 12)));
49
50 return output;
51}
52
53#define SPC_GAUSSIAN_FAST_AMP
54static inline int gaussian_fast_amp( struct voice_t* voice, int output,
55 int* amp_0, int* amp_1 )
56{
57 int t0;
58
59 asm volatile (
60 "mov %[t0], %[out], asr #11 \n"
61 "mul %[out], %[t0], %[envx] \n"
62 : [out]"+r"(output), [t0]"=&r"(t0)
63 : [envx]"r"((int) voice->envx));
64
65 asm volatile (
66 "mov %[out], %[out], asr #11 \n"
67 "mul %[a0], %[out], %[v0] \n"
68 "mul %[a1], %[out], %[v1] \n"
69 : [out]"+r"(output),
70 [a0]"=&r"(*amp_0), [a1]"=r"(*amp_1)
71 : [v0]"r"((int) voice->volume [0]),
72 [v1]"r"((int) voice->volume [1]));
73
74 return output;
75}
76
77#define SPC_GAUSSIAN_SLOW_INTERP
78static inline int gaussian_slow_interp( int16_t const* samples,
79 int32_t position,
80 int16_t const* fwd,
81 int16_t const* rev )
82{
83 int output;
84 int t0, t1, t2, t3;
85
86 asm volatile (
87 "ldrsh %[t0], [%[samp]] \n"
88 "ldrsh %[t2], [%[fwd]] \n"
89 "ldrsh %[t1], [%[samp], #2] \n"
90 "ldrsh %[t3], [%[fwd], #2] \n"
91 "mul %[out], %[t2], %[t0] \n" /* fwd[0]*samp[0] */
92 "ldrsh %[t2], [%[rev], #2] \n"
93 "mul %[t0], %[t3], %[t1] \n" /* fwd[1]*samp[1] */
94 "ldrsh %[t1], [%[samp], #4] \n"
95 "mov %[out], %[out], asr #12 \n"
96 "ldrsh %[t3], [%[rev]] \n"
97 "mul %[t2], %[t1], %[t2] \n" /* rev[1]*samp[2] */
98 "ldrsh %[t1], [%[samp], #6] \n"
99 "add %[t0], %[out], %[t0], asr #12 \n"
100 "mul %[t3], %[t1], %[t3] \n" /* rev[0]*samp[3] */
101 "add %[t2], %[t0], %[t2], asr #12 \n"
102 "mov %[t2], %[t2], lsl #17 \n"
103 "mov %[t3], %[t3], asr #12 \n"
104 "mov %[t3], %[t3], asl #1 \n"
105 "add %[out], %[t3], %[t2], asr #16 \n"
106 : [out]"=&r"(output),
107 [t0]"=&r"(t0), [t1]"=&r"(t1), [t2]"=&r"(t2), [t3]"=&r"(t3)
108 : [fwd]"r"(fwd), [rev]"r"(rev),
109 [samp]"r"(samples + (position >> 12)));
110
111 return CLAMP16( output );
112}
113
114#define SPC_GAUSSIAN_SLOW_AMP
115static inline int gaussian_slow_amp( struct voice_t* voice, int output,
116 int* amp_0, int* amp_1 )
117{
118 int t0;
119
120 asm volatile (
121 "mul %[t0], %[out], %[envx]"
122 : [t0]"=r"(t0)
123 : [out]"r"(output), [envx]"r"((int) voice->envx));
124 asm volatile (
125 "mov %[t0], %[t0], asr #11 \n"
126 "bic %[t0], %[t0], #0x1 \n"
127 "mul %[a0], %[t0], %[v0] \n"
128 "mul %[a1], %[t0], %[v1] \n"
129 : [t0]"+r"(t0),
130 [a0]"=&r"(*amp_0), [a1]"=r"(*amp_1)
131 : [v0]"r"((int) voice->volume [0]),
132 [v1]"r"((int) voice->volume [1]));
133
134 return t0;
135}
136
137#else /* SPC_NOINTERP */
138
139#define SPC_LINEAR_INTERP
140static inline int linear_interp( int16_t const* samples, int32_t position )
141{
142 int output = (int) samples;
143 int y1;
144
145 asm volatile(
146 "mov %[y1], %[f], lsr #12 \n"
147 "eor %[f], %[f], %[y1], lsl #12 \n"
148 "add %[y1], %[y0], %[y1], lsl #1 \n"
149 "ldrsh %[y0], [%[y1], #2] \n"
150 "ldrsh %[y1], [%[y1], #4] \n"
151 "sub %[y1], %[y1], %[y0] \n"
152 "mul %[f], %[y1], %[f] \n"
153 "add %[y0], %[y0], %[f], asr #12 \n"
154 : [f]"+r"(position), [y0]"+r"(output), [y1]"=&r"(y1));
155
156 return output;
157}
158
159#define SPC_LINEAR_AMP
160static inline int linear_amp( struct voice_t* voice, int output,
161 int* amp_0, int* amp_1 )
162{
163 int t0;
164
165 asm volatile(
166 "mul %[t0], %[out], %[envx]"
167 : [t0]"=&r"(t0)
168 : [out]"r"(output), [envx]"r"(voice->envx));
169 asm volatile(
170 "mov %[t0], %[t0], asr #11 \n"
171 "mul %[a1], %[t0], %[v1] \n"
172 "mul %[a0], %[t0], %[v0] \n"
173 : [t0]"+r"(t0),
174 [a0]"=&r"(*amp_0), [a1]"=&r"(*amp_1)
175 : [v0]"r"((int) voice->volume [0]),
176 [v1]"r"((int) voice->volume [1]));
177
178 return t0;
179}
180
181#endif /* !SPC_NOINTERP */
182
183
184#if !SPC_NOECHO
185
186#define SPC_DSP_ECHO_APPLY
187
188/* Echo filter history */
189static int32_t fir_buf[FIR_BUF_CNT] IBSS_ATTR_SPC
190 __attribute__(( aligned(FIR_BUF_ALIGN*1) ));
191
192static inline void echo_init( struct Spc_Dsp* this )
193{
194 this->fir.ptr = fir_buf;
195 ci->memset( fir_buf, 0, sizeof fir_buf );
196}
197
198static inline void echo_apply( struct Spc_Dsp* this, uint8_t *echo_ptr,
199 int* out_0, int* out_1 )
200{
201 int t0 = GET_LE16SA( echo_ptr );
202 int t1 = GET_LE16SA( echo_ptr + 2 );
203
204 /* Keep last 8 samples */
205 int32_t *fir_ptr;
206 asm volatile (
207 "add %[p], %[t_p], #8 \n"
208 "bic %[t_p], %[p], %[mask] \n"
209 "str %[t0], [%[p], #-8] \n"
210 "str %[t1], [%[p], #-4] \n"
211 /* duplicate at +8 eliminates wrap checking below */
212 "str %[t0], [%[p], #56] \n"
213 "str %[t1], [%[p], #60] \n"
214 : [p]"=&r"(fir_ptr), [t_p]"+r"(this->fir.ptr)
215 : [t0]"r"(t0), [t1]"r"(t1), [mask]"i"(~FIR_BUF_MASK));
216
217 int32_t *fir_coeff = this->fir.coeff;
218
219 asm volatile (
220 "ldmia %[c]!, { r0-r1 } \n"
221 "ldmia %[p]!, { r4-r5 } \n"
222 "mul %[acc0], r0, %[acc0] \n"
223 "mul %[acc1], r0, %[acc1] \n"
224 "mla %[acc0], r4, r1, %[acc0] \n"
225 "mla %[acc1], r5, r1, %[acc1] \n"
226 "ldmia %[c]!, { r0-r1 } \n"
227 "ldmia %[p]!, { r2-r5 } \n"
228 "mla %[acc0], r2, r0, %[acc0] \n"
229 "mla %[acc1], r3, r0, %[acc1] \n"
230 "mla %[acc0], r4, r1, %[acc0] \n"
231 "mla %[acc1], r5, r1, %[acc1] \n"
232 "ldmia %[c]!, { r0-r1 } \n"
233 "ldmia %[p]!, { r2-r5 } \n"
234 "mla %[acc0], r2, r0, %[acc0] \n"
235 "mla %[acc1], r3, r0, %[acc1] \n"
236 "mla %[acc0], r4, r1, %[acc0] \n"
237 "mla %[acc1], r5, r1, %[acc1] \n"
238 "ldmia %[c]!, { r0-r1 } \n"
239 "ldmia %[p]!, { r2-r5 } \n"
240 "mla %[acc0], r2, r0, %[acc0] \n"
241 "mla %[acc1], r3, r0, %[acc1] \n"
242 "mla %[acc0], r4, r1, %[acc0] \n"
243 "mla %[acc1], r5, r1, %[acc1] \n"
244 : [acc0]"+r"(t0), [acc1]"+r"(t1),
245 [p]"+r"(fir_ptr), [c]"+r"(fir_coeff)
246 :
247 : "r0", "r1", "r2", "r3", "r4", "r5");
248
249 *out_0 = t0;
250 *out_1 = t1;
251}
252
253#endif /* SPC_NOECHO */