//===------------ ARMDecoderEmitter.cpp - Decoder Generator ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is part of the ARM Disassembler.
// It contains the tablegen backend that emits the decoder functions for ARM and
// Thumb.  The disassembler core includes the auto-generated file, invokes the
// decoder functions, and builds up the MCInst based on the decoded Opcode.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "arm-decoder-emitter"

#include "ARMDecoderEmitter.h"
#include "CodeGenTarget.h"
#include "Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"

#include <vector>
#include <map>
#include <string>

using namespace llvm;

/////////////////////////////////////////////////////
//                                                 //
//  Enums and Utilities for ARM Instruction Format //
//                                                 //
/////////////////////////////////////////////////////

#define ARM_FORMATS                   \
  ENTRY(ARM_FORMAT_PSEUDO,         0) \
  ENTRY(ARM_FORMAT_MULFRM,         1) \
  ENTRY(ARM_FORMAT_BRFRM,          2) \
  ENTRY(ARM_FORMAT_BRMISCFRM,      3) \
  ENTRY(ARM_FORMAT_DPFRM,          4) \
  ENTRY(ARM_FORMAT_DPSOREGFRM,     5) \
  ENTRY(ARM_FORMAT_LDFRM,          6) \
  ENTRY(ARM_FORMAT_STFRM,          7) \
  ENTRY(ARM_FORMAT_LDMISCFRM,      8) \
  ENTRY(ARM_FORMAT_STMISCFRM,      9) \
  ENTRY(ARM_FORMAT_LDSTMULFRM,    10) \
  ENTRY(ARM_FORMAT_LDSTEXFRM,     11) \
  ENTRY(ARM_FORMAT_ARITHMISCFRM,  12) \
  ENTRY(ARM_FORMAT_SATFRM,        13) \
  ENTRY(ARM_FORMAT_EXTFRM,        14) \
  ENTRY(ARM_FORMAT_VFPUNARYFRM,   15) \
  ENTRY(ARM_FORMAT_VFPBINARYFRM,  16) \
  ENTRY(ARM_FORMAT_VFPCONV1FRM,   17) \
  ENTRY(ARM_FORMAT_VFPCONV2FRM,   18) \
  ENTRY(ARM_FORMAT_VFPCONV3FRM,   19) \
  ENTRY(ARM_FORMAT_VFPCONV4FRM,   20) \
  ENTRY(ARM_FORMAT_VFPCONV5FRM,   21) \
  ENTRY(ARM_FORMAT_VFPLDSTFRM,    22) \
  ENTRY(ARM_FORMAT_VFPLDSTMULFRM, 23) \
  ENTRY(ARM_FORMAT_VFPMISCFRM,    24) \
  ENTRY(ARM_FORMAT_THUMBFRM,      25) \
  ENTRY(ARM_FORMAT_MISCFRM,       26) \
  ENTRY(ARM_FORMAT_NEONGETLNFRM,  27) \
  ENTRY(ARM_FORMAT_NEONSETLNFRM,  28) \
  ENTRY(ARM_FORMAT_NEONDUPFRM,    29) \
  ENTRY(ARM_FORMAT_NLdSt,         30) \
  ENTRY(ARM_FORMAT_N1RegModImm,   31) \
  ENTRY(ARM_FORMAT_N2Reg,         32) \
  ENTRY(ARM_FORMAT_NVCVT,         33) \
  ENTRY(ARM_FORMAT_NVecDupLn,     34) \
  ENTRY(ARM_FORMAT_N2RegVecShL,   35) \
  ENTRY(ARM_FORMAT_N2RegVecShR,   36) \
  ENTRY(ARM_FORMAT_N3Reg,         37) \
  ENTRY(ARM_FORMAT_N3RegVecSh,    38) \
  ENTRY(ARM_FORMAT_NVecExtract,   39) \
  ENTRY(ARM_FORMAT_NVecMulScalar, 40) \
  ENTRY(ARM_FORMAT_NVTBL,         41)

// ARM instruction format specifies the encoding used by the instruction.
#define ENTRY(n, v) n = v,
typedef enum {
  ARM_FORMATS
  ARM_FORMAT_NA
} ARMFormat;
#undef ENTRY

// Converts enum to const char*.
static const char *stringForARMFormat(ARMFormat form) {
#define ENTRY(n, v) case n: return #n;
  switch(form) {
    ARM_FORMATS
  case ARM_FORMAT_NA:
  default:
    return "";
  }
#undef ENTRY
}

enum {
  IndexModeNone = 0,
  IndexModePre  = 1,
  IndexModePost = 2,
  IndexModeUpd  = 3
};

/////////////////////////
//                     //
//  Utility functions  //
//                     //
/////////////////////////

/// byteFromBitsInit - Return the byte value from a BitsInit.
/// Called from getByteField().
static uint8_t byteFromBitsInit(BitsInit &init) {
  int width = init.getNumBits();

  assert(width <= 8 && "Field is too large for uint8_t!");

  int index;
  uint8_t mask = 0x01;

  uint8_t ret = 0;

  for (index = 0; index < width; index++) {
    if (static_cast<BitInit*>(init.getBit(index))->getValue())
      ret |= mask;

    mask <<= 1;
  }

  return ret;
}

static uint8_t getByteField(const Record &def, const char *str) {
  BitsInit *bits = def.getValueAsBitsInit(str);
  return byteFromBitsInit(*bits);
}

static BitsInit &getBitsField(const Record &def, const char *str) {
  BitsInit *bits = def.getValueAsBitsInit(str);
  return *bits;
}

/// sameStringExceptSuffix - Return true if the two strings differ only in RHS's
/// suffix.  ("VST4d8", "VST4d8_UPD", "_UPD") as input returns true.
static
bool sameStringExceptSuffix(const StringRef LHS, const StringRef RHS,
                            const StringRef Suffix) {

  if (RHS.startswith(LHS) && RHS.endswith(Suffix))
    return RHS.size() == LHS.size() + Suffix.size();

  return false;
}

/// thumbInstruction - Determine whether we have a Thumb instruction.
/// See also ARMInstrFormats.td.
static bool thumbInstruction(uint8_t Form) {
  return Form == ARM_FORMAT_THUMBFRM;
}

// The set (BIT_TRUE, BIT_FALSE, BIT_UNSET) represents a ternary logic system
// for a bit value.
//
// BIT_UNFILTERED is used as the init value for a filter position.  It is used
// only for filter processings.
typedef enum {
  BIT_TRUE,      // '1'
  BIT_FALSE,     // '0'
  BIT_UNSET,     // '?'
  BIT_UNFILTERED // unfiltered
} bit_value_t;

static bool ValueSet(bit_value_t V) {
  return (V == BIT_TRUE || V == BIT_FALSE);
}
static bool ValueNotSet(bit_value_t V) {
  return (V == BIT_UNSET);
}
static int Value(bit_value_t V) {
  return ValueNotSet(V) ? -1 : (V == BIT_FALSE ? 0 : 1);
}
static bit_value_t bitFromBits(BitsInit &bits, unsigned index) {
  if (BitInit *bit = dynamic_cast<BitInit*>(bits.getBit(index)))
    return bit->getValue() ? BIT_TRUE : BIT_FALSE;

  // The bit is uninitialized.
  return BIT_UNSET;
}
// Prints the bit value for each position.
static void dumpBits(raw_ostream &o, BitsInit &bits) {
  unsigned index;

  for (index = bits.getNumBits(); index > 0; index--) {
    switch (bitFromBits(bits, index - 1)) {
    case BIT_TRUE:
      o << "1";
      break;
    case BIT_FALSE:
      o << "0";
      break;
    case BIT_UNSET:
      o << "_";
      break;
    default:
      assert(0 && "unexpected return value from bitFromBits");
    }
  }
}

// Enums for the available target names.
typedef enum {
  TARGET_ARM = 0,
  TARGET_THUMB
} TARGET_NAME_t;

// FIXME: Possibly auto-detected?
#define BIT_WIDTH 32

// Forward declaration.
class FilterChooser;

// Representation of the instruction to work on.
typedef bit_value_t insn_t[BIT_WIDTH];

/// Filter - Filter works with FilterChooser to produce the decoding tree for
/// the ISA.
///
/// It is useful to think of a Filter as governing the switch stmts of the
/// decoding tree in a certain level.  Each case stmt delegates to an inferior
/// FilterChooser to decide what further decoding logic to employ, or in another
/// words, what other remaining bits to look at.  The FilterChooser eventually
/// chooses a best Filter to do its job.
///
/// This recursive scheme ends when the number of Opcodes assigned to the
/// FilterChooser becomes 1 or if there is a conflict.  A conflict happens when
/// the Filter/FilterChooser combo does not know how to distinguish among the
/// Opcodes assigned.
///
/// An example of a conflcit is 
///
/// Conflict:
///                     111101000.00........00010000....
///                     111101000.00........0001........
///                     1111010...00........0001........
///                     1111010...00....................
///                     1111010.........................
///                     1111............................
///                     ................................
///     VST4q8a         111101000_00________00010000____
///     VST4q8b         111101000_00________00010000____
///
/// The Debug output shows the path that the decoding tree follows to reach the
/// the conclusion that there is a conflict.  VST4q8a is a vst4 to double-spaced
/// even registers, while VST4q8b is a vst4 to double-spaced odd regsisters.
///
/// The encoding info in the .td files does not specify this meta information,
/// which could have been used by the decoder to resolve the conflict.  The
/// decoder could try to decode the even/odd register numbering and assign to
/// VST4q8a or VST4q8b, but for the time being, the decoder chooses the "a"
/// version and return the Opcode since the two have the same Asm format string.
class Filter {
protected:
  FilterChooser *Owner; // points to the FilterChooser who owns this filter
  unsigned StartBit; // the starting bit position
  unsigned NumBits; // number of bits to filter
  bool Mixed; // a mixed region contains both set and unset bits

  // Map of well-known segment value to the set of uid's with that value. 
  std::map<uint64_t, std::vector<unsigned> > FilteredInstructions;

  // Set of uid's with non-constant segment values.
  std::vector<unsigned> VariableInstructions;

  // Map of well-known segment value to its delegate.
  std::map<unsigned, FilterChooser*> FilterChooserMap;

  // Number of instructions which fall under FilteredInstructions category.
  unsigned NumFiltered;

  // Keeps track of the last opcode in the filtered bucket.
  unsigned LastOpcFiltered;

  // Number of instructions which fall under VariableInstructions category.
  unsigned NumVariable;

public:
  unsigned getNumFiltered() { return NumFiltered; }
  unsigned getNumVariable() { return NumVariable; }
  unsigned getSingletonOpc() {
    assert(NumFiltered == 1);
    return LastOpcFiltered;
  }
  // Return the filter chooser for the group of instructions without constant
  // segment values.
  FilterChooser &getVariableFC() {
    assert(NumFiltered == 1);
    assert(FilterChooserMap.size() == 1);
    return *(FilterChooserMap.find((unsigned)-1)->second);
  }

  Filter(const Filter &f);
  Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, bool mixed);

  ~Filter();

  // Divides the decoding task into sub tasks and delegates them to the
  // inferior FilterChooser's.
  //
  // A special case arises when there's only one entry in the filtered
  // instructions.  In order to unambiguously decode the singleton, we need to
  // match the remaining undecoded encoding bits against the singleton.
  void recurse();

  // Emit code to decode instructions given a segment or segments of bits.
  void emit(raw_ostream &o, unsigned &Indentation);

  // Returns the number of fanout produced by the filter.  More fanout implies
  // the filter distinguishes more categories of instructions.
  unsigned usefulness() const;
}; // End of class Filter

// These are states of our finite state machines used in FilterChooser's
// filterProcessor() which produces the filter candidates to use.
typedef enum {
  ATTR_NONE,
  ATTR_FILTERED,
  ATTR_ALL_SET,
  ATTR_ALL_UNSET,
  ATTR_MIXED
} bitAttr_t;

/// FilterChooser - FilterChooser chooses the best filter among a set of Filters
/// in order to perform the decoding of instructions at the current level.
///
/// Decoding proceeds from the top down.  Based on the well-known encoding bits
/// of instructions available, FilterChooser builds up the possible Filters that
/// can further the task of decoding by distinguishing among the remaining
/// candidate instructions.
///
/// Once a filter has been chosen, it is called upon to divide the decoding task
/// into sub-tasks and delegates them to its inferior FilterChoosers for further
/// processings.
///
/// It is useful to think of a Filter as governing the switch stmts of the
/// decoding tree.  And each case is delegated to an inferior FilterChooser to
/// decide what further remaining bits to look at.
class FilterChooser {
  static TARGET_NAME_t TargetName;

protected:
  friend class Filter;

  // Vector of codegen instructions to choose our filter.
  const std::vector<const CodeGenInstruction*> &AllInstructions;

  // Vector of uid's for this filter chooser to work on.
  const std::vector<unsigned> Opcodes;

  // Vector of candidate filters.
  std::vector<Filter> Filters;

  // Array of bit values passed down from our parent.
  // Set to all BIT_UNFILTERED's for Parent == NULL.
  bit_value_t FilterBitValues[BIT_WIDTH];

  // Links to the FilterChooser above us in the decoding tree.
  FilterChooser *Parent;
  
  // Index of the best filter from Filters.
  int BestIndex;

public:
  static void setTargetName(TARGET_NAME_t tn) { TargetName = tn; }

  FilterChooser(const FilterChooser &FC) :
      AllInstructions(FC.AllInstructions), Opcodes(FC.Opcodes),
      Filters(FC.Filters), Parent(FC.Parent), BestIndex(FC.BestIndex) {
    memcpy(FilterBitValues, FC.FilterBitValues, sizeof(FilterBitValues));
  }

  FilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
                const std::vector<unsigned> &IDs) :
      AllInstructions(Insts), Opcodes(IDs), Filters(), Parent(NULL),
      BestIndex(-1) {
    for (unsigned i = 0; i < BIT_WIDTH; ++i)
      FilterBitValues[i] = BIT_UNFILTERED;

    doFilter();
  }

  FilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
                const std::vector<unsigned> &IDs,
                bit_value_t (&ParentFilterBitValues)[BIT_WIDTH],
                FilterChooser &parent) :
      AllInstructions(Insts), Opcodes(IDs), Filters(), Parent(&parent),
      BestIndex(-1) {
    for (unsigned i = 0; i < BIT_WIDTH; ++i)
      FilterBitValues[i] = ParentFilterBitValues[i];

    doFilter();
  }

  // The top level filter chooser has NULL as its parent.
  bool isTopLevel() { return Parent == NULL; }

  // This provides an opportunity for target specific code emission.
  void emitTopHook(raw_ostream &o);

  // Emit the top level typedef and decodeInstruction() function.
  void emitTop(raw_ostream &o, unsigned &Indentation);

  // This provides an opportunity for target specific code emission after
  // emitTop().
  void emitBot(raw_ostream &o, unsigned &Indentation);

protected:
  // Populates the insn given the uid.
  void insnWithID(insn_t &Insn, unsigned Opcode) const {
    BitsInit &Bits = getBitsField(*AllInstructions[Opcode]->TheDef, "Inst");

    for (unsigned i = 0; i < BIT_WIDTH; ++i)
      Insn[i] = bitFromBits(Bits, i);

    // Set Inst{21} to 1 (wback) when IndexModeBits == IndexModeUpd.
    if (getByteField(*AllInstructions[Opcode]->TheDef, "IndexModeBits")
        == IndexModeUpd)
      Insn[21] = BIT_TRUE;
  }

  // Returns the record name.
  const std::string &nameWithID(unsigned Opcode) const {
    return AllInstructions[Opcode]->TheDef->getName();
  }

  // Populates the field of the insn given the start position and the number of
  // consecutive bits to scan for.
  //
  // Returns false if there exists any uninitialized bit value in the range.
  // Returns true, otherwise.
  bool fieldFromInsn(uint64_t &Field, insn_t &Insn, unsigned StartBit,
      unsigned NumBits) const;

  /// dumpFilterArray - dumpFilterArray prints out debugging info for the given
  /// filter array as a series of chars.
  void dumpFilterArray(raw_ostream &o, bit_value_t (&filter)[BIT_WIDTH]);

  /// dumpStack - dumpStack traverses the filter chooser chain and calls
  /// dumpFilterArray on each filter chooser up to the top level one.
  void dumpStack(raw_ostream &o, const char *prefix);

  Filter &bestFilter() {
    assert(BestIndex != -1 && "BestIndex not set");
    return Filters[BestIndex];
  }

  // Called from Filter::recurse() when singleton exists.  For debug purpose.
  void SingletonExists(unsigned Opc);

  bool PositionFiltered(unsigned i) {
    return ValueSet(FilterBitValues[i]);
  }

  // Calculates the island(s) needed to decode the instruction.
  // This returns a lit of undecoded bits of an instructions, for example,
  // Inst{20} = 1 && Inst{3-0} == 0b1111 represents two islands of yet-to-be
  // decoded bits in order to verify that the instruction matches the Opcode.
  unsigned getIslands(std::vector<unsigned> &StartBits,
      std::vector<unsigned> &EndBits, std::vector<uint64_t> &FieldVals,
      insn_t &Insn);

  // The purpose of this function is for the API client to detect possible
  // Load/Store Coprocessor instructions.  If the coprocessor number is of
  // the instruction is either 10 or 11, the decoder should not report the
  // instruction as LDC/LDC2/STC/STC2, but should match against Advanced SIMD or
  // VFP instructions.
  bool LdStCopEncoding1(unsigned Opc) {
    const std::string &Name = nameWithID(Opc);
    if (Name == "LDC_OFFSET" || Name == "LDC_OPTION" ||
        Name == "LDC_POST" || Name == "LDC_PRE" ||
        Name == "LDCL_OFFSET" || Name == "LDCL_OPTION" ||
        Name == "LDCL_POST" || Name == "LDCL_PRE" ||
        Name == "STC_OFFSET" || Name == "STC_OPTION" ||
        Name == "STC_POST" || Name == "STC_PRE" ||
        Name == "STCL_OFFSET" || Name == "STCL_OPTION" ||
        Name == "STCL_POST" || Name == "STCL_PRE")
      return true;
    else
      return false;
  }

  // Emits code to decode the singleton.  Return true if we have matched all the
  // well-known bits.
  bool emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,unsigned Opc);

  // Emits code to decode the singleton, and then to decode the rest.
  void emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,Filter &Best);

  // Assign a single filter and run with it.
  void runSingleFilter(FilterChooser &owner, unsigned startBit, unsigned numBit,
      bool mixed);

  // reportRegion is a helper function for filterProcessor to mark a region as
  // eligible for use as a filter region.
  void reportRegion(bitAttr_t RA, unsigned StartBit, unsigned BitIndex,
      bool AllowMixed);

  // FilterProcessor scans the well-known encoding bits of the instructions and
  // builds up a list of candidate filters.  It chooses the best filter and
  // recursively descends down the decoding tree.
  bool filterProcessor(bool AllowMixed, bool Greedy = true);

  // Decides on the best configuration of filter(s) to use in order to decode
  // the instructions.  A conflict of instructions may occur, in which case we
  // dump the conflict set to the standard error.
  void doFilter();

  // Emits code to decode our share of instructions.  Returns true if the
  // emitted code causes a return, which occurs if we know how to decode
  // the instruction at this level or the instruction is not decodeable.
  bool emit(raw_ostream &o, unsigned &Indentation);
};

///////////////////////////
//                       //
// Filter Implmenetation //
//                       //
///////////////////////////

Filter::Filter(const Filter &f) :
  Owner(f.Owner), StartBit(f.StartBit), NumBits(f.NumBits), Mixed(f.Mixed),
  FilteredInstructions(f.FilteredInstructions),
  VariableInstructions(f.VariableInstructions),
  FilterChooserMap(f.FilterChooserMap), NumFiltered(f.NumFiltered),
  LastOpcFiltered(f.LastOpcFiltered), NumVariable(f.NumVariable) {
}

Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits,
    bool mixed) : Owner(&owner), StartBit(startBit), NumBits(numBits),
                  Mixed(mixed) {
  assert(StartBit + NumBits - 1 < BIT_WIDTH);

  NumFiltered = 0;
  LastOpcFiltered = 0;
  NumVariable = 0;

  for (unsigned i = 0, e = Owner->Opcodes.size(); i != e; ++i) {
    insn_t Insn;

    // Populates the insn given the uid.
    Owner->insnWithID(Insn, Owner->Opcodes[i]);

    uint64_t Field;
    // Scans the segment for possibly well-specified encoding bits.
    bool ok = Owner->fieldFromInsn(Field, Insn, StartBit, NumBits);

    if (ok) {
      // The encoding bits are well-known.  Lets add the uid of the
      // instruction into the bucket keyed off the constant field value.
      LastOpcFiltered = Owner->Opcodes[i];
      FilteredInstructions[Field].push_back(LastOpcFiltered);
      ++NumFiltered;
    } else {
      // Some of the encoding bit(s) are unspecfied.  This contributes to
      // one additional member of "Variable" instructions.
      VariableInstructions.push_back(Owner->Opcodes[i]);
      ++NumVariable;
    }
  }

  assert((FilteredInstructions.size() + VariableInstructions.size() > 0)
         && "Filter returns no instruction categories");
}

Filter::~Filter() {
  std::map<unsigned, FilterChooser*>::iterator filterIterator;
  for (filterIterator = FilterChooserMap.begin();
       filterIterator != FilterChooserMap.end();
       filterIterator++) {
    delete filterIterator->second;
  }
}

// Divides the decoding task into sub tasks and delegates them to the
// inferior FilterChooser's.
//
// A special case arises when there's only one entry in the filtered
// instructions.  In order to unambiguously decode the singleton, we need to
// match the remaining undecoded encoding bits against the singleton.
void Filter::recurse() {
  std::map<uint64_t, std::vector<unsigned> >::const_iterator mapIterator;

  bit_value_t BitValueArray[BIT_WIDTH];
  // Starts by inheriting our parent filter chooser's filter bit values.
  memcpy(BitValueArray, Owner->FilterBitValues, sizeof(BitValueArray));

  unsigned bitIndex;

  if (VariableInstructions.size()) {
    // Conservatively marks each segment position as BIT_UNSET.
    for (bitIndex = 0; bitIndex < NumBits; bitIndex++)
      BitValueArray[StartBit + bitIndex] = BIT_UNSET;

    // Delegates to an inferior filter chooser for futher processing on this
    // group of instructions whose segment values are variable.
    FilterChooserMap.insert(std::pair<unsigned, FilterChooser*>(
                              (unsigned)-1,
                              new FilterChooser(Owner->AllInstructions,
                                                VariableInstructions,
                                                BitValueArray,
                                                *Owner)
                              ));
  }

  // No need to recurse for a singleton filtered instruction.
  // See also Filter::emit().
  if (getNumFiltered() == 1) {
    //Owner->SingletonExists(LastOpcFiltered);
    assert(FilterChooserMap.size() == 1);
    return;
  }

  // Otherwise, create sub choosers.
  for (mapIterator = FilteredInstructions.begin();
       mapIterator != FilteredInstructions.end();
       mapIterator++) {

    // Marks all the segment positions with either BIT_TRUE or BIT_FALSE.
    for (bitIndex = 0; bitIndex < NumBits; bitIndex++) {
      if (mapIterator->first & (1ULL << bitIndex))
        BitValueArray[StartBit + bitIndex] = BIT_TRUE;
      else
        BitValueArray[StartBit + bitIndex] = BIT_FALSE;
    }

    // Delegates to an inferior filter chooser for futher processing on this
    // category of instructions.
    FilterChooserMap.insert(std::pair<unsigned, FilterChooser*>(
                              mapIterator->first,
                              new FilterChooser(Owner->AllInstructions,
                                                mapIterator->second,
                                                BitValueArray,
                                                *Owner)
                              ));
  }
}

// Emit code to decode instructions given a segment or segments of bits.
void Filter::emit(raw_ostream &o, unsigned &Indentation) {
  o.indent(Indentation) << "// Check Inst{";

  if (NumBits > 1)
    o << (StartBit + NumBits - 1) << '-';

  o << StartBit << "} ...\n";

  o.indent(Indentation) << "switch (fieldFromInstruction(insn, "
                        << StartBit << ", " << NumBits << ")) {\n";

  std::map<unsigned, FilterChooser*>::iterator filterIterator;

  bool DefaultCase = false;
  for (filterIterator = FilterChooserMap.begin();
       filterIterator != FilterChooserMap.end();
       filterIterator++) {

    // Field value -1 implies a non-empty set of variable instructions.
    // See also recurse().
    if (filterIterator->first == (unsigned)-1) {
      DefaultCase = true;

      o.indent(Indentation) << "default:\n";
      o.indent(Indentation) << "  break; // fallthrough\n";

      // Closing curly brace for the switch statement.
      // This is unconventional because we want the default processing to be
      // performed for the fallthrough cases as well, i.e., when the "cases"
      // did not prove a decoded instruction.
      o.indent(Indentation) << "}\n";

    } else
      o.indent(Indentation) << "case " << filterIterator->first << ":\n";

    // We arrive at a category of instructions with the same segment value.
    // Now delegate to the sub filter chooser for further decodings.
    // The case may fallthrough, which happens if the remaining well-known
    // encoding bits do not match exactly.
    if (!DefaultCase) { ++Indentation; ++Indentation; }

    bool finished = filterIterator->second->emit(o, Indentation);
    // For top level default case, there's no need for a break statement.
    if (Owner->isTopLevel() && DefaultCase)
      break;
    if (!finished)
      o.indent(Indentation) << "break;\n";

    if (!DefaultCase) { --Indentation; --Indentation; }
  }

  // If there is no default case, we still need to supply a closing brace.
  if (!DefaultCase) {
    // Closing curly brace for the switch statement.
    o.indent(Indentation) << "}\n";
  }
}

// Returns the number of fanout produced by the filter.  More fanout implies
// the filter distinguishes more categories of instructions.
unsigned Filter::usefulness() const {
  if (VariableInstructions.size())
    return FilteredInstructions.size();
  else
    return FilteredInstructions.size() + 1;
}

//////////////////////////////////
//                              //
// Filterchooser Implementation //
//                              //
//////////////////////////////////

// Define the symbol here.
TARGET_NAME_t FilterChooser::TargetName;

// This provides an opportunity for target specific code emission.
void FilterChooser::emitTopHook(raw_ostream &o) {
  if (TargetName == TARGET_ARM) {
    // Emit code that references the ARMFormat data type.
    o << "static const ARMFormat ARMFormats[] = {\n";
    for (unsigned i = 0, e = AllInstructions.size(); i != e; ++i) {
      const Record &Def = *(AllInstructions[i]->TheDef);
      const std::string &Name = Def.getName();
      if (Def.isSubClassOf("InstARM") || Def.isSubClassOf("InstThumb"))
        o.indent(2) << 
          stringForARMFormat((ARMFormat)getByteField(Def, "Form"));
      else
        o << "  ARM_FORMAT_NA";

      o << ",\t// Inst #" << i << " = " << Name << '\n';
    }
    o << "  ARM_FORMAT_NA\t// Unreachable.\n";
    o << "};\n\n";
  }
}

// Emit the top level typedef and decodeInstruction() function.
void FilterChooser::emitTop(raw_ostream &o, unsigned &Indentation) {
  // Run the target specific emit hook.
  emitTopHook(o);

  switch (BIT_WIDTH) {
  case 8:
    o.indent(Indentation) << "typedef uint8_t field_t;\n";
    break;
  case 16:
    o.indent(Indentation) << "typedef uint16_t field_t;\n";
    break;
  case 32:
    o.indent(Indentation) << "typedef uint32_t field_t;\n";
    break;
  case 64:
    o.indent(Indentation) << "typedef uint64_t field_t;\n";
    break;
  default:
    assert(0 && "Unexpected instruction size!");
  }

  o << '\n';

  o.indent(Indentation) << "static field_t " <<
    "fieldFromInstruction(field_t insn, unsigned startBit, unsigned numBits)\n";

  o.indent(Indentation) << "{\n";

  ++Indentation; ++Indentation;
  o.indent(Indentation) << "assert(startBit + numBits <= " << BIT_WIDTH
                        << " && \"Instruction field out of bounds!\");\n";
  o << '\n';
  o.indent(Indentation) << "field_t fieldMask;\n";
  o << '\n';
  o.indent(Indentation) << "if (numBits == " << BIT_WIDTH << ")\n";

  ++Indentation; ++Indentation;
  o.indent(Indentation) << "fieldMask = (field_t)-1;\n";
  --Indentation; --Indentation;

  o.indent(Indentation) << "else\n";

  ++Indentation; ++Indentation;
  o.indent(Indentation) << "fieldMask = ((1 << numBits) - 1) << startBit;\n";
  --Indentation; --Indentation;

  o << '\n';
  o.indent(Indentation) << "return (insn & fieldMask) >> startBit;\n";
  --Indentation; --Indentation;

  o.indent(Indentation) << "}\n";

  o << '\n';

  o.indent(Indentation) << "static uint16_t decodeInstruction(field_t insn) {\n";

  ++Indentation; ++Indentation;
  // Emits code to decode the instructions.
  emit(o, Indentation);

  o << '\n';
  o.indent(Indentation) << "return 0;\n";
  --Indentation; --Indentation;

  o.indent(Indentation) << "}\n";

  o << '\n';
}

// This provides an opportunity for target specific code emission after
// emitTop().
void FilterChooser::emitBot(raw_ostream &o, unsigned &Indentation) {
  if (TargetName != TARGET_THUMB) return;

  // Emit code that decodes the Thumb ISA.
  o.indent(Indentation)
    << "static uint16_t decodeThumbInstruction(field_t insn) {\n";

  ++Indentation; ++Indentation;

  // Emits code to decode the instructions.
  emit(o, Indentation);

  o << '\n';
  o.indent(Indentation) << "return 0;\n";

  --Indentation; --Indentation;

  o.indent(Indentation) << "}\n";
}

// Populates the field of the insn given the start position and the number of
// consecutive bits to scan for.
//
// Returns false if and on the first uninitialized bit value encountered.
// Returns true, otherwise.
bool FilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn,
    unsigned StartBit, unsigned NumBits) const {
  Field = 0;

  for (unsigned i = 0; i < NumBits; ++i) {
    if (Insn[StartBit + i] == BIT_UNSET)
      return false;

    if (Insn[StartBit + i] == BIT_TRUE)
      Field = Field | (1ULL << i);
  }

  return true;
}

/// dumpFilterArray - dumpFilterArray prints out debugging info for the given
/// filter array as a series of chars.
void FilterChooser::dumpFilterArray(raw_ostream &o,
    bit_value_t (&filter)[BIT_WIDTH]) {
  unsigned bitIndex;

  for (bitIndex = BIT_WIDTH; bitIndex > 0; bitIndex--) {
    switch (filter[bitIndex - 1]) {
    case BIT_UNFILTERED:
      o << ".";
      break;
    case BIT_UNSET:
      o << "_";
      break;
    case BIT_TRUE:
      o << "1";
      break;
    case BIT_FALSE:
      o << "0";
      break;
    }
  }
}

/// dumpStack - dumpStack traverses the filter chooser chain and calls
/// dumpFilterArray on each filter chooser up to the top level one.
void FilterChooser::dumpStack(raw_ostream &o, const char *prefix) {
  FilterChooser *current = this;

  while (current) {
    o << prefix;
    dumpFilterArray(o, current->FilterBitValues);
    o << '\n';
    current = current->Parent;
  }
}

// Called from Filter::recurse() when singleton exists.  For debug purpose.
void FilterChooser::SingletonExists(unsigned Opc) {
  insn_t Insn0;
  insnWithID(Insn0, Opc);

  errs() << "Singleton exists: " << nameWithID(Opc)
         << " with its decoding dominating ";
  for (unsigned i = 0; i < Opcodes.size(); ++i) {
    if (Opcodes[i] == Opc) continue;
    errs() << nameWithID(Opcodes[i]) << ' ';
  }
  errs() << '\n';

  dumpStack(errs(), "\t\t");
  for (unsigned i = 0; i < Opcodes.size(); i++) {
    const std::string &Name = nameWithID(Opcodes[i]);

    errs() << '\t' << Name << " ";
    dumpBits(errs(),
             getBitsField(*AllInstructions[Opcodes[i]]->TheDef, "Inst"));
    errs() << '\n';
  }
}

// Calculates the island(s) needed to decode the instruction.
// This returns a list of undecoded bits of an instructions, for example,
// Inst{20} = 1 && Inst{3-0} == 0b1111 represents two islands of yet-to-be
// decoded bits in order to verify that the instruction matches the Opcode.
unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits,
    std::vector<unsigned> &EndBits, std::vector<uint64_t> &FieldVals,
    insn_t &Insn) {
  unsigned Num, BitNo;
  Num = BitNo = 0;

  uint64_t FieldVal = 0;

  // 0: Init
  // 1: Water (the bit value does not affect decoding)
  // 2: Island (well-known bit value needed for decoding)
  int State = 0;
  int Val = -1;

  for (unsigned i = 0; i < BIT_WIDTH; ++i) {
    Val = Value(Insn[i]);
    bool Filtered = PositionFiltered(i);
    switch (State) {
    default:
      assert(0 && "Unreachable code!");
      break;
    case 0:
    case 1:
      if (Filtered || Val == -1)
        State = 1; // Still in Water
      else {
        State = 2; // Into the Island
        BitNo = 0;
        StartBits.push_back(i);
        FieldVal = Val;
      }
      break;
    case 2:
      if (Filtered || Val == -1) {
        State = 1; // Into the Water
        EndBits.push_back(i - 1);
        FieldVals.push_back(FieldVal);
        ++Num;
      } else {
        State = 2; // Still in Island
        ++BitNo;
        FieldVal = FieldVal | Val << BitNo;
      }
      break;
    }
  }
  // If we are still in Island after the loop, do some housekeeping.
  if (State == 2) {
    EndBits.push_back(BIT_WIDTH - 1);
    FieldVals.push_back(FieldVal);
    ++Num;
  }

  assert(StartBits.size() == Num && EndBits.size() == Num &&
         FieldVals.size() == Num);
  return Num;
}

// Emits code to decode the singleton.  Return true if we have matched all the
// well-known bits.
bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
                                         unsigned Opc) {
  std::vector<unsigned> StartBits;
  std::vector<unsigned> EndBits;
  std::vector<uint64_t> FieldVals;
  insn_t Insn;
  insnWithID(Insn, Opc);

  // This provides a good opportunity to check for possible Ld/St Coprocessor
  // Opcode and escapes if the coproc # is either 10 or 11.  It is a NEON/VFP
  // instruction is disguise.
  if (TargetName == TARGET_ARM && LdStCopEncoding1(Opc)) {
    o.indent(Indentation);
    // A8.6.51 & A8.6.188
    // If coproc = 0b101?, i.e, slice(insn, 11, 8) = 10 or 11, escape.
    o << "if (fieldFromInstruction(insn, 9, 3) == 5) break; // fallthrough\n";
  }

  // Look for islands of undecoded bits of the singleton.
  getIslands(StartBits, EndBits, FieldVals, Insn);

  unsigned Size = StartBits.size();
  unsigned I, NumBits;

  // If we have matched all the well-known bits, just issue a return.
  if (Size == 0) {
    o.indent(Indentation) << "return " << Opc << "; // " << nameWithID(Opc)
                          << '\n';
    return true;
  }

  // Otherwise, there are more decodings to be done!

  // Emit code to match the island(s) for the singleton.
  o.indent(Indentation) << "// Check ";

  for (I = Size; I != 0; --I) {
    o << "Inst{" << EndBits[I-1] << '-' << StartBits[I-1] << "} ";
    if (I > 1)
      o << "&& ";
    else
      o << "for singleton decoding...\n";
  }

  o.indent(Indentation) << "if (";

  for (I = Size; I != 0; --I) {
    NumBits = EndBits[I-1] - StartBits[I-1] + 1;
    o << "fieldFromInstruction(insn, " << StartBits[I-1] << ", " << NumBits
      << ") == " << FieldVals[I-1];
    if (I > 1)
      o << " && ";
    else
      o << ")\n";
  }

  o.indent(Indentation) << "  return " << Opc << "; // " << nameWithID(Opc)
                        << '\n';

  return false;
}

// Emits code to decode the singleton, and then to decode the rest.
void FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
    Filter &Best) {

  unsigned Opc = Best.getSingletonOpc();

  emitSingletonDecoder(o, Indentation, Opc);

  // Emit code for the rest.
  o.indent(Indentation) << "else\n";

  Indentation += 2;
  Best.getVariableFC().emit(o, Indentation);
  Indentation -= 2;
}

// Assign a single filter and run with it.  Top level API client can initialize
// with a single filter to start the filtering process.
void FilterChooser::runSingleFilter(FilterChooser &owner, unsigned startBit,
    unsigned numBit, bool mixed) {
  Filters.clear();
  Filter F(*this, startBit, numBit, true);
  Filters.push_back(F);
  BestIndex = 0; // Sole Filter instance to choose from.
  bestFilter().recurse();
}

// reportRegion is a helper function for filterProcessor to mark a region as
// eligible for use as a filter region.
void FilterChooser::reportRegion(bitAttr_t RA, unsigned StartBit,
    unsigned BitIndex, bool AllowMixed) {
  if (RA == ATTR_MIXED && AllowMixed)
    Filters.push_back(Filter(*this, StartBit, BitIndex - StartBit, true));   
  else if (RA == ATTR_ALL_SET && !AllowMixed)
    Filters.push_back(Filter(*this, StartBit, BitIndex - StartBit, false));
}

// FilterProcessor scans the well-known encoding bits of the instructions and
// builds up a list of candidate filters.  It chooses the best filter and
// recursively descends down the decoding tree.
bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) {
  Filters.clear();
  BestIndex = -1;
  unsigned numInstructions = Opcodes.size();

  assert(numInstructions && "Filter created with no instructions");

  // No further filtering is necessary.
  if (numInstructions == 1)
    return true;

  // Heuristics.  See also doFilter()'s "Heuristics" comment when num of
  // instructions is 3.
  if (AllowMixed && !Greedy) {
    assert(numInstructions == 3);

    for (unsigned i = 0; i < Opcodes.size(); ++i) {
      std::vector<unsigned> StartBits;
      std::vector<unsigned> EndBits;
      std::vector<uint64_t> FieldVals;
      insn_t Insn;

      insnWithID(Insn, Opcodes[i]);

      // Look for islands of undecoded bits of any instruction.
      if (getIslands(StartBits, EndBits, FieldVals, Insn) > 0) {
        // Found an instruction with island(s).  Now just assign a filter.
        runSingleFilter(*this, StartBits[0], EndBits[0] - StartBits[0] + 1,
                        true);
        return true;
      }
    }
  }

  unsigned BitIndex, InsnIndex;

  // We maintain BIT_WIDTH copies of the bitAttrs automaton.
  // The automaton consumes the corresponding bit from each
  // instruction.
  //
  //   Input symbols: 0, 1, and _ (unset).
  //   States:        NONE, FILTERED, ALL_SET, ALL_UNSET, and MIXED.
  //   Initial state: NONE.
  //
  // (NONE) ------- [01] -> (ALL_SET)
  // (NONE) ------- _ ----> (ALL_UNSET)
  // (ALL_SET) ---- [01] -> (ALL_SET)
  // (ALL_SET) ---- _ ----> (MIXED)
  // (ALL_UNSET) -- [01] -> (MIXED)
  // (ALL_UNSET) -- _ ----> (ALL_UNSET)
  // (MIXED) ------ . ----> (MIXED)
  // (FILTERED)---- . ----> (FILTERED)

  bitAttr_t bitAttrs[BIT_WIDTH];

  // FILTERED bit positions provide no entropy and are not worthy of pursuing.
  // Filter::recurse() set either BIT_TRUE or BIT_FALSE for each position.
  for (BitIndex = 0; BitIndex < BIT_WIDTH; ++BitIndex)
    if (FilterBitValues[BitIndex] == BIT_TRUE ||
        FilterBitValues[BitIndex] == BIT_FALSE)
      bitAttrs[BitIndex] = ATTR_FILTERED;
    else
      bitAttrs[BitIndex] = ATTR_NONE;

  for (InsnIndex = 0; InsnIndex < numInstructions; ++InsnIndex) {
    insn_t insn;

    insnWithID(insn, Opcodes[InsnIndex]);

    for (BitIndex = 0; BitIndex < BIT_WIDTH; ++BitIndex) {
      switch (bitAttrs[BitIndex]) {
      case ATTR_NONE:
        if (insn[BitIndex] == BIT_UNSET)
          bitAttrs[BitIndex] = ATTR_ALL_UNSET;
        else
          bitAttrs[BitIndex] = ATTR_ALL_SET;
        break;
      case ATTR_ALL_SET:
        if (insn[BitIndex] == BIT_UNSET)
          bitAttrs[BitIndex] = ATTR_MIXED;
        break;
      case ATTR_ALL_UNSET:
        if (insn[BitIndex] != BIT_UNSET)
          bitAttrs[BitIndex] = ATTR_MIXED;
        break;
      case ATTR_MIXED:
      case ATTR_FILTERED:
        break;
      }
    }
  }

  // The regionAttr automaton consumes the bitAttrs automatons' state,
  // lowest-to-highest.
  //
  //   Input symbols: F(iltered), (all_)S(et), (all_)U(nset), M(ixed)
  //   States:        NONE, ALL_SET, MIXED
  //   Initial state: NONE
  //
  // (NONE) ----- F --> (NONE)
  // (NONE) ----- S --> (ALL_SET)     ; and set region start
  // (NONE) ----- U --> (NONE)
  // (NONE) ----- M --> (MIXED)       ; and set region start
  // (ALL_SET) -- F --> (NONE)        ; and report an ALL_SET region
  // (ALL_SET) -- S --> (ALL_SET)
  // (ALL_SET) -- U --> (NONE)        ; and report an ALL_SET region
  // (ALL_SET) -- M --> (MIXED)       ; and report an ALL_SET region
  // (MIXED) ---- F --> (NONE)        ; and report a MIXED region
  // (MIXED) ---- S --> (ALL_SET)     ; and report a MIXED region
  // (MIXED) ---- U --> (NONE)        ; and report a MIXED region
  // (MIXED) ---- M --> (MIXED)

  bitAttr_t RA = ATTR_NONE;
  unsigned StartBit = 0;

  for (BitIndex = 0; BitIndex < BIT_WIDTH; BitIndex++) {
    bitAttr_t bitAttr = bitAttrs[BitIndex];

    assert(bitAttr != ATTR_NONE && "Bit without attributes");

    switch (RA) {
    case ATTR_NONE:
      switch (bitAttr) {
      case ATTR_FILTERED:
        break;
      case ATTR_ALL_SET:
        StartBit = BitIndex;
        RA = ATTR_ALL_SET;
        break;
      case ATTR_ALL_UNSET:
        break;
      case ATTR_MIXED:
        StartBit = BitIndex;
        RA = ATTR_MIXED;
        break;
      default:
        assert(0 && "Unexpected bitAttr!");
      }
      break;
    case ATTR_ALL_SET:
      switch (bitAttr) {
      case ATTR_FILTERED:
        reportRegion(RA, StartBit, BitIndex, AllowMixed);
        RA = ATTR_NONE;
        break;
      case ATTR_ALL_SET:
        break;
      case ATTR_ALL_UNSET:
        reportRegion(RA, StartBit, BitIndex, AllowMixed);
        RA = ATTR_NONE;
        break;
      case ATTR_MIXED:
        reportRegion(RA, StartBit, BitIndex, AllowMixed);
        StartBit = BitIndex;
        RA = ATTR_MIXED;
        break;
      default:
        assert(0 && "Unexpected bitAttr!");
      }
      break;
    case ATTR_MIXED:
      switch (bitAttr) {
      case ATTR_FILTERED:
        reportRegion(RA, StartBit, BitIndex, AllowMixed);
        StartBit = BitIndex;
        RA = ATTR_NONE;
        break;
      case ATTR_ALL_SET:
        reportRegion(RA, StartBit, BitIndex, AllowMixed);
        StartBit = BitIndex;
        RA = ATTR_ALL_SET;
        break;
      case ATTR_ALL_UNSET:
        reportRegion(RA, StartBit, BitIndex, AllowMixed);
        RA = ATTR_NONE;
        break;
      case ATTR_MIXED:
        break;
      default:
        assert(0 && "Unexpected bitAttr!");
      }
      break;
    case ATTR_ALL_UNSET:
      assert(0 && "regionAttr state machine has no ATTR_UNSET state");
    case ATTR_FILTERED:
      assert(0 && "regionAttr state machine has no ATTR_FILTERED state");
    }
  }

  // At the end, if we're still in ALL_SET or MIXED states, report a region
  switch (RA) {
  case ATTR_NONE:
    break;
  case ATTR_FILTERED:
    break;
  case ATTR_ALL_SET:
    reportRegion(RA, StartBit, BitIndex, AllowMixed);
    break;
  case ATTR_ALL_UNSET:
    break;
  case ATTR_MIXED:
    reportRegion(RA, StartBit, BitIndex, AllowMixed);
    break;
  }

  // We have finished with the filter processings.  Now it's time to choose
  // the best performing filter.
  BestIndex = 0;
  bool AllUseless = true;
  unsigned BestScore = 0;

  for (unsigned i = 0, e = Filters.size(); i != e; ++i) {
    unsigned Usefulness = Filters[i].usefulness();

    if (Usefulness)
      AllUseless = false;

    if (Usefulness > BestScore) {
      BestIndex = i;
      BestScore = Usefulness;
    }
  }

  if (!AllUseless)
    bestFilter().recurse();

  return !AllUseless;
} // end of FilterChooser::filterProcessor(bool)

// Decides on the best configuration of filter(s) to use in order to decode
// the instructions.  A conflict of instructions may occur, in which case we
// dump the conflict set to the standard error.
void FilterChooser::doFilter() {
  unsigned Num = Opcodes.size();
  assert(Num && "FilterChooser created with no instructions");

  // Heuristics: Use Inst{31-28} as the top level filter for ARM ISA.
  if (TargetName == TARGET_ARM && Parent == NULL) {
    runSingleFilter(*this, 28, 4, false);
    return;
  }

  // Try regions of consecutive known bit values first. 
  if (filterProcessor(false))
    return;

  // Then regions of mixed bits (both known and unitialized bit values allowed).
  if (filterProcessor(true))
    return;

  // Heuristics to cope with conflict set {t2CMPrs, t2SUBSrr, t2SUBSrs} where
  // no single instruction for the maximum ATTR_MIXED region Inst{14-4} has a
  // well-known encoding pattern.  In such case, we backtrack and scan for the
  // the very first consecutive ATTR_ALL_SET region and assign a filter to it.
  if (Num == 3 && filterProcessor(true, false))
    return;

  // If we come to here, the instruction decoding has failed.
  // Set the BestIndex to -1 to indicate so.
  BestIndex = -1;
}

// Emits code to decode our share of instructions.  Returns true if the
// emitted code causes a return, which occurs if we know how to decode
// the instruction at this level or the instruction is not decodeable.
bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) {
  if (Opcodes.size() == 1)
    // There is only one instruction in the set, which is great!
    // Call emitSingletonDecoder() to see whether there are any remaining
    // encodings bits.
    return emitSingletonDecoder(o, Indentation, Opcodes[0]);

  // Choose the best filter to do the decodings!
  if (BestIndex != -1) {
    Filter &Best = bestFilter();
    if (Best.getNumFiltered() == 1)
      emitSingletonDecoder(o, Indentation, Best);
    else
      bestFilter().emit(o, Indentation);
    return false;
  }

  // If we reach here, there is a conflict in decoding.  Let's resolve the known
  // conflicts!
  if ((TargetName == TARGET_ARM || TargetName == TARGET_THUMB) &&
      Opcodes.size() == 2) {
    // Resolve the known conflict sets:
    //
    // 1. source registers are identical => VMOVDneon; otherwise => VORRd
    // 2. source registers are identical => VMOVQ; otherwise => VORRq
    // 3. LDR, LDRcp => return LDR for now.
    // FIXME: How can we distinguish between LDR and LDRcp?  Do we need to?
    // 4. tLDM, tLDM_UPD => Rn = Inst{10-8}, reglist = Inst{7-0},
    //    wback = registers<Rn> = 0
    // NOTE: (tLDM, tLDM_UPD) resolution must come before Advanced SIMD
    //       addressing mode resolution!!!
    // 5. VLD[234]LN*/VST[234]LN* vs. VLD[234]LN*_UPD/VST[234]LN*_UPD conflicts
    //    are resolved returning the non-UPD versions of the instructions if the
    //    Rm field, i.e., Inst{3-0} is 0b1111.  This is specified in A7.7.1
    //    Advanced SIMD addressing mode.
    const std::string &name1 = nameWithID(Opcodes[0]);
    const std::string &name2 = nameWithID(Opcodes[1]);
    if ((name1 == "VMOVDneon" && name2 == "VORRd") ||
        (name1 == "VMOVQ" && name2 == "VORRq")) {
      // Inserting the opening curly brace for this case block.
      --Indentation; --Indentation;
      o.indent(Indentation) << "{\n";
      ++Indentation; ++Indentation;

      o.indent(Indentation)
        << "field_t N = fieldFromInstruction(insn, 7, 1), "
        << "M = fieldFromInstruction(insn, 5, 1);\n";
      o.indent(Indentation)
        << "field_t Vn = fieldFromInstruction(insn, 16, 4), "
        << "Vm = fieldFromInstruction(insn, 0, 4);\n";
      o.indent(Indentation)
        << "return (N == M && Vn == Vm) ? "
        << Opcodes[0] << " /* " << name1 << " */ : "
        << Opcodes[1] << " /* " << name2 << " */ ;\n";

      // Inserting the closing curly brace for this case block.
      --Indentation; --Indentation;
      o.indent(Indentation) << "}\n";
      ++Indentation; ++Indentation;

      return true;
    }
    if (name1 == "LDR" && name2 == "LDRcp") {
      o.indent(Indentation)
        << "return " << Opcodes[0]
        << "; // Returning LDR for {LDR, LDRcp}\n";
      return true;
    }
    if (name1 == "tLDM" && name2 == "tLDM_UPD") {
      // Inserting the opening curly brace for this case block.
      --Indentation; --Indentation;
      o.indent(Indentation) << "{\n";
      ++Indentation; ++Indentation;
      
      o.indent(Indentation)
        << "unsigned Rn = fieldFromInstruction(insn, 8, 3), "
        << "list = fieldFromInstruction(insn, 0, 8);\n";
      o.indent(Indentation)
        << "return ((list >> Rn) & 1) == 0 ? "
        << Opcodes[1] << " /* " << name2 << " */ : "
        << Opcodes[0] << " /* " << name1 << " */ ;\n";

      // Inserting the closing curly brace for this case block.
      --Indentation; --Indentation;
      o.indent(Indentation) << "}\n";
      ++Indentation; ++Indentation;

      return true;
    }
    if (sameStringExceptSuffix(name1, name2, "_UPD")) {
      o.indent(Indentation)
        << "return fieldFromInstruction(insn, 0, 4) == 15 ? " << Opcodes[0]
        << " /* " << name1 << " */ : " << Opcodes[1] << "/* " << name2
        << " */ ; // Advanced SIMD addressing mode\n";
      return true;
    }

    // Otherwise, it does not belong to the known conflict sets.
  }

  // We don't know how to decode these instructions!  Return 0 and dump the
  // conflict set!
  o.indent(Indentation) << "return 0;" << " // Conflict set: ";
  for (int i = 0, N = Opcodes.size(); i < N; ++i) {
    o << nameWithID(Opcodes[i]);
    if (i < (N - 1))
      o << ", ";
    else
      o << '\n';
  }

  // Print out useful conflict information for postmortem analysis.
  errs() << "Decoding Conflict:\n";

  dumpStack(errs(), "\t\t");

  for (unsigned i = 0; i < Opcodes.size(); i++) {
    const std::string &Name = nameWithID(Opcodes[i]);

    errs() << '\t' << Name << " ";
    dumpBits(errs(),
             getBitsField(*AllInstructions[Opcodes[i]]->TheDef, "Inst"));
    errs() << '\n';
  }

  return true;
}


////////////////////////////////////////////
//                                        //
//  ARMDEBackend                          //
//  (Helper class for ARMDecoderEmitter)  //
//                                        //
////////////////////////////////////////////

class ARMDecoderEmitter::ARMDEBackend {
public:
  ARMDEBackend(ARMDecoderEmitter &frontend) :
    NumberedInstructions(),
    Opcodes(),
    Frontend(frontend),
    Target(),
    FC(NULL)
  {
    if (Target.getName() == "ARM")
      TargetName = TARGET_ARM;
    else {
      errs() << "Target name " << Target.getName() << " not recognized\n";
      assert(0 && "Unknown target");
    }

    // Populate the instructions for our TargetName.
    populateInstructions();
  }

  ~ARMDEBackend() {
    if (FC) {
      delete FC;
      FC = NULL;
    }
  }

  void getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
                                                &NumberedInstructions) {
    // We must emit the PHI opcode first...
    std::string Namespace = Target.getInstNamespace();
    assert(!Namespace.empty() && "No instructions defined.");

    NumberedInstructions = Target.getInstructionsByEnumValue();
  }

  bool populateInstruction(const CodeGenInstruction &CGI, TARGET_NAME_t TN);

  void populateInstructions();

  // Emits disassembler code for instruction decoding.  This delegates to the
  // FilterChooser instance to do the heavy lifting.
  void emit(raw_ostream &o);

protected:
  std::vector<const CodeGenInstruction*> NumberedInstructions;
  std::vector<unsigned> Opcodes;
  // Special case for the ARM chip, which supports ARM and Thumb ISAs.
  // Opcodes2 will be populated with the Thumb opcodes.
  std::vector<unsigned> Opcodes2;
  ARMDecoderEmitter &Frontend;
  CodeGenTarget Target;
  FilterChooser *FC;

  TARGET_NAME_t TargetName;
};

bool ARMDecoderEmitter::ARMDEBackend::populateInstruction(
    const CodeGenInstruction &CGI, TARGET_NAME_t TN) {
  const Record &Def = *CGI.TheDef;
  const StringRef Name = Def.getName();
  uint8_t Form = getByteField(Def, "Form");

  BitsInit &Bits = getBitsField(Def, "Inst");

  // If all the bit positions are not specified; do not decode this instruction.
  // We are bound to fail!  For proper disassembly, the well-known encoding bits
  // of the instruction must be fully specified.
  //
  // This also removes pseudo instructions from considerations of disassembly,
  // which is a better design and less fragile than the name matchings.
  if (Bits.allInComplete()) return false;

  if (TN == TARGET_ARM) {
    // FIXME: what about Int_MemBarrierV6 and Int_SyncBarrierV6?
    if ((Name != "Int_MemBarrierV7" && Name != "Int_SyncBarrierV7") &&
        Form == ARM_FORMAT_PSEUDO)
      return false;
    if (thumbInstruction(Form))
      return false;
    if (Name.find("CMPz") != std::string::npos /* ||
        Name.find("CMNz") != std::string::npos */)
      return false;

    // Ignore pseudo instructions.
    if (Name == "BXr9" || Name == "BMOVPCRX" || Name == "BMOVPCRXr9")
      return false;

    // Tail calls are other patterns that generate existing instructions.
    if (Name == "TCRETURNdi" || Name == "TCRETURNdiND" ||
        Name == "TCRETURNri" || Name == "TCRETURNriND" ||
        Name == "TAILJMPd"  || Name == "TAILJMPdt" ||
        Name == "TAILJMPdND" || Name == "TAILJMPdNDt" ||
        Name == "TAILJMPr"  || Name == "TAILJMPrND" ||
        Name == "MOVr_TC")
      return false;

    // VLDMQ/VSTMQ can be handled with the more generic VLDMD/VSTMD.
    if (Name == "VLDMQ" || Name == "VLDMQ_UPD" ||
        Name == "VSTMQ" || Name == "VSTMQ_UPD")
      return false;

    //
    // The following special cases are for conflict resolutions.
    //

    // NEON NLdStFrm conflict resolutions:
    //
    // 1. Ignore suffix "odd" and "odd_UPD", prefer the "even" register-
    //    numbered ones which have the same Asm format string.
    // 2. Ignore VST2d64_UPD, which conflicts with VST1q64_UPD.
    // 3. Ignore VLD2d64_UPD, which conflicts with VLD1q64_UPD.
    // 4. Ignore VLD1q[_UPD], which conflicts with VLD1q64[_UPD].
    // 5. Ignore VST1q[_UPD], which conflicts with VST1q64[_UPD].
    if (Name.endswith("odd") || Name.endswith("odd_UPD") ||
        Name == "VST2d64_UPD" || Name == "VLD2d64_UPD" ||
        Name == "VLD1q" || Name == "VLD1q_UPD" ||
        Name == "VST1q" || Name == "VST1q_UPD")
      return false;

    // RSCSri and RSCSrs set the 's' bit, but are not predicated.  We are
    // better off using the generic RSCri and RSCrs instructions.
    if (Name == "RSCSri" || Name == "RSCSrs") return false;

    // MOVCCr, MOVCCs, MOVCCi, FCYPScc, FCYPDcc, FNEGScc, and FNEGDcc are used
    // in the compiler to implement conditional moves.  We can ignore them in
    // favor of their more generic versions of instructions.
    // See also SDNode *ARMDAGToDAGISel::Select(SDValue Op).
    if (Name == "MOVCCr" || Name == "MOVCCs" || Name == "MOVCCi" ||
        Name == "FCPYScc" || Name == "FCPYDcc" ||
        Name == "FNEGScc" || Name == "FNEGDcc")
      return false;

    // Ditto for VMOVDcc, VMOVScc, VNEGDcc, and VNEGScc.
    if (Name == "VMOVDcc" || Name == "VMOVScc" || Name == "VNEGDcc" ||
        Name == "VNEGScc")
      return false;

    // Ignore the *_sfp instructions when decoding.  They are used by the
    // compiler to implement scalar floating point operations using vector
    // operations in order to work around some performance issues.
    if (Name.find("_sfp") != std::string::npos) return false;

    // LDM_RET is a special case of LDM (Load Multiple) where the registers
    // loaded include the PC, causing a branch to a loaded address.  Ignore
    // the LDM_RET instruction when decoding.
    if (Name == "LDM_RET") return false;

    // Bcc is in a more generic form than B.  Ignore B when decoding.
    if (Name == "B") return false;

    // Ignore the non-Darwin BL instructions and the TPsoft (TLS) instruction.
    if (Name == "BL" || Name == "BL_pred" || Name == "BLX" || Name == "BX" ||
        Name == "TPsoft")
      return false;

    // Ignore VDUPf[d|q] instructions known to conflict with VDUP32[d-q] for
    // decoding.  The instruction duplicates an element from an ARM core
    // register into every element of the destination vector.  There is no
    // distinction between data types.
    if (Name == "VDUPfd" || Name == "VDUPfq") return false;

    // A8-598: VEXT
    // Vector Extract extracts elements from the bottom end of the second
    // operand vector and the top end of the first, concatenates them and
    // places the result in the destination vector.  The elements of the
    // vectors are treated as being 8-bit bitfields.  There is no distinction
    // between data types.  The size of the operation can be specified in
    // assembler as vext.size.  If the value is 16, 32, or 64, the syntax is
    // a pseudo-instruction for a VEXT instruction specifying the equivalent
    // number of bytes.
    //
    // Variants VEXTd16, VEXTd32, VEXTd8, and VEXTdf are reduced to VEXTd8;
    // variants VEXTq16, VEXTq32, VEXTq8, and VEXTqf are reduced to VEXTq8.
    if (Name == "VEXTd16" || Name == "VEXTd32" || Name == "VEXTdf" ||
        Name == "VEXTq16" || Name == "VEXTq32" || Name == "VEXTqf")
      return false;

    // Vector Reverse is similar to Vector Extract.  There is no distinction
    // between data types, other than size.
    //
    // VREV64df is equivalent to VREV64d32.
    // VREV64qf is equivalent to VREV64q32.
    if (Name == "VREV64df" || Name == "VREV64qf") return false;

    // VDUPLNfd is equivalent to VDUPLN32d; VDUPfdf is specialized VDUPLN32d.
    // VDUPLNfq is equivalent to VDUPLN32q; VDUPfqf is specialized VDUPLN32q.
    // VLD1df is equivalent to VLD1d32.
    // VLD1qf is equivalent to VLD1q32.
    // VLD2d64 is equivalent to VLD1q64.
    // VST1df is equivalent to VST1d32.
    // VST1qf is equivalent to VST1q32.
    // VST2d64 is equivalent to VST1q64.
    if (Name == "VDUPLNfd" || Name == "VDUPfdf" ||
        Name == "VDUPLNfq" || Name == "VDUPfqf" ||
        Name == "VLD1df" || Name == "VLD1qf" || Name == "VLD2d64" ||
        Name == "VST1df" || Name == "VST1qf" || Name == "VST2d64")
      return false;
  } else if (TN == TARGET_THUMB) {
    if (!thumbInstruction(Form))
      return false;

    // On Darwin R9 is call-clobbered.  Ignore the non-Darwin counterparts.
    if (Name == "tBL" || Name == "tBLXi" || Name == "tBLXr")
      return false;

    // Ignore the TPsoft (TLS) instructions, which conflict with tBLr9.
    if (Name == "tTPsoft" || Name == "t2TPsoft")
      return false;

    // Ignore tLEApcrel and tLEApcrelJT, prefer tADDrPCi.
    if (Name == "tLEApcrel" || Name == "tLEApcrelJT")
      return false;

    // Ignore t2LEApcrel, prefer the generic t2ADD* for disassembly printing.
    if (Name == "t2LEApcrel")
      return false;

    // Ignore tADDrSP, tADDspr, and tPICADD, prefer the generic tADDhirr.
    // Ignore t2SUBrSPs, prefer the t2SUB[S]r[r|s].
    // Ignore t2ADDrSPs, prefer the t2ADD[S]r[r|s].
    // Ignore t2ADDrSPi/t2SUBrSPi, which have more generic couterparts.
    // Ignore t2ADDrSPi12/t2SUBrSPi12, which have more generic couterparts
    if (Name == "tADDrSP" || Name == "tADDspr" || Name == "tPICADD" ||
        Name == "t2SUBrSPs" || Name == "t2ADDrSPs" ||
        Name == "t2ADDrSPi" || Name == "t2SUBrSPi" ||
        Name == "t2ADDrSPi12" || Name == "t2SUBrSPi12")
      return false;

    // Ignore t2LDRDpci, prefer the generic t2LDRDi8, t2LDRD_PRE, t2LDRD_POST.
    if (Name == "t2LDRDpci")
      return false;

    // Ignore t2TBB, t2TBH and prefer the generic t2TBBgen, t2TBHgen.
    if (Name == "t2TBB" || Name == "t2TBH")
      return false;

    // Resolve conflicts:
    //
    //   tBfar conflicts with tBLr9
    //   tCMNz conflicts with tCMN (with assembly format strings being equal)
    //   tPOP_RET/t2LDM_RET conflict with tPOP/t2LDM (ditto)
    //   tMOVCCi conflicts with tMOVi8
    //   tMOVCCr conflicts with tMOVgpr2gpr
    //   tBR_JTr conflicts with tBRIND
    //   tSpill conflicts with tSTRspi
    //   tLDRcp conflicts with tLDRspi
    //   tRestore conflicts with tLDRspi
    //   t2LEApcrelJT conflicts with t2LEApcrel
    if (Name == "tBfar" ||
        /* Name == "tCMNz" || */ Name == "tCMPzi8" || Name == "tCMPzr" ||
        Name == "tCMPzhir" || /* Name == "t2CMNzrr" || Name == "t2CMNzrs" ||
        Name == "t2CMNzri" || */ Name == "t2CMPzrr" || Name == "t2CMPzrs" ||
        Name == "t2CMPzri" || Name == "tPOP_RET" || Name == "t2LDM_RET" ||
        Name == "tMOVCCi" || Name == "tMOVCCr" || Name == "tBR_JTr" ||
        Name == "tSpill" || Name == "tLDRcp" || Name == "tRestore" ||
        Name == "t2LEApcrelJT")
      return false;
  }

  // Dumps the instruction encoding format.
  switch (TargetName) {
  case TARGET_ARM:
  case TARGET_THUMB:
    DEBUG(errs() << Name << " " << stringForARMFormat((ARMFormat)Form));
    break;
  }

  DEBUG({
      errs() << " ";

      // Dumps the instruction encoding bits.
      dumpBits(errs(), Bits);

      errs() << '\n';

      // Dumps the list of operand info.
      for (unsigned i = 0, e = CGI.OperandList.size(); i != e; ++i) {
        CodeGenInstruction::OperandInfo Info = CGI.OperandList[i];
        const std::string &OperandName = Info.Name;
        const Record &OperandDef = *Info.Rec;

        errs() << "\t" << OperandName << " (" << OperandDef.getName() << ")\n";
      }
    });

  return true;
}

void ARMDecoderEmitter::ARMDEBackend::populateInstructions() {
  getInstructionsByEnumValue(NumberedInstructions);

  uint16_t numUIDs = NumberedInstructions.size();
  uint16_t uid;

  const char *instClass = NULL;

  switch (TargetName) {
  case TARGET_ARM:
    instClass = "InstARM";
    break;
  default:
    assert(0 && "Unreachable code!");
  }

  for (uid = 0; uid < numUIDs; uid++) {
    // filter out intrinsics
    if (!NumberedInstructions[uid]->TheDef->isSubClassOf(instClass))
      continue;

    if (populateInstruction(*NumberedInstructions[uid], TargetName))
      Opcodes.push_back(uid);
  }

  // Special handling for the ARM chip, which supports two modes of execution.
  // This branch handles the Thumb opcodes.
  if (TargetName == TARGET_ARM) {
    for (uid = 0; uid < numUIDs; uid++) {
      // filter out intrinsics
      if (!NumberedInstructions[uid]->TheDef->isSubClassOf("InstARM")
          && !NumberedInstructions[uid]->TheDef->isSubClassOf("InstThumb"))
        continue;

      if (populateInstruction(*NumberedInstructions[uid], TARGET_THUMB))
        Opcodes2.push_back(uid);
    }
  }
}

// Emits disassembler code for instruction decoding.  This delegates to the
// FilterChooser instance to do the heavy lifting.
void ARMDecoderEmitter::ARMDEBackend::emit(raw_ostream &o) {
  switch (TargetName) {
  case TARGET_ARM:
    Frontend.EmitSourceFileHeader("ARM/Thumb Decoders", o);
    break;
  default:
    assert(0 && "Unreachable code!");
  }

  o << "#include \"llvm/System/DataTypes.h\"\n";
  o << "#include <assert.h>\n";
  o << '\n';
  o << "namespace llvm {\n\n";

  FilterChooser::setTargetName(TargetName);

  switch (TargetName) {
  case TARGET_ARM: {
    // Emit common utility and ARM ISA decoder.
    FC = new FilterChooser(NumberedInstructions, Opcodes);
    // Reset indentation level.
    unsigned Indentation = 0;
    FC->emitTop(o, Indentation);
    delete FC;

    // Emit Thumb ISA decoder as well.
    FilterChooser::setTargetName(TARGET_THUMB);
    FC = new FilterChooser(NumberedInstructions, Opcodes2);
    // Reset indentation level.
    Indentation = 0;
    FC->emitBot(o, Indentation);
    break;
  }
  default:
    assert(0 && "Unreachable code!");
  }

  o << "\n} // End llvm namespace \n";
}

/////////////////////////
//  Backend interface  //
/////////////////////////

void ARMDecoderEmitter::initBackend()
{
    Backend = new ARMDEBackend(*this);
}

void ARMDecoderEmitter::run(raw_ostream &o)
{
  Backend->emit(o);
}

void ARMDecoderEmitter::shutdownBackend()
{
  delete Backend;
  Backend = NULL;
}
