[mips][mips64r6] Relocation R_MIPS_PC18_S3
authorZoran Jovanovic <zoran.jovanovic@imgtec.com>
Fri, 13 Jun 2014 14:26:47 +0000 (14:26 +0000)
committerZoran Jovanovic <zoran.jovanovic@imgtec.com>
Fri, 13 Jun 2014 14:26:47 +0000 (14:26 +0000)
Differential Revision: http://reviews.llvm.org/D3890

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@210908 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
lib/Target/Mips/MipsInstrInfo.td
test/MC/Mips/mips64r6/relocations.s

index ea8ab4d309cc245cd403974de158c26da81c2e45..d8e6128cd54d5477bd6164c4537a2375d11d8b0f 100644 (file)
@@ -111,6 +111,13 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
     if (!isIntN(16, Value) && Ctx)
       Ctx->FatalError(Fixup.getLoc(), "out of range PC16 fixup");
     break;
+  case Mips::fixup_MIPS_PC18_S3:
+    // Forcing a signed division because Value can be negative.
+    Value = (int64_t)Value / 8;
+    // We now check if Value can be encoded as a 18-bit signed immediate.
+    if (!isIntN(18, Value) && Ctx)
+      Ctx->FatalError(Fixup.getLoc(), "out of range PC18 fixup");
+    break;
   case Mips::fixup_MIPS_PC21_S2:
     Value -= 4;
     // Forcing a signed division because Value can be negative.
@@ -254,6 +261,7 @@ getFixupKindInfo(MCFixupKind Kind) const {
     { "fixup_Mips_GOT_LO16",     0,     16,   0 },
     { "fixup_Mips_CALL_HI16",    0,     16,   0 },
     { "fixup_Mips_CALL_LO16",    0,     16,   0 },
+    { "fixup_Mips_PC18_S3",      0,     18,  MCFixupKindInfo::FKF_IsPCRel },
     { "fixup_MIPS_PC19_S2",      0,     19,  MCFixupKindInfo::FKF_IsPCRel },
     { "fixup_MIPS_PC21_S2",      0,     21,  MCFixupKindInfo::FKF_IsPCRel },
     { "fixup_MIPS_PC26_S2",      0,     26,  MCFixupKindInfo::FKF_IsPCRel },
@@ -316,6 +324,7 @@ getFixupKindInfo(MCFixupKind Kind) const {
     { "fixup_Mips_GOT_LO16",    16,     16,   0 },
     { "fixup_Mips_CALL_HI16",   16,     16,   0 },
     { "fixup_Mips_CALL_LO16",   16,     16,   0 },
+    { "fixup_Mips_PC18_S3",     14,     18,  MCFixupKindInfo::FKF_IsPCRel },
     { "fixup_MIPS_PC19_S2",     13,     19,  MCFixupKindInfo::FKF_IsPCRel },
     { "fixup_MIPS_PC21_S2",     11,     21,  MCFixupKindInfo::FKF_IsPCRel },
     { "fixup_MIPS_PC26_S2",      6,     26,  MCFixupKindInfo::FKF_IsPCRel },
index a431e802378d2ebb99a86214da3a168e4b9d50d2..49ac25690b98408938cfe902a8b7a6d6850032dd 100644 (file)
@@ -196,6 +196,9 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target,
   case Mips::fixup_MIPS_PC19_S2:
     Type = ELF::R_MIPS_PC19_S2;
     break;
+  case Mips::fixup_MIPS_PC18_S3:
+    Type = ELF::R_MIPS_PC18_S3;
+    break;
   case Mips::fixup_MIPS_PC21_S2:
     Type = ELF::R_MIPS_PC21_S2;
     break;
index 7af723af6550dfe745d6e21627899674c5ba4ccc..05080f046f89a00f93533bb8ff7b644e80cabc2b 100644 (file)
@@ -128,6 +128,9 @@ namespace Mips {
     // resulting in - R_MIPS_CALL_LO16
     fixup_Mips_CALL_LO16,
 
+    // resulting in - R_MIPS_PC18_S3
+    fixup_MIPS_PC18_S3,
+
     // resulting in - R_MIPS_PC19_S2
     fixup_MIPS_PC19_S2,
 
index 0e3c6847f345592979e9aed426fdcaedb2bf4b8f..43fc52136ddc90bcc2a1db4b524ed3788f5152de 100644 (file)
@@ -642,11 +642,21 @@ unsigned
 MipsMCCodeEmitter::getSimm18Lsl3Encoding(const MCInst &MI, unsigned OpNo,
                                          SmallVectorImpl<MCFixup> &Fixups,
                                          const MCSubtargetInfo &STI) const {
-  assert(MI.getOperand(OpNo).isImm());
-  // The immediate is encoded as 'immediate << 3'.
-  unsigned Res = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
-  assert((Res & 7) == 0);
-  return Res >> 3;
+  const MCOperand &MO = MI.getOperand(OpNo);
+  if (MO.isImm()) {
+    // The immediate is encoded as 'immediate << 3'.
+    unsigned Res = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
+    assert((Res & 7) == 0);
+    return Res >> 3;
+  }
+
+  assert(MO.isExpr() &&
+         "getSimm18Lsl2Encoding expects only expressions or an immediate");
+
+  const MCExpr *Expr = MO.getExpr();
+  Fixups.push_back(MCFixup::Create(0, Expr,
+                                   MCFixupKind(Mips::fixup_MIPS_PC18_S3)));
+  return 0;
 }
 
 #include "MipsGenMCCodeEmitter.inc"
index 65795a109dd0c8b6193ffc955283b74bdad283ba..8503c8290feca79e98f49bb0e7bceefe4a15725a 100644 (file)
@@ -365,6 +365,7 @@ def simm19_lsl2 : Operand<i32> {
 def simm18_lsl3 : Operand<i32> {
   let EncoderMethod = "getSimm18Lsl3Encoding";
   let DecoderMethod = "DecodeSimm18Lsl3";
+  let ParserMatchClass = MipsJumpTargetAsmOperand;
 }
 
 def simm20      : Operand<i32> {
index a3304f582346e1471ca8a69bfee0b9f89e8c0c31..651ebfb6c4c1adbe1fb735527240fb0f47f87b46 100644 (file)
 # CHECK-FIXUP:                              #   fixup A - offset: 0,
 # CHECK-FIXUP:                                  value: bar@PCREL_LO16,
 # CHECK-FIXUP:                                  kind: fixup_MIPS_PCLO16
+# CHECK-FIXUP: ldpc    $2, bar  # encoding: [0xec,0b010110AA,A,A]
+# CHECK-FIXUP:                  # fixup A - offset: 0,
+# CHECK-FIXUP:                      value: bar,
+# CHECK-FIXUP:                      kind: fixup_Mips_PC18_S3
 # CHECK-FIXUP: lwpc    $2, bar  # encoding: [0xec,0b01001AAA,A,A]
 # CHECK-FIXUP:                  #   fixup A - offset: 0,
 # CHECK-FIXUP:                      value: bar, kind: fixup_MIPS_PC19_S2
@@ -53,8 +57,9 @@
 # CHECK-ELF:     0x18 R_MIPS_PC26_S2 bar 0x0
 # CHECK-ELF:     0x1C R_MIPS_PCHI16 bar 0x0
 # CHECK-ELF:     0x20 R_MIPS_PCLO16 bar 0x0
-# CHECK-ELF:     0x24 R_MIPS_PC19_S2 bar 0x0
+# CHECK-ELF:     0x24 R_MIPS_PC18_S3 bar 0x0
 # CHECK-ELF:     0x28 R_MIPS_PC19_S2 bar 0x0
+# CHECK-ELF:     0x2C R_MIPS_PC19_S2 bar 0x0
 # CHECK-ELF: ]
 
   addiupc   $2,bar
@@ -66,5 +71,6 @@
   bc    bar
   aluipc $2, %pcrel_hi(bar)
   addiu  $2, $2, %pcrel_lo(bar)
+  ldpc  $2,bar
   lwpc  $2,bar
   lwupc $2,bar