summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/codecs/libffmpegFLAC/coldfire.S321
-rw-r--r--apps/codecs/libffmpegFLAC/coldfire.h5
-rw-r--r--apps/codecs/libffmpegFLAC/decoder.c13
3 files changed, 299 insertions, 40 deletions
diff --git a/apps/codecs/libffmpegFLAC/coldfire.S b/apps/codecs/libffmpegFLAC/coldfire.S
index 1d144ec..5f464be 100644
--- a/apps/codecs/libffmpegFLAC/coldfire.S
+++ b/apps/codecs/libffmpegFLAC/coldfire.S
@@ -17,11 +17,14 @@
*
****************************************************************************/
-/* The following is an assembler optimised version of the LPC filtering
- routines needed for FLAC decoding. It is optimised for use with the
+/* The following are assembler optimised version of the LPC filtering
+ routines needed for FLAC decoding. They is optimised for use with the
MCF5249 processor, or any other similar ColdFire core with the EMAC unit.
- All LPC filtering up to order 10 is done in specially optimised unrolled
- loops, while every order above this is handled by a slower default routine.
+ */
+
+/* This routine deals with sample widths 16 and lower. All LPC filtering up to
+ order 10 is done in specially optimised unrolled loops, while every order
+ above this is handled by a slower default routine.
*/
.section .icode,"ax",@progbits
.global lpc_decode_emac
@@ -65,7 +68,7 @@ lpc_decode_emac:
.order10:
movem.l (%a1), %d3-%d7/%a1-%a5 | load lpc coefs
move.l (%a0)+, %a6 | load first history sample
-.loop10:
+1:
mac.l %a6, %a5, (%a0)+, %a6, %acc0
mac.l %a6, %a4, (%a0)+, %a6, %acc0
mac.l %a6, %a3, (%a0)+, %a6, %acc0
@@ -81,13 +84,13 @@ lpc_decode_emac:
add.l %d2, (%a0) | add residual and save
lea.l (-8*4, %a0), %a0 | point history back at second element
subq.l #1, %d0 | decrement sample count
- jne .loop10 | are we done?
+ jne 1b | are we done?
jra .exit
.order9:
movem.l (%a1), %d4-%d7/%a1-%a5
move.l (%a0)+, %a6
-.loop9:
+1:
mac.l %a6, %a5, (%a0)+, %a6, %acc0
mac.l %a6, %a4, (%a0)+, %a6, %acc0
mac.l %a6, %a3, (%a0)+, %a6, %acc0
@@ -102,13 +105,13 @@ lpc_decode_emac:
add.l %d2, (%a0)
lea.l (-7*4, %a0), %a0
subq.l #1, %d0
- jne .loop9
+ jne 1b
jra .exit
.order8:
movem.l (%a1), %d5-%d7/%a1-%a5
move.l (%a0)+, %a6
-.loop8:
+1:
mac.l %a6, %a5, (%a0)+, %a6, %acc0
mac.l %a6, %a4, (%a0)+, %a6, %acc0
mac.l %a6, %a3, (%a0)+, %a6, %acc0
@@ -122,13 +125,13 @@ lpc_decode_emac:
add.l %d2, (%a0)
lea.l (-6*4, %a0), %a0
subq.l #1, %d0
- jne .loop8
+ jne 1b
jra .exit
.order7:
movem.l (%a1), %d6-%d7/%a1-%a5
move.l (%a0)+, %a6
-.loop7:
+1:
mac.l %a6, %a5, (%a0)+, %a6, %acc0
mac.l %a6, %a4, (%a0)+, %a6, %acc0
mac.l %a6, %a3, (%a0)+, %a6, %acc0
@@ -141,13 +144,13 @@ lpc_decode_emac:
add.l %d2, (%a0)
lea.l (-5*4, %a0), %a0
subq.l #1, %d0
- jne .loop7
+ jne 1b
jra .exit
.order6:
movem.l (%a1), %d7/%a1-%a5
move.l (%a0)+, %a6
-.loop6:
+1:
mac.l %a6, %a5, (%a0)+, %a6, %acc0
mac.l %a6, %a4, (%a0)+, %a6, %acc0
mac.l %a6, %a3, (%a0)+, %a6, %acc0
@@ -159,13 +162,13 @@ lpc_decode_emac:
add.l %d2, (%a0)
lea.l (-4*4, %a0), %a0
subq.l #1, %d0
- jne .loop6
+ jne 1b
jra .exit
.order5:
movem.l (%a1), %a1-%a5
move.l (%a0)+, %a6
-.loop5:
+1:
mac.l %a6, %a5, (%a0)+, %a6, %acc0
mac.l %a6, %a4, (%a0)+, %a6, %acc0
mac.l %a6, %a3, (%a0)+, %a6, %acc0
@@ -176,13 +179,13 @@ lpc_decode_emac:
add.l %d2, (%a0)
lea.l (-3*4, %a0), %a0
subq.l #1, %d0
- jne .loop5
+ jne 1b
jra .exit
.order4:
movem.l (%a1), %a2-%a5
move.l (%a0)+, %a6
-.loop4:
+1:
mac.l %a6, %a5, (%a0)+, %a6, %acc0
mac.l %a6, %a4, (%a0)+, %a6, %acc0
mac.l %a6, %a3, (%a0)+, %a6, %acc0
@@ -192,13 +195,13 @@ lpc_decode_emac:
add.l %d2, (%a0)
subq.l #8, %a0
subq.l #1, %d0
- jne .loop4
+ jne 1b
jra .exit
.order3:
movem.l (%a1), %a3-%a5
move.l (%a0)+, %a6
-.loop3:
+1:
mac.l %a6, %a5, (%a0)+, %a6, %acc0
mac.l %a6, %a4, (%a0)+, %a6, %acc0
mac.l %a6, %a3, (-2*4, %a0), %a6, %acc0
@@ -207,32 +210,32 @@ lpc_decode_emac:
add.l %d2, (%a0)
subq.l #4, %a0
subq.l #1, %d0
- jne .loop3
+ jne 1b
jra .exit
.order2:
movem.l (%a1), %a4-%a5
move.l (%a0)+, %a6
-.loop2:
+1:
mac.l %a6, %a5, (%a0)+, %a6, %acc0
mac.l %a6, %a4, %acc0 | data for next iteration is already loaded
movclr.l %acc0, %d2
asr.l %d1, %d2
add.l %d2, (%a0)
subq.l #1, %d0
- jne .loop2
+ jne 1b
jra .exit
.order1:
| no point in using mac here
move.l (%a1), %a5
-.loop1:
+1:
move.l %a5, %d2
muls.l (%a0)+, %d2
asr.l %d1, %d2
add.l %d2, (%a0)
subq.l #1, %d0
- jne .loop1
+ jne 1b
jra .exit
.default:
@@ -243,7 +246,7 @@ lpc_decode_emac:
move.l %d2, %d3
lsr.l #2, %d3 | coefs/4, num of iterations needed in next loop
move.l (%a3)+, %a5 | preload data for loop
-.dloop1:
+1:
lea.l (-4*4, %a2), %a2 | move lpc coef pointer four samples backwards
movem.l (%a2), %d4-%d7 | load four coefs
mac.l %a5, %d7, (%a3)+, %a5, %acc0
@@ -251,33 +254,277 @@ lpc_decode_emac:
mac.l %a5, %d5, (%a3)+, %a5, %acc0
mac.l %a5, %d4, (%a3)+, %a5, %acc0
subq.l #1, %d3 | any more unrolled loop operations left?
- jne .dloop1
+ jne 1b
moveq.l #3, %d3 | mask 0x00000003
and.l %d2, %d3 | get the remaining samples to be filtered
jmp.l (2, %pc, %d3*2) | then jump into mac.l chain
| jumptable:
- bra.b .dsave
- bra.b .oneleft
- bra.b .twoleft
-| implicit .threeleft
+ bra.b 3f | none left
+ bra.b 2f | one left
+ bra.b 1f | two left
+| three left
move.l -(%a2), %d4
mac.l %a5, %d4, (%a3)+, %a5, %acc0
-.twoleft:
+1:
move.l -(%a2), %d4
mac.l %a5, %d4, (%a3)+, %a5, %acc0
-.oneleft:
+2:
move.l -(%a2), %d4
- mac.l %a5, %d4, (%a3)+, %a5, %acc0 | need this fetch to not break line below
-
-.dsave:
- subq.l #4, %a3 | we're one past the save location
+ mac.l %a5, %d4, (%a3)+, %a5, %acc0
+3:
movclr.l %acc0, %d3 | get result
asr.l %d1, %d3 | shift qlevel bits right
- add.l %d3, (%a3) | add residual and save
+ add.l %a5, %d3 | add residual, which is in a5 by now
+ move.l %d3, -(%a3) | save, a3 is also one past save location
addq.l #4, %a0 | increment history pointer
subq.l #1, %d0 | decrement sample count
jne .default | are we done?
+ jra .exit | if so, fall through to exit
+
+
+/* This routine deals with sample widths 24 and lower. All LPC filtering up to
+ order 8 is done in specially optimised unrolled loops, while every order
+ above this is handled by a slower default routine.
+ */
+ .global lpc_decode_emac_wide
+ .align 2
+lpc_decode_emac_wide:
+ lea.l (-44, %sp), %sp
+ movem.l %d2-%d7/%a2-%a6, (%sp)
+ movem.l (44+4, %sp), %d0-%d1/%d3/%a0-%a1
+ /* d0 = blocksize, d1 = qlevel, d3 = pred_order
+ a0 = data, a1 = coeffs
+ */
+
+ /* the data pointer always lags behind history pointer by 'pred_order'
+ samples. since we have one loop for each order, we can hard code this
+ and free a register by not saving data pointer.
+ */
+ move.l %d3, %d2
+ neg.l %d2
+ lea.l (%a0, %d2.l*4), %a0 | history
+ clr.l %d2
+ move.l %d2, %macsr | we'll need integer mode for this
+ tst.l %d0
+ jeq .exit | zero samples to process, exit
+ moveq.l #32, %d2
+ sub.l %d1, %d2 | calculate shift amount for extension byte
+ moveq.l #8, %d4
+ cmp.l %d4, %d3
+ jgt .wdefault | order is over 8, jump to default case
+ jmp.l (2, %pc, %d3.l*4) | jump to loop corresponding to pred_order
+| jumptable:
+ bra.w .exit | zero order filter isn't possible, exit function
+ bra.w .worder1
+ bra.w .worder2
+ bra.w .worder3
+ bra.w .worder4
+ bra.w .worder5
+ bra.w .worder6
+ bra.w .worder7
+
+| last jump table entry coincides with target, so leave it out
+.worder8:
+ movem.l (%a1), %d5-%d7/%a1-%a5 | load lpc coefs
+ move.l (%a0)+, %a6 | load first history sample
+1:
+ mac.l %a6, %a5, (%a0)+, %a6, %acc0
+ mac.l %a6, %a4, (%a0)+, %a6, %acc0
+ mac.l %a6, %a3, (%a0)+, %a6, %acc0
+ mac.l %a6, %a2, (%a0)+, %a6, %acc0
+ mac.l %a6, %a1, (%a0)+, %a6, %acc0
+ mac.l %a6, %d7, (%a0)+, %a6, %acc0
+ mac.l %a6, %d6, (%a0)+, %a6, %acc0
+ mac.l %a6, %d5, (-7*4, %a0), %a6, %acc0 | load for the next iteration
+ move.l %accext01, %d4 | get top 8 bits of sum
+ movclr.l %acc0, %d3 | then botten 32 bits
+ lsr.l %d1, %d3 | shift bottom bits qlevel bits right
+ asl.l %d2, %d4 | shift top bits 32 - qlevel bits left
+ or.l %d4, %d3 | now combine results
+ add.l %d3, (%a0) | add residual and save
+ lea.l (-6*4, %a0), %a0 | point history back at second element
+ subq.l #1, %d0 | decrement sample count
+ jne 1b | are we done?
+ jra .exit
+
+.worder7:
+ movem.l (%a1), %d6-%d7/%a1-%a5
+ move.l (%a0)+, %a6
+1:
+ mac.l %a6, %a5, (%a0)+, %a6, %acc0
+ mac.l %a6, %a4, (%a0)+, %a6, %acc0
+ mac.l %a6, %a3, (%a0)+, %a6, %acc0
+ mac.l %a6, %a2, (%a0)+, %a6, %acc0
+ mac.l %a6, %a1, (%a0)+, %a6, %acc0
+ mac.l %a6, %d7, (%a0)+, %a6, %acc0
+ mac.l %a6, %d6, (-6*4, %a0), %a6, %acc0
+ move.l %accext01, %d4
+ movclr.l %acc0, %d3
+ lsr.l %d1, %d3
+ asl.l %d2, %d4
+ or.l %d4, %d3
+ add.l %d3, (%a0)
+ lea.l (-5*4, %a0), %a0
+ subq.l #1, %d0
+ jne 1b
+ jra .exit
+
+.worder6:
+ movem.l (%a1), %d7/%a1-%a5
+ move.l (%a0)+, %a6
+1:
+ mac.l %a6, %a5, (%a0)+, %a6, %acc0
+ mac.l %a6, %a4, (%a0)+, %a6, %acc0
+ mac.l %a6, %a3, (%a0)+, %a6, %acc0
+ mac.l %a6, %a2, (%a0)+, %a6, %acc0
+ mac.l %a6, %a1, (%a0)+, %a6, %acc0
+ mac.l %a6, %d7, (-5*4, %a0), %a6, %acc0
+ move.l %accext01, %d4
+ movclr.l %acc0, %d3
+ lsr.l %d1, %d3
+ asl.l %d2, %d4
+ or.l %d4, %d3
+ add.l %d3, (%a0)
+ lea.l (-4*4, %a0), %a0
+ subq.l #1, %d0
+ jne 1b
+ jra .exit
+
+.worder5:
+ movem.l (%a1), %a1-%a5
+ move.l (%a0)+, %a6
+1:
+ mac.l %a6, %a5, (%a0)+, %a6, %acc0
+ mac.l %a6, %a4, (%a0)+, %a6, %acc0
+ mac.l %a6, %a3, (%a0)+, %a6, %acc0
+ mac.l %a6, %a2, (%a0)+, %a6, %acc0
+ mac.l %a6, %a1, (-4*4, %a0), %a6, %acc0
+ move.l %accext01, %d4
+ movclr.l %acc0, %d3
+ lsr.l %d1, %d3
+ asl.l %d2, %d4
+ or.l %d4, %d3
+ add.l %d3, (%a0)
+ lea.l (-3*4, %a0), %a0
+ subq.l #1, %d0
+ jne 1b
+ jra .exit
+
+.worder4:
+ movem.l (%a1), %a2-%a5
+ move.l (%a0)+, %a6
+1:
+ mac.l %a6, %a5, (%a0)+, %a6, %acc0
+ mac.l %a6, %a4, (%a0)+, %a6, %acc0
+ mac.l %a6, %a3, (%a0)+, %a6, %acc0
+ mac.l %a6, %a2, (-3*4, %a0), %a6, %acc0
+ move.l %accext01, %d4
+ movclr.l %acc0, %d3
+ lsr.l %d1, %d3
+ asl.l %d2, %d4
+ or.l %d4, %d3
+ add.l %d3, (%a0)
+ subq.l #8, %a0
+ subq.l #1, %d0
+ jne 1b
+ jra .exit
+
+.worder3:
+ movem.l (%a1), %a3-%a5
+ move.l (%a0)+, %a6
+1:
+ mac.l %a6, %a5, (%a0)+, %a6, %acc0
+ mac.l %a6, %a4, (%a0)+, %a6, %acc0
+ mac.l %a6, %a3, (-2*4, %a0), %a6, %acc0
+ move.l %accext01, %d4
+ movclr.l %acc0, %d3
+ lsr.l %d1, %d3
+ asl.l %d2, %d4
+ or.l %d4, %d3
+ add.l %d3, (%a0)
+ subq.l #4, %a0
+ subq.l #1, %d0
+ jne 1b
+ jra .exit
+
+.worder2:
+ movem.l (%a1), %a4-%a5
+ move.l (%a0)+, %a6
+1:
+ mac.l %a6, %a5, (%a0)+, %a6, %acc0
+ mac.l %a6, %a4, %acc0 | data for next iteration is already loaded
+ move.l %accext01, %d4
+ movclr.l %acc0, %d3
+ lsr.l %d1, %d3
+ asl.l %d2, %d4
+ or.l %d4, %d3
+ add.l %d3, (%a0)
+ subq.l #1, %d0
+ jne 1b
+ jra .exit
+
+.worder1:
+ move.l (%a1), %a5
+ move.l (%a0)+, %a6
+1:
+ mac.l %a6, %a5, (%a0), %a6, %acc0
+ move.l %accext01, %d4
+ movclr.l %acc0, %d3
+ lsr.l %d1, %d3
+ asl.l %d2, %d4
+ or.l %d4, %d3
+ add.l %a6, %d3 | residual is already in a6
+ move.l %d3, (%a0)+
+ subq.l #1, %d0
+ jne 1b
+ jra .exit
+
+.wdefault:
+ /* we do the filtering in an unrolled by 4 loop as far as we can, and then
+ do the rest by jump table. */
+ lea.l (%a1, %d3.l*4), %a2 | need to start in the other end of coefs
+ move.l %a0, %a3 | working copy of history pointer
+ move.l %d3, %d4
+ lsr.l #2, %d4 | coefs/4, num of iterations needed in next loop
+ move.l (%a3)+, %a5 | preload data for loop
+1:
+ lea.l (-4*4, %a2), %a2 | move lpc coef pointer four samples backwards
+ movem.l (%a2), %d5-%d7/%a4 | load four coefs
+ mac.l %a5, %a4, (%a3)+, %a5, %acc0
+ mac.l %a5, %d7, (%a3)+, %a5, %acc0
+ mac.l %a5, %d6, (%a3)+, %a5, %acc0
+ mac.l %a5, %d5, (%a3)+, %a5, %acc0
+ subq.l #1, %d4 | any more unrolled loop operations left?
+ jne 1b
+
+ moveq.l #3, %d4 | mask 0x00000003
+ and.l %d3, %d4 | get the remaining samples to be filtered
+ jmp.l (2, %pc, %d4*2) | then jump into mac.l chain
+| jumptable:
+ bra.b 3f | none left
+ bra.b 2f | one left
+ bra.b 1f | two left
+| three left
+ move.l -(%a2), %d4
+ mac.l %a5, %d4, (%a3)+, %a5, %acc0
+1:
+ move.l -(%a2), %d4
+ mac.l %a5, %d4, (%a3)+, %a5, %acc0
+2:
+ move.l -(%a2), %d4
+ mac.l %a5, %d4, (%a3)+, %a5, %acc0
+3:
+ move.l %accext01, %d5 | get high 32 bits of result
+ movclr.l %acc0, %d4 | get low 32 bits of result
+ lsr.l %d1, %d4 | shift qlevel bits right
+ asl.l %d2, %d5 | shift 32 - qlevel bits left
+ or.l %d5, %d4 | combine top and low bits after shift
+ add.l %a5, %d4 | add residual, which is in a5 by now
+ move.l %d4, -(%a3) | save, a3 is also one past save location
+ addq.l #4, %a0 | increment history pointer
+ subq.l #1, %d0 | decrement sample count
+ jne .wdefault | are we done?
| if so, fall through to exit
.exit:
diff --git a/apps/codecs/libffmpegFLAC/coldfire.h b/apps/codecs/libffmpegFLAC/coldfire.h
index 5493f54..d6f0996 100644
--- a/apps/codecs/libffmpegFLAC/coldfire.h
+++ b/apps/codecs/libffmpegFLAC/coldfire.h
@@ -3,6 +3,9 @@
#include "bitstream.h"
-void lpc_decode_emac(int blocksize, int qlevel, int pred_order, int32_t* data, int* coeffs);
+void lpc_decode_emac(int blocksize, int qlevel, int pred_order, int32_t* data,
+ int* coeffs);
+void lpc_decode_emac_wide(int blocksize, int qlevel, int pred_order,
+ int32_t* data, int* coeffs);
#endif
diff --git a/apps/codecs/libffmpegFLAC/decoder.c b/apps/codecs/libffmpegFLAC/decoder.c
index 9c85864..4dbae97 100644
--- a/apps/codecs/libffmpegFLAC/decoder.c
+++ b/apps/codecs/libffmpegFLAC/decoder.c
@@ -262,10 +262,12 @@ static int decode_subframe_lpc(FLACContext *s, int32_t* decoded, int pred_order)
if ((s->bps + coeff_prec + av_log2(pred_order)) <= 32) {
#if defined(CPU_COLDFIRE) && !defined(SIMULATOR)
(void)sum;
- lpc_decode_emac(s->blocksize - pred_order, qlevel, pred_order, decoded + pred_order, coeffs);
+ lpc_decode_emac(s->blocksize - pred_order, qlevel, pred_order,
+ decoded + pred_order, coeffs);
#elif defined(CPU_ARM) && !defined(SIMULATOR)
(void)sum;
- lpc_decode_arm(s->blocksize - pred_order, qlevel, pred_order, decoded + pred_order, coeffs);
+ lpc_decode_arm(s->blocksize - pred_order, qlevel, pred_order,
+ decoded + pred_order, coeffs);
#else
for (i = pred_order; i < s->blocksize; i++)
{
@@ -276,6 +278,12 @@ static int decode_subframe_lpc(FLACContext *s, int32_t* decoded, int pred_order)
}
#endif
} else {
+ #if defined(CPU_COLDFIRE) && !defined(SIMULATOR)
+ (void)wsum;
+ (void)j;
+ lpc_decode_emac_wide(s->blocksize - pred_order, qlevel, pred_order,
+ decoded + pred_order, coeffs);
+ #else
for (i = pred_order; i < s->blocksize; i++)
{
wsum = 0;
@@ -283,6 +291,7 @@ static int decode_subframe_lpc(FLACContext *s, int32_t* decoded, int pred_order)
wsum += (int64_t)coeffs[j] * (int64_t)decoded[i-j-1];
decoded[i] += wsum >> qlevel;
}
+ #endif
}
return 0;