Implement ELF object file writing support for the MBlaze backend. Its not perfect yet, but it works for many tests.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119952 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp b/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp
index 19dc89b..625c73f 100644
--- a/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp
+++ b/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp
@@ -58,8 +58,9 @@
 
   const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
     const static MCFixupKindInfo Infos[] = {
-      { "reloc_pcrel_4byte", 0, 4 * 8, MCFixupKindInfo::FKF_IsPCRel },
-      { "reloc_pcrel_2byte", 0, 2 * 8, MCFixupKindInfo::FKF_IsPCRel } };
+      // name                offset  bits    flags
+      { "reloc_pcrel_4byte", 2,      4 * 8,  MCFixupKindInfo::FKF_IsPCRel },
+      { "reloc_pcrel_2byte", 2,      2 * 8,  MCFixupKindInfo::FKF_IsPCRel } };
 
     if (Kind < FirstTargetFixupKind)
       return MCCodeEmitter::getFixupKindInfo(Kind);
@@ -103,11 +104,9 @@
   }
 
   void EmitIMM(const MCOperand &imm, unsigned &CurByte, raw_ostream &OS) const;
-  void EmitIMM(const MCInst &MI, unsigned op, unsigned &CurByte,
-               raw_ostream &OS) const;
+  void EmitIMM(const MCInst &MI, unsigned &CurByte, raw_ostream &OS) const;
 
-  void EmitImmediate(const MCInst &MI,
-                     unsigned opNo, MCFixupKind FixupKind,
+  void EmitImmediate(const MCInst &MI, unsigned opNo, bool pcrel,
                      unsigned &CurByte, raw_ostream &OS,
                      SmallVectorImpl<MCFixup> &Fixups) const;
 
@@ -155,28 +154,43 @@
 }
 
 void MBlazeMCCodeEmitter::
-EmitIMM(const MCInst &MI, unsigned op, unsigned &CurByte,
-        raw_ostream &OS) const {
-    MCOperand mcop = MI.getOperand(op);
-    if (mcop.isExpr()) {
-        EmitByte(0x0D, CurByte, OS);
-        EmitByte(0x00, CurByte, OS);
-        EmitRawByte(0, CurByte, OS);
-        EmitRawByte(0, CurByte, OS);
-    }
+EmitIMM(const MCInst &MI, unsigned &CurByte,raw_ostream &OS) const {
+  switch (MI.getOpcode()) {
+  default: break;
+
+  case MBlaze::ADDI32:
+  case MBlaze::ORI32:
+  case MBlaze::BRLID32:
+    EmitByte(0x0D, CurByte, OS);
+    EmitByte(0x00, CurByte, OS);
+    EmitRawByte(0, CurByte, OS);
+    EmitRawByte(0, CurByte, OS);
+  }
 }
 
 void MBlazeMCCodeEmitter::
-EmitImmediate(const MCInst &MI, unsigned opNo, MCFixupKind FixupKind,
-              unsigned &CurByte, raw_ostream &OS,
-              SmallVectorImpl<MCFixup> &Fixups) const {
+EmitImmediate(const MCInst &MI, unsigned opNo, bool pcrel, unsigned &CurByte,
+              raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups) const {
   assert(MI.getNumOperands()>opNo && "Not enought operands for instruction");
 
   MCOperand oper = MI.getOperand(opNo);
+
   if (oper.isImm()) {
-      EmitIMM(oper, CurByte, OS);
+    EmitIMM(oper, CurByte, OS);
   } else if (oper.isExpr()) {
+    MCFixupKind FixupKind;
+    switch (MI.getOpcode()) {
+    default:
+      FixupKind = pcrel ? MCFixupKind(MBlaze::reloc_pcrel_2byte) : FK_Data_2;
       Fixups.push_back(MCFixup::Create(0,oper.getExpr(),FixupKind));
+      break;
+    case MBlaze::ORI32:
+    case MBlaze::ADDI32:
+    case MBlaze::BRLID32:
+      FixupKind = pcrel ? MCFixupKind(MBlaze::reloc_pcrel_4byte) : FK_Data_4;
+      Fixups.push_back(MCFixup::Create(0,oper.getExpr(),FixupKind));
+      break;
+    }
   }
 }
 
@@ -191,56 +205,33 @@
   // Keep track of the current byte being emitted.
   unsigned CurByte = 0;
 
+  // Emit an IMM instruction if the instruction we are encoding requires it
+  EmitIMM(MI,CurByte,OS);
+
   switch ((TSFlags & MBlazeII::FormMask)) {
   default: break;
   case MBlazeII::FPseudo:
     // Pseudo instructions don't get encoded.
     return;
-
   case MBlazeII::FRRI:
-    EmitImmediate(MI, 2, FK_Data_4, CurByte, OS, Fixups);
+    EmitImmediate(MI, 2, false, CurByte, OS, Fixups);
     break;
-
   case MBlazeII::FRIR:
-    EmitImmediate(MI, 1, FK_Data_4, CurByte, OS, Fixups);
+    EmitImmediate(MI, 1, false, CurByte, OS, Fixups);
     break;
-
   case MBlazeII::FCRI:
-    EmitImmediate(MI, 1, MCFixupKind(MBlaze::reloc_pcrel_2byte), CurByte, OS,
-                  Fixups);
+    EmitImmediate(MI, 1, true, CurByte, OS, Fixups);
     break;
-
   case MBlazeII::FRCI:
-    EmitImmediate(MI, 1, MCFixupKind(MBlaze::reloc_pcrel_4byte), CurByte, OS,
-                  Fixups);
-
+    EmitImmediate(MI, 1, true, CurByte, OS, Fixups);
   case MBlazeII::FCCI:
-    EmitImmediate(MI, 0, MCFixupKind(MBlaze::reloc_pcrel_4byte), CurByte, OS,
-                  Fixups);
+    EmitImmediate(MI, 0, true, CurByte, OS, Fixups);
     break;
   }
 
   ++MCNumEmitted;  // Keep track of the # of mi's emitted
   unsigned Value = getBinaryCodeForInstr(MI);
-  switch (Opcode) {
-  default:
-    EmitConstant(Value, 4, CurByte, OS);
-    break;
-
-  case MBlaze::BRLID:
-  case MBlaze::BRALID:
-    EmitIMM(MI,1,CurByte,OS);
-    EmitConstant(Value, 4, CurByte, OS);
-    break;
-
-  case MBlaze::BRI:
-  case MBlaze::BRAI:
-  case MBlaze::BRID:
-  case MBlaze::BRAID:
-    EmitIMM(MI,0,CurByte,OS);
-    EmitConstant(Value, 4, CurByte, OS);
-    break;
-  }
+  EmitConstant(Value, 4, CurByte, OS);
 }
 
 // FIXME: These #defines shouldn't be necessary. Instead, tblgen should