http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27619
Segher Boessenkool <segher at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |ASSIGNED CC| |segher at gcc dot gnu.org AssignedTo|unassigned at gcc dot |segher at gcc dot gnu.org |gnu.org | --- Comment #15 from Segher Boessenkool <segher at gcc dot gnu.org> 2012-10-23 16:10:34 UTC --- Things become a little clearer if you compile with -ffast-math, so that the floatdisf2_internal2 pattern is not used. The function then starts as: stwu 1,-16(1) lis 9,i@ha lwa 9,i@l(9) mflr 0 std 9,8(1) and stepi shows that the lwa insn already loads the wrong value! Of course, GDB will not show the instruction because it does not want to disassemble 64-bit insns in a 32-bit binary; but it shows 0x100002fc <+12>: .long 0xe9290890 which is wrong: it should be e9290892, low two bits zero means it is an ld insn, not lwa. The lwa patterns use the wrong constraint (they use "m", should be "Y", because the low 2 bits of the offset are required to be zero); but that does not fix it. For 64-bit binaries, the relocations formed by @l for ld and lwa and friends are ADDR16_LO_DS relocations; but for 32-bit binaries, GAS simply makes ADDR16_LO relocations, which do set the low two vits from the offset. Oops. Now of course ADDR16_LO_DS relocations do not exist for the 32-bit PowerPC ABI, but overwriting the low bits of the instruction isn't terribly helpful. On GCC's side, I don't think we have any other choice than to disable all instructions that need DS relocations when targetting an ABI that does not have relocations for those; except we can get away with it for insns that should have the low two bits zero. So we need to disable (for -m32 -mpowerpc64): lwa, ldu, stdu; but we can keep: ld, std (and ldx, ldux, stdx, stdux -- those aren't DS-form, do not need relocations).