make usb_serial work again. Also know as "make sure arrays are allocated at their...
[kugel-rb.git] / apps / codecs / libffmpegFLAC / coldfire.S
blob5f464be762f67a4287a460331582c10f32186758
1 /***************************************************************************
2  *             __________               __   ___.
3  *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
4  *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
5  *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
6  *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
7  *                     \/            \/     \/    \/            \/
8  * $Id$
9  *
10  * Copyright (C) 2005 by Thom Johansen 
11  *
12  * All files in this archive are subject to the GNU General Public License.
13  * See the file COPYING in the source tree root for full license agreement.
14  *
15  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16  * KIND, either express or implied.
17  *
18  ****************************************************************************/
20 /* The following are assembler optimised version of the LPC filtering
21    routines needed for FLAC decoding. They is optimised for use with the
22    MCF5249 processor, or any other similar ColdFire core with the EMAC unit.
23  */
25 /* This routine deals with sample widths 16 and lower. All LPC filtering up to
26    order 10 is done in specially optimised unrolled loops, while every order
27    above this is handled by a slower default routine.
28  */
29     .section .icode,"ax",@progbits
30     .global lpc_decode_emac
31     .align 2
32 lpc_decode_emac:
33     lea.l (-44, %sp), %sp
34     movem.l %d2-%d7/%a2-%a6, (%sp)
35     movem.l (44+4, %sp), %d0-%d2/%a0-%a1
36     /* d0 = blocksize, d1 = qlevel, d2 = pred_order
37        a0 = data, a1 = coeffs
38      */
39      
40     /* the data pointer always lags behind history pointer by 'pred_order'
41        samples. since we have one loop for each order, we can hard code this
42        and free a register by not saving data pointer. 
43      */ 
44     move.l %d2, %d3 
45     neg.l %d3
46     lea.l (%a0, %d3.l*4), %a0 | history
47     clr.l %d3
48     move.l %d3, %macsr        | we'll need integer mode for this
49     tst.l %d0          
50     jeq .exit                 | zero samples to process, exit
51     moveq.l #10, %d3
52     cmp.l %d3, %d2
53     jgt .default              | order is over 10, jump to default case
54     jmp.l (2, %pc, %d2.l*4)   | jump to loop corresponding to pred_order
55 | jumptable:
56     bra.w .exit               | zero order filter isn't possible, exit function
57     bra.w .order1
58     bra.w .order2
59     bra.w .order3
60     bra.w .order4
61     bra.w .order5
62     bra.w .order6
63     bra.w .order7
64     bra.w .order8
65     bra.w .order9
67 | last jump table entry coincides with target, so leave it out
68 .order10:
69     movem.l (%a1), %d3-%d7/%a1-%a5 | load lpc coefs
70     move.l (%a0)+, %a6             | load first history sample
72     mac.l %a6, %a5, (%a0)+, %a6, %acc0
73     mac.l %a6, %a4, (%a0)+, %a6, %acc0
74     mac.l %a6, %a3, (%a0)+, %a6, %acc0
75     mac.l %a6, %a2, (%a0)+, %a6, %acc0
76     mac.l %a6, %a1, (%a0)+, %a6, %acc0
77     mac.l %a6, %d7, (%a0)+, %a6, %acc0
78     mac.l %a6, %d6, (%a0)+, %a6, %acc0
79     mac.l %a6, %d5, (%a0)+, %a6, %acc0
80     mac.l %a6, %d4, (%a0)+, %a6, %acc0
81     mac.l %a6, %d3, (-9*4, %a0), %a6, %acc0 | load for the next iteration
82     movclr.l %acc0, %d2    | get sum
83     asr.l %d1, %d2         | shift sum by qlevel bits
84     add.l %d2, (%a0)       | add residual and save
85     lea.l (-8*4, %a0), %a0 | point history back at second element
86     subq.l #1, %d0         | decrement sample count
87     jne 1b                 | are we done?
88     jra .exit
90 .order9:
91     movem.l (%a1), %d4-%d7/%a1-%a5
92     move.l (%a0)+, %a6
94     mac.l %a6, %a5, (%a0)+, %a6, %acc0
95     mac.l %a6, %a4, (%a0)+, %a6, %acc0
96     mac.l %a6, %a3, (%a0)+, %a6, %acc0
97     mac.l %a6, %a2, (%a0)+, %a6, %acc0
98     mac.l %a6, %a1, (%a0)+, %a6, %acc0
99     mac.l %a6, %d7, (%a0)+, %a6, %acc0
100     mac.l %a6, %d6, (%a0)+, %a6, %acc0
101     mac.l %a6, %d5, (%a0)+, %a6, %acc0
102     mac.l %a6, %d4, (-8*4, %a0), %a6, %acc0
103     movclr.l %acc0, %d2
104     asr.l %d1, %d2
105     add.l %d2, (%a0)
106     lea.l (-7*4, %a0), %a0
107     subq.l #1, %d0
108     jne 1b
109     jra .exit
111 .order8:
112     movem.l (%a1), %d5-%d7/%a1-%a5
113     move.l (%a0)+, %a6
115     mac.l %a6, %a5, (%a0)+, %a6, %acc0
116     mac.l %a6, %a4, (%a0)+, %a6, %acc0
117     mac.l %a6, %a3, (%a0)+, %a6, %acc0
118     mac.l %a6, %a2, (%a0)+, %a6, %acc0
119     mac.l %a6, %a1, (%a0)+, %a6, %acc0
120     mac.l %a6, %d7, (%a0)+, %a6, %acc0
121     mac.l %a6, %d6, (%a0)+, %a6, %acc0
122     mac.l %a6, %d5, (-7*4, %a0), %a6, %acc0
123     movclr.l %acc0, %d2
124     asr.l %d1, %d2
125     add.l %d2, (%a0)
126     lea.l (-6*4, %a0), %a0
127     subq.l #1, %d0
128     jne 1b
129     jra .exit
131 .order7:
132     movem.l (%a1), %d6-%d7/%a1-%a5
133     move.l (%a0)+, %a6
135     mac.l %a6, %a5, (%a0)+, %a6, %acc0
136     mac.l %a6, %a4, (%a0)+, %a6, %acc0
137     mac.l %a6, %a3, (%a0)+, %a6, %acc0
138     mac.l %a6, %a2, (%a0)+, %a6, %acc0
139     mac.l %a6, %a1, (%a0)+, %a6, %acc0
140     mac.l %a6, %d7, (%a0)+, %a6, %acc0
141     mac.l %a6, %d6, (-6*4, %a0), %a6, %acc0
142     movclr.l %acc0, %d2
143     asr.l %d1, %d2
144     add.l %d2, (%a0)
145     lea.l (-5*4, %a0), %a0
146     subq.l #1, %d0
147     jne 1b
148     jra .exit
150 .order6:
151     movem.l (%a1), %d7/%a1-%a5
152     move.l (%a0)+, %a6
154     mac.l %a6, %a5, (%a0)+, %a6, %acc0
155     mac.l %a6, %a4, (%a0)+, %a6, %acc0
156     mac.l %a6, %a3, (%a0)+, %a6, %acc0
157     mac.l %a6, %a2, (%a0)+, %a6, %acc0
158     mac.l %a6, %a1, (%a0)+, %a6, %acc0
159     mac.l %a6, %d7, (-5*4, %a0), %a6, %acc0
160     movclr.l %acc0, %d2
161     asr.l %d1, %d2
162     add.l %d2, (%a0)
163     lea.l (-4*4, %a0), %a0
164     subq.l #1, %d0
165     jne 1b
166     jra .exit
168 .order5:
169     movem.l (%a1), %a1-%a5
170     move.l (%a0)+, %a6
172     mac.l %a6, %a5, (%a0)+, %a6, %acc0
173     mac.l %a6, %a4, (%a0)+, %a6, %acc0
174     mac.l %a6, %a3, (%a0)+, %a6, %acc0
175     mac.l %a6, %a2, (%a0)+, %a6, %acc0
176     mac.l %a6, %a1, (-4*4, %a0), %a6, %acc0
177     movclr.l %acc0, %d2
178     asr.l %d1, %d2
179     add.l %d2, (%a0)
180     lea.l (-3*4, %a0), %a0
181     subq.l #1, %d0
182     jne 1b
183     jra .exit
185 .order4:
186     movem.l (%a1), %a2-%a5
187     move.l (%a0)+, %a6
189     mac.l %a6, %a5, (%a0)+, %a6, %acc0
190     mac.l %a6, %a4, (%a0)+, %a6, %acc0
191     mac.l %a6, %a3, (%a0)+, %a6, %acc0
192     mac.l %a6, %a2, (-3*4, %a0), %a6, %acc0
193     movclr.l %acc0, %d2
194     asr.l %d1, %d2
195     add.l %d2, (%a0)
196     subq.l #8, %a0
197     subq.l #1, %d0
198     jne 1b
199     jra .exit
201 .order3:
202     movem.l (%a1), %a3-%a5
203     move.l (%a0)+, %a6
205     mac.l %a6, %a5, (%a0)+, %a6, %acc0
206     mac.l %a6, %a4, (%a0)+, %a6, %acc0
207     mac.l %a6, %a3, (-2*4, %a0), %a6, %acc0
208     movclr.l %acc0, %d2
209     asr.l %d1, %d2
210     add.l %d2, (%a0)
211     subq.l #4, %a0
212     subq.l #1, %d0
213     jne 1b
214     jra .exit
216 .order2:
217     movem.l (%a1), %a4-%a5
218     move.l (%a0)+, %a6
220     mac.l %a6, %a5, (%a0)+, %a6, %acc0
221     mac.l %a6, %a4, %acc0    | data for next iteration is already loaded
222     movclr.l %acc0, %d2
223     asr.l %d1, %d2
224     add.l %d2, (%a0)
225     subq.l #1, %d0
226     jne 1b
227     jra .exit
229 .order1:
230     | no point in using mac here
231     move.l (%a1), %a5 
233     move.l %a5, %d2
234     muls.l (%a0)+, %d2
235     asr.l %d1, %d2
236     add.l %d2, (%a0)
237     subq.l #1, %d0
238     jne 1b
239     jra .exit
240     
241 .default:
242     /* we do the filtering in an unrolled by 4 loop as far as we can, and then
243        do the rest by jump table. */
244     lea.l (%a1, %d2.l*4), %a2 | need to start in the other end of coefs
245     move.l %a0, %a3           | working copy of history pointer
246     move.l %d2, %d3
247     lsr.l #2, %d3             | coefs/4, num of iterations needed in next loop
248     move.l (%a3)+, %a5        | preload data for loop
250     lea.l (-4*4, %a2), %a2    | move lpc coef pointer four samples backwards
251     movem.l (%a2), %d4-%d7    | load four coefs
252     mac.l %a5, %d7, (%a3)+, %a5, %acc0
253     mac.l %a5, %d6, (%a3)+, %a5, %acc0
254     mac.l %a5, %d5, (%a3)+, %a5, %acc0
255     mac.l %a5, %d4, (%a3)+, %a5, %acc0
256     subq.l #1, %d3            | any more unrolled loop operations left?
257     jne 1b
258     
259     moveq.l #3, %d3           | mask 0x00000003
260     and.l %d2, %d3            | get the remaining samples to be filtered
261     jmp.l (2, %pc, %d3*2)     | then jump into mac.l chain
262 | jumptable:
263     bra.b 3f                  | none left 
264     bra.b 2f                  | one left
265     bra.b 1f                  | two left
266 | three left
267     move.l -(%a2), %d4
268     mac.l %a5, %d4, (%a3)+, %a5, %acc0
270     move.l -(%a2), %d4
271     mac.l %a5, %d4, (%a3)+, %a5, %acc0
273     move.l -(%a2), %d4
274     mac.l %a5, %d4, (%a3)+, %a5, %acc0
276     movclr.l %acc0, %d3       | get result
277     asr.l %d1, %d3            | shift qlevel bits right
278     add.l %a5, %d3            | add residual, which is in a5 by now
279     move.l %d3, -(%a3)        | save, a3 is also one past save location
280     addq.l #4, %a0            | increment history pointer
281     subq.l #1, %d0            | decrement sample count 
282     jne .default              | are we done?
283     jra .exit                 | if so, fall through to exit
286 /* This routine deals with sample widths 24 and lower. All LPC filtering up to
287    order 8 is done in specially optimised unrolled loops, while every order
288    above this is handled by a slower default routine.
289  */
290     .global lpc_decode_emac_wide
291     .align 2
292 lpc_decode_emac_wide:
293     lea.l (-44, %sp), %sp
294     movem.l %d2-%d7/%a2-%a6, (%sp)
295     movem.l (44+4, %sp), %d0-%d1/%d3/%a0-%a1
296     /* d0 = blocksize, d1 = qlevel, d3 = pred_order
297        a0 = data, a1 = coeffs
298      */
299      
300     /* the data pointer always lags behind history pointer by 'pred_order'
301        samples. since we have one loop for each order, we can hard code this
302        and free a register by not saving data pointer. 
303      */ 
304     move.l %d3, %d2
305     neg.l %d2
306     lea.l (%a0, %d2.l*4), %a0 | history
307     clr.l %d2
308     move.l %d2, %macsr        | we'll need integer mode for this
309     tst.l %d0          
310     jeq .exit                 | zero samples to process, exit
311     moveq.l #32, %d2
312     sub.l %d1, %d2            | calculate shift amount for extension byte
313     moveq.l #8, %d4
314     cmp.l %d4, %d3
315     jgt .wdefault             | order is over 8, jump to default case
316     jmp.l (2, %pc, %d3.l*4)   | jump to loop corresponding to pred_order
317 | jumptable:
318     bra.w .exit               | zero order filter isn't possible, exit function
319     bra.w .worder1
320     bra.w .worder2
321     bra.w .worder3
322     bra.w .worder4
323     bra.w .worder5
324     bra.w .worder6
325     bra.w .worder7
327 | last jump table entry coincides with target, so leave it out
328 .worder8:
329     movem.l (%a1), %d5-%d7/%a1-%a5 | load lpc coefs
330     move.l (%a0)+, %a6             | load first history sample
332     mac.l %a6, %a5, (%a0)+, %a6, %acc0
333     mac.l %a6, %a4, (%a0)+, %a6, %acc0
334     mac.l %a6, %a3, (%a0)+, %a6, %acc0
335     mac.l %a6, %a2, (%a0)+, %a6, %acc0
336     mac.l %a6, %a1, (%a0)+, %a6, %acc0
337     mac.l %a6, %d7, (%a0)+, %a6, %acc0
338     mac.l %a6, %d6, (%a0)+, %a6, %acc0
339     mac.l %a6, %d5, (-7*4, %a0), %a6, %acc0 | load for the next iteration
340     move.l %accext01, %d4  | get top 8 bits of sum
341     movclr.l %acc0, %d3    | then botten 32 bits
342     lsr.l %d1, %d3         | shift bottom bits qlevel bits right
343     asl.l %d2, %d4         | shift top bits 32 - qlevel bits left
344     or.l %d4, %d3          | now combine results
345     add.l %d3, (%a0)       | add residual and save
346     lea.l (-6*4, %a0), %a0 | point history back at second element
347     subq.l #1, %d0         | decrement sample count
348     jne 1b                 | are we done?
349     jra .exit
351 .worder7:
352     movem.l (%a1), %d6-%d7/%a1-%a5
353     move.l (%a0)+, %a6
355     mac.l %a6, %a5, (%a0)+, %a6, %acc0
356     mac.l %a6, %a4, (%a0)+, %a6, %acc0
357     mac.l %a6, %a3, (%a0)+, %a6, %acc0
358     mac.l %a6, %a2, (%a0)+, %a6, %acc0
359     mac.l %a6, %a1, (%a0)+, %a6, %acc0
360     mac.l %a6, %d7, (%a0)+, %a6, %acc0
361     mac.l %a6, %d6, (-6*4, %a0), %a6, %acc0
362     move.l %accext01, %d4
363     movclr.l %acc0, %d3
364     lsr.l %d1, %d3
365     asl.l %d2, %d4
366     or.l %d4, %d3
367     add.l %d3, (%a0)
368     lea.l (-5*4, %a0), %a0
369     subq.l #1, %d0
370     jne 1b
371     jra .exit
373 .worder6:
374     movem.l (%a1), %d7/%a1-%a5
375     move.l (%a0)+, %a6
377     mac.l %a6, %a5, (%a0)+, %a6, %acc0
378     mac.l %a6, %a4, (%a0)+, %a6, %acc0
379     mac.l %a6, %a3, (%a0)+, %a6, %acc0
380     mac.l %a6, %a2, (%a0)+, %a6, %acc0
381     mac.l %a6, %a1, (%a0)+, %a6, %acc0
382     mac.l %a6, %d7, (-5*4, %a0), %a6, %acc0
383     move.l %accext01, %d4
384     movclr.l %acc0, %d3
385     lsr.l %d1, %d3
386     asl.l %d2, %d4
387     or.l %d4, %d3
388     add.l %d3, (%a0)
389     lea.l (-4*4, %a0), %a0
390     subq.l #1, %d0
391     jne 1b
392     jra .exit
394 .worder5:
395     movem.l (%a1), %a1-%a5
396     move.l (%a0)+, %a6
398     mac.l %a6, %a5, (%a0)+, %a6, %acc0
399     mac.l %a6, %a4, (%a0)+, %a6, %acc0
400     mac.l %a6, %a3, (%a0)+, %a6, %acc0
401     mac.l %a6, %a2, (%a0)+, %a6, %acc0
402     mac.l %a6, %a1, (-4*4, %a0), %a6, %acc0
403     move.l %accext01, %d4
404     movclr.l %acc0, %d3
405     lsr.l %d1, %d3
406     asl.l %d2, %d4
407     or.l %d4, %d3
408     add.l %d3, (%a0)
409     lea.l (-3*4, %a0), %a0
410     subq.l #1, %d0
411     jne 1b
412     jra .exit
414 .worder4:
415     movem.l (%a1), %a2-%a5
416     move.l (%a0)+, %a6
418     mac.l %a6, %a5, (%a0)+, %a6, %acc0
419     mac.l %a6, %a4, (%a0)+, %a6, %acc0
420     mac.l %a6, %a3, (%a0)+, %a6, %acc0
421     mac.l %a6, %a2, (-3*4, %a0), %a6, %acc0
422     move.l %accext01, %d4
423     movclr.l %acc0, %d3
424     lsr.l %d1, %d3
425     asl.l %d2, %d4
426     or.l %d4, %d3
427     add.l %d3, (%a0)
428     subq.l #8, %a0
429     subq.l #1, %d0
430     jne 1b
431     jra .exit
433 .worder3:
434     movem.l (%a1), %a3-%a5
435     move.l (%a0)+, %a6
437     mac.l %a6, %a5, (%a0)+, %a6, %acc0
438     mac.l %a6, %a4, (%a0)+, %a6, %acc0
439     mac.l %a6, %a3, (-2*4, %a0), %a6, %acc0
440     move.l %accext01, %d4
441     movclr.l %acc0, %d3
442     lsr.l %d1, %d3
443     asl.l %d2, %d4
444     or.l %d4, %d3
445     add.l %d3, (%a0)
446     subq.l #4, %a0
447     subq.l #1, %d0
448     jne 1b
449     jra .exit
451 .worder2:
452     movem.l (%a1), %a4-%a5
453     move.l (%a0)+, %a6
455     mac.l %a6, %a5, (%a0)+, %a6, %acc0
456     mac.l %a6, %a4, %acc0    | data for next iteration is already loaded
457     move.l %accext01, %d4
458     movclr.l %acc0, %d3
459     lsr.l %d1, %d3
460     asl.l %d2, %d4
461     or.l %d4, %d3
462     add.l %d3, (%a0)
463     subq.l #1, %d0
464     jne 1b
465     jra .exit
467 .worder1:
468     move.l (%a1), %a5
469     move.l (%a0)+, %a6
471     mac.l %a6, %a5, (%a0), %a6, %acc0
472     move.l %accext01, %d4
473     movclr.l %acc0, %d3
474     lsr.l %d1, %d3
475     asl.l %d2, %d4
476     or.l %d4, %d3
477     add.l %a6, %d3      | residual is already in a6
478     move.l %d3, (%a0)+
479     subq.l #1, %d0
480     jne 1b
481     jra .exit
482     
483 .wdefault:
484     /* we do the filtering in an unrolled by 4 loop as far as we can, and then
485        do the rest by jump table. */
486     lea.l (%a1, %d3.l*4), %a2 | need to start in the other end of coefs
487     move.l %a0, %a3           | working copy of history pointer
488     move.l %d3, %d4
489     lsr.l #2, %d4             | coefs/4, num of iterations needed in next loop
490     move.l (%a3)+, %a5        | preload data for loop
492     lea.l (-4*4, %a2), %a2     | move lpc coef pointer four samples backwards
493     movem.l (%a2), %d5-%d7/%a4 | load four coefs
494     mac.l %a5, %a4, (%a3)+, %a5, %acc0
495     mac.l %a5, %d7, (%a3)+, %a5, %acc0
496     mac.l %a5, %d6, (%a3)+, %a5, %acc0
497     mac.l %a5, %d5, (%a3)+, %a5, %acc0
498     subq.l #1, %d4            | any more unrolled loop operations left?
499     jne 1b
500     
501     moveq.l #3, %d4           | mask 0x00000003
502     and.l %d3, %d4            | get the remaining samples to be filtered
503     jmp.l (2, %pc, %d4*2)     | then jump into mac.l chain
504 | jumptable:
505     bra.b 3f                  | none left 
506     bra.b 2f                  | one left
507     bra.b 1f                  | two left
508 | three left
509     move.l -(%a2), %d4
510     mac.l %a5, %d4, (%a3)+, %a5, %acc0
512     move.l -(%a2), %d4
513     mac.l %a5, %d4, (%a3)+, %a5, %acc0
515     move.l -(%a2), %d4
516     mac.l %a5, %d4, (%a3)+, %a5, %acc0
518     move.l %accext01, %d5     | get high 32 bits of result
519     movclr.l %acc0, %d4       | get low 32 bits of result
520     lsr.l %d1, %d4            | shift qlevel bits right
521     asl.l %d2, %d5            | shift 32 - qlevel bits left
522     or.l %d5, %d4             | combine top and low bits after shift
523     add.l %a5, %d4            | add residual, which is in a5 by now
524     move.l %d4, -(%a3)        | save, a3 is also one past save location
525     addq.l #4, %a0            | increment history pointer
526     subq.l #1, %d0            | decrement sample count 
527     jne .wdefault             | are we done?
528                               | if so, fall through to exit
530 .exit:
531     movem.l (%sp), %d2-%d7/%a2-%a6
532     lea.l (44, %sp), %sp
533     rts