Mips relocations R_MIPS_HIGHER and R_MIPS_HIGHEST.
authorJack Carter <jcarter@mips.com>
Mon, 6 Aug 2012 21:26:03 +0000 (21:26 +0000)
committerJack Carter <jcarter@mips.com>
Mon, 6 Aug 2012 21:26:03 +0000 (21:26 +0000)
These 2 relocations gain access to the
highest and the second highest 16 bits
of a 64 bit object.

R_MIPS_HIGHER %higher(A+S)
The %higher(x) function is [ (((long long) x + 0x80008000LL) >> 32) & 0xffff ].

R_MIPS_HIGHEST %highest(A+S)
The %highest(x) function is [ (((long long) x + 0x800080008000LL) >> 48) & 0xffff ].

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161348 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
test/MC/Mips/higher_highest.ll [new file with mode: 0644]

index 6fe0c11911d1897d0bc2fc6907a4724d5d9159ee..f679b6f909953639dda18148ecc20b3b30aacf87 100644 (file)
@@ -59,9 +59,17 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
     break;
   case Mips::fixup_Mips_HI16:
   case Mips::fixup_Mips_GOT_Local:
-    // Get the higher 16-bits. Also add 1 if bit 15 is 1.
+    // Get the 2nd 16-bits. Also add 1 if bit 15 is 1.
     Value = ((Value + 0x8000) >> 16) & 0xffff;
     break;
+  case Mips::fixup_Mips_HIGHER:
+    // Get the 3rd 16-bits.
+    Value = ((Value + 0x80008000LL) >> 32) & 0xffff;
+    break;
+  case Mips::fixup_Mips_HIGHEST:
+    // Get the 4th 16-bits.
+    Value = ((Value + 0x800080008000LL) >> 48) & 0xffff;
+    break;
   }
 
   return Value;
@@ -168,7 +176,9 @@ public:
       { "fixup_Mips_GPOFF_LO",     0,     16,   0 },
       { "fixup_Mips_GOT_PAGE",     0,     16,   0 },
       { "fixup_Mips_GOT_OFST",     0,     16,   0 },
-      { "fixup_Mips_GOT_DISP",     0,     16,   0 }
+      { "fixup_Mips_GOT_DISP",     0,     16,   0 },
+      { "fixup_Mips_HIGHER",       0,     16,   0 },
+      { "fixup_Mips_HIGHEST",      0,     16,   0 }
     };
 
     if (Kind < FirstTargetFixupKind)
index 77c1524531c3a0756bc987d72456f42fdf8a9e86..1ff304494e7e5145d7992781a1591687e14681cf 100644 (file)
@@ -169,6 +169,12 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target,
     Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type);
     Type = setRType3((unsigned)ELF::R_MIPS_LO16, Type);
     break;
+  case Mips::fixup_Mips_HIGHER:
+    Type = ELF::R_MIPS_HIGHER;
+    break;
+  case Mips::fixup_Mips_HIGHEST:
+    Type = ELF::R_MIPS_HIGHEST;
+    break;
   }
   return Type;
 }
index f5cbbd537d1c4d16a01e78a5150b19d2594a5dbe..77faec54fb233835a47bf4e4b5217ce60dc37e77 100644 (file)
@@ -110,6 +110,12 @@ namespace Mips {
     // resulting in - R_MIPS_GOT_DISP
     fixup_Mips_GOT_DISP,
 
+    // resulting in - R_MIPS_GOT_HIGHER
+    fixup_Mips_HIGHER,
+
+    // resulting in - R_MIPS_HIGHEST
+    fixup_Mips_HIGHEST,
+
     // Marker
     LastTargetFixupKind,
     NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
index ff3b3a7ed1c2d85e2b568af37475310f9ca8f2b6..8dab62d518135f9c69e1b454b7fc9da691c4468f 100644 (file)
@@ -255,6 +255,12 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO,
   case MCSymbolRefExpr::VK_Mips_TPREL_LO:
     FixupKind = Mips::fixup_Mips_TPREL_LO;
     break;
+  case MCSymbolRefExpr::VK_Mips_HIGHER:
+    FixupKind = Mips::fixup_Mips_HIGHER;
+    break;
+  case MCSymbolRefExpr::VK_Mips_HIGHEST:
+    FixupKind = Mips::fixup_Mips_HIGHEST;
+    break;
   } // switch
 
   Fixups.push_back(MCFixup::Create(0, MO.getExpr(), MCFixupKind(FixupKind)));
diff --git a/test/MC/Mips/higher_highest.ll b/test/MC/Mips/higher_highest.ll
new file mode 100644 (file)
index 0000000..81a89e3
--- /dev/null
@@ -0,0 +1,27 @@
+; RUN: llc -march=mips64el -mcpu=mips64 -mattr=n64  -force-mips-long-branch -filetype=obj < %s -o - | elf-dump --dump-section-data | FileCheck %s
+
+; Check that the R_MIPS_HIGHER and R_MIPS_HIGHEST relocations were created.
+
+; CHECK:     ('r_type', 0x1d)
+; CHECK:     ('r_type', 0x1d)
+; CHECK:     ('r_type', 0x1c)
+; CHECK:     ('r_type', 0x1c)
+
+@g0 = external global i32
+
+define void @foo1(i32 %s) nounwind {
+entry:
+
+  %tobool = icmp eq i32 %s, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+if.then:                                          ; preds = %entry
+  %0 = load i32* @g0, align 4
+  %add = add nsw i32 %0, 12
+  store i32 %add, i32* @g0, align 4
+  br label %if.end
+
+if.end:                                           ; preds = %entry, %if.then
+  ret void
+}
+