https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78176

--- Comment #28 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to James Cowgill from comment #0)
> Before the ldxc1 instruction is executed, gdb reports that the values in v0
> and s0 are both large integers (above 0x80000000):
> (gdb) print/x $v0
> $1 = 0xfffee7f8
> (gdb) print/x $s0
> $2 = 0x80008b50
> 
> When added together, the lower 32-bits contains the correct pointer (in this
> case on the stack). On a 32-bit processor this is fine.
> 
> On a 64-bit processor, we know that v0 and s0 are sign extended as the last
> instructions to touch them were the addu at 924 and the subu at 8e0. So the
> values in the registers are actually:
> v0 = 0xfffffffffffee7f8
> s0 = 0xffffffff80008b50
> 
> Adding these together (modulo 64-bit) gives the final pointer of
> 0xffffffff7fff7348 which is outside the user address space and thus results
> in a SIGBUS.
> 
> I think GCC is assuming that the address calculated by the ldxc1 instruction
> is modulo 32-bit when compiled for a 32-bit processor. However, this is not
> true if the code is later run on a 64-bit processor.

Given the above GCC has to consider pointers (even integer regs!?) being
64bit even in 32bit mode since obviously semantics between 32bit and 64bit
hardware differs.  Thus as Eric says Pmode needs to be DImode and
ptr_mode SImode for 32bit and DImode for 64bit.  Everything else is going
to lead to issues like the ones observed.

Reply via email to