xref: /aosp_15_r20/external/vixl/src/aarch64/decoder-aarch64.cc (revision f5c631da2f1efdd72b5fd1e20510e4042af13d77)
1*f5c631daSSadaf Ebrahimi // Copyright 2019, VIXL authors
2*f5c631daSSadaf Ebrahimi // All rights reserved.
3*f5c631daSSadaf Ebrahimi //
4*f5c631daSSadaf Ebrahimi // Redistribution and use in source and binary forms, with or without
5*f5c631daSSadaf Ebrahimi // modification, are permitted provided that the following conditions are met:
6*f5c631daSSadaf Ebrahimi //
7*f5c631daSSadaf Ebrahimi //   * Redistributions of source code must retain the above copyright notice,
8*f5c631daSSadaf Ebrahimi //     this list of conditions and the following disclaimer.
9*f5c631daSSadaf Ebrahimi //   * Redistributions in binary form must reproduce the above copyright notice,
10*f5c631daSSadaf Ebrahimi //     this list of conditions and the following disclaimer in the documentation
11*f5c631daSSadaf Ebrahimi //     and/or other materials provided with the distribution.
12*f5c631daSSadaf Ebrahimi //   * Neither the name of ARM Limited nor the names of its contributors may be
13*f5c631daSSadaf Ebrahimi //     used to endorse or promote products derived from this software without
14*f5c631daSSadaf Ebrahimi //     specific prior written permission.
15*f5c631daSSadaf Ebrahimi //
16*f5c631daSSadaf Ebrahimi // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17*f5c631daSSadaf Ebrahimi // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18*f5c631daSSadaf Ebrahimi // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19*f5c631daSSadaf Ebrahimi // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20*f5c631daSSadaf Ebrahimi // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*f5c631daSSadaf Ebrahimi // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22*f5c631daSSadaf Ebrahimi // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23*f5c631daSSadaf Ebrahimi // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24*f5c631daSSadaf Ebrahimi // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25*f5c631daSSadaf Ebrahimi // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*f5c631daSSadaf Ebrahimi 
27*f5c631daSSadaf Ebrahimi #include <string>
28*f5c631daSSadaf Ebrahimi 
29*f5c631daSSadaf Ebrahimi #include "../globals-vixl.h"
30*f5c631daSSadaf Ebrahimi #include "../utils-vixl.h"
31*f5c631daSSadaf Ebrahimi 
32*f5c631daSSadaf Ebrahimi #include "decoder-aarch64.h"
33*f5c631daSSadaf Ebrahimi #include "decoder-constants-aarch64.h"
34*f5c631daSSadaf Ebrahimi 
35*f5c631daSSadaf Ebrahimi namespace vixl {
36*f5c631daSSadaf Ebrahimi namespace aarch64 {
37*f5c631daSSadaf Ebrahimi 
Decode(const Instruction * instr)38*f5c631daSSadaf Ebrahimi void Decoder::Decode(const Instruction* instr) {
39*f5c631daSSadaf Ebrahimi   std::list<DecoderVisitor*>::iterator it;
40*f5c631daSSadaf Ebrahimi   for (it = visitors_.begin(); it != visitors_.end(); it++) {
41*f5c631daSSadaf Ebrahimi     VIXL_ASSERT((*it)->IsConstVisitor());
42*f5c631daSSadaf Ebrahimi   }
43*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(compiled_decoder_root_ != NULL);
44*f5c631daSSadaf Ebrahimi   compiled_decoder_root_->Decode(instr);
45*f5c631daSSadaf Ebrahimi }
46*f5c631daSSadaf Ebrahimi 
Decode(Instruction * instr)47*f5c631daSSadaf Ebrahimi void Decoder::Decode(Instruction* instr) {
48*f5c631daSSadaf Ebrahimi   compiled_decoder_root_->Decode(const_cast<const Instruction*>(instr));
49*f5c631daSSadaf Ebrahimi }
50*f5c631daSSadaf Ebrahimi 
AddDecodeNode(const DecodeNode & node)51*f5c631daSSadaf Ebrahimi void Decoder::AddDecodeNode(const DecodeNode& node) {
52*f5c631daSSadaf Ebrahimi   if (decode_nodes_.count(node.GetName()) == 0) {
53*f5c631daSSadaf Ebrahimi     decode_nodes_.insert(std::make_pair(node.GetName(), node));
54*f5c631daSSadaf Ebrahimi   }
55*f5c631daSSadaf Ebrahimi }
56*f5c631daSSadaf Ebrahimi 
GetDecodeNode(std::string name)57*f5c631daSSadaf Ebrahimi DecodeNode* Decoder::GetDecodeNode(std::string name) {
58*f5c631daSSadaf Ebrahimi   if (decode_nodes_.count(name) != 1) {
59*f5c631daSSadaf Ebrahimi     std::string msg = "Can't find decode node " + name + ".\n";
60*f5c631daSSadaf Ebrahimi     VIXL_ABORT_WITH_MSG(msg.c_str());
61*f5c631daSSadaf Ebrahimi   }
62*f5c631daSSadaf Ebrahimi   return &decode_nodes_[name];
63*f5c631daSSadaf Ebrahimi }
64*f5c631daSSadaf Ebrahimi 
ConstructDecodeGraph()65*f5c631daSSadaf Ebrahimi void Decoder::ConstructDecodeGraph() {
66*f5c631daSSadaf Ebrahimi   // Add all of the decoding nodes to the Decoder.
67*f5c631daSSadaf Ebrahimi   for (unsigned i = 0; i < ArrayLength(kDecodeMapping); i++) {
68*f5c631daSSadaf Ebrahimi     AddDecodeNode(DecodeNode(kDecodeMapping[i], this));
69*f5c631daSSadaf Ebrahimi 
70*f5c631daSSadaf Ebrahimi     // Add a node for each instruction form named, identified by having no '_'
71*f5c631daSSadaf Ebrahimi     // prefix on the node name.
72*f5c631daSSadaf Ebrahimi     const DecodeMapping& map = kDecodeMapping[i];
73*f5c631daSSadaf Ebrahimi     for (unsigned j = 0; j < map.mapping.size(); j++) {
74*f5c631daSSadaf Ebrahimi       if ((map.mapping[j].handler != NULL) &&
75*f5c631daSSadaf Ebrahimi           (map.mapping[j].handler[0] != '_')) {
76*f5c631daSSadaf Ebrahimi         AddDecodeNode(DecodeNode(map.mapping[j].handler, this));
77*f5c631daSSadaf Ebrahimi       }
78*f5c631daSSadaf Ebrahimi     }
79*f5c631daSSadaf Ebrahimi   }
80*f5c631daSSadaf Ebrahimi 
81*f5c631daSSadaf Ebrahimi   // Add an "unallocated" node, used when an instruction encoding is not
82*f5c631daSSadaf Ebrahimi   // recognised by the decoding graph.
83*f5c631daSSadaf Ebrahimi   AddDecodeNode(DecodeNode("unallocated", this));
84*f5c631daSSadaf Ebrahimi 
85*f5c631daSSadaf Ebrahimi   // Compile the graph from the root.
86*f5c631daSSadaf Ebrahimi   compiled_decoder_root_ = GetDecodeNode("Root")->Compile(this);
87*f5c631daSSadaf Ebrahimi }
88*f5c631daSSadaf Ebrahimi 
AppendVisitor(DecoderVisitor * new_visitor)89*f5c631daSSadaf Ebrahimi void Decoder::AppendVisitor(DecoderVisitor* new_visitor) {
90*f5c631daSSadaf Ebrahimi   visitors_.push_back(new_visitor);
91*f5c631daSSadaf Ebrahimi }
92*f5c631daSSadaf Ebrahimi 
93*f5c631daSSadaf Ebrahimi 
PrependVisitor(DecoderVisitor * new_visitor)94*f5c631daSSadaf Ebrahimi void Decoder::PrependVisitor(DecoderVisitor* new_visitor) {
95*f5c631daSSadaf Ebrahimi   visitors_.push_front(new_visitor);
96*f5c631daSSadaf Ebrahimi }
97*f5c631daSSadaf Ebrahimi 
98*f5c631daSSadaf Ebrahimi 
InsertVisitorBefore(DecoderVisitor * new_visitor,DecoderVisitor * registered_visitor)99*f5c631daSSadaf Ebrahimi void Decoder::InsertVisitorBefore(DecoderVisitor* new_visitor,
100*f5c631daSSadaf Ebrahimi                                   DecoderVisitor* registered_visitor) {
101*f5c631daSSadaf Ebrahimi   std::list<DecoderVisitor*>::iterator it;
102*f5c631daSSadaf Ebrahimi   for (it = visitors_.begin(); it != visitors_.end(); it++) {
103*f5c631daSSadaf Ebrahimi     if (*it == registered_visitor) {
104*f5c631daSSadaf Ebrahimi       visitors_.insert(it, new_visitor);
105*f5c631daSSadaf Ebrahimi       return;
106*f5c631daSSadaf Ebrahimi     }
107*f5c631daSSadaf Ebrahimi   }
108*f5c631daSSadaf Ebrahimi   // We reached the end of the list. The last element must be
109*f5c631daSSadaf Ebrahimi   // registered_visitor.
110*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(*it == registered_visitor);
111*f5c631daSSadaf Ebrahimi   visitors_.insert(it, new_visitor);
112*f5c631daSSadaf Ebrahimi }
113*f5c631daSSadaf Ebrahimi 
114*f5c631daSSadaf Ebrahimi 
InsertVisitorAfter(DecoderVisitor * new_visitor,DecoderVisitor * registered_visitor)115*f5c631daSSadaf Ebrahimi void Decoder::InsertVisitorAfter(DecoderVisitor* new_visitor,
116*f5c631daSSadaf Ebrahimi                                  DecoderVisitor* registered_visitor) {
117*f5c631daSSadaf Ebrahimi   std::list<DecoderVisitor*>::iterator it;
118*f5c631daSSadaf Ebrahimi   for (it = visitors_.begin(); it != visitors_.end(); it++) {
119*f5c631daSSadaf Ebrahimi     if (*it == registered_visitor) {
120*f5c631daSSadaf Ebrahimi       it++;
121*f5c631daSSadaf Ebrahimi       visitors_.insert(it, new_visitor);
122*f5c631daSSadaf Ebrahimi       return;
123*f5c631daSSadaf Ebrahimi     }
124*f5c631daSSadaf Ebrahimi   }
125*f5c631daSSadaf Ebrahimi   // We reached the end of the list. The last element must be
126*f5c631daSSadaf Ebrahimi   // registered_visitor.
127*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(*it == registered_visitor);
128*f5c631daSSadaf Ebrahimi   visitors_.push_back(new_visitor);
129*f5c631daSSadaf Ebrahimi }
130*f5c631daSSadaf Ebrahimi 
131*f5c631daSSadaf Ebrahimi 
RemoveVisitor(DecoderVisitor * visitor)132*f5c631daSSadaf Ebrahimi void Decoder::RemoveVisitor(DecoderVisitor* visitor) {
133*f5c631daSSadaf Ebrahimi   visitors_.remove(visitor);
134*f5c631daSSadaf Ebrahimi }
135*f5c631daSSadaf Ebrahimi 
VisitNamedInstruction(const Instruction * instr,const std::string & name)136*f5c631daSSadaf Ebrahimi void Decoder::VisitNamedInstruction(const Instruction* instr,
137*f5c631daSSadaf Ebrahimi                                     const std::string& name) {
138*f5c631daSSadaf Ebrahimi   std::list<DecoderVisitor*>::iterator it;
139*f5c631daSSadaf Ebrahimi   Metadata m = {{"form", name}};
140*f5c631daSSadaf Ebrahimi   for (it = visitors_.begin(); it != visitors_.end(); it++) {
141*f5c631daSSadaf Ebrahimi     (*it)->Visit(&m, instr);
142*f5c631daSSadaf Ebrahimi   }
143*f5c631daSSadaf Ebrahimi }
144*f5c631daSSadaf Ebrahimi 
145*f5c631daSSadaf Ebrahimi // Initialise empty vectors for sampled bits and pattern table.
146*f5c631daSSadaf Ebrahimi const std::vector<uint8_t> DecodeNode::kEmptySampledBits;
147*f5c631daSSadaf Ebrahimi const std::vector<DecodePattern> DecodeNode::kEmptyPatternTable;
148*f5c631daSSadaf Ebrahimi 
CompileNodeForBits(Decoder * decoder,std::string name,uint32_t bits)149*f5c631daSSadaf Ebrahimi void DecodeNode::CompileNodeForBits(Decoder* decoder,
150*f5c631daSSadaf Ebrahimi                                     std::string name,
151*f5c631daSSadaf Ebrahimi                                     uint32_t bits) {
152*f5c631daSSadaf Ebrahimi   DecodeNode* n = decoder->GetDecodeNode(name);
153*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(n != NULL);
154*f5c631daSSadaf Ebrahimi   if (!n->IsCompiled()) {
155*f5c631daSSadaf Ebrahimi     n->Compile(decoder);
156*f5c631daSSadaf Ebrahimi   }
157*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(n->IsCompiled());
158*f5c631daSSadaf Ebrahimi   compiled_node_->SetNodeForBits(bits, n->GetCompiledNode());
159*f5c631daSSadaf Ebrahimi }
160*f5c631daSSadaf Ebrahimi 
161*f5c631daSSadaf Ebrahimi 
162*f5c631daSSadaf Ebrahimi #define INSTANTIATE_TEMPLATE_M(M)                      \
163*f5c631daSSadaf Ebrahimi   case 0x##M:                                          \
164*f5c631daSSadaf Ebrahimi     bit_extract_fn = &Instruction::ExtractBits<0x##M>; \
165*f5c631daSSadaf Ebrahimi     break;
166*f5c631daSSadaf Ebrahimi #define INSTANTIATE_TEMPLATE_MV(M, V)                           \
167*f5c631daSSadaf Ebrahimi   case 0x##M##V:                                                \
168*f5c631daSSadaf Ebrahimi     bit_extract_fn = &Instruction::IsMaskedValue<0x##M, 0x##V>; \
169*f5c631daSSadaf Ebrahimi     break;
170*f5c631daSSadaf Ebrahimi 
GetBitExtractFunctionHelper(uint32_t x,uint32_t y)171*f5c631daSSadaf Ebrahimi BitExtractFn DecodeNode::GetBitExtractFunctionHelper(uint32_t x, uint32_t y) {
172*f5c631daSSadaf Ebrahimi   // Instantiate a templated bit extraction function for every pattern we
173*f5c631daSSadaf Ebrahimi   // might encounter. If the assertion in the default clause is reached, add a
174*f5c631daSSadaf Ebrahimi   // new instantiation below using the information in the failure message.
175*f5c631daSSadaf Ebrahimi   BitExtractFn bit_extract_fn = NULL;
176*f5c631daSSadaf Ebrahimi 
177*f5c631daSSadaf Ebrahimi   // The arguments x and y represent the mask and value. If y is 0, x is the
178*f5c631daSSadaf Ebrahimi   // mask. Otherwise, y is the mask, and x is the value to compare against a
179*f5c631daSSadaf Ebrahimi   // masked result.
180*f5c631daSSadaf Ebrahimi   uint64_t signature = (static_cast<uint64_t>(y) << 32) | x;
181*f5c631daSSadaf Ebrahimi   switch (signature) {
182*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00000001);
183*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00000010);
184*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(0000001f);
185*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00000060);
186*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00000100);
187*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00000200);
188*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00000400);
189*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00000800);
190*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00000c00);
191*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00000c10);
192*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00000fc0);
193*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00001000);
194*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00001400);
195*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00001800);
196*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00001c00);
197*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00002000);
198*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00002010);
199*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00002400);
200*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00003000);
201*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00003020);
202*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00003400);
203*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00003800);
204*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00003c00);
205*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00013000);
206*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00020000);
207*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00020010);
208*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(000203e0);
209*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(000303e0);
210*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00060000);
211*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00061000);
212*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00070000);
213*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(000703c0);
214*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00080000);
215*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00090000);
216*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(000f0000);
217*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(000f0010);
218*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00100000);
219*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00180000);
220*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(001d1c00);
221*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(001f0000);
222*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(001f2000);
223*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(001f3000);
224*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00400000);
225*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00400800);
226*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00403000);
227*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00500800);
228*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00583000);
229*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(005f0000);
230*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00800000);
231*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00800400);
232*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00800c1e);
233*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(0080101f);
234*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00801c00);
235*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00803000);
236*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00803c00);
237*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(009f0000);
238*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(009f2000);
239*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00c00000);
240*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00c00010);
241*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00c0001f);
242*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00c00200);
243*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00c00400);
244*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00c00c00);
245*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00c00c1c);
246*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00c01000);
247*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00c01400);
248*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00c01c00);
249*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00c02000);
250*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00c03000);
251*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00c03c00);
252*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00c83000);
253*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00cf0000);
254*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00d00200);
255*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00d80800);
256*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00d81800);
257*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00d81c00);
258*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00d82800);
259*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00d82c00);
260*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00d92400);
261*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00d93000);
262*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00db0000);
263*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00dc0000);
264*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00dc2000);
265*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00dd2000);
266*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(00df0000);
267*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40000000);
268*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40000010);
269*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40000c00);
270*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40002000);
271*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40002010);
272*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40003000);
273*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40003c00);
274*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(400f0000);
275*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(400f0400);
276*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(401f2000);
277*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40400800);
278*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40400c00);
279*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40403c00);
280*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40800000);
281*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40800c00);
282*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40802000);
283*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40802010);
284*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40803400);
285*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40803c00);
286*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40c00000);
287*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40c00c00);
288*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40c00c10);
289*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40c01c00);
290*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40c02000);
291*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40c02010);
292*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40c02c00);
293*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40c03c00);
294*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40c80000);
295*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40c90000);
296*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40cf0000);
297*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40d02000);
298*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40d02010);
299*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40d80000);
300*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(40d81800);
301*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_M(bf20c000);
302*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00000003, 00000000);
303*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00000003, 00000003);
304*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(0000001f, 0000001f);
305*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00000210, 00000000);
306*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(000003e0, 00000000);
307*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(000003e0, 000003e0);
308*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(000003e1, 000003e0);
309*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(000003e3, 000003e0);
310*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(000003e3, 000003e3);
311*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00000c00, 00000000);
312*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00000fc0, 00000000);
313*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(000013e0, 00001000);
314*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00001c00, 00000000);
315*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00002400, 00000000);
316*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00003000, 00000000);
317*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00003000, 00001000);
318*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00003000, 00002000);
319*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00003000, 00003000);
320*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00003010, 00000000);
321*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00060000, 00000000);
322*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00061000, 00000000);
323*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00070000, 00030000);
324*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(0007309f, 0000001f);
325*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00073ee0, 00033060);
326*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(000f0000, 00000000);
327*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(000f0010, 00000000);
328*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00100200, 00000000);
329*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00100210, 00000000);
330*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00160000, 00000000);
331*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00170000, 00000000);
332*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(001c0000, 00000000);
333*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(001d0000, 00000000);
334*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(001e0000, 00000000);
335*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(001f0000, 00000000);
336*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(001f0000, 00010000);
337*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(001f0000, 00100000);
338*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(001f0000, 001f0000);
339*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(001f3000, 00000000);
340*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(001f3000, 001f0000);
341*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(001f300f, 0000000d);
342*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(001f301f, 0000000d);
343*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(001f33e0, 000103e0);
344*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(001f3800, 00000000);
345*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00401000, 00400000);
346*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00403000, 00000000);
347*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(005f3000, 001f0000);
348*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(005f3000, 001f1000);
349*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00800010, 00000000);
350*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00800400, 00000000);
351*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00800410, 00000000);
352*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00803000, 00002000);
353*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00870000, 00000000);
354*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(009f0000, 00010000);
355*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00c00000, 00000000);
356*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00c00000, 00400000);
357*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00c0001f, 00000000);
358*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00c001ff, 00000000);
359*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00c00200, 00400000);
360*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00c0020f, 00400000);
361*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00c003e0, 00000000);
362*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00c00800, 00000000);
363*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00d80800, 00000000);
364*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00df0000, 00000000);
365*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(00df3800, 001f0800);
366*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(40002000, 40000000);
367*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(40003c00, 00000000);
368*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(40040000, 00000000);
369*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(40800c00, 40000400);
370*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(40c00000, 00000000);
371*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(40c00000, 00400000);
372*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(40c00000, 40000000);
373*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(40c00000, 40800000);
374*f5c631daSSadaf Ebrahimi     INSTANTIATE_TEMPLATE_MV(40df0000, 00000000);
375*f5c631daSSadaf Ebrahimi     default: {
376*f5c631daSSadaf Ebrahimi       static bool printed_preamble = false;
377*f5c631daSSadaf Ebrahimi       if (!printed_preamble) {
378*f5c631daSSadaf Ebrahimi         printf("One or more missing template instantiations.\n");
379*f5c631daSSadaf Ebrahimi         printf(
380*f5c631daSSadaf Ebrahimi             "Add the following to either GetBitExtractFunction() "
381*f5c631daSSadaf Ebrahimi             "implementations\n");
382*f5c631daSSadaf Ebrahimi         printf("in %s near line %d:\n", __FILE__, __LINE__);
383*f5c631daSSadaf Ebrahimi         printed_preamble = true;
384*f5c631daSSadaf Ebrahimi       }
385*f5c631daSSadaf Ebrahimi 
386*f5c631daSSadaf Ebrahimi       if (y == 0) {
387*f5c631daSSadaf Ebrahimi         printf("  INSTANTIATE_TEMPLATE_M(%08x);\n", x);
388*f5c631daSSadaf Ebrahimi         bit_extract_fn = &Instruction::ExtractBitsAbsent;
389*f5c631daSSadaf Ebrahimi       } else {
390*f5c631daSSadaf Ebrahimi         printf("  INSTANTIATE_TEMPLATE_MV(%08x, %08x);\n", y, x);
391*f5c631daSSadaf Ebrahimi         bit_extract_fn = &Instruction::IsMaskedValueAbsent;
392*f5c631daSSadaf Ebrahimi       }
393*f5c631daSSadaf Ebrahimi     }
394*f5c631daSSadaf Ebrahimi   }
395*f5c631daSSadaf Ebrahimi   return bit_extract_fn;
396*f5c631daSSadaf Ebrahimi }
397*f5c631daSSadaf Ebrahimi 
398*f5c631daSSadaf Ebrahimi #undef INSTANTIATE_TEMPLATE_M
399*f5c631daSSadaf Ebrahimi #undef INSTANTIATE_TEMPLATE_MV
400*f5c631daSSadaf Ebrahimi 
TryCompileOptimisedDecodeTable(Decoder * decoder)401*f5c631daSSadaf Ebrahimi bool DecodeNode::TryCompileOptimisedDecodeTable(Decoder* decoder) {
402*f5c631daSSadaf Ebrahimi   // EitherOr optimisation: if there are only one or two patterns in the table,
403*f5c631daSSadaf Ebrahimi   // try to optimise the node to exploit that.
404*f5c631daSSadaf Ebrahimi   size_t table_size = pattern_table_.size();
405*f5c631daSSadaf Ebrahimi   if ((table_size <= 2) && (GetSampledBitsCount() > 1)) {
406*f5c631daSSadaf Ebrahimi     // TODO: support 'x' in this optimisation by dropping the sampled bit
407*f5c631daSSadaf Ebrahimi     // positions before making the mask/value.
408*f5c631daSSadaf Ebrahimi     if (!PatternContainsSymbol(pattern_table_[0].pattern,
409*f5c631daSSadaf Ebrahimi                                PatternSymbol::kSymbolX) &&
410*f5c631daSSadaf Ebrahimi         (table_size == 1)) {
411*f5c631daSSadaf Ebrahimi       // A pattern table consisting of a fixed pattern with no x's, and an
412*f5c631daSSadaf Ebrahimi       // "otherwise" or absent case. Optimise this into an instruction mask and
413*f5c631daSSadaf Ebrahimi       // value test.
414*f5c631daSSadaf Ebrahimi       uint32_t single_decode_mask = 0;
415*f5c631daSSadaf Ebrahimi       uint32_t single_decode_value = 0;
416*f5c631daSSadaf Ebrahimi       const std::vector<uint8_t>& bits = GetSampledBits();
417*f5c631daSSadaf Ebrahimi 
418*f5c631daSSadaf Ebrahimi       // Construct the instruction mask and value from the pattern.
419*f5c631daSSadaf Ebrahimi       VIXL_ASSERT(bits.size() == GetPatternLength(pattern_table_[0].pattern));
420*f5c631daSSadaf Ebrahimi       for (size_t i = 0; i < bits.size(); i++) {
421*f5c631daSSadaf Ebrahimi         single_decode_mask |= 1U << bits[i];
422*f5c631daSSadaf Ebrahimi         if (GetSymbolAt(pattern_table_[0].pattern, i) ==
423*f5c631daSSadaf Ebrahimi             PatternSymbol::kSymbol1) {
424*f5c631daSSadaf Ebrahimi           single_decode_value |= 1U << bits[i];
425*f5c631daSSadaf Ebrahimi         }
426*f5c631daSSadaf Ebrahimi       }
427*f5c631daSSadaf Ebrahimi       BitExtractFn bit_extract_fn =
428*f5c631daSSadaf Ebrahimi           GetBitExtractFunction(single_decode_mask, single_decode_value);
429*f5c631daSSadaf Ebrahimi 
430*f5c631daSSadaf Ebrahimi       // Create a compiled node that contains a two entry table for the
431*f5c631daSSadaf Ebrahimi       // either/or cases.
432*f5c631daSSadaf Ebrahimi       CreateCompiledNode(bit_extract_fn, 2);
433*f5c631daSSadaf Ebrahimi 
434*f5c631daSSadaf Ebrahimi       // Set DecodeNode for when the instruction after masking doesn't match the
435*f5c631daSSadaf Ebrahimi       // value.
436*f5c631daSSadaf Ebrahimi       CompileNodeForBits(decoder, "unallocated", 0);
437*f5c631daSSadaf Ebrahimi 
438*f5c631daSSadaf Ebrahimi       // Set DecodeNode for when it does match.
439*f5c631daSSadaf Ebrahimi       CompileNodeForBits(decoder, pattern_table_[0].handler, 1);
440*f5c631daSSadaf Ebrahimi 
441*f5c631daSSadaf Ebrahimi       return true;
442*f5c631daSSadaf Ebrahimi     }
443*f5c631daSSadaf Ebrahimi   }
444*f5c631daSSadaf Ebrahimi   return false;
445*f5c631daSSadaf Ebrahimi }
446*f5c631daSSadaf Ebrahimi 
Compile(Decoder * decoder)447*f5c631daSSadaf Ebrahimi CompiledDecodeNode* DecodeNode::Compile(Decoder* decoder) {
448*f5c631daSSadaf Ebrahimi   if (IsLeafNode()) {
449*f5c631daSSadaf Ebrahimi     // A leaf node is a simple wrapper around a visitor function, with no
450*f5c631daSSadaf Ebrahimi     // instruction decoding to do.
451*f5c631daSSadaf Ebrahimi     CreateVisitorNode();
452*f5c631daSSadaf Ebrahimi   } else if (!TryCompileOptimisedDecodeTable(decoder)) {
453*f5c631daSSadaf Ebrahimi     // The "otherwise" node is the default next node if no pattern matches.
454*f5c631daSSadaf Ebrahimi     std::string otherwise = "unallocated";
455*f5c631daSSadaf Ebrahimi 
456*f5c631daSSadaf Ebrahimi     // For each pattern in pattern_table_, create an entry in matches that
457*f5c631daSSadaf Ebrahimi     // has a corresponding mask and value for the pattern.
458*f5c631daSSadaf Ebrahimi     std::vector<MaskValuePair> matches;
459*f5c631daSSadaf Ebrahimi     for (size_t i = 0; i < pattern_table_.size(); i++) {
460*f5c631daSSadaf Ebrahimi       matches.push_back(GenerateMaskValuePair(
461*f5c631daSSadaf Ebrahimi           GenerateOrderedPattern(pattern_table_[i].pattern)));
462*f5c631daSSadaf Ebrahimi     }
463*f5c631daSSadaf Ebrahimi 
464*f5c631daSSadaf Ebrahimi     BitExtractFn bit_extract_fn =
465*f5c631daSSadaf Ebrahimi         GetBitExtractFunction(GenerateSampledBitsMask());
466*f5c631daSSadaf Ebrahimi 
467*f5c631daSSadaf Ebrahimi     // Create a compiled node that contains a table with an entry for every bit
468*f5c631daSSadaf Ebrahimi     // pattern.
469*f5c631daSSadaf Ebrahimi     CreateCompiledNode(bit_extract_fn, 1U << GetSampledBitsCount());
470*f5c631daSSadaf Ebrahimi     VIXL_ASSERT(compiled_node_ != NULL);
471*f5c631daSSadaf Ebrahimi 
472*f5c631daSSadaf Ebrahimi     // When we find a pattern matches the representation, set the node's decode
473*f5c631daSSadaf Ebrahimi     // function for that representation to the corresponding function.
474*f5c631daSSadaf Ebrahimi     for (uint32_t bits = 0; bits < (1U << GetSampledBitsCount()); bits++) {
475*f5c631daSSadaf Ebrahimi       for (size_t i = 0; i < matches.size(); i++) {
476*f5c631daSSadaf Ebrahimi         if ((bits & matches[i].first) == matches[i].second) {
477*f5c631daSSadaf Ebrahimi           // Only one instruction class should match for each value of bits, so
478*f5c631daSSadaf Ebrahimi           // if we get here, the node pointed to should still be unallocated.
479*f5c631daSSadaf Ebrahimi           VIXL_ASSERT(compiled_node_->GetNodeForBits(bits) == NULL);
480*f5c631daSSadaf Ebrahimi           CompileNodeForBits(decoder, pattern_table_[i].handler, bits);
481*f5c631daSSadaf Ebrahimi           break;
482*f5c631daSSadaf Ebrahimi         }
483*f5c631daSSadaf Ebrahimi       }
484*f5c631daSSadaf Ebrahimi 
485*f5c631daSSadaf Ebrahimi       // If the decode_table_ entry for these bits is still NULL, the
486*f5c631daSSadaf Ebrahimi       // instruction must be handled by the "otherwise" case, which by default
487*f5c631daSSadaf Ebrahimi       // is the Unallocated visitor.
488*f5c631daSSadaf Ebrahimi       if (compiled_node_->GetNodeForBits(bits) == NULL) {
489*f5c631daSSadaf Ebrahimi         CompileNodeForBits(decoder, otherwise, bits);
490*f5c631daSSadaf Ebrahimi       }
491*f5c631daSSadaf Ebrahimi     }
492*f5c631daSSadaf Ebrahimi   }
493*f5c631daSSadaf Ebrahimi 
494*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(compiled_node_ != NULL);
495*f5c631daSSadaf Ebrahimi   return compiled_node_;
496*f5c631daSSadaf Ebrahimi }
497*f5c631daSSadaf Ebrahimi 
Decode(const Instruction * instr) const498*f5c631daSSadaf Ebrahimi void CompiledDecodeNode::Decode(const Instruction* instr) const {
499*f5c631daSSadaf Ebrahimi   if (IsLeafNode()) {
500*f5c631daSSadaf Ebrahimi     // If this node is a leaf, call the registered visitor function.
501*f5c631daSSadaf Ebrahimi     VIXL_ASSERT(decoder_ != NULL);
502*f5c631daSSadaf Ebrahimi     decoder_->VisitNamedInstruction(instr, instruction_name_);
503*f5c631daSSadaf Ebrahimi   } else {
504*f5c631daSSadaf Ebrahimi     // Otherwise, using the sampled bit extractor for this node, look up the
505*f5c631daSSadaf Ebrahimi     // next node in the decode tree, and call its Decode method.
506*f5c631daSSadaf Ebrahimi     VIXL_ASSERT(bit_extract_fn_ != NULL);
507*f5c631daSSadaf Ebrahimi     VIXL_ASSERT((instr->*bit_extract_fn_)() < decode_table_size_);
508*f5c631daSSadaf Ebrahimi     VIXL_ASSERT(decode_table_[(instr->*bit_extract_fn_)()] != NULL);
509*f5c631daSSadaf Ebrahimi     decode_table_[(instr->*bit_extract_fn_)()]->Decode(instr);
510*f5c631daSSadaf Ebrahimi   }
511*f5c631daSSadaf Ebrahimi }
512*f5c631daSSadaf Ebrahimi 
GenerateMaskValuePair(uint32_t pattern) const513*f5c631daSSadaf Ebrahimi DecodeNode::MaskValuePair DecodeNode::GenerateMaskValuePair(
514*f5c631daSSadaf Ebrahimi     uint32_t pattern) const {
515*f5c631daSSadaf Ebrahimi   uint32_t mask = 0, value = 0;
516*f5c631daSSadaf Ebrahimi   for (size_t i = 0; i < GetPatternLength(pattern); i++) {
517*f5c631daSSadaf Ebrahimi     PatternSymbol sym = GetSymbolAt(pattern, i);
518*f5c631daSSadaf Ebrahimi     mask = (mask << 1) | ((sym == PatternSymbol::kSymbolX) ? 0 : 1);
519*f5c631daSSadaf Ebrahimi     value = (value << 1) | (static_cast<uint32_t>(sym) & 1);
520*f5c631daSSadaf Ebrahimi   }
521*f5c631daSSadaf Ebrahimi   return std::make_pair(mask, value);
522*f5c631daSSadaf Ebrahimi }
523*f5c631daSSadaf Ebrahimi 
GenerateOrderedPattern(uint32_t pattern) const524*f5c631daSSadaf Ebrahimi uint32_t DecodeNode::GenerateOrderedPattern(uint32_t pattern) const {
525*f5c631daSSadaf Ebrahimi   const std::vector<uint8_t>& sampled_bits = GetSampledBits();
526*f5c631daSSadaf Ebrahimi   uint64_t temp = 0xffffffffffffffff;
527*f5c631daSSadaf Ebrahimi 
528*f5c631daSSadaf Ebrahimi   // Place symbols into the field of set bits. Symbols are two bits wide and
529*f5c631daSSadaf Ebrahimi   // take values 0, 1 or 2, so 3 will represent "no symbol".
530*f5c631daSSadaf Ebrahimi   for (size_t i = 0; i < sampled_bits.size(); i++) {
531*f5c631daSSadaf Ebrahimi     int shift = sampled_bits[i] * 2;
532*f5c631daSSadaf Ebrahimi     temp ^= static_cast<uint64_t>(kEndOfPattern) << shift;
533*f5c631daSSadaf Ebrahimi     temp |= static_cast<uint64_t>(GetSymbolAt(pattern, i)) << shift;
534*f5c631daSSadaf Ebrahimi   }
535*f5c631daSSadaf Ebrahimi 
536*f5c631daSSadaf Ebrahimi   // Iterate over temp and extract new pattern ordered by sample position.
537*f5c631daSSadaf Ebrahimi   uint32_t result = kEndOfPattern;  // End of pattern marker.
538*f5c631daSSadaf Ebrahimi 
539*f5c631daSSadaf Ebrahimi   // Iterate over the pattern one symbol (two bits) at a time.
540*f5c631daSSadaf Ebrahimi   for (int i = 62; i >= 0; i -= 2) {
541*f5c631daSSadaf Ebrahimi     uint32_t sym = (temp >> i) & kPatternSymbolMask;
542*f5c631daSSadaf Ebrahimi 
543*f5c631daSSadaf Ebrahimi     // If this is a valid symbol, shift into the result.
544*f5c631daSSadaf Ebrahimi     if (sym != kEndOfPattern) {
545*f5c631daSSadaf Ebrahimi       result = (result << 2) | sym;
546*f5c631daSSadaf Ebrahimi     }
547*f5c631daSSadaf Ebrahimi   }
548*f5c631daSSadaf Ebrahimi 
549*f5c631daSSadaf Ebrahimi   // The length of the ordered pattern must be the same as the input pattern,
550*f5c631daSSadaf Ebrahimi   // and the number of sampled bits.
551*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(GetPatternLength(result) == GetPatternLength(pattern));
552*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(GetPatternLength(result) == sampled_bits.size());
553*f5c631daSSadaf Ebrahimi 
554*f5c631daSSadaf Ebrahimi   return result;
555*f5c631daSSadaf Ebrahimi }
556*f5c631daSSadaf Ebrahimi 
GenerateSampledBitsMask() const557*f5c631daSSadaf Ebrahimi uint32_t DecodeNode::GenerateSampledBitsMask() const {
558*f5c631daSSadaf Ebrahimi   uint32_t mask = 0;
559*f5c631daSSadaf Ebrahimi   for (int bit : GetSampledBits()) {
560*f5c631daSSadaf Ebrahimi     mask |= 1 << bit;
561*f5c631daSSadaf Ebrahimi   }
562*f5c631daSSadaf Ebrahimi   return mask;
563*f5c631daSSadaf Ebrahimi }
564*f5c631daSSadaf Ebrahimi 
565*f5c631daSSadaf Ebrahimi }  // namespace aarch64
566*f5c631daSSadaf Ebrahimi }  // namespace vixl
567