Possible bug using inline assembler?

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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 );

Resulting asm:

	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?

cheers...

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).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have to add the "earlyclobber" modifier (&) to the input operand:

            : "=&r" (var) : "b" (payload), "I" (first_byte_index) \

This modifier is "invented" exactly to prevent this effect, i.e. tells the compiler not to use for an "earlyclobbered" output operand the same registers than for inputs.

http://gcc.gnu.org/onlinedocs/gc...

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hmm.. I'm not really convinced that that modifier exists to prevent "exactly" what I'm seeing, because the compiler has every possibility to spot this issue on its own, and I would even go so far as to say, that the compiler *caused* the issue, not me.. But anyway, it seems to fix it, so thanks :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hooverphonique wrote:
Hmm.. I'm not really convinced that that modifier exists to prevent "exactly" what I'm seeing, because the compiler has every possibility to spot this issue on its own, and I would even go so far as to say, that the compiler *caused* the issue, not me.. But anyway, it seems to fix it, so thanks :)
The compiler doesn't try to understand the assembly.

Iluvatar is the better part of Valar.