I have the following macro to extract an uint16_t from a big-endian byte array at the specified index:
#define vPayloadParamGet_uint16( payload, var, first_byte_index ) \ ( \ "ldd *B0, *a1+(*2+0) " \ "ldd *A0, *a1+(*2+1) " \ : "=r" (var) : "b" (payload), "I" (first_byte_index) \ )
Please replace * with percent sign, as the bbs wouldn't allow me to post with percent signs in there!!!
Now, in a case I'm investigating, the compiler steps all over itself by picking the same register pair for payload and var.
C code using the macro (in->Payload is a volatile uint8_t*):
uint16_t limit; vPayloadParamGet_uint16( in->Payload, limit, 1 ); vPressureLimitSet( limit );
uint16_t limit; vPayloadParamGet_uint16( in->Payload, limit, 1 ); c2e: 05 5b subi r16, 0xB5 ; 181 c30: 1f 4f sbci r17, 0xFF ; 255 c32: d8 01 movw r26, r16 c34: ed 91 ld r30, X+ c36: fc 91 ld r31, X c38: 0b 54 subi r16, 0x4B ; 75 c3a: 10 40 sbci r17, 0x00 ; 0 c3c: f1 81 ldd r31, Z+1 ; 0x01 c3e: e2 81 ldd r30, Z+2 ; 0x02 vPressureLimitSet( limit ); c40: cf 01 movw r24, r30 c42: 0d d7 rcall .+3610 ; 0x1a5e
The two last ldd's are from the inline asm macro, where the compiler overwrites its own pointer.
I'm using avr-gcc 4.3.3.
Is this a bug or am I doing something wrong?
Edit: I should probably mention that this macro is used in other places as well, where it works fine (i.e. the compiler doesn't pick the same reg pair for the pointer and output).