This is the mail archive of the crossgcc@sources.redhat.com mailing list for the crossgcc project.

See the CrossGCC FAQ for lots more information.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: GCC ARM: Memory not written


On Tue, Feb 08, 2005 at 09:54:31PM +0100, Thomas Kolejka wrote:
> Hello,
> 
> I'm working on an Arm processor and tried to make the following program run:
> 
> 
> typedef unsigned char U1;
> typedef U1 * P_U1;
> 
> 
> U1 data[100];
> 
> int main()
> {
>   int i;
> 
>   U1 *p = 0x87654321;
> 
>   P_U1 *p2;
> 
>   printf("p: -> %p\n", (void *)p);
> 
>   for (i = 0; i < 10; i++)
>   {
> 	 p2 = (P_U1)&data[i];
> 	 //  ldr	r2, .L10+4
> 	 //  ldr	r3, [fp, #-16]	@  i
> 	 //  add	r3, r2, r3
> 	 //  str	r3, [fp, #-24]	@  p2
> 
> 
> 	 printf("p2: -> %p\n", (void *)p2);
> 
> 	 *p2 = p;
> 	 //   ldr	r2, [fp, #-24]	@  p2
> 	 //   ldr	r3, [fp, #-20]	@  p
> 	 //   str	r3, [r2, #0]
> 	 }
> 
>   for (i=0; i < 10; i++)
> 	 printf("0x%0x ", data[i]);
> 
>   printf("\n");
> }
> 
> 
> 
> The program should write 0x87654321 into every position of data[100] -
> therefore overwrite 3 bytes 
> of the last write. 
> On the PC (Pentium III) this works alright; on the ARM only every fourth
> value 
> is written to the memory: "str	r3, [r2, #0]" is executed (gdb, ddd: ni), but
> nothing happens. 
> 
> Including 'asm("str r3, [r2]");' into the code does not work, too.
> 
> I've tested a lot of options for gcc and arm-options, but nothing changed. 
> 
> This happens with gcc version 2.95.3 and 3.3.2.
> 
> 
> Thanks in advance for any help,
> 
> Thomas

It looks like you're doing unaligned word writes with the line   *p2 = p;

Some ARM cores, depending on the specific architecture, don't take kindly
to writing 32-bit quantities on non-0-mod-4 addresses.  Some will silently
accept the instruction and do the wrong thing, without throwing any kind
of processor exception.  In particular, I've personally observed ARM cores
do the following...

   assume little endian, intial memory condition:
   0x0000:  0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00

   now you execute *(unsigned long*)3 = 0x12345678;

   you'd expect to get:
   0x0000:  0x00 0x00 0x00 0x78 0x56 0x34 0x12 0x00

   but instead you get:
   0x0000:  0x56 0x34 0x12 0x78 0x00 0x00 0x00 0x00

   the general pattern being that for every byte written that's in a
   different word than the address given in the store instruction (e.g. 3
   in this case, so 3 is in the same word; 4, 5, 6 are in a different word),
   byte n-4 gets written with what byte n should have gotten, thus all bytes
   modified are in a single word.  The byte lane switching portion of the
   unaligned access works, but there's only a single word access made to
   memory, as the core can't split a word write across two word accesses
   to memory.  So everything ends up in the first word of the two that
   were meant to be spanned.  Did that make sense?


Bottom line is, unaligned word writes are not guaranteed to work in general.
Some machines happily take them; some machines throw an exception; some
machines just plain do the wrong thing with them.  It's architecture-
dependent.  The compiler makes it somewhat difficult to generate an unaligned
word write because it's not supported.  If you force the compiler to generate
one, then you're taking your chances with your target architecture, and if
it doesn't do what you had hoped, it's not the compiler's fault.


You mention it works in a PC.  Under what OS?  Windows generally allows it.
Linux generally gives an exception.  This is because the x86 architecture
does support unaligned word accesses, but it also has a bit in one of the
machine configuration registers to disallow them and give a processor
exception.  Windows runs with that bit off.  Linux runs with it on.  If it's
Windows you've been trying it under, give the exact same code a shot under
Linux.  I bet it cores with a SIGBUS.


                            ------Carl


------
Want more information?  See the CrossGCC FAQ, http://www.objsw.com/CrossGCC/
Want to unsubscribe? Send a note to crossgcc-unsubscribe@sources.redhat.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]