[Top][All Lists]

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

Re: [avr-gcc-list] How to get the GCC to use the swap instruction?

From: Bruce D. Lightner
Subject: Re: [avr-gcc-list] How to get the GCC to use the swap instruction?
Date: Fri, 01 Nov 2002 11:17:48 -0800

Tehn Yit Chin,

> I want to swap the nibbles in a byte, but I can't seem to get the GCC to use
> the SWAP instruction without using assembler? Does anybody know how to do
> it?

I've been recently playing with a swap() macro for avr-gcc in order to get
the "last few bytes" from the compiler, using it to program an 8-pin
ATtiny15L part.  (That AVR part holds only 512 AVR instructions and has
zero SRAM.  Careful coding is essential!  I am truely amazed by the
quality of the register allocation logic in avr-gcc.)

Jerry Quinn's (address@hidden) "untried" suggestion to Mr. Chin for
a swap macro...

  #define swap_nibble(a) { asm("swap %0": "=r" (a) : "r" (a)); }

...may not do exactly what you want.  

Below are a couple of comments, which are in fact quesitons about
constructing avr-gcc macros of this sort.

Comment #1:

In Harald Kipp's (address@hidden) wonderful document, the "GCC-AVR
Inline Assembler Cookbook"...


...he makes the following comment regarding the his "swap" macro

   asm volatile("swap %0" : "=r" (value) : "0" (value));

Harald says: "This statement will swap the nibbles of an 8-bit variable
named value. Constraint "0" tells the compiler,
to use the same input register as for the first operand."  

Does this mean that Jerry's swap macro above MUST use the "0" in place of
the "input" operand, or does the fact that both the "input" and "output"
operands have the same name (i.e., "a") yield the same result?

Comment #2:

I found that the above swap() macros, this one constructed from Harald's

   #define swap(a) { asm volatile("swap %0" : "=r" (a) : "0" (a)); }

...is only useful when the "input/output" is an "lvalue", for obvious
reasons, if you think about that the compiler is being asked to do.  For

     unsigned char i;

     swap(i);       // no errors
     swap(i << 1);  // error! (invalid lvalue in assignment)

Therefore, here is what I have been using for my swap() macro...

#define swap(a) ({ \
        unsigned char ch; \
        asm volatile ( \
        "mov %0, %1" "\n\t" \
        "swap %0"\
        : "=r&" (ch) \
        : "r" ((uint8_t)(a)) \
        ); \
        ch; \

Note the use of the type cast of the input parameter to "uint8_t".  This
in fact makes a difference for 16-bit parameters.

Can anyone see how to improve on this?  This macro, as written, forces the
"input" and "output" registers to be different (i.e., because of the
"&").  This forces register copying when all you may want to do is modify
a variable "in place".

For example, here is the AVR code one gets using the above macro...

  94:avrprog.c     ****     n = swap(n);
 166            .LM14:
 167            .LBB3:
 168            /* #APP */
 169 0020 522F          mov r21, r18
 170 0022 5295          swap r21
 171            /* #NOAPP */
 172 0024 252F          mov r18,r21

Based on my understanding of the "rules" in the "Inline Assembler
Cookbook", I believe that the "&" is required.  Am I right?


After constructing this email, I also tried the following slightly
improved swap() macro...

#define swap(a) ({ \
        unsigned char ch; \
        asm volatile ( \
        "swap %0"\
        : "=r" (ch) \
        : "0" ((uint8_t)(a)) \
        ); \
        ch; \

Note the use of "0".  This seems to do "the right thing".  

One would expect this macro to be a tiny bit more efficient in certain
circumstances, and in fact it is...

  94:avrprog.c     **** n = swap(n);
 165            .LM14:
 166            .LBB3:
 167            /* #APP */
 168 001e 2295          swap r18
 169            /* #NOAPP */

...as the above mixed listing shows.  Am I on the right track?

Best regards,


 Bruce D. Lightner
 Lightner Engineering
 La Jolla, California
 Email: address@hidden
 URL: http://www.lightner.net/lightner/bruce/
avr-gcc-list at http://avr1.org

reply via email to

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