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

    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 emitMiscInstruction(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);
    unsigned getMachineOpValue(const MachineInstr &MI, unsigned OpIdx) {
      return getMachineOpValue(MI, MI.getOperand(OpIdx));
    }

    /// 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);
    unsigned getMovi32Value(const MachineInstr &MI, unsigned OpIdx,
                            unsigned Reloc) {
      return getMovi32Value(MI, MI.getOperand(OpIdx), 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);
    void emitExternalSymbolAddress(const char *ES, unsigned Reloc);
    void emitConstPoolAddress(unsigned CPI, unsigned Reloc);
    void emitJumpTableAddress(unsigned JTIndex, unsigned Reloc);
    void emitMachineBasicBlock(MachineBasicBlock *BB, unsigned Reloc,
                               intptr_t JTBase = 0);
  };
}

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) {
  if (MO.isReg())
    return ARMRegisterInfo::getRegisterNumbering(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 {
#ifndef NDEBUG
    errs() << MO;
#endif
    llvm_unreachable(0);
  }
  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) {
  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) {
  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) {
  // 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) {
  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) {
  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::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;
  case ARMII::VFPMiscFrm:
    emitMiscInstruction(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-31} = 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 |= ARMRegisterInfo::getRegisterNumbering(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::MOVrx:
    // 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:
  case ARM::BMOVPCRX:
  case ARM::BXr9:
  case ARM::BMOVPCRXr9: {
    // 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:
    emitMOVi32immInstruction(MI);
    break;

  case ARM::MOVi2pieces:
    // Two instructions to materialize a constant.
    emitMOVi2piecesInstruction(MI);
    break;
  case ARM::LEApcrelJT:
    // Materialize jumptable address.
    emitLEApcrelJTInstruction(MI);
    break;
  case ARM::MOVrx:
  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 |
      (ARMRegisterInfo::getRegisterNumbering(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 |= (ARMRegisterInfo::getRegisterNumbering(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 |= (ARMRegisterInfo::getRegisterNumbering(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 | ARMRegisterInfo::getRegisterNumbering(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);

  // 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 |= (ARMRegisterInfo::getRegisterNumbering(ImplicitRd)
               << ARMII::RegRdShift);
  else
    Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift;

  // Set second operand
  if (ImplicitRn)
    // Special handling for implicit use (e.g. PC).
    Binary |= (ARMRegisterInfo::getRegisterNumbering(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 enconding.
  Binary |= 1 << ARMII::I_BitShift;
  assert(TargetRegisterInfo::isPhysicalRegister(MO2.getReg()));
  // Set bit[3:0] to the corresponding Rm register
  Binary |= ARMRegisterInfo::getRegisterNumbering(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 |= (ARMRegisterInfo::getRegisterNumbering(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 |= ARMRegisterInfo::getRegisterNumbering(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)
  const MachineOperand &MO = MI.getOperand(OpIdx++);
  Binary |= getAddrModeUPBits(ARM_AM::getAM4SubMode(MO.getImm()));

  // 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 = ARMRegisterInfo::getRegisterNumbering(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();
  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::SSATlsl ||
      TID.Opcode == ARM::SSATasr ||
      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 ShiftAmt = MI.getOperand(3).getImm();
    if (ShiftAmt == 32 &&
        (TID.Opcode == ARM::SSATasr || TID.Opcode == ARM::USATasr))
      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 |= ARMRegisterInfo::getRegisterNumbering(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 = false;
  RegD = ARMRegisterInfo::getRegisterNumbering(RegD, &isSPVFP);
  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 = false;
  RegN = ARMRegisterInfo::getRegisterNumbering(RegN, &isSPVFP);
  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 = false;
  RegM = ARMRegisterInfo::getRegisterNumbering(RegM, &isSPVFP);
  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)
  const MachineOperand &MO = MI.getOperand(OpIdx++);
  Binary |= getAddrModeUPBits(ARM_AM::getAM5SubMode(MO.getImm()));

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

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

  // Number of registers are encoded in offset field.
  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);
}

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

  switch(Opcode) {
  default:
    llvm_unreachable("ARMCodeEmitter::emitMiscInstruction");

  case ARM::FMSTAT:
    // No further encoding needed.
    break;

  case ARM::VMRS:
  case ARM::VMSR: {
    const MachineOperand &MO0 = MI.getOperand(0);
    // Encode Rt.
    Binary |= ARMRegisterInfo::getRegisterNumbering(MO0.getReg())
                << ARMII::RegRdShift;
    break;
  }

  case ARM::FCONSTD:
  case ARM::FCONSTS: {
    // Encode Dd / Sd.
    Binary |= encodeVFPRd(MI, 0);

    // Encode imm., Table A7-18 VFP modified immediate constants
    const MachineOperand &MO1 = MI.getOperand(1);
    unsigned Imm = static_cast<unsigned>(MO1.getFPImm()->getValueAPF()
                      .bitcastToAPInt().getHiBits(32).getLimitedValue());
    unsigned ModifiedImm;

    if(Opcode == ARM::FCONSTS)
      ModifiedImm = (Imm & 0x80000000) >> 24 | // a
                    (Imm & 0x03F80000) >> 19;  // bcdefgh
    else // Opcode == ARM::FCONSTD
      ModifiedImm = (Imm & 0x80000000) >> 24 | // a
                    (Imm & 0x007F0000) >> 16;  // bcdefgh

    // Insts{19-16} = abcd, Insts{3-0} = efgh
    Binary |= ((ModifiedImm & 0xF0) >> 4) << 16;
    Binary |= (ModifiedImm & 0xF);
    break;
  }
  }

  emitWordLE(Binary);
}

static unsigned encodeNEONRd(const MachineInstr &MI, unsigned OpIdx) {
  unsigned RegD = MI.getOperand(OpIdx).getReg();
  unsigned Binary = 0;
  RegD = ARMRegisterInfo::getRegisterNumbering(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 = ARMRegisterInfo::getRegisterNumbering(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 = ARMRegisterInfo::getRegisterNumbering(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 = ARMRegisterInfo::getRegisterNumbering(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 = ARMRegisterInfo::getRegisterNumbering(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"
