avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] gcc builds wrong code?


From: Theodore A. Roth
Subject: Re: [avr-gcc-list] gcc builds wrong code?
Date: Mon, 26 Jul 2004 08:43:48 -0700 (PDT)

On Sun, 25 Jul 2004, Theodore A. Roth wrote:

> On Sun, 25 Jul 2004, Klaus Rudolph wrote:
>
> > Hi all,
> >
> > I wrote the following testcode and found that if a table of pointers to
> > functions
> > recides in flash "attribute progmem" the code is not correct.
> >
> > Is the compiler doing the wrong or am I the problem :-)
> >
> > Compiler Version:
> > avr-gcc (GCC) 3.4.0
> >
> > Build my code with:
> > avr-gcc -O2 -g -mmcu=at90s8515 test.c -c
> > avr-gcc -O2 -g -mmcu=at90s8515 test.o -o go
> >
> > The code generation is wrong if version 1 is enabled, with version 2 the
> > code is
> > correct.
> >
> > Thanks
> >     Klaus
> >
> > ///////////////////////////////// test.c /////////////////////////////
> >
> >
> > #ifdef __AVR__
> > #include <avr/io.h>
> > #endif
> >
> > int f2(int a) {
> >     return a+1;
> > }
> >
> > int f3(int a) {
> >     return a*2;
> > }
> >
> > int f4(int a) {
> >     return a*2+1;
> > }
> >
> >
> >
> > volatile int all=0;
> >
> > typedef int(*fp_t)(int) ;
> >
> > // Version 1 fail
> > const fp_t __attribute__ ((progmem)) fp[]={f2,f3,f4,0} ;
> > //Version 2 ok
> > //const fp_t fp[]={f2,f3,f4,0} ;
> >
> >
> > int main() {
> >     int index=1;
> >     int tmp=1;
> >
> >     while (fp[index]) {
> >         tmp+=(fp[index++])(tmp);
> >     }
> >
> >     all=tmp;
> >
> >     return 0;
> > }
>
> I seem to recall there being a rather long discussion about exactly this
> issue a week or two ago. No one every posted a tested, working example.
>
> Attached is a tested working example. I've tried to reduce it down to
> the bare minimum example. The variable "func" in the inner loop is not
> needed, I only did that to force the compiler to not use registers so
> as to make it easier to debug with gdb using 'display func'.
>
> Tested on a mega128 with a stk500/501. Compliled with these commands:
>
>   $ avr-gcc -g -Os -Wall -mmcu=atmega128 -c -o f_ptr_pgm.o f_ptr_pgm.c
>   $ avr-gcc -g -Os -Wall -mmcu=atmega128 -Wl,-Map,f_ptr_pgm.map  -o 
> f_ptr_pgm.elf f_ptr_pgm.o
>
> The part that may or may not be a bug in gcc is the 'fp += 2;' statement
> to increment the fp variable. You would think that 'fp++;' would do the
> right thing, but gcc seems to want to convert the byte address to a word
> address and only increment by one instead of the expected 2.

The bug was in my example. :-\ I had declared fp to be this:

  func_t fp = (func_t) func_list;

when it should be this:

  func_t *fp = (func_t *) func_list;

func_list is declared as this:

  typedef void (*func_t) (void);
  func_t func_list [] PROGMEM = { f0, f1, f2, f3, f4, f5, f6, f7, NULL };

Once I made that change, the 'fp++;' statement worked like I expected.

The generated asm for the loop looks like this:

    while (1)
    {
        func_t func = (func_t) pgm_read_word (fp);
 18a:   fe 01           movw    r30, r28
 18c:   85 91           lpm     r24, Z+
 18e:   94 91           lpm     r25, Z

        if (func == NULL)
 190:   00 97           sbiw    r24, 0x00       ; 0
 192:   31 f0           breq    .+12            ; 0x1a0
            break;

        func ();
 194:   fc 01           movw    r30, r24
 196:   09 95           icall

        delay ();
 198:   0e 94 6e 00     call    0xdc

        fp++;
 19c:   22 96           adiw    r28, 0x02       ; 2
 19e:   f5 cf           rjmp    .-22            ; 0x18a
    }

I've attached the fixed example for anyone interested in seeing the
whole working example.

Klaus, were you able to get your test case working?

---
Ted Roth
PGP Key ID: 0x18F846E9
Jabber ID: address@hidden

Attachment: f_ptr_pgm.c
Description: Text document


reply via email to

[Prev in Thread] Current Thread [Next in Thread]