> Try casting the expression (foo +1) to a function pointer. This may > prove the point and correct the code in table - and elsewhere. > > Arithmetic with function pointers is probably not well standardized - if > at all. >
I agree. Although giving different results for the same statement is very nasty. I tried casting but I could not get any difference. When I tried to cast both operands to a function pointer I got a message that + is not a legal operation. Which seems ok and logical to me. Is there anyway we can make this warning an error (by default)? "main.c:14: warning: internal error: out of range error" So the user knows something is broken in his code. Thanks for the help Wouter > Andy > > > Wouter van Gulik wrote: > >> http://gcc.gnu.org/onlinedocs/gcc-4.2.2/gcc/Pointer-Arith.html#Pointer- > >> Arith > >> > >> The elements to which function (and void) pointer refer are assumed to > >> be size 1 byte. > >> > >> So if you really want to mess with these pointers, you must treat as > >> byte address. > >> > >> > > > > Exactly what I thought. If I do nasty things I should know what I am > doing. > > > > > >> That does not explain the other problems reported directly. However > >> given foo is a function pointer, what is the type of the expression > foo > >> + 1.? Perhaps gcc treats such an expression as void? > >> > >> > > > > Exactly the table is still messed up by gcc. > > Any idea how I/we can test this? I looked at the -da output but I could > not > > find anything related to the table. > > > > Is the avr backend involved in generating the correct function pointer > > addresses? Where is this gs() coming from? I searched through the as > > documentation but I could not find it. Is it from ld? > > > > Are there other platforms supported by gcc having the same strange non > equal > > data/program space? > > I know that the TI C54x series have a 8 bit program space, and a 16 bit > data > > space. sizeof(char) == sizeof(int), both 16-bit!, but instructions and > > function addresses are in bytes .... > > Maybe we can find some hints there? > > > > HTH > > > > Wouter > > > > > >> Andy > >> > >> > >> > >> Andrew Hutchinson wrote: > >> > >>> I think you highlight the problem for gcc. > >>> > >>> We are have to treat program memory as byte addressable to support > LPM. > >>> > >>> Direct, function calls only want word address to form the correct > >>> opcode. But we use byte address labels and assembler removes the > >>> redundant bit to form the correct opcode. > >>> > >>> Indirect (icall) functions show up the anomaly as these are formed > >>> outside of the assembler. > >>> > >>> Gcc is assuming that the item that a function pointer points to is > >>> size 1. When in fact it is size 2. > >>> > >>> This is similar as having pointer to some other object such as long: > >>> > >>> long *ptr; > >>> x = ptr+1; /* x will be assinged byte address potr+4 */ > >>> > >>> So if we can correct that mistake, I believe the problem is resolved. > >>> Now, I am not sure how gcc determines that size! So I will look. > >>> > >>> Andy > >>> > >>> > >>> > >>> Wouter van Gulik wrote: > >>> > >>>> 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 > >>>> > >>>> > >>>> > >>>> _______________________________________________ > >>>> AVR-GCC-list mailing list > >>>> AVR-GCC-list@nongnu.org > >>>> http://lists.nongnu.org/mailman/listinfo/avr-gcc-list > >>>> > >>>> > >>> _______________________________________________ > >>> AVR-GCC-list mailing list > >>> AVR-GCC-list@nongnu.org > >>> http://lists.nongnu.org/mailman/listinfo/avr-gcc-list > >>> > > > > > > _______________________________________________ AVR-GCC-list mailing list AVR-GCC-list@nongnu.org http://lists.nongnu.org/mailman/listinfo/avr-gcc-list