[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-gcc-list] avr-gcc 3.4.3 confused about function pointers
From: |
Ned Konz |
Subject: |
Re: [avr-gcc-list] avr-gcc 3.4.3 confused about function pointers |
Date: |
Sun, 16 Apr 2006 16:01:44 -0700 |
On Apr 16, 2006, at 2:55 PM, John Regehr wrote:
Compiling like this:
avr-gcc -Wall -mmcu=atmega128 -Os foo.c
gives a program that icalls to a bad address.
On the other hand, compiling the same program with -O instead of -Os
results in correct code.
The problem occurs when the Z register is loaded with the address of
foo(). In the buggy (-Os) version, the literal address of foo() is
loaded, rather than the address shifted right by one bit position.
With -O the compiler gets it right.
I'd appreciate hearing about it if there's a patch for this or if
the bug is known to be fixed in later versions.
Under avr-gcc 4.1.0 both foo and stuff get optimized out (well, they
both end up empty):
32 .global foo
34 foo:
41 0000 0895 ret
43 /* function foo size 1 (0) */
45 .Lscope0:
49 .global stuff
51 stuff:
58 0002 0895 ret
60 /* function stuff size 1 (0) */
62 .Lscope1:
66 .global main
68 main:
73 0004 C0E0 ldi r28,lo8(__stack - 0)
74 0006 D0E0 ldi r29,hi8(__stack - 0)
75 0008 DEBF out __SP_H__,r29
76 000a CDBF out __SP_L__,r28
80 000c 0E94 0000 call stuff
83 0010 80E0 ldi r24,lo8(0)
84 0012 90E0 ldi r25,hi8(0)
86 0014 0C94 0000 jmp exit
88 /* function main size 10 (4) */
If you force foo to be called (for instance, passing a pointer to back
[0], after declaring back as volatile) then the compiler is clever
enough just to call foo(), rather than using a pointer.
You'll have to come up with a test program that's cleverer than that.
I did notice that for the expression (&foo + 1) it used a byte
increment, rather than a word increment (which seems wrong to me).
void
foo(volatile struct bar *b)
{
ca: fc 01 movw r30, r24
b->yyy = (void*)0;
cc: 11 82 std Z+1, r1 ; 0x01
ce: 10 82 st Z, r1
d0: 08 95 ret
000000d2 <stuff>:
}
void
stuff(void)
{
d2: cf 93 push r28
d4: df 93 push r29
d6: cd b7 in r28, 0x3d ; 61
d8: de b7 in r29, 0x3e ; 62
da: 28 97 sbiw r28, 0x08 ; 8
dc: 0f b6 in r0, 0x3f ; 63
de: f8 94 cli
e0: de bf out 0x3e, r29 ; 62
e2: 0f be out 0x3f, r0 ; 63
e4: cd bf out 0x3d, r28 ; 61
volatile struct bar back[2];
void (*p) (volatile struct bar *) = foo;
back[0].aaa = (void *) (&foo + 1);
e6: 8b ec ldi r24, 0xCB ; 203 <<<< questionable!
e8: 90 e0 ldi r25, 0x00 ; 0
ea: 9c 83 std Y+4, r25 ; 0x04
ec: 8b 83 std Y+3, r24 ; 0x03
int i;
for (i = 0; i < 6; i++)
{
back[0].aaa = back[0].yyy;
ee: 89 81 ldd r24, Y+1 ; 0x01
f0: 9a 81 ldd r25, Y+2 ; 0x02
f2: 9c 83 std Y+4, r25 ; 0x04
f4: 8b 83 std Y+3, r24 ; 0x03
.. etc ..
}
(*p) (&back[0]);
11e: ce 01 movw r24, r28
120: 01 96 adiw r24, 0x01 ; 1
122: 0e 94 65 00 call 0xca <foo>
126: 28 96 adiw r28, 0x08 ; 8
128: 0f b6 in r0, 0x3f ; 63
12a: f8 94 cli
12c: de bf out 0x3e, r29 ; 62
12e: 0f be out 0x3f, r0 ; 63
130: cd bf out 0x3d, r28 ; 61
132: df 91 pop r29
134: cf 91 pop r28
136: 08 95 ret
--
Ned Konz
address@hidden