[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-gcc-list] swap bits
From: |
Bruce D. Lightner |
Subject: |
Re: [avr-gcc-list] swap bits |
Date: |
Tue, 21 Jan 2003 12:49:16 -0800 |
Christian Ludlam wrote:
> On 21 Jan Klaus Rudolph wrote:
>
> > 51 cycles total without wasting any register.
> > 10 words flash.
> > 51 cycles is very expensive. Any better ideas here :-)
>
> Which processor is this running on?
>
> You could use a table lookup in 4 bits to reduce flash usage - this code
> requires an architecture with enhanced LPM addressing modes:
>
> ; E r16 = byte
> ; X r16 = reversed byte
> reverse_byte
> ldi ZL,(table * 2) & 0xff ; 1
> ldi ZH,(table >> 7) ; 1
> ;
> mov r0,r16 ; 1
> andi r16,0x0f ; 1
> add ZL,r16 ; 1
> adc ZH,__zero_reg__ ; 1
> mov r16,r0 ; 1
> lpm R0,Z ; 2
> ;
> ldi ZL,(table * 2) & 0xff ; 1
> ldi ZH,(table >> 7) ; 1
> ;
> swap r16 ; 1
> andi r16,0x0f ; 1
> add ZL,r16 ; 1
> adc ZH,__zero_reg__ ; 1
> lpm R16,Z ; 2
> ;
> swap r0 ; 1
> or r16,r0 ; 1
>
> table db 0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15
>
> Total 20 cycles, 24 flash words. You could optimise it further by ensuring
> the table doesn't cross a page boundary and removing the adc instructions.
>
> --
> Christian Ludlam
> address@hidden
> avr-gcc-list at http://avr1.org
How about this "brute force" AVR gcc assembly language macro...
#define reverse(a) ({ \
unsigned char ch; \
asm volatile ( \
"ror %1" "\n\t" \
"rol %0" "\n\t" \
"ror %1" "\n\t" \
"rol %0" "\n\t" \
"ror %1" "\n\t" \
"rol %0" "\n\t" \
"ror %1" "\n\t" \
"rol %0" "\n\t" \
"ror %1" "\n\t" \
"rol %0" "\n\t" \
"ror %1" "\n\t" \
"rol %0" "\n\t" \
"ror %1" "\n\t" \
"rol %0" "\n\t" \
"ror %1" "\n\t" \
"rol %0" "\n\t" \
"ror %1" /* restore input register */ \
: /* output */ "=r&" (ch) \
: /* input */ "r" ((uint8_t)(a)) \
); \
ch; \
})
A total of 17 cycles, 17 flash words.
This macro, as written, forces the "input" and "output" registers
to be different (i.e., because of the "&"). Perhaps someone smarter
than I could reduce this by one cycle (and one flash word) by
deleting the last ROR and somehow telling the code generator you
were destroying the input register.
My test program...
unsigned char test(unsigned char ch)
{
return reverse(ch);
}
...generates the following assembly language listing (using
the avr-gcc switch "-Wa,-almshd=test.lst")...
79 .section .text
82 .global test
84 test:
35:utest.c **** unsigned char test(unsigned char x)
36:utest.c **** {
86 .LM1:
87 /* prologue: frame size=0 */
88 /* prologue end (size=0) */
37:utest.c **** return reverse(x);
90 .LM2:
91 .LBB2:
92 .LBB3:
93 /* #APP */
94 0000 9795 ror r25
95 0002 881F rol r24
96 0004 9795 ror r25
97 0006 881F rol r24
98 0008 9795 ror r25
99 000a 881F rol r24
100 000c 9795 ror r25
101 000e 881F rol r24
102 0010 9795 ror r25
103 0012 881F rol r24
104 0014 9795 ror r25
105 0016 881F rol r24
106 0018 9795 ror r25
107 001a 881F rol r24
108 001c 9795 ror r25
109 001e 881F rol r24
110 0020 9795 ror r25
111
112 /* #NOAPP */
113 .LBE3:
114 0022 9927 clr r25
38:utest.c **** }
116 .LM3:
117 .LBE2:
118 /* epilogue: frame size=0 */
119 0024 0895 ret
120 /* epilogue end (size=1) */
121 /* function test size 38 (37) */
Best regards,
Bruce
--
Bruce D. Lightner
Lightner Engineering
La Jolla, California
Voice: +1-858-551-4011
FAX: +1-858-551-0777
Email: address@hidden
URL: http://www.lightner.net/lightner/bruce/
avr-gcc-list at http://avr1.org