aboutsummaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
authorJohnny Chen <johnny.chen@apple.com>2009-10-29 02:04:53 +0000
committerJohnny Chen <johnny.chen@apple.com>2009-10-29 02:04:53 +0000
commitf7bb23f343792df7739be6bf3a1f693214e13f19 (patch)
treed7367f0b61584a270684fb043f7026de15ffe85b /utils
parent1846dfa45079376f170fa50153344f48ff2bd257 (diff)
downloadexternal_llvm-f7bb23f343792df7739be6bf3a1f693214e13f19.zip
external_llvm-f7bb23f343792df7739be6bf3a1f693214e13f19.tar.gz
external_llvm-f7bb23f343792df7739be6bf3a1f693214e13f19.tar.bz2
Sorry to break the build.
I was trying to check the WIP file to some local repository, but ended up checking in the llvm repository. Oops! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85470 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/RISCDisassemblerEmitter.cpp1158
1 files changed, 0 insertions, 1158 deletions
diff --git a/utils/TableGen/RISCDisassemblerEmitter.cpp b/utils/TableGen/RISCDisassemblerEmitter.cpp
deleted file mode 100644
index 3ef697c..0000000
--- a/utils/TableGen/RISCDisassemblerEmitter.cpp
+++ /dev/null
@@ -1,1158 +0,0 @@
-//===- RISCDisassemblerEmitter.cpp - Disassembler Generator ---------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// FIXME: document
-//
-//===----------------------------------------------------------------------===//
-
-#include "RISCDisassemblerEmitter.h"
-#include "CodeGenTarget.h"
-#include "Record.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/Debug.h"
-
-#include <iostream>
-#include <iomanip>
-#include <vector>
-#include <cstdio>
-#include <map>
-#include <string>
-#include <sstream>
-
-#include <asl.h>
-
-using namespace llvm;
-
-#pragma mark Utility classes / structures
-
-// LLVM coding style
-#define INDENT_LEVEL 2
-
-class Indenter {
-public:
- Indenter() : fDepth(0) {
- memset(fString, ' ', sizeof(fString));
- fString[fDepth] = '\0';
- }
-
- void push() {
- if (fDepth < sizeof(fString) - INDENT_LEVEL) {
- fString[fDepth] = ' ';
- fDepth += INDENT_LEVEL;
- fString[fDepth] = '\0';
- }
- }
-
- void pop() {
- if(fDepth >= INDENT_LEVEL) {
- fString[fDepth] = ' ';
- fDepth -= INDENT_LEVEL;
- fString[fDepth] = '\0';
- }
- }
-
- const char* indent() const {
- return &fString[0];
- }
-private:
- char fString[256];
- uint8_t fDepth;
-};
-
-#pragma mark Utility functions
-
-#if 0
-static int dprintf(int level, const char* format, ...) throw() {
- static aslmsg* fMessage = NULL;
-
- if (!fMessage) {
- fMessage = new aslmsg;
- *fMessage = asl_new(ASL_TYPE_MSG);
- asl_set(*fMessage, ASL_KEY_FACILITY, "com.apple.llvm.disassembler.emitter.risc");
- }
-
- va_list ap;
-
- va_start(ap, format);
- int ret = asl_vlog(NULL, *fMessage, level, format, ap);
- va_end(ap);
-
- return ret;
-}
-#endif
-
-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;
-}
-
-#if 0
-static void binaryFromNumber(std::string& binary,
- uint64_t number,
- unsigned minimumWidth = 1) {
- unsigned bitIndex;
- bool emitting = false;
-
- binary = "0b";
-
- for (bitIndex = (sizeof(number) * 8); bitIndex > 0; bitIndex--) {
- uint64_t bit = (number & (1 << (bitIndex - 1))) >> (bitIndex - 1);
-
- if (bitIndex == minimumWidth)
- emitting = true;
-
- if (bit) {
- emitting = true;
- binary.append("1");
- } else if(emitting) {
- binary.append("0");
- }
- }
-}
-#endif
-
-// 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
-} bitValue_t;
-
-static bitValue_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;
-}
-
-static void dumpBits(std::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");
- }
- }
-}
-
-#pragma mark Enums
-
-#define ARM_FORMS \
- ENTRY(ARM_FORM_PSEUDO, 0) \
- ENTRY(ARM_FORM_MULFRM, 1) \
- ENTRY(ARM_FORM_BRFRM, 2) \
- ENTRY(ARM_FORM_BRMISCFRM, 3) \
- ENTRY(ARM_FORM_DPFRM, 4) \
- ENTRY(ARM_FORM_DPSOREGFRM, 5) \
- ENTRY(ARM_FORM_LDFRM, 6) \
- ENTRY(ARM_FORM_STFRM, 7) \
- ENTRY(ARM_FORM_LDMISCFRM, 8) \
- ENTRY(ARM_FORM_STMISCFRM, 9) \
- ENTRY(ARM_FORM_LDSTMULFRM, 10) \
- ENTRY(ARM_FORM_ARITHMISCFRM, 11) \
- ENTRY(ARM_FORM_EXTFRM, 12) \
- ENTRY(ARM_FORM_VFPUNARYFRM, 13) \
- ENTRY(ARM_FORM_VFPBINARYFRM, 14) \
- ENTRY(ARM_FORM_VFPCONV1FRM, 15) \
- ENTRY(ARM_FORM_VFPCONV2FRM, 16) \
- ENTRY(ARM_FORM_VFPCONV3FRM, 17) \
- ENTRY(ARM_FORM_VFPCONV4FRM, 18) \
- ENTRY(ARM_FORM_VFPCONV5FRM, 19) \
- ENTRY(ARM_FORM_VFPLDSTFRM, 20) \
- ENTRY(ARM_FORM_VFPLDSTMULFRM, 21) \
- ENTRY(ARM_FORM_VFPMISCFRM, 22) \
- ENTRY(ARM_FORM_THUMBFRM, 23) \
- ENTRY(ARM_FORM_NEONFRM, 24) \
- ENTRY(ARM_FORM_NEONGETLNFRM, 25) \
- ENTRY(ARM_FORM_NEONSETLNFRM, 26) \
- ENTRY(ARM_FORM_NEONDUPFRM, 27)
-
-// ARM instruction format specifies the encoding used by the instruction.
-#define ENTRY(n, v) n = v,
-enum ARMForm {
- ARM_FORMS
- ARM_FORM_max
-};
-#undef ENTRY
-
-// Converts enum to const char*.
-static const char* stringWithARMForm(enum ARMForm form) {
-#define ENTRY(n, v) case n: return #n;
- switch(form) {
- ARM_FORMS
- case ARM_FORM_max:
- default:
- return "";
- }
-#undef ENTRY
-}
-
-static std::vector< std::vector<unsigned> > sConflicts;
-
-class AbstractFilterChooser {
-public:
- virtual void emitTop(std::ostream& o, Indenter& i) = 0;
-};
-
-template <unsigned tBitWidth>
-class FilterChooser : public AbstractFilterChooser {
-protected:
- // Representation of the instruction to work on.
- typedef uint8_t insn_t[tBitWidth];
-
- class Filter {
- protected:
- FilterChooser* fParent; // pointer without ownership
- unsigned fStartBit; // the starting bit position
- unsigned fNumBits; // number of bits to filter
- bool fMixed; // a mixed region contains 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> > fFilteredInstructions;
-
- // Set of uid's with non-constant segment values.
- std::vector<unsigned> fVariableInstructions;
-
- // Map of well-known segment value to its delegate.
- std::map<unsigned, FilterChooser> fSubChoosers;
- public:
- Filter(const Filter& f) :
- fParent(f.fParent),
- fStartBit(f.fStartBit),
- fNumBits(f.fNumBits),
- fMixed(f.fMixed),
- fFilteredInstructions(f.fFilteredInstructions),
- fVariableInstructions(f.fVariableInstructions),
- fSubChoosers(f.fSubChoosers) { }
-
- Filter(FilterChooser& parent, unsigned startBit, unsigned numBits, bool mixed) :
- fParent(&parent),
- fStartBit(startBit),
- fNumBits(numBits),
- fMixed(mixed)
- {
- unsigned insnIndex;
- unsigned numInsns = fParent->fInstructionsToFilter.size();
-
- for (insnIndex = 0; insnIndex < numInsns; insnIndex++) {
- insn_t insn;
-
- // Populates the insn given the uid.
- fParent->insnWithID(insn, fParent->fInstructionsToFilter[insnIndex]);
-
- uint64_t field;
- // Scans the segment for possibly well-specified encoding bits.
- bool ok = fParent->fieldFromInsn(field, insn, fStartBit, fNumBits);
-
- if (ok) {
- // The encoding bits are well-known. Lets add the uid of the
- // instruction into the bucket keyed off the constant field value.
- fFilteredInstructions[field].push_back(fParent->fInstructionsToFilter[insnIndex]);
- } else {
- // Some of the encoding bit(s) are unspecfied. This contributes to
- // one additional member of "Variable" instructions.
- fVariableInstructions.push_back(fParent->fInstructionsToFilter[insnIndex]);
- }
- }
-
- assert((fFilteredInstructions.size() + fVariableInstructions.size() > 0)
- && "Filter returns no instruction categories");
- }
-
- // Divides the decoding task into sub tasks and delegates them to the
- // inferior FilterChooser's.
- void recurse() {
- std::map<uint64_t, std::vector<unsigned> >::const_iterator mapIterator;
-
- bitValue_t filtered[tBitWidth];
- // Starts by inheriting our parent filter chooser's bit values.
- memcpy(filtered, fParent->fFiltered, sizeof(filtered));
-
- unsigned bitIndex;
-
- for (mapIterator = fFilteredInstructions.begin();
- mapIterator != fFilteredInstructions.end();
- mapIterator++) {
-
- // Marks all the segment positions with either BIT_TRUE or BIT_FALSE.
- for (bitIndex = 0; bitIndex < fNumBits; bitIndex++) {
- if (mapIterator->first & (1 << bitIndex))
- filtered[fStartBit + bitIndex] = BIT_TRUE;
- else
- filtered[fStartBit + bitIndex] = BIT_FALSE;
- }
-
- // Delegates to an inferior filter chooser for futher processing on this
- // category of instructions.
- fSubChoosers.insert(std::pair<unsigned, FilterChooser>(
- mapIterator->first,
- FilterChooser(fParent->fAllInstructions,
- mapIterator->second,
- filtered,
- *fParent)
- ));
- }
-
- if (fVariableInstructions.size()) {
- // Conservatively marks each segment position as BIT_UNSET.
- for (bitIndex = 0; bitIndex < fNumBits; bitIndex++)
- filtered[fStartBit + bitIndex] = BIT_UNSET;
-
- // Delegates to an inferior filter chooser for futher processing on this
- // group of instructions whose segment values are variable.
- fSubChoosers.insert(std::pair<unsigned, FilterChooser>(
- (unsigned)-1,
- FilterChooser(fParent->fAllInstructions,
- fVariableInstructions,
- filtered,
- *fParent)
- ));
- }
- }
-
- // Emits code to decode instructions given a segment of bits.
- void emit(std::ostream& o, Indenter& i) {
- o << i.indent() << "// Check Inst{";
-
- if (fNumBits > 1)
- o << (fStartBit + fNumBits - 1) << '-';
-
- o << fStartBit << "} ...\n";
-
- o << i.indent() << "switch (fieldFromInstruction(insn, " << fStartBit << ", " << fNumBits << ")) {\n";
- i.push();
-
- typename std::map<unsigned, FilterChooser>::iterator filterIterator;
-
- for (filterIterator = fSubChoosers.begin();
- filterIterator != fSubChoosers.end();
- filterIterator++) {
-
- // Field value -1 implies a non-empty set of variable instructions.
- // See also recurse().
- if (filterIterator->first == (unsigned)-1)
- o << i.indent() << "default:\n";
- else
- o << i.indent() << "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.
- i.push();
- {
- bool finished = filterIterator->second.emit(o, i);
- if (!finished) o << i.indent() << "break;\n";
- }
- i.pop();
- }
-
- i.pop();
- o << i.indent() << "}\n";
- }
-
- // Returns the number of fanout produced by the filter. More fanout implies
- // the filter distinguishes more categories of instructions.
- unsigned usefulness() const {
- if (fVariableInstructions.size())
- return fFilteredInstructions.size();
- else
- return fFilteredInstructions.size() - 1;
- }
- };
-
- friend class Filter;
-
- // Vector of codegen instructions to choose our filter.
- const std::vector<const CodeGenInstruction*>& fAllInstructions;
-
- // Vector of uid's for this filter chooser to work on.
- const std::vector<unsigned> fInstructionsToFilter;
-
- // Vector of candidate filters.
- std::vector<Filter> fFilters;
-
- // Array of bit values passed down from our parent.
- // Set to all BIT_UNFILTERED's for fRarent == NULL.
- bitValue_t fFiltered[tBitWidth];
-
- // Link to the FilterChooser in our parent chain.
- FilterChooser* fParent;
-
- // Index of the best filter from fFilters.
- int fBestIndex;
-
-public:
- FilterChooser(const FilterChooser& fc) :
- AbstractFilterChooser(),
- fAllInstructions(fc.fAllInstructions),
- fInstructionsToFilter(fc.fInstructionsToFilter),
- fFilters(fc.fFilters),
- fParent(fc.fParent),
- fBestIndex(fc.fBestIndex)
- {
- memcpy(fFiltered, fc.fFiltered, sizeof(fFiltered));
- }
-
- FilterChooser(const std::vector<const CodeGenInstruction*>& allInstructions,
- const std::vector<unsigned>& instructionsToFilter) :
- fAllInstructions(allInstructions),
- fInstructionsToFilter(instructionsToFilter),
- fFilters(),
- fParent(NULL),
- fBestIndex(-1)
- {
- unsigned bitIndex;
-
- for (bitIndex = 0; bitIndex < tBitWidth; bitIndex++)
- fFiltered[bitIndex] = BIT_UNFILTERED;
-
- doFilter();
- }
-
- FilterChooser(const std::vector<const CodeGenInstruction*>& allInstructions,
- const std::vector<unsigned>& instructionsToFilter,
- bitValue_t (&lastFiltered)[tBitWidth],
- FilterChooser& parent) :
- fAllInstructions(allInstructions),
- fInstructionsToFilter(instructionsToFilter),
- fFilters(),
- fParent(&parent),
- fBestIndex(-1)
- {
- unsigned bitIndex;
-
- for (bitIndex = 0; bitIndex < tBitWidth; bitIndex++)
- fFiltered[bitIndex] = lastFiltered[bitIndex];
-
- doFilter();
- }
-
- void emitTop(std::ostream& o, Indenter& i) {
- switch(tBitWidth) {
- case 8:
- o << i.indent() << "typedef uint8_t field_t;\n";
- break;
- case 16:
- o << i.indent() << "typedef uint16_t field_t;\n";
- break;
- case 32:
- o << i.indent() << "typedef uint32_t field_t;\n";
- break;
- case 64:
- o << i.indent() << "typedef uint64_t field_t;\n";
- break;
- default:
- assert(0 && "Unexpected instruction size!");
- }
-
- o << '\n';
-
- o << i.indent() << "field_t fieldFromInstruction(field_t insn, unsigned startBit, unsigned numBits)\n";
-
- o << i.indent() << "{\n";
- i.push();
- {
- o << i.indent() << "assert(startBit + numBits <= " << tBitWidth << " && \"Instruction field out of bounds!\");\n";
- o << '\n';
- o << i.indent() << "field_t fieldMask;\n";
- o << '\n';
- o << i.indent() << "if (numBits == " << tBitWidth << ")\n";
-
- i.push();
- {
- o << i.indent() << "fieldMask = (field_t)-1;\n";
- }
- i.pop();
-
- o << i.indent() << "else\n";
-
- i.push();
- {
- o << i.indent() << "fieldMask = ((1 << numBits) - 1) << startBit;\n";
- }
- i.pop();
-
- o << '\n';
- o << i.indent() << "return (insn & fieldMask) >> numBits;\n";
- }
- i.pop();
- o << i.indent() << "}\n";
-
- o << '\n';
-
- o << i.indent() << "uint16_t decodeInstruction(field_t insn) {\n";
-
- i.push();
- {
- // Emits code to decode the instructions.
- emit(o, i);
-
- o << '\n';
- o << i.indent() << "return 0;\n";
- }
- i.pop();
-
- o << i.indent() << "}" << std::endl;
- }
-
-protected:
- // Populates the insn given the uid.
- void insnWithID(insn_t& insn, unsigned insnID) const {
- BitsInit& bits = getBitsField(*fAllInstructions[insnID]->TheDef, "Inst");
-
- unsigned index;
-
- for (index = 0; index < tBitWidth; index++)
- insn[index] = bitFromBits(bits, index);
- }
-
- // Returns the record name.
- const std::string& nameWithID(unsigned insnID) const {
- return fAllInstructions[insnID]->TheDef->getName();
- }
-
- // 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.
- const bool fieldFromInsn(uint64_t& field, insn_t& insn, unsigned startBit,
- unsigned numBits) const {
- unsigned bitIndex;
-
- field = 0;
-
- for (bitIndex = 0; bitIndex < numBits; bitIndex++) {
- if (insn[startBit + bitIndex] == BIT_UNSET)
- return false;
-
- if (insn[startBit + bitIndex] == BIT_TRUE)
- field = field | (1 << bitIndex);
- }
-
- return true;
- }
-
- void dumpFilterArray(std::ostream& o, bitValue_t (&filter)[tBitWidth]) {
- unsigned bitIndex;
-
- for (bitIndex = tBitWidth; 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;
- }
- }
- }
-
- void dumpStack(std::ostream& o, const char* prefix) {
- FilterChooser* current = this;
-
- while (current) {
- o << prefix;
-
- dumpFilterArray(o, current->fFiltered);
-
- o << std::endl;
-
- current = current->fParent;
- }
- }
-
- Filter& bestFilter() {
- assert(fBestIndex != -1 && "fBestIndex not set");
- return fFilters[fBestIndex];
- }
-
- // States of our finite state machines.
- typedef enum {
- ATTR_NONE,
- ATTR_FILTERED,
- ATTR_ALL_SET,
- ATTR_ALL_UNSET,
- ATTR_MIXED
- } bitAttr_t;
-
- bool filterProcessor(bool allowMixed = true) {
- fFilters.clear();
- unsigned numInstructions = fInstructionsToFilter.size();
-
- assert(numInstructions && "Filter created with no instructions");
-
- // No further filtering is necessary.
- if (numInstructions == 1)
- return true;
-
- unsigned bitIndex, insnIndex;
-
- // We maintain tBitWidth 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[tBitWidth];
-
- // 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 < tBitWidth; ++bitIndex)
- if (fFiltered[bitIndex] == BIT_TRUE || fFiltered[bitIndex] == BIT_FALSE)
- bitAttrs[bitIndex] = ATTR_FILTERED;
- else
- bitAttrs[bitIndex] = ATTR_NONE;
-
- for (insnIndex = 0; insnIndex < numInstructions; ++insnIndex) {
- insn_t insn;
-
- insnWithID(insn, fInstructionsToFilter[insnIndex]);
-
- for (bitIndex = 0; bitIndex < tBitWidth; ++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 regionAttr = ATTR_NONE;
-
- unsigned startBit = 0;
-
- for (bitIndex = 0; bitIndex < tBitWidth; bitIndex++) {
- bitAttr_t bitAttr = bitAttrs[bitIndex];
-
- assert(bitAttr != ATTR_NONE && "Bit without attributes");
-
-#define SET_START \
- startBit = bitIndex;
-
-#define REPORT_REGION \
- if (regionAttr == ATTR_MIXED && allowMixed) \
- fFilters.push_back(Filter(*this, startBit, bitIndex - startBit, true));\
- else if (regionAttr == ATTR_ALL_SET && !allowMixed) \
- fFilters.push_back(Filter(*this, startBit, bitIndex - startBit, false));
-
- switch (regionAttr) {
- case ATTR_NONE:
- switch (bitAttr) {
- case ATTR_FILTERED:
- break;
- case ATTR_ALL_SET:
- SET_START
- regionAttr = ATTR_ALL_SET;
- break;
- case ATTR_ALL_UNSET:
- break;
- case ATTR_MIXED:
- SET_START
- regionAttr = ATTR_MIXED;
- break;
- default:
- assert(0 && "Unexpected bitAttr!");
- }
- break;
- case ATTR_ALL_SET:
- switch (bitAttr) {
- case ATTR_FILTERED:
- REPORT_REGION
- regionAttr = ATTR_NONE;
- break;
- case ATTR_ALL_SET:
- break;
- case ATTR_ALL_UNSET:
- REPORT_REGION
- regionAttr = ATTR_NONE;
- break;
- case ATTR_MIXED:
- REPORT_REGION
- SET_START
- regionAttr = ATTR_MIXED;
- break;
- default:
- assert(0 && "Unexpected bitAttr!");
- }
- break;
- case ATTR_MIXED:
- switch (bitAttr) {
- case ATTR_FILTERED:
- REPORT_REGION
- SET_START
- regionAttr = ATTR_NONE;
- break;
- case ATTR_ALL_SET:
- REPORT_REGION
- SET_START
- regionAttr = ATTR_ALL_SET;
- break;
- case ATTR_ALL_UNSET:
- REPORT_REGION
- regionAttr = 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 (regionAttr) {
- case ATTR_NONE:
- break;
- case ATTR_FILTERED:
- break;
- case ATTR_ALL_SET:
- REPORT_REGION
- break;
- case ATTR_ALL_UNSET:
- break;
- case ATTR_MIXED:
- REPORT_REGION
- break;
- }
-
-#undef SET_START
-#undef REPORT_REGION
-
- bool allAreUseless = true;
- fBestIndex = 0;
- unsigned bestUsefulness = 0;
- unsigned filterIndex;
- unsigned numFilters = fFilters.size();
-
- for (filterIndex = 0; filterIndex < numFilters; ++filterIndex) {
- unsigned usefulness = fFilters[filterIndex].usefulness();
-
- if (usefulness)
- allAreUseless = false;
-
- if (usefulness > bestUsefulness) {
- fBestIndex = filterIndex;
- bestUsefulness = usefulness;
- }
- }
-
- if (!allAreUseless) {
- bestFilter().recurse();
- }
-
- return !allAreUseless;
- } // end of 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 doFilter() {
- unsigned numInstructions = fInstructionsToFilter.size();
- assert(numInstructions && "FilterChooser created with no instructions");
-
- if (filterProcessor(false))
- return;
-
- if (filterProcessor(true))
- return;
-
- // If we come to here, the instruction decoding has failed.
- // Print out the instructions in the conflict set...
-
- fBestIndex = -1;
-
- std::cerr << "Conflict:" << std::endl;
-
- unsigned insnIndex;
-
- dumpStack(std::cerr, " ");
-
- for (insnIndex = 0; insnIndex < numInstructions; insnIndex++) {
- const std::string& name = nameWithID(fInstructionsToFilter[insnIndex]);
-
- std::cerr << " " << std::setw(15) << std::left << name << " ";
- dumpBits(std::cerr,
- getBitsField(*fAllInstructions[
- fInstructionsToFilter[insnIndex]]->TheDef,
- "Inst"));
- std::cerr << std::endl;
- }
- }
-
- // Emits code to decode our share of instructions. Returns true if the
- // emitted code causes a return, which occurs if we known how to decode
- // the instruction at this level or the instruction is not decodeable.
- bool emit(std::ostream& o, Indenter& i) {
- if (fInstructionsToFilter.size() == 1) {
- // There is only one instruction in the set, which is great!
- // Lets return the decoded instruction.
- o << i.indent() << "return " << fInstructionsToFilter[0] << "; // "
- << nameWithID(fInstructionsToFilter[0]) << '\n';
- return true;
- } else if (fBestIndex == -1) {
- if (fInstructionsToFilter.size() == 2) {
- // Resolve the known conflicts sets:
- //
- // 1. source registers are identical => VMOVD; otherwise => VORRd
- // 2. source registers are identical => VMOVQ; otherwise => VORRq
- const std::string& name1 = nameWithID(fInstructionsToFilter[0]);
- const std::string& name2 = nameWithID(fInstructionsToFilter[1]);
- if ((name1 == "VMOVD" && name2 == "VORRd") ||
- (name1 == "VMOVQ" && name2 == "VORRq")) {
- // Inserting the opening curly brace for this case block.
- i.pop();
- o << i.indent() << "{\n";
- i.push();
-
- o << i.indent() <<
- "field_t N = fieldFromInstruction(insn, 7, 1), M = fieldFromInstruction(insn, 5, 1);\n";
- o << i.indent() <<
- "field_t Vn = fieldFromInstruction(insn, 16, 4), Vm = fieldFromInstruction(insn, 0, 4);\n";
- o << i.indent() << "return (N == M && Vn == Vm) ? "
- << fInstructionsToFilter[0] << " /* " << name1 << " */ : "
- << fInstructionsToFilter[1] << " /* " << name2 << " */ ;\n";
-
- // Inserting the closing curly brace for this case block.
- i.pop();
- o << i.indent() << "}\n";
- i.push();
-
- return true;
- }
- // Otherwise, it does not belong to the known conflict sets.
- }
- // We don't know how to decode this instruction! Dump the conflict set!
- o << i.indent() << "return 0;" << " // Conflict set: ";
- for (int i = 0, N = fInstructionsToFilter.size(); i < N; ++i) {
- o << nameWithID(fInstructionsToFilter[i]);
- if (i < (N - 1))
- o << ", ";
- else
- o << '\n';
- }
- return true;
- } else {
- // Choose the best filter to do the decodings!
- bestFilter().emit(o, i);
- return false;
- }
- }
-};
-
-#pragma mark Backend
-
-class RISCDisassemblerEmitter::RISCDEBackend {
-public:
- RISCDEBackend(RISCDisassemblerEmitter& frontend) :
- fNumberedInstructions(),
- fTopLevelInstructions(),
- fFrontend(frontend),
- fTarget(),
- fFilterChooser(NULL)
- {
- populateInstructions();
-
- if (fTarget.getName() == "ARM") {
- fTargetName = TARGET_ARM;
- } else {
- std::cerr << "Target name " << fTarget.getName() << " not recognized" << std::endl;
- assert(0 && "Unknown target");
- }
- }
-
- ~RISCDEBackend() {
- if (fFilterChooser) {
- delete fFilterChooser;
- fFilterChooser = NULL;
- }
- }
-
- void getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>&
- numberedInstructions) {
- // Dig down to the proper namespace. Code shamelessly stolen from
- // InstrEnumEmitter.cpp
- std::string Namespace;
- CodeGenTarget::inst_iterator II, E;
-
- for (II = fTarget.inst_begin(), E = fTarget.inst_end(); II != E; ++II)
- if (II->second.Namespace != "TargetInstrInfo") {
- Namespace = II->second.Namespace;
- break;
- }
-
- assert(!Namespace.empty() && "No instructions defined.");
-
- fTarget.getInstructionsByEnumValue(numberedInstructions);
- }
-
- bool populateInstruction(const CodeGenInstruction& insn) {
- const Record& def = *insn.TheDef;
- const std::string& name = def.getName();
- uint8_t form = getByteField(def, "Form");
- BitsInit& bits = getBitsField(def, "Inst");
-
- if (fTargetName == TARGET_ARM) {
- if (form == ARM_FORM_PSEUDO)
- return false;
- if (fTargetName == TARGET_ARM && name[0] == 't')
- return false;
- if (name.find("CMPz") != std::string::npos ||
- name.find("CMNz") != std::string::npos)
- return false;
- if (name.find("BX_RET") != std::string::npos ||
- name.find("BXr9") != std::string::npos ||
- name.find("BLXr9") != std::string::npos)
- return false;
-
- //
- // The following special cases are for conflict resolutions.
- //
-
- // RSCSri and RSCSrs set the 's' bit, but are not predicated. We are
- // better off using the generic RSCri and RSCrs instructions.
- if (name == "RSCSri" || name == "RSCSrs") return false;
-
- // MOVCCr, MOVCCs, MOVCCi, FCYPScc, FCYPDcc, FNEGScc, and FNEGDcc are used
- // in the compiler to implement conditional moves. We can ignore them in
- // favor of their more generic versions of instructions.
- // See also SDNode *ARMDAGToDAGISel::Select(SDValue Op).
- if (name == "MOVCCr" || name == "MOVCCs" || name == "MOVCCi" ||
- name == "FCPYScc" || name == "FCPYDcc" ||
- name == "FNEGScc" || name == "FNEGDcc")
- return false;
-
- // Ignore the *_sfp instructions when decoding. They are used by the
- // compiler to implement scalar floating point operations using vector
- // operations in order to work around some performance issues.
- if (name.find("_sfp") != std::string::npos) return false;
-
- // LDM_RET is a special case of LDM (Load Multiple) where the registers
- // loaded include the PC, causing a branch to a loaded address. Ignore
- // the LDM_RET instruction when decoding.
- if (name == "LDM_RET") return false;
-
- // Bcc is in a more generic form than B. Ignore B when decoding.
- if (name == "B") return false;
-
- // Ignore the non-Darwin BL instructions and the TPsoft (TLS) instruction.
- if (name == "BL" || name == "BL_pred" || name == "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;
- }
-
- // Dumps the instruction encoding format.
- switch (fTargetName) {
- case TARGET_ARM:
- std::cerr << name << " " << stringWithARMForm((ARMForm)form);
- break;
- }
-
- std::cerr << " ";
-
- // Dumps the instruction encoding bits.
- dumpBits(std::cerr, bits);
-
- std::cerr << std::endl;
-
- // Dumps the list of operand info.
- for (unsigned i = 0, e = insn.OperandList.size(); i != e; ++i) {
- CodeGenInstruction::OperandInfo info = insn.OperandList[i];
- const std::string& operandName = info.Name;
- const Record& operandDef = *info.Rec;
-
- std::cerr << "\t" << operandName << " (" << operandDef.getName() << ") "
- << std::endl;
- }
-
- return true;
- }
-
- void populateInstructions() {
- getInstructionsByEnumValue(fNumberedInstructions);
-
- uint16_t numUIDs = fNumberedInstructions.size();
- uint16_t uid;
-
- const char* instClass;
-
- switch (fTargetName) {
- case TARGET_ARM:
- instClass = "InstARM";
- }
-
- for (uid = 0; uid < numUIDs; uid++) {
- // filter out intrinsics
- if (!fNumberedInstructions[uid]->TheDef->isSubClassOf(instClass))
- continue;
-
- if (populateInstruction(*fNumberedInstructions[uid]))
- fTopLevelInstructions.push_back(uid);
- }
-
- switch (fTargetName) {
- case TARGET_ARM:
- fFilterChooser = new FilterChooser<32>(fNumberedInstructions,
- fTopLevelInstructions);
- }
- }
-
- // Emits disassembler code for instruction decoding. This delegates to the
- // FilterChooser instance to do the heavy lifting.
- void emit(std::ostream& o) {
- Indenter i;
- std::string s;
- raw_string_ostream ro(s);
-
- switch (fTargetName) {
- case TARGET_ARM:
- fFrontend.EmitSourceFileHeader("ARM Disassembler", ro);
- }
-
- ro.flush();
- o << s;
-
- o << i.indent() << "#include <inttypes.h>\n";
- o << i.indent() << "#include <assert.h>\n";
- o << '\n';
-
- fFilterChooser->emitTop(o, i);
- }
-
-protected:
- std::vector<const CodeGenInstruction*> fNumberedInstructions;
- std::vector<unsigned> fTopLevelInstructions;
- RISCDisassemblerEmitter& fFrontend;
- CodeGenTarget fTarget;
- AbstractFilterChooser* fFilterChooser;
-
- enum {
- TARGET_ARM = 0
- } fTargetName;
-};
-
-#pragma mark Backend interface
-
-void RISCDisassemblerEmitter::initBackend()
-{
- fBackend = new RISCDEBackend(*this);
-}
-
-void RISCDisassemblerEmitter::run(raw_ostream& o)
-{
- std::ostringstream so;
- fBackend->emit(so);
- o << so.str();
-}
-
-void RISCDisassemblerEmitter::shutdownBackend()
-{
- delete fBackend;
-}