Reported by geckosenator on avrfreaks.net

Code:

int sat; 

static volatile long data[3]; 
static volatile int datacount[3]; 

static volatile int chan; 
static volatile long val; 

int __attribute__((always_inline)) transfer(int data) 
{ 
   return (*(int *)((0x00))); 
} 

int init_status; 

long read_scale(void) 
{ 
   long val; 
   if(init_status) 
      val |= (long)transfer(0) << 16; 
   val |= (long)transfer(0) << 8; 
   return val; 
} 

void get_mode(int *mode, int *psw) 
{ 
    int val = transfer(0); 
    *psw = val & 0x10 ? 1 : 0; 
} 

long __attribute__((always_inline)) read_data(void) 
{ 
   long val; 

   val <<= 8; 
   if(init_status) 
      val |= transfer(0); 

   return val - 0x80; 
} 

void function1() 
{ 
    long data2 = read_data(); 
    sat = (data2 > 1) || (data2 < -100); 
    val += data2; 
    data[chan] += val; 
    datacount[chan] ++; 
} 

void function2(long *data) 
{ 
    int i, j; 
    data[i] += i + j; 
} 




Compile with: 

Code:

avr-gcc -std=gnu99 -fgnu89-inline -Os -mmcu=at90usb1287 -c testcase.c -o
testcase.S -S 



Then look in testcase.S for: 

Code:

.L16: 
   ldi r16,lo8(-128) 
   mov r14,r16 
   ldi r16,hi8(-128) 
   mov r15,r16 
   ldi r16,hlo8(-128) 
   mov r16,r16    <-----  bad, this does nothing! 
   ldi r16,hhi8(-128) <-- nice, we just clobbered r16 
   mov r17,r16 
   add r14,r18 
   adc r15,r19 
   adc r16,r20 
   adc r17,r21 
   sts (sat)+1,__zero_reg__ 



It looks like the compiler got confused and tried to use r16 in two different
ways at the same time. 


The bug occurs in peephole optmisation. Here avr-gcc looks for a spare register
R16-R31 that it can use to load a constant value into operands which are
located in lower register (R2-R15). 

The test for "spare" occurred before instruction. So if the instruction
happened to use that register (because it was spare), bad things
happen.Typically this will happen with long - or long long registers.


-- 
           Summary: [AVR] avr-gcc generating incorrect assembly for
                    expression with the long constant operands
           Product: gcc
           Version: 4.2.2
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: aesok at gcc dot gnu dot org
GCC target triplet: avr-*-*


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37466

Reply via email to