Use statically-initialised std::vectors for decoder data
Replace fixed size arrays with std::vector for static data used by the decoder,
and store const references rather than copies in each decoding node.
diff --git a/src/aarch64/decoder-aarch64.cc b/src/aarch64/decoder-aarch64.cc
index a84ce6a..a4e2989 100644
--- a/src/aarch64/decoder-aarch64.cc
+++ b/src/aarch64/decoder-aarch64.cc
@@ -70,7 +70,7 @@
// Add a node for each instruction form named, identified by having no '_'
// prefix on the node name.
const DecodeMapping& map = kDecodeMapping[i];
- for (unsigned j = 0; j < kMaxDecodeMappings; j++) {
+ for (unsigned j = 0; j < map.mapping.size(); j++) {
if ((map.mapping[j].handler != NULL) &&
(map.mapping[j].handler[0] != '_')) {
AddDecodeNode(DecodeNode(map.mapping[j].handler, this));
@@ -142,30 +142,9 @@
}
}
-void DecodeNode::SetSampledBits(const uint8_t* bits, int bit_count) {
- VIXL_ASSERT(!IsCompiled());
-
- sampled_bits_.resize(bit_count);
- for (int i = 0; i < bit_count; i++) {
- sampled_bits_[i] = bits[i];
- }
-}
-
-std::vector<uint8_t> DecodeNode::GetSampledBits() const {
- return sampled_bits_;
-}
-
-size_t DecodeNode::GetSampledBitsCount() const { return sampled_bits_.size(); }
-
-void DecodeNode::AddPatterns(const DecodePattern* patterns) {
- VIXL_ASSERT(!IsCompiled());
- for (unsigned i = 0; i < kMaxDecodeMappings; i++) {
- // Empty string indicates end of patterns.
- if (patterns[i].pattern == 0) break;
- VIXL_ASSERT(GetPatternLength(patterns[i].pattern) == GetSampledBitsCount());
- pattern_table_.push_back(patterns[i]);
- }
-}
+// Initialise empty vectors for sampled bits and pattern table.
+const std::vector<uint8_t> DecodeNode::kEmptySampledBits;
+const std::vector<DecodePattern> DecodeNode::kEmptyPatternTable;
void DecodeNode::CompileNodeForBits(Decoder* decoder,
std::string name,
@@ -434,7 +413,7 @@
// value test.
uint32_t single_decode_mask = 0;
uint32_t single_decode_value = 0;
- std::vector<uint8_t> bits = GetSampledBits();
+ const std::vector<uint8_t>& bits = GetSampledBits();
// Construct the instruction mask and value from the pattern.
VIXL_ASSERT(bits.size() == GetPatternLength(pattern_table_[0].pattern));
@@ -454,9 +433,7 @@
// Set DecodeNode for when the instruction after masking doesn't match the
// value.
- const char* doesnt_match_handler =
- (table_size == 1) ? "unallocated" : pattern_table_[1].handler;
- CompileNodeForBits(decoder, doesnt_match_handler, 0);
+ CompileNodeForBits(decoder, "unallocated", 0);
// Set DecodeNode for when it does match.
CompileNodeForBits(decoder, pattern_table_[0].handler, 1);
@@ -545,7 +522,7 @@
}
uint32_t DecodeNode::GenerateOrderedPattern(uint32_t pattern) const {
- std::vector<uint8_t> sampled_bits = GetSampledBits();
+ const std::vector<uint8_t>& sampled_bits = GetSampledBits();
uint64_t temp = 0xffffffffffffffff;
// Place symbols into the field of set bits. Symbols are two bits wide and
@@ -578,10 +555,9 @@
}
uint32_t DecodeNode::GenerateSampledBitsMask() const {
- std::vector<uint8_t> sampled_bits = GetSampledBits();
uint32_t mask = 0;
- for (size_t i = 0; i < sampled_bits.size(); i++) {
- mask |= 1 << sampled_bits[i];
+ for (int bit : GetSampledBits()) {
+ mask |= 1 << bit;
}
return mask;
}
diff --git a/src/aarch64/decoder-aarch64.h b/src/aarch64/decoder-aarch64.h
index 99fb644..22c66e8 100644
--- a/src/aarch64/decoder-aarch64.h
+++ b/src/aarch64/decoder-aarch64.h
@@ -394,8 +394,6 @@
std::map<std::string, DecodeNode> decode_nodes_;
};
-const int kMaxDecodeSampledBits = 24;
-const int kMaxDecodeMappings = 280;
typedef void (Decoder::*DecodeFnPtr)(const Instruction*);
typedef uint32_t (Instruction::*BitExtractFn)(void) const;
@@ -425,8 +423,8 @@
// sampled bits match to the corresponding name of a node.
struct DecodeMapping {
const char* name;
- const uint8_t sampled_bits[kMaxDecodeSampledBits];
- const DecodePattern mapping[kMaxDecodeMappings];
+ const std::vector<uint8_t> sampled_bits;
+ const std::vector<DecodePattern> mapping;
};
// For speed, before nodes can be used for decoding instructions, they must
@@ -512,29 +510,35 @@
class DecodeNode {
public:
// Default constructor needed for map initialisation.
- DecodeNode() : compiled_node_(NULL) {}
+ DecodeNode()
+ : sampled_bits_(DecodeNode::kEmptySampledBits),
+ pattern_table_(DecodeNode::kEmptyPatternTable),
+ compiled_node_(NULL) {}
// Constructor for DecodeNode wrappers around visitor functions. These are
// marked as "compiled", as there is no decoding left to do.
explicit DecodeNode(const std::string& iname, Decoder* decoder)
: name_(iname),
+ sampled_bits_(DecodeNode::kEmptySampledBits),
instruction_name_(iname),
+ pattern_table_(DecodeNode::kEmptyPatternTable),
decoder_(decoder),
compiled_node_(NULL) {}
// Constructor for DecodeNodes that map bit patterns to other DecodeNodes.
explicit DecodeNode(const DecodeMapping& map, Decoder* decoder = NULL)
: name_(map.name),
+ sampled_bits_(map.sampled_bits),
instruction_name_("node"),
+ pattern_table_(map.mapping),
decoder_(decoder),
compiled_node_(NULL) {
- // The length of the bit string in the first mapping determines the number
- // of sampled bits. When adding patterns later, we assert that all mappings
- // sample the same number of bits.
- size_t bit_count = GetPatternLength(map.mapping[0].pattern);
- VIXL_CHECK(bit_count <= 32);
- SetSampledBits(map.sampled_bits, static_cast<int>(bit_count));
- AddPatterns(map.mapping);
+ // With the current two bits per symbol encoding scheme, the maximum pattern
+ // length is (32 - 2) / 2 = 15 bits.
+ VIXL_CHECK(GetPatternLength(map.mapping[0].pattern) <= 15);
+ for (const DecodePattern& p : map.mapping) {
+ VIXL_CHECK(GetPatternLength(p.pattern) == map.sampled_bits.size());
+ }
}
~DecodeNode() {
@@ -544,17 +548,11 @@
}
}
- // Set the bits sampled from the instruction by this node.
- void SetSampledBits(const uint8_t* bits, int bit_count);
-
// Get the bits sampled from the instruction by this node.
- std::vector<uint8_t> GetSampledBits() const;
+ const std::vector<uint8_t>& GetSampledBits() const { return sampled_bits_; }
// Get the number of bits sampled from the instruction by this node.
- size_t GetSampledBitsCount() const;
-
- // Add patterns to this node's internal pattern table.
- void AddPatterns(const DecodePattern* patterns);
+ size_t GetSampledBitsCount() const { return sampled_bits_.size(); }
// A leaf node is a DecodeNode that wraps the visitor function for the
// identified instruction class.
@@ -671,14 +669,16 @@
// Vector of bits sampled from an instruction to determine which node to look
// up next in the decode process.
- std::vector<uint8_t> sampled_bits_;
+ const std::vector<uint8_t>& sampled_bits_;
+ static const std::vector<uint8_t> kEmptySampledBits;
// For leaf nodes, this is the name of the instruction form that the node
// represents. For other nodes, this is always set to "node".
std::string instruction_name_;
// Source mapping from bit pattern to name of next decode stage.
- std::vector<DecodePattern> pattern_table_;
+ const std::vector<DecodePattern>& pattern_table_;
+ static const std::vector<DecodePattern> kEmptyPatternTable;
// Pointer to the decoder containing this node, used to call its visitor
// function for leaf nodes.