rockbox/lib
Michael Giacomelli d514ee9282 opus: ARMv4 assembly for the backward MDCT inner loops
Cuts realtime decode on the Sansa e200v1 from 52.1 MHz to 50.8 MHz.
clt_mdct_backward was the largest remaining item at 13.5% of decode.

Only the three inner loops move to assembly.  The setup stays in C, so
mdct.c remains readable and the assembly needs no knowledge of
mdct_lookup.

What the compiled loops lose is registers.  Each needs more live values
than gcc can hold, so it spills the loop-invariant pointers, strides and
limits and reloads them every pass: five stack accesses per iteration in
the post-rotation alone.  Holding the twiddle as a 16-bit value and
accumulating the product pair with smull/smlal is what makes the
bookkeeping fit, needing seven live registers where the shifted
MULT16_32_Q15 form needs nine.

ldm/stm helps only where the addressing allows.  The post-rotation walks
the buffer from both ends and so reads and writes contiguous pairs.  The
pre-rotation reads the spectrum through a runtime stride and writes
through the bitrev table, so only its 8-byte output pair merges, and the
TDAC mirror merges nothing.

Over 160 ms of stereo music, traced under qemu:

  clt_mdct_backward  1,037,962 ->   900,982   -13.2%
  whole decode       7,695,876 -> 7,558,896    -1.8%
  loads                650,157 ->   611,667    -5.9%
  stores               350,605 ->   323,605    -7.7%
  multiplies           337,493 ->   337,493   unchanged

Accuracy improves substantially, because all three loops keep 32 bits of
each Q15 product where MULT16_32_Q15_armv4 drops the low bit, and the
backward MDCT applies three such rounds per sample.  The rounding SNR of
the backward transform rises about 9.5 dB, and its worst case error falls
from 708 to 186.  Decoded output differs from the previous build in 90 of
15,360 samples, each by one LSB.

Build with OPUS_ARM_NO_MDCT_ASM to select the C loops instead.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Change-Id: I3c4404b4dbe581d8bcf1f357266a658a068fdb50
2026-09-22 07:26:56 -04:00
..
arm_support chore: Get rid of *all* vestigal CVS '$Id:$' tags 2026-06-01 16:01:18 -04:00
fixedpoint chore: Get rid of *all* vestigal CVS '$Id:$' tags 2026-06-01 16:01:18 -04:00
libsetjmp libsetjmp: fix unpredictable behavior warning on ARM Cortex-M 2025-04-19 11:24:01 -04:00
microtar chore: Get rid of *all* vestigal CVS '$Id:$' tags 2026-06-01 16:01:18 -04:00
mipsunwinder chore: Get rid of *all* vestigal CVS '$Id:$' tags 2026-06-01 16:01:18 -04:00
rbcodec opus: ARMv4 assembly for the backward MDCT inner loops 2026-09-22 07:26:56 -04:00
skin_parser skin_parser: Fix regression in 0d5afa6d 2026-07-05 19:12:25 -04:00
tlsf chore: Get rid of *all* vestigal CVS '$Id:$' tags 2026-06-01 16:01:18 -04:00
unwarminder chore: Get rid of *all* vestigal CVS '$Id:$' tags 2026-06-01 16:01:18 -04:00
utf8proc utf8proc: Add utf8proc for normalizing UTF-8 strings 2026-03-01 08:26:00 -05:00