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

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

Re: [avr-gcc-list] (no subject)


From: Andrew Hutchinson
Subject: Re: [avr-gcc-list] (no subject)
Date: Sun, 27 Jan 2008 17:58:50 -0500
User-agent: Thunderbird 2.0.0.9 (Windows/20071031)

The problem report in part is explained by:

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.

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?

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
address@hidden
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


_______________________________________________
AVR-GCC-list mailing list
address@hidden
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list




reply via email to

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