From e858136d915ea23c5f2c7e44f1988e83029164f3 Mon Sep 17 00:00:00 2001 From: Daniel Sanders Date: Tue, 14 Jun 2016 10:13:47 +0000 Subject: [PATCH] [mips][ias] Implement one N32 case (of two) for .cpsetup. This patch implements the N32 case where -mno-shared is in effect. The case where -mshared is in effect will be added later since doing that now requires additional changes to how we handle %hi(%neg(%gp_rel(foo))) expressions to emit the three relocations as three relocations (currently only one of the three would be emitted) which then requires further changes to our MCFixup handling. While we could fix both cases together, fixing the -mno-shared case allows us to fix the ELFCLASS bug (where N32 incorrectly uses ELFCLASS64 instead of ELFCLASS32) in a way that allows cpsetup.s to check for a correct output instead of another incorrect output. Reviewers: sdardis Subscribers: dsanders, llvm-commits, sdardis Differential Revision: http://reviews.llvm.org/D21131 llvm-svn: 272652 --- .../Mips/MCTargetDesc/MipsTargetStreamer.cpp | 55 +++++++++---------- llvm/test/MC/Mips/cpsetup.s | 44 ++++++--------- 2 files changed, 43 insertions(+), 56 deletions(-) diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index 45296091e2895..7f79eb400f597 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -1077,25 +1077,38 @@ void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, 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 @@ void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, 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, diff --git a/llvm/test/MC/Mips/cpsetup.s b/llvm/test/MC/Mips/cpsetup.s index b51dd0b69adda..255c1f620194c 100644 --- a/llvm/test/MC/Mips/cpsetup.s +++ b/llvm/test/MC/Mips/cpsetup.s @@ -31,16 +31,13 @@ t1: # 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 @@ -62,16 +59,13 @@ t2: # 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 @@ -101,16 +95,13 @@ t3: # 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 @@ -157,16 +148,13 @@ t5: # 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