implement the start of support for lo16 and ha16, allowing us to get stuff like:

        lis r4, ha16(__ZL4init)         ; encoding: [0x3c,0x80,A,A]
                                        ;   fixup A - offset: 0, value: ha16(__ZL4init), kind: fixup_ppc_ha16


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119127 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/PowerPC/PPCCodeEmitter.cpp b/lib/Target/PowerPC/PPCCodeEmitter.cpp
index 952a456..9335b18 100644
--- a/lib/Target/PowerPC/PPCCodeEmitter.cpp
+++ b/lib/Target/PowerPC/PPCCodeEmitter.cpp
@@ -63,7 +63,11 @@
     unsigned get_crbitm_encoding(const MachineInstr &MI, unsigned OpNo) const;
     unsigned getDirectBrEncoding(const MachineInstr &MI, unsigned OpNo) const;
     unsigned getCondBrEncoding(const MachineInstr &MI, unsigned OpNo) const;
-    
+
+    unsigned getHA16Encoding(const MachineInstr &MI, unsigned OpNo) const;
+    unsigned getLO16Encoding(const MachineInstr &MI, unsigned OpNo) const;
+    unsigned getLO14Encoding(const MachineInstr &MI, unsigned OpNo) const;
+
     const char *getPassName() const { return "PowerPC Machine Code Emitter"; }
 
     /// runOnMachineFunction - emits the given MachineFunction to memory
@@ -140,16 +144,27 @@
 
 MachineRelocation PPCCodeEmitter::GetRelocation(const MachineOperand &MO, 
                                                 unsigned RelocID) const {
+  // If in PIC mode, we need to encode the negated address of the
+  // 'movepctolr' into the unrelocated field.  After relocation, we'll have
+  // &gv-&movepctolr-4 in the imm field.  Once &movepctolr is added to the imm
+  // field, we get &gv.  This doesn't happen for branch relocations, which are
+  // always implicitly pc relative.
+  intptr_t Cst = 0;
+  if (TM.getRelocationModel() == Reloc::PIC_) {
+    assert(MovePCtoLROffset && "MovePCtoLR not seen yet?");
+    Cst = -(intptr_t)MovePCtoLROffset - 4;
+  }
+  
   if (MO.isGlobal())
     return MachineRelocation::getGV(MCE.getCurrentPCOffset(), RelocID,
-                                    const_cast<GlobalValue *>(MO.getGlobal()),0,
-                                    isa<Function>(MO.getGlobal()));
+                                    const_cast<GlobalValue *>(MO.getGlobal()),
+                                    Cst, isa<Function>(MO.getGlobal()));
   if (MO.isSymbol())
     return MachineRelocation::getExtSym(MCE.getCurrentPCOffset(),
-                                        RelocID, MO.getSymbolName(), 0);
+                                        RelocID, MO.getSymbolName(), Cst);
   if (MO.isCPI())
     return MachineRelocation::getConstPool(MCE.getCurrentPCOffset(),
-                                           RelocID, MO.getIndex(), 0);
+                                           RelocID, MO.getIndex(), Cst);
 
   if (MO.isMBB())
     MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(),
@@ -157,7 +172,7 @@
   
   assert(MO.isJTI());
   return MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(),
-                                         RelocID, MO.getIndex(), 0);
+                                         RelocID, MO.getIndex(), Cst);
 }
 
 unsigned PPCCodeEmitter::getDirectBrEncoding(const MachineInstr &MI,
@@ -176,6 +191,33 @@
   return 0;
 }
 
+unsigned PPCCodeEmitter::getHA16Encoding(const MachineInstr &MI,
+                                         unsigned OpNo) const {
+  const MachineOperand &MO = MI.getOperand(OpNo);
+  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO);
+
+  MCE.addRelocation(GetRelocation(MO, PPC::reloc_absolute_high));
+  return 0;
+}
+
+unsigned PPCCodeEmitter::getLO16Encoding(const MachineInstr &MI,
+                                         unsigned OpNo) const {
+  const MachineOperand &MO = MI.getOperand(OpNo);
+  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO);
+  
+  MCE.addRelocation(GetRelocation(MO, PPC::reloc_absolute_low));
+  return 0;
+}
+
+unsigned PPCCodeEmitter::getLO14Encoding(const MachineInstr &MI,
+                                         unsigned OpNo) const {
+  const MachineOperand &MO = MI.getOperand(OpNo);
+  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO);
+  
+  MCE.addRelocation(GetRelocation(MO, PPC::reloc_absolute_low_ix));
+  return 0;
+}
+
 
 unsigned PPCCodeEmitter::getMachineOpValue(const MachineInstr &MI,
                                            const MachineOperand &MO) const {
@@ -194,15 +236,6 @@
            "MovePCtoLR not seen yet?");
     switch (MI.getOpcode()) {
     default: MI.dump(); llvm_unreachable("Unknown instruction for relocation!");
-    case PPC::LIS:
-    case PPC::LIS8:
-    case PPC::ADDIS:
-    case PPC::ADDIS8:
-      Reloc = PPC::reloc_absolute_high;       // Pointer to symbol
-      break;
-    case PPC::LI:
-    case PPC::LI8:
-    case PPC::LA:
     // Loads.
     case PPC::LBZ:
     case PPC::LBZ8:
@@ -235,18 +268,7 @@
       break;
     }
 
-    MachineRelocation R = GetRelocation(MO, Reloc);
-
-    // If in PIC mode, we need to encode the negated address of the
-    // 'movepctolr' into the unrelocated field.  After relocation, we'll have
-    // &gv-&movepctolr-4 in the imm field.  Once &movepctolr is added to the imm
-    // field, we get &gv.  This doesn't happen for branch relocations, which are
-    // always implicitly pc relative.
-    if (TM.getRelocationModel() == Reloc::PIC_) {
-      assert(MovePCtoLROffset && "MovePCtoLR not seen yet?");
-      R.setConstantVal(-(intptr_t)MovePCtoLROffset - 4);
-    }
-    MCE.addRelocation(R);
+    MCE.addRelocation(GetRelocation(MO, Reloc));
   } else {
 #ifndef NDEBUG
     errs() << "ERROR: Unknown type of MachineOperand: " << MO << "\n";