Endian problem when accessing internel regs on 8347
Bruce_Leonard at selinc.com
Bruce_Leonard at selinc.com
Mon Jan 21 18:21:48 EST 2008
> >>> __asm__ __volatile__("lwz%U1%X1 %0,%1; twi 0,%0,0; isync" : "=r"
(ret)
> > :
> >>> "m" (*addr));
> >> They allow the compiler to use update and/or index mode for the
memory
> >> operand.
> >
> > Well that makes sense, U for update and X for index, but I'm not sure
> > they're applicable to this particular instruction and I'm not sure
that
> > the memory operand makes sense for PowerPC.
>
> Why not?
Okay, after much digging and experimenting, I'll agree that the memory
operand makes sense. When I first said that I was thinking of direct
manipulation of memory, which the PPC doesn't support. (Don't ask, my
brain sometimes goes off into la-la land without me :-> ) Also, update
mode is applicable and makes sense. But I do still have a problem with
the index mode, though it could be compiler magic. Here's why: the index
mode of the 'lwz' instruction requires three operands, i.e., 'lwzx
rD,rA,rB', and there's only place holders for two operands. Is the
compiler smart enough to add the third operand for the index mode? If so,
what does it put for the third operand?
Another question is how does the compiler know which mode to pick? And
what is the significance of the trailing number? Some places in the code
have %U1%X1 and others have %U2%X2? I've found documentation for the #
and ## tokens, but I can't find anything for the %U or %X tokens.
Now this has all been very interesting to learn but doesn't solve my
underlying problem which I've finally drilled down to. At first I thought
in_be32() might be broken because I wasn't getting back the value I knew
to be in the internal register. I knew I had the address and the mapping
to kernel space correct because I could use in_le32 and get the right
value though it was byte swapped. The value in the register was
0xFFFFFFE7 but what I was getting from in_be32 was 0xFFFFFFFF. Then I
started playing and here's what I found:
Register value in_be32 value
0x12345678 0x1234567
0xff345678 0xff345678
0xffff5678 0xffff5678
0xfffff678 0xfffff678
0xfffffe78 0xffffffff
0xffffff78 0xffffffff
This isn't an exhastive list but I tried about twenty values and pretty
much what I found was that if bits 0 through 22 are set to 1 then in_be32
reads 0xffffffff. I've also tried it at a variety of addresses and the
behaviour is the same. in_le32 works fine as does in_be16. I've got no
ideas as to what may be wrong. I don't want to just arbitrarily point to
that %U1%X1 parameter list, but I get compiler errors if I try to remove
them so I can't prove or disprove it and I can't find any documentation on
it I can't even form a theroy. Has anyone ever seen anything like this?
Can't anyone suggest anything I can try?
More information about the Linuxppc-embedded
mailing list