I'm using arm-elf-gcc compiler, build for cygwin environment (gnuarm.org).
Here is example, which shows wrong results:
//---------------------------------------------------------------------------
#include <string.h>
#define FPGA_BASE 0x81000000
static inline void fpga_write( unsigned short address, unsigned short data )
{
*((volatile unsigned short*)(FPGA_BASE+address)) = data;
asm volatile( "nop" ); /* Slow down IO */
}
int f()
{
unsigned int counter;
unsigned short* buf = (unsigned short*)((void*)&counter);
memcpy( buf, "test", 4 );
counter++;
fpga_write( 0x6A, buf[0] );
fpga_write( 0x6A, buf[1] );
return 0;
}
//---------------------------------------------------------------------------
I run gcc with following options:
arm-elf-gcc -Wa,-adhls=test.lst -fomit-frame-pointer -Os -Wall -g -c
-march=armv4t -mtune=arm7tdmi -msoft-float -pipe test.c
Gcc produces following listing for my code:
str lr,[sp,#-4]!
sub sp,sp,#4
mov r0,sp
ldr r1,.L3
mov r2,#4
bl memcpy
ldr r3,[sp,#0]
ldrh r1,[sp,#0] ; source of problem. This word is extracted from memory
add r3,r3,#1 ; before actual increment. This is wrong.
mov r2,#-2130706432
str r3,[sp,#0] ; Saving incremented value. But least significant word
strh r1,[r2,#106] ; will not be incremented. :(
nop
ldrh r3,[sp,#2] ; All is right here.
strh r3,[r2,#106]
nop
mov r0,#0
add sp,sp,#4
ldmfd sp!,{pc}
Disabling optimisations solves this problem. But in this case binary code will
be noticeably bigger.
--
Summary: Wrong compilation results with -Os option specified
Product: gcc
Version: 4.1.0
Status: UNCONFIRMED
Severity: major
Priority: P3
Component: c
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: dednev at pisem dot net
GCC host triplet: i686-cygwin
GCC target triplet: arm-elf
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31421