Index: lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -1077,25 +1077,38 @@ if (!Pic || !(getABI().IsN32() || getABI().IsN64())) return; + forbidModuleDirective(); + MCAssembler &MCA = getStreamer().getAssembler(); MCInst Inst; // Either store the old $gp in a register or on the stack if (IsReg) { // move $save, $gpreg - Inst.setOpcode(Mips::OR64); - Inst.addOperand(MCOperand::createReg(RegOrOffset)); - Inst.addOperand(MCOperand::createReg(Mips::GP)); - Inst.addOperand(MCOperand::createReg(Mips::ZERO)); + emitRRR(Mips::OR64, RegOrOffset, Mips::GP, Mips::ZERO, SMLoc(), &STI); } else { // sd $gpreg, offset($sp) - Inst.setOpcode(Mips::SD); - Inst.addOperand(MCOperand::createReg(Mips::GP)); - Inst.addOperand(MCOperand::createReg(Mips::SP)); - Inst.addOperand(MCOperand::createImm(RegOrOffset)); + emitRRI(Mips::SD, Mips::GP, Mips::SP, RegOrOffset, SMLoc(), &STI); + } + + if (getABI().IsN32()) { + MCSymbol *GPSym = MCA.getContext().getOrCreateSymbol("__gnu_local_gp"); + const MipsMCExpr *HiExpr = MipsMCExpr::create( + MipsMCExpr::MEK_HI, MCSymbolRefExpr::create(GPSym, MCA.getContext()), + MCA.getContext()); + const MipsMCExpr *LoExpr = MipsMCExpr::create( + MipsMCExpr::MEK_LO, MCSymbolRefExpr::create(GPSym, MCA.getContext()), + MCA.getContext()); + + // lui $gp, %hi(__gnu_local_gp) + emitRX(Mips::LUi, Mips::GP, MCOperand::createExpr(HiExpr), SMLoc(), &STI); + + // addiu $gp, $gp, %lo(__gnu_local_gp) + emitRRX(Mips::ADDiu, Mips::GP, Mips::GP, MCOperand::createExpr(LoExpr), + SMLoc(), &STI); + + return; } - getStreamer().EmitInstruction(Inst, STI); - Inst.clear(); const MipsMCExpr *HiExpr = MipsMCExpr::createGpOff( MipsMCExpr::MEK_HI, MCSymbolRefExpr::create(&Sym, MCA.getContext()), @@ -1105,28 +1118,14 @@ MCA.getContext()); // lui $gp, %hi(%neg(%gp_rel(funcSym))) - Inst.setOpcode(Mips::LUi); - Inst.addOperand(MCOperand::createReg(Mips::GP)); - Inst.addOperand(MCOperand::createExpr(HiExpr)); - getStreamer().EmitInstruction(Inst, STI); - Inst.clear(); + emitRX(Mips::LUi, Mips::GP, MCOperand::createExpr(HiExpr), SMLoc(), &STI); // addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym))) - Inst.setOpcode(Mips::ADDiu); - Inst.addOperand(MCOperand::createReg(Mips::GP)); - Inst.addOperand(MCOperand::createReg(Mips::GP)); - Inst.addOperand(MCOperand::createExpr(LoExpr)); - getStreamer().EmitInstruction(Inst, STI); - Inst.clear(); + emitRRX(Mips::ADDiu, Mips::GP, Mips::GP, MCOperand::createExpr(LoExpr), + SMLoc(), &STI); // daddu $gp, $gp, $funcreg - Inst.setOpcode(Mips::DADDu); - Inst.addOperand(MCOperand::createReg(Mips::GP)); - Inst.addOperand(MCOperand::createReg(Mips::GP)); - Inst.addOperand(MCOperand::createReg(RegNo)); - getStreamer().EmitInstruction(Inst, STI); - - forbidModuleDirective(); + emitRRR(Mips::DADDu, Mips::GP, Mips::GP, RegNo, SMLoc(), &STI); } void MipsTargetELFStreamer::emitDirectiveCpreturn(unsigned SaveLocation, Index: test/MC/Mips/cpsetup.s =================================================================== --- test/MC/Mips/cpsetup.s +++ test/MC/Mips/cpsetup.s @@ -30,16 +30,13 @@ # O32-NOT: __cerror -# FIXME: Direct object emission for N32 is still under development. -# N32 doesn't allow 3 operations to be specified in the same relocation -# record like N64 does. - # NXX-NEXT: sd $gp, 8($sp) # NXX-NEXT: lui $gp, 0 -# NXX-NEXT: R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_HI16 __cerror +# N32-NEXT: R_MIPS_HI16/R_MIPS_NONE/R_MIPS_NONE __gnu_local_gp +# N64-NEXT: R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_HI16 __cerror # NXX-NEXT: addiu $gp, $gp, 0 -# NXX-NEXT: R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_LO16 __cerror -# N32-NEXT: addu $gp, $gp, $25 +# N32-NEXT: R_MIPS_LO16/R_MIPS_NONE/R_MIPS_NONE __gnu_local_gp +# N64-NEXT: R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_LO16 __cerror # N64-NEXT: daddu $gp, $gp, $25 # ASM-NEXT: .cpsetup $25, 8, __cerror @@ -61,16 +58,13 @@ # O32-NOT: __cerror -# FIXME: Direct object emission for N32 is still under development. -# N32 doesn't allow 3 operations to be specified in the same relocation -# record like N64 does. - # NXX-NEXT: move $2, $gp # NXX-NEXT: lui $gp, 0 -# NXX-NEXT: R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_HI16 __cerror +# N32-NEXT: R_MIPS_HI16/R_MIPS_NONE/R_MIPS_NONE __gnu_local_gp +# N64-NEXT: R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_HI16 __cerror # NXX-NEXT: addiu $gp, $gp, 0 -# NXX-NEXT: R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_LO16 __cerror -# N32-NEXT: addu $gp, $gp, $25 +# N32-NEXT: R_MIPS_LO16/R_MIPS_NONE/R_MIPS_NONE __gnu_local_gp +# N64-NEXT: R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_LO16 __cerror # N64-NEXT: daddu $gp, $gp, $25 # ASM-NEXT: .cpsetup $25, $2, __cerror @@ -100,16 +94,13 @@ # O32-NEXT: nop # O32-NEXT: sub $3, $3, $2 -# FIXME: Direct object emission for N32 is still under development. -# N32 doesn't allow 3 operations to be specified in the same relocation -# record like N64 does. - # NXX-NEXT: move $2, $gp # NXX-NEXT: lui $gp, 0 -# NXX-NEXT: {{^ *0+}}40: R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_HI16 .text +# N32-NEXT: {{^ *0+}}38: R_MIPS_HI16/R_MIPS_NONE/R_MIPS_NONE __gnu_local_gp +# N64-NEXT: {{^ *0+}}40: R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_HI16 .text # NXX-NEXT: addiu $gp, $gp, 0 -# NXX-NEXT: {{^ *0+}}44: R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_LO16 .text -# N32-NEXT: addu $gp, $gp, $25 +# N32-NEXT: {{^ *0+}}3c: R_MIPS_LO16/R_MIPS_NONE/R_MIPS_NONE __gnu_local_gp +# N64-NEXT: {{^ *0+}}44: R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_LO16 .text # N64-NEXT: daddu $gp, $gp, $25 # NXX-NEXT: nop # NXX-NEXT: sub $3, $3, $2 @@ -156,16 +147,13 @@ # O32-NOT: __cerror -# FIXME: Direct object emission for N32 is still under development. -# N32 doesn't allow 3 operations to be specified in the same relocation -# record like N64 does. - # NXX-NEXT: sd $gp, 8($sp) # NXX-NEXT: lui $gp, 0 -# NXX-NEXT: R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_HI16 __cerror +# N32-NEXT: R_MIPS_HI16/R_MIPS_NONE/R_MIPS_NONE __gnu_local_gp +# N64-NEXT: R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_HI16 __cerror # NXX-NEXT: addiu $gp, $gp, 0 -# NXX-NEXT: R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_LO16 __cerror -# N32-NEXT: addu $gp, $gp, $25 +# N32-NEXT: R_MIPS_LO16/R_MIPS_NONE/R_MIPS_NONE __gnu_local_gp +# N64-NEXT: R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_LO16 __cerror # N64-NEXT: daddu $gp, $gp, $25 # ASM-NEXT: .cpsetup $25, 8, __cerror