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:
parent
d11f15fcc3
commit
149df9794e
2 changed files with 41 additions and 37 deletions
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue