On 2008-02-14, Peter Jansen <[email protected]> wrote:
>> I'm afraid you've lost me completely. I thought the OP was
>> complaining about mps430-gcc not generating correct code for
>> accessing misaligned fields in packed structs.
>
> Where is the test case?
Excellent question. I tried to wade through the OP's code, but
didn't make it all the way through. I'm still not 100% sure
what he thought was wrong. That's why I asked a few posts back
if he was complaining that msp43-gcc didn't generate correct
code when accessing a misaligned field in a packed struct. At
least that's what I meant to ask, because it _does_ work
correctly on other targets (e.g. ARM, SPARC).
> there are many ways to generate misaligned access, an example
> (with Makefile or command line arguments) that replicates the
> problem would make it easier to find. I have seen one case and
> not been able to replicate it all the time, I think it was
> something to do with passing pointers to structures to
> functions.
De-referencing a pointer to a field in a packed struct is an
excellent way to shoot yourself in the foot -- I've done that a
couple of times. However, that's not supposed to work. Is
_that_ what the OP was complaining abuot? It would be cool if
there was some sort of "pointer to packed <foo>" type that
would generate alignment-neutral code, but that's not a feature
that gcc has.
>> I wasn't aware we were discussing type casting...
>
> Ok I thought that you were trying to use your packed structure
> to get an array of bytes to send/receive over a communications
> channel. This is a type conversion between a structure and an
> array of bytes.
Right. Using a packed struct to get things aligned in memory
the way you want works fine. Accessing the structure as an
array of bytes works fine. On _other_targets_, accessing
fields within the packed stuct works fine. With msp430-gcc it
doesn't work.
Here's an example:
struct foo
{
char c;
unsigned u;
} __attribute__((packed));
struct foo s;
unsigned bar(void)
{
return s.u;
}
On the MSP430, you get code like this:
GAS LISTING /tmp/ccfoE3n2.s page 1
9:testit.c **** unsigned bar(void)
10:testit.c **** {
51 .LM1:
52 /* prologue: frame size = 0 */
53 .L__FrameSize_bar=0x0
54 .L__FrameOffset_bar=0x0
55 /* prologue end (size=0) */
11:testit.c **** return s.u;
12:testit.c **** }
57 .LM2:
58 0000 1F42 0000 mov &s+1, r15
59 0004 3041 ret
That's wrong. The "mov" instruction at line 58 is a word
access to an odd address. Apparently this is a known bug, but
it isn't clearly documented.
If you compile the same code for ARM, you get this:
unsigned bar(void)
{
return s.u;
0: e59f2020 ldr r2, [pc, #32] ; 28 <bar+0x28>
4: e5d23002 ldrb r3, [r2, #2]
8: e5d21001 ldrb r1, [r2, #1]
c: e5d2c003 ldrb ip, [r2, #3]
10: e1a03803 mov r3, r3, lsl #16
14: e1833c01 orr r3, r3, r1, lsl #24
18: e5d20004 ldrb r0, [r2, #4]
1c: e183340c orr r3, r3, ip, lsl #8
20: e1800003 orr r0, r0, r3
}
24: e1a0f00e mov pc, lr
As you can see, the ARM backend generates byte-accesses and
assembles the return value from the individually accessed bytes
as it should.
--
Grant Edwards grante Yow! Am I elected yet?
at
visi.com