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

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

Re: [avr-gcc-list] Time-efficient read of high byte in two-bytevariable


From: Wallace White
Subject: Re: [avr-gcc-list] Time-efficient read of high byte in two-bytevariable
Date: Fri, 09 May 2003 08:24:18 -0700
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.3.1) Gecko/20030425

David Brown wrote:
You are on the right track with unions, but I think it could be a little
neater.
First off, if you want to make a type that combines a 16-bit and two 8-bit
data, you can do it a bit neater with anonymous unions:

typedef union {
    uint16_t w;
    struct {
        unsigned char lo, hi;
    };
} combo;

It is best to avoid making your normal variables of type "combo" - you'll
make a mess of the rest of your program just for the sake of a couple of
clock cycles (changing "encPosDetentsNow ++" into "encPosDetentsNow.w ++" is
not good).

I found the most efficient method is to use a typecast from int to a pair of
bytes (or a "combo").  However, as far as I know it is impossible to force
the compiler to do that directly - we can only force a convertion of pointer
types.  As long as you want to take the high or low byte of something that
is not a local variable in a register, the best arrangement seems to be:

typedef struct { unsigned char lo, hi; } bytePair;
#define LoByte(x) ((*(bytePair*) &(x)).lo)
#define HiByte(x) ((*(bytePair*) &(x)).hi)

signed int encPosDetentsNow;
UDR = HiByte(encPosDetentsNow);

Ah, that's perfect for what I'm doing--using a global variable that, in this one place, needs to have its high byte read. (And indeed, it compiles into the pair of LDS & OUT instructions I was hoping for.)

This produces optimal code under all optomisations.  But it forces the
compiler to generate addressable objects, so code like:

void test(void) {
    int encPosDetentsNow = 0x123;
    UDR = HiByte(encPosDetentsNow);
}

is going to be awful - encPosDetentsNow gets put on the stack.  Of course,
if gcc knew that registers are also directly addressable on the AVR, then
that would not be a problem.

Good point. Thanks for the warning.

So for local variables, the best code is using a local "combo" variable to
do the convertion.  If you want to wrap that in an inline function, remember
to use "static inline" to avoid an extra copy of the function being
generated - "static inline" can generally be used in header files just like
#define macros.  Also, don't worry about signed or unsigned integers - as
long as you are not using comparisons, shifts, multiplies or divides, you
can freely mix them.

Right. Thanks very much, David.

- Wallace



reply via email to

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