Omit frame pointer bug in m68k gcc 3.3.1
David Brown
david@westcontrol.com
Fri Sep 26 11:48:00 GMT 2003
I've found a bug in the gcc build on
http://www.davehylands.com/avi/index.htm that I've been trying. This isn't
just an inconvenience thing, but a matter of incorrectly generated code when
the -fomit-frame-pointer flag is on. I normally have that flag on, since
gdb does not need the frame pointer for debugging, and without it the
compiler saves a few instructions and cycles, and has another free register
to use. But with it enabled, the compiler produces incorrect code (example
below) - it reads function parameters from the wrong place, and it uses
incorrect addresses for local variables. I notice (from
http://www.davehylands.com/avi/compile_instructions_for_gcc.htm ) that this
build has a patch called gcc-3.3.1-coldfire-frame.patch.txt (available from
Avi's site) - I don't know if this is a standard or commonly used patch, but
it seems to provide the "interrupt" attribute (which is essential for my
program - I am running bare-bones without an OS on one of our own cards, and
I much prefer the "interrupt" attribute to writing assembly wrappers). I
don't know if the patch is related to the problem or not.
An example of the problem is the function:
// *************************
extern void sendMessage(char *p);
void sendDec(unsigned long val) {
/* Convert a long int to decimal and send it. */
char s[12];
char *p = &s[11];
*p-- = 0;
if (val == 0) {
*p-- = '0';
} else {
while (val) {
*p-- = (val % 10) + '0';
val /= 10;
};
};
sendMessage((p+1));
}
// *************************
When compiled with gcc 2.95 and -fomit-frame-pointer, the listing starts:
93:utils.c **** void sendDec(unsigned long int val) {
446 .LM60:
68K GAS page 9
447 017c 514F subq.w #8,%sp
448 017e 514F subq.w #8,%sp
449 0180 48E7 3020 movm.l #0x3020,-(%sp)
450 0184 242F 0020 move.l 32(%sp),%d2
94:utils.c **** /* Convert a long int to decimal and send it. */
95:utils.c ****
96:utils.c **** char s[12];
452 .LM61:
453 .LBB11:
97:utils.c **** char *p = &s[11];
455 .LM62:
456 0188 41EF 0017 lea (23,%sp),%a0
98:utils.c ****
99:utils.c **** *p-- = 0;
458 .LM63:
459 018c 4210 clr.b (%a0)
460 018e 5388 subq.l #1,%a0
That code works fine. But if I compile it using the patched 3.3.1
and -fomit-frame-pointer, the listing starts:
93:utils.c **** void sendDec(dword val) {
308 .loc 1 93 0
309 0188 514F subq.w #8,%sp
310 018a 514F subq.w #8,%sp
311 .LCFI6:
312 018c 2F02 move.l %d2,-(%sp)
313 .LCFI7:
314 018e 242F 0014 move.l 20(%sp),%d2
94:utils.c **** /* Convert a long int to decimal and send it. */
95:utils.c ****
96:utils.c **** char s[12];
97:utils.c **** char *p = &s[11];
315 .loc 1 97 0
316 .LBB10:
317 0192 41EF 000B lea (11,%sp),%a0
98:utils.c ****
99:utils.c **** *p-- = 0;
318 .loc 1 99 0
319 0196 4210 clr.b (%a0)
320 0198 5388 subq.l #1,%a0
The parameter is being read from the wrong place on the stack, and the
pointer p is set incorrectly. If I don't have -fomit-frame-pointer, the
code is correct - even with -O3 and a few other optomisations turned on.
David Brown
System Developer
WestControl a.s
Norway
"Utvikling er kunsten av å vikle seg ut av det man har viklet seg inn i"
------
Want more information? See the CrossGCC FAQ, http://www.objsw.com/CrossGCC/
Want to unsubscribe? Send a note to crossgcc-unsubscribe@sources.redhat.com
More information about the crossgcc
mailing list