http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49807
--- Comment #2 from Eric Weddington <eric.weddington at atmel dot com> 2011-07-21 20:12:58 UTC --- (In reply to comment #0) > This C source: > > #define SPDR (*((char volatile*) 0x2c)) Hi Johann, That's not quite correct. In avr-libc the header file sfr_defs.h will define a register as this: #define SPDR (*((volatile char *) 0x2c)) It's a pointer to a volatile char, not a volatile pointer to a char. > Changing the source like > > #define SPDR0 (*((char*) 0x2c)) > #define SPDR1 (*((char*) 0x2d)) > #define SPDR2 (*((char*) 0x2e)) > #define SPDR3 (*((char*) 0x2f)) > > void read_adc (long big) > { > SPDR0 = big >> 24; > SPDR1 = big >> 16; > SPDR2 = big >> 8; > SPDR3 = big; > } > > > and it compiles fine: Is your intent to change the address AND remove the volatile keyword? If you want to test if it's the volatile keyword that is the cause then you should only change that part: #define SPDR (*((char *) 0x2c)) void read_adc (long big) { SPDR = big >> 24; SPDR = big >> 16; SPDR = big >> 8; SPDR = big; } Overall, though, I think you're on the right track. Most users would like to be able to do the shift-and-assign pattern in C and have it compile to storing the individual byte without a shift in the assembly. Right now, the only way to do a workaround to achieve that result is through the use of a union with a struct and an integer type (like a long). If this issue can be fixed then I think that this has a chance to reduce a lot of code size problems.