diff options
author | Thom Johansen <thomj@rockbox.org> | 2006-03-05 21:16:57 +0000 |
---|---|---|
committer | Thom Johansen <thomj@rockbox.org> | 2006-03-05 21:16:57 +0000 |
commit | 149df9794ee3513cd815c095ad3cb65e4346d6a4 (patch) | |
tree | cd1164c07c14e1dc8008224205339a51061a07e2 /firmware/pcm_playback.c | |
parent | d11f15fcc3b20a1c7a7226aeb8e100c5b6ed6234 (diff) | |
download | rockbox-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/pcm_playback.c')
-rw-r--r-- | firmware/pcm_playback.c | 72 |
1 files changed, 35 insertions, 37 deletions
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; | |||
330 | static bool pcm_paused; | 330 | static bool pcm_paused; |
331 | static int pcm_freq = 0x6; /* 44.1 is default */ | 331 | static 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. */ | ||
333 | unsigned short* p IBSS_ATTR; | 335 | unsigned short* p IBSS_ATTR; |
334 | long p_size IBSS_ATTR; | 336 | long p_size IBSS_ATTR; |
335 | 337 | ||
@@ -552,36 +554,38 @@ bool pcm_is_playing(void) | |||
552 | void fiq(void) ICODE_ATTR __attribute__((naked)); | 554 | void fiq(void) ICODE_ATTR __attribute__((naked)); |
553 | void fiq(void) | 555 | void 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 | } |