Side effects in asm inline code (r1)

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

Hi, I have found a strange issue with avr-gcc (both 20071221 and 20080610). My asm code has side-effects, and I can't work out how to fix it.

Basically, I have this routine that writes either into data RAM or into Code RAM, depending on the address:

void HW_PatchPutWord(uint16_t *ptr, uint16_t data) {
    if (ptr < (uint16_t *)CODE_RAM_INIT) {
        *ptr = data;
    } else {
        __asm__ __volatile__(
                "movw r0, %A1"      "\n\t"
                "spm"               "\n\t" // store r1:r0 to *(ptr)
                : // no outputs
                : "z" (ptr),
                  "r" (data)
                : "r0", "r1", "memory"
           );
    }
}

This code gets called (inline) like this:

   uint16_t *ptr;
   ...
   HW_PatchPutWord(ptr, value);
   ptr++;
   ...

The generated code is the following:

    134e:	e0 91 c3 00 	lds	r30, 0x00C3
    1352:	f0 91 c4 00 	lds	r31, 0x00C4
    1356:	20 e1       	ldi	r18, 0x10	; 16
    1358:	e0 30       	cpi	r30, 0x00	; 0
    135a:	f2 07       	cpc	r31, r18
    135c:	18 f4       	brcc	.+6      	; 0x1364 <__vector_5+0x102>
    135e:	91 83       	std	Z+1, r25	; 0x01
    1360:	80 83       	st	Z, r24
    1362:	02 c0       	rjmp	.+4      	; 0x1368 <__vector_5+0x106>
    1364:	0c 01       	movw	r0, r24
    1366:	e8 95       	spm
    1368:	80 91 c3 00 	lds	r24, 0x00C3
    136c:	90 91 c4 00 	lds	r25, 0x00C4
    1370:	02 96       	adiw	r24, 0x02	; 2
    1372:	90 93 c4 00 	sts	0x00C4, r25
    1376:	80 93 c3 00 	sts	0x00C3, r24
    137a:	10 92 87 00 	sts	0x0087, r1
    137e:	04 c0       	rjmp	.+8      	; 0x1388 <__vector_5+0x126>

What puzzles me here is that at address 137a r1 is written to memory, although the asm instruction marks it as clobbered. I suspect that gcc thinks r1 has not been modified.

Am I doing something wrong in declaring the clobbered registers or might this be a compiler issue?

Cheers,
Thomas

pycrc -- a free CRC calculator and C source code generator

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

As a kind of work-around I use this code. It is very clunky, but it seems not to have side effects.

void HW_PatchPutWord(uint16_t *ptr, uint16_t data) {
    if (ptr < (uint16_t *)CODE_RAM_INIT) {
        *ptr = data;
    } else {
        __asm__ __volatile__(
                "movw r30, %A0"     "\n\t"
                "movw %A0, r0"      "\n\t"
                "movw r0, %A1"      "\n\t"
                "spm"               "\n\t"
                "movw r0, %A0"      "\n\t"
                : "+r" (ptr)
                : "r" (data)
                : "r0", "r1", "r30", "r31", "memory"
           );
    }
}

But I would like to understand what is wrong with the straightforward example.

Cheers,
Thomas

pycrc -- a free CRC calculator and C source code generator

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

Well, I think all that code is pretty much useless, as an SPM all by itself is not going to do anything anyway (so at least I'm not going to think too hard about that asm code, as it will now be changed- not that I would otherwise be of much help, though).

I would refer you to the boot.h header for the 'simple' way to do things (along with a good read of the datasheet self-programming section), and also point out that there is more to it than just writing. Also, depending if your avr has bootloader support (it appears you have an avr >4k, so unless you are using a 'tiny' avr, I suspect it does), you need to get the SPM command into the bootloader section.

(you may want to also change the phrase 'code RAM' to something like 'Flash', 'Flash Memory', or 'Program Space')

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

Thanks for the pointer to boot.h!
I see the code uses a "clr r1", and I have found in the avr-libc FAQ now the answer why:

Quote:
r1 - assumed to be always zero in any C code, may be used to remember something for a while within one piece of assembler code, but must then be cleared after use (clr r1)

Sorry for having complicated things by using "spm". I'm using a custom avr5 which actually has a few bytes of RAM program memory.

Cheers,
Thomas

pycrc -- a free CRC calculator and C source code generator

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

Custom AVR?

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

Ah, that one :) I was confused by the avr5, which seems to be some library version, or a Harman Kardon device, or alternator regulator :)

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

Surely he means AVR5 in the sense that it appears in the following:

C:\WinAVR-20080512\avr\lib>dir
 Volume in drive C has no label.
 Volume Serial Number is 8C00-2289

 Directory of C:\WinAVR-20080512\avr\lib

29/05/2008  15:33              .
29/05/2008  15:33              ..
29/05/2008  15:33              avr25
29/05/2008  15:33              avr3
29/05/2008  15:33              avr31
29/05/2008  15:33              avr35
29/05/2008  15:33              avr4
29/05/2008  15:33              avr5
29/05/2008  15:33              avr51
29/05/2008  15:33              avr6
29/05/2008  15:33              avrxmega5
29/05/2008  15:33              avrxmega7