1 // Copyright 2019, VIXL authors
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 //   * Redistributions of source code must retain the above copyright notice,
8 //     this list of conditions and the following disclaimer.
9 //   * Redistributions in binary form must reproduce the above copyright notice,
10 //     this list of conditions and the following disclaimer in the documentation
11 //     and/or other materials provided with the distribution.
12 //   * Neither the name of ARM Limited nor the names of its contributors may be
13 //     used to endorse or promote products derived from this software without
14 //     specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 #include <string>
28 
29 #include "../globals-vixl.h"
30 #include "../utils-vixl.h"
31 
32 #include "decoder-aarch64.h"
33 #include "decoder-constants-aarch64.h"
34 
35 namespace vixl {
36 namespace aarch64 {
37 
Decode(const Instruction * instr)38 void Decoder::Decode(const Instruction* instr) {
39   std::list<DecoderVisitor*>::iterator it;
40   for (it = visitors_.begin(); it != visitors_.end(); it++) {
41     VIXL_ASSERT((*it)->IsConstVisitor());
42   }
43   VIXL_ASSERT(compiled_decoder_root_ != NULL);
44   compiled_decoder_root_->Decode(instr);
45 }
46 
Decode(Instruction * instr)47 void Decoder::Decode(Instruction* instr) {
48   compiled_decoder_root_->Decode(const_cast<const Instruction*>(instr));
49 }
50 
AddDecodeNode(const DecodeNode & node)51 void Decoder::AddDecodeNode(const DecodeNode& node) {
52   decode_nodes_.insert(std::make_pair(node.GetName(), node));
53 }
54 
GetDecodeNode(std::string name)55 DecodeNode* Decoder::GetDecodeNode(std::string name) {
56   if (decode_nodes_.count(name) != 1) {
57     std::string msg = "Can't find decode node " + name + ".\n";
58     VIXL_ABORT_WITH_MSG(msg.c_str());
59   }
60   return &decode_nodes_[name];
61 }
62 
ConstructDecodeGraph()63 void Decoder::ConstructDecodeGraph() {
64   // Add all of the decoding nodes to the Decoder.
65   for (unsigned i = 0; i < ArrayLength(kDecodeMapping); i++) {
66     AddDecodeNode(DecodeNode(kDecodeMapping[i], this));
67   }
68 
69   // Add the visitor function wrapping nodes to the Decoder.
70   for (unsigned i = 0; i < ArrayLength(kVisitorNodes); i++) {
71     AddDecodeNode(DecodeNode(kVisitorNodes[i], this));
72   }
73 
74   // Compile the graph from the root.
75   compiled_decoder_root_ = GetDecodeNode("Root")->Compile(this);
76 }
77 
AppendVisitor(DecoderVisitor * new_visitor)78 void Decoder::AppendVisitor(DecoderVisitor* new_visitor) {
79   visitors_.push_back(new_visitor);
80 }
81 
82 
PrependVisitor(DecoderVisitor * new_visitor)83 void Decoder::PrependVisitor(DecoderVisitor* new_visitor) {
84   visitors_.push_front(new_visitor);
85 }
86 
87 
InsertVisitorBefore(DecoderVisitor * new_visitor,DecoderVisitor * registered_visitor)88 void Decoder::InsertVisitorBefore(DecoderVisitor* new_visitor,
89                                   DecoderVisitor* registered_visitor) {
90   std::list<DecoderVisitor*>::iterator it;
91   for (it = visitors_.begin(); it != visitors_.end(); it++) {
92     if (*it == registered_visitor) {
93       visitors_.insert(it, new_visitor);
94       return;
95     }
96   }
97   // We reached the end of the list. The last element must be
98   // registered_visitor.
99   VIXL_ASSERT(*it == registered_visitor);
100   visitors_.insert(it, new_visitor);
101 }
102 
103 
InsertVisitorAfter(DecoderVisitor * new_visitor,DecoderVisitor * registered_visitor)104 void Decoder::InsertVisitorAfter(DecoderVisitor* new_visitor,
105                                  DecoderVisitor* registered_visitor) {
106   std::list<DecoderVisitor*>::iterator it;
107   for (it = visitors_.begin(); it != visitors_.end(); it++) {
108     if (*it == registered_visitor) {
109       it++;
110       visitors_.insert(it, new_visitor);
111       return;
112     }
113   }
114   // We reached the end of the list. The last element must be
115   // registered_visitor.
116   VIXL_ASSERT(*it == registered_visitor);
117   visitors_.push_back(new_visitor);
118 }
119 
120 
RemoveVisitor(DecoderVisitor * visitor)121 void Decoder::RemoveVisitor(DecoderVisitor* visitor) {
122   visitors_.remove(visitor);
123 }
124 
125 #define DEFINE_VISITOR_CALLERS(A)                               \
126   void Decoder::Visit##A(const Instruction* instr) {            \
127     VIXL_ASSERT(((A##FMask == 0) && (A##Fixed == 0)) ||         \
128                 (instr->Mask(A##FMask) == A##Fixed));           \
129     std::list<DecoderVisitor*>::iterator it;                    \
130     for (it = visitors_.begin(); it != visitors_.end(); it++) { \
131       (*it)->Visit##A(instr);                                   \
132     }                                                           \
133   }
VISITOR_LIST(DEFINE_VISITOR_CALLERS)134 VISITOR_LIST(DEFINE_VISITOR_CALLERS)
135 #undef DEFINE_VISITOR_CALLERS
136 
137 void DecodeNode::SetSampledBits(const uint8_t* bits, int bit_count) {
138   VIXL_ASSERT(!IsCompiled());
139 
140   sampled_bits_.resize(bit_count);
141   for (int i = 0; i < bit_count; i++) {
142     sampled_bits_[i] = bits[i];
143   }
144 }
145 
GetSampledBits() const146 std::vector<uint8_t> DecodeNode::GetSampledBits() const {
147   return sampled_bits_;
148 }
149 
GetSampledBitsCount() const150 size_t DecodeNode::GetSampledBitsCount() const { return sampled_bits_.size(); }
151 
AddPatterns(const DecodePattern * patterns)152 void DecodeNode::AddPatterns(const DecodePattern* patterns) {
153   VIXL_ASSERT(!IsCompiled());
154   for (unsigned i = 0; i < kMaxDecodeMappings; i++) {
155     // Empty string indicates end of patterns.
156     if (patterns[i].pattern == NULL) break;
157     VIXL_ASSERT((strlen(patterns[i].pattern) == GetSampledBitsCount()) ||
158                 (strcmp(patterns[i].pattern, "otherwise") == 0));
159     pattern_table_.push_back(patterns[i]);
160   }
161 }
162 
CompileNodeForBits(Decoder * decoder,std::string name,uint32_t bits)163 void DecodeNode::CompileNodeForBits(Decoder* decoder,
164                                     std::string name,
165                                     uint32_t bits) {
166   DecodeNode* n = decoder->GetDecodeNode(name);
167   VIXL_ASSERT(n != NULL);
168   if (!n->IsCompiled()) {
169     n->Compile(decoder);
170   }
171   VIXL_ASSERT(n->IsCompiled());
172   compiled_node_->SetNodeForBits(bits, n->GetCompiledNode());
173 }
174 
GetBitExtractFunction(uint32_t mask)175 BitExtractFn DecodeNode::GetBitExtractFunction(uint32_t mask) {
176   // Instantiate a templated bit extraction function for every pattern we
177   // might encounter. If the assertion in the default clause is reached, add a
178   // new instantiation below using the information in the failure message.
179   BitExtractFn bit_extract_fn = NULL;
180   switch (mask) {
181 #define INSTANTIATE_TEMPLATE(M)                    \
182   case M:                                          \
183     bit_extract_fn = &Instruction::ExtractBits<M>; \
184     break;
185     INSTANTIATE_TEMPLATE(0x000001e0);
186     INSTANTIATE_TEMPLATE(0x00000400);
187     INSTANTIATE_TEMPLATE(0x00000800);
188     INSTANTIATE_TEMPLATE(0x00000c00);
189     INSTANTIATE_TEMPLATE(0x00001000);
190     INSTANTIATE_TEMPLATE(0x00001800);
191     INSTANTIATE_TEMPLATE(0x00001c00);
192     INSTANTIATE_TEMPLATE(0x00004000);
193     INSTANTIATE_TEMPLATE(0x00008000);
194     INSTANTIATE_TEMPLATE(0x0000f000);
195     INSTANTIATE_TEMPLATE(0x0000fc00);
196     INSTANTIATE_TEMPLATE(0x00060010);
197     INSTANTIATE_TEMPLATE(0x00093e00);
198     INSTANTIATE_TEMPLATE(0x000c1000);
199     INSTANTIATE_TEMPLATE(0x00100000);
200     INSTANTIATE_TEMPLATE(0x00101800);
201     INSTANTIATE_TEMPLATE(0x00140000);
202     INSTANTIATE_TEMPLATE(0x00180000);
203     INSTANTIATE_TEMPLATE(0x00181000);
204     INSTANTIATE_TEMPLATE(0x00190000);
205     INSTANTIATE_TEMPLATE(0x00191400);
206     INSTANTIATE_TEMPLATE(0x001c0000);
207     INSTANTIATE_TEMPLATE(0x001c1800);
208     INSTANTIATE_TEMPLATE(0x001f0000);
209     INSTANTIATE_TEMPLATE(0x0020fc00);
210     INSTANTIATE_TEMPLATE(0x0038f000);
211     INSTANTIATE_TEMPLATE(0x00400000);
212     INSTANTIATE_TEMPLATE(0x00400010);
213     INSTANTIATE_TEMPLATE(0x0040f000);
214     INSTANTIATE_TEMPLATE(0x00500000);
215     INSTANTIATE_TEMPLATE(0x00800000);
216     INSTANTIATE_TEMPLATE(0x00800010);
217     INSTANTIATE_TEMPLATE(0x00801800);
218     INSTANTIATE_TEMPLATE(0x009f0000);
219     INSTANTIATE_TEMPLATE(0x00c00000);
220     INSTANTIATE_TEMPLATE(0x00c00010);
221     INSTANTIATE_TEMPLATE(0x00cf8000);
222     INSTANTIATE_TEMPLATE(0x00db0000);
223     INSTANTIATE_TEMPLATE(0x00dc0000);
224     INSTANTIATE_TEMPLATE(0x00e00003);
225     INSTANTIATE_TEMPLATE(0x00f80400);
226     INSTANTIATE_TEMPLATE(0x01e00000);
227     INSTANTIATE_TEMPLATE(0x03800000);
228     INSTANTIATE_TEMPLATE(0x04c0f000);
229     INSTANTIATE_TEMPLATE(0x10800400);
230     INSTANTIATE_TEMPLATE(0x1e000000);
231     INSTANTIATE_TEMPLATE(0x20000000);
232     INSTANTIATE_TEMPLATE(0x20000410);
233     INSTANTIATE_TEMPLATE(0x20007000);
234     INSTANTIATE_TEMPLATE(0x20007800);
235     INSTANTIATE_TEMPLATE(0x2000f000);
236     INSTANTIATE_TEMPLATE(0x2000f800);
237     INSTANTIATE_TEMPLATE(0x201e0c00);
238     INSTANTIATE_TEMPLATE(0x20803800);
239     INSTANTIATE_TEMPLATE(0x20c0cc00);
240     INSTANTIATE_TEMPLATE(0x20c0f000);
241     INSTANTIATE_TEMPLATE(0x20c0f800);
242     INSTANTIATE_TEMPLATE(0x20c1f000);
243     INSTANTIATE_TEMPLATE(0x51e00000);
244     INSTANTIATE_TEMPLATE(0x60007800);
245     INSTANTIATE_TEMPLATE(0x6000f800);
246     INSTANTIATE_TEMPLATE(0x601e0000);
247     INSTANTIATE_TEMPLATE(0x80007c00);
248     INSTANTIATE_TEMPLATE(0x80017c00);
249     INSTANTIATE_TEMPLATE(0x80408000);
250     INSTANTIATE_TEMPLATE(0x80a07c00);
251     INSTANTIATE_TEMPLATE(0x80df0000);
252     INSTANTIATE_TEMPLATE(0x80e08000);
253     INSTANTIATE_TEMPLATE(0xa0c00000);
254     INSTANTIATE_TEMPLATE(0xb5a00000);
255     INSTANTIATE_TEMPLATE(0xc0c00c00);
256     INSTANTIATE_TEMPLATE(0xc4400000);
257     INSTANTIATE_TEMPLATE(0xc4c00000);
258     INSTANTIATE_TEMPLATE(0xe0400000);
259     INSTANTIATE_TEMPLATE(0xe120e000);
260     INSTANTIATE_TEMPLATE(0xe3c00000);
261     INSTANTIATE_TEMPLATE(0xf1200000);
262 #undef INSTANTIATE_TEMPLATE
263     default:
264       printf("Node %s: No template instantiated for extracting 0x%08x.\n",
265              GetName().c_str(),
266              GenerateSampledBitsMask());
267       printf("Add one in %s above line %d:\n", __FILE__, __LINE__);
268       printf("  INSTANTIATE_TEMPLATE(0x%08x);\n", GenerateSampledBitsMask());
269       VIXL_UNREACHABLE();
270   }
271   return bit_extract_fn;
272 }
273 
GetBitExtractFunction(uint32_t mask,uint32_t value)274 BitExtractFn DecodeNode::GetBitExtractFunction(uint32_t mask, uint32_t value) {
275   // Instantiate a templated bit extraction function for every pattern we
276   // might encounter. If the assertion in the following check fails, add a
277   // new instantiation below using the information in the failure message.
278   bool instantiated = false;
279   BitExtractFn bit_extract_fn = NULL;
280 #define INSTANTIATE_TEMPLATE(M, V)                      \
281   if ((mask == M) && (value == V)) {                    \
282     bit_extract_fn = &Instruction::IsMaskedValue<M, V>; \
283     instantiated = true;                                \
284   }
285   INSTANTIATE_TEMPLATE(0x0000001c, 0x00000000);
286   INSTANTIATE_TEMPLATE(0x00000210, 0x00000000);
287   INSTANTIATE_TEMPLATE(0x000003c0, 0x00000000);
288   INSTANTIATE_TEMPLATE(0x00001c00, 0x00000000);
289   INSTANTIATE_TEMPLATE(0x00001c0f, 0x00000000);
290   INSTANTIATE_TEMPLATE(0x00003000, 0x00000000);
291   INSTANTIATE_TEMPLATE(0x00007800, 0x00000000);
292   INSTANTIATE_TEMPLATE(0x0000e000, 0x0000a000);
293   INSTANTIATE_TEMPLATE(0x0000f000, 0x00000000);
294   INSTANTIATE_TEMPLATE(0x00030400, 0x00000000);
295   INSTANTIATE_TEMPLATE(0x0003801f, 0x0000000d);
296   INSTANTIATE_TEMPLATE(0x00060210, 0x00000000);
297   INSTANTIATE_TEMPLATE(0x00060810, 0x00000000);
298   INSTANTIATE_TEMPLATE(0x00060a10, 0x00000000);
299   INSTANTIATE_TEMPLATE(0x00060bf0, 0x00000000);
300   INSTANTIATE_TEMPLATE(0x00061e10, 0x00000000);
301   INSTANTIATE_TEMPLATE(0x00061e10, 0x00000400);
302   INSTANTIATE_TEMPLATE(0x00070200, 0x00000000);
303   INSTANTIATE_TEMPLATE(0x000b1e10, 0x00000000);
304   INSTANTIATE_TEMPLATE(0x000f0000, 0x00000000);
305   INSTANTIATE_TEMPLATE(0x00130e1f, 0x00000000);
306   INSTANTIATE_TEMPLATE(0x00130fff, 0x00000000);
307   INSTANTIATE_TEMPLATE(0x00180000, 0x00000000);
308   INSTANTIATE_TEMPLATE(0x00180000, 0x00100000);
309   INSTANTIATE_TEMPLATE(0x001e0000, 0x00000000);
310   INSTANTIATE_TEMPLATE(0x001f0000, 0x00000000);
311   INSTANTIATE_TEMPLATE(0x001f0000, 0x001f0000);
312   INSTANTIATE_TEMPLATE(0x0038e000, 0x00000000);
313   INSTANTIATE_TEMPLATE(0x0039e000, 0x00002000);
314   INSTANTIATE_TEMPLATE(0x003ae000, 0x00002000);
315   INSTANTIATE_TEMPLATE(0x003ce000, 0x00042000);
316   INSTANTIATE_TEMPLATE(0x005f0000, 0x001f0000);
317   INSTANTIATE_TEMPLATE(0x00780000, 0x00000000);
318   INSTANTIATE_TEMPLATE(0x00870210, 0x00000000);
319   INSTANTIATE_TEMPLATE(0x00c00000, 0x00000000);
320   INSTANTIATE_TEMPLATE(0x00c00000, 0x00800000);
321   INSTANTIATE_TEMPLATE(0x00c00000, 0x00c00000);
322   INSTANTIATE_TEMPLATE(0x00c00010, 0x00800000);
323   INSTANTIATE_TEMPLATE(0x00ca1e10, 0x00000000);
324   INSTANTIATE_TEMPLATE(0x01000010, 0x00000000);
325   INSTANTIATE_TEMPLATE(0x20000800, 0x00000000);
326   INSTANTIATE_TEMPLATE(0x20008000, 0x00000000);
327   INSTANTIATE_TEMPLATE(0x20040000, 0x00000000);
328   INSTANTIATE_TEMPLATE(0x201e8000, 0x00000000);
329   INSTANTIATE_TEMPLATE(0x60000000, 0x00000000);
330   INSTANTIATE_TEMPLATE(0x60000000, 0x20000000);
331   INSTANTIATE_TEMPLATE(0x60000000, 0x60000000);
332   INSTANTIATE_TEMPLATE(0x60200000, 0x00000000);
333   INSTANTIATE_TEMPLATE(0x80008000, 0x00000000);
334   INSTANTIATE_TEMPLATE(0x80008000, 0x00008000);
335   INSTANTIATE_TEMPLATE(0x80400000, 0x00400000);
336   INSTANTIATE_TEMPLATE(0xa00003e0, 0x00000000);
337   INSTANTIATE_TEMPLATE(0xa000c007, 0x00000000);
338   INSTANTIATE_TEMPLATE(0xa0100000, 0x00000000);
339   INSTANTIATE_TEMPLATE(0xc4000000, 0xc0000000);
340   INSTANTIATE_TEMPLATE(0xc4000000, 0xc4000000);
341   INSTANTIATE_TEMPLATE(0xe0000010, 0xa0000000);
342   INSTANTIATE_TEMPLATE(0xe01c0000, 0x20000000);
343   INSTANTIATE_TEMPLATE(0xe1ff0000, 0x00000000);
344 #undef INSTANTIATE_TEMPLATE
345 
346   if (!instantiated) {
347     printf(
348         "Node %s: no template instantiated for mask 0x%08x, value = "
349         "0x%08x.\n",
350         GetName().c_str(),
351         mask,
352         value);
353     printf("Add one in %s above line %d:\n", __FILE__, __LINE__);
354     printf("  INSTANTIATE_TEMPLATE(0x%08x, 0x%08x);\n", mask, value);
355     VIXL_UNREACHABLE();
356   }
357   return bit_extract_fn;
358 }
359 
TryCompileOptimisedDecodeTable(Decoder * decoder)360 bool DecodeNode::TryCompileOptimisedDecodeTable(Decoder* decoder) {
361   // EitherOr optimisation: if there are only one or two patterns in the table,
362   // try to optimise the node to exploit that.
363   size_t table_size = pattern_table_.size();
364   if ((table_size <= 2) && (GetSampledBitsCount() > 1)) {
365     // TODO: support 'x' in this optimisation by dropping the sampled bit
366     // positions before making the mask/value.
367     if ((strchr(pattern_table_[0].pattern, 'x') == NULL) &&
368         ((table_size == 1) ||
369          (strcmp(pattern_table_[1].pattern, "otherwise") == 0))) {
370       // A pattern table consisting of a fixed pattern with no x's, and an
371       // "otherwise" or absent case. Optimise this into an instruction mask and
372       // value test.
373       uint32_t single_decode_mask = 0;
374       uint32_t single_decode_value = 0;
375       std::vector<uint8_t> bits = GetSampledBits();
376 
377       // Construct the instruction mask and value from the pattern.
378       VIXL_ASSERT(bits.size() == strlen(pattern_table_[0].pattern));
379       for (size_t i = 0; i < bits.size(); i++) {
380         single_decode_mask |= 1U << bits[i];
381         if (pattern_table_[0].pattern[i] == '1') {
382           single_decode_value |= 1U << bits[i];
383         }
384       }
385       BitExtractFn bit_extract_fn =
386           GetBitExtractFunction(single_decode_mask, single_decode_value);
387 
388       // Create a compiled node that contains a two entry table for the
389       // either/or cases.
390       CreateCompiledNode(bit_extract_fn, 2);
391 
392       // Set DecodeNode for when the instruction after masking doesn't match the
393       // value.
394       const char* doesnt_match_handler =
395           (table_size == 1) ? "VisitUnallocated" : pattern_table_[1].handler;
396       CompileNodeForBits(decoder, doesnt_match_handler, 0);
397 
398       // Set DecodeNode for when it does match.
399       CompileNodeForBits(decoder, pattern_table_[0].handler, 1);
400 
401       return true;
402     }
403   }
404   return false;
405 }
406 
Compile(Decoder * decoder)407 CompiledDecodeNode* DecodeNode::Compile(Decoder* decoder) {
408   if (IsLeafNode()) {
409     // A leaf node is a simple wrapper around a visitor function, with no
410     // instruction decoding to do.
411     CreateVisitorNode();
412   } else if (!TryCompileOptimisedDecodeTable(decoder)) {
413     // The "otherwise" node is the default next node if no pattern matches.
414     std::string otherwise = "VisitUnallocated";
415 
416     // For each pattern in pattern_table_, create an entry in matches that
417     // has a corresponding mask and value for the pattern.
418     std::vector<MaskValuePair> matches;
419     for (size_t i = 0; i < pattern_table_.size(); i++) {
420       if (strcmp(pattern_table_[i].pattern, "otherwise") == 0) {
421         // "otherwise" must be the last pattern in the list, otherwise the
422         // indices won't match for pattern_table_ and matches.
423         VIXL_ASSERT(i == pattern_table_.size() - 1);
424         otherwise = pattern_table_[i].handler;
425       } else {
426         matches.push_back(GenerateMaskValuePair(
427             GenerateOrderedPattern(pattern_table_[i].pattern)));
428       }
429     }
430 
431     BitExtractFn bit_extract_fn =
432         GetBitExtractFunction(GenerateSampledBitsMask());
433 
434     // Create a compiled node that contains a table with an entry for every bit
435     // pattern.
436     CreateCompiledNode(bit_extract_fn, 1U << GetSampledBitsCount());
437     VIXL_ASSERT(compiled_node_ != NULL);
438 
439     // When we find a pattern matches the representation, set the node's decode
440     // function for that representation to the corresponding function.
441     for (uint32_t bits = 0; bits < (1U << GetSampledBitsCount()); bits++) {
442       for (size_t i = 0; i < matches.size(); i++) {
443         if ((bits & matches[i].first) == matches[i].second) {
444           // Only one instruction class should match for each value of bits, so
445           // if we get here, the node pointed to should still be unallocated.
446           VIXL_ASSERT(compiled_node_->GetNodeForBits(bits) == NULL);
447           CompileNodeForBits(decoder, pattern_table_[i].handler, bits);
448           break;
449         }
450       }
451 
452       // If the decode_table_ entry for these bits is still NULL, the
453       // instruction must be handled by the "otherwise" case, which by default
454       // is the Unallocated visitor.
455       if (compiled_node_->GetNodeForBits(bits) == NULL) {
456         CompileNodeForBits(decoder, otherwise, bits);
457       }
458     }
459   }
460 
461   VIXL_ASSERT(compiled_node_ != NULL);
462   return compiled_node_;
463 }
464 
Decode(const Instruction * instr) const465 void CompiledDecodeNode::Decode(const Instruction* instr) const {
466   if (IsLeafNode()) {
467     // If this node is a leaf, call the registered visitor function.
468     VIXL_ASSERT(decoder_ != NULL);
469     (decoder_->*visitor_fn_)(instr);
470   } else {
471     // Otherwise, using the sampled bit extractor for this node, look up the
472     // next node in the decode tree, and call its Decode method.
473     VIXL_ASSERT(bit_extract_fn_ != NULL);
474     VIXL_ASSERT((instr->*bit_extract_fn_)() < decode_table_size_);
475     VIXL_ASSERT(decode_table_[(instr->*bit_extract_fn_)()] != NULL);
476     decode_table_[(instr->*bit_extract_fn_)()]->Decode(instr);
477   }
478 }
479 
GenerateMaskValuePair(std::string pattern) const480 DecodeNode::MaskValuePair DecodeNode::GenerateMaskValuePair(
481     std::string pattern) const {
482   uint32_t mask = 0, value = 0;
483   for (size_t i = 0; i < pattern.size(); i++) {
484     mask |= ((pattern[i] == 'x') ? 0 : 1) << i;
485     value |= ((pattern[i] == '1') ? 1 : 0) << i;
486   }
487   return std::make_pair(mask, value);
488 }
489 
GenerateOrderedPattern(std::string pattern) const490 std::string DecodeNode::GenerateOrderedPattern(std::string pattern) const {
491   std::vector<uint8_t> sampled_bits = GetSampledBits();
492   // Construct a temporary 32-character string containing '_', then at each
493   // sampled bit position, set the corresponding pattern character.
494   std::string temp(32, '_');
495   for (size_t i = 0; i < sampled_bits.size(); i++) {
496     temp[sampled_bits[i]] = pattern[i];
497   }
498 
499   // Iterate through the temporary string, filtering out the non-'_' characters
500   // into a new ordered pattern result string.
501   std::string result;
502   for (size_t i = 0; i < temp.size(); i++) {
503     if (temp[i] != '_') {
504       result.push_back(temp[i]);
505     }
506   }
507   VIXL_ASSERT(result.size() == sampled_bits.size());
508   return result;
509 }
510 
GenerateSampledBitsMask() const511 uint32_t DecodeNode::GenerateSampledBitsMask() const {
512   std::vector<uint8_t> sampled_bits = GetSampledBits();
513   uint32_t mask = 0;
514   for (size_t i = 0; i < sampled_bits.size(); i++) {
515     mask |= 1 << sampled_bits[i];
516   }
517   return mask;
518 }
519 
520 }  // namespace aarch64
521 }  // namespace vixl
522