summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorThom Johansen <thomj@rockbox.org>2006-02-01 00:04:55 +0000
committerThom Johansen <thomj@rockbox.org>2006-02-01 00:04:55 +0000
commit5fff854126b0367168bdcbb24f6c49f053c045ee (patch)
treeb2636672e244e15aaf704af7e69a828c251f8aef /apps
parentb69d59ba8e06de799f7fc13c00e9d038867c38df (diff)
EQ filtering code for ARM targets.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8515 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/eq_arm.S67
1 files changed, 67 insertions, 0 deletions
diff --git a/apps/eq_arm.S b/apps/eq_arm.S
new file mode 100644
index 0000000000..85617dc2fb
--- /dev/null
+++ b/apps/eq_arm.S
@@ -0,0 +1,67 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Thom Johansen
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+ .text
+ .global eq_filter
+eq_filter:
+ ldr r12, [sp] @ get shift parameter
+ stmdb sp!, { r0-r11, lr } @ save all params and clobbered regs
+ ldmia r1!, { r4-r8 } @ load coefs
+ mov r10, r1 @ loop prelude expects filter struct addr in r10
+
+.filterloop:
+ ldr r9, [sp] @ get pointer to this channels data
+ add r0, r9, #4
+ str r0, [sp] @ save back pointer to next channels data
+ ldr r9, [r9] @ r9 = x[]
+ ldr r14, [sp, #8] @ r14 = numsamples
+ ldmia r10, { r0-r3 } @ load history, r10 should be filter struct addr
+ str r10, [sp, #4] @ save it for loop end
+.loop:
+ /* r0-r3 = history, r4-r8 = coefs, r9 = x[], r10..r11 = accumulator,
+ r12 = shift amount, r14 = number of samples.
+ See eq_cf.S for explanation of what this loop does. Primary difference
+ is the reordering of the equation we do here, which is done for register
+ reuse reasons, we're pretty short on regs.
+ */
+ smull r10, r11, r6, r1 @ acc = b2*x[i - 2]
+ mov r1, r0 @ fix input history
+ smlal r10, r11, r5, r0 @ acc += b1*x[i - 1]
+ ldr r0, [r9] @ load input and fix history in same operation
+ smlal r10, r11, r4, r0 @ acc += b0*x[i]
+ smlal r10, r11, r7, r2 @ acc += a1*y[i - 1]
+ smlal r10, r11, r8, r3 @ acc += a2*y[i - 2]
+ mov r3, r2 @ fix output history
+ mov r2, r11, lsl r12 @ get result
+ @ TODO: arm makes it easy to mix in lower bits from r10 for extended
+ @ precision here, but we don't have enough regs to save the shift factor
+ @ we would need (32 - r12).
+ str r2, [r9], #4 @ save result
+ subs r14, r14, #1 @ are we done with this channel?
+ bne .loop
+
+ ldr r10, [sp, #4] @ load filter struct pointer
+ stmia r10!, { r0-r3 } @ save back history
+ ldr r11, [sp, #12] @ load number of channels
+ subs r11, r11, #1 @ all channels processed?
+ strne r11, [sp, #12]
+ bne .filterloop
+
+ add sp, sp, #16 @ compensate for temp storage
+ ldmia sp!, { r4-r11, pc }