Encode VFP arithmetic instructions.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59016 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp
index ddd2564..b39ab7f8 100644
--- a/lib/Target/ARM/ARMCodeEmitter.cpp
+++ b/lib/Target/ARM/ARMCodeEmitter.cpp
@@ -120,6 +120,8 @@
 
     void emitMiscBranchInstruction(const MachineInstr &MI);
 
+    void emitVFPArithInstruction(const MachineInstr &MI);
+
     /// getBinaryCodeForInstr - This function, generated by the
     /// CodeEmitterGenerator using TableGen, produces the binary encoding for
     /// machine instructions.
@@ -313,6 +315,11 @@
   case ARMII::BrMiscFrm:
     emitMiscBranchInstruction(MI);
     break;
+  // VFP instructions.
+  case ARMII::VFPUnaryFrm:
+  case ARMII::VFPBinaryFrm:
+    emitVFPArithInstruction(MI);
+    break;
   }
 }
 
@@ -976,4 +983,42 @@
   emitWordLE(Binary);
 }
 
+void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) {
+  const TargetInstrDesc &TID = MI.getDesc();
+
+  // Part of binary is determined by TableGn.
+  unsigned Binary = getBinaryCodeForInstr(MI);
+
+  // Set the conditional execution predicate
+  Binary |= II->getPredicate(&MI) << ARMII::CondShift;
+
+  unsigned OpIdx = 0;
+  assert((Binary & ARMII::D_BitShift) == 0 &&
+         (Binary & ARMII::N_BitShift) == 0 &&
+         (Binary & ARMII::M_BitShift) == 0 && "VFP encoding bug!");
+
+  // Encode Dd / Sd.
+  unsigned RegD = getMachineOpValue(MI, OpIdx++);
+  Binary |= (RegD & 0x0f) << ARMII::RegFdShift;
+  Binary |= (RegD & 0x10) << ARMII::D_BitShift;
+
+  // If this is a two-address operand, skip it, e.g. FMACD.
+  if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)
+    ++OpIdx;
+
+  // Encode Dn / Sn.
+  if ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPBinaryFrm) {
+    unsigned RegN = getMachineOpValue(MI, OpIdx++);
+    Binary |= (RegN & 0x0f);
+    Binary |= (RegN & 0x10) << ARMII::N_BitShift;
+  }
+
+  // Encode Dm / Sm.
+  unsigned RegM = getMachineOpValue(MI, OpIdx++);
+  Binary |= (RegM & 0x0f);
+  Binary |= (RegM & 0x10) << ARMII::M_BitShift;
+  
+  emitWordLE(Binary);
+}
+
 #include "ARMGenCodeEmitter.inc"