summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/libatrac/atrac3_arm.S
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/codecs/libatrac/atrac3_arm.S')
-rw-r--r--lib/rbcodec/codecs/libatrac/atrac3_arm.S172
1 files changed, 172 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/libatrac/atrac3_arm.S b/lib/rbcodec/codecs/libatrac/atrac3_arm.S
new file mode 100644
index 0000000000..68f8de2c4e
--- /dev/null
+++ b/lib/rbcodec/codecs/libatrac/atrac3_arm.S
@@ -0,0 +1,172 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id:
9 *
10 * Copyright (C) 2009 by Andree Buschmann
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
22#include "config.h"
23
24 .section .text, "ax", %progbits
25
26/****************************************************************************
27 * void atrac3_iqmf_matrixing(int32_t *dest,
28 * int32_t *inlo,
29 * int32_t *inhi,
30 * unsigned int count);
31 *
32 * Matrixing step within iqmf of atrac3 synthesis. Reference implementation:
33 *
34 * for(i=0; i<counter; i+=2){
35 * dest[2*i+0] = inlo[i ] + inhi[i ];
36 * dest[2*i+1] = inlo[i ] - inhi[i ];
37 * dest[2*i+2] = inlo[i+1] + inhi[i+1];
38 * dest[2*i+3] = inlo[i+1] - inhi[i+1];
39 * }
40 * Note: r12 is a scratch register and can be used without restorage.
41 ****************************************************************************/
42 .align 2
43 .global atrac3_iqmf_matrixing
44 .type atrac3_iqmf_matrixing, %function
45
46atrac3_iqmf_matrixing:
47 /* r0 = dest */
48 /* r1 = inlo */
49 /* r2 = inhi */
50 /* r3 = counter */
51 stmfd sp!, {r4-r9, lr} /* save non-scratch registers */
52
53.iqmf_matrixing_loop:
54 ldmia r1!, { r4, r6, r8, r12} /* load inlo[0...3] */
55 ldmia r2!, { r5, r7, r9, lr } /* load inhi[0...3] */
56 add r4, r4, r5 /* r4 = inlo[0] + inhi[0] */
57 sub r5, r4, r5, asl #1 /* r5 = inlo[0] - inhi[0] */
58 add r6, r6, r7 /* r6 = inlo[1] + inhi[1] */
59 sub r7, r6, r7, asl #1 /* r7 = inlo[1] - inhi[1] */
60 add r8, r8, r9 /* r8 = inlo[2] + inhi[2] */
61 sub r9, r8, r9, asl #1 /* r9 = inlo[2] - inhi[2] */
62 add r12, r12, lr /* r12 = inlo[3] + inhi[3] */
63 sub lr , r12, lr, asl #1 /* lr = inlo[3] - inhi[3] */
64 stmia r0!, {r4-r9, r12, lr} /* store results to dest */
65 subs r3, r3, #4 /* counter -= 4 */
66 bgt .iqmf_matrixing_loop
67
68 ldmpc regs=r4-r9 /* restore registers */
69
70.atrac3_iqmf_matrixing_end:
71 .size atrac3_iqmf_matrixing,.atrac3_iqmf_matrixing_end-atrac3_iqmf_matrixing
72
73
74/****************************************************************************
75 * atrac3_iqmf_dewindowing(int32_t *out,
76 * int32_t *in,
77 * int32_t *win,
78 * unsigned int nIn);
79 *
80 * Dewindowing step within iqmf of atrac3 synthesis. Reference implementation:
81 *
82 * for (j = nIn; j != 0; j--) {
83 * s1 = fixmul32(in[0], win[0]);
84 * s2 = fixmul32(in[1], win[1]);
85 * for (i = 2; i < 48; i += 2) {
86 * s1 += fixmul32(in[i ], win[i ]);
87 * s2 += fixmul32(in[i+1], win[i+1]);
88 * }
89 * out[0] = s2 << 1;
90 * out[1] = s1 << 1;
91 * in += 2;
92 * out += 2;
93 * }
94 * Note: r12 is a scratch register and can be used without restorage.
95 ****************************************************************************/
96
97/* To be called as first block to call smull for initial filling of the result
98 * registers lr/r9 and r12/r8. */
99#define DEWIN_8_SAMPLES_MUL_ASM \
100 ldmia r2!, {r4, r5}; /* load win[0..1] */ \
101 ldmia r1!, {r6, r7}; /* load in [0..1] */ \
102 smull lr , r9, r4, r6; /* s1 = win[0] * in[0] */ \
103 smull r12, r8, r5, r7; /* s2 = win[1] * in[1] */ \
104 ldmia r2!, {r4, r5}; /* load win[i..i+1] */ \
105 ldmia r1!, {r6, r7}; /* load in [i..i+1] */ \
106 smlal lr , r9, r4, r6; /* s1 = win[i ] * in[i ] */ \
107 smlal r12, r8, r5, r7; /* s2 = win[i+1] * in[i+1] */ \
108 ldmia r2!, {r4, r5}; /* load win[i..i+1] */ \
109 ldmia r1!, {r6, r7}; /* load in [i..i+1] */ \
110 smlal lr , r9, r4, r6; /* s1 = win[i ] * in[i ] */ \
111 smlal r12, r8, r5, r7; /* s2 = win[i+1] * in[i+1] */ \
112 ldmia r2!, {r4, r5}; /* load win[i..i+1] */ \
113 ldmia r1!, {r6, r7}; /* load in [i..i+1] */ \
114 smlal lr , r9, r4, r6; /* s1 = win[i ] * in[i ] */ \
115 smlal r12, r8, r5, r7; /* s2 = win[i+1] * in[i+1] */
116
117/* Called after first block. Will always multiply-add to the result registers
118 * lr/r9 and r12/r8. */
119#define DEWIN_8_SAMPLES_MLA_ASM \
120 ldmia r2!, {r4, r5}; /* load win[i..i+1] */ \
121 ldmia r1!, {r6, r7}; /* load in [i..i+1] */ \
122 smlal lr , r9, r4, r6; /* s1 = win[i ] * in[i ] */ \
123 smlal r12, r8, r5, r7; /* s2 = win[i+1] * in[i+1] */ \
124 ldmia r2!, {r4, r5}; /* load win[i..i+1] */ \
125 ldmia r1!, {r6, r7}; /* load in [i..i+1] */ \
126 smlal lr , r9, r4, r6; /* s1 = win[i ] * in[i ] */ \
127 smlal r12, r8, r5, r7; /* s2 = win[i+1] * in[i+1] */ \
128 ldmia r2!, {r4, r5}; /* load win[i..i+1] */ \
129 ldmia r1!, {r6, r7}; /* load in [i..i+1] */ \
130 smlal lr , r9, r4, r6; /* s1 = win[i ] * in[i ] */ \
131 smlal r12, r8, r5, r7; /* s2 = win[i+1] * in[i+1] */ \
132 ldmia r2!, {r4, r5}; /* load win[i..i+1] */ \
133 ldmia r1!, {r6, r7}; /* load in [i..i+1] */ \
134 smlal lr , r9, r4, r6; /* s1 = win[i ] * in[i ] */ \
135 smlal r12, r8, r5, r7; /* s2 = win[i+1] * in[i+1] */
136
137 .align 2
138 .global atrac3_iqmf_dewindowing
139 .type atrac3_iqmf_dewindowing, %function
140
141atrac3_iqmf_dewindowing:
142 /* r0 = dest */
143 /* r1 = input samples */
144 /* r2 = window coefficients */
145 /* r3 = counter */
146 stmfd sp!, {r4-r9, lr} /* save non-scratch registers */
147
148.iqmf_dewindow_outer_loop: /* outer loop 0...counter-1 */
149
150 DEWIN_8_SAMPLES_MUL_ASM /* 0.. 7, use "MUL" macro here! */
151 DEWIN_8_SAMPLES_MLA_ASM /* 8..15 */
152 DEWIN_8_SAMPLES_MLA_ASM /* 16..23 */
153 DEWIN_8_SAMPLES_MLA_ASM /* 24..31 */
154 DEWIN_8_SAMPLES_MLA_ASM /* 32..39 */
155 DEWIN_8_SAMPLES_MLA_ASM /* 40..47 */
156
157 mov lr , lr , lsr #31
158 orr r9, lr , r9, lsl #1 /* s1 = low>>31 || hi<<1 */
159 mov r12, r12, lsr #31
160 orr r8, r12, r8, lsl #1 /* s2 = low>>31 || hi<<1 */
161
162 stmia r0!, {r8, r9} /* store result out[0]=s2, out[1]=s1 */
163 sub r1, r1, #184 /* roll back 64 entries = 184 bytes */
164 sub r2, r2, #192 /* roll back 48 entries = 192 bytes = win[0] */
165
166 subs r3, r3, #1 /* outer loop -= 1 */
167 bgt .iqmf_dewindow_outer_loop
168
169 ldmpc regs=r4-r9 /* restore registers */
170
171.atrac3_iqmf_dewindowing_end:
172 .size atrac3_iqmf_dewindowing,.atrac3_iqmf_dewindowing_end-atrac3_iqmf_dewindowing