On 02/16/2011 02:32 PM, Paul Koning wrote:
On Feb 16, 2011, at 5:25 PM, David Daney wrote:
What is the state of your C0_Status[{KX,SX,UX}] bits?
0, 0, 0
It is not really a compiler bug, but rather a defect in the n32 ABI. When using
32-bit pointers you can only do 32-bit operations on them. To do otherwise
raises the possibility of generating addresses that fall outside of the allowed
range.
Sure, I understand that. Actually, I'm using O64, but the issue is the same as
with N32.
??
The problem is that the machine is doing 64 bit arithmetic when applying an
offset to a base register. So what the compiler has to do is valid 64 bit
operations from 32-bit sign extended memory and constant values.
But as you have found, there is this 64kb region centered on the split where
behavior can become undefined.
The only real way to avoid it would be to prohibit GCC from generating non-zero
offsets for load/store instructions, the resulting code would be slower and
bigger than the current behavior of using the offsets in address calculations.
I don't think it needs to do anything slower. As far as I can tell, the only
change needed is that arithmetic on pointer values held in registers must be
done with 64-bit operations. That just changes the opcodes, but it doesn't
make them any longer.
So to answer your question:
I think your 'compiler bug' is a false predicate. And yes, I do suggest that
you modify your kernel.
I don't have the option of modifying the kernel, since I'm dealing with data
structures that are at hardwired addresses and moving them isn't an available
option.
I guess I'll go beat on the code generator...
It might be easier to do something to force the base address into a
register so that the offsetting doesn't happen.
Something like:
struct foo *v = (struct foo *)0x80007110UL;
v -= 2;
/* Clobber v so GCC forces the value into a register. */
asm("" : "+r" (v));
int bar = v->element;
.
.
.