Our chip is 64 bits / 64 registers, and the little-endian tool chain
works fine. I have configured "as" and "ld" to be big-endian and they
work. For gcc I have set BYTES_BIG_ENDIAN to 1 and left the rest of the
*_ENDIAN definitions as 0, which is appropriate for the architecture.
But, I have a problem which shows up (at least) two ways, for the same
reason:
Compiling:
if (x != x)
{
x = 1.0;
}
causes an assertion failure in emit-rtl.c:gen_rtx_SUBREG() because
validate_subreg() thinks the value of the compare is in the high half of
a register, but needs to be in the bottom half. [ Note: The required
value is actually in the bottom half, where it belongs, and the
generated code is correct if I comment out the assert. ]
Compiling with -O0:
void
test_48(long arg)
{
PASS((signed char)arg);
}
results in the following broken code:
00000000000101a0 <test_48>:
<prologue>
101d0: { addi r1, r52, -16 } // save "arg" on stack
101d8: { st r1, r0 } // 64 bit store
101e0: { addi r0, r52, -16 } // retrieve "arg"
101e8: { addi r0, r0, 7 } // BROKEN!!! -- the hardware
makes this adjustment in BE mode.
101f0: { ld1s r0, r0 } // 1 byte load
101f8: { mtspr PASS, r0 }
<epilogue>
[ Note: compiling -O3 gives the right code because it doesn't waste
instructions storing arg into memory and retrieving it. ]
The problem is that both gcc and the big-endian hardware make the same
adjustment -- we only need this done once. [ Note: in BE mode our
hardware adjusts the addresses of loads and stores that are smaller than
64 bits. Access to 64 bit words is unchanged. ]
So, why do I care? In both cases above my little-endian gcc produces
exactly the code I want. I want a big-endian version of gcc so that
structures, especially structures with bit fields, are laid out in
memory the way big-endian users expect them. Can I get either a BE gcc
that understands my memory hardware, or else a LE gcc that will reverse
structures as expected for BE users?
Thanks.
--jeff kenton