Newbie: arm-elf-gcc generated asm question

Started by Ken Barlow May 28, 2004
Hi,

I have started evaluating the GNUARM tools for a LPC210x target
(little-endian) and come across the following which is odd to me.

With ul defined as:
unsigned long *ul;

The function function1 returns a pointer to void.  For the following line,
ul = ( unsigned long * ) function1();

GCC uses R0 to return the function1() result which is 0x40000625, the
instruction:
STR R0, [R4,#0x0004]

stores the result to RAM.  Inspecting the RAM location [R4, #0x0004] shows
the value stored correctly in little endian form as 25 06 00 40.


So far so good...


Now I have another function that takes ul as an argument.  GCC uses R0 to
pass the argument to the function.  The code generated to load R0 is:
LDR R0, [R2,#0004]
where R2 in this case has the same value as R4 in the previous case - but
the value loaded into R0 is 0x25400006 - which is all the correct digits but
in the wrong order!

I am using a simulator to run the code - both Insight and the Keil
simulators behave exactly the same, so I am assuming I have done something
stupid in the setup of the mpu.

Any ideas what???

Thanks.






On Fri, 28 May 2004 10:33:56 +0100, Ken Barlow 
<ken_barlow@hotmail.com.NOSPAM> wrote:

> The code generated to load R0 is: LDR R0, [R2,#0004] > where R2 in this case has the same value as R4 in the previous case - but > the value loaded into R0 is 0x25400006 - which is all the correct digits > but in the wrong order!
Check that R2 is word aligned. If it is not, the loaded value will be rotated. Your address seems to have bit 0 set. If this is the case -- the compiler is doing something really nasty. HTH, Vadim
> > The code generated to load R0 is: LDR R0, [R2,#0004] > > where R2 in this case has the same value as R4 in the previous case -
but
> > the value loaded into R0 is 0x25400006 - which is all the correct digits > > but in the wrong order! > > Check that R2 is word aligned. If it is not, the loaded value will be > rotated. > > Your address seems to have bit 0 set. If this is the case -- the compiler > is doing something really nasty. > > HTH, > Vadim
Thanks for the advice - the variable being assigned is actually part of a structure (I simplified the example). Ensuring the variable started on a 4byte boundary fixed the problem. Pointer alignment troubles! Is there a way of forcing all alignment onto four byte boundaries? I've looked through the GCC and LD docs and can find switches for other targets, but not the ARM. Thanks again!
On Fri, 28 May 2004 16:28:13 +0100, Ken Barlow 
<ken_barlow@hotmail.com.NOSPAM> wrote:

> Is there a way of forcing all alignment onto four byte boundaries? I've > looked through the GCC and LD docs and can find switches for other > targets, but not the ARM.
Compiler does this automatically. If you, say, have the structure struct { uint8_t one; uint32_t two; } foo; then foo.two will always be word aligned. What are your trying to do? If you would post a snippet of your data structure it might be easier to help. Vadim
Ken Barlow wrote:
>Thanks for the advice - the variable being assigned is actually part of a >structure (I simplified the example). Ensuring the variable started on a >4byte boundary fixed the problem. Pointer alignment troubles! > >Is there a way of forcing all alignment onto four byte boundaries? I've >looked through the GCC and LD docs and can find switches for other targets, >but not the ARM.
Are you using the compiler switch '-fpack-struct' ? If so you must manually ensure the correct padding is used. Andy
On 2004-05-28, Ken Barlow <ken_barlow@hotmail.com.NOSPAM> wrote:

>>> The code generated to load R0 is: LDR R0, [R2,#0004] where R2 >>> in this case has the same value as R4 in the previous case - >>> but the value loaded into R0 is 0x25400006 - which is all the >>> correct digits but in the wrong order! >> >> Check that R2 is word aligned. If it is not, the loaded value will be >> rotated. >> >> Your address seems to have bit 0 set. If this is the case -- the compiler >> is doing something really nasty. > > Thanks for the advice - the variable being assigned is > actually part of a structure (I simplified the example). > Ensuring the variable started on a 4byte boundary fixed the > problem. Pointer alignment troubles! > > Is there a way of forcing all alignment onto four byte > boundaries? I've looked through the GCC and LD docs and can > find switches for other targets, but not the ARM.
The compiler will properly align all variables and structure fields unless you tell it to do otherwise. IOW, you had to write code that does something bad to get such an alignment problem (most likely typecasting a pointer or using a packed struct). You're probably better off not doing "bad" things rather than forcing the alignment of everything to a word boundary. If you explain what it is you're actually trying to do, somebody can show you how to do it the "good" way. -- Grant Edwards grante Yow! ... I'm IMAGINING a at sensuous GIRAFFE, CAVORTING visi.com in the BACK ROOMof a KOSHER DELI --
> > Is there a way of forcing all alignment onto four byte boundaries? I've > > looked through the GCC and LD docs and can find switches for other > > targets, but not the ARM. > > Compiler does this automatically. If you, say, have the structure > > struct { > uint8_t one; > uint32_t two; > } foo; > > then foo.two will always be word aligned. > > What are your trying to do? If you would post a snippet of your data > structure it might be easier to help. >
Hi again, The structure is like this: struct { uint8 aByte; uint8 aByteArray[ 64 ]; } foo; Hence my problem - the aByteArray is used as a generic buffer that can hold anything. I was putting 32bit words into it, and as a byte array there is no way of the compiler knowing that I wanted it 32bit aligned - a bit silly now I come to look at it but sometimes it takes somebody else to point out you are doing something daft ;-) In answer to the other question: I'm not using -fpack-struct. Thanks again.
In article <cjKtc.4668$Dm2.2182@front-1.news.blueyonder.co.uk>, Ken Barlow wrote:

> struct { > uint8 aByte; > uint8 aByteArray[ 64 ]; > } foo; > > Hence my problem - the aByteArray is used as a generic buffer that can hold > anything. I was putting 32bit words into it, and as a byte array there is > no way of the compiler knowing that I wanted it 32bit aligned - a bit silly > now I come to look at it but sometimes it takes somebody else to point out > you are doing something daft ;-)
You probably need to use memcpy() to copy data to/from your buffer. You could force alignment of the beginning of the array, but things will still fall apart if you use type-punned pointers to put multiple things of differing sizes into the buffer.
> In answer to the other question: I'm not using -fpack-struct.
-- Grant Edwards grante Yow! Nice decor! at visi.com
On Fri, 28 May 2004 18:03:02 +0100, Ken Barlow 
<ken_barlow@hotmail.com.NOSPAM> wrote:

> The structure is like this: > > struct { > uint8 aByte; > uint8 aByteArray[ 64 ]; > } foo;
Fine, this explains why the value you read is rotated right by one byte. You might probably need to do something like struct { uint8 aByte; union { uint32 aWordArray[16]; uint8 aByteArray[64]; } u; } foo; In this case foo.u.aWordArray[x] is guaranteed to be word aligned, as the whole union will be. HTH, Vadim
On Fri, 28 May 2004 18:03:02 +0100, "Ken Barlow"
<ken_barlow@hotmail.com.NOSPAM> wrote:

>Hi again, > >The structure is like this: > >struct { > uint8 aByte; > uint8 aByteArray[ 64 ]; >} foo; > >Hence my problem - the aByteArray is used as a generic buffer that can hold >anything. I was putting 32bit words into it, and as a byte array there is >no way of the compiler knowing that I wanted it 32bit aligned - a bit silly >now I come to look at it but sometimes it takes somebody else to point out >you are doing something daft ;-)
There seems to be something a bit kludgy about what I'm about to suggest (I'm not sure why, except there's this Bogus_Variable defined but never used), but could you use a union of a 4-byte 'bogus' unused varuable with the aByteArray, to make the compiler align it? Like this: struct { uint8 aByte; union { uint32 Bogus_Variable; uint8 aByteArray[ 64 ]; } } foo; There seems like there ought to be another way to do it, perhaps with a compiler-specific #pragma, but this should work with any compiler.
>In answer to the other question: I'm not using -fpack-struct. > >Thanks again.
----- http://mindspring.com/~benbradley