avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-gcc-list] How to (efficeiently !!!) test a bit within a multi-byte


From: Vincent Trouilliez
Subject: [avr-gcc-list] How to (efficeiently !!!) test a bit within a multi-byte integer ?
Date: Fri, 04 Nov 2005 06:35:57 +0100

Hello list,

I just ran into a weird problem that I hardly expected. 
I wrote a trivial routine that takes a 32bit unsigned int, which holds a
memory address, and shifts the lower 19 bits, out to a port pin (this
feeds cascaded shift registers, that in turn drive the 19 address lines
of a memory chip).
The 19th/MSbit is shifted first, so this is the bit I actually test.
But when I timed the routine, I discovered with much surprise and
horror, that instead of being very quick, it's massively slow to
execute ! About 3ms/3,000 cycles ! This makes it useless in the case at
hand sadly.
I looked at the disassembler output and discovered that instead of
testing directly the required (19th) bit of the address/integer, it
shifted the number 18 times to bring said bit on the far right, and then
only, test it.
So the routine takes about 20 times more time to execute than it should,
hence the 3ms horror figure I measured :-/
I tried various optimisation flags (-O, -Os, -O3) but all of them use
the same method, none of them manages to test the bit directly/quickly.
Looking at the AVR instruction set, there exist instructions by the
names of SBRC and SBRS, which should be able to test whatever bit in a
register, which is what is needed here: test the third bit of the third
byte of this 4 byte integer.

How should I re-word my bit test statement/expression, to cause the
compiler to use these lovely SBRS/C instructions at last ?



Regards,


--
Vince, puzzled...


static void log_address_set( uint32_t address )
{
...
...
        if (address & 0x00040000)
                PORTB |= LOG_SDA;
        else
                PORTB &= ~LOG_SDA;
...
}


static void log_address_set( uint32_t address )
{
...
...
                if (address & 0x00040000)
    24ec:       da 01           movw    r26, r20
    24ee:       c9 01           movw    r24, r18
    24f0:       72 e1           ldi     r23, 0x12       ; 18
    24f2:       b6 95           lsr     r27
    24f4:       a7 95           ror     r26
    24f6:       97 95           ror     r25
    24f8:       87 95           ror     r24
    24fa:       7a 95           dec     r23
    24fc:       d1 f7           brne    .-12            ; 0x24f2
    24fe:       81 70           andi    r24, 0x01       ; 1
    2500:       90 70           andi    r25, 0x00       ; 0
    2502:       89 2b           or      r24, r25
    2504:       11 f0           breq    .+4             ; 0x250a
                        PORTB |= LOG_SDA;
    2506:       c0 9a           sbi     0x18, 0 ; 24
    2508:       01 c0           rjmp    .+2             ; 0x250c
                else
                        PORTB &= ~LOG_SDA;
    250a:       c0 98           cbi     0x18, 0 ; 24






reply via email to

[Prev in Thread] Current Thread [Next in Thread]