MIPS: Trouble with address calculation near the useg/kseg boundary
David Daney
ddaney@caviumnetworks.com
Thu Feb 17 10:47:00 GMT 2011
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;
.
.
.
More information about the Gcc
mailing list