//===------------ 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 conflict 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, RecordKeeper &Records) :
    NumberedInstructions(),
    Opcodes(),
    Frontend(frontend),
    Target(Records),
    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;

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

    //
    // 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, MOVCCi16, 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 == "MOVCCi16" || 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;

    // LDMIA_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 LDMIA_RET instruction when decoding.
    if (Name == "LDMIA_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.
    // VDUPLNfq is equivalent to 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 == "VDUPLNfq" ||
        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;

    // Resolve conflicts:
    //
    //   tBfar conflicts with tBLr9
    //   tPOP_RET/t2LDMIA_RET conflict with tPOP/t2LDM (ditto)
    //   tMOVCCi conflicts with tMOVi8
    //   tMOVCCr conflicts with tMOVgpr2gpr
    //   tSpill conflicts with tSTRspi
    //   tLDRcp conflicts with tLDRspi
    //   tRestore conflicts with tLDRspi
    //   t2LEApcrelJT conflicts with t2LEApcrel
    //   t2MOVCCi16 conflicts with tMOVi16
    if (Name == "tBfar" ||
        Name == "tPOP_RET" || Name == "t2LDMIA_RET" ||
        Name == "tMOVCCi" || Name == "tMOVCCr" ||
        Name == "tSpill" || Name == "tLDRcp" || Name == "tRestore" ||
        Name == "t2LEApcrelJT" || Name == "t2MOVCCi16")
      return false;
  }

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

      errs() << " ";

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

      errs() << '\n';

      // Dumps the list of operand info.
      for (unsigned i = 0, e = CGI.Operands.size(); i != e; ++i) {
        const CGIOperandList::OperandInfo &Info = CGI.Operands[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/Support/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, Records);
}

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

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