ARM/MC/ELF relocation "hello world" for movw/movt.
Lifted adjustFixupValue() from Darwin for sharing w ELF.
Test added
TODO:
  refactor ELFObjectWriter::RecordRelocation more.
  Possibly share more code with Darwin?
  Lots more relocations...



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120534 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/ARM/ARMAsmBackend.cpp b/lib/Target/ARM/ARMAsmBackend.cpp
index 6267a5a..432d077 100644
--- a/lib/Target/ARM/ARMAsmBackend.cpp
+++ b/lib/Target/ARM/ARMAsmBackend.cpp
@@ -38,6 +38,48 @@
   unsigned getPointerSize() const {
     return 4;
   }
+
+protected:
+  static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
+    switch (Kind) {
+    default:
+      llvm_unreachable("Unknown fixup kind!");
+    case FK_Data_4:
+    case ARM::fixup_arm_movt_hi16:
+    case ARM::fixup_arm_movw_lo16:
+      return Value;
+    case ARM::fixup_arm_pcrel_12: {
+      bool isAdd = true;
+      // ARM PC-relative values are offset by 8.
+      Value -= 8;
+      if ((int64_t)Value < 0) {
+        Value = -Value;
+        isAdd = false;
+      }
+      assert ((Value < 4096) && "Out of range pc-relative fixup value!");
+      Value |= isAdd << 23;
+      return Value;
+    }
+    case ARM::fixup_arm_branch:
+      // These values don't encode the low two bits since they're always zero.
+      // Offset by 8 just as above.
+      return (Value - 8) >> 2;
+    case ARM::fixup_arm_vfp_pcrel_12: {
+      // Offset by 8 just as above.
+      Value = Value - 8;
+      bool isAdd = true;
+      if ((int64_t)Value < 0) {
+        Value = -Value;
+        isAdd = false;
+      }
+      // These values don't encode the low two bits since they're always zero.
+      Value >>= 2;
+      assert ((Value < 256) && "Out of range pc-relative fixup value!");
+      Value |= isAdd << 23;
+      return Value;
+    }
+    }
+  }
 };
 } // end anonymous namespace
 
@@ -52,10 +94,6 @@
 }
 
 bool ARMAsmBackend::WriteNopData(uint64_t Count, MCObjectWriter *OW) const {
-//  if ((Count % 4) != 0) {
-//    // Fixme: % 2 for Thumb?
-//    return false;
-//  }
   // FIXME: Zero fill for now. That's not right, but at least will get the
   // section size right.
   for (uint64_t i = 0; i != Count; ++i)
@@ -94,7 +132,39 @@
 // Fixme: can we raise this to share code between Darwin and ELF?
 void ELFARMAsmBackend::ApplyFixup(const MCFixup &Fixup, MCDataFragment &DF,
                                   uint64_t Value) const {
-  assert(0 && "ELFARMAsmBackend::ApplyFixup() unimplemented");
+  uint32_t Mask = 0;
+  // Fixme: 2 for Thumb
+  int NumBytes = 4; 
+  Value = adjustFixupValue(Fixup.getKind(), Value);
+
+  switch (Fixup.getKind()) {
+  default: assert(0 && "Unsupported Fixup kind"); break;
+  case ARM::fixup_arm_branch: {
+    unsigned Lo24 = Value & 0xFFFFFF;
+    Mask = ~(0xFFFFFF);
+    Value = Lo24;
+  }; break;
+  case ARM::fixup_arm_movt_hi16:
+  case ARM::fixup_arm_movw_lo16: {
+    unsigned Hi4 = (Value & 0xF000) >> 12;
+    unsigned Lo12 = Value & 0x0FFF;
+    // inst{19-16} = Hi4;
+    // inst{11-0} = Lo12;
+    Value = (Hi4 << 16) | (Lo12);
+    Mask = ~(0xF0FFF);
+  }; break;
+  }
+
+  assert((Fixup.getOffset() % NumBytes == 0)
+         && "Offset mod NumBytes is nonzero!");
+  // For each byte of the fragment that the fixup touches, mask in the
+  // bits from the fixup value.
+  // The Value has been "split up" into the appropriate bitfields above.
+  // Fixme: how to share code with the .td generated code?
+  for (unsigned i = 0; i != NumBytes; ++i) {
+    DF.getContents()[Fixup.getOffset() + i] &= uint8_t(Mask >> (i * 8));
+    DF.getContents()[Fixup.getOffset() + i] |= uint8_t(Value >> (i * 8));
+  }
 }
 
 namespace {
@@ -137,45 +207,6 @@
   }
 }
 
-static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
-  switch (Kind) {
-  default:
-    llvm_unreachable("Unknown fixup kind!");
-  case FK_Data_4:
-    return Value;
-  case ARM::fixup_arm_pcrel_12: {
-    bool isAdd = true;
-    // ARM PC-relative values are offset by 8.
-    Value -= 8;
-    if ((int64_t)Value < 0) {
-      Value = -Value;
-      isAdd = false;
-    }
-    assert ((Value < 4096) && "Out of range pc-relative fixup value!");
-    Value |= isAdd << 23;
-    return Value;
-  }
-  case ARM::fixup_arm_branch:
-    // These values don't encode the low two bits since they're always zero.
-    // Offset by 8 just as above.
-    return (Value - 8) >> 2;
-  case ARM::fixup_arm_vfp_pcrel_12: {
-    // Offset by 8 just as above.
-    Value = Value - 8;
-    bool isAdd = true;
-    if ((int64_t)Value < 0) {
-      Value = -Value;
-      isAdd = false;
-    }
-    // These values don't encode the low two bits since they're always zero.
-    Value >>= 2;
-    assert ((Value < 256) && "Out of range pc-relative fixup value!");
-    Value |= isAdd << 23;
-    return Value;
-  }
-  }
-}
-
 void DarwinARMAsmBackend::ApplyFixup(const MCFixup &Fixup, MCDataFragment &DF,
                                      uint64_t Value) const {
   unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());