Add FixedLenDecoderEmitter, the skeleton of a new disassembler emitter for fixed-length instruction encodings.

A major part of its (eventual) goal is to support a much cleaner separation between disassembly callbacks
provided by the target and the disassembler emitter itself, i.e. not requiring hardcoding of knowledge in tblgen
like the existing disassembly emitters do.

The hope is that some day this will allow us to replace the existing non-Thumb ARM disassembler and remove
some of the hacks the old one introduced to tblgen.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@125966 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Owen Anderson 2011-02-18 21:51:29 +00:00
parent ce99120084
commit d8c87888a7
5 changed files with 1535 additions and 99 deletions

View File

@ -245,6 +245,7 @@ class Instruction {
string DisableEncoding = ""; string DisableEncoding = "";
string PostEncoderMethod = ""; string PostEncoderMethod = "";
string DecoderMethod = "";
/// Target-specific flags. This becomes the TSFlags field in TargetInstrDesc. /// Target-specific flags. This becomes the TSFlags field in TargetInstrDesc.
bits<64> TSFlags = 0; bits<64> TSFlags = 0;
@ -360,6 +361,7 @@ class Operand<ValueType ty> {
ValueType Type = ty; ValueType Type = ty;
string PrintMethod = "printOperand"; string PrintMethod = "printOperand";
string EncoderMethod = ""; string EncoderMethod = "";
string DecoderMethod = "";
string AsmOperandLowerMethod = ?; string AsmOperandLowerMethod = ?;
dag MIOperandInfo = (ops); dag MIOperandInfo = (ops);

View File

@ -221,7 +221,7 @@ typedef enum {
#define BIT_WIDTH 32 #define BIT_WIDTH 32
// Forward declaration. // Forward declaration.
class FilterChooser; class ARMFilterChooser;
// Representation of the instruction to work on. // Representation of the instruction to work on.
typedef bit_value_t insn_t[BIT_WIDTH]; typedef bit_value_t insn_t[BIT_WIDTH];
@ -262,9 +262,9 @@ typedef bit_value_t insn_t[BIT_WIDTH];
/// decoder could try to decode the even/odd register numbering and assign to /// 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" /// 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. /// version and return the Opcode since the two have the same Asm format string.
class Filter { class ARMFilter {
protected: protected:
FilterChooser *Owner; // points to the FilterChooser who owns this filter ARMFilterChooser *Owner; // points to the FilterChooser who owns this filter
unsigned StartBit; // the starting bit position unsigned StartBit; // the starting bit position
unsigned NumBits; // number of bits to filter unsigned NumBits; // number of bits to filter
bool Mixed; // a mixed region contains both set and unset bits bool Mixed; // a mixed region contains both set and unset bits
@ -276,7 +276,7 @@ protected:
std::vector<unsigned> VariableInstructions; std::vector<unsigned> VariableInstructions;
// Map of well-known segment value to its delegate. // Map of well-known segment value to its delegate.
std::map<unsigned, FilterChooser*> FilterChooserMap; std::map<unsigned, ARMFilterChooser*> FilterChooserMap;
// Number of instructions which fall under FilteredInstructions category. // Number of instructions which fall under FilteredInstructions category.
unsigned NumFiltered; unsigned NumFiltered;
@ -296,16 +296,17 @@ public:
} }
// Return the filter chooser for the group of instructions without constant // Return the filter chooser for the group of instructions without constant
// segment values. // segment values.
FilterChooser &getVariableFC() { ARMFilterChooser &getVariableFC() {
assert(NumFiltered == 1); assert(NumFiltered == 1);
assert(FilterChooserMap.size() == 1); assert(FilterChooserMap.size() == 1);
return *(FilterChooserMap.find((unsigned)-1)->second); return *(FilterChooserMap.find((unsigned)-1)->second);
} }
Filter(const Filter &f); ARMFilter(const ARMFilter &f);
Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, bool mixed); ARMFilter(ARMFilterChooser &owner, unsigned startBit, unsigned numBits,
bool mixed);
~Filter(); ~ARMFilter();
// Divides the decoding task into sub tasks and delegates them to the // Divides the decoding task into sub tasks and delegates them to the
// inferior FilterChooser's. // inferior FilterChooser's.
@ -333,7 +334,7 @@ typedef enum {
ATTR_MIXED ATTR_MIXED
} bitAttr_t; } bitAttr_t;
/// FilterChooser - FilterChooser chooses the best filter among a set of Filters /// ARMFilterChooser - FilterChooser chooses the best filter among a set of Filters
/// in order to perform the decoding of instructions at the current level. /// 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 /// Decoding proceeds from the top down. Based on the well-known encoding bits
@ -348,11 +349,11 @@ typedef enum {
/// It is useful to think of a Filter as governing the switch stmts of the /// 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 /// decoding tree. And each case is delegated to an inferior FilterChooser to
/// decide what further remaining bits to look at. /// decide what further remaining bits to look at.
class FilterChooser { class ARMFilterChooser {
static TARGET_NAME_t TargetName; static TARGET_NAME_t TargetName;
protected: protected:
friend class Filter; friend class ARMFilter;
// Vector of codegen instructions to choose our filter. // Vector of codegen instructions to choose our filter.
const std::vector<const CodeGenInstruction*> &AllInstructions; const std::vector<const CodeGenInstruction*> &AllInstructions;
@ -361,14 +362,14 @@ protected:
const std::vector<unsigned> Opcodes; const std::vector<unsigned> Opcodes;
// Vector of candidate filters. // Vector of candidate filters.
std::vector<Filter> Filters; std::vector<ARMFilter> Filters;
// Array of bit values passed down from our parent. // Array of bit values passed down from our parent.
// Set to all BIT_UNFILTERED's for Parent == NULL. // Set to all BIT_UNFILTERED's for Parent == NULL.
bit_value_t FilterBitValues[BIT_WIDTH]; bit_value_t FilterBitValues[BIT_WIDTH];
// Links to the FilterChooser above us in the decoding tree. // Links to the FilterChooser above us in the decoding tree.
FilterChooser *Parent; ARMFilterChooser *Parent;
// Index of the best filter from Filters. // Index of the best filter from Filters.
int BestIndex; int BestIndex;
@ -376,13 +377,13 @@ protected:
public: public:
static void setTargetName(TARGET_NAME_t tn) { TargetName = tn; } static void setTargetName(TARGET_NAME_t tn) { TargetName = tn; }
FilterChooser(const FilterChooser &FC) : ARMFilterChooser(const ARMFilterChooser &FC) :
AllInstructions(FC.AllInstructions), Opcodes(FC.Opcodes), AllInstructions(FC.AllInstructions), Opcodes(FC.Opcodes),
Filters(FC.Filters), Parent(FC.Parent), BestIndex(FC.BestIndex) { Filters(FC.Filters), Parent(FC.Parent), BestIndex(FC.BestIndex) {
memcpy(FilterBitValues, FC.FilterBitValues, sizeof(FilterBitValues)); memcpy(FilterBitValues, FC.FilterBitValues, sizeof(FilterBitValues));
} }
FilterChooser(const std::vector<const CodeGenInstruction*> &Insts, ARMFilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
const std::vector<unsigned> &IDs) : const std::vector<unsigned> &IDs) :
AllInstructions(Insts), Opcodes(IDs), Filters(), Parent(NULL), AllInstructions(Insts), Opcodes(IDs), Filters(), Parent(NULL),
BestIndex(-1) { BestIndex(-1) {
@ -392,10 +393,10 @@ public:
doFilter(); doFilter();
} }
FilterChooser(const std::vector<const CodeGenInstruction*> &Insts, ARMFilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
const std::vector<unsigned> &IDs, const std::vector<unsigned> &IDs,
bit_value_t (&ParentFilterBitValues)[BIT_WIDTH], bit_value_t (&ParentFilterBitValues)[BIT_WIDTH],
FilterChooser &parent) : ARMFilterChooser &parent) :
AllInstructions(Insts), Opcodes(IDs), Filters(), Parent(&parent), AllInstructions(Insts), Opcodes(IDs), Filters(), Parent(&parent),
BestIndex(-1) { BestIndex(-1) {
for (unsigned i = 0; i < BIT_WIDTH; ++i) for (unsigned i = 0; i < BIT_WIDTH; ++i)
@ -426,8 +427,9 @@ protected:
Insn[i] = bitFromBits(Bits, i); Insn[i] = bitFromBits(Bits, i);
// Set Inst{21} to 1 (wback) when IndexModeBits == IndexModeUpd. // Set Inst{21} to 1 (wback) when IndexModeBits == IndexModeUpd.
if (getByteField(*AllInstructions[Opcode]->TheDef, "IndexModeBits") Record *R = AllInstructions[Opcode]->TheDef;
== IndexModeUpd) if (R->getValue("IndexModeBits") &&
getByteField(*R, "IndexModeBits") == IndexModeUpd)
Insn[21] = BIT_TRUE; Insn[21] = BIT_TRUE;
} }
@ -452,7 +454,7 @@ protected:
/// dumpFilterArray on each filter chooser up to the top level one. /// dumpFilterArray on each filter chooser up to the top level one.
void dumpStack(raw_ostream &o, const char *prefix); void dumpStack(raw_ostream &o, const char *prefix);
Filter &bestFilter() { ARMFilter &bestFilter() {
assert(BestIndex != -1 && "BestIndex not set"); assert(BestIndex != -1 && "BestIndex not set");
return Filters[BestIndex]; return Filters[BestIndex];
} }
@ -497,11 +499,12 @@ protected:
bool emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,unsigned Opc); bool emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,unsigned Opc);
// Emits code to decode the singleton, and then to decode the rest. // Emits code to decode the singleton, and then to decode the rest.
void emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,Filter &Best); void emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
ARMFilter &Best);
// Assign a single filter and run with it. // Assign a single filter and run with it.
void runSingleFilter(FilterChooser &owner, unsigned startBit, unsigned numBit, void runSingleFilter(ARMFilterChooser &owner, unsigned startBit,
bool mixed); unsigned numBit, bool mixed);
// reportRegion is a helper function for filterProcessor to mark a region as // reportRegion is a helper function for filterProcessor to mark a region as
// eligible for use as a filter region. // eligible for use as a filter region.
@ -530,7 +533,7 @@ protected:
// // // //
/////////////////////////// ///////////////////////////
Filter::Filter(const Filter &f) : ARMFilter::ARMFilter(const ARMFilter &f) :
Owner(f.Owner), StartBit(f.StartBit), NumBits(f.NumBits), Mixed(f.Mixed), Owner(f.Owner), StartBit(f.StartBit), NumBits(f.NumBits), Mixed(f.Mixed),
FilteredInstructions(f.FilteredInstructions), FilteredInstructions(f.FilteredInstructions),
VariableInstructions(f.VariableInstructions), VariableInstructions(f.VariableInstructions),
@ -538,7 +541,7 @@ Filter::Filter(const Filter &f) :
LastOpcFiltered(f.LastOpcFiltered), NumVariable(f.NumVariable) { LastOpcFiltered(f.LastOpcFiltered), NumVariable(f.NumVariable) {
} }
Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, ARMFilter::ARMFilter(ARMFilterChooser &owner, unsigned startBit, unsigned numBits,
bool mixed) : Owner(&owner), StartBit(startBit), NumBits(numBits), bool mixed) : Owner(&owner), StartBit(startBit), NumBits(numBits),
Mixed(mixed) { Mixed(mixed) {
assert(StartBit + NumBits - 1 < BIT_WIDTH); assert(StartBit + NumBits - 1 < BIT_WIDTH);
@ -575,8 +578,8 @@ Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits,
&& "Filter returns no instruction categories"); && "Filter returns no instruction categories");
} }
Filter::~Filter() { ARMFilter::~ARMFilter() {
std::map<unsigned, FilterChooser*>::iterator filterIterator; std::map<unsigned, ARMFilterChooser*>::iterator filterIterator;
for (filterIterator = FilterChooserMap.begin(); for (filterIterator = FilterChooserMap.begin();
filterIterator != FilterChooserMap.end(); filterIterator != FilterChooserMap.end();
filterIterator++) { filterIterator++) {
@ -590,7 +593,7 @@ Filter::~Filter() {
// A special case arises when there's only one entry in the filtered // A special case arises when there's only one entry in the filtered
// instructions. In order to unambiguously decode the singleton, we need to // instructions. In order to unambiguously decode the singleton, we need to
// match the remaining undecoded encoding bits against the singleton. // match the remaining undecoded encoding bits against the singleton.
void Filter::recurse() { void ARMFilter::recurse() {
std::map<uint64_t, std::vector<unsigned> >::const_iterator mapIterator; std::map<uint64_t, std::vector<unsigned> >::const_iterator mapIterator;
bit_value_t BitValueArray[BIT_WIDTH]; bit_value_t BitValueArray[BIT_WIDTH];
@ -606,12 +609,12 @@ void Filter::recurse() {
// Delegates to an inferior filter chooser for futher processing on this // Delegates to an inferior filter chooser for futher processing on this
// group of instructions whose segment values are variable. // group of instructions whose segment values are variable.
FilterChooserMap.insert(std::pair<unsigned, FilterChooser*>( FilterChooserMap.insert(std::pair<unsigned, ARMFilterChooser*>(
(unsigned)-1, (unsigned)-1,
new FilterChooser(Owner->AllInstructions, new ARMFilterChooser(Owner->AllInstructions,
VariableInstructions, VariableInstructions,
BitValueArray, BitValueArray,
*Owner) *Owner)
)); ));
} }
@ -638,18 +641,18 @@ void Filter::recurse() {
// Delegates to an inferior filter chooser for futher processing on this // Delegates to an inferior filter chooser for futher processing on this
// category of instructions. // category of instructions.
FilterChooserMap.insert(std::pair<unsigned, FilterChooser*>( FilterChooserMap.insert(std::pair<unsigned, ARMFilterChooser*>(
mapIterator->first, mapIterator->first,
new FilterChooser(Owner->AllInstructions, new ARMFilterChooser(Owner->AllInstructions,
mapIterator->second, mapIterator->second,
BitValueArray, BitValueArray,
*Owner) *Owner)
)); ));
} }
} }
// Emit code to decode instructions given a segment or segments of bits. // Emit code to decode instructions given a segment or segments of bits.
void Filter::emit(raw_ostream &o, unsigned &Indentation) { void ARMFilter::emit(raw_ostream &o, unsigned &Indentation) {
o.indent(Indentation) << "// Check Inst{"; o.indent(Indentation) << "// Check Inst{";
if (NumBits > 1) if (NumBits > 1)
@ -660,7 +663,7 @@ void Filter::emit(raw_ostream &o, unsigned &Indentation) {
o.indent(Indentation) << "switch (fieldFromInstruction(insn, " o.indent(Indentation) << "switch (fieldFromInstruction(insn, "
<< StartBit << ", " << NumBits << ")) {\n"; << StartBit << ", " << NumBits << ")) {\n";
std::map<unsigned, FilterChooser*>::iterator filterIterator; std::map<unsigned, ARMFilterChooser*>::iterator filterIterator;
bool DefaultCase = false; bool DefaultCase = false;
for (filterIterator = FilterChooserMap.begin(); for (filterIterator = FilterChooserMap.begin();
@ -709,7 +712,7 @@ void Filter::emit(raw_ostream &o, unsigned &Indentation) {
// Returns the number of fanout produced by the filter. More fanout implies // Returns the number of fanout produced by the filter. More fanout implies
// the filter distinguishes more categories of instructions. // the filter distinguishes more categories of instructions.
unsigned Filter::usefulness() const { unsigned ARMFilter::usefulness() const {
if (VariableInstructions.size()) if (VariableInstructions.size())
return FilteredInstructions.size(); return FilteredInstructions.size();
else else
@ -723,10 +726,10 @@ unsigned Filter::usefulness() const {
////////////////////////////////// //////////////////////////////////
// Define the symbol here. // Define the symbol here.
TARGET_NAME_t FilterChooser::TargetName; TARGET_NAME_t ARMFilterChooser::TargetName;
// This provides an opportunity for target specific code emission. // This provides an opportunity for target specific code emission.
void FilterChooser::emitTopHook(raw_ostream &o) { void ARMFilterChooser::emitTopHook(raw_ostream &o) {
if (TargetName == TARGET_ARM) { if (TargetName == TARGET_ARM) {
// Emit code that references the ARMFormat data type. // Emit code that references the ARMFormat data type.
o << "static const ARMFormat ARMFormats[] = {\n"; o << "static const ARMFormat ARMFormats[] = {\n";
@ -747,7 +750,7 @@ void FilterChooser::emitTopHook(raw_ostream &o) {
} }
// Emit the top level typedef and decodeInstruction() function. // Emit the top level typedef and decodeInstruction() function.
void FilterChooser::emitTop(raw_ostream &o, unsigned &Indentation) { void ARMFilterChooser::emitTop(raw_ostream &o, unsigned &Indentation) {
// Run the target specific emit hook. // Run the target specific emit hook.
emitTopHook(o); emitTopHook(o);
@ -818,7 +821,7 @@ void FilterChooser::emitTop(raw_ostream &o, unsigned &Indentation) {
// This provides an opportunity for target specific code emission after // This provides an opportunity for target specific code emission after
// emitTop(). // emitTop().
void FilterChooser::emitBot(raw_ostream &o, unsigned &Indentation) { void ARMFilterChooser::emitBot(raw_ostream &o, unsigned &Indentation) {
if (TargetName != TARGET_THUMB) return; if (TargetName != TARGET_THUMB) return;
// Emit code that decodes the Thumb ISA. // Emit code that decodes the Thumb ISA.
@ -843,7 +846,7 @@ void FilterChooser::emitBot(raw_ostream &o, unsigned &Indentation) {
// //
// Returns false if and on the first uninitialized bit value encountered. // Returns false if and on the first uninitialized bit value encountered.
// Returns true, otherwise. // Returns true, otherwise.
bool FilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn, bool ARMFilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn,
unsigned StartBit, unsigned NumBits) const { unsigned StartBit, unsigned NumBits) const {
Field = 0; Field = 0;
@ -860,7 +863,7 @@ bool FilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn,
/// dumpFilterArray - dumpFilterArray prints out debugging info for the given /// dumpFilterArray - dumpFilterArray prints out debugging info for the given
/// filter array as a series of chars. /// filter array as a series of chars.
void FilterChooser::dumpFilterArray(raw_ostream &o, void ARMFilterChooser::dumpFilterArray(raw_ostream &o,
bit_value_t (&filter)[BIT_WIDTH]) { bit_value_t (&filter)[BIT_WIDTH]) {
unsigned bitIndex; unsigned bitIndex;
@ -884,8 +887,8 @@ void FilterChooser::dumpFilterArray(raw_ostream &o,
/// dumpStack - dumpStack traverses the filter chooser chain and calls /// dumpStack - dumpStack traverses the filter chooser chain and calls
/// dumpFilterArray on each filter chooser up to the top level one. /// dumpFilterArray on each filter chooser up to the top level one.
void FilterChooser::dumpStack(raw_ostream &o, const char *prefix) { void ARMFilterChooser::dumpStack(raw_ostream &o, const char *prefix) {
FilterChooser *current = this; ARMFilterChooser *current = this;
while (current) { while (current) {
o << prefix; o << prefix;
@ -896,7 +899,7 @@ void FilterChooser::dumpStack(raw_ostream &o, const char *prefix) {
} }
// Called from Filter::recurse() when singleton exists. For debug purpose. // Called from Filter::recurse() when singleton exists. For debug purpose.
void FilterChooser::SingletonExists(unsigned Opc) { void ARMFilterChooser::SingletonExists(unsigned Opc) {
insn_t Insn0; insn_t Insn0;
insnWithID(Insn0, Opc); insnWithID(Insn0, Opc);
@ -923,7 +926,7 @@ void FilterChooser::SingletonExists(unsigned Opc) {
// This returns a list of undecoded bits of an instructions, for example, // 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 // 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. // decoded bits in order to verify that the instruction matches the Opcode.
unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits, unsigned ARMFilterChooser::getIslands(std::vector<unsigned> &StartBits,
std::vector<unsigned> &EndBits, std::vector<uint64_t> &FieldVals, std::vector<unsigned> &EndBits, std::vector<uint64_t> &FieldVals,
insn_t &Insn) { insn_t &Insn) {
unsigned Num, BitNo; unsigned Num, BitNo;
@ -983,7 +986,7 @@ unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits,
// Emits code to decode the singleton. Return true if we have matched all the // Emits code to decode the singleton. Return true if we have matched all the
// well-known bits. // well-known bits.
bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, bool ARMFilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
unsigned Opc) { unsigned Opc) {
std::vector<unsigned> StartBits; std::vector<unsigned> StartBits;
std::vector<unsigned> EndBits; std::vector<unsigned> EndBits;
@ -1046,8 +1049,9 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
} }
// Emits code to decode the singleton, and then to decode the rest. // Emits code to decode the singleton, and then to decode the rest.
void FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, void ARMFilterChooser::emitSingletonDecoder(raw_ostream &o,
Filter &Best) { unsigned &Indentation,
ARMFilter &Best) {
unsigned Opc = Best.getSingletonOpc(); unsigned Opc = Best.getSingletonOpc();
@ -1063,10 +1067,11 @@ void FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
// Assign a single filter and run with it. Top level API client can initialize // Assign a single filter and run with it. Top level API client can initialize
// with a single filter to start the filtering process. // with a single filter to start the filtering process.
void FilterChooser::runSingleFilter(FilterChooser &owner, unsigned startBit, void ARMFilterChooser::runSingleFilter(ARMFilterChooser &owner,
unsigned numBit, bool mixed) { unsigned startBit,
unsigned numBit, bool mixed) {
Filters.clear(); Filters.clear();
Filter F(*this, startBit, numBit, true); ARMFilter F(*this, startBit, numBit, true);
Filters.push_back(F); Filters.push_back(F);
BestIndex = 0; // Sole Filter instance to choose from. BestIndex = 0; // Sole Filter instance to choose from.
bestFilter().recurse(); bestFilter().recurse();
@ -1074,18 +1079,18 @@ void FilterChooser::runSingleFilter(FilterChooser &owner, unsigned startBit,
// reportRegion is a helper function for filterProcessor to mark a region as // reportRegion is a helper function for filterProcessor to mark a region as
// eligible for use as a filter region. // eligible for use as a filter region.
void FilterChooser::reportRegion(bitAttr_t RA, unsigned StartBit, void ARMFilterChooser::reportRegion(bitAttr_t RA, unsigned StartBit,
unsigned BitIndex, bool AllowMixed) { unsigned BitIndex, bool AllowMixed) {
if (RA == ATTR_MIXED && AllowMixed) if (RA == ATTR_MIXED && AllowMixed)
Filters.push_back(Filter(*this, StartBit, BitIndex - StartBit, true)); Filters.push_back(ARMFilter(*this, StartBit, BitIndex - StartBit, true));
else if (RA == ATTR_ALL_SET && !AllowMixed) else if (RA == ATTR_ALL_SET && !AllowMixed)
Filters.push_back(Filter(*this, StartBit, BitIndex - StartBit, false)); Filters.push_back(ARMFilter(*this, StartBit, BitIndex - StartBit, false));
} }
// FilterProcessor scans the well-known encoding bits of the instructions and // FilterProcessor scans the well-known encoding bits of the instructions and
// builds up a list of candidate filters. It chooses the best filter and // builds up a list of candidate filters. It chooses the best filter and
// recursively descends down the decoding tree. // recursively descends down the decoding tree.
bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { bool ARMFilterChooser::filterProcessor(bool AllowMixed, bool Greedy) {
Filters.clear(); Filters.clear();
BestIndex = -1; BestIndex = -1;
unsigned numInstructions = Opcodes.size(); unsigned numInstructions = Opcodes.size();
@ -1317,7 +1322,7 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) {
// Decides on the best configuration of filter(s) to use in order to decode // 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 // the instructions. A conflict of instructions may occur, in which case we
// dump the conflict set to the standard error. // dump the conflict set to the standard error.
void FilterChooser::doFilter() { void ARMFilterChooser::doFilter() {
unsigned Num = Opcodes.size(); unsigned Num = Opcodes.size();
assert(Num && "FilterChooser created with no instructions"); assert(Num && "FilterChooser created with no instructions");
@ -1350,7 +1355,7 @@ void FilterChooser::doFilter() {
// Emits code to decode our share of instructions. Returns true if the // 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 // emitted code causes a return, which occurs if we know how to decode
// the instruction at this level or the instruction is not decodeable. // the instruction at this level or the instruction is not decodeable.
bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) { bool ARMFilterChooser::emit(raw_ostream &o, unsigned &Indentation) {
if (Opcodes.size() == 1) if (Opcodes.size() == 1)
// There is only one instruction in the set, which is great! // There is only one instruction in the set, which is great!
// Call emitSingletonDecoder() to see whether there are any remaining // Call emitSingletonDecoder() to see whether there are any remaining
@ -1359,7 +1364,7 @@ bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) {
// Choose the best filter to do the decodings! // Choose the best filter to do the decodings!
if (BestIndex != -1) { if (BestIndex != -1) {
Filter &Best = bestFilter(); ARMFilter &Best = bestFilter();
if (Best.getNumFiltered() == 1) if (Best.getNumFiltered() == 1)
emitSingletonDecoder(o, Indentation, Best); emitSingletonDecoder(o, Indentation, Best);
else else
@ -1538,7 +1543,7 @@ protected:
std::vector<unsigned> Opcodes2; std::vector<unsigned> Opcodes2;
ARMDecoderEmitter &Frontend; ARMDecoderEmitter &Frontend;
CodeGenTarget Target; CodeGenTarget Target;
FilterChooser *FC; ARMFilterChooser *FC;
TARGET_NAME_t TargetName; TARGET_NAME_t TargetName;
}; };
@ -1752,32 +1757,20 @@ ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI,
void ARMDecoderEmitter::ARMDEBackend::populateInstructions() { void ARMDecoderEmitter::ARMDEBackend::populateInstructions() {
getInstructionsByEnumValue(NumberedInstructions); getInstructionsByEnumValue(NumberedInstructions);
uint16_t numUIDs = NumberedInstructions.size(); unsigned 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) { if (TargetName == TARGET_ARM) {
for (uid = 0; uid < numUIDs; uid++) { for (unsigned uid = 0; uid < numUIDs; uid++) {
// filter out intrinsics
if (!NumberedInstructions[uid]->TheDef->isSubClassOf("InstARM"))
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.
for (unsigned uid = 0; uid < numUIDs; uid++) {
// filter out intrinsics // filter out intrinsics
if (!NumberedInstructions[uid]->TheDef->isSubClassOf("InstARM") if (!NumberedInstructions[uid]->TheDef->isSubClassOf("InstARM")
&& !NumberedInstructions[uid]->TheDef->isSubClassOf("InstThumb")) && !NumberedInstructions[uid]->TheDef->isSubClassOf("InstThumb"))
@ -1786,6 +1779,18 @@ void ARMDecoderEmitter::ARMDEBackend::populateInstructions() {
if (populateInstruction(*NumberedInstructions[uid], TARGET_THUMB)) if (populateInstruction(*NumberedInstructions[uid], TARGET_THUMB))
Opcodes2.push_back(uid); Opcodes2.push_back(uid);
} }
return;
}
// For other targets.
for (unsigned uid = 0; uid < numUIDs; uid++) {
Record *R = NumberedInstructions[uid]->TheDef;
if (R->getValueAsString("Namespace") == "TargetOpcode")
continue;
if (populateInstruction(*NumberedInstructions[uid], TargetName))
Opcodes.push_back(uid);
} }
} }
@ -1805,20 +1810,20 @@ void ARMDecoderEmitter::ARMDEBackend::emit(raw_ostream &o) {
o << '\n'; o << '\n';
o << "namespace llvm {\n\n"; o << "namespace llvm {\n\n";
FilterChooser::setTargetName(TargetName); ARMFilterChooser::setTargetName(TargetName);
switch (TargetName) { switch (TargetName) {
case TARGET_ARM: { case TARGET_ARM: {
// Emit common utility and ARM ISA decoder. // Emit common utility and ARM ISA decoder.
FC = new FilterChooser(NumberedInstructions, Opcodes); FC = new ARMFilterChooser(NumberedInstructions, Opcodes);
// Reset indentation level. // Reset indentation level.
unsigned Indentation = 0; unsigned Indentation = 0;
FC->emitTop(o, Indentation); FC->emitTop(o, Indentation);
delete FC; delete FC;
// Emit Thumb ISA decoder as well. // Emit Thumb ISA decoder as well.
FilterChooser::setTargetName(TARGET_THUMB); ARMFilterChooser::setTargetName(TARGET_THUMB);
FC = new FilterChooser(NumberedInstructions, Opcodes2); FC = new ARMFilterChooser(NumberedInstructions, Opcodes2);
// Reset indentation level. // Reset indentation level.
Indentation = 0; Indentation = 0;
FC->emitBot(o, Indentation); FC->emitBot(o, Indentation);

View File

@ -13,6 +13,7 @@
#include "X86DisassemblerTables.h" #include "X86DisassemblerTables.h"
#include "X86RecognizableInstr.h" #include "X86RecognizableInstr.h"
#include "ARMDecoderEmitter.h" #include "ARMDecoderEmitter.h"
#include "FixedLenDecoderEmitter.h"
using namespace llvm; using namespace llvm;
using namespace llvm::X86Disassembler; using namespace llvm::X86Disassembler;
@ -127,11 +128,11 @@ void DisassemblerEmitter::run(raw_ostream &OS) {
} }
// Fixed-instruction-length targets use a common disassembler. // Fixed-instruction-length targets use a common disassembler.
// ARM use its own implementation for now.
if (Target.getName() == "ARM") { if (Target.getName() == "ARM") {
ARMDecoderEmitter(Records).run(OS); ARMDecoderEmitter(Records).run(OS);
return; return;
} }
throw TGError(Target.getTargetRecord()->getLoc(), FixedLenDecoderEmitter(Records).run(OS);
"Unable to generate disassembler for this target");
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,56 @@
//===------------ FixedLenDecoderEmitter.h - Decoder Generator --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// It contains the tablegen backend that emits the decoder functions for
// targets with fixed length instruction set.
//
//===----------------------------------------------------------------------===//
#ifndef FixedLenDECODEREMITTER_H
#define FixedLenDECODEREMITTER_H
#include "CodeGenTarget.h"
#include "TableGenBackend.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
struct OperandInfo {
unsigned FieldBase;
unsigned FieldLength;
std::string Decoder;
OperandInfo(unsigned FB, unsigned FL, std::string D)
: FieldBase(FB), FieldLength(FL), Decoder(D) { }
};
class FixedLenDecoderEmitter : public TableGenBackend {
public:
FixedLenDecoderEmitter(RecordKeeper &R) :
Records(R), Target(R),
NumberedInstructions(Target.getInstructionsByEnumValue()) {}
// run - Output the code emitter
void run(raw_ostream &o);
private:
RecordKeeper &Records;
CodeGenTarget Target;
std::vector<const CodeGenInstruction*> NumberedInstructions;
std::vector<unsigned> Opcodes;
std::map<unsigned, std::vector<OperandInfo> > Operands;
bool populateInstruction(const CodeGenInstruction &CGI, unsigned Opc);
void populateInstructions();
};
} // end llvm namespace
#endif