[En-Nut-Discussion] Probable GCC Compiler error, was: Re: Problem with ARM floating point, again
Bob Wirka
bobwirka at yahoo.com
Thu Sep 19 22:05:57 CEST 2013
Hello,
Well, guess what? It's not a compiler issue; it's an alignment issue that's fixed by changing one line in the load script.
I'm using /arch/arm/ldscripts/at91sam7x512_rom.S, and the relevant part is:
.bss :
{
PROVIDE (__bss_start = .);
*(.bss)
*(COMMON)
. = ALIGN(8);<--- Here's the problem!!!
PROVIDE (__bss_end = .);
. += 0x400;
PROVIDE (__exp_stack = .);
. += 0x400;
PROVIDE (__stack = .);
PROVIDE (__heap_start = .);
} > ram
If the color doesn't show up, the ALIGN(8) was ALIGN(4), and, I believe, that's what the problem was. YOU NEED 8 BYTE STACK ALIGNMENT.
I couldn't figure out how my ARM9 Linux platform did not have an issue with printf, as the compiler I'm using for that project produces the same parameter stack for variadic functions as does the compiler for the ARM7. And, the va_arg() macro used the same arithmetic. Got to looking at the assembly language put out by the compiler and noticed that when a function is entered, it subtracts from the stack pointer a value that it believes will put the new stack pointer on an 8 byte boundary. You can check this by just adding dummy parameters on a printf() call and look at what the function does to the stack pointer on entry.
Then it occurred to me that if the va_list is aligned on an 8 byte boundary, the math used by va_arg() will always work. I thought the stack could be at any 4 byte boundary, but NO, the va_ functions appear to require an 8 byte aligned stack.
With this change, the build that did not work with printf() now does.
Hope this is real, and that it helps.
Best,
Bob Wirka
Realtime Control Works
Janesville, WI
PS: We still need Uwe's fix for long long integers...
________________________________
From: "bon at elektron.ikp.physik.tu-darmstadt.de" <bon at elektron.ikp.physik.tu-darmstadt.de>
To: Bob Wirka <bobwirka at yahoo.com>; Ethernut User Chat (English) <en-nut-discussion at egnite.de>
Sent: Sunday, September 15, 2013 4:02 PM
Subject: Probable GCC Compiler error, was: Re: [En-Nut-Discussion] Problem with ARM floating point, again
>>>>> "Bob" == Bob Wirka <bobwirka at yahoo.com> writes:
Bob> Hello, I'm having issues with printf("%f") on my AT91SAM7X512
Bob> platform (using ethernut-4.10.3). We're using the Codesourcery
Bob> compiler (gcc version 4.5.1 (Sourcery G++ Lite 2010.09-51)).
Sending a working, stripped down example may lower the barrier for others
to enter that problem...
Anyway, I tried on STM32F4 with Launchpad gcc and I can see the problem
too. Debugging and stepping a lot through the code, I am quite sure that it
is a compiler problem. I can get things to print right with substituting
_double = va_arg(ap, double);
by
uint32_t *l = (uint32_t *)&_double;
if (*(uint32_t*)&ap & 4) {
l[0]= va_arg(ap, uint32_t);
l[1]= va_arg(ap, uint32_t);
}
else {
l[0]= va_arg(ap, uint32_t);
l[0]= va_arg(ap, uint32_t);
l[1]= va_arg(ap, uint32_t);
}
When pushing the arguments on the stack, the arm calling convention tells to
put 64-bit units in R0/1 or R2/3 or stack aligned. I see this happening. It
seems as va_start doesn't care for that alignment. The 64-bit data has also
either its 32-bit words swapped in the va_list, or va_arg(ap, double) uses the
wrong order.
Can anybody confirm that this may not me caused by some strange compiler
option we give?
Bye
--
Uwe Bonnes bon at elektron.ikp.physik.tu-darmstadt.de
Institut fuer Kernphysik Schlossgartenstrasse 9 64289 Darmstadt
--------- Tel. 06151 162516 -------- Fax. 06151 164321 ----------
More information about the En-Nut-Discussion
mailing list