Make better use of banked registers in FIQ mode to shrink the iPod FIQ

handler a bit.


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8920 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Thom Johansen 2006-03-05 21:16:57 +00:00
parent d11f15fcc3
commit 149df9794e
2 changed files with 41 additions and 37 deletions

View file

@ -285,6 +285,12 @@ boot_table:
/* Set up stack for FIQ mode */
msr cpsr_c, #0xd1
ldr sp, =fiq_stack
#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002
/* We'll load the banked FIQ mode registers with useful values here.
These values will be used in the FIQ handler in pcm_playback.c */
ldr r12, =0x70002800 /* IISCONFIG */
ldr r11, =p
#endif
/* Let abort mode use IRQ stack */
msr cpsr_c, #0xd7
ldr sp, =irq_stack

View file

@ -330,6 +330,8 @@ static bool pcm_playing;
static bool pcm_paused;
static int pcm_freq = 0x6; /* 44.1 is default */
/* NOTE: The order of these two variables is important if you use the iPod
assembler optimised fiq handler, so don't change it. */
unsigned short* p IBSS_ATTR;
long p_size IBSS_ATTR;
@ -552,36 +554,38 @@ bool pcm_is_playing(void)
void fiq(void) ICODE_ATTR __attribute__((naked));
void fiq(void)
{
/* r12 contains IISCONFIG address (set in crt0.S to minimise code in actual
* FIQ handler. r11 contains address of p (also set in crt0.S). Most other
* addresses we need are generated by using offsets with these two.
* r12 + 0x40 is IISFIFO_WR, and r12 + 0x0c is IISFIFO_CFG.
* r8 and r9 contains local copies of p_size and p respectively.
* r10 is a working register.
*/
asm volatile (
"ldr r12, =0x70002800 \n\t" /* r12 = IISCONFIG */
"ldr r11, [r12] \n\t"
"bic r11, r11, #0x2 \n\t" /* clear interrupt */
"str r11, [r12] \n\t"
"ldr r8, =p_size \n\t"
"ldr r9, =p \n\t"
"ldr r8, [r8] \n\t" /* r8 = p_size */
"ldr r9, [r9] \n\t" /* r9 = p */
"ldr r10, =0x70002840 \n\t" /* r10 = IISFIFO_WR */
"ldr r11, =0x7000280c \n\t" /* r11 = IISFIFO_CFG */
"ldr r10, [r12] \n\t"
"bic r10, r10, #0x2 \n\t" /* clear interrupt */
"str r10, [r12] \n\t"
"ldr r8, [r11, #4] \n\t" /* r8 = p_size */
"ldr r9, [r11] \n\t" /* r9 = p */
".loop: \n\t"
"cmp r8, #0 \n\t" /* is p_size 0? */
"beq .more_data \n\t" /* if so, ask pcmbuf for more data */
".fifo_loop: \n\t"
"ldr r12, [r11] \n\t" /* read IISFIFO_CFG to check FIFO status */
"and r12, r12, #0x3f0000\n\t"
"cmp r12, #0x10000 \n\t"
"ldr r10, [r12, #0x0c]\n\t" /* read IISFIFO_CFG to check FIFO status */
"and r10, r10, #0x3f0000\n\t"
"cmp r10, #0x10000 \n\t"
"bls .fifo_full \n\t" /* FIFO full, exit */
"ldr r12, [r9], #4 \n\t" /* load two samples to r12 */
"mov r12, r12, ror #16\n\t" /* put left sample at the top bits */
"str r12, [r10] \n\t" /* write top sample, lower sample ignored */
"mov r12, r12, lsl #16\n\t" /* shift lower sample up */
"str r12, [r10] \n\t" /* then write it */
"ldr r10, [r9], #4 \n\t" /* load two samples */
"mov r10, r10, ror #16\n\t" /* put left sample at the top bits */
"str r10, [r12, #0x40]\n\t" /* write top sample, lower sample ignored */
"mov r10, r10, lsl #16\n\t" /* shift lower sample up */
"str r10, [r12, #0x40]\n\t" /* then write it */
"subs r8, r8, #4 \n\t" /* check if we have more samples */
"bne .fifo_loop \n\t" /* yes, continue */
".more_data: \n\t"
"stmdb sp!, { r0-r3, lr}\n\t" /* stack scratch regs and lr */
"ldr r0, =p \n\t" /* load parameters to callback_for_more */
"ldr r1, =p_size \n\t"
"stmdb sp!, { r0-r3, r12, lr}\n\t" /* stack scratch regs and lr */
"mov r0, r11 \n\t" /* r0 = &p */
"add r1, r11, #4 \n\t" /* r1 = &p_size */
"str r9, [r0] \n\t" /* save internal copies of variables back */
"str r8, [r1] \n\t"
"ldr r2, =callback_for_more\n\t"
@ -589,36 +593,30 @@ void fiq(void)
"cmp r2, #0 \n\t" /* check for null pointer */
"movne lr, pc \n\t" /* call callback_for_more */
"bxne r2 \n\t"
"ldmia sp!, { r0-r3, lr}\n\t"
"ldr r8, =p_size \n\t" /* reload p_size and p */
"ldr r9, =p \n\t"
"ldr r8, [r8] \n\t"
"ldr r9, [r9] \n\t"
"ldmia sp!, { r0-r3, r12, lr}\n\t"
"ldr r8, [r11, #4] \n\t" /* reload p_size and p */
"ldr r9, [r11] \n\t"
"cmp r8, #0 \n\t" /* did we actually get more data? */
"bne .loop \n\t" /* yes, continue to try feeding FIFO */
".dma_stop: \n\t" /* no more data, do dma_stop() and exit */
"ldr r10, =pcm_playing\n\t"
"strb r8, [r10] \n\t" /* pcm_playing = false (r8=0, look above) */
"ldr r10, =0x70002800 \n\t" /* r10 = IISCONFIG */
"ldr r11, [r10] \n\t"
"bic r11, r11, #0x20000002\n\t" /* disable playback FIFO and IRQ */
"str r11, [r10] \n\t"
"ldr r10, [r12] \n\t"
"bic r10, r10, #0x20000002\n\t" /* disable playback FIFO and IRQ */
"str r10, [r12] \n\t"
"mrs r10, cpsr \n\t"
"orr r10, r10, #0x40 \n\t" /* disable FIQ */
"msr cpsr_c, r10 \n\t"
"ldr r10, =pcm_paused \n\t"
"strb r8, [r10] \n\t" /* pcm_paused = false */
".exit: \n\t"
"ldr r10, =p_size \n\t" /* save back p_size and p, then exit */
"ldr r11, =p \n\t"
"str r8, [r10] \n\t"
"str r8, [r11, #4] \n\t"
"str r9, [r11] \n\t"
"subs pc, lr, #4 \n\t" /* FIQ specific return sequence */
".fifo_full: \n\t" /* enable IRQ and exit */
"ldr r12, =0x70002800 \n\t" /* r12 = IISCONFIG */
"ldr r11, [r12] \n\t"
"orr r11, r11, #0x2 \n\t" /* set interrupt */
"str r11, [r12] \n\t"
"ldr r10, [r12] \n\t"
"orr r10, r10, #0x2 \n\t" /* set interrupt */
"str r10, [r12] \n\t"
"b .exit \n\t"
);
}