Skip to content

Commit

Permalink
[mips][ias] Implement one N32 case (of two) for .cpsetup.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
dsandersllvm committed Jun 14, 2016
1 parent cf1165b commit e858136
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 56 deletions.
55 changes: 27 additions & 28 deletions llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
Expand Up @@ -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()),
Expand All @@ -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,
Expand Down
44 changes: 16 additions & 28 deletions llvm/test/MC/Mips/cpsetup.s
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit e858136

Please sign in to comment.