//===-- 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 "ARMBaseInstrInfo.h"
#include "ARMConstantPoolValue.h"
#include "ARMRelocations.h"
#include "ARMSubtarget.h"
#include "ARMTargetMachine.h"
#include "MCTargetDesc/ARMAddressingModes.h"
#include "llvm/ADT/Statistic.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/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/PassManager.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 ARMBaseInstrInfo    *II;
    const DataLayout          *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 ARMBaseInstrInfo *)tm.getInstrInfo()),
        TD(tm.getDataLayout()), 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.
    uint64_t 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 MCInstrDesc &MCID,
                                    const MachineOperand &MO,
                                    unsigned OpIdx);

    unsigned getMachineSoImmOpValue(unsigned SoImm);
    unsigned getAddrModeSBit(const MachineInstr &MI,
                             const MCInstrDesc &MCID) 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 NEONThumb2V8PostEncoder(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 getARMBLTargetOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getARMBLXTargetOpValue(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 getSORegRegOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getSORegImmOpValue(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 getT2Imm8s4OpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getT2AddrModeImm8s4OpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getT2AddrModeImm0_1020s4OpValue(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 getT2AdrLabelOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getAddrMode6AddressOpValue(const MachineInstr &MI, unsigned Op)
      const { return 0; }
    unsigned getAddrMode6OneLane32AddressOpValue(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 getSsatBitPosValue(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 = II->getRegisterInfo().getEncodingValue(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 getPostIdxRegOpValue(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 = II->getRegisterInfo().getEncodingValue(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;
    unsigned encodeVFPRd(const MachineInstr &MI, unsigned OpIdx) const;
    unsigned encodeVFPRn(const MachineInstr &MI, unsigned OpIdx) const;
    unsigned encodeVFPRm(const MachineInstr &MI, unsigned OpIdx) const;
    unsigned encodeNEONRd(const MachineInstr &MI, unsigned OpIdx) const;
    unsigned encodeNEONRn(const MachineInstr &MI, unsigned OpIdx) const;
    unsigned encodeNEONRm(const MachineInstr &MI, unsigned OpIdx) 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) {
  TargetMachine &Target = const_cast<TargetMachine&>(MF.getTarget());

  assert((Target.getRelocationModel() != Reloc::Default ||
          Target.getRelocationModel() != Reloc::Static) &&
         "JIT relocation model must be set to static or default!");

  JTI = static_cast<ARMJITInfo*>(Target.getJITInfo());
  II = static_cast<const ARMBaseInstrInfo*>(Target.getInstrInfo());
  TD = Target.getDataLayout();

  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.getName() << "'\n");
    MCE.startFunction(MF);
    for (MachineFunction::iterator MBB = MF.begin(), E = MF.end();
         MBB != E; ++MBB) {
      MCE.StartMachineBasicBlock(MBB);
      for (MachineBasicBlock::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;
  }
}

/// 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 II->getRegisterInfo().getEncodingValue(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 MCInstrDesc &MCID = MI.getDesc();
    // For VFP load, the immediate offset is multiplied by 4.
    unsigned Reloc =  ((MCID.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!");
  }
  case ARMII::MiscFrm:
    if (MI.getOpcode() == ARM::LEApcrelJT) {
      // Materialize jumptable address.
      emitLEApcrelJTInstruction(MI);
      break;
    }
    llvm_unreachable("Unhandled instruction encoding!");
  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 = cast<ARMConstantPoolConstant>(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  {
      const char *Sym = cast<ARMConstantPoolSymbol>(ACPV)->getSymbol();
      emitExternalSymbolAddress(Sym, 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 MCInstrDesc &MCID = 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, MCID);

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

  // Encode Rn which is PC.
  Binary |= II->getRegisterInfo().getEncodingValue(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: {
    // 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 MCInstrDesc &MCID,
                                                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 | (II->getRegisterInfo().getEncodingValue(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 MCInstrDesc &MCID) const {
  for (unsigned i = MI.getNumOperands(), e = MCID.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 MCInstrDesc &MCID = 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, MCID);

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

  if (MCID.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(MCID.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 ((MCID.Opcode == ARM::BFC) || (MCID.Opcode == ARM::BFI)) {
      uint32_t v = ~MI.getOperand(2).getImm();
      int32_t lsb = countTrailingZeros(v);
      int32_t msb = (32 - countLeadingZeros(v)) - 1;
      // Instr{20-16} = msb, Instr{11-7} = lsb
      Binary |= (msb & 0x1F) << 16;
      Binary |= (lsb & 0x1F) << 7;
      emitWordLE(Binary);
      return;
  } else if ((MCID.Opcode == ARM::UBFX) || (MCID.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 (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)
    ++OpIdx;

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

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

  if (MO.isReg()) {
    // Encode register Rm.
    emitWordLE(Binary | II->getRegisterInfo().getEncodingValue(MO.getReg()));
    return;
  }

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

  emitWordLE(Binary);
}

void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI,
                                              unsigned ImplicitRd,
                                              unsigned ImplicitRn) {
  const MCInstrDesc &MCID = MI.getDesc();
  unsigned Form = MCID.TSFlags & ARMII::FormMask;
  bool IsPrePost = (MCID.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 |= (II->getRegisterInfo().getEncodingValue(ImplicitRd) << ARMII::RegRdShift);
  else
    Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift;

  // Set second operand
  if (ImplicitRn)
    // Special handling for implicit use (e.g. PC).
    Binary |= (II->getRegisterInfo().getEncodingValue(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 && MCID.getOperandConstraint(OpIdx, MCOI::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 |= II->getRegisterInfo().getEncodingValue(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 MCInstrDesc &MCID = MI.getDesc();
  unsigned Form = MCID.TSFlags & ARMII::FormMask;
  bool IsPrePost = (MCID.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 (MCID.Opcode == ARM::LDRD || MCID.Opcode == ARM::STRD)
    ++OpIdx;

  // Set second operand
  if (ImplicitRn)
    // Special handling for implicit use (e.g. PC).
    Binary |= (II->getRegisterInfo().getEncodingValue(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 && MCID.getOperandConstraint(OpIdx, MCOI::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 |= II->getRegisterInfo().getEncodingValue(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 MCInstrDesc &MCID = MI.getDesc();
  bool IsUpdating = (MCID.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 = II->getRegisterInfo().getEncodingValue(MO.getReg());
    assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
           RegNum < 16);
    Binary |= 0x1 << RegNum;
  }

  emitWordLE(Binary);
}

void ARMCodeEmitter::emitMulFrmInstruction(const MachineInstr &MI) {
  const MCInstrDesc &MCID = 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, MCID);

  // 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 (MCID.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 (MCID.getNumOperands() > OpIdx &&
      !MCID.OpInfo[OpIdx].isPredicate() &&
      !MCID.OpInfo[OpIdx].isOptionalDef())
    Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRdLoShift;

  emitWordLE(Binary);
}

void ARMCodeEmitter::emitExtendInstruction(const MachineInstr &MI) {
  const MCInstrDesc &MCID = 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() &&
      !MCID.OpInfo[OpIdx].isPredicate() &&
      !MCID.OpInfo[OpIdx].isOptionalDef())
    Binary |= (getMachineOpValue(MI, OpIdx) / 8) << ARMII::ExtRotImmShift;

  emitWordLE(Binary);
}

void ARMCodeEmitter::emitMiscArithInstruction(const MachineInstr &MI) {
  const MCInstrDesc &MCID = MI.getDesc();

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

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

  // PKH instructions are finished at this point
  if (MCID.Opcode == ARM::PKHBT || MCID.Opcode == ARM::PKHTB) {
    emitWordLE(Binary);
    return;
  }

  unsigned OpIdx = 0;

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

  const MachineOperand &MO = MI.getOperand(OpIdx++);
  if (OpIdx == MCID.getNumOperands() ||
      MCID.OpInfo[OpIdx].isPredicate() ||
      MCID.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 (MCID.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 MCInstrDesc &MCID = 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 (MCID.Opcode == ARM::SSAT || MCID.Opcode == ARM::SSAT16)
    Pos -= 1;
  assert((Pos < 16 || (Pos < 32 &&
                       MCID.Opcode != ARM::SSAT16 &&
                       MCID.Opcode != ARM::USAT16)) &&
         "saturate bit position out of range");
  Binary |= Pos << 16;

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

  // Encode shift_imm.
  if (MCID.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 MCInstrDesc &MCID = MI.getDesc();

  if (MCID.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 MCInstrDesc &MCID = MI.getDesc();

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

    // Then emit the inline jump table.
    unsigned JTIndex =
      (MCID.Opcode == ARM::BR_JTr)
      ? MI.getOperand(1).getIndex() : MI.getOperand(2).getIndex();
    emitInlineJumpTable(JTIndex);
    return;
  } else if (MCID.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 (MCID.Opcode == ARM::BX_RET || MCID.Opcode == ARM::MOVPCLR)
    // The return register is LR.
    Binary |= II->getRegisterInfo().getEncodingValue(ARM::LR);
  else
    // otherwise, set the return register
    Binary |= getMachineOpValue(MI, 0);

  emitWordLE(Binary);
}

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

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

unsigned ARMCodeEmitter::encodeVFPRm(const MachineInstr &MI,
                                     unsigned OpIdx) const {
  unsigned RegM = MI.getOperand(OpIdx).getReg();
  unsigned Binary = 0;
  bool isSPVFP = ARM::SPRRegClass.contains(RegM);
  RegM = II->getRegisterInfo().getEncodingValue(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 MCInstrDesc &MCID = 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 (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)
    ++OpIdx;

  // Encode Dn / Sn.
  if ((MCID.TSFlags & ARMII::FormMask) == ARMII::VFPBinaryFrm)
    Binary |= encodeVFPRn(MI, OpIdx++);

  if (OpIdx == MCID.getNumOperands() ||
      MCID.OpInfo[OpIdx].isPredicate() ||
      MCID.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 MCInstrDesc &MCID = MI.getDesc();
  unsigned Form = MCID.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 MCInstrDesc &MCID = MI.getDesc();
  bool IsUpdating = (MCID.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);
}

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

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

unsigned ARMCodeEmitter::encodeNEONRm(const MachineInstr &MI,
                                      unsigned OpIdx) const {
  unsigned RegM = MI.getOperand(OpIdx).getReg();
  unsigned Binary = 0;
  RegM = II->getRegisterInfo().getEncodingValue(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 MCInstrDesc &MCID = MI.getDesc();
  if ((MCID.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 = II->getRegisterInfo().getEncodingValue(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 = II->getRegisterInfo().getEncodingValue(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 MCInstrDesc &MCID = MI.getDesc();
  unsigned Binary = getBinaryCodeForInstr(MI);
  // Destination register is encoded in Dd; source register in Dm.
  unsigned OpIdx = 0;
  Binary |= encodeNEONRd(MI, OpIdx++);
  if (MCID.getOperandConstraint(OpIdx, MCOI::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 MCInstrDesc &MCID = 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 (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)
    ++OpIdx;
  Binary |= encodeNEONRn(MI, OpIdx++);
  if (MCID.getOperandConstraint(OpIdx, MCOI::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"
