//===-- ARM/ARMCodeEmitter.cpp - Convert ARM code to machine code ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the pass that transforms the ARM machine instructions into
// relocatable machine code.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "jit"
#include "ARM.h"
#include "ARMAddressingModes.h"
#include "ARMConstantPoolValue.h"
#include "ARMInstrInfo.h"
#include "ARMRelocations.h"
#include "ARMSubtarget.h"
#include "ARMTargetMachine.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/PassManager.h"
#include "llvm/CodeGen/JITCodeEmitter.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#ifndef NDEBUG
#include <iomanip>
#endif
using namespace llvm;

STATISTIC(NumEmitted, "Number of machine instructions emitted");

namespace {

  class ARMCodeEmitter : public MachineFunctionPass {
    ARMJITInfo                *JTI;
    const ARMInstrInfo        *II;
    const TargetData          *TD;
    const ARMSubtarget        *Subtarget;
    TargetMachine             &TM;
    JITCodeEmitter            &MCE;
    MachineModuleInfo *MMI;
    const std::vector<MachineConstantPoolEntry> *MCPEs;
    const std::vector<MachineJumpTableEntry> *MJTEs;
    bool IsPIC;
    bool IsThumb;

    void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequired<MachineModuleInfo>();
      MachineFunctionPass::getAnalysisUsage(AU);
    }

    static char ID;
  public:
    ARMCodeEmitter(TargetMachine &tm, JITCodeEmitter &mce)
      : MachineFunctionPass(ID), JTI(0),
        II((const ARMInstrInfo *)tm.getInstrInfo()),
        TD(tm.getTargetData()), TM(tm),
        MCE(mce), MCPEs(0), MJTEs(0),
        IsPIC(TM.getRelocationModel() == Reloc::PIC_), IsThumb(false) {}

    /// getBinaryCodeForInstr - This function, generated by the
    /// CodeEmitterGenerator using TableGen, produces the binary encoding for
    /// machine instructions.
    unsigned getBinaryCodeForInstr(const MachineInstr &MI) const;

    bool runOnMachineFunction(MachineFunction &MF);

    virtual const char *getPassName() const {
      return "ARM Machine Code Emitter";
    }

    void emitInstruction(const MachineInstr &MI);

  private:

    void emitWordLE(unsigned Binary);
    void emitDWordLE(uint64_t Binary);
    void emitConstPoolInstruction(const MachineInstr &MI);
    void emitMOVi32immInstruction(const MachineInstr &MI);
    void emitMOVi2piecesInstruction(const MachineInstr &MI);
    void emitLEApcrelJTInstruction(const MachineInstr &MI);
    void emitPseudoMoveInstruction(const MachineInstr &MI);
    void addPCLabel(unsigned LabelID);
    void emitPseudoInstruction(const MachineInstr &MI);
    unsigned getMachineSoRegOpValue(const MachineInstr &MI,
                                    const TargetInstrDesc &TID,
                                    const MachineOperand &MO,
                                    unsigned OpIdx);

    unsigned getMachineSoImmOpValue(unsigned SoImm);
    unsigned getAddrModeSBit(const MachineInstr &MI,
                             const TargetInstrDesc &TID) const;

    void emitDataProcessingInstruction(const MachineInstr &MI,
                                       unsigned ImplicitRd = 0,
                                       unsigned ImplicitRn = 0);

    void emitLoadStoreInstruction(const MachineInstr &MI,
                                  unsigned ImplicitRd = 0,
                                  unsigned ImplicitRn = 0);

    void emitMiscLoadStoreInstruction(const MachineInstr &MI,
                                      unsigned ImplicitRn = 0);

    void emitLoadStoreMultipleInstruction(const MachineInstr &MI);

    void emitMulFrmInstruction(const MachineInstr &MI);

    void emitExtendInstruction(const MachineInstr &MI);

    void emitMiscArithInstruction(const MachineInstr &MI);

    void emitSaturateInstruction(const MachineInstr &MI);

    void emitBranchInstruction(const MachineInstr &MI);

    void emitInlineJumpTable(unsigned JTIndex);

    void emitMiscBranchInstruction(const MachineInstr &MI);

    void emitVFPArithInstruction(const MachineInstr &MI);

    void emitVFPConversionInstruction(const MachineInstr &MI);

    void emitVFPLoadStoreInstruction(const MachineInstr &MI);

    void emitVFPLoadStoreMultipleInstruction(const MachineInstr &MI);

    void emitNEONLaneInstruction(const MachineInstr &MI);
    void emitNEONDupInstruction(const MachineInstr &MI);
    void emitNEON1RegModImmInstruction(const MachineInstr &MI);
    void emitNEON2RegInstruction(const MachineInstr &MI);
    void emitNEON3RegInstruction(const MachineInstr &MI);

    /// getMachineOpValue - Return binary encoding of operand. If the machine
    /// operand requires relocation, record the relocation and return zero.
    unsigned getMachineOpValue(const MachineInstr &MI,
                               const MachineOperand &MO) const;
    unsigned getMachineOpValue(const MachineInstr &MI, unsigned OpIdx) const {
      return getMachineOpValue(MI, MI.getOperand(OpIdx));
    }

    // FIXME: The legacy JIT ARMCodeEmitter doesn't rely on the the
    //  TableGen'erated getBinaryCodeForInstr() function to encode any
    //  operand values, instead querying getMachineOpValue() directly for
    //  each operand it needs to encode. Thus, any of the new encoder
    //  helper functions can simply return 0 as the values the return
    //  are already handled elsewhere. They are placeholders to allow this
    //  encoder to continue to function until the MC encoder is sufficiently
    //  far along that this one can be eliminated entirely.
    unsigned NEONThumb2DataIPostEncoder(const MachineInstr &MI, unsigned Val) 
      const { return 0; }
    unsigned NEONThumb2LoadStorePostEncoder(const MachineInstr &MI,unsigned Val) 
      const { return 0; }
    unsigned NEONThumb2DupPostEncoder(const MachineInstr &MI,unsigned Val) 
      const { return 0; }
    unsigned VFPThumb2PostEncoder(const MachineInstr&MI, unsigned Val)
      const { return 0; }
    unsigned getAdrLabelOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getThumbAdrLabelOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getThumbBLTargetOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getThumbBLXTargetOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getThumbBRTargetOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getThumbBCCTargetOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getThumbCBTargetOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getUnconditionalBranchTargetOpValue(const MachineInstr &MI,
      unsigned Op) const { return 0; }
    unsigned getARMBranchTargetOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getCCOutOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getSOImmOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getT2SOImmOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getSORegOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getThumbAddrModeRegRegOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getT2AddrModeImm12OpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getT2AddrModeImm8OpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getT2AddrModeImm8s4OpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getT2AddrModeImm8OffsetOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getT2AddrModeImm12OffsetOpValue(const MachineInstr &MI,unsigned Op)
      const { return 0; }
    unsigned getT2AddrModeSORegOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getT2SORegOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getRotImmOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getImmMinusOneOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getT2AdrLabelOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getAddrMode6AddressOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getAddrMode6DupAddressOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getAddrMode6OffsetOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getBitfieldInvertedMaskOpValue(const MachineInstr &MI,
                                            unsigned Op) const { return 0; }
    unsigned getMsbOpValue(const MachineInstr &MI,
                           unsigned Op) const { return 0; }
    uint32_t getLdStmModeOpValue(const MachineInstr &MI, unsigned OpIdx)
      const {return 0; }
    uint32_t getLdStSORegOpValue(const MachineInstr &MI, unsigned OpIdx)
      const { return 0; }

    unsigned getAddrModeImm12OpValue(const MachineInstr &MI, unsigned Op)
      const {
      // {17-13} = reg
      // {12}    = (U)nsigned (add == '1', sub == '0')
      // {11-0}  = imm12
      const MachineOperand &MO  = MI.getOperand(Op);
      const MachineOperand &MO1 = MI.getOperand(Op + 1);
      if (!MO.isReg()) {
        emitConstPoolAddress(MO.getIndex(), ARM::reloc_arm_cp_entry);
        return 0;
      }
      unsigned Reg = getARMRegisterNumbering(MO.getReg());
      int32_t Imm12 = MO1.getImm();
      uint32_t Binary;
      Binary = Imm12 & 0xfff;
      if (Imm12 >= 0)
        Binary |= (1 << 12);
      Binary |= (Reg << 13);
      return Binary;
    }

    unsigned getHiLo16ImmOpValue(const MachineInstr &MI, unsigned Op) const {
      return 0;
    }

    uint32_t getAddrMode2OpValue(const MachineInstr &MI, unsigned OpIdx)
      const { return 0;}
    uint32_t getAddrMode2OffsetOpValue(const MachineInstr &MI, unsigned OpIdx)
      const { return 0;}
    uint32_t getAddrMode3OffsetOpValue(const MachineInstr &MI, unsigned OpIdx)
      const { return 0;}
    uint32_t getAddrMode3OpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    uint32_t getAddrModeThumbSPOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    uint32_t getAddrModeSOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    uint32_t getAddrModeISOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    uint32_t getAddrModePCOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    uint32_t getAddrMode5OpValue(const MachineInstr &MI, unsigned Op) const {
      // {17-13} = reg
      // {12}    = (U)nsigned (add == '1', sub == '0')
      // {11-0}  = imm12
      const MachineOperand &MO  = MI.getOperand(Op);
      const MachineOperand &MO1 = MI.getOperand(Op + 1);
      if (!MO.isReg()) {
        emitConstPoolAddress(MO.getIndex(), ARM::reloc_arm_cp_entry);
        return 0;
      }
      unsigned Reg = getARMRegisterNumbering(MO.getReg());
      int32_t Imm12 = MO1.getImm();

      // Special value for #-0
      if (Imm12 == INT32_MIN)
        Imm12 = 0;

      // Immediate is always encoded as positive. The 'U' bit controls add vs
      // sub.
      bool isAdd = true;
      if (Imm12 < 0) {
        Imm12 = -Imm12;
        isAdd = false;
      }

      uint32_t Binary = Imm12 & 0xfff;
      if (isAdd)
        Binary |= (1 << 12);
      Binary |= (Reg << 13);
      return Binary;
    }
    unsigned getNEONVcvtImm32OpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }

    unsigned getRegisterListOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }

    unsigned getShiftRight8Imm(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getShiftRight16Imm(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getShiftRight32Imm(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getShiftRight64Imm(const MachineInstr &MI, unsigned Op)
      const { return 0; }

    /// getMovi32Value - Return binary encoding of operand for movw/movt. If the
    /// machine operand requires relocation, record the relocation and return
    /// zero.
    unsigned getMovi32Value(const MachineInstr &MI,const MachineOperand &MO,
                            unsigned Reloc);

    /// getShiftOp - Return the shift opcode (bit[6:5]) of the immediate value.
    ///
    unsigned getShiftOp(unsigned Imm) const ;

    /// Routines that handle operands which add machine relocations which are
    /// fixed up by the relocation stage.
    void emitGlobalAddress(const GlobalValue *GV, unsigned Reloc,
                           bool MayNeedFarStub,  bool Indirect,
                           intptr_t ACPV = 0) const;
    void emitExternalSymbolAddress(const char *ES, unsigned Reloc) const;
    void emitConstPoolAddress(unsigned CPI, unsigned Reloc) const;
    void emitJumpTableAddress(unsigned JTIndex, unsigned Reloc) const;
    void emitMachineBasicBlock(MachineBasicBlock *BB, unsigned Reloc,
                               intptr_t JTBase = 0) const;
  };
}

char ARMCodeEmitter::ID = 0;

/// createARMJITCodeEmitterPass - Return a pass that emits the collected ARM
/// code to the specified MCE object.
FunctionPass *llvm::createARMJITCodeEmitterPass(ARMBaseTargetMachine &TM,
                                                JITCodeEmitter &JCE) {
  return new ARMCodeEmitter(TM, JCE);
}

bool ARMCodeEmitter::runOnMachineFunction(MachineFunction &MF) {
  assert((MF.getTarget().getRelocationModel() != Reloc::Default ||
          MF.getTarget().getRelocationModel() != Reloc::Static) &&
         "JIT relocation model must be set to static or default!");
  JTI = ((ARMTargetMachine &)MF.getTarget()).getJITInfo();
  II = ((const ARMTargetMachine &)MF.getTarget()).getInstrInfo();
  TD = ((const ARMTargetMachine &)MF.getTarget()).getTargetData();
  Subtarget = &TM.getSubtarget<ARMSubtarget>();
  MCPEs = &MF.getConstantPool()->getConstants();
  MJTEs = 0;
  if (MF.getJumpTableInfo()) MJTEs = &MF.getJumpTableInfo()->getJumpTables();
  IsPIC = TM.getRelocationModel() == Reloc::PIC_;
  IsThumb = MF.getInfo<ARMFunctionInfo>()->isThumbFunction();
  JTI->Initialize(MF, IsPIC);
  MMI = &getAnalysis<MachineModuleInfo>();
  MCE.setModuleInfo(MMI);

  do {
    DEBUG(errs() << "JITTing function '"
          << MF.getFunction()->getName() << "'\n");
    MCE.startFunction(MF);
    for (MachineFunction::iterator MBB = MF.begin(), E = MF.end();
         MBB != E; ++MBB) {
      MCE.StartMachineBasicBlock(MBB);
      for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end();
           I != E; ++I)
        emitInstruction(*I);
    }
  } while (MCE.finishFunction(MF));

  return false;
}

/// getShiftOp - Return the shift opcode (bit[6:5]) of the immediate value.
///
unsigned ARMCodeEmitter::getShiftOp(unsigned Imm) const {
  switch (ARM_AM::getAM2ShiftOpc(Imm)) {
  default: llvm_unreachable("Unknown shift opc!");
  case ARM_AM::asr: return 2;
  case ARM_AM::lsl: return 0;
  case ARM_AM::lsr: return 1;
  case ARM_AM::ror:
  case ARM_AM::rrx: return 3;
  }
  return 0;
}

/// getMovi32Value - Return binary encoding of operand for movw/movt. If the
/// machine operand requires relocation, record the relocation and return zero.
unsigned ARMCodeEmitter::getMovi32Value(const MachineInstr &MI,
                                        const MachineOperand &MO,
                                        unsigned Reloc) {
  assert(((Reloc == ARM::reloc_arm_movt) || (Reloc == ARM::reloc_arm_movw))
      && "Relocation to this function should be for movt or movw");

  if (MO.isImm())
    return static_cast<unsigned>(MO.getImm());
  else if (MO.isGlobal())
    emitGlobalAddress(MO.getGlobal(), Reloc, true, false);
  else if (MO.isSymbol())
    emitExternalSymbolAddress(MO.getSymbolName(), Reloc);
  else if (MO.isMBB())
    emitMachineBasicBlock(MO.getMBB(), Reloc);
  else {
#ifndef NDEBUG
    errs() << MO;
#endif
    llvm_unreachable("Unsupported operand type for movw/movt");
  }
  return 0;
}

/// getMachineOpValue - Return binary encoding of operand. If the machine
/// operand requires relocation, record the relocation and return zero.
unsigned ARMCodeEmitter::getMachineOpValue(const MachineInstr &MI,
                                           const MachineOperand &MO) const {
  if (MO.isReg())
    return getARMRegisterNumbering(MO.getReg());
  else if (MO.isImm())
    return static_cast<unsigned>(MO.getImm());
  else if (MO.isGlobal())
    emitGlobalAddress(MO.getGlobal(), ARM::reloc_arm_branch, true, false);
  else if (MO.isSymbol())
    emitExternalSymbolAddress(MO.getSymbolName(), ARM::reloc_arm_branch);
  else if (MO.isCPI()) {
    const TargetInstrDesc &TID = MI.getDesc();
    // For VFP load, the immediate offset is multiplied by 4.
    unsigned Reloc =  ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPLdStFrm)
      ? ARM::reloc_arm_vfp_cp_entry : ARM::reloc_arm_cp_entry;
    emitConstPoolAddress(MO.getIndex(), Reloc);
  } else if (MO.isJTI())
    emitJumpTableAddress(MO.getIndex(), ARM::reloc_arm_relative);
  else if (MO.isMBB())
    emitMachineBasicBlock(MO.getMBB(), ARM::reloc_arm_branch);
  else
    llvm_unreachable("Unable to encode MachineOperand!");
  return 0;
}

/// emitGlobalAddress - Emit the specified address to the code stream.
///
void ARMCodeEmitter::emitGlobalAddress(const GlobalValue *GV, unsigned Reloc,
                                       bool MayNeedFarStub, bool Indirect,
                                       intptr_t ACPV) const {
  MachineRelocation MR = Indirect
    ? MachineRelocation::getIndirectSymbol(MCE.getCurrentPCOffset(), Reloc,
                                           const_cast<GlobalValue *>(GV),
                                           ACPV, MayNeedFarStub)
    : MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc,
                               const_cast<GlobalValue *>(GV), ACPV,
                               MayNeedFarStub);
  MCE.addRelocation(MR);
}

/// emitExternalSymbolAddress - Arrange for the address of an external symbol to
/// be emitted to the current location in the function, and allow it to be PC
/// relative.
void ARMCodeEmitter::
emitExternalSymbolAddress(const char *ES, unsigned Reloc) const {
  MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(),
                                                 Reloc, ES));
}

/// emitConstPoolAddress - Arrange for the address of an constant pool
/// to be emitted to the current location in the function, and allow it to be PC
/// relative.
void ARMCodeEmitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc) const {
  // Tell JIT emitter we'll resolve the address.
  MCE.addRelocation(MachineRelocation::getConstPool(MCE.getCurrentPCOffset(),
                                                    Reloc, CPI, 0, true));
}

/// emitJumpTableAddress - Arrange for the address of a jump table to
/// be emitted to the current location in the function, and allow it to be PC
/// relative.
void ARMCodeEmitter::
emitJumpTableAddress(unsigned JTIndex, unsigned Reloc) const {
  MCE.addRelocation(MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(),
                                                    Reloc, JTIndex, 0, true));
}

/// emitMachineBasicBlock - Emit the specified address basic block.
void ARMCodeEmitter::emitMachineBasicBlock(MachineBasicBlock *BB,
                                           unsigned Reloc,
                                           intptr_t JTBase) const {
  MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(),
                                             Reloc, BB, JTBase));
}

void ARMCodeEmitter::emitWordLE(unsigned Binary) {
  DEBUG(errs() << "  0x";
        errs().write_hex(Binary) << "\n");
  MCE.emitWordLE(Binary);
}

void ARMCodeEmitter::emitDWordLE(uint64_t Binary) {
  DEBUG(errs() << "  0x";
        errs().write_hex(Binary) << "\n");
  MCE.emitDWordLE(Binary);
}

void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) {
  DEBUG(errs() << "JIT: " << (void*)MCE.getCurrentPCValue() << ":\t" << MI);

  MCE.processDebugLoc(MI.getDebugLoc(), true);

  ++NumEmitted;  // Keep track of the # of mi's emitted
  switch (MI.getDesc().TSFlags & ARMII::FormMask) {
  default: {
    llvm_unreachable("Unhandled instruction encoding format!");
    break;
  }
  case ARMII::MiscFrm:
    if (MI.getOpcode() == ARM::LEApcrelJT) {
      // Materialize jumptable address.
      emitLEApcrelJTInstruction(MI);
      break;
    }
    llvm_unreachable("Unhandled instruction encoding!");
    break;
  case ARMII::Pseudo:
    emitPseudoInstruction(MI);
    break;
  case ARMII::DPFrm:
  case ARMII::DPSoRegFrm:
    emitDataProcessingInstruction(MI);
    break;
  case ARMII::LdFrm:
  case ARMII::StFrm:
    emitLoadStoreInstruction(MI);
    break;
  case ARMII::LdMiscFrm:
  case ARMII::StMiscFrm:
    emitMiscLoadStoreInstruction(MI);
    break;
  case ARMII::LdStMulFrm:
    emitLoadStoreMultipleInstruction(MI);
    break;
  case ARMII::MulFrm:
    emitMulFrmInstruction(MI);
    break;
  case ARMII::ExtFrm:
    emitExtendInstruction(MI);
    break;
  case ARMII::ArithMiscFrm:
    emitMiscArithInstruction(MI);
    break;
  case ARMII::SatFrm:
    emitSaturateInstruction(MI);
    break;
  case ARMII::BrFrm:
    emitBranchInstruction(MI);
    break;
  case ARMII::BrMiscFrm:
    emitMiscBranchInstruction(MI);
    break;
  // VFP instructions.
  case ARMII::VFPUnaryFrm:
  case ARMII::VFPBinaryFrm:
    emitVFPArithInstruction(MI);
    break;
  case ARMII::VFPConv1Frm:
  case ARMII::VFPConv2Frm:
  case ARMII::VFPConv3Frm:
  case ARMII::VFPConv4Frm:
  case ARMII::VFPConv5Frm:
    emitVFPConversionInstruction(MI);
    break;
  case ARMII::VFPLdStFrm:
    emitVFPLoadStoreInstruction(MI);
    break;
  case ARMII::VFPLdStMulFrm:
    emitVFPLoadStoreMultipleInstruction(MI);
    break;

  // NEON instructions.
  case ARMII::NGetLnFrm:
  case ARMII::NSetLnFrm:
    emitNEONLaneInstruction(MI);
    break;
  case ARMII::NDupFrm:
    emitNEONDupInstruction(MI);
    break;
  case ARMII::N1RegModImmFrm:
    emitNEON1RegModImmInstruction(MI);
    break;
  case ARMII::N2RegFrm:
    emitNEON2RegInstruction(MI);
    break;
  case ARMII::N3RegFrm:
    emitNEON3RegInstruction(MI);
    break;
  }
  MCE.processDebugLoc(MI.getDebugLoc(), false);
}

void ARMCodeEmitter::emitConstPoolInstruction(const MachineInstr &MI) {
  unsigned CPI = MI.getOperand(0).getImm();       // CP instruction index.
  unsigned CPIndex = MI.getOperand(1).getIndex(); // Actual cp entry index.
  const MachineConstantPoolEntry &MCPE = (*MCPEs)[CPIndex];

  // Remember the CONSTPOOL_ENTRY address for later relocation.
  JTI->addConstantPoolEntryAddr(CPI, MCE.getCurrentPCValue());

  // Emit constpool island entry. In most cases, the actual values will be
  // resolved and relocated after code emission.
  if (MCPE.isMachineConstantPoolEntry()) {
    ARMConstantPoolValue *ACPV =
      static_cast<ARMConstantPoolValue*>(MCPE.Val.MachineCPVal);

    DEBUG(errs() << "  ** ARM constant pool #" << CPI << " @ "
          << (void*)MCE.getCurrentPCValue() << " " << *ACPV << '\n');

    assert(ACPV->isGlobalValue() && "unsupported constant pool value");
    const GlobalValue *GV = ACPV->getGV();
    if (GV) {
      Reloc::Model RelocM = TM.getRelocationModel();
      emitGlobalAddress(GV, ARM::reloc_arm_machine_cp_entry,
                        isa<Function>(GV),
                        Subtarget->GVIsIndirectSymbol(GV, RelocM),
                        (intptr_t)ACPV);
     } else  {
      emitExternalSymbolAddress(ACPV->getSymbol(), ARM::reloc_arm_absolute);
    }
    emitWordLE(0);
  } else {
    const Constant *CV = MCPE.Val.ConstVal;

    DEBUG({
        errs() << "  ** Constant pool #" << CPI << " @ "
               << (void*)MCE.getCurrentPCValue() << " ";
        if (const Function *F = dyn_cast<Function>(CV))
          errs() << F->getName();
        else
          errs() << *CV;
        errs() << '\n';
      });

    if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
      emitGlobalAddress(GV, ARM::reloc_arm_absolute, isa<Function>(GV), false);
      emitWordLE(0);
    } else if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
      uint32_t Val = uint32_t(*CI->getValue().getRawData());
      emitWordLE(Val);
    } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
      if (CFP->getType()->isFloatTy())
        emitWordLE(CFP->getValueAPF().bitcastToAPInt().getZExtValue());
      else if (CFP->getType()->isDoubleTy())
        emitDWordLE(CFP->getValueAPF().bitcastToAPInt().getZExtValue());
      else {
        llvm_unreachable("Unable to handle this constantpool entry!");
      }
    } else {
      llvm_unreachable("Unable to handle this constantpool entry!");
    }
  }
}

void ARMCodeEmitter::emitMOVi32immInstruction(const MachineInstr &MI) {
  const MachineOperand &MO0 = MI.getOperand(0);
  const MachineOperand &MO1 = MI.getOperand(1);

  // Emit the 'movw' instruction.
  unsigned Binary = 0x30 << 20;  // mov: Insts{27-20} = 0b00110000

  unsigned Lo16 = getMovi32Value(MI, MO1, ARM::reloc_arm_movw) & 0xFFFF;

  // Set the conditional execution predicate.
  Binary |= II->getPredicate(&MI) << ARMII::CondShift;

  // Encode Rd.
  Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRdShift;

  // Encode imm16 as imm4:imm12
  Binary |= Lo16 & 0xFFF; // Insts{11-0} = imm12
  Binary |= ((Lo16 >> 12) & 0xF) << 16; // Insts{19-16} = imm4
  emitWordLE(Binary);

  unsigned Hi16 = getMovi32Value(MI, MO1, ARM::reloc_arm_movt) >> 16;
  // Emit the 'movt' instruction.
  Binary = 0x34 << 20; // movt: Insts{27-20} = 0b00110100

  // Set the conditional execution predicate.
  Binary |= II->getPredicate(&MI) << ARMII::CondShift;

  // Encode Rd.
  Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRdShift;

  // Encode imm16 as imm4:imm1, same as movw above.
  Binary |= Hi16 & 0xFFF;
  Binary |= ((Hi16 >> 12) & 0xF) << 16;
  emitWordLE(Binary);
}

void ARMCodeEmitter::emitMOVi2piecesInstruction(const MachineInstr &MI) {
  const MachineOperand &MO0 = MI.getOperand(0);
  const MachineOperand &MO1 = MI.getOperand(1);
  assert(MO1.isImm() && ARM_AM::isSOImmTwoPartVal(MO1.getImm()) &&
                                                  "Not a valid so_imm value!");
  unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO1.getImm());
  unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO1.getImm());

  // Emit the 'mov' instruction.
  unsigned Binary = 0xd << 21;  // mov: Insts{24-21} = 0b1101

  // Set the conditional execution predicate.
  Binary |= II->getPredicate(&MI) << ARMII::CondShift;

  // Encode Rd.
  Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRdShift;

  // Encode so_imm.
  // Set bit I(25) to identify this is the immediate form of <shifter_op>
  Binary |= 1 << ARMII::I_BitShift;
  Binary |= getMachineSoImmOpValue(V1);
  emitWordLE(Binary);

  // Now the 'orr' instruction.
  Binary = 0xc << 21;  // orr: Insts{24-21} = 0b1100

  // Set the conditional execution predicate.
  Binary |= II->getPredicate(&MI) << ARMII::CondShift;

  // Encode Rd.
  Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRdShift;

  // Encode Rn.
  Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRnShift;

  // Encode so_imm.
  // Set bit I(25) to identify this is the immediate form of <shifter_op>
  Binary |= 1 << ARMII::I_BitShift;
  Binary |= getMachineSoImmOpValue(V2);
  emitWordLE(Binary);
}

void ARMCodeEmitter::emitLEApcrelJTInstruction(const MachineInstr &MI) {
  // It's basically add r, pc, (LJTI - $+8)

  const TargetInstrDesc &TID = MI.getDesc();

  // Emit the 'add' instruction.
  unsigned Binary = 0x4 << 21;  // add: Insts{24-21} = 0b0100

  // Set the conditional execution predicate
  Binary |= II->getPredicate(&MI) << ARMII::CondShift;

  // Encode S bit if MI modifies CPSR.
  Binary |= getAddrModeSBit(MI, TID);

  // Encode Rd.
  Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift;

  // Encode Rn which is PC.
  Binary |= getARMRegisterNumbering(ARM::PC) << ARMII::RegRnShift;

  // Encode the displacement.
  Binary |= 1 << ARMII::I_BitShift;
  emitJumpTableAddress(MI.getOperand(1).getIndex(), ARM::reloc_arm_jt_base);

  emitWordLE(Binary);
}

void ARMCodeEmitter::emitPseudoMoveInstruction(const MachineInstr &MI) {
  unsigned Opcode = MI.getDesc().Opcode;

  // Part of binary is determined by TableGn.
  unsigned Binary = getBinaryCodeForInstr(MI);

  // Set the conditional execution predicate
  Binary |= II->getPredicate(&MI) << ARMII::CondShift;

  // Encode S bit if MI modifies CPSR.
  if (Opcode == ARM::MOVsrl_flag || Opcode == ARM::MOVsra_flag)
    Binary |= 1 << ARMII::S_BitShift;

  // Encode register def if there is one.
  Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift;

  // Encode the shift operation.
  switch (Opcode) {
  default: break;
  case ARM::RRX:
    // rrx
    Binary |= 0x6 << 4;
    break;
  case ARM::MOVsrl_flag:
    // lsr #1
    Binary |= (0x2 << 4) | (1 << 7);
    break;
  case ARM::MOVsra_flag:
    // asr #1
    Binary |= (0x4 << 4) | (1 << 7);
    break;
  }

  // Encode register Rm.
  Binary |= getMachineOpValue(MI, 1);

  emitWordLE(Binary);
}

void ARMCodeEmitter::addPCLabel(unsigned LabelID) {
  DEBUG(errs() << "  ** LPC" << LabelID << " @ "
        << (void*)MCE.getCurrentPCValue() << '\n');
  JTI->addPCLabelAddr(LabelID, MCE.getCurrentPCValue());
}

void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) {
  unsigned Opcode = MI.getDesc().Opcode;
  switch (Opcode) {
  default:
    llvm_unreachable("ARMCodeEmitter::emitPseudoInstruction");
  case ARM::BX_CALL:
  case ARM::BMOVPCRX_CALL:
  case ARM::BXr9_CALL:
  case ARM::BMOVPCRXr9_CALL: {
    // First emit mov lr, pc
    unsigned Binary = 0x01a0e00f;
    Binary |= II->getPredicate(&MI) << ARMII::CondShift;
    emitWordLE(Binary);

    // and then emit the branch.
    emitMiscBranchInstruction(MI);
    break;
  }
  case TargetOpcode::INLINEASM: {
    // We allow inline assembler nodes with empty bodies - they can
    // implicitly define registers, which is ok for JIT.
    if (MI.getOperand(0).getSymbolName()[0]) {
      report_fatal_error("JIT does not support inline asm!");
    }
    break;
  }
  case TargetOpcode::PROLOG_LABEL:
  case TargetOpcode::EH_LABEL:
    MCE.emitLabel(MI.getOperand(0).getMCSymbol());
    break;
  case TargetOpcode::IMPLICIT_DEF:
  case TargetOpcode::KILL:
    // Do nothing.
    break;
  case ARM::CONSTPOOL_ENTRY:
    emitConstPoolInstruction(MI);
    break;
  case ARM::PICADD: {
    // Remember of the address of the PC label for relocation later.
    addPCLabel(MI.getOperand(2).getImm());
    // PICADD is just an add instruction that implicitly read pc.
    emitDataProcessingInstruction(MI, 0, ARM::PC);
    break;
  }
  case ARM::PICLDR:
  case ARM::PICLDRB:
  case ARM::PICSTR:
  case ARM::PICSTRB: {
    // Remember of the address of the PC label for relocation later.
    addPCLabel(MI.getOperand(2).getImm());
    // These are just load / store instructions that implicitly read pc.
    emitLoadStoreInstruction(MI, 0, ARM::PC);
    break;
  }
  case ARM::PICLDRH:
  case ARM::PICLDRSH:
  case ARM::PICLDRSB:
  case ARM::PICSTRH: {
    // Remember of the address of the PC label for relocation later.
    addPCLabel(MI.getOperand(2).getImm());
    // These are just load / store instructions that implicitly read pc.
    emitMiscLoadStoreInstruction(MI, ARM::PC);
    break;
  }

  case ARM::MOVi32imm:
    // Two instructions to materialize a constant.
    if (Subtarget->hasV6T2Ops())
      emitMOVi32immInstruction(MI);
    else
      emitMOVi2piecesInstruction(MI);
    break;

  case ARM::LEApcrelJT:
    // Materialize jumptable address.
    emitLEApcrelJTInstruction(MI);
    break;
  case ARM::RRX:
  case ARM::MOVsrl_flag:
  case ARM::MOVsra_flag:
    emitPseudoMoveInstruction(MI);
    break;
  }
}

unsigned ARMCodeEmitter::getMachineSoRegOpValue(const MachineInstr &MI,
                                                const TargetInstrDesc &TID,
                                                const MachineOperand &MO,
                                                unsigned OpIdx) {
  unsigned Binary = getMachineOpValue(MI, MO);

  const MachineOperand &MO1 = MI.getOperand(OpIdx + 1);
  const MachineOperand &MO2 = MI.getOperand(OpIdx + 2);
  ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO2.getImm());

  // Encode the shift opcode.
  unsigned SBits = 0;
  unsigned Rs = MO1.getReg();
  if (Rs) {
    // Set shift operand (bit[7:4]).
    // LSL - 0001
    // LSR - 0011
    // ASR - 0101
    // ROR - 0111
    // RRX - 0110 and bit[11:8] clear.
    switch (SOpc) {
    default: llvm_unreachable("Unknown shift opc!");
    case ARM_AM::lsl: SBits = 0x1; break;
    case ARM_AM::lsr: SBits = 0x3; break;
    case ARM_AM::asr: SBits = 0x5; break;
    case ARM_AM::ror: SBits = 0x7; break;
    case ARM_AM::rrx: SBits = 0x6; break;
    }
  } else {
    // Set shift operand (bit[6:4]).
    // LSL - 000
    // LSR - 010
    // ASR - 100
    // ROR - 110
    switch (SOpc) {
    default: llvm_unreachable("Unknown shift opc!");
    case ARM_AM::lsl: SBits = 0x0; break;
    case ARM_AM::lsr: SBits = 0x2; break;
    case ARM_AM::asr: SBits = 0x4; break;
    case ARM_AM::ror: SBits = 0x6; break;
    }
  }
  Binary |= SBits << 4;
  if (SOpc == ARM_AM::rrx)
    return Binary;

  // Encode the shift operation Rs or shift_imm (except rrx).
  if (Rs) {
    // Encode Rs bit[11:8].
    assert(ARM_AM::getSORegOffset(MO2.getImm()) == 0);
    return Binary | (getARMRegisterNumbering(Rs) << ARMII::RegRsShift);
  }

  // Encode shift_imm bit[11:7].
  return Binary | ARM_AM::getSORegOffset(MO2.getImm()) << 7;
}

unsigned ARMCodeEmitter::getMachineSoImmOpValue(unsigned SoImm) {
  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;
}

unsigned ARMCodeEmitter::getAddrModeSBit(const MachineInstr &MI,
                                         const TargetInstrDesc &TID) const {
  for (unsigned i = MI.getNumOperands(), e = TID.getNumOperands(); i >= e; --i){
    const MachineOperand &MO = MI.getOperand(i-1);
    if (MO.isReg() && MO.isDef() && MO.getReg() == ARM::CPSR)
      return 1 << ARMII::S_BitShift;
  }
  return 0;
}

void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI,
                                                   unsigned ImplicitRd,
                                                   unsigned ImplicitRn) {
  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;

  // Encode S bit if MI modifies CPSR.
  Binary |= getAddrModeSBit(MI, TID);

  // Encode register def if there is one.
  unsigned NumDefs = TID.getNumDefs();
  unsigned OpIdx = 0;
  if (NumDefs)
    Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift;
  else if (ImplicitRd)
    // Special handling for implicit use (e.g. PC).
    Binary |= (getARMRegisterNumbering(ImplicitRd) << ARMII::RegRdShift);

  if (TID.Opcode == ARM::MOVi16) {
      // Get immediate from MI.
      unsigned Lo16 = getMovi32Value(MI, MI.getOperand(OpIdx),
                      ARM::reloc_arm_movw);
      // Encode imm which is the same as in emitMOVi32immInstruction().
      Binary |= Lo16 & 0xFFF;
      Binary |= ((Lo16 >> 12) & 0xF) << 16;
      emitWordLE(Binary);
      return;
  } else if(TID.Opcode == ARM::MOVTi16) {
      unsigned Hi16 = (getMovi32Value(MI, MI.getOperand(OpIdx),
                       ARM::reloc_arm_movt) >> 16);
      Binary |= Hi16 & 0xFFF;
      Binary |= ((Hi16 >> 12) & 0xF) << 16;
      emitWordLE(Binary);
      return;
  } else if ((TID.Opcode == ARM::BFC) || (TID.Opcode == ARM::BFI)) {
      uint32_t v = ~MI.getOperand(2).getImm();
      int32_t lsb = CountTrailingZeros_32(v);
      int32_t msb = (32 - CountLeadingZeros_32(v)) - 1;
      // Instr{20-16} = msb, Instr{11-7} = lsb
      Binary |= (msb & 0x1F) << 16;
      Binary |= (lsb & 0x1F) << 7;
      emitWordLE(Binary);
      return;
  } else if ((TID.Opcode == ARM::UBFX) || (TID.Opcode == ARM::SBFX)) {
      // Encode Rn in Instr{0-3}
      Binary |= getMachineOpValue(MI, OpIdx++);

      uint32_t lsb = MI.getOperand(OpIdx++).getImm();
      uint32_t widthm1 = MI.getOperand(OpIdx++).getImm() - 1;

      // Instr{20-16} = widthm1, Instr{11-7} = lsb
      Binary |= (widthm1 & 0x1F) << 16;
      Binary |= (lsb & 0x1F) << 7;
      emitWordLE(Binary);
      return;
  }

  // If this is a two-address operand, skip it. e.g. MOVCCr operand 1.
  if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)
    ++OpIdx;

  // Encode first non-shifter register operand if there is one.
  bool isUnary = TID.TSFlags & ARMII::UnaryDP;
  if (!isUnary) {
    if (ImplicitRn)
      // Special handling for implicit use (e.g. PC).
      Binary |= (getARMRegisterNumbering(ImplicitRn) << ARMII::RegRnShift);
    else {
      Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRnShift;
      ++OpIdx;
    }
  }

  // Encode shifter operand.
  const MachineOperand &MO = MI.getOperand(OpIdx);
  if ((TID.TSFlags & ARMII::FormMask) == ARMII::DPSoRegFrm) {
    // Encode SoReg.
    emitWordLE(Binary | getMachineSoRegOpValue(MI, TID, MO, OpIdx));
    return;
  }

  if (MO.isReg()) {
    // Encode register Rm.
    emitWordLE(Binary | getARMRegisterNumbering(MO.getReg()));
    return;
  }

  // Encode so_imm.
  Binary |= getMachineSoImmOpValue((unsigned)MO.getImm());

  emitWordLE(Binary);
}

void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI,
                                              unsigned ImplicitRd,
                                              unsigned ImplicitRn) {
  const TargetInstrDesc &TID = MI.getDesc();
  unsigned Form = TID.TSFlags & ARMII::FormMask;
  bool IsPrePost = (TID.TSFlags & ARMII::IndexModeMask) != 0;

  // Part of binary is determined by TableGn.
  unsigned Binary = getBinaryCodeForInstr(MI);

  // If this is an LDRi12, STRi12 or LDRcp, nothing more needs be done.
  if (MI.getOpcode() == ARM::LDRi12 || MI.getOpcode() == ARM::LDRcp ||
      MI.getOpcode() == ARM::STRi12) {
    emitWordLE(Binary);
    return;
  }

  // Set the conditional execution predicate
  Binary |= II->getPredicate(&MI) << ARMII::CondShift;

  unsigned OpIdx = 0;

  // Operand 0 of a pre- and post-indexed store is the address base
  // writeback. Skip it.
  bool Skipped = false;
  if (IsPrePost && Form == ARMII::StFrm) {
    ++OpIdx;
    Skipped = true;
  }

  // Set first operand
  if (ImplicitRd)
    // Special handling for implicit use (e.g. PC).
    Binary |= (getARMRegisterNumbering(ImplicitRd) << ARMII::RegRdShift);
  else
    Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift;

  // Set second operand
  if (ImplicitRn)
    // Special handling for implicit use (e.g. PC).
    Binary |= (getARMRegisterNumbering(ImplicitRn) << ARMII::RegRnShift);
  else
    Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift;

  // If this is a two-address operand, skip it. e.g. LDR_PRE.
  if (!Skipped && TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)
    ++OpIdx;

  const MachineOperand &MO2 = MI.getOperand(OpIdx);
  unsigned AM2Opc = (ImplicitRn == ARM::PC)
    ? 0 : MI.getOperand(OpIdx+1).getImm();

  // Set bit U(23) according to sign of immed value (positive or negative).
  Binary |= ((ARM_AM::getAM2Op(AM2Opc) == ARM_AM::add ? 1 : 0) <<
             ARMII::U_BitShift);
  if (!MO2.getReg()) { // is immediate
    if (ARM_AM::getAM2Offset(AM2Opc))
      // Set the value of offset_12 field
      Binary |= ARM_AM::getAM2Offset(AM2Opc);
    emitWordLE(Binary);
    return;
  }

  // Set bit I(25), because this is not in immediate encoding.
  Binary |= 1 << ARMII::I_BitShift;
  assert(TargetRegisterInfo::isPhysicalRegister(MO2.getReg()));
  // Set bit[3:0] to the corresponding Rm register
  Binary |= getARMRegisterNumbering(MO2.getReg());

  // If this instr is in scaled register offset/index instruction, set
  // shift_immed(bit[11:7]) and shift(bit[6:5]) fields.
  if (unsigned ShImm = ARM_AM::getAM2Offset(AM2Opc)) {
    Binary |= getShiftOp(AM2Opc) << ARMII::ShiftImmShift;  // shift
    Binary |= ShImm              << ARMII::ShiftShift;     // shift_immed
  }

  emitWordLE(Binary);
}

void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI,
                                                  unsigned ImplicitRn) {
  const TargetInstrDesc &TID = MI.getDesc();
  unsigned Form = TID.TSFlags & ARMII::FormMask;
  bool IsPrePost = (TID.TSFlags & ARMII::IndexModeMask) != 0;

  // 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;

  // Operand 0 of a pre- and post-indexed store is the address base
  // writeback. Skip it.
  bool Skipped = false;
  if (IsPrePost && Form == ARMII::StMiscFrm) {
    ++OpIdx;
    Skipped = true;
  }

  // Set first operand
  Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift;

  // Skip LDRD and STRD's second operand.
  if (TID.Opcode == ARM::LDRD || TID.Opcode == ARM::STRD)
    ++OpIdx;

  // Set second operand
  if (ImplicitRn)
    // Special handling for implicit use (e.g. PC).
    Binary |= (getARMRegisterNumbering(ImplicitRn) << ARMII::RegRnShift);
  else
    Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift;

  // If this is a two-address operand, skip it. e.g. LDRH_POST.
  if (!Skipped && TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)
    ++OpIdx;

  const MachineOperand &MO2 = MI.getOperand(OpIdx);
  unsigned AM3Opc = (ImplicitRn == ARM::PC)
    ? 0 : MI.getOperand(OpIdx+1).getImm();

  // Set bit U(23) according to sign of immed value (positive or negative)
  Binary |= ((ARM_AM::getAM3Op(AM3Opc) == ARM_AM::add ? 1 : 0) <<
             ARMII::U_BitShift);

  // If this instr is in register offset/index encoding, set bit[3:0]
  // to the corresponding Rm register.
  if (MO2.getReg()) {
    Binary |= getARMRegisterNumbering(MO2.getReg());
    emitWordLE(Binary);
    return;
  }

  // This instr is in immediate offset/index encoding, set bit 22 to 1.
  Binary |= 1 << ARMII::AM3_I_BitShift;
  if (unsigned ImmOffs = ARM_AM::getAM3Offset(AM3Opc)) {
    // Set operands
    Binary |= (ImmOffs >> 4) << ARMII::ImmHiShift;  // immedH
    Binary |= (ImmOffs & 0xF);                      // immedL
  }

  emitWordLE(Binary);
}

static unsigned getAddrModeUPBits(unsigned Mode) {
  unsigned Binary = 0;

  // Set addressing mode by modifying bits U(23) and P(24)
  // IA - Increment after  - bit U = 1 and bit P = 0
  // IB - Increment before - bit U = 1 and bit P = 1
  // DA - Decrement after  - bit U = 0 and bit P = 0
  // DB - Decrement before - bit U = 0 and bit P = 1
  switch (Mode) {
  default: llvm_unreachable("Unknown addressing sub-mode!");
  case ARM_AM::da:                                     break;
  case ARM_AM::db: Binary |= 0x1 << ARMII::P_BitShift; break;
  case ARM_AM::ia: Binary |= 0x1 << ARMII::U_BitShift; break;
  case ARM_AM::ib: Binary |= 0x3 << ARMII::U_BitShift; break;
  }

  return Binary;
}

void ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) {
  const TargetInstrDesc &TID = MI.getDesc();
  bool IsUpdating = (TID.TSFlags & ARMII::IndexModeMask) != 0;

  // Part of binary is determined by TableGn.
  unsigned Binary = getBinaryCodeForInstr(MI);

  // Set the conditional execution predicate
  Binary |= II->getPredicate(&MI) << ARMII::CondShift;

  // Skip operand 0 of an instruction with base register update.
  unsigned OpIdx = 0;
  if (IsUpdating)
    ++OpIdx;

  // Set base address operand
  Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift;

  // Set addressing mode by modifying bits U(23) and P(24)
  ARM_AM::AMSubMode Mode = ARM_AM::getLoadStoreMultipleSubMode(MI.getOpcode());
  Binary |= getAddrModeUPBits(ARM_AM::getAM4SubMode(Mode));

  // Set bit W(21)
  if (IsUpdating)
    Binary |= 0x1 << ARMII::W_BitShift;

  // Set registers
  for (unsigned i = OpIdx+2, e = MI.getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI.getOperand(i);
    if (!MO.isReg() || MO.isImplicit())
      break;
    unsigned RegNum = getARMRegisterNumbering(MO.getReg());
    assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
           RegNum < 16);
    Binary |= 0x1 << RegNum;
  }

  emitWordLE(Binary);
}

void ARMCodeEmitter::emitMulFrmInstruction(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;

  // Encode S bit if MI modifies CPSR.
  Binary |= getAddrModeSBit(MI, TID);

  // 32x32->64bit operations have two destination registers. The number
  // of register definitions will tell us if that's what we're dealing with.
  unsigned OpIdx = 0;
  if (TID.getNumDefs() == 2)
    Binary |= getMachineOpValue (MI, OpIdx++) << ARMII::RegRdLoShift;

  // Encode Rd
  Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdHiShift;

  // Encode Rm
  Binary |= getMachineOpValue(MI, OpIdx++);

  // Encode Rs
  Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRsShift;

  // Many multiple instructions (e.g. MLA) have three src operands. Encode
  // it as Rn (for multiply, that's in the same offset as RdLo.
  if (TID.getNumOperands() > OpIdx &&
      !TID.OpInfo[OpIdx].isPredicate() &&
      !TID.OpInfo[OpIdx].isOptionalDef())
    Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRdLoShift;

  emitWordLE(Binary);
}

void ARMCodeEmitter::emitExtendInstruction(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;

  // Encode Rd
  Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift;

  const MachineOperand &MO1 = MI.getOperand(OpIdx++);
  const MachineOperand &MO2 = MI.getOperand(OpIdx);
  if (MO2.isReg()) {
    // Two register operand form.
    // Encode Rn.
    Binary |= getMachineOpValue(MI, MO1) << ARMII::RegRnShift;

    // Encode Rm.
    Binary |= getMachineOpValue(MI, MO2);
    ++OpIdx;
  } else {
    Binary |= getMachineOpValue(MI, MO1);
  }

  // Encode rot imm (0, 8, 16, or 24) if it has a rotate immediate operand.
  if (MI.getOperand(OpIdx).isImm() &&
      !TID.OpInfo[OpIdx].isPredicate() &&
      !TID.OpInfo[OpIdx].isOptionalDef())
    Binary |= (getMachineOpValue(MI, OpIdx) / 8) << ARMII::ExtRotImmShift;

  emitWordLE(Binary);
}

void ARMCodeEmitter::emitMiscArithInstruction(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;

  // Encode Rd
  Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift;

  const MachineOperand &MO = MI.getOperand(OpIdx++);
  if (OpIdx == TID.getNumOperands() ||
      TID.OpInfo[OpIdx].isPredicate() ||
      TID.OpInfo[OpIdx].isOptionalDef()) {
    // Encode Rm and it's done.
    Binary |= getMachineOpValue(MI, MO);
    emitWordLE(Binary);
    return;
  }

  // Encode Rn.
  Binary |= getMachineOpValue(MI, MO) << ARMII::RegRnShift;

  // Encode Rm.
  Binary |= getMachineOpValue(MI, OpIdx++);

  // Encode shift_imm.
  unsigned ShiftAmt = MI.getOperand(OpIdx).getImm();
  if (TID.Opcode == ARM::PKHTB) {
    assert(ShiftAmt != 0 && "PKHTB shift_imm is 0!");
    if (ShiftAmt == 32)
      ShiftAmt = 0;
  }
  assert(ShiftAmt < 32 && "shift_imm range is 0 to 31!");
  Binary |= ShiftAmt << ARMII::ShiftShift;

  emitWordLE(Binary);
}

void ARMCodeEmitter::emitSaturateInstruction(const MachineInstr &MI) {
  const TargetInstrDesc &TID = MI.getDesc();

  // Part of binary is determined by TableGen.
  unsigned Binary = getBinaryCodeForInstr(MI);

  // Set the conditional execution predicate
  Binary |= II->getPredicate(&MI) << ARMII::CondShift;

  // Encode Rd
  Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift;

  // Encode saturate bit position.
  unsigned Pos = MI.getOperand(1).getImm();
  if (TID.Opcode == ARM::SSAT || TID.Opcode == ARM::SSAT16)
    Pos -= 1;
  assert((Pos < 16 || (Pos < 32 &&
                       TID.Opcode != ARM::SSAT16 &&
                       TID.Opcode != ARM::USAT16)) &&
         "saturate bit position out of range");
  Binary |= Pos << 16;

  // Encode Rm
  Binary |= getMachineOpValue(MI, 2);

  // Encode shift_imm.
  if (TID.getNumOperands() == 4) {
    unsigned ShiftOp = MI.getOperand(3).getImm();
    ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp);
    if (Opc == ARM_AM::asr)
      Binary |= (1 << 6);
    unsigned ShiftAmt = MI.getOperand(3).getImm();
    if (ShiftAmt == 32 && Opc == ARM_AM::asr)
      ShiftAmt = 0;
    assert(ShiftAmt < 32 && "shift_imm range is 0 to 31!");
    Binary |= ShiftAmt << ARMII::ShiftShift;
  }

  emitWordLE(Binary);
}

void ARMCodeEmitter::emitBranchInstruction(const MachineInstr &MI) {
  const TargetInstrDesc &TID = MI.getDesc();

  if (TID.Opcode == ARM::TPsoft) {
    llvm_unreachable("ARM::TPsoft FIXME"); // FIXME
  }

  // Part of binary is determined by TableGn.
  unsigned Binary = getBinaryCodeForInstr(MI);

  // Set the conditional execution predicate
  Binary |= II->getPredicate(&MI) << ARMII::CondShift;

  // Set signed_immed_24 field
  Binary |= getMachineOpValue(MI, 0);

  emitWordLE(Binary);
}

void ARMCodeEmitter::emitInlineJumpTable(unsigned JTIndex) {
  // Remember the base address of the inline jump table.
  uintptr_t JTBase = MCE.getCurrentPCValue();
  JTI->addJumpTableBaseAddr(JTIndex, JTBase);
  DEBUG(errs() << "  ** Jump Table #" << JTIndex << " @ " << (void*)JTBase
               << '\n');

  // Now emit the jump table entries.
  const std::vector<MachineBasicBlock*> &MBBs = (*MJTEs)[JTIndex].MBBs;
  for (unsigned i = 0, e = MBBs.size(); i != e; ++i) {
    if (IsPIC)
      // DestBB address - JT base.
      emitMachineBasicBlock(MBBs[i], ARM::reloc_arm_pic_jt, JTBase);
    else
      // Absolute DestBB address.
      emitMachineBasicBlock(MBBs[i], ARM::reloc_arm_absolute);
    emitWordLE(0);
  }
}

void ARMCodeEmitter::emitMiscBranchInstruction(const MachineInstr &MI) {
  const TargetInstrDesc &TID = MI.getDesc();

  // Handle jump tables.
  if (TID.Opcode == ARM::BR_JTr || TID.Opcode == ARM::BR_JTadd) {
    // First emit a ldr pc, [] instruction.
    emitDataProcessingInstruction(MI, ARM::PC);

    // Then emit the inline jump table.
    unsigned JTIndex =
      (TID.Opcode == ARM::BR_JTr)
      ? MI.getOperand(1).getIndex() : MI.getOperand(2).getIndex();
    emitInlineJumpTable(JTIndex);
    return;
  } else if (TID.Opcode == ARM::BR_JTm) {
    // First emit a ldr pc, [] instruction.
    emitLoadStoreInstruction(MI, ARM::PC);

    // Then emit the inline jump table.
    emitInlineJumpTable(MI.getOperand(3).getIndex());
    return;
  }

  // Part of binary is determined by TableGn.
  unsigned Binary = getBinaryCodeForInstr(MI);

  // Set the conditional execution predicate
  Binary |= II->getPredicate(&MI) << ARMII::CondShift;

  if (TID.Opcode == ARM::BX_RET || TID.Opcode == ARM::MOVPCLR)
    // The return register is LR.
    Binary |= getARMRegisterNumbering(ARM::LR);
  else
    // otherwise, set the return register
    Binary |= getMachineOpValue(MI, 0);

  emitWordLE(Binary);
}

static unsigned encodeVFPRd(const MachineInstr &MI, unsigned OpIdx) {
  unsigned RegD = MI.getOperand(OpIdx).getReg();
  unsigned Binary = 0;
  bool isSPVFP = ARM::SPRRegisterClass->contains(RegD);
  RegD = getARMRegisterNumbering(RegD);
  if (!isSPVFP)
    Binary |=   RegD               << ARMII::RegRdShift;
  else {
    Binary |= ((RegD & 0x1E) >> 1) << ARMII::RegRdShift;
    Binary |=  (RegD & 0x01)       << ARMII::D_BitShift;
  }
  return Binary;
}

static unsigned encodeVFPRn(const MachineInstr &MI, unsigned OpIdx) {
  unsigned RegN = MI.getOperand(OpIdx).getReg();
  unsigned Binary = 0;
  bool isSPVFP = ARM::SPRRegisterClass->contains(RegN);
  RegN = getARMRegisterNumbering(RegN);
  if (!isSPVFP)
    Binary |=   RegN               << ARMII::RegRnShift;
  else {
    Binary |= ((RegN & 0x1E) >> 1) << ARMII::RegRnShift;
    Binary |=  (RegN & 0x01)       << ARMII::N_BitShift;
  }
  return Binary;
}

static unsigned encodeVFPRm(const MachineInstr &MI, unsigned OpIdx) {
  unsigned RegM = MI.getOperand(OpIdx).getReg();
  unsigned Binary = 0;
  bool isSPVFP = ARM::SPRRegisterClass->contains(RegM);
  RegM = getARMRegisterNumbering(RegM);
  if (!isSPVFP)
    Binary |=   RegM;
  else {
    Binary |= ((RegM & 0x1E) >> 1);
    Binary |=  (RegM & 0x01)       << ARMII::M_BitShift;
  }
  return 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.
  Binary |= encodeVFPRd(MI, OpIdx++);

  // 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)
    Binary |= encodeVFPRn(MI, OpIdx++);

  if (OpIdx == TID.getNumOperands() ||
      TID.OpInfo[OpIdx].isPredicate() ||
      TID.OpInfo[OpIdx].isOptionalDef()) {
    // FCMPEZD etc. has only one operand.
    emitWordLE(Binary);
    return;
  }

  // Encode Dm / Sm.
  Binary |= encodeVFPRm(MI, OpIdx);

  emitWordLE(Binary);
}

void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) {
  const TargetInstrDesc &TID = MI.getDesc();
  unsigned Form = TID.TSFlags & ARMII::FormMask;

  // Part of binary is determined by TableGn.
  unsigned Binary = getBinaryCodeForInstr(MI);

  // Set the conditional execution predicate
  Binary |= II->getPredicate(&MI) << ARMII::CondShift;

  switch (Form) {
  default: break;
  case ARMII::VFPConv1Frm:
  case ARMII::VFPConv2Frm:
  case ARMII::VFPConv3Frm:
    // Encode Dd / Sd.
    Binary |= encodeVFPRd(MI, 0);
    break;
  case ARMII::VFPConv4Frm:
    // Encode Dn / Sn.
    Binary |= encodeVFPRn(MI, 0);
    break;
  case ARMII::VFPConv5Frm:
    // Encode Dm / Sm.
    Binary |= encodeVFPRm(MI, 0);
    break;
  }

  switch (Form) {
  default: break;
  case ARMII::VFPConv1Frm:
    // Encode Dm / Sm.
    Binary |= encodeVFPRm(MI, 1);
    break;
  case ARMII::VFPConv2Frm:
  case ARMII::VFPConv3Frm:
    // Encode Dn / Sn.
    Binary |= encodeVFPRn(MI, 1);
    break;
  case ARMII::VFPConv4Frm:
  case ARMII::VFPConv5Frm:
    // Encode Dd / Sd.
    Binary |= encodeVFPRd(MI, 1);
    break;
  }

  if (Form == ARMII::VFPConv5Frm)
    // Encode Dn / Sn.
    Binary |= encodeVFPRn(MI, 2);
  else if (Form == ARMII::VFPConv3Frm)
    // Encode Dm / Sm.
    Binary |= encodeVFPRm(MI, 2);

  emitWordLE(Binary);
}

void ARMCodeEmitter::emitVFPLoadStoreInstruction(const MachineInstr &MI) {
  // 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;

  // Encode Dd / Sd.
  Binary |= encodeVFPRd(MI, OpIdx++);

  // Encode address base.
  const MachineOperand &Base = MI.getOperand(OpIdx++);
  Binary |= getMachineOpValue(MI, Base) << ARMII::RegRnShift;

  // If there is a non-zero immediate offset, encode it.
  if (Base.isReg()) {
    const MachineOperand &Offset = MI.getOperand(OpIdx);
    if (unsigned ImmOffs = ARM_AM::getAM5Offset(Offset.getImm())) {
      if (ARM_AM::getAM5Op(Offset.getImm()) == ARM_AM::add)
        Binary |= 1 << ARMII::U_BitShift;
      Binary |= ImmOffs;
      emitWordLE(Binary);
      return;
    }
  }

  // If immediate offset is omitted, default to +0.
  Binary |= 1 << ARMII::U_BitShift;

  emitWordLE(Binary);
}

void
ARMCodeEmitter::emitVFPLoadStoreMultipleInstruction(const MachineInstr &MI) {
  const TargetInstrDesc &TID = MI.getDesc();
  bool IsUpdating = (TID.TSFlags & ARMII::IndexModeMask) != 0;

  // Part of binary is determined by TableGn.
  unsigned Binary = getBinaryCodeForInstr(MI);

  // Set the conditional execution predicate
  Binary |= II->getPredicate(&MI) << ARMII::CondShift;

  // Skip operand 0 of an instruction with base register update.
  unsigned OpIdx = 0;
  if (IsUpdating)
    ++OpIdx;

  // Set base address operand
  Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift;

  // Set addressing mode by modifying bits U(23) and P(24)
  ARM_AM::AMSubMode Mode = ARM_AM::getLoadStoreMultipleSubMode(MI.getOpcode());
  Binary |= getAddrModeUPBits(ARM_AM::getAM4SubMode(Mode));

  // Set bit W(21)
  if (IsUpdating)
    Binary |= 0x1 << ARMII::W_BitShift;

  // First register is encoded in Dd.
  Binary |= encodeVFPRd(MI, OpIdx+2);

  // Count the number of registers.
  unsigned NumRegs = 1;
  for (unsigned i = OpIdx+3, e = MI.getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI.getOperand(i);
    if (!MO.isReg() || MO.isImplicit())
      break;
    ++NumRegs;
  }
  // Bit 8 will be set if <list> is consecutive 64-bit registers (e.g., D0)
  // Otherwise, it will be 0, in the case of 32-bit registers.
  if(Binary & 0x100)
    Binary |= NumRegs * 2;
  else
    Binary |= NumRegs;

  emitWordLE(Binary);
}

static unsigned encodeNEONRd(const MachineInstr &MI, unsigned OpIdx) {
  unsigned RegD = MI.getOperand(OpIdx).getReg();
  unsigned Binary = 0;
  RegD = getARMRegisterNumbering(RegD);
  Binary |= (RegD & 0xf) << ARMII::RegRdShift;
  Binary |= ((RegD >> 4) & 1) << ARMII::D_BitShift;
  return Binary;
}

static unsigned encodeNEONRn(const MachineInstr &MI, unsigned OpIdx) {
  unsigned RegN = MI.getOperand(OpIdx).getReg();
  unsigned Binary = 0;
  RegN = getARMRegisterNumbering(RegN);
  Binary |= (RegN & 0xf) << ARMII::RegRnShift;
  Binary |= ((RegN >> 4) & 1) << ARMII::N_BitShift;
  return Binary;
}

static unsigned encodeNEONRm(const MachineInstr &MI, unsigned OpIdx) {
  unsigned RegM = MI.getOperand(OpIdx).getReg();
  unsigned Binary = 0;
  RegM = getARMRegisterNumbering(RegM);
  Binary |= (RegM & 0xf);
  Binary |= ((RegM >> 4) & 1) << ARMII::M_BitShift;
  return Binary;
}

/// convertNEONDataProcToThumb - Convert the ARM mode encoding for a NEON
/// data-processing instruction to the corresponding Thumb encoding.
static unsigned convertNEONDataProcToThumb(unsigned Binary) {
  assert((Binary & 0xfe000000) == 0xf2000000 &&
         "not an ARM NEON data-processing instruction");
  unsigned UBit = (Binary >> 24) & 1;
  return 0xef000000 | (UBit << 28) | (Binary & 0xffffff);
}

void ARMCodeEmitter::emitNEONLaneInstruction(const MachineInstr &MI) {
  unsigned Binary = getBinaryCodeForInstr(MI);

  unsigned RegTOpIdx, RegNOpIdx, LnOpIdx;
  const TargetInstrDesc &TID = MI.getDesc();
  if ((TID.TSFlags & ARMII::FormMask) == ARMII::NGetLnFrm) {
    RegTOpIdx = 0;
    RegNOpIdx = 1;
    LnOpIdx = 2;
  } else { // ARMII::NSetLnFrm
    RegTOpIdx = 2;
    RegNOpIdx = 0;
    LnOpIdx = 3;
  }

  // Set the conditional execution predicate
  Binary |= (IsThumb ? ARMCC::AL : II->getPredicate(&MI)) << ARMII::CondShift;

  unsigned RegT = MI.getOperand(RegTOpIdx).getReg();
  RegT = getARMRegisterNumbering(RegT);
  Binary |= (RegT << ARMII::RegRdShift);
  Binary |= encodeNEONRn(MI, RegNOpIdx);

  unsigned LaneShift;
  if ((Binary & (1 << 22)) != 0)
    LaneShift = 0; // 8-bit elements
  else if ((Binary & (1 << 5)) != 0)
    LaneShift = 1; // 16-bit elements
  else
    LaneShift = 2; // 32-bit elements

  unsigned Lane = MI.getOperand(LnOpIdx).getImm() << LaneShift;
  unsigned Opc1 = Lane >> 2;
  unsigned Opc2 = Lane & 3;
  assert((Opc1 & 3) == 0 && "out-of-range lane number operand");
  Binary |= (Opc1 << 21);
  Binary |= (Opc2 << 5);

  emitWordLE(Binary);
}

void ARMCodeEmitter::emitNEONDupInstruction(const MachineInstr &MI) {
  unsigned Binary = getBinaryCodeForInstr(MI);

  // Set the conditional execution predicate
  Binary |= (IsThumb ? ARMCC::AL : II->getPredicate(&MI)) << ARMII::CondShift;

  unsigned RegT = MI.getOperand(1).getReg();
  RegT = getARMRegisterNumbering(RegT);
  Binary |= (RegT << ARMII::RegRdShift);
  Binary |= encodeNEONRn(MI, 0);
  emitWordLE(Binary);
}

void ARMCodeEmitter::emitNEON1RegModImmInstruction(const MachineInstr &MI) {
  unsigned Binary = getBinaryCodeForInstr(MI);
  // Destination register is encoded in Dd.
  Binary |= encodeNEONRd(MI, 0);
  // Immediate fields: Op, Cmode, I, Imm3, Imm4
  unsigned Imm = MI.getOperand(1).getImm();
  unsigned Op = (Imm >> 12) & 1;
  unsigned Cmode = (Imm >> 8) & 0xf;
  unsigned I = (Imm >> 7) & 1;
  unsigned Imm3 = (Imm >> 4) & 0x7;
  unsigned Imm4 = Imm & 0xf;
  Binary |= (I << 24) | (Imm3 << 16) | (Cmode << 8) | (Op << 5) | Imm4;
  if (IsThumb)
    Binary = convertNEONDataProcToThumb(Binary);
  emitWordLE(Binary);
}

void ARMCodeEmitter::emitNEON2RegInstruction(const MachineInstr &MI) {
  const TargetInstrDesc &TID = MI.getDesc();
  unsigned Binary = getBinaryCodeForInstr(MI);
  // Destination register is encoded in Dd; source register in Dm.
  unsigned OpIdx = 0;
  Binary |= encodeNEONRd(MI, OpIdx++);
  if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)
    ++OpIdx;
  Binary |= encodeNEONRm(MI, OpIdx);
  if (IsThumb)
    Binary = convertNEONDataProcToThumb(Binary);
  // FIXME: This does not handle VDUPfdf or VDUPfqf.
  emitWordLE(Binary);
}

void ARMCodeEmitter::emitNEON3RegInstruction(const MachineInstr &MI) {
  const TargetInstrDesc &TID = MI.getDesc();
  unsigned Binary = getBinaryCodeForInstr(MI);
  // Destination register is encoded in Dd; source registers in Dn and Dm.
  unsigned OpIdx = 0;
  Binary |= encodeNEONRd(MI, OpIdx++);
  if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)
    ++OpIdx;
  Binary |= encodeNEONRn(MI, OpIdx++);
  if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)
    ++OpIdx;
  Binary |= encodeNEONRm(MI, OpIdx);
  if (IsThumb)
    Binary = convertNEONDataProcToThumb(Binary);
  // FIXME: This does not handle VMOVDneon or VMOVQ.
  emitWordLE(Binary);
}

#include "ARMGenCodeEmitter.inc"
