[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-gcc-list] mass stupidity with registers and longs
From: |
David Gay |
Subject: |
Re: [avr-gcc-list] mass stupidity with registers and longs |
Date: |
Mon, 17 Jan 2005 09:26:22 -0800 |
User-agent: |
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040316 |
Curtis Maloney wrote:
I give up. I've been trying to shift 4 chars into an unsigned long, but
can't stop GCC 3.4.1 (what's shipped with the latest WinAVR) from sign
extending values, let alone producing sane code.
I've tried -Os, -O2, -O3, with and without -fnew-ra... the asm varies,
but is generaly crap.
now, if I have:
extern char a[4];
unsigned long ul;
ul = ( (unsigned)a[0] << 8 ) | (unsigned)a[1];
why would it be sign extending a[0] and a[1] when they're cast to
unsigneds?
And then why doesn't the code optimiser see to just mov rX, a[1]; mov
rX+1,a[0] ?
I tried casts on casts on casts... everything I could think of to get
better code, and it just did not improve.
Am I missing something,
Yes. As others have not given the actual explanation of why what you did
doesn't work, and why you actually did ask for those sign extensions:
- "char" is signed on most platforms (including avr-gcc)
- "unsigned" is a shorthand for "unsigned int", 16-bits with avr-gcc
- all expressions whose type is shorter than int are automatically
converted to ints
- therefore: a[0] is a char, so is converted to int. sign-extension
happens as char is signed. All this occurs before the cast...
- you then asked for a cast of '(int)a[0]' to (unsigned int). Not much
actually happens here (the cast could have some effects depending on how
the result is used, but not here).
Possible fixes (some already mentioned):
- declare a as "unsigned char a[4]". The conversion to int still
happens, but it doesn't involve sign extension (it's a "zero
extension"). The optimiser will typically get rid of the zero-extension.
- cast a[0] to (unsigned char). The sign extension will also occur, but
again, the optimiser will typically get rid of it (as the sign extended
byte is discarded by the cast to unsigned char).
- write 'a[0] & 0xff'. Effectively equivalent to the cast to 'unsigned
char'.
The first solution is definitely the cleanest...
David Gay