Add encoding information for the remainder of the generic arithmetic
ARM instructions.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@116313 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp
index ad87b38..27ed551 100644
--- a/lib/Target/ARM/ARMMCCodeEmitter.cpp
+++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp
@@ -39,6 +39,8 @@
 
   ~ARMMCCodeEmitter() {}
 
+  unsigned getMachineSoImmOpValue(unsigned SoImm) const;
+
   // getBinaryCodeForInstr - TableGen'erated function for getting the
   // binary encoding for an instruction.
   unsigned getBinaryCodeForInstr(const MCInst &MI) const;
@@ -61,12 +63,6 @@
     return rtn;
   }
 
-  static unsigned GetARMRegNum(const MCOperand &MO) {
-    // FIXME: getARMRegisterNumbering() is sufficient?
-    assert(0 && "ARMMCCodeEmitter::GetARMRegNum() not yet implemented.");
-    return 0;
-  }
-
   void EmitByte(unsigned char C, unsigned &CurByte, raw_ostream &OS) const {
     OS << (char)C;
     ++CurByte;
@@ -93,6 +89,18 @@
 
 } // end anonymous namespace
 
+unsigned ARMMCCodeEmitter::getMachineSoImmOpValue(unsigned SoImm) const {
+  int SoImmVal = ARM_AM::getSOImmVal(SoImm);
+  assert(SoImmVal != -1 && "Not a valid so_imm value!");
+
+  // Encode rotate_imm.
+  unsigned Binary = (ARM_AM::getSOImmValRot((unsigned)SoImmVal) >> 1)
+    << ARMII::SoRotImmShift;
+
+  // Encode immed_8.
+  Binary |= ARM_AM::getSOImmValImm((unsigned)SoImmVal);
+  return Binary;
+}
 
 MCCodeEmitter *llvm::createARMMCCodeEmitter(const Target &,
                                              TargetMachine &TM,
@@ -112,12 +120,10 @@
 unsigned ARMMCCodeEmitter::getMachineOpValue(const MCInst &MI,
                                              const MCOperand &MO) const {
   if (MO.isReg())
-    // FIXME: Should shifted register stuff be handled as part of this? Maybe.
     return getARMRegisterNumbering(MO.getReg());
-  else if (MO.isImm())
-    // FIXME: This is insufficient. Shifted immediates and all that... (blech).
+  else if (MO.isImm()) {
     return static_cast<unsigned>(MO.getImm());
-  else {
+  } else {
 #ifndef NDEBUG
     errs() << MO;
 #endif
@@ -142,31 +148,42 @@
   ++MCNumEmitted;  // Keep track of the # of mi's emitted
   // FIXME: TableGen doesn't deal well with operands that expand to multiple
   // machine instruction operands, so for now we'll fix those up here.
+  // Similarly, operands that are encoded as other than their literal
+  // values in the MI.
+  unsigned Value = getBinaryCodeForInstr(MI);
   switch (Opcode) {
+  default: break;
+  case ARM::ADDri:
+  case ARM::ANDri:
+  case ARM::BICri:
+  case ARM::EORri:
+  case ARM::ORRri:
+  case ARM::SUBri:
+    // The 's' bit.
+    if (MI.getOperand(5).getReg() == ARM::CPSR)
+      Value |= 1 << ARMII::S_BitShift;
+    // The shifted immediate value.
+    Value |= getMachineSoImmOpValue((unsigned)MI.getOperand(2).getImm());
+    break;
   case ARM::ADDrs:
   case ARM::ANDrs:
   case ARM::BICrs:
   case ARM::EORrs:
   case ARM::ORRrs:
   case ARM::SUBrs: {
+    // The 's' bit.
+    if (MI.getOperand(7).getReg() == ARM::CPSR)
+      Value |= 1 << ARMII::S_BitShift;
     // The so_reg operand needs the shift ammount encoded.
-    unsigned Value = getBinaryCodeForInstr(MI);
     unsigned ShVal = MI.getOperand(4).getImm();
     unsigned ShType = ARM_AM::getShiftOpcEncoding(ARM_AM::getSORegShOp(ShVal));
     unsigned ShAmt = ARM_AM::getSORegOffset(ShVal);
-
     Value |= ShType << ARMII::ShiftTypeShift;
     Value |= ShAmt << ARMII::ShiftShift;
-
-    EmitConstant(Value, 4, CurByte, OS);
-    break;
-  }
-  default: {
-    unsigned Value = getBinaryCodeForInstr(MI);
-    EmitConstant(Value, 4, CurByte, OS);
     break;
   }
   }
+  EmitConstant(Value, 4, CurByte, OS);
 }
 
 // FIXME: These #defines shouldn't be necessary. Instead, tblgen should