summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorThom Johansen <thomj@rockbox.org>2006-03-05 21:16:57 +0000
committerThom Johansen <thomj@rockbox.org>2006-03-05 21:16:57 +0000
commit149df9794ee3513cd815c095ad3cb65e4346d6a4 (patch)
treecd1164c07c14e1dc8008224205339a51061a07e2 /firmware
parentd11f15fcc3b20a1c7a7226aeb8e100c5b6ed6234 (diff)
downloadrockbox-149df9794ee3513cd815c095ad3cb65e4346d6a4.tar.gz
rockbox-149df9794ee3513cd815c095ad3cb65e4346d6a4.zip
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
Diffstat (limited to 'firmware')
-rw-r--r--firmware/crt0.S6
-rw-r--r--firmware/pcm_playback.c72
2 files changed, 41 insertions, 37 deletions
diff --git a/firmware/crt0.S b/firmware/crt0.S
index 061ffebeab..e7210e6d78 100644
--- a/firmware/crt0.S
+++ b/firmware/crt0.S
@@ -285,6 +285,12 @@ boot_table:
285 /* Set up stack for FIQ mode */ 285 /* Set up stack for FIQ mode */
286 msr cpsr_c, #0xd1 286 msr cpsr_c, #0xd1
287 ldr sp, =fiq_stack 287 ldr sp, =fiq_stack
288#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002
289 /* We'll load the banked FIQ mode registers with useful values here.
290 These values will be used in the FIQ handler in pcm_playback.c */
291 ldr r12, =0x70002800 /* IISCONFIG */
292 ldr r11, =p
293#endif
288 /* Let abort mode use IRQ stack */ 294 /* Let abort mode use IRQ stack */
289 msr cpsr_c, #0xd7 295 msr cpsr_c, #0xd7
290 ldr sp, =irq_stack 296 ldr sp, =irq_stack
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c
index 6d60c40fdb..75b3de4f90 100644
--- a/firmware/pcm_playback.c
+++ b/firmware/pcm_playback.c
@@ -330,6 +330,8 @@ static bool pcm_playing;
330static bool pcm_paused; 330static bool pcm_paused;
331static int pcm_freq = 0x6; /* 44.1 is default */ 331static int pcm_freq = 0x6; /* 44.1 is default */
332 332
333/* NOTE: The order of these two variables is important if you use the iPod
334 assembler optimised fiq handler, so don't change it. */
333unsigned short* p IBSS_ATTR; 335unsigned short* p IBSS_ATTR;
334long p_size IBSS_ATTR; 336long p_size IBSS_ATTR;
335 337
@@ -552,36 +554,38 @@ bool pcm_is_playing(void)
552void fiq(void) ICODE_ATTR __attribute__((naked)); 554void fiq(void) ICODE_ATTR __attribute__((naked));
553void fiq(void) 555void fiq(void)
554{ 556{
557 /* r12 contains IISCONFIG address (set in crt0.S to minimise code in actual
558 * FIQ handler. r11 contains address of p (also set in crt0.S). Most other
559 * addresses we need are generated by using offsets with these two.
560 * r12 + 0x40 is IISFIFO_WR, and r12 + 0x0c is IISFIFO_CFG.
561 * r8 and r9 contains local copies of p_size and p respectively.
562 * r10 is a working register.
563 */
555 asm volatile ( 564 asm volatile (
556 "ldr r12, =0x70002800 \n\t" /* r12 = IISCONFIG */ 565 "ldr r10, [r12] \n\t"
557 "ldr r11, [r12] \n\t" 566 "bic r10, r10, #0x2 \n\t" /* clear interrupt */
558 "bic r11, r11, #0x2 \n\t" /* clear interrupt */ 567 "str r10, [r12] \n\t"
559 "str r11, [r12] \n\t" 568 "ldr r8, [r11, #4] \n\t" /* r8 = p_size */
560 "ldr r8, =p_size \n\t" 569 "ldr r9, [r11] \n\t" /* r9 = p */
561 "ldr r9, =p \n\t"
562 "ldr r8, [r8] \n\t" /* r8 = p_size */
563 "ldr r9, [r9] \n\t" /* r9 = p */
564 "ldr r10, =0x70002840 \n\t" /* r10 = IISFIFO_WR */
565 "ldr r11, =0x7000280c \n\t" /* r11 = IISFIFO_CFG */
566 ".loop: \n\t" 570 ".loop: \n\t"
567 "cmp r8, #0 \n\t" /* is p_size 0? */ 571 "cmp r8, #0 \n\t" /* is p_size 0? */
568 "beq .more_data \n\t" /* if so, ask pcmbuf for more data */ 572 "beq .more_data \n\t" /* if so, ask pcmbuf for more data */
569 ".fifo_loop: \n\t" 573 ".fifo_loop: \n\t"
570 "ldr r12, [r11] \n\t" /* read IISFIFO_CFG to check FIFO status */ 574 "ldr r10, [r12, #0x0c]\n\t" /* read IISFIFO_CFG to check FIFO status */
571 "and r12, r12, #0x3f0000\n\t" 575 "and r10, r10, #0x3f0000\n\t"
572 "cmp r12, #0x10000 \n\t" 576 "cmp r10, #0x10000 \n\t"
573 "bls .fifo_full \n\t" /* FIFO full, exit */ 577 "bls .fifo_full \n\t" /* FIFO full, exit */
574 "ldr r12, [r9], #4 \n\t" /* load two samples to r12 */ 578 "ldr r10, [r9], #4 \n\t" /* load two samples */
575 "mov r12, r12, ror #16\n\t" /* put left sample at the top bits */ 579 "mov r10, r10, ror #16\n\t" /* put left sample at the top bits */
576 "str r12, [r10] \n\t" /* write top sample, lower sample ignored */ 580 "str r10, [r12, #0x40]\n\t" /* write top sample, lower sample ignored */
577 "mov r12, r12, lsl #16\n\t" /* shift lower sample up */ 581 "mov r10, r10, lsl #16\n\t" /* shift lower sample up */
578 "str r12, [r10] \n\t" /* then write it */ 582 "str r10, [r12, #0x40]\n\t" /* then write it */
579 "subs r8, r8, #4 \n\t" /* check if we have more samples */ 583 "subs r8, r8, #4 \n\t" /* check if we have more samples */
580 "bne .fifo_loop \n\t" /* yes, continue */ 584 "bne .fifo_loop \n\t" /* yes, continue */
581 ".more_data: \n\t" 585 ".more_data: \n\t"
582 "stmdb sp!, { r0-r3, lr}\n\t" /* stack scratch regs and lr */ 586 "stmdb sp!, { r0-r3, r12, lr}\n\t" /* stack scratch regs and lr */
583 "ldr r0, =p \n\t" /* load parameters to callback_for_more */ 587 "mov r0, r11 \n\t" /* r0 = &p */
584 "ldr r1, =p_size \n\t" 588 "add r1, r11, #4 \n\t" /* r1 = &p_size */
585 "str r9, [r0] \n\t" /* save internal copies of variables back */ 589 "str r9, [r0] \n\t" /* save internal copies of variables back */
586 "str r8, [r1] \n\t" 590 "str r8, [r1] \n\t"
587 "ldr r2, =callback_for_more\n\t" 591 "ldr r2, =callback_for_more\n\t"
@@ -589,36 +593,30 @@ void fiq(void)
589 "cmp r2, #0 \n\t" /* check for null pointer */ 593 "cmp r2, #0 \n\t" /* check for null pointer */
590 "movne lr, pc \n\t" /* call callback_for_more */ 594 "movne lr, pc \n\t" /* call callback_for_more */
591 "bxne r2 \n\t" 595 "bxne r2 \n\t"
592 "ldmia sp!, { r0-r3, lr}\n\t" 596 "ldmia sp!, { r0-r3, r12, lr}\n\t"
593 "ldr r8, =p_size \n\t" /* reload p_size and p */ 597 "ldr r8, [r11, #4] \n\t" /* reload p_size and p */
594 "ldr r9, =p \n\t" 598 "ldr r9, [r11] \n\t"
595 "ldr r8, [r8] \n\t"
596 "ldr r9, [r9] \n\t"
597 "cmp r8, #0 \n\t" /* did we actually get more data? */ 599 "cmp r8, #0 \n\t" /* did we actually get more data? */
598 "bne .loop \n\t" /* yes, continue to try feeding FIFO */ 600 "bne .loop \n\t" /* yes, continue to try feeding FIFO */
599 ".dma_stop: \n\t" /* no more data, do dma_stop() and exit */ 601 ".dma_stop: \n\t" /* no more data, do dma_stop() and exit */
600 "ldr r10, =pcm_playing\n\t" 602 "ldr r10, =pcm_playing\n\t"
601 "strb r8, [r10] \n\t" /* pcm_playing = false (r8=0, look above) */ 603 "strb r8, [r10] \n\t" /* pcm_playing = false (r8=0, look above) */
602 "ldr r10, =0x70002800 \n\t" /* r10 = IISCONFIG */ 604 "ldr r10, [r12] \n\t"
603 "ldr r11, [r10] \n\t" 605 "bic r10, r10, #0x20000002\n\t" /* disable playback FIFO and IRQ */
604 "bic r11, r11, #0x20000002\n\t" /* disable playback FIFO and IRQ */ 606 "str r10, [r12] \n\t"
605 "str r11, [r10] \n\t"
606 "mrs r10, cpsr \n\t" 607 "mrs r10, cpsr \n\t"
607 "orr r10, r10, #0x40 \n\t" /* disable FIQ */ 608 "orr r10, r10, #0x40 \n\t" /* disable FIQ */
608 "msr cpsr_c, r10 \n\t" 609 "msr cpsr_c, r10 \n\t"
609 "ldr r10, =pcm_paused \n\t" 610 "ldr r10, =pcm_paused \n\t"
610 "strb r8, [r10] \n\t" /* pcm_paused = false */ 611 "strb r8, [r10] \n\t" /* pcm_paused = false */
611 ".exit: \n\t" 612 ".exit: \n\t"
612 "ldr r10, =p_size \n\t" /* save back p_size and p, then exit */ 613 "str r8, [r11, #4] \n\t"
613 "ldr r11, =p \n\t"
614 "str r8, [r10] \n\t"
615 "str r9, [r11] \n\t" 614 "str r9, [r11] \n\t"
616 "subs pc, lr, #4 \n\t" /* FIQ specific return sequence */ 615 "subs pc, lr, #4 \n\t" /* FIQ specific return sequence */
617 ".fifo_full: \n\t" /* enable IRQ and exit */ 616 ".fifo_full: \n\t" /* enable IRQ and exit */
618 "ldr r12, =0x70002800 \n\t" /* r12 = IISCONFIG */ 617 "ldr r10, [r12] \n\t"
619 "ldr r11, [r12] \n\t" 618 "orr r10, r10, #0x2 \n\t" /* set interrupt */
620 "orr r11, r11, #0x2 \n\t" /* set interrupt */ 619 "str r10, [r12] \n\t"
621 "str r11, [r12] \n\t"
622 "b .exit \n\t" 620 "b .exit \n\t"
623 ); 621 );
624} 622}