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

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

[avr-gcc-list] (no subject)


From: Wouter van Gulik
Subject: [avr-gcc-list] (no subject)
Date: Sun, 27 Jan 2008 21:48:28 +0100

Compiling the following program ends up in 
"main.c:(.text+0x2): warning: internal error: out of range error"

================= main.c ================

//Dummy func
void foo(void) {}

//Table with address manipulation
void (* const pFuncTable[]) (void) = {
    foo + 0,
    foo + 1, //need odd offset
};      
        
int main(int argc, char* argv[]) {
    //Call table
    pFuncTable[1]();
    
    return 1;
}       

Looking into the generated assembler gives:

pFuncTable:
        .word   gs(foo)
        .word   foo+1

Which is wrong. It should have been gs(foo + 1) or perhaps gs(foo)+1

But the true wrong thing is that gcc out smarts the table (since it's const)
and directly does: "call foo+1". This gives the internal error.
Even worse is that the compiler does not stop!! IMHO it should stop here,
instead it generates this final assembly: 
000000a6 <main>:
  a6:   0e 94 00 00     call    0       ; 0x0 <__vectors>
  aa:   81 e0           ldi     r24, 0x01       ; 1
  ac:   90 e0           ldi     r25, 0x00       ; 0
  ae:   08 95           ret


Before I post a note to the existing bug report (it's probably related with
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27192 ) I want to know what foo
+ 1 is supposed to do. GCC seems to mix up byte address (for lpm) and word
addresses (for ijmp/jmp//icall/call).
Is it supposed to increment the byte address or the word address?
I guess byte addresses are what it's supposed to be, since calling foo + 2
ends up in calling foo + 2 bytes. Leaving foo + 1 as illegal address.

And I just found another nasty error:

//Dummy func
void foo(void) {}

//Table with address manipulation
void (* const pFuncTable[]) (void) = {
    foo + 4, //need odd offset
};      
        
int main(int argc, char* argv[]) {
    //Call table
    pFuncTable[0]();
    
    return 1;
}       

This will generate a correct call (4 bytes after foo) but the value in the
table is not left shifted! Meaning that a call via the table will generate a
call to the wrong address, while the original call is ok.

Wouter





reply via email to

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