Index: include/llvm/MC/MCExpr.h
===================================================================
--- include/llvm/MC/MCExpr.h
+++ include/llvm/MC/MCExpr.h
@@ -73,7 +73,8 @@
   /// \name Utility Methods
   /// @{
 
-  void print(raw_ostream &OS, const MCAsmInfo *MAI) const;
+  void print(raw_ostream &OS, const MCAsmInfo *MAI,
+             bool InParens = false) const;
   void dump() const;
 
   /// @}
@@ -250,33 +251,6 @@
     VK_PPC_TLSLD,          // symbol@tlsld
     VK_PPC_LOCAL,          // symbol@local
 
-    VK_Mips_GPREL,
-    VK_Mips_GOT_CALL,
-    VK_Mips_GOT16,
-    VK_Mips_GOT,
-    VK_Mips_ABS_HI,
-    VK_Mips_ABS_LO,
-    VK_Mips_TLSGD,
-    VK_Mips_TLSLDM,
-    VK_Mips_DTPREL_HI,
-    VK_Mips_DTPREL_LO,
-    VK_Mips_GOTTPREL,
-    VK_Mips_TPREL_HI,
-    VK_Mips_TPREL_LO,
-    VK_Mips_GPOFF_HI,
-    VK_Mips_GPOFF_LO,
-    VK_Mips_GOT_DISP,
-    VK_Mips_GOT_PAGE,
-    VK_Mips_GOT_OFST,
-    VK_Mips_HIGHER,
-    VK_Mips_HIGHEST,
-    VK_Mips_GOT_HI16,
-    VK_Mips_GOT_LO16,
-    VK_Mips_CALL_HI16,
-    VK_Mips_CALL_LO16,
-    VK_Mips_PCREL_HI16,
-    VK_Mips_PCREL_LO16,
-
     VK_COFF_IMGREL32, // symbol@imgrel (image-relative)
 
     VK_Hexagon_PCREL,
Index: lib/MC/ELFObjectWriter.cpp
===================================================================
--- lib/MC/ELFObjectWriter.cpp
+++ lib/MC/ELFObjectWriter.cpp
@@ -536,7 +536,6 @@
   case MCSymbolRefExpr::VK_GOT:
   case MCSymbolRefExpr::VK_PLT:
   case MCSymbolRefExpr::VK_GOTPCREL:
-  case MCSymbolRefExpr::VK_Mips_GOT:
   case MCSymbolRefExpr::VK_PPC_GOT_LO:
   case MCSymbolRefExpr::VK_PPC_GOT_HI:
   case MCSymbolRefExpr::VK_PPC_GOT_HA:
Index: lib/MC/MCELFStreamer.cpp
===================================================================
--- lib/MC/MCELFStreamer.cpp
+++ lib/MC/MCELFStreamer.cpp
@@ -412,10 +412,6 @@
     case MCSymbolRefExpr::VK_TPREL:
     case MCSymbolRefExpr::VK_DTPOFF:
     case MCSymbolRefExpr::VK_DTPREL:
-    case MCSymbolRefExpr::VK_Mips_TLSGD:
-    case MCSymbolRefExpr::VK_Mips_GOTTPREL:
-    case MCSymbolRefExpr::VK_Mips_TPREL_HI:
-    case MCSymbolRefExpr::VK_Mips_TPREL_LO:
     case MCSymbolRefExpr::VK_PPC_DTPMOD:
     case MCSymbolRefExpr::VK_PPC_TPREL_LO:
     case MCSymbolRefExpr::VK_PPC_TPREL_HI:
Index: lib/MC/MCExpr.cpp
===================================================================
--- lib/MC/MCExpr.cpp
+++ lib/MC/MCExpr.cpp
@@ -30,7 +30,7 @@
 }
 }
 
-void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
+void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens) const {
   switch (getKind()) {
   case MCExpr::Target:
     return cast<MCTargetExpr>(this)->printImpl(OS, MAI);
@@ -43,7 +43,8 @@
     const MCSymbol &Sym = SRE.getSymbol();
     // Parenthesize names that start with $ so that they don't look like
     // absolute names.
-    bool UseParens = Sym.getName().size() && Sym.getName()[0] == '$';
+    bool UseParens =
+        !InParens && Sym.getName().size() && Sym.getName()[0] == '$';
     if (UseParens) {
       OS << '(';
       Sym.print(OS, MAI);
@@ -264,32 +265,6 @@
   case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha";
   case VK_PPC_TLSLD: return "tlsld";
   case VK_PPC_LOCAL: return "local";
-  case VK_Mips_GPREL: return "GPREL";
-  case VK_Mips_GOT_CALL: return "GOT_CALL";
-  case VK_Mips_GOT16: return "GOT16";
-  case VK_Mips_GOT: return "GOT";
-  case VK_Mips_ABS_HI: return "ABS_HI";
-  case VK_Mips_ABS_LO: return "ABS_LO";
-  case VK_Mips_TLSGD: return "TLSGD";
-  case VK_Mips_TLSLDM: return "TLSLDM";
-  case VK_Mips_DTPREL_HI: return "DTPREL_HI";
-  case VK_Mips_DTPREL_LO: return "DTPREL_LO";
-  case VK_Mips_GOTTPREL: return "GOTTPREL";
-  case VK_Mips_TPREL_HI: return "TPREL_HI";
-  case VK_Mips_TPREL_LO: return "TPREL_LO";
-  case VK_Mips_GPOFF_HI: return "GPOFF_HI";
-  case VK_Mips_GPOFF_LO: return "GPOFF_LO";
-  case VK_Mips_GOT_DISP: return "GOT_DISP";
-  case VK_Mips_GOT_PAGE: return "GOT_PAGE";
-  case VK_Mips_GOT_OFST: return "GOT_OFST";
-  case VK_Mips_HIGHER:   return "HIGHER";
-  case VK_Mips_HIGHEST:  return "HIGHEST";
-  case VK_Mips_GOT_HI16: return "GOT_HI16";
-  case VK_Mips_GOT_LO16: return "GOT_LO16";
-  case VK_Mips_CALL_HI16: return "CALL_HI16";
-  case VK_Mips_CALL_LO16: return "CALL_LO16";
-  case VK_Mips_PCREL_HI16: return "PCREL_HI16";
-  case VK_Mips_PCREL_LO16: return "PCREL_LO16";
   case VK_COFF_IMGREL32: return "IMGREL";
   case VK_Hexagon_PCREL: return "PCREL";
   case VK_Hexagon_LO16: return "LO16";
Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp
===================================================================
--- lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -303,8 +303,6 @@
 
   bool parseInternalDirectiveReallowModule();
 
-  MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
-
   bool eatComma(StringRef ErrorStr);
 
   int matchCPURegisterName(StringRef Symbol);
@@ -1635,9 +1633,7 @@
       return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
 
     // FIXME: This is checking the expression can be handled by the later stages
-    //        of the assembler. We ought to leave it to those later stages but
-    //        we can't do that until we stop evaluateRelocExpr() rewriting the
-    //        expressions into non-equivalent forms.
+    //        of the assembler. We ought to leave it to those later stages.
     const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
 
     // FIXME: Add support for label+offset operands (currently causes an error).
@@ -1651,8 +1647,10 @@
         //  addiu $25, $25, 0
         //    R_(MICRO)MIPS_LO16   label
         //  jalr  $25
-        const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
-        const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
+        const MCExpr *Got16RelocExpr =
+            MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
+        const MCExpr *Lo16RelocExpr =
+            MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
 
         TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
                      MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
@@ -1664,7 +1662,8 @@
         //  lw/ld $25, 0($gp)
         //    R_(MICRO)MIPS_GOT_DISP  label
         //  jalr  $25
-        const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
+        const MCExpr *GotDispRelocExpr =
+            MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
 
         TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
                      Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
@@ -1675,7 +1674,8 @@
       //  lw/ld    $25, 0($gp)
       //    R_(MICRO)MIPS_CALL16  label
       //  jalr  $25
-      const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
+      const MCExpr *Call16RelocExpr =
+          MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
 
       TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
                    MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
@@ -2341,10 +2341,10 @@
   warnIfNoMacro(IDLoc);
 
   const MCExpr *Symbol = cast<MCExpr>(SymExpr);
-  const MipsMCExpr *HiExpr = MipsMCExpr::create(
-      MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
-  const MipsMCExpr *LoExpr = MipsMCExpr::create(
-      MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
+  const MipsMCExpr *HiExpr =
+      MipsMCExpr::create(MipsMCExpr::MEK_HI, Symbol, getContext());
+  const MipsMCExpr *LoExpr =
+      MipsMCExpr::create(MipsMCExpr::MEK_LO, Symbol, getContext());
 
   bool UseSrcReg = SrcReg != Mips::NoRegister;
 
@@ -2356,10 +2356,10 @@
     if (!ATReg)
       return true;
 
-    const MipsMCExpr *HighestExpr = MipsMCExpr::create(
-        MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
-    const MipsMCExpr *HigherExpr = MipsMCExpr::create(
-        MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
+    const MipsMCExpr *HighestExpr =
+        MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, Symbol, getContext());
+    const MipsMCExpr *HigherExpr =
+        MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, Symbol, getContext());
 
     if (UseSrcReg &&
         getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
@@ -2579,10 +2579,10 @@
   }
 
   const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
-  MCOperand LoOperand =
-      MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo"));
-  MCOperand HiOperand =
-      MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi"));
+  MCOperand LoOperand = MCOperand::createExpr(
+      MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
+  MCOperand HiOperand = MCOperand::createExpr(
+      MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
 
   // Try to use DstReg as the temporary.
   if (IsGPR && (BaseReg != DstReg)) {
@@ -2620,10 +2620,10 @@
   }
 
   const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
-  MCOperand LoOperand =
-      MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo"));
-  MCOperand HiOperand =
-      MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi"));
+  MCOperand LoOperand = MCOperand::createExpr(
+      MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
+  MCOperand HiOperand = MCOperand::createExpr(
+      MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
   TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
                               LoOperand, ATReg, IDLoc, STI);
 }
@@ -4080,64 +4080,41 @@
 
 const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
                                                StringRef RelocStr) {
-  const MCExpr *Res;
-  // Check the type of the expression.
-  if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
-    // It's a constant, evaluate reloc value.
-    int16_t Val;
-    switch (getVariantKind(RelocStr)) {
-    case MCSymbolRefExpr::VK_Mips_ABS_LO:
-      // Get the 1st 16-bits.
-      Val = MCE->getValue() & 0xffff;
-      break;
-    case MCSymbolRefExpr::VK_Mips_ABS_HI:
-    case MCSymbolRefExpr::VK_Mips_GOT:
-      // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
-      // 16 bits being negative.
-      Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
-      break;
-    case MCSymbolRefExpr::VK_Mips_HIGHER:
-      // Get the 3rd 16-bits.
-      Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
-      break;
-    case MCSymbolRefExpr::VK_Mips_HIGHEST:
-      // Get the 4th 16-bits.
-      Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
-      break;
-    default:
-      report_fatal_error("unsupported reloc value");
-    }
-    return MCConstantExpr::create(Val, getContext());
-  }
-
-  if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
-    // It's a symbol, create a symbolic expression from the symbol.
-    const MCSymbol *Symbol = &MSRE->getSymbol();
-    MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
-    Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
-    return Res;
-  }
-
-  if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
-    MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
-
-    // Try to create target expression.
-    if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
-      return MipsMCExpr::create(VK, Expr, getContext());
-
-    const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
-    const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
-    Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
-    return Res;
-  }
-
-  if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
-    const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
-    Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
-    return Res;
-  }
-  // Just return the original expression.
-  return Expr;
+  if (RelocStr == "hi(%neg(%gp_rel")
+    return MipsMCExpr::createGpOff(MipsMCExpr::MEK_HI, Expr, getContext());
+  else if (RelocStr == "lo(%neg(%gp_rel")
+    return MipsMCExpr::createGpOff(MipsMCExpr::MEK_LO, Expr, getContext());
+
+  MipsMCExpr::MipsExprKind Kind =
+      StringSwitch<MipsMCExpr::MipsExprKind>(RelocStr)
+          .Case("call16", MipsMCExpr::MEK_GOT_CALL)
+          .Case("call_hi", MipsMCExpr::MEK_CALL_HI16)
+          .Case("call_lo", MipsMCExpr::MEK_CALL_LO16)
+          .Case("dtprel_hi", MipsMCExpr::MEK_DTPREL_HI)
+          .Case("dtprel_lo", MipsMCExpr::MEK_DTPREL_LO)
+          .Case("got", MipsMCExpr::MEK_GOT)
+          .Case("got_disp", MipsMCExpr::MEK_GOT_DISP)
+          .Case("got_hi", MipsMCExpr::MEK_GOT_HI16)
+          .Case("got_lo", MipsMCExpr::MEK_GOT_LO16)
+          .Case("got_ofst", MipsMCExpr::MEK_GOT_OFST)
+          .Case("got_page", MipsMCExpr::MEK_GOT_PAGE)
+          .Case("gottprel", MipsMCExpr::MEK_GOTTPREL)
+          .Case("gp_rel", MipsMCExpr::MEK_GPREL)
+          .Case("hi", MipsMCExpr::MEK_HI)
+          .Case("higher", MipsMCExpr::MEK_HIGHER)
+          .Case("highest", MipsMCExpr::MEK_HIGHEST)
+          .Case("lo", MipsMCExpr::MEK_LO)
+          .Case("neg", MipsMCExpr::MEK_NEG)
+          .Case("pcrel_hi", MipsMCExpr::MEK_PCREL_HI16)
+          .Case("pcrel_lo", MipsMCExpr::MEK_PCREL_LO16)
+          .Case("tlsgd", MipsMCExpr::MEK_TLSGD)
+          .Case("tlsldm", MipsMCExpr::MEK_TLSLDM)
+          .Case("tprel_hi", MipsMCExpr::MEK_TPREL_HI)
+          .Case("tprel_lo", MipsMCExpr::MEK_TPREL_LO)
+          .Default(MipsMCExpr::MEK_None);
+
+  assert(Kind != MipsMCExpr::MEK_None);
+  return MipsMCExpr::create(Kind, Expr, getContext());
 }
 
 bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
@@ -4740,42 +4717,6 @@
   return MatchOperand_Success;
 }
 
-MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
-
-  MCSymbolRefExpr::VariantKind VK =
-      StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
-          .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
-          .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
-          .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
-          .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
-          .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
-          .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
-          .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
-          .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
-          .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
-          .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
-          .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
-          .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
-          .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
-          .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
-          .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
-          .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
-          .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
-          .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
-          .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
-          .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
-          .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
-          .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
-          .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
-          .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
-          .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
-          .Default(MCSymbolRefExpr::VK_None);
-
-  assert(VK != MCSymbolRefExpr::VK_None);
-
-  return VK;
-}
-
 /// Sometimes (i.e. load/stores) the operand may be followed immediately by
 /// either this.
 /// ::= '(', register, ')'
Index: lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp
===================================================================
--- lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp
+++ lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp
@@ -140,36 +140,7 @@
 
   MCSymbolRefExpr::VariantKind Kind = SRE->getKind();
 
-  switch (Kind) {
-  default:                                 llvm_unreachable("Invalid kind!");
-  case MCSymbolRefExpr::VK_None:           break;
-  case MCSymbolRefExpr::VK_Mips_GPREL:     OS << "%gp_rel("; break;
-  case MCSymbolRefExpr::VK_Mips_GOT_CALL:  OS << "%call16("; break;
-  case MCSymbolRefExpr::VK_Mips_GOT16:     OS << "%got(";    break;
-  case MCSymbolRefExpr::VK_Mips_GOT:       OS << "%got(";    break;
-  case MCSymbolRefExpr::VK_Mips_ABS_HI:    OS << "%hi(";     break;
-  case MCSymbolRefExpr::VK_Mips_ABS_LO:    OS << "%lo(";     break;
-  case MCSymbolRefExpr::VK_Mips_TLSGD:     OS << "%tlsgd(";  break;
-  case MCSymbolRefExpr::VK_Mips_TLSLDM:    OS << "%tlsldm(";  break;
-  case MCSymbolRefExpr::VK_Mips_DTPREL_HI: OS << "%dtprel_hi(";  break;
-  case MCSymbolRefExpr::VK_Mips_DTPREL_LO: OS << "%dtprel_lo(";  break;
-  case MCSymbolRefExpr::VK_Mips_GOTTPREL:  OS << "%gottprel("; break;
-  case MCSymbolRefExpr::VK_Mips_TPREL_HI:  OS << "%tprel_hi("; break;
-  case MCSymbolRefExpr::VK_Mips_TPREL_LO:  OS << "%tprel_lo("; break;
-  case MCSymbolRefExpr::VK_Mips_GPOFF_HI:  OS << "%hi(%neg(%gp_rel("; break;
-  case MCSymbolRefExpr::VK_Mips_GPOFF_LO:  OS << "%lo(%neg(%gp_rel("; break;
-  case MCSymbolRefExpr::VK_Mips_GOT_DISP:  OS << "%got_disp("; break;
-  case MCSymbolRefExpr::VK_Mips_GOT_PAGE:  OS << "%got_page("; break;
-  case MCSymbolRefExpr::VK_Mips_GOT_OFST:  OS << "%got_ofst("; break;
-  case MCSymbolRefExpr::VK_Mips_HIGHER:    OS << "%higher("; break;
-  case MCSymbolRefExpr::VK_Mips_HIGHEST:   OS << "%highest("; break;
-  case MCSymbolRefExpr::VK_Mips_GOT_HI16:  OS << "%got_hi("; break;
-  case MCSymbolRefExpr::VK_Mips_GOT_LO16:  OS << "%got_lo("; break;
-  case MCSymbolRefExpr::VK_Mips_CALL_HI16: OS << "%call_hi("; break;
-  case MCSymbolRefExpr::VK_Mips_CALL_LO16: OS << "%call_lo("; break;
-  case MCSymbolRefExpr::VK_Mips_PCREL_HI16: OS << "%pcrel_hi("; break;
-  case MCSymbolRefExpr::VK_Mips_PCREL_LO16: OS << "%pcrel_lo("; break;
-  }
+  assert(Kind == MCSymbolRefExpr::VK_None && "Invalid kind!");
 
   SRE->getSymbol().print(OS, MAI);
 
@@ -179,10 +150,7 @@
     OS << Offset;
   }
 
-  if ((Kind == MCSymbolRefExpr::VK_Mips_GPOFF_HI) ||
-      (Kind == MCSymbolRefExpr::VK_Mips_GPOFF_LO))
-    OS << ")))";
-  else if (Kind != MCSymbolRefExpr::VK_None)
+  if (Kind != MCSymbolRefExpr::VK_None)
     OS << ')';
 }
 
Index: lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
===================================================================
--- lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
+++ lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
@@ -14,6 +14,7 @@
 
 #include "MCTargetDesc/MipsFixupKinds.h"
 #include "MCTargetDesc/MipsAsmBackend.h"
+#include "MCTargetDesc/MipsMCExpr.h"
 #include "MCTargetDesc/MipsMCTargetDesc.h"
 #include "llvm/MC/MCAsmBackend.h"
 #include "llvm/MC/MCAssembler.h"
@@ -23,7 +24,9 @@
 #include "llvm/MC/MCFixupKindInfo.h"
 #include "llvm/MC/MCObjectWriter.h"
 #include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCValue.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -40,9 +43,6 @@
   default:
     return 0;
   case FK_Data_2:
-  case FK_GPRel_4:
-  case FK_Data_4:
-  case FK_Data_8:
   case Mips::fixup_Mips_LO16:
   case Mips::fixup_Mips_GPREL16:
   case Mips::fixup_Mips_GPOFF_HI:
@@ -57,6 +57,11 @@
   case Mips::fixup_MICROMIPS_GOT_OFST:
   case Mips::fixup_MICROMIPS_GOT_DISP:
   case Mips::fixup_MIPS_PCLO16:
+    Value &= 0xffff;
+    break;
+  case FK_GPRel_4:
+  case FK_Data_4:
+  case FK_Data_8:
     break;
   case Mips::fixup_Mips_PC16:
     // The displacement is then divided by 4 to give us an 18 bit
@@ -85,7 +90,7 @@
     Value >>= 2;
     break;
   case Mips::fixup_Mips_HI16:
-  case Mips::fixup_Mips_GOT_Local:
+  case Mips::fixup_Mips_GOT:
   case Mips::fixup_Mips_GOT_HI16:
   case Mips::fixup_Mips_CALL_HI16:
   case Mips::fixup_MICROMIPS_HI16:
@@ -295,8 +300,7 @@
     { "fixup_Mips_LO16",         0,     16,   0 },
     { "fixup_Mips_GPREL16",      0,     16,   0 },
     { "fixup_Mips_LITERAL",      0,     16,   0 },
-    { "fixup_Mips_GOT_Global",   0,     16,   0 },
-    { "fixup_Mips_GOT_Local",    0,     16,   0 },
+    { "fixup_Mips_GOT",          0,     16,   0 },
     { "fixup_Mips_PC16",         0,     16,  MCFixupKindInfo::FKF_IsPCRel },
     { "fixup_Mips_CALL16",       0,     16,   0 },
     { "fixup_Mips_GPREL32",      0,     32,   0 },
@@ -364,8 +368,7 @@
     { "fixup_Mips_LO16",        16,     16,   0 },
     { "fixup_Mips_GPREL16",     16,     16,   0 },
     { "fixup_Mips_LITERAL",     16,     16,   0 },
-    { "fixup_Mips_GOT_Global",  16,     16,   0 },
-    { "fixup_Mips_GOT_Local",   16,     16,   0 },
+    { "fixup_Mips_GOT",         16,     16,   0 },
     { "fixup_Mips_PC16",        16,     16,  MCFixupKindInfo::FKF_IsPCRel },
     { "fixup_Mips_CALL16",      16,     16,   0 },
     { "fixup_Mips_GPREL32",      0,     32,   0 },
@@ -460,6 +463,8 @@
   // we are only checking if the fixup can be applied correctly. We have
   // access to MCContext from here which allows us to report a fatal error
   // with *possibly* a source code location.
+  // The caller will also ignore any changes we make to Value
+  // (recordRelocation() overwrite it with it's own calculation).
   (void)adjustFixupValue(Fixup, Value, &Asm.getContext());
 }
 
Index: lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
===================================================================
--- lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
+++ lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
@@ -33,9 +33,8 @@
 
     MO_NO_FLAG,
 
-    /// MO_GOT16 - Represents the offset into the global offset table at which
+    /// MO_GOT - Represents the offset into the global offset table at which
     /// the address the relocation entry symbol resides during execution.
-    MO_GOT16,
     MO_GOT,
 
     /// MO_GOT_CALL - Represents the offset into the global offset table at
Index: lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
===================================================================
--- lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
+++ lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
@@ -131,8 +131,7 @@
     return ELF::R_MIPS_26;
   case Mips::fixup_Mips_CALL16:
     return ELF::R_MIPS_CALL16;
-  case Mips::fixup_Mips_GOT_Global:
-  case Mips::fixup_Mips_GOT_Local:
+  case Mips::fixup_Mips_GOT:
     return ELF::R_MIPS_GOT16;
   case Mips::fixup_Mips_HI16:
     return ELF::R_MIPS_HI16;
@@ -402,7 +401,7 @@
   case ELF::R_MIPS_GOT16:
   case ELF::R_MIPS16_GOT16:
   case ELF::R_MICROMIPS_GOT16:
-    llvm_unreachable("Should have been handled already");
+    return true;
 
   // These relocations might be paired with another relocation. The pairing is
   // done by the static linker by matching the symbol. Since we only see one
Index: lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
===================================================================
--- lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
+++ lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
@@ -50,11 +50,8 @@
     // 16 bit literal fixup resulting in - R_MIPS_LITERAL.
     fixup_Mips_LITERAL,
 
-    // Global symbol fixup resulting in - R_MIPS_GOT16.
-    fixup_Mips_GOT_Global,
-
-    // Local symbol fixup resulting in - R_MIPS_GOT16.
-    fixup_Mips_GOT_Local,
+    // Symbol fixup resulting in - R_MIPS_GOT16.
+    fixup_Mips_GOT,
 
     // PC relative branch fixup resulting in - R_MIPS_PC16.
     fixup_Mips_PC16,
Index: lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
===================================================================
--- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
+++ lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
@@ -509,126 +509,117 @@
 
     Mips::Fixups FixupKind = Mips::Fixups(0);
     switch (MipsExpr->getKind()) {
-    default: llvm_unreachable("Unsupported fixup kind for target expression!");
-    case MipsMCExpr::VK_Mips_HIGHEST:
-      FixupKind = Mips::fixup_Mips_HIGHEST;
+    case MipsMCExpr::MEK_NEG:
+    case MipsMCExpr::MEK_None:
+    case MipsMCExpr::MEK_Special:
+      llvm_unreachable("Unhandled fixup kind!");
       break;
-    case MipsMCExpr::VK_Mips_HIGHER:
-      FixupKind = Mips::fixup_Mips_HIGHER;
+    case MipsMCExpr::MEK_CALL_HI16:
+      FixupKind = Mips::fixup_Mips_CALL_HI16;
       break;
-    case MipsMCExpr::VK_Mips_HI:
-      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16
-                                   : Mips::fixup_Mips_HI16;
+    case MipsMCExpr::MEK_CALL_LO16:
+      FixupKind = Mips::fixup_Mips_CALL_LO16;
       break;
-    case MipsMCExpr::VK_Mips_LO:
-      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16
-                                   : Mips::fixup_Mips_LO16;
+    case MipsMCExpr::MEK_DTPREL_HI:
+      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_HI16
+                                   : Mips::fixup_Mips_DTPREL_HI;
       break;
-    }
-    Fixups.push_back(MCFixup::create(0, MipsExpr, MCFixupKind(FixupKind)));
-    return 0;
-  }
-
-  if (Kind == MCExpr::SymbolRef) {
-    Mips::Fixups FixupKind = Mips::Fixups(0);
-
-    switch(cast<MCSymbolRefExpr>(Expr)->getKind()) {
-    default: llvm_unreachable("Unknown fixup kind!");
+    case MipsMCExpr::MEK_DTPREL_LO:
+      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_LO16
+                                   : Mips::fixup_Mips_DTPREL_LO;
       break;
-    case MCSymbolRefExpr::VK_None:
-      FixupKind = Mips::fixup_Mips_32; // FIXME: This is ok for O32/N32 but not N64.
+    case MipsMCExpr::MEK_GOTTPREL:
+      FixupKind = Mips::fixup_Mips_GOTTPREL;
+      break;
+    case MipsMCExpr::MEK_GOT:
+      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16
+                                   : Mips::fixup_Mips_GOT;
       break;
-    case MCSymbolRefExpr::VK_Mips_GPOFF_HI :
-      FixupKind = Mips::fixup_Mips_GPOFF_HI;
+    case MipsMCExpr::MEK_GOT_CALL:
+      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_CALL16
+                                   : Mips::fixup_Mips_CALL16;
       break;
-    case MCSymbolRefExpr::VK_Mips_GPOFF_LO :
-      FixupKind = Mips::fixup_Mips_GPOFF_LO;
+    case MipsMCExpr::MEK_GOT_DISP:
+      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_DISP
+                                   : Mips::fixup_Mips_GOT_DISP;
       break;
-    case MCSymbolRefExpr::VK_Mips_GOT_PAGE :
+    case MipsMCExpr::MEK_GOT_HI16:
+      FixupKind = Mips::fixup_Mips_GOT_HI16;
+      break;
+    case MipsMCExpr::MEK_GOT_LO16:
+      FixupKind = Mips::fixup_Mips_GOT_LO16;
+      break;
+    case MipsMCExpr::MEK_GOT_PAGE:
       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_PAGE
-                              : Mips::fixup_Mips_GOT_PAGE;
+                                   : Mips::fixup_Mips_GOT_PAGE;
       break;
-    case MCSymbolRefExpr::VK_Mips_GOT_OFST :
+    case MipsMCExpr::MEK_GOT_OFST:
       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_OFST
-                              : Mips::fixup_Mips_GOT_OFST;
-      break;
-    case MCSymbolRefExpr::VK_Mips_GOT_DISP :
-      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_DISP
-                              : Mips::fixup_Mips_GOT_DISP;
+                                   : Mips::fixup_Mips_GOT_OFST;
       break;
-    case MCSymbolRefExpr::VK_Mips_GPREL:
+    case MipsMCExpr::MEK_GPREL:
       FixupKind = Mips::fixup_Mips_GPREL16;
       break;
-    case MCSymbolRefExpr::VK_Mips_GOT_CALL:
-      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_CALL16
-                              : Mips::fixup_Mips_CALL16;
+    case MipsMCExpr::MEK_LO: {
+      // Check for %lo(%neg(%gp_rel(X)))
+      if (MipsExpr->isGpOff()) {
+        FixupKind = Mips::fixup_Mips_GPOFF_LO;
+        break;
+      }
+      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16
+                                   : Mips::fixup_Mips_LO16;
       break;
-    case MCSymbolRefExpr::VK_Mips_GOT16:
-      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16
-                              : Mips::fixup_Mips_GOT_Global;
+    }
+    case MipsMCExpr::MEK_HIGHEST:
+      FixupKind = Mips::fixup_Mips_HIGHEST;
       break;
-    case MCSymbolRefExpr::VK_Mips_GOT:
-      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16
-                              : Mips::fixup_Mips_GOT_Local;
+    case MipsMCExpr::MEK_HIGHER:
+      FixupKind = Mips::fixup_Mips_HIGHER;
       break;
-    case MCSymbolRefExpr::VK_Mips_ABS_HI:
+    case MipsMCExpr::MEK_HI:
+      // Check for %hi(%neg(%gp_rel(X)))
+      if (MipsExpr->isGpOff()) {
+        FixupKind = Mips::fixup_Mips_GPOFF_HI;
+        break;
+      }
       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16
-                              : Mips::fixup_Mips_HI16;
+                                   : Mips::fixup_Mips_HI16;
       break;
-    case MCSymbolRefExpr::VK_Mips_ABS_LO:
-      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16
-                              : Mips::fixup_Mips_LO16;
+    case MipsMCExpr::MEK_PCREL_HI16:
+      FixupKind = Mips::fixup_MIPS_PCHI16;
       break;
-    case MCSymbolRefExpr::VK_Mips_TLSGD:
+    case MipsMCExpr::MEK_PCREL_LO16:
+      FixupKind = Mips::fixup_MIPS_PCLO16;
+      break;
+    case MipsMCExpr::MEK_TLSGD:
       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_GD
-                              : Mips::fixup_Mips_TLSGD;
+                                   : Mips::fixup_Mips_TLSGD;
       break;
-    case MCSymbolRefExpr::VK_Mips_TLSLDM:
+    case MipsMCExpr::MEK_TLSLDM:
       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_LDM
-                              : Mips::fixup_Mips_TLSLDM;
-      break;
-    case MCSymbolRefExpr::VK_Mips_DTPREL_HI:
-      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_HI16
-                              : Mips::fixup_Mips_DTPREL_HI;
-      break;
-    case MCSymbolRefExpr::VK_Mips_DTPREL_LO:
-      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_LO16
-                              : Mips::fixup_Mips_DTPREL_LO;
-      break;
-    case MCSymbolRefExpr::VK_Mips_GOTTPREL:
-      FixupKind = Mips::fixup_Mips_GOTTPREL;
+                                   : Mips::fixup_Mips_TLSLDM;
       break;
-    case MCSymbolRefExpr::VK_Mips_TPREL_HI:
+    case MipsMCExpr::MEK_TPREL_HI:
       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_HI16
-                              : Mips::fixup_Mips_TPREL_HI;
+                                   : Mips::fixup_Mips_TPREL_HI;
       break;
-    case MCSymbolRefExpr::VK_Mips_TPREL_LO:
+    case MipsMCExpr::MEK_TPREL_LO:
       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_LO16
-                              : Mips::fixup_Mips_TPREL_LO;
-      break;
-    case MCSymbolRefExpr::VK_Mips_HIGHER:
-      FixupKind = Mips::fixup_Mips_HIGHER;
+                                   : Mips::fixup_Mips_TPREL_LO;
       break;
-    case MCSymbolRefExpr::VK_Mips_HIGHEST:
-      FixupKind = Mips::fixup_Mips_HIGHEST;
-      break;
-    case MCSymbolRefExpr::VK_Mips_GOT_HI16:
-      FixupKind = Mips::fixup_Mips_GOT_HI16;
-      break;
-    case MCSymbolRefExpr::VK_Mips_GOT_LO16:
-      FixupKind = Mips::fixup_Mips_GOT_LO16;
-      break;
-    case MCSymbolRefExpr::VK_Mips_CALL_HI16:
-      FixupKind = Mips::fixup_Mips_CALL_HI16;
-      break;
-    case MCSymbolRefExpr::VK_Mips_CALL_LO16:
-      FixupKind = Mips::fixup_Mips_CALL_LO16;
-      break;
-    case MCSymbolRefExpr::VK_Mips_PCREL_HI16:
-      FixupKind = Mips::fixup_MIPS_PCHI16;
+    }
+    Fixups.push_back(MCFixup::create(0, MipsExpr, MCFixupKind(FixupKind)));
+    return 0;
+  }
+
+  if (Kind == MCExpr::SymbolRef) {
+    Mips::Fixups FixupKind = Mips::Fixups(0);
+
+    switch(cast<MCSymbolRefExpr>(Expr)->getKind()) {
+    default: llvm_unreachable("Unknown fixup kind!");
       break;
-    case MCSymbolRefExpr::VK_Mips_PCREL_LO16:
-      FixupKind = Mips::fixup_MIPS_PCLO16;
+    case MCSymbolRefExpr::VK_None:
+      FixupKind = Mips::fixup_Mips_32; // FIXME: This is ok for O32/N32 but not N64.
       break;
     } // switch
 
Index: lib/Target/Mips/MCTargetDesc/MipsMCExpr.h
===================================================================
--- lib/Target/Mips/MCTargetDesc/MipsMCExpr.h
+++ lib/Target/Mips/MCTargetDesc/MipsMCExpr.h
@@ -18,49 +18,73 @@
 
 class MipsMCExpr : public MCTargetExpr {
 public:
-  enum VariantKind {
-    VK_Mips_None,
-    VK_Mips_LO,
-    VK_Mips_HI,
-    VK_Mips_HIGHER,
-    VK_Mips_HIGHEST
+  enum MipsExprKind {
+    MEK_None,
+    MEK_CALL_HI16,
+    MEK_CALL_LO16,
+    MEK_DTPREL_HI,
+    MEK_DTPREL_LO,
+    MEK_GOT,
+    MEK_GOTTPREL,
+    MEK_GOT_CALL,
+    MEK_GOT_DISP,
+    MEK_GOT_HI16,
+    MEK_GOT_LO16,
+    MEK_GOT_OFST,
+    MEK_GOT_PAGE,
+    MEK_GPREL,
+    MEK_HI,
+    MEK_HIGHER,
+    MEK_HIGHEST,
+    MEK_LO,
+    MEK_NEG,
+    MEK_PCREL_HI16,
+    MEK_PCREL_LO16,
+    MEK_TLSGD,
+    MEK_TLSLDM,
+    MEK_TPREL_HI,
+    MEK_TPREL_LO,
+    MEK_Special,
   };
 
 private:
-  const VariantKind Kind;
+  const MipsExprKind Kind;
   const MCExpr *Expr;
 
-  explicit MipsMCExpr(VariantKind Kind, const MCExpr *Expr)
-    : Kind(Kind), Expr(Expr) {}
+  explicit MipsMCExpr(MipsExprKind Kind, const MCExpr *Expr)
+      : Kind(Kind), Expr(Expr) {}
 
 public:
-  static bool isSupportedBinaryExpr(MCSymbolRefExpr::VariantKind VK,
-                                    const MCBinaryExpr *BE);
+  static const MipsMCExpr *create(MipsExprKind Kind, const MCExpr *Expr,
+                                  MCContext &Ctx);
+  static const MipsMCExpr *createGpOff(MipsExprKind Kind, const MCExpr *Expr,
+                                       MCContext &Ctx);
 
-  static const MipsMCExpr *create(MCSymbolRefExpr::VariantKind VK,
-                                  const MCExpr *Expr, MCContext &Ctx);
+  /// Get the kind of this expression.
+  MipsExprKind getKind() const { return Kind; }
 
-  /// getOpcode - Get the kind of this expression.
-  VariantKind getKind() const { return Kind; }
-
-  /// getSubExpr - Get the child of this expression.
+  /// Get the child of this expression.
   const MCExpr *getSubExpr() const { return Expr; }
 
   void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;
-  bool evaluateAsRelocatableImpl(MCValue &Res,
-                                 const MCAsmLayout *Layout,
+  bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout,
                                  const MCFixup *Fixup) const override;
   void visitUsedExpr(MCStreamer &Streamer) const override;
   MCFragment *findAssociatedFragment() const override {
     return getSubExpr()->findAssociatedFragment();
   }
 
-  // There are no TLS MipsMCExprs at the moment.
-  void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override {}
+  void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override;
 
   static bool classof(const MCExpr *E) {
     return E->getKind() == MCExpr::Target;
   }
+
+  bool isGpOff(MipsExprKind &Kind) const;
+  bool isGpOff() const {
+    MipsExprKind Kind;
+    return isGpOff(Kind);
+  }
 };
 } // end namespace llvm
 
Index: lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp
===================================================================
--- lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp
+++ lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp
@@ -12,69 +12,110 @@
 #include "llvm/MC/MCAssembler.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCObjectStreamer.h"
+#include "llvm/MC/MCSymbolELF.h"
+#include "llvm/Support/ELF.h"
 
 using namespace llvm;
 
 #define DEBUG_TYPE "mipsmcexpr"
 
-bool MipsMCExpr::isSupportedBinaryExpr(MCSymbolRefExpr::VariantKind VK,
-                                       const MCBinaryExpr *BE) {
-  switch (VK) {
-  case MCSymbolRefExpr::VK_Mips_ABS_LO:
-  case MCSymbolRefExpr::VK_Mips_ABS_HI:
-  case MCSymbolRefExpr::VK_Mips_HIGHER:
-  case MCSymbolRefExpr::VK_Mips_HIGHEST:
-    break;
-  default:
-    return false;
-  }
+const MipsMCExpr *MipsMCExpr::create(MipsMCExpr::MipsExprKind Kind,
+                                     const MCExpr *Expr, MCContext &Ctx) {
+  return new (Ctx) MipsMCExpr(Kind, Expr);
+}
 
-  // We support expressions of the form "(sym1 binop1 sym2) binop2 const",
-  // where "binop2 const" is optional.
-  if (isa<MCBinaryExpr>(BE->getLHS())) {
-    if (!isa<MCConstantExpr>(BE->getRHS()))
-      return false;
-    BE = cast<MCBinaryExpr>(BE->getLHS());
-  }
-  return (isa<MCSymbolRefExpr>(BE->getLHS())
-          && isa<MCSymbolRefExpr>(BE->getRHS()));
+const MipsMCExpr *MipsMCExpr::createGpOff(MipsMCExpr::MipsExprKind Kind,
+                                          const MCExpr *Expr, MCContext &Ctx) {
+  return create(Kind, create(MEK_NEG, create(MEK_GPREL, Expr, Ctx), Ctx), Ctx);
 }
 
-const MipsMCExpr*
-MipsMCExpr::create(MCSymbolRefExpr::VariantKind VK, const MCExpr *Expr,
-                   MCContext &Ctx) {
-  VariantKind Kind;
-  switch (VK) {
-  case MCSymbolRefExpr::VK_Mips_ABS_LO:
-    Kind = VK_Mips_LO;
+void MipsMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
+  int64_t AbsVal;
+
+  switch (Kind) {
+  case MEK_None:
+  case MEK_Special:
+    llvm_unreachable("MEK_None and MEK_Special are invalid");
     break;
-  case MCSymbolRefExpr::VK_Mips_ABS_HI:
-    Kind = VK_Mips_HI;
+  case MEK_CALL_HI16:
+    OS << "%call_hi";
     break;
-  case MCSymbolRefExpr::VK_Mips_HIGHER:
-    Kind = VK_Mips_HIGHER;
+  case MEK_CALL_LO16:
+    OS << "%call_lo";
     break;
-  case MCSymbolRefExpr::VK_Mips_HIGHEST:
-    Kind = VK_Mips_HIGHEST;
+  case MEK_DTPREL_HI:
+    OS << "%dtprel_hi";
+    break;
+  case MEK_DTPREL_LO:
+    OS << "%dtprel_lo";
+    break;
+  case MEK_GOT:
+    OS << "%got";
+    break;
+  case MEK_GOTTPREL:
+    OS << "%gottprel";
+    break;
+  case MEK_GOT_CALL:
+    OS << "%call16";
+    break;
+  case MEK_GOT_DISP:
+    OS << "%got_disp";
+    break;
+  case MEK_GOT_HI16:
+    OS << "%got_hi";
+    break;
+  case MEK_GOT_LO16:
+    OS << "%got_lo";
+    break;
+  case MEK_GOT_PAGE:
+    OS << "%got_page";
+    break;
+  case MEK_GOT_OFST:
+    OS << "%got_ofst";
+    break;
+  case MEK_GPREL:
+    OS << "%gp_rel";
+    break;
+  case MEK_HI:
+    OS << "%hi";
+    break;
+  case MEK_HIGHER:
+    OS << "%higher";
+    break;
+  case MEK_HIGHEST:
+    OS << "%highest";
+    break;
+  case MEK_LO:
+    OS << "%lo";
+    break;
+  case MEK_NEG:
+    OS << "%neg";
+    break;
+  case MEK_PCREL_HI16:
+    OS << "%pcrel_hi";
+    break;
+  case MEK_PCREL_LO16:
+    OS << "%pcrel_lo";
+    break;
+  case MEK_TLSGD:
+    OS << "%tlsgd";
+    break;
+  case MEK_TLSLDM:
+    OS << "%tlsldm";
+    break;
+  case MEK_TPREL_HI:
+    OS << "%tprel_hi";
+    break;
+  case MEK_TPREL_LO:
+    OS << "%tprel_lo";
     break;
-  default:
-    llvm_unreachable("Invalid kind!");
-  }
-
-  return new (Ctx) MipsMCExpr(Kind, Expr);
-}
-
-void MipsMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
-  switch (Kind) {
-  default: llvm_unreachable("Invalid kind!");
-  case VK_Mips_LO: OS << "%lo"; break;
-  case VK_Mips_HI: OS << "%hi"; break;
-  case VK_Mips_HIGHER: OS << "%higher"; break;
-  case VK_Mips_HIGHEST: OS << "%highest"; break;
   }
 
   OS << '(';
-  Expr->print(OS, MAI);
+  if (Expr->evaluateAsAbsolute(AbsVal))
+    OS << AbsVal;
+  else
+    Expr->print(OS, MAI, true);
   OS << ')';
 }
 
@@ -82,9 +123,165 @@
 MipsMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
                                       const MCAsmLayout *Layout,
                                       const MCFixup *Fixup) const {
-  return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup);
+  // Look for the %hi(%neg(%gp_rel(X))) and %lo(%neg(%gp_rel(X))) special cases.
+  if (isGpOff()) {
+    const MCExpr *SubExpr =
+        cast<MipsMCExpr>(cast<MipsMCExpr>(getSubExpr())->getSubExpr())
+            ->getSubExpr();
+    if (!SubExpr->evaluateAsRelocatable(Res, Layout, Fixup))
+      return false;
+
+    Res = MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(),
+                       MEK_Special);
+    return true;
+  }
+
+  if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup))
+    return false;
+
+  if (Res.getRefKind() != MCSymbolRefExpr::VK_None)
+    return false;
+
+  // evaluateAsAbsolute() and evaluateAsValue() require that we evaluate the
+  // %hi/%lo/etc. here. Fixup is a null pointer when either of these is the
+  // caller.
+  if (Res.isAbsolute() && Fixup == nullptr) {
+    int64_t AbsVal = Res.getConstant();
+    switch (Kind) {
+    case MEK_None:
+    case MEK_Special:
+      llvm_unreachable("MEK_None and MEK_Special are invalid");
+    case MEK_DTPREL_HI:
+    case MEK_DTPREL_LO:
+    case MEK_GOT:
+    case MEK_GOTTPREL:
+    case MEK_GOT_CALL:
+    case MEK_GOT_DISP:
+    case MEK_GOT_HI16:
+    case MEK_GOT_LO16:
+    case MEK_GOT_OFST:
+    case MEK_GOT_PAGE:
+    case MEK_GPREL:
+    case MEK_PCREL_HI16:
+    case MEK_PCREL_LO16:
+    case MEK_TLSGD:
+    case MEK_TLSLDM:
+    case MEK_TPREL_HI:
+    case MEK_TPREL_LO:
+      return false;
+    case MEK_LO:
+    case MEK_CALL_LO16:
+      AbsVal = SignExtend64<16>(AbsVal);
+      break;
+    case MEK_CALL_HI16:
+    case MEK_HI:
+      AbsVal = SignExtend64<16>((AbsVal + 0x8000) >> 16);
+      break;
+    case MEK_HIGHER:
+      AbsVal = SignExtend64<16>((AbsVal + 0x80008000LL) >> 32);
+      break;
+    case MEK_HIGHEST:
+      AbsVal = SignExtend64<16>((AbsVal + 0x800080008000LL) >> 48);
+      break;
+    case MEK_NEG:
+      AbsVal = -AbsVal;
+      break;
+    }
+    Res = MCValue::get(AbsVal);
+    return true;
+  }
+
+  // We want to defer it for relocatable expressions since the constant is
+  // applied to the whole symbol value.
+  //
+  // The value of getKind() that is given to MCValue is only intended to aid
+  // debugging when inspecting MCValue objects. It shouldn't be relied upon
+  // for decision making.
+  Res = MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind());
+
+  return true;
 }
 
 void MipsMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
   Streamer.visitUsedExpr(*getSubExpr());
 }
+
+static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
+  switch (Expr->getKind()) {
+  case MCExpr::Target:
+    fixELFSymbolsInTLSFixupsImpl(cast<MipsMCExpr>(Expr)->getSubExpr(), Asm);
+    break;
+  case MCExpr::Constant:
+    break;
+  case MCExpr::Binary: {
+    const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
+    fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
+    fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
+    break;
+  }
+  case MCExpr::SymbolRef: {
+    // We're known to be under a TLS fixup, so any symbol should be
+    // modified. There should be only one.
+    const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
+    cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
+    break;
+  }
+  case MCExpr::Unary:
+    fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
+    break;
+  }
+}
+
+void MipsMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
+  switch (getKind()) {
+  case MEK_None:
+  case MEK_Special:
+    llvm_unreachable("MEK_None and MEK_Special are invalid");
+    break;
+  case MEK_CALL_HI16:
+  case MEK_CALL_LO16:
+  case MEK_DTPREL_HI:
+  case MEK_DTPREL_LO:
+  case MEK_GOT:
+  case MEK_GOT_CALL:
+  case MEK_GOT_DISP:
+  case MEK_GOT_HI16:
+  case MEK_GOT_LO16:
+  case MEK_GOT_OFST:
+  case MEK_GOT_PAGE:
+  case MEK_GPREL:
+  case MEK_HI:
+  case MEK_HIGHER:
+  case MEK_HIGHEST:
+  case MEK_LO:
+  case MEK_NEG:
+  case MEK_PCREL_HI16:
+  case MEK_PCREL_LO16:
+  case MEK_TLSLDM:
+    // If we do have nested target-specific expressions, they will be in
+    // a consecutive chain.
+    if (const MipsMCExpr *E = dyn_cast<const MipsMCExpr>(getSubExpr()))
+      E->fixELFSymbolsInTLSFixups(Asm);
+    break;
+  case MEK_GOTTPREL:
+  case MEK_TLSGD:
+  case MEK_TPREL_HI:
+  case MEK_TPREL_LO:
+    fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
+    break;
+  }
+}
+
+bool MipsMCExpr::isGpOff(MipsExprKind &Kind) const {
+  if (getKind() == MEK_HI || getKind() == MEK_LO) {
+    if (const MipsMCExpr *S1 = dyn_cast<const MipsMCExpr>(getSubExpr())) {
+      if (const MipsMCExpr *S2 = dyn_cast<const MipsMCExpr>(S1->getSubExpr())) {
+        if (S1->getKind() == MEK_NEG && S2->getKind() == MEK_GPREL) {
+          Kind = getKind();
+          return true;
+        }
+      }
+    }
+  }
+  return false;
+}
Index: lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
===================================================================
--- lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
+++ lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
@@ -14,6 +14,7 @@
 #include "MipsTargetStreamer.h"
 #include "InstPrinter/MipsInstPrinter.h"
 #include "MipsELFStreamer.h"
+#include "MipsMCExpr.h"
 #include "MipsMCTargetDesc.h"
 #include "MipsTargetObjectFile.h"
 #include "llvm/MC/MCContext.h"
@@ -966,8 +967,11 @@
   MCInst TmpInst;
   TmpInst.setOpcode(Mips::LUi);
   TmpInst.addOperand(MCOperand::createReg(Mips::GP));
-  const MCSymbolRefExpr *HiSym = MCSymbolRefExpr::create(
-      "_gp_disp", MCSymbolRefExpr::VK_Mips_ABS_HI, MCA.getContext());
+  const MCExpr *HiSym = MipsMCExpr::create(
+      MipsMCExpr::MEK_HI,
+      MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None,
+                              MCA.getContext()),
+      MCA.getContext());
   TmpInst.addOperand(MCOperand::createExpr(HiSym));
   getStreamer().EmitInstruction(TmpInst, STI);
 
@@ -976,8 +980,11 @@
   TmpInst.setOpcode(Mips::ADDiu);
   TmpInst.addOperand(MCOperand::createReg(Mips::GP));
   TmpInst.addOperand(MCOperand::createReg(Mips::GP));
-  const MCSymbolRefExpr *LoSym = MCSymbolRefExpr::create(
-      "_gp_disp", MCSymbolRefExpr::VK_Mips_ABS_LO, MCA.getContext());
+  const MCExpr *LoSym = MipsMCExpr::create(
+      MipsMCExpr::MEK_LO,
+      MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None,
+                              MCA.getContext()),
+      MCA.getContext());
   TmpInst.addOperand(MCOperand::createExpr(LoSym));
   getStreamer().EmitInstruction(TmpInst, STI);
 
@@ -1040,10 +1047,12 @@
   getStreamer().EmitInstruction(Inst, STI);
   Inst.clear();
 
-  const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::create(
-      &Sym, MCSymbolRefExpr::VK_Mips_GPOFF_HI, MCA.getContext());
-  const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::create(
-      &Sym, MCSymbolRefExpr::VK_Mips_GPOFF_LO, MCA.getContext());
+  const MipsMCExpr *HiExpr = MipsMCExpr::createGpOff(
+      MipsMCExpr::MEK_HI, MCSymbolRefExpr::create(&Sym, MCA.getContext()),
+      MCA.getContext());
+  const MipsMCExpr *LoExpr = MipsMCExpr::createGpOff(
+      MipsMCExpr::MEK_LO, MCSymbolRefExpr::create(&Sym, MCA.getContext()),
+      MCA.getContext());
 
   // lui $gp, %hi(%neg(%gp_rel(funcSym)))
   Inst.setOpcode(Mips::LUi);
Index: lib/Target/Mips/MipsISelLowering.cpp
===================================================================
--- lib/Target/Mips/MipsISelLowering.cpp
+++ lib/Target/Mips/MipsISelLowering.cpp
@@ -1742,7 +1742,7 @@
 
   return getAddrGlobal(
       N, SDLoc(N), Ty, DAG,
-      (ABI.IsN32() || ABI.IsN64()) ? MipsII::MO_GOT_DISP : MipsII::MO_GOT16,
+      (ABI.IsN32() || ABI.IsN64()) ? MipsII::MO_GOT_DISP : MipsII::MO_GOT,
       DAG.getEntryNode(), MachinePointerInfo::getGOT(DAG.getMachineFunction()));
 }
 
Index: lib/Target/Mips/MipsMCInstLower.h
===================================================================
--- lib/Target/Mips/MipsMCInstLower.h
+++ lib/Target/Mips/MipsMCInstLower.h
@@ -37,11 +37,10 @@
   MCOperand LowerSymbolOperand(const MachineOperand &MO,
                                MachineOperandType MOTy, unsigned Offset) const;
   MCOperand createSub(MachineBasicBlock *BB1, MachineBasicBlock *BB2,
-                      MCSymbolRefExpr::VariantKind Kind) const;
+                      MipsMCExpr::MipsExprKind Kind) const;
   void lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const;
-  void lowerLongBranchADDiu(const MachineInstr *MI, MCInst &OutMI,
-                            int Opcode,
-                            MCSymbolRefExpr::VariantKind Kind) const;
+  void lowerLongBranchADDiu(const MachineInstr *MI, MCInst &OutMI, int Opcode,
+                            MipsMCExpr::MipsExprKind Kind) const;
   bool lowerLongBranch(const MachineInstr *MI, MCInst &OutMI) const;
 };
 }
Index: lib/Target/Mips/MipsMCInstLower.cpp
===================================================================
--- lib/Target/Mips/MipsMCInstLower.cpp
+++ lib/Target/Mips/MipsMCInstLower.cpp
@@ -36,36 +36,87 @@
 MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
                                               MachineOperandType MOTy,
                                               unsigned Offset) const {
-  MCSymbolRefExpr::VariantKind Kind;
+  MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
+  MipsMCExpr::MipsExprKind TargetKind = MipsMCExpr::MEK_None;
+  bool IsGpOff = false;
   const MCSymbol *Symbol;
 
   switch(MO.getTargetFlags()) {
-  default:                   llvm_unreachable("Invalid target flag!");
-  case MipsII::MO_NO_FLAG:   Kind = MCSymbolRefExpr::VK_None; break;
-  case MipsII::MO_GPREL:     Kind = MCSymbolRefExpr::VK_Mips_GPREL; break;
-  case MipsII::MO_GOT_CALL:  Kind = MCSymbolRefExpr::VK_Mips_GOT_CALL; break;
-  case MipsII::MO_GOT16:     Kind = MCSymbolRefExpr::VK_Mips_GOT16; break;
-  case MipsII::MO_GOT:       Kind = MCSymbolRefExpr::VK_Mips_GOT; break;
-  case MipsII::MO_ABS_HI:    Kind = MCSymbolRefExpr::VK_Mips_ABS_HI; break;
-  case MipsII::MO_ABS_LO:    Kind = MCSymbolRefExpr::VK_Mips_ABS_LO; break;
-  case MipsII::MO_TLSGD:     Kind = MCSymbolRefExpr::VK_Mips_TLSGD; break;
-  case MipsII::MO_TLSLDM:    Kind = MCSymbolRefExpr::VK_Mips_TLSLDM; break;
-  case MipsII::MO_DTPREL_HI: Kind = MCSymbolRefExpr::VK_Mips_DTPREL_HI; break;
-  case MipsII::MO_DTPREL_LO: Kind = MCSymbolRefExpr::VK_Mips_DTPREL_LO; break;
-  case MipsII::MO_GOTTPREL:  Kind = MCSymbolRefExpr::VK_Mips_GOTTPREL; break;
-  case MipsII::MO_TPREL_HI:  Kind = MCSymbolRefExpr::VK_Mips_TPREL_HI; break;
-  case MipsII::MO_TPREL_LO:  Kind = MCSymbolRefExpr::VK_Mips_TPREL_LO; break;
-  case MipsII::MO_GPOFF_HI:  Kind = MCSymbolRefExpr::VK_Mips_GPOFF_HI; break;
-  case MipsII::MO_GPOFF_LO:  Kind = MCSymbolRefExpr::VK_Mips_GPOFF_LO; break;
-  case MipsII::MO_GOT_DISP:  Kind = MCSymbolRefExpr::VK_Mips_GOT_DISP; break;
-  case MipsII::MO_GOT_PAGE:  Kind = MCSymbolRefExpr::VK_Mips_GOT_PAGE; break;
-  case MipsII::MO_GOT_OFST:  Kind = MCSymbolRefExpr::VK_Mips_GOT_OFST; break;
-  case MipsII::MO_HIGHER:    Kind = MCSymbolRefExpr::VK_Mips_HIGHER; break;
-  case MipsII::MO_HIGHEST:   Kind = MCSymbolRefExpr::VK_Mips_HIGHEST; break;
-  case MipsII::MO_GOT_HI16:  Kind = MCSymbolRefExpr::VK_Mips_GOT_HI16; break;
-  case MipsII::MO_GOT_LO16:  Kind = MCSymbolRefExpr::VK_Mips_GOT_LO16; break;
-  case MipsII::MO_CALL_HI16: Kind = MCSymbolRefExpr::VK_Mips_CALL_HI16; break;
-  case MipsII::MO_CALL_LO16: Kind = MCSymbolRefExpr::VK_Mips_CALL_LO16; break;
+  default:
+    llvm_unreachable("Invalid target flag!");
+  case MipsII::MO_NO_FLAG:
+    break;
+  case MipsII::MO_GPREL:
+    TargetKind = MipsMCExpr::MEK_GPREL;
+    break;
+  case MipsII::MO_GOT_CALL:
+    TargetKind = MipsMCExpr::MEK_GOT_CALL;
+    break;
+  case MipsII::MO_GOT:
+    TargetKind = MipsMCExpr::MEK_GOT;
+    break;
+  case MipsII::MO_ABS_HI:
+    TargetKind = MipsMCExpr::MEK_HI;
+    break;
+  case MipsII::MO_ABS_LO:
+    TargetKind = MipsMCExpr::MEK_LO;
+    break;
+  case MipsII::MO_TLSGD:
+    TargetKind = MipsMCExpr::MEK_TLSGD;
+    break;
+  case MipsII::MO_TLSLDM:
+    TargetKind = MipsMCExpr::MEK_TLSLDM;
+    break;
+  case MipsII::MO_DTPREL_HI:
+    TargetKind = MipsMCExpr::MEK_DTPREL_HI;
+    break;
+  case MipsII::MO_DTPREL_LO:
+    TargetKind = MipsMCExpr::MEK_DTPREL_LO;
+    break;
+  case MipsII::MO_GOTTPREL:
+    TargetKind = MipsMCExpr::MEK_GOTTPREL;
+    break;
+  case MipsII::MO_TPREL_HI:
+    TargetKind = MipsMCExpr::MEK_TPREL_HI;
+    break;
+  case MipsII::MO_TPREL_LO:
+    TargetKind = MipsMCExpr::MEK_TPREL_LO;
+    break;
+  case MipsII::MO_GPOFF_HI:
+    TargetKind = MipsMCExpr::MEK_HI;
+    IsGpOff = true;
+    break;
+  case MipsII::MO_GPOFF_LO:
+    TargetKind = MipsMCExpr::MEK_LO;
+    IsGpOff = true;
+    break;
+  case MipsII::MO_GOT_DISP:
+    TargetKind = MipsMCExpr::MEK_GOT_DISP;
+    break;
+  case MipsII::MO_GOT_HI16:
+    TargetKind = MipsMCExpr::MEK_GOT_HI16;
+    break;
+  case MipsII::MO_GOT_LO16:
+    TargetKind = MipsMCExpr::MEK_GOT_LO16;
+    break;
+  case MipsII::MO_GOT_PAGE:
+    TargetKind = MipsMCExpr::MEK_GOT_PAGE;
+    break;
+  case MipsII::MO_GOT_OFST:
+    TargetKind = MipsMCExpr::MEK_GOT_OFST;
+    break;
+  case MipsII::MO_HIGHER:
+    TargetKind = MipsMCExpr::MEK_HIGHER;
+    break;
+  case MipsII::MO_HIGHEST:
+    TargetKind = MipsMCExpr::MEK_HIGHEST;
+    break;
+  case MipsII::MO_CALL_HI16:
+    TargetKind = MipsMCExpr::MEK_CALL_HI16;
+    break;
+  case MipsII::MO_CALL_LO16:
+    TargetKind = MipsMCExpr::MEK_CALL_LO16;
+    break;
   }
 
   switch (MOTy) {
@@ -106,30 +157,23 @@
     llvm_unreachable("<unknown operand type>");
   }
 
-  const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Symbol, Kind, *Ctx);
+  const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, *Ctx);
 
-  if (!Offset)
-    return MCOperand::createExpr(MCSym);
+  if (Offset) {
+    // Assume offset is never negative.
+    assert(Offset > 0);
 
-  // Assume offset is never negative.
-  assert(Offset > 0);
+    Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx),
+                                   *Ctx);
+  }
 
-  const MCConstantExpr *OffsetExpr =  MCConstantExpr::create(Offset, *Ctx);
-  const MCBinaryExpr *Add = MCBinaryExpr::createAdd(MCSym, OffsetExpr, *Ctx);
-  return MCOperand::createExpr(Add);
-}
+  if (IsGpOff)
+    Expr = MipsMCExpr::createGpOff(TargetKind, Expr, *Ctx);
+  else if (TargetKind != MipsMCExpr::MEK_None)
+    Expr = MipsMCExpr::create(TargetKind, Expr, *Ctx);
 
-/*
-static void CreateMCInst(MCInst& Inst, unsigned Opc, const MCOperand &Opnd0,
-                         const MCOperand &Opnd1,
-                         const MCOperand &Opnd2 = MCOperand()) {
-  Inst.setOpcode(Opc);
-  Inst.addOperand(Opnd0);
-  Inst.addOperand(Opnd1);
-  if (Opnd2.isValid())
-    Inst.addOperand(Opnd2);
+  return MCOperand::createExpr(Expr);
 }
-*/
 
 MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO,
                                         unsigned offset) const {
@@ -160,7 +204,7 @@
 
 MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1,
                                      MachineBasicBlock *BB2,
-                                     MCSymbolRefExpr::VariantKind Kind) const {
+                                     MipsMCExpr::MipsExprKind Kind) const {
   const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::create(BB1->getSymbol(), *Ctx);
   const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::create(BB2->getSymbol(), *Ctx);
   const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Sym1, Sym2, *Ctx);
@@ -178,12 +222,12 @@
   // Create %hi($tgt-$baltgt).
   OutMI.addOperand(createSub(MI->getOperand(1).getMBB(),
                              MI->getOperand(2).getMBB(),
-                             MCSymbolRefExpr::VK_Mips_ABS_HI));
+                             MipsMCExpr::MEK_HI));
 }
 
-void MipsMCInstLower::
-lowerLongBranchADDiu(const MachineInstr *MI, MCInst &OutMI, int Opcode,
-                     MCSymbolRefExpr::VariantKind Kind) const {
+void MipsMCInstLower::lowerLongBranchADDiu(
+    const MachineInstr *MI, MCInst &OutMI, int Opcode,
+    MipsMCExpr::MipsExprKind Kind) const {
   OutMI.setOpcode(Opcode);
 
   // Lower two register operands.
@@ -206,17 +250,14 @@
     lowerLongBranchLUi(MI, OutMI);
     return true;
   case Mips::LONG_BRANCH_ADDiu:
-    lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu,
-                         MCSymbolRefExpr::VK_Mips_ABS_LO);
+    lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu, MipsMCExpr::MEK_LO);
     return true;
   case Mips::LONG_BRANCH_DADDiu:
     unsigned TargetFlags = MI->getOperand(2).getTargetFlags();
     if (TargetFlags == MipsII::MO_ABS_HI)
-      lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu,
-                           MCSymbolRefExpr::VK_Mips_ABS_HI);
+      lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu, MipsMCExpr::MEK_HI);
     else if (TargetFlags == MipsII::MO_ABS_LO)
-      lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu,
-                           MCSymbolRefExpr::VK_Mips_ABS_LO);
+      lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu, MipsMCExpr::MEK_LO);
     else
       report_fatal_error("Unexpected flags for LONG_BRANCH_DADDiu");
     return true;
Index: test/MC/Mips/cprestore-noreorder.s
===================================================================
--- test/MC/Mips/cprestore-noreorder.s
+++ test/MC/Mips/cprestore-noreorder.s
@@ -44,9 +44,9 @@
 # CHECK: lw    $gp, 8($sp)         # encoding: [0x8f,0xbc,0x00,0x08]
 
 # CHECK: lw    $25, %got(foo)($gp) # encoding: [0x8f,0x99,A,A]
-# CHECK:                           #   fixup A - offset: 0, value: foo@GOT, kind: fixup_Mips_GOT_Local
+# CHECK:                           #   fixup A - offset: 0, value: %got(foo), kind: fixup_Mips_GOT
 # CHECK: addiu $25, $25, %lo(foo)  # encoding: [0x27,0x39,A,A]
-# CHECK:                           #   fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_Mips_LO16
+# CHECK:                           #   fixup A - offset: 0, value: %lo(foo), kind: fixup_Mips_LO16
 # CHECK: jalr  $25                 # encoding: [0x03,0x20,0xf8,0x09]
 # CHECK: nop                       # encoding: [0x00,0x00,0x00,0x00]
 # CHECK: lw    $gp, 8($sp)         # encoding: [0x8f,0xbc,0x00,0x08]
@@ -62,9 +62,9 @@
 # MICROMIPS: lw      $gp, 8($sp)         # encoding: [0xff,0x9d,0x00,0x08]
 
 # MICROMIPS: lw      $25, %got(foo)($gp) # encoding: [0xff,0x3c,A,A]
-# MICROMIPS:                             #   fixup A - offset: 0, value: foo@GOT, kind: fixup_MICROMIPS_GOT16
+# MICROMIPS:                             #   fixup A - offset: 0, value: %got(foo), kind: fixup_MICROMIPS_GOT16
 # MICROMIPS: addiu   $25, $25, %lo(foo)  # encoding: [0x33,0x39,A,A]
-# MICROMIPS:                             #   fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_MICROMIPS_LO16
+# MICROMIPS:                             #   fixup A - offset: 0, value: %lo(foo), kind: fixup_MICROMIPS_LO16
 # MICROMIPS: jalrs   $ra, $25            # encoding: [0x03,0xf9,0x4f,0x3c]
 # MICROMIPS: nop                         # encoding: [0x0c,0x00]
 # MICROMIPS: lw      $gp, 8($sp)         # encoding: [0xff,0x9d,0x00,0x08]
@@ -91,7 +91,7 @@
 
 # BAD-ABI-N32: lw    $25, %got_disp(foo)($gp) # encoding: [0x8f,0x99,A,A]
 # BAD-ABI-N64: ld    $25, %got_disp(foo)($gp) # encoding: [0xdf,0x99,A,A]
-# BAD-ABI:                                    #   fixup A - offset: 0, value: foo@GOT_DISP, kind: fixup_Mips_GOT_DISP
+# BAD-ABI:                                    #   fixup A - offset: 0, value: %got_disp(foo), kind: fixup_Mips_GOT_DISP
 # BAD-ABI:     jalr  $25                      # encoding: [0x03,0x20,0xf8,0x09]
 # BAD-ABI-NOT: lw    $gp, 8($sp)              # encoding: [0x8f,0xbc,0x00,0x08]
 # BAD-ABI:  .end  foo
Index: test/MC/Mips/cprestore-reorder.s
===================================================================
--- test/MC/Mips/cprestore-reorder.s
+++ test/MC/Mips/cprestore-reorder.s
@@ -45,9 +45,9 @@
 # CHECK: lw    $gp, 8($sp)         # encoding: [0x8f,0xbc,0x00,0x08]
 
 # CHECK: lw    $25, %got(foo)($gp) # encoding: [0x8f,0x99,A,A]
-# CHECK:                           #   fixup A - offset: 0, value: foo@GOT, kind: fixup_Mips_GOT_Local
+# CHECK:                           #   fixup A - offset: 0, value: %got(foo), kind: fixup_Mips_GOT
 # CHECK: addiu $25, $25, %lo(foo)  # encoding: [0x27,0x39,A,A]
-# CHECK:                           #   fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_Mips_LO16
+# CHECK:                           #   fixup A - offset: 0, value: %lo(foo), kind: fixup_Mips_LO16
 # CHECK: jalr  $25                 # encoding: [0x03,0x20,0xf8,0x09]
 # CHECK: nop                       # encoding: [0x00,0x00,0x00,0x00]
 # CHECK: lw    $gp, 8($sp)         # encoding: [0x8f,0xbc,0x00,0x08]
@@ -63,9 +63,9 @@
 # MICROMIPS: lw      $gp, 8($sp)         # encoding: [0xff,0x9d,0x00,0x08]
 
 # MICROMIPS: lw      $25, %got(foo)($gp) # encoding: [0xff,0x3c,A,A]
-# MICROMIPS:                             #   fixup A - offset: 0, value: foo@GOT, kind: fixup_MICROMIPS_GOT16
+# MICROMIPS:                             #   fixup A - offset: 0, value: %got(foo), kind: fixup_MICROMIPS_GOT16
 # MICROMIPS: addiu   $25, $25, %lo(foo)  # encoding: [0x33,0x39,A,A]
-# MICROMIPS:                             #   fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_MICROMIPS_LO16
+# MICROMIPS:                             #   fixup A - offset: 0, value: %lo(foo), kind: fixup_MICROMIPS_LO16
 # MICROMIPS: jalrs   $ra, $25            # encoding: [0x03,0xf9,0x4f,0x3c]
 # MICROMIPS: nop                         # encoding: [0x0c,0x00]
 # MICROMIPS: lw      $gp, 8($sp)         # encoding: [0xff,0x9d,0x00,0x08]
@@ -92,7 +92,7 @@
 
 # BAD-ABI-N32: lw    $25, %got_disp(foo)($gp) # encoding: [0x8f,0x99,A,A]
 # BAD-ABI-N64: ld    $25, %got_disp(foo)($gp) # encoding: [0xdf,0x99,A,A]
-# BAD-ABI:                                    #   fixup A - offset: 0, value: foo@GOT_DISP, kind: fixup_Mips_GOT_DISP
+# BAD-ABI:                                    #   fixup A - offset: 0, value: %got_disp(foo), kind: fixup_Mips_GOT_DISP
 # BAD-ABI:     jalr  $25                      # encoding: [0x03,0x20,0xf8,0x09]
 # BAD-ABI-NOT: lw    $gp, 8($sp)              # encoding: [0x8f,0xbc,0x00,0x08]
 # BAD-ABI:     .end  foo
Index: test/MC/Mips/expansion-jal-sym-pic.s
===================================================================
--- test/MC/Mips/expansion-jal-sym-pic.s
+++ test/MC/Mips/expansion-jal-sym-pic.s
@@ -51,26 +51,26 @@
 
 # Expanding "jal local_label":
 # O32: lw     $25, %got(local_label)($gp)   # encoding: [0x8f,0x99,A,A]
-# O32:                                      #   fixup A - offset: 0, value: local_label@GOT, kind:   fixup_Mips_GOT_Local
+# O32:                                      #   fixup A - offset: 0, value: %got(local_label), kind:   fixup_Mips_GOT
 # O32: addiu  $25, $25, %lo(local_label)    # encoding: [0x27,0x39,A,A]
-# O32:                                      #   fixup A - offset: 0, value: local_label@ABS_LO, kind:   fixup_Mips_LO16
+# O32:                                      #   fixup A - offset: 0, value: %lo(local_label), kind:   fixup_Mips_LO16
 
 # N32: lw  $25, %got_disp(local_label)($gp) # encoding: [0x8f,0x99,A,A]
-# N32:                                      #   fixup A - offset: 0, value: local_label@GOT_DISP, kind:   fixup_Mips_GOT_DISP
+# N32:                                      #   fixup A - offset: 0, value: %got_disp(local_label), kind:   fixup_Mips_GOT_DISP
 
 # N64: ld  $25, %got_disp(local_label)($gp) # encoding: [0xdf,0x99,A,A]
-# N64:                                      #   fixup A - offset: 0, value: local_label@GOT_DISP, kind:   fixup_Mips_GOT_DISP
+# N64:                                      #   fixup A - offset: 0, value: %got_disp(local_label), kind:   fixup_Mips_GOT_DISP
 
 # O32-MICROMIPS: lw    $25, %got(local_label)($gp)      # encoding: [0xff,0x3c,A,A]
-# O32-MICROMIPS:                                        #   fixup A - offset: 0, value: local_label@GOT, kind:   fixup_MICROMIPS_GOT16
+# O32-MICROMIPS:                                        #   fixup A - offset: 0, value: %got(local_label), kind:   fixup_MICROMIPS_GOT16
 # O32-MICROMIPS: addiu $25, $25, %lo(local_label)       # encoding: [0x33,0x39,A,A]
-# O32-MICROMIPS:                                        #   fixup A - offset: 0, value: local_label@ABS_LO, kind:   fixup_MICROMIPS_LO16
+# O32-MICROMIPS:                                        #   fixup A - offset: 0, value: %lo(local_label), kind:   fixup_MICROMIPS_LO16
 
 # N32-MICROMIPS: lw    $25, %got_disp(local_label)($gp) # encoding: [0xff,0x3c,A,A]
-# N32-MICROMIPS:                                        #   fixup A - offset: 0, value: local_label@GOT_DISP, kind: fixup_MICROMIPS_GOT_DISP
+# N32-MICROMIPS:                                        #   fixup A - offset: 0, value: %got_disp(local_label), kind: fixup_MICROMIPS_GOT_DISP
 
 # N64-MICROMIPS: ld    $25, %got_disp(local_label)($gp) # encoding: [0xdf,0x99,A,A]
-# N64-MICROMIPS:                                        #   fixup A - offset: 0, value: local_label@GOT_DISP, kind: fixup_MICROMIPS_GOT_DISP
+# N64-MICROMIPS:                                        #   fixup A - offset: 0, value: %got_disp(local_label), kind: fixup_MICROMIPS_GOT_DISP
 
 # NORMAL:    jalr $25      # encoding: [0x03,0x20,0xf8,0x09]
 # MICROMIPS: jalr $ra, $25 # encoding: [0x03,0xf9,0x0f,0x3c]
@@ -79,22 +79,22 @@
 
 # Expanding "jal weak_label":
 # O32: lw  $25, %call16(weak_label)($gp) # encoding: [0x8f,0x99,A,A]
-# O32:                                   #   fixup A - offset: 0, value: weak_label@GOT_CALL, kind:   fixup_Mips_CALL16
+# O32:                                   #   fixup A - offset: 0, value: %call16(weak_label), kind:   fixup_Mips_CALL16
 
 # N32: lw  $25, %call16(weak_label)($gp) # encoding: [0x8f,0x99,A,A]
-# N32:                                   #   fixup A - offset: 0, value: weak_label@GOT_CALL, kind:   fixup_Mips_CALL16
+# N32:                                   #   fixup A - offset: 0, value: %call16(weak_label), kind:   fixup_Mips_CALL16
 
 # N64: ld  $25, %call16(weak_label)($gp) # encoding: [0xdf,0x99,A,A]
-# N64:                                   #   fixup A - offset: 0, value: weak_label@GOT_CALL, kind:   fixup_Mips_CALL16
+# N64:                                   #   fixup A - offset: 0, value: %call16(weak_label), kind:   fixup_Mips_CALL16
 
 # O32-MICROMIPS: lw  $25, %call16(weak_label)($gp) # encoding: [0xff,0x3c,A,A]
-# O32-MICROMIPS:                                   #   fixup A - offset: 0, value: weak_label@GOT_CALL, kind:   fixup_MICROMIPS_CALL16
+# O32-MICROMIPS:                                   #   fixup A - offset: 0, value: %call16(weak_label), kind:   fixup_MICROMIPS_CALL16
 
 # N32-MICROMIPS: lw  $25, %call16(weak_label)($gp) # encoding: [0xff,0x3c,A,A]
-# N32-MICROMIPS:                                   #   fixup A - offset: 0, value: weak_label@GOT_CALL, kind: fixup_MICROMIPS_CALL16
+# N32-MICROMIPS:                                   #   fixup A - offset: 0, value: %call16(weak_label), kind: fixup_MICROMIPS_CALL16
 
 # N64-MICROMIPS: ld  $25, %call16(weak_label)($gp) # encoding: [0xdf,0x99,A,A]
-# N64-MICROMIPS:                                   #   fixup A - offset: 0, value: weak_label@GOT_CALL, kind: fixup_MICROMIPS_CALL16
+# N64-MICROMIPS:                                   #   fixup A - offset: 0, value: %call16(weak_label), kind: fixup_MICROMIPS_CALL16
 
 # NORMAL:    jalr $25      # encoding: [0x03,0x20,0xf8,0x09]
 # MICROMIPS: jalr $ra, $25 # encoding: [0x03,0xf9,0x0f,0x3c]
@@ -103,22 +103,22 @@
 
 # Expanding "jal global_label":
 # O32: lw  $25, %call16(global_label)($gp) # encoding: [0x8f,0x99,A,A]
-# O32:                                     #   fixup A - offset: 0, value: global_label@GOT_CALL, kind:   fixup_Mips_CALL16
+# O32:                                     #   fixup A - offset: 0, value: %call16(global_label), kind:   fixup_Mips_CALL16
 
 # N32: lw  $25, %call16(global_label)($gp) # encoding: [0x8f,0x99,A,A]
-# N32:                                     #   fixup A - offset: 0, value: global_label@GOT_CALL, kind:   fixup_Mips_CALL16
+# N32:                                     #   fixup A - offset: 0, value: %call16(global_label), kind:   fixup_Mips_CALL16
 
 # N64: ld  $25, %call16(global_label)($gp) # encoding: [0xdf,0x99,A,A]
-# N64:                                     #   fixup A - offset: 0, value: global_label@GOT_CALL, kind:   fixup_Mips_CALL16
+# N64:                                     #   fixup A - offset: 0, value: %call16(global_label), kind:   fixup_Mips_CALL16
 
 # O32-MICROMIPS: lw  $25, %call16(global_label)($gp) # encoding: [0xff,0x3c,A,A]
-# O32-MICROMIPS:                                     #   fixup A - offset: 0, value: global_label@GOT_CALL, kind: fixup_MICROMIPS_CALL16
+# O32-MICROMIPS:                                     #   fixup A - offset: 0, value: %call16(global_label), kind: fixup_MICROMIPS_CALL16
 
 # N32-MICROMIPS: lw  $25, %call16(global_label)($gp) # encoding: [0xff,0x3c,A,A]
-# N32-MICROMIPS:                                     #   fixup A - offset: 0, value: global_label@GOT_CALL, kind: fixup_MICROMIPS_CALL16
+# N32-MICROMIPS:                                     #   fixup A - offset: 0, value: %call16(global_label), kind: fixup_MICROMIPS_CALL16
 
 # N64-MICROMIPS: ld  $25, %call16(global_label)($gp) # encoding: [0xdf,0x99,A,A]
-# N64-MICROMIPS:                                     #   fixup A - offset: 0, value: global_label@GOT_CALL, kind: fixup_MICROMIPS_CALL16
+# N64-MICROMIPS:                                     #   fixup A - offset: 0, value: %call16(global_label), kind: fixup_MICROMIPS_CALL16
 
 # NORMAL:    jalr $25      # encoding: [0x03,0x20,0xf8,0x09]
 # MICROMIPS: jalr $ra, $25 # encoding: [0x03,0xf9,0x0f,0x3c]
@@ -129,26 +129,26 @@
 # it is created when generating an ELF object file.
 # Expanding "jal .text":
 # O32-FIXME: lw    $25, %got(.text)($gp)           # encoding: [0x8f,0x99,A,A]
-# O32-FIXME:                                       #   fixup A - offset: 0, value: .text@GOT, kind: fixup_Mips_GOT_Local
+# O32-FIXME:                                       #   fixup A - offset: 0, value: %got(.text), kind: fixup_Mips_GOT
 # O32-FIXME: addiu $25, $25, %lo(.text)            # encoding: [0x27,0x39,A,A]
-# O32-FIXME:                                       #   fixup A - offset: 0, value: .text@ABS_LO, kind: fixup_Mips_LO16
+# O32-FIXME:                                       #   fixup A - offset: 0, value: %lo(.text), kind: fixup_Mips_LO16
 
 # N32-FIXME: lw  $25, %got_disp(.text)($gp)        # encoding: [0x8f,0x99,A,A]
-# N32-FIXME:                                       #   fixup A - offset: 0, value: .text@GOT_DISP, kind: fixup_Mips_GOT_DISP
+# N32-FIXME:                                       #   fixup A - offset: 0, value: %got_disp(.text), kind: fixup_Mips_GOT_DISP
 
 # N64-FIXME: ld  $25, %got_disp(.text)($gp)        # encoding: [0xdf,0x99,A,A]
-# N64-FIXME:                                       #   fixup A - offset: 0, value: .text@GOT_DISP, kind: fixup_Mips_GOT_DISP
+# N64-FIXME:                                       #   fixup A - offset: 0, value: %got_disp(.text), kind: fixup_Mips_GOT_DISP
 
 # O32-MICROMIPS-FIXME: lw    $25, %got(.text)($gp)      # encoding: [0xff,0x3c,A,A]
-# O32-MICROMIPS-FIXME:                                  #   fixup A - offset: 0, value: .text@GOT, kind: fixup_MICROMIPS_GOT16
+# O32-MICROMIPS-FIXME:                                  #   fixup A - offset: 0, value: %got(.text), kind: fixup_MICROMIPS_GOT16
 # O32-MICROMIPS-FIXME: addiu $25, $25, %lo(.text)       # encoding: [0x33,0x39,A,A]
-# O32-MICROMIPS-FIXME:                                  #   fixup A - offset: 0, value: .text@ABS_LO, kind: fixup_MICROMIPS_LO16
+# O32-MICROMIPS-FIXME:                                  #   fixup A - offset: 0, value: %lo(.text), kind: fixup_MICROMIPS_LO16
 
 # N32-MICROMIPS-FIXME: lw    $25, %got_disp(.text)($gp) # encoding: [0xff,0x3c,A,A]
-# N32-MICROMIPS-FIXME:                                  #   fixup A - offset: 0, value: .text@GOT_DISP, kind: fixup_MICROMIPS_GOT_DISP
+# N32-MICROMIPS-FIXME:                                  #   fixup A - offset: 0, value: %got_disp(.text), kind: fixup_MICROMIPS_GOT_DISP
 
 # N64-MICROMIPS-FIXME: ld    $25, %got_disp(.text)($gp) # encoding: [0xdf,0x99,A,A]
-# N64-MICROMIPS-FIXME:                                  #   fixup A - offset: 0, value: .text@GOT_DISP, kind: fixup_MICROMIPS_GOT_DISP
+# N64-MICROMIPS-FIXME:                                  #   fixup A - offset: 0, value: %got_disp(.text), kind: fixup_MICROMIPS_GOT_DISP
 
 # NORMAL:    jalr $25      # encoding: [0x03,0x20,0xf8,0x09]
 # MICROMIPS: jalr $ra, $25 # encoding: [0x03,0xf9,0x0f,0x3c]
@@ -157,26 +157,26 @@
 
 # Expanding "jal 1f":
 # O32: lw     $25, %got($tmp0)($gp)   # encoding: [0x8f,0x99,A,A]
-# O32:                                #   fixup A - offset: 0, value: ($tmp0)@GOT, kind:   fixup_Mips_GOT_Local
+# O32:                                #   fixup A - offset: 0, value: %got($tmp0), kind:   fixup_Mips_GOT
 # O32: addiu  $25, $25, %lo($tmp0)    # encoding: [0x27,0x39,A,A]
-# O32:                                #   fixup A - offset: 0, value: ($tmp0)@ABS_LO, kind:   fixup_Mips_LO16
+# O32:                                #   fixup A - offset: 0, value: %lo($tmp0), kind:   fixup_Mips_LO16
 
 # N32: lw  $25, %got_disp($tmp0)($gp) # encoding: [0x8f,0x99,A,A]
-# N32:                                #   fixup A - offset: 0, value: ($tmp0)@GOT_DISP, kind:   fixup_Mips_GOT_DISP
+# N32:                                #   fixup A - offset: 0, value: %got_disp($tmp0), kind:   fixup_Mips_GOT_DISP
 
 # N64: ld  $25, %got_disp($tmp0)($gp) # encoding: [0xdf,0x99,A,A]
-# N64:                                #   fixup A - offset: 0, value: ($tmp0)@GOT_DISP, kind:   fixup_Mips_GOT_DISP
+# N64:                                #   fixup A - offset: 0, value: %got_disp($tmp0), kind:   fixup_Mips_GOT_DISP
 
 # O32-MICROMIPS: lw    $25, %got($tmp0)($gp)    # encoding: [0xff,0x3c,A,A]
-# O32-MICROMIPS:                                #   fixup A - offset: 0, value: ($tmp0)@GOT, kind: fixup_MICROMIPS_GOT16
+# O32-MICROMIPS:                                #   fixup A - offset: 0, value: %got($tmp0), kind: fixup_MICROMIPS_GOT16
 # O32-MICROMIPS: addiu $25, $25, %lo($tmp0)     # encoding: [0x33,0x39,A,A]
-# O32-MICROMIPS:                                #   fixup A - offset: 0, value: ($tmp0)@ABS_LO, kind: fixup_MICROMIPS_LO16
+# O32-MICROMIPS:                                #   fixup A - offset: 0, value: %lo($tmp0), kind: fixup_MICROMIPS_LO16
 
 # N32-MICROMIPS: lw  $25, %got_disp($tmp0)($gp) # encoding: [0xff,0x3c,A,A]
-# N32-MICROMIPS:                                #   fixup A - offset: 0, value: ($tmp0)@GOT_DISP, kind: fixup_MICROMIPS_GOT_DISP
+# N32-MICROMIPS:                                #   fixup A - offset: 0, value: %got_disp($tmp0), kind: fixup_MICROMIPS_GOT_DISP
 
 # N64-MICROMIPS: ld  $25, %got_disp($tmp0)($gp) # encoding: [0xdf,0x99,A,A]
-# N64-MICROMIPS:                                #   fixup A - offset: 0, value: ($tmp0)@GOT_DISP, kind: fixup_MICROMIPS_GOT_DISP
+# N64-MICROMIPS:                                #   fixup A - offset: 0, value: %got_disp($tmp0), kind: fixup_MICROMIPS_GOT_DISP
 
 # NORMAL:    jalr $25      # encoding: [0x03,0x20,0xf8,0x09]
 # MICROMIPS: jalr $ra, $25 # encoding: [0x03,0xf9,0x0f,0x3c]
Index: test/MC/Mips/expr1.s
===================================================================
--- test/MC/Mips/expr1.s
+++ test/MC/Mips/expr1.s
@@ -8,38 +8,38 @@
 # 32R2-EL: .globl  foo
 # 32R2-EL: foo:
 # 32R2-EL: lw   $4, %lo(foo)($4)       # encoding: [A,A,0x84,0x8c]
-# 32R2-EL:                             #   fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_Mips_LO16
+# 32R2-EL:                             #   fixup A - offset: 0, value: %lo(foo), kind: fixup_Mips_LO16
 # 32R2-EL: lw   $4, 56($4)             # encoding: [0x38,0x00,0x84,0x8c]
-# 32R2-EL: lw   $4, %lo(foo+8)($4)     # encoding: [0x08'A',A,0x84,0x8c]
-# 32R2-EL:                             #   fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_Mips_LO16
-# 32R2-EL: lw   $4, %lo(foo+8)($4)     # encoding: [0x08'A',A,0x84,0x8c]
-# 32R2-EL:                             #   fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_Mips_LO16
-# 32R2-EL: lw   $4, %lo(foo+8)($4)     # encoding: [0x08'A',A,0x84,0x8c]
-# 32R2-EL:                             #   fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_Mips_LO16
+# 32R2-EL: lw   $4, %lo(8+foo)($4)     # encoding: [A,A,0x84,0x8c]
+# 32R2-EL:                             #   fixup A - offset: 0, value: %lo(8+foo), kind: fixup_Mips_LO16
+# 32R2-EL: lw   $4, %lo(8+foo)($4)     # encoding: [A,A,0x84,0x8c]
+# 32R2-EL:                             #   fixup A - offset: 0, value: %lo(8+foo), kind: fixup_Mips_LO16
+# 32R2-EL: lw   $4, %lo(8+foo)($4)     # encoding: [A,A,0x84,0x8c]
+# 32R2-EL:                             #   fixup A - offset: 0, value: %lo(8+foo), kind: fixup_Mips_LO16
 # 32R2-EL: lw   $4, 10($4)             # encoding: [0x0a,0x00,0x84,0x8c]
 # 32R2-EL: lw   $4, 15($4)             # encoding: [0x0f,0x00,0x84,0x8c]
 # 32R2-EL: lw   $4, 21($4)             # encoding: [0x15,0x00,0x84,0x8c]
 # 32R2-EL: lw   $4, 28($4)             # encoding: [0x1c,0x00,0x84,0x8c]
-# 32R2-EL: lw   $4, 6($4)              # encoding: [0x06,0x00,0x84,0x8c]
+# 32R2-EL: lw   $4, %lo(65542)($4)     # encoding: [0x06,0x00,0x84,0x8c]
 # 32R2-EL: .space  64
 
 # MM-32R2-EL: .text
 # MM-32R2-EL: .globl  foo
 # MM-32R2-EL: foo:
-# MM-32R2-EL: lw   $4, %lo(foo)($4)    # encoding: [0x84'A',0xfc'A',0x00,0x00]
-# MM-32R2-EL:                          #   fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_MICROMIPS_LO16
-# MM-32R2-EL: lw   $4, 56($4)          # encoding: [0x84,0xfc,0x38,0x00]
-# MM-32R2-EL: lw   $4, %lo(foo+8)($4)  # encoding: [0x84'A',0xfc'A',0x08,0x00]
-# MM-32R2-EL:                          #   fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_MICROMIPS_LO16
-# MM-32R2-EL: lw   $4, %lo(foo+8)($4)  # encoding: [0x84'A',0xfc'A',0x08,0x00]
-# MM-32R2-EL:                          #   fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_MICROMIPS_LO16
-# MM-32R2-EL: lw   $4, %lo(foo+8)($4)  # encoding: [0x84'A',0xfc'A',0x08,0x00]
-# MM-32R2-EL:                          #   fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_MICROMIPS_LO16
-# MM-32R2-EL: lw   $4, 10($4)          # encoding: [0x84,0xfc,0x0a,0x00]
-# MM-32R2-EL: lw   $4, 15($4)          # encoding: [0x84,0xfc,0x0f,0x00]
-# MM-32R2-EL: lw   $4, 21($4)          # encoding: [0x84,0xfc,0x15,0x00]
-# MM-32R2-EL: lw   $4, 28($4)          # encoding: [0x84,0xfc,0x1c,0x00]
-# MM-32R2-EL: lw   $4, 6($4)           # encoding: [0x84,0xfc,0x06,0x00]
+# MM-32R2-EL: lw   $4, %lo(foo)($4)     # encoding: [0x84'A',0xfc'A',0x00,0x00]
+# MM-32R2-EL:                           #   fixup A - offset: 0, value: %lo(foo), kind: fixup_MICROMIPS_LO16
+# MM-32R2-EL: lw   $4, 56($4)           # encoding: [0x84,0xfc,0x38,0x00]
+# MM-32R2-EL: lw   $4, %lo(8+foo)($4)   # encoding: [0x84'A',0xfc'A',0x00,0x00]
+# MM-32R2-EL:                           #   fixup A - offset: 0, value: %lo(8+foo), kind: fixup_MICROMIPS_LO16
+# MM-32R2-EL: lw   $4, %lo(8+foo)($4)   # encoding: [0x84'A',0xfc'A',0x00,0x00]
+# MM-32R2-EL:                           #   fixup A - offset: 0, value: %lo(8+foo), kind: fixup_MICROMIPS_LO16
+# MM-32R2-EL: lw   $4, %lo(8+foo)($4)   # encoding: [0x84'A',0xfc'A',0x00,0x00]
+# MM-32R2-EL:                           #   fixup A - offset: 0, value: %lo(8+foo), kind: fixup_MICROMIPS_LO16
+# MM-32R2-EL: lw   $4, 10($4)           # encoding: [0x84,0xfc,0x0a,0x00]
+# MM-32R2-EL: lw   $4, 15($4)           # encoding: [0x84,0xfc,0x0f,0x00]
+# MM-32R2-EL: lw   $4, 21($4)           # encoding: [0x84,0xfc,0x15,0x00]
+# MM-32R2-EL: lw   $4, 28($4)           # encoding: [0x84,0xfc,0x1c,0x00]
+# MM-32R2-EL: lw   $4, %lo(65542)($4)   # encoding: [0x84,0xfc,0x06,0x00]
 # MM-32R2-EL: .space  64
 
   .globl  foo
Index: test/MC/Mips/macro-la.s
===================================================================
--- test/MC/Mips/macro-la.s
+++ test/MC/Mips/macro-la.s
@@ -272,8 +272,8 @@
                       # CHECK: addiu $1, $1, %lo(symbol+8) # encoding: [0x24,0x21,A,A]
                       # CHECK:                             #   fixup A - offset: 0, value: %lo(symbol+8), kind: fixup_Mips_LO16
                       # CHECK: addu $6, $1, $6             # encoding: [0x00,0x26,0x30,0x21]
-la $5, 1f             # CHECK: lui $5, %hi(($tmp0))        # encoding: [0x3c,0x05,A,A]
-                      # CHECK:                             #   fixup A - offset: 0, value: %hi(($tmp0)), kind: fixup_Mips_HI16
-                      # CHECK: addiu $5, $5, %lo(($tmp0))  # encoding: [0x24,0xa5,A,A]
-                      # CHECK:                             #   fixup A - offset: 0, value: %lo(($tmp0)), kind: fixup_Mips_LO16
+la $5, 1f             # CHECK: lui $5, %hi($tmp0)          # encoding: [0x3c,0x05,A,A]
+                      # CHECK:                             #   fixup A - offset: 0, value: %hi($tmp0), kind: fixup_Mips_HI16
+                      # CHECK: addiu $5, $5, %lo($tmp0)    # encoding: [0x24,0xa5,A,A]
+                      # CHECK:                             #   fixup A - offset: 0, value: %lo($tmp0), kind: fixup_Mips_LO16
 1:
Index: test/MC/Mips/micromips-expansions.s
===================================================================
--- test/MC/Mips/micromips-expansions.s
+++ test/MC/Mips/micromips-expansions.s
@@ -18,21 +18,21 @@
 # CHECK: addu  $7, $7, $8            # encoding: [0x07,0x01,0x50,0x39]
 # CHECK: lui   $10, %hi(symbol)      # encoding: [0xaa'A',0x41'A',0x00,0x00]
 # CHECK:                             # fixup A - offset: 0,
-# CHECK:                               value: symbol@ABS_HI,
+# CHECK:                               value: %hi(symbol),
 # CHECK:                               kind: fixup_MICROMIPS_HI16
 # CHECK: addu  $10, $10, $4          # encoding: [0x8a,0x00,0x50,0x51]
 # CHECK: lw    $10, %lo(symbol)($10) # encoding: [0x4a'A',0xfd'A',0x00,0x00]
 # CHECK:                             # fixup A - offset: 0,
-# CHECK:                               value: symbol@ABS_LO,
+# CHECK:                               value: %lo(symbol),
 # CHECK:                               kind: fixup_MICROMIPS_LO16
 # CHECK: lui   $1, %hi(symbol)       # encoding: [0xa1'A',0x41'A',0x00,0x00]
 # CHECK:                             # fixup A - offset: 0,
-# CHECK:                               value: symbol@ABS_HI,
+# CHECK:                               value: %hi(symbol),
 # CHECK:                               kind: fixup_MICROMIPS_HI16
 # CHECK: addu  $1, $1, $9            # encoding: [0x21,0x01,0x50,0x09]
 # CHECK: sw    $10, %lo(symbol)($1)  # encoding: [0x41'A',0xf9'A',0x00,0x00]
 # CHECK:                             # fixup A - offset: 0,
-# CHECK:                               value: symbol@ABS_LO,
+# CHECK:                               value: %lo(symbol),
 # CHECK:                               kind: fixup_MICROMIPS_LO16
 # CHECK: lui   $10, 10               # encoding: [0xaa,0x41,0x0a,0x00]
 # CHECK: addu  $10, $10, $4          # encoding: [0x8a,0x00,0x50,0x51]
Index: test/MC/Mips/micromips-relocations.s
===================================================================
--- test/MC/Mips/micromips-relocations.s
+++ test/MC/Mips/micromips-relocations.s
@@ -10,71 +10,71 @@
 # CHECK-FIXUP: lui $2, %hi(_gp_disp)
 # CHECK-FIXUP:        # encoding: [0xa2'A',0x41'A',0x00,0x00]
 # CHECK-FIXUP:        # fixup A - offset: 0,
-# CHECK-FIXUP:          value: _gp_disp@ABS_HI,
+# CHECK-FIXUP:          value: %hi(_gp_disp),
 # CHECK-FIXUP:          kind: fixup_MICROMIPS_HI16
 # CHECK-FIXUP: addiu $2, $2, %lo(_gp_disp)
 # CHECK-FIXUP:        # encoding: [0x42'A',0x30'A',0x00,0x00]
 # CHECK-FIXUP:        # fixup A - offset: 0,
-# CHECK-FIXUP:          value: _gp_disp@ABS_LO,
+# CHECK-FIXUP:          value: %lo(_gp_disp),
 # CHECK-FIXUP:          kind: fixup_MICROMIPS_LO16
 # CHECK-FIXUP: lw $25, %call16(strchr)($gp)
 # CHECK-FIXUP:        # encoding: [0x3c'A',0xff'A',0x00,0x00]
 # CHECK-FIXUP:        # fixup A - offset: 0,
-# CHECK-FIXUP:          value: strchr@GOT_CALL,
+# CHECK-FIXUP:          value: %call16(strchr),
 # CHECK-FIXUP:          kind: fixup_MICROMIPS_CALL16
 # CHECK-FIXUP: lw $3, %got(loop_1)($2)
 # CHECK-FIXUP:        # encoding: [0x62'A',0xfc'A',0x00,0x00]
 # CHECK-FIXUP:        # fixup A - offset: 0,
-# CHECK-FIXUP:          value: loop_1@GOT,
+# CHECK-FIXUP:          value: %got(loop_1),
 # CHECK-FIXUP:          kind: fixup_MICROMIPS_GOT16
 # CHECK-FIXUP: lui $2, %dtprel_hi(_gp_disp)
 # CHECK-FIXUP:        # encoding: [0xa2'A',0x41'A',0x00,0x00]
 # CHECK-FIXUP:        # fixup A - offset: 0,
-# CHECK-FIXUP:          value: _gp_disp@DTPREL_HI,
+# CHECK-FIXUP:          value: %dtprel_hi(_gp_disp),
 # CHECK-FIXUP:          kind: fixup_MICROMIPS_TLS_DTPREL_HI16
 # CHECK-FIXUP: addiu $2, $2, %dtprel_lo(_gp_disp)
 # CHECK-FIXUP:        # encoding: [0x42'A',0x30'A',0x00,0x00]
 # CHECK-FIXUP:        # fixup A - offset: 0,
-# CHECK-FIXUP:          value: _gp_disp@DTPREL_LO,
+# CHECK-FIXUP:          value: %dtprel_lo(_gp_disp),
 # CHECK-FIXUP:          kind: fixup_MICROMIPS_TLS_DTPREL_LO16
 # CHECK-FIXUP: lw $3, %got(loop_1)($2)
 # CHECK-FIXUP:        # encoding: [0x62'A',0xfc'A',0x00,0x00]
 # CHECK-FIXUP:        # fixup A - offset: 0,
-# CHECK-FIXUP:          value: loop_1@GOT,
+# CHECK-FIXUP:          value: %got(loop_1),
 # CHECK-FIXUP:          kind: fixup_MICROMIPS_GOT16
 # CHECK-FIXUP: lw $4, %got_disp(loop_2)($3)
 # CHECK-FIXUP:        # encoding: [0x83'A',0xfc'A',0x00,0x00]
 # CHECK-FIXUP:        # fixup A - offset: 0,
-# CHECK-FIXUP:          value: loop_2@GOT_DISP,
+# CHECK-FIXUP:          value: %got_disp(loop_2),
 # CHECK-FIXUP:          kind: fixup_MICROMIPS_GOT_DISP
 # CHECK-FIXUP: lw $5, %got_page(loop_3)($4)
 # CHECK-FIXUP:        # encoding: [0xa4'A',0xfc'A',0x00,0x00]
 # CHECK-FIXUP:        # fixup A - offset: 0,
-# CHECK-FIXUP:          value: loop_3@GOT_PAGE,
+# CHECK-FIXUP:          value: %got_page(loop_3),
 # CHECK-FIXUP:          kind: fixup_MICROMIPS_GOT_PAGE
 # CHECK-FIXUP: lw $6, %got_ofst(loop_4)($5)
 # CHECK-FIXUP:        # encoding: [0xc5'A',0xfc'A',0x00,0x00]
 # CHECK-FIXUP:        # fixup A - offset: 0,
-# CHECK-FIXUP:          value: loop_4@GOT_OFST,
+# CHECK-FIXUP:          value: %got_ofst(loop_4),
 # CHECK-FIXUP:          kind: fixup_MICROMIPS_GOT_OFST
 # CHECK-FIXUP: lui $2, %tprel_hi(_gp_disp)
 # CHECK-FIXUP:        # encoding: [0xa2'A',0x41'A',0x00,0x00]
 # CHECK-FIXUP:        # fixup A - offset: 0,
-# CHECK-FIXUP:          value: _gp_disp@TPREL_HI,
+# CHECK-FIXUP:          value: %tprel_hi(_gp_disp),
 # CHECK-FIXUP:          kind: fixup_MICROMIPS_TLS_TPREL_HI16
 # CHECK-FIXUP: addiu $2, $2, %tprel_lo(_gp_disp)
 # CHECK-FIXUP:        # encoding: [0x42'A',0x30'A',0x00,0x00]
 # CHECK-FIXUP:        # fixup A - offset: 0,
-# CHECK-FIXUP:          value: _gp_disp@TPREL_LO,
+# CHECK-FIXUP:          value: %tprel_lo(_gp_disp),
 # CHECK-FIXUP:          kind: fixup_MICROMIPS_TLS_TPREL_LO16
 # CHECK-FIXUP: addiu $4, $gp, %tlsgd(a)
 # CHECK-FIXUP:        # encoding: [0x9c'A',0x30'A',0x00,0x00]
 # CHECK-FIXUP:        # fixup A - offset: 0,
-# CHECK-FIXUP:          value: a@TLSGD, kind: fixup_MICROMIPS_TLS_GD
+# CHECK-FIXUP:          value: %tlsgd(a), kind: fixup_MICROMIPS_TLS_GD
 # CHECK-FIXUP: addiu $4, $gp, %tlsldm(f.i)
 # CHECK-FIXUP:        # encoding: [0x9c'A',0x30'A',0x00,0x00]
 # CHECK-FIXUP:        # fixup A - offset: 0,
-# CHECK-FIXUP:          value: f.i@TLSLDM, kind: fixup_MICROMIPS_TLS_LDM
+# CHECK-FIXUP:          value: %tlsldm(f.i), kind: fixup_MICROMIPS_TLS_LDM
 #------------------------------------------------------------------------------
 # Check that the appropriate relocations were created.
 #------------------------------------------------------------------------------
Index: test/MC/Mips/mips-expansions.s
===================================================================
--- test/MC/Mips/mips-expansions.s
+++ test/MC/Mips/mips-expansions.s
@@ -8,37 +8,37 @@
 # Load address, done by MipsAsmParser::expandLoadAddressReg()
 # and MipsAsmParser::expandLoadAddressImm():
   la $8, 1f
-# CHECK-LE: lui     $8, %hi(($tmp0))      # encoding: [A,A,0x08,0x3c]
-# CHECK-LE:                             #   fixup A - offset: 0, value: %hi(($tmp0)), kind: fixup_Mips_HI16
-# CHECK-LE: addiu   $8, $8, %lo(($tmp0))  # encoding: [A,A,0x08,0x25]
-# CHECK-LE:                             #   fixup A - offset: 0, value: %lo(($tmp0)), kind: fixup_Mips_LO16
+# CHECK-LE: lui     $8, %hi($tmp0)        # encoding: [A,A,0x08,0x3c]
+# CHECK-LE:                               #   fixup A - offset: 0, value: %hi($tmp0), kind: fixup_Mips_HI16
+# CHECK-LE: addiu   $8, $8, %lo($tmp0)    # encoding: [A,A,0x08,0x25]
+# CHECK-LE:                               #   fixup A - offset: 0, value: %lo($tmp0), kind: fixup_Mips_LO16
 
 # LW/SW and LDC1/SDC1 of symbol address, done by MipsAsmParser::expandMemInst():
   .set noat
   lw $10, symbol($4)
 # CHECK-LE: lui     $10, %hi(symbol)        # encoding: [A,A,0x0a,0x3c]
-# CHECK-LE:                                 #   fixup A - offset: 0, value: symbol@ABS_HI, kind: fixup_Mips_HI16
+# CHECK-LE:                                 #   fixup A - offset: 0, value: %hi(symbol), kind: fixup_Mips_HI16
 # CHECK-LE: addu    $10, $10, $4            # encoding: [0x21,0x50,0x44,0x01]
 # CHECK-LE: lw      $10, %lo(symbol)($10)   # encoding: [A,A,0x4a,0x8d]
-# CHECK-LE:                                 #   fixup A - offset: 0, value: symbol@ABS_LO, kind: fixup_Mips_LO16
+# CHECK-LE:                                 #   fixup A - offset: 0, value: %lo(symbol), kind: fixup_Mips_LO16
   .set at
   sw $10, symbol($9)
 # CHECK-LE: lui     $1, %hi(symbol)         # encoding: [A,A,0x01,0x3c]
-# CHECK-LE:                                 #   fixup A - offset: 0, value: symbol@ABS_HI, kind: fixup_Mips_HI16
+# CHECK-LE:                                 #   fixup A - offset: 0, value: %hi(symbol), kind: fixup_Mips_HI16
 # CHECK-LE: addu    $1, $1, $9              # encoding: [0x21,0x08,0x29,0x00]
 # CHECK-LE: sw      $10, %lo(symbol)($1)    # encoding: [A,A,0x2a,0xac]
-# CHECK-LE:                                 #   fixup A - offset: 0, value: symbol@ABS_LO, kind: fixup_Mips_LO16
+# CHECK-LE:                                 #   fixup A - offset: 0, value: %lo(symbol), kind: fixup_Mips_LO16
 
   lw $8, 1f
 # CHECK-LE: lui $8, %hi($tmp0)              # encoding: [A,A,0x08,0x3c]
-# CHECK-LE:                                 #   fixup A - offset: 0, value: ($tmp0)@ABS_HI, kind: fixup_Mips_HI16
+# CHECK-LE:                                 #   fixup A - offset: 0, value: %hi($tmp0), kind: fixup_Mips_HI16
 # CHECK-LE: lw  $8, %lo($tmp0)($8)          # encoding: [A,A,0x08,0x8d]
-# CHECK-LE:                                 #   fixup A - offset: 0, value: ($tmp0)@ABS_LO, kind: fixup_Mips_LO16
+# CHECK-LE:                                 #   fixup A - offset: 0, value: %lo($tmp0), kind: fixup_Mips_LO16
   sw $8, 1f
 # CHECK-LE: lui $1, %hi($tmp0)              # encoding: [A,A,0x01,0x3c]
-# CHECK-LE:                                 #   fixup A - offset: 0, value: ($tmp0)@ABS_HI, kind: fixup_Mips_HI16
+# CHECK-LE:                                 #   fixup A - offset: 0, value: %hi($tmp0), kind: fixup_Mips_HI16
 # CHECK-LE: sw  $8, %lo($tmp0)($1)          # encoding: [A,A,0x28,0xac]
-# CHECK-LE:                                 #   fixup A - offset: 0, value: ($tmp0)@ABS_LO, kind: fixup_Mips_LO16
+# CHECK-LE:                                 #   fixup A - offset: 0, value: %lo($tmp0), kind: fixup_Mips_LO16
 
   lw $10, 655483($4)
 # CHECK-LE: lui     $10, 10                 # encoding: [0x0a,0x00,0x0a,0x3c]
@@ -51,16 +51,16 @@
 
   lw $8, symbol
 # CHECK-LE:     lui     $8, %hi(symbol)     # encoding: [A,A,0x08,0x3c]
-# CHECK-LE:                                 #   fixup A - offset: 0, value: symbol@ABS_HI, kind: fixup_Mips_HI16
+# CHECK-LE:                                 #   fixup A - offset: 0, value: %hi(symbol), kind: fixup_Mips_HI16
 # CHECK-LE-NOT: move    $8, $8              # encoding: [0x21,0x40,0x00,0x01]
 # CHECK-LE:     lw      $8, %lo(symbol)($8) # encoding: [A,A,0x08,0x8d]
-# CHECK-LE:                                 #   fixup A - offset: 0, value: symbol@ABS_LO, kind: fixup_Mips_LO16
+# CHECK-LE:                                 #   fixup A - offset: 0, value: %lo(symbol), kind: fixup_Mips_LO16
   sw $8, symbol
 # CHECK-LE:     lui     $1, %hi(symbol)     # encoding: [A,A,0x01,0x3c]
-# CHECK-LE:                                 #   fixup A - offset: 0, value: symbol@ABS_HI, kind: fixup_Mips_HI16
+# CHECK-LE:                                 #   fixup A - offset: 0, value: %hi(symbol), kind: fixup_Mips_HI16
 # CHECK-LE-NOT: move    $1, $1              # encoding: [0x21,0x08,0x20,0x00]
 # CHECK-LE:     sw      $8, %lo(symbol)($1) # encoding: [A,A,0x28,0xac]
-# CHECK-LE:                                 #   fixup A - offset: 0, value: symbol@ABS_LO, kind: fixup_Mips_LO16
+# CHECK-LE:                                 #   fixup A - offset: 0, value: %lo(symbol), kind: fixup_Mips_LO16
 
   ldc1 $f0, symbol
 # CHECK-LE: lui     $1, %hi(symbol)
Index: test/MC/Mips/mips32r6/relocations.s
===================================================================
--- test/MC/Mips/mips32r6/relocations.s
+++ test/MC/Mips/mips32r6/relocations.s
@@ -28,11 +28,11 @@
 # CHECK-FIXUP:                      value: bar-4, kind: fixup_MIPS_PC26_S2
 # CHECK-FIXUP: aluipc $2, %pcrel_hi(bar)    # encoding: [0xec,0x5f,A,A]
 # CHECK-FIXUP:                              #   fixup A - offset: 0,
-# CHECK-FIXUP:                                  value: bar@PCREL_HI16,
+# CHECK-FIXUP:                                  value: %pcrel_hi(bar),
 # CHECK-FIXUP:                                  kind: fixup_MIPS_PCHI16
 # CHECK-FIXUP: addiu $2, $2, %pcrel_lo(bar) # encoding: [0x24,0x42,A,A]
 # CHECK-FIXUP:                              #   fixup A - offset: 0,
-# CHECK-FIXUP:                                  value: bar@PCREL_LO16,
+# CHECK-FIXUP:                                  value: %pcrel_lo(bar),
 # CHECK-FIXUP:                                  kind: fixup_MIPS_PCLO16
 # CHECK-FIXUP: lwpc    $2, bar  # encoding: [0xec,0b01001AAA,A,A]
 # CHECK-FIXUP:                  #   fixup A - offset: 0,
Index: test/MC/Mips/mips64r6/relocations.s
===================================================================
--- test/MC/Mips/mips64r6/relocations.s
+++ test/MC/Mips/mips64r6/relocations.s
@@ -28,11 +28,11 @@
 # CHECK-FIXUP:                      value: bar-4, kind: fixup_MIPS_PC26_S2
 # CHECK-FIXUP: aluipc $2, %pcrel_hi(bar)    # encoding: [0xec,0x5f,A,A]
 # CHECK-FIXUP:                              #   fixup A - offset: 0,
-# CHECK-FIXUP:                                  value: bar@PCREL_HI16,
+# CHECK-FIXUP:                                  value: %pcrel_hi(bar),
 # CHECK-FIXUP:                                  kind: fixup_MIPS_PCHI16
 # CHECK-FIXUP: addiu $2, $2, %pcrel_lo(bar) # encoding: [0x24,0x42,A,A]
 # CHECK-FIXUP:                              #   fixup A - offset: 0,
-# CHECK-FIXUP:                                  value: bar@PCREL_LO16,
+# CHECK-FIXUP:                                  value: %pcrel_lo(bar),
 # CHECK-FIXUP:                                  kind: fixup_MIPS_PCLO16
 # CHECK-FIXUP: ldpc    $2, bar  # encoding: [0xec,0b010110AA,A,A]
 # CHECK-FIXUP:                  # fixup A - offset: 0,
Index: test/MC/Mips/mips_directives.s
===================================================================
--- test/MC/Mips/mips_directives.s
+++ test/MC/Mips/mips_directives.s
@@ -54,7 +54,7 @@
     .set f6,$f6
 # CHECK:    abs.s   $f6, $f7           # encoding: [0x46,0x00,0x39,0x85]
 # CHECK:    lui     $1, %hi($tmp7)     # encoding: [0x3c,0x01,A,A]
-# CHECK:                               #   fixup A - offset: 0, value: ($tmp7)@ABS_HI, kind: fixup_Mips_HI16
+# CHECK:                               #   fixup A - offset: 0, value: %hi($tmp7), kind: fixup_Mips_HI16
     abs.s  f6,FPU_MASK
     lui $1, %hi($tmp7)
 
Index: test/MC/Mips/relocation.s
===================================================================
--- test/MC/Mips/relocation.s
+++ test/MC/Mips/relocation.s
@@ -31,31 +31,31 @@
         addiu $2, $3, %hi(foo)             // RELOC: R_MIPS_HI16 foo
                                            // ENCBE: addiu $2, $3, %hi(foo) # encoding: [0x24,0x62,A,A]
                                            // ENCLE: addiu $2, $3, %hi(foo) # encoding: [A,A,0x62,0x24]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@ABS_HI, kind: fixup_Mips_HI16
+                                           // FIXUP: # fixup A - offset: 0, value: %hi(foo), kind: fixup_Mips_HI16
 
         addiu $2, $3, %lo(foo)             // RELOC: R_MIPS_LO16 foo
                                            // ENCBE: addiu $2, $3, %lo(foo) # encoding: [0x24,0x62,A,A]
                                            // ENCLE: addiu $2, $3, %lo(foo) # encoding: [A,A,0x62,0x24]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_Mips_LO16
+                                           // FIXUP: # fixup A - offset: 0, value: %lo(foo), kind: fixup_Mips_LO16
 
         addiu $2, $3, %gp_rel(foo)         // RELOC: R_MIPS_GPREL16 foo
                                            // ENCBE: addiu $2, $3, %gp_rel(foo) # encoding: [0x24,0x62,A,A]
                                            // ENCLE: addiu $2, $3, %gp_rel(foo) # encoding: [A,A,0x62,0x24]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@GPREL, kind: fixup_Mips_GPREL
+                                           // FIXUP: # fixup A - offset: 0, value: %gp_rel(foo), kind: fixup_Mips_GPREL
 
                                            // ?????: R_MIPS_LITERAL foo
 
         addiu $2, $3, %got(foo)            // RELOC: R_MIPS_GOT16 foo
                                            // ENCBE: addiu $2, $3, %got(foo) # encoding: [0x24,0x62,A,A]
                                            // ENCLE: addiu $2, $3, %got(foo) # encoding: [A,A,0x62,0x24]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@GOT, kind: fixup_Mips_GOT_Local
+                                           // FIXUP: # fixup A - offset: 0, value: %got(foo), kind: fixup_Mips_GOT
 
         .short foo-.                       // RELOC: R_MIPS_PC16 foo
 
         addiu $2, $3, %call16(foo)         // RELOC: R_MIPS_CALL16 foo
                                            // ENCBE: addiu $2, $3, %call16(foo) # encoding: [0x24,0x62,A,A]
                                            // ENCLE: addiu $2, $3, %call16(foo) # encoding: [A,A,0x62,0x24]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@GOT_CALL, kind: fixup_Mips_CALL16
+                                           // FIXUP: # fixup A - offset: 0, value: %call16(foo), kind: fixup_Mips_CALL16
 
         .quad foo                          // RELOC: R_MIPS_64 foo
 
@@ -69,27 +69,27 @@
         addiu $2, $3, %got_disp(foo)       // RELOC: R_MIPS_GOT_DISP foo
                                            // ENCBE: addiu $2, $3, %got_disp(foo) # encoding: [0x24,0x62,A,A]
                                            // ENCLE: addiu $2, $3, %got_disp(foo) # encoding: [A,A,0x62,0x24]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@GOT_DISP, kind: fixup_Mips_GOT_DISP
+                                           // FIXUP: # fixup A - offset: 0, value: %got_disp(foo), kind: fixup_Mips_GOT_DISP
 
         addiu $2, $3, %got_page(foo)       // RELOC: R_MIPS_GOT_PAGE foo
                                            // ENCBE: addiu $2, $3, %got_page(foo) # encoding: [0x24,0x62,A,A]
                                            // ENCLE: addiu $2, $3, %got_page(foo) # encoding: [A,A,0x62,0x24]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@GOT_PAGE, kind: fixup_Mips_GOT_PAGE
+                                           // FIXUP: # fixup A - offset: 0, value: %got_page(foo), kind: fixup_Mips_GOT_PAGE
 
         addiu $2, $3, %got_ofst(foo)       // RELOC: R_MIPS_GOT_OFST foo
                                            // ENCBE: addiu $2, $3, %got_ofst(foo) # encoding: [0x24,0x62,A,A]
                                            // ENCLE: addiu $2, $3, %got_ofst(foo) # encoding: [A,A,0x62,0x24]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@GOT_OFST, kind: fixup_Mips_GOT_OFST
+                                           // FIXUP: # fixup A - offset: 0, value: %got_ofst(foo), kind: fixup_Mips_GOT_OFST
 
         addiu $2, $3, %got_hi(foo)         // RELOC: R_MIPS_GOT_HI16 foo
                                            // ENCBE: addiu $2, $3, %got_hi(foo) # encoding: [0x24,0x62,A,A]
                                            // ENCLE: addiu $2, $3, %got_hi(foo) # encoding: [A,A,0x62,0x24]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@GOT_HI16, kind: fixup_Mips_GOT_HI16
+                                           // FIXUP: # fixup A - offset: 0, value: %got_hi(foo), kind: fixup_Mips_GOT_HI16
 
         addiu $2, $3, %got_lo(foo)         // RELOC: R_MIPS_GOT_LO16 foo
                                            // ENCBE: addiu $2, $3, %got_lo(foo) # encoding: [0x24,0x62,A,A]
                                            // ENCLE: addiu $2, $3, %got_lo(foo) # encoding: [A,A,0x62,0x24]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@GOT_LO16, kind: fixup_Mips_GOT_LO16
+                                           // FIXUP: # fixup A - offset: 0, value: %got_lo(foo), kind: fixup_Mips_GOT_LO16
 
 //      addiu $2, $3, %neg(foo)            // FIXME: R_MIPS_SUB foo
                                            // ?????: R_MIPS_INSERT_A
@@ -100,23 +100,23 @@
         daddiu $2, $3, %higher(foo)        // RELOC: R_MIPS_HIGHER foo
                                            // ENCBE: daddiu $2, $3, %higher(foo) # encoding: [0x64,0x62,A,A]
                                            // ENCLE: daddiu $2, $3, %higher(foo) # encoding: [A,A,0x62,0x64]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@HIGHER, kind: fixup_Mips_HIGHER
+                                           // FIXUP: # fixup A - offset: 0, value: %higher(foo), kind: fixup_Mips_HIGHER
 
         daddiu $2, $3, %highest(foo)       // RELOC: R_MIPS_HIGHEST foo
                                            // ENCBE: daddiu $2, $3, %highest(foo) # encoding: [0x64,0x62,A,A]
                                            // ENCLE: daddiu $2, $3, %highest(foo) # encoding: [A,A,0x62,0x64]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@HIGHEST, kind: fixup_Mips_HIGHEST
+                                           // FIXUP: # fixup A - offset: 0, value: %highest(foo), kind: fixup_Mips_HIGHEST
 
         .set mips0
         addiu $2, $3, %call_hi(foo)        // RELOC: R_MIPS_CALL_HI16 foo
                                            // ENCBE: addiu $2, $3, %call_hi(foo) # encoding: [0x24,0x62,A,A]
                                            // ENCLE: addiu $2, $3, %call_hi(foo) # encoding: [A,A,0x62,0x24]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@CALL_HI16, kind: fixup_Mips_CALL_HI16
+                                           // FIXUP: # fixup A - offset: 0, value: %call_hi(foo), kind: fixup_Mips_CALL_HI16
 
         addiu $2, $3, %call_lo(foo)        // RELOC: R_MIPS_CALL_LO16 foo
                                            // ENCBE: addiu $2, $3, %call_lo(foo) # encoding: [0x24,0x62,A,A]
                                            // ENCLE: addiu $2, $3, %call_lo(foo) # encoding: [A,A,0x62,0x24]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@CALL_LO16, kind: fixup_Mips_CALL_LO16
+                                           // FIXUP: # fixup A - offset: 0, value: %call_lo(foo), kind: fixup_Mips_CALL_LO16
 
                                            // ?????: R_MIPS_SCN_DISP foo
                                            // ?????: R_MIPS_REL16 foo
@@ -132,39 +132,39 @@
         addiu $2, $3, %tlsgd(foo)          // RELOC: R_MIPS_TLS_GD foo
                                            // ENCBE: addiu $2, $3, %tlsgd(foo) # encoding: [0x24,0x62,A,A]
                                            // ENCLE: addiu $2, $3, %tlsgd(foo) # encoding: [A,A,0x62,0x24]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@TLSGD, kind: fixup_Mips_TLSGD
+                                           // FIXUP: # fixup A - offset: 0, value: %tlsgd(foo), kind: fixup_Mips_TLSGD
 
         addiu $2, $3, %tlsldm(foo)         // RELOC: R_MIPS_TLS_LDM foo
                                            // ENCBE: addiu $2, $3, %tlsldm(foo) # encoding: [0x24,0x62,A,A]
                                            // ENCLE: addiu $2, $3, %tlsldm(foo) # encoding: [A,A,0x62,0x24]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@TLSLDM, kind: fixup_Mips_TLSLDM
+                                           // FIXUP: # fixup A - offset: 0, value: %tlsldm(foo), kind: fixup_Mips_TLSLDM
 
         addiu $2, $3, %dtprel_hi(foo)      // RELOC: R_MIPS_TLS_DTPREL_HI16 foo
                                            // ENCBE: addiu $2, $3, %dtprel_hi(foo) # encoding: [0x24,0x62,A,A]
                                            // ENCLE: addiu $2, $3, %dtprel_hi(foo) # encoding: [A,A,0x62,0x24]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@DTPREL_HI, kind: fixup_Mips_DTPREL_HI
+                                           // FIXUP: # fixup A - offset: 0, value: %dtprel_hi(foo), kind: fixup_Mips_DTPREL_HI
 
         addiu $2, $3, %dtprel_lo(foo)      // RELOC: R_MIPS_TLS_DTPREL_LO16 foo
                                            // ENCBE: addiu $2, $3, %dtprel_lo(foo) # encoding: [0x24,0x62,A,A]
                                            // ENCLE: addiu $2, $3, %dtprel_lo(foo) # encoding: [A,A,0x62,0x24]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@DTPREL_LO, kind: fixup_Mips_DTPREL_LO
+                                           // FIXUP: # fixup A - offset: 0, value: %dtprel_lo(foo), kind: fixup_Mips_DTPREL_LO
 
         addiu $2, $3, %gottprel(foo)       // RELOC: R_MIPS_TLS_GOTTPREL foo
                                            // ENCBE: addiu $2, $3, %gottprel(foo) # encoding: [0x24,0x62,A,A]
                                            // ENCLE: addiu $2, $3, %gottprel(foo) # encoding: [A,A,0x62,0x24]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@GOTTPREL, kind: fixup_Mips_GOTTPREL
+                                           // FIXUP: # fixup A - offset: 0, value: %gottprel(foo), kind: fixup_Mips_GOTTPREL
 
 //      .tprelword foo                     // FIXME: R_MIPS_TLS_TPREL32 foo
 //      .tpreldword foo                    // FIXME: R_MIPS_TLS_TPREL64 foo
         addiu $2, $3, %tprel_hi(foo)       // RELOC: R_MIPS_TLS_TPREL_HI16 foo
                                            // ENCBE: addiu $2, $3, %tprel_hi(foo) # encoding: [0x24,0x62,A,A]
                                            // ENCLE: addiu $2, $3, %tprel_hi(foo) # encoding: [A,A,0x62,0x24]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@TPREL_HI, kind: fixup_Mips_TPREL_HI
+                                           // FIXUP: # fixup A - offset: 0, value: %tprel_hi(foo), kind: fixup_Mips_TPREL_HI
 
         addiu $2, $3, %tprel_lo(foo)       // RELOC: R_MIPS_TLS_TPREL_LO16 foo
                                            // ENCBE: addiu $2, $3, %tprel_lo(foo) # encoding: [0x24,0x62,A,A]
                                            // ENCLE: addiu $2, $3, %tprel_lo(foo) # encoding: [A,A,0x62,0x24]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@TPREL_LO, kind: fixup_Mips_TPREL_LO
+                                           // FIXUP: # fixup A - offset: 0, value: %tprel_lo(foo), kind: fixup_Mips_TPREL_LO
 
                                            // ?????: R_MIPS_GLOB_DAT foo
         .set mips32r6
@@ -193,12 +193,12 @@
         addiu $2, $3, %pcrel_hi(foo)       // RELOC: R_MIPS_PCHI16 foo
                                            // ENCBE: addiu $2, $3, %pcrel_hi(foo) # encoding: [0x24,0x62,A,A]
                                            // ENCLE: addiu $2, $3, %pcrel_hi(foo) # encoding: [A,A,0x62,0x24]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@PCREL_HI16, kind: fixup_MIPS_PCHI16
+                                           // FIXUP: # fixup A - offset: 0, value: %pcrel_hi(foo), kind: fixup_MIPS_PCHI16
 
         addiu $2, $3, %pcrel_lo(foo)       // RELOC: R_MIPS_PCLO16 foo
                                            // ENCBE: addiu $2, $3, %pcrel_lo(foo) # encoding: [0x24,0x62,A,A]
                                            // ENCLE: addiu $2, $3, %pcrel_lo(foo) # encoding: [A,A,0x62,0x24]
-                                           // FIXUP: # fixup A - offset: 0, value: foo@PCREL_LO16, kind: fixup_MIPS_PCLO16
+                                           // FIXUP: # fixup A - offset: 0, value: %pcrel_lo(foo), kind: fixup_MIPS_PCLO16
 
         .set mips0
                                            // FIXME: R_MIPS16_*