• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef VIXL_AARCH64_DECODER_AARCH64_H_
28 #define VIXL_AARCH64_DECODER_AARCH64_H_
29 
30 #include <list>
31 #include <map>
32 #include <string>
33 
34 #include "../globals-vixl.h"
35 
36 #include "instructions-aarch64.h"
37 
38 
39 // List macro containing all visitors needed by the decoder class.
40 
41 #define VISITOR_LIST_THAT_RETURN(V)     \
42   V(AddSubExtended)                     \
43   V(AddSubImmediate)                    \
44   V(AddSubShifted)                      \
45   V(AddSubWithCarry)                    \
46   V(AtomicMemory)                       \
47   V(Bitfield)                           \
48   V(CompareBranch)                      \
49   V(ConditionalBranch)                  \
50   V(ConditionalCompareImmediate)        \
51   V(ConditionalCompareRegister)         \
52   V(ConditionalSelect)                  \
53   V(Crypto2RegSHA)                      \
54   V(Crypto3RegSHA)                      \
55   V(CryptoAES)                          \
56   V(DataProcessing1Source)              \
57   V(DataProcessing2Source)              \
58   V(DataProcessing3Source)              \
59   V(Exception)                          \
60   V(Extract)                            \
61   V(EvaluateIntoFlags)                  \
62   V(FPCompare)                          \
63   V(FPConditionalCompare)               \
64   V(FPConditionalSelect)                \
65   V(FPDataProcessing1Source)            \
66   V(FPDataProcessing2Source)            \
67   V(FPDataProcessing3Source)            \
68   V(FPFixedPointConvert)                \
69   V(FPImmediate)                        \
70   V(FPIntegerConvert)                   \
71   V(LoadLiteral)                        \
72   V(LoadStoreExclusive)                 \
73   V(LoadStorePAC)                       \
74   V(LoadStorePairNonTemporal)           \
75   V(LoadStorePairOffset)                \
76   V(LoadStorePairPostIndex)             \
77   V(LoadStorePairPreIndex)              \
78   V(LoadStorePostIndex)                 \
79   V(LoadStorePreIndex)                  \
80   V(LoadStoreRCpcUnscaledOffset)        \
81   V(LoadStoreRegisterOffset)            \
82   V(LoadStoreUnscaledOffset)            \
83   V(LoadStoreUnsignedOffset)            \
84   V(LogicalImmediate)                   \
85   V(LogicalShifted)                     \
86   V(MoveWideImmediate)                  \
87   V(NEON2RegMisc)                       \
88   V(NEON2RegMiscFP16)                   \
89   V(NEON3Different)                     \
90   V(NEON3Same)                          \
91   V(NEON3SameExtra)                     \
92   V(NEON3SameFP16)                      \
93   V(NEONAcrossLanes)                    \
94   V(NEONByIndexedElement)               \
95   V(NEONCopy)                           \
96   V(NEONExtract)                        \
97   V(NEONLoadStoreMultiStruct)           \
98   V(NEONLoadStoreMultiStructPostIndex)  \
99   V(NEONLoadStoreSingleStruct)          \
100   V(NEONLoadStoreSingleStructPostIndex) \
101   V(NEONModifiedImmediate)              \
102   V(NEONPerm)                           \
103   V(NEONScalar2RegMisc)                 \
104   V(NEONScalar2RegMiscFP16)             \
105   V(NEONScalar3Diff)                    \
106   V(NEONScalar3Same)                    \
107   V(NEONScalar3SameExtra)               \
108   V(NEONScalar3SameFP16)                \
109   V(NEONScalarByIndexedElement)         \
110   V(NEONScalarCopy)                     \
111   V(NEONScalarPairwise)                 \
112   V(NEONScalarShiftImmediate)           \
113   V(NEONShiftImmediate)                 \
114   V(NEONTable)                          \
115   V(PCRelAddressing)                    \
116   V(RotateRightIntoFlags)               \
117   V(System)                             \
118   V(TestBranch)                         \
119   V(UnconditionalBranch)                \
120   V(UnconditionalBranchToRegister)
121 
122 // TODO: We shouldn't expose debug-only behaviour like this. Instead, we should
123 // use release-mode aborts where appropriate, and merge thse into a single
124 // no-return list.
125 #define VISITOR_LIST_THAT_DONT_RETURN_IN_DEBUG_MODE(V) \
126   V(Unallocated)                                       \
127   V(Unimplemented)
128 
129 #define VISITOR_LIST_THAT_DONT_RETURN(V) V(Reserved)
130 
131 #define VISITOR_LIST(V)                          \
132   VISITOR_LIST_THAT_RETURN(V)                    \
133   VISITOR_LIST_THAT_DONT_RETURN_IN_DEBUG_MODE(V) \
134   VISITOR_LIST_THAT_DONT_RETURN(V)
135 
136 namespace vixl {
137 namespace aarch64 {
138 
139 // The Visitor interface. Disassembler and simulator (and other tools)
140 // must provide implementations for all of these functions.
141 class DecoderVisitor {
142  public:
143   enum VisitorConstness { kConstVisitor, kNonConstVisitor };
144   explicit DecoderVisitor(VisitorConstness constness = kConstVisitor)
constness_(constness)145       : constness_(constness) {}
146 
~DecoderVisitor()147   virtual ~DecoderVisitor() {}
148 
149 #define DECLARE(A) virtual void Visit##A(const Instruction* instr) = 0;
VISITOR_LIST(DECLARE)150   VISITOR_LIST(DECLARE)
151 #undef DECLARE
152 
153   bool IsConstVisitor() const { return constness_ == kConstVisitor; }
MutableInstruction(const Instruction * instr)154   Instruction* MutableInstruction(const Instruction* instr) {
155     VIXL_ASSERT(!IsConstVisitor());
156     return const_cast<Instruction*>(instr);
157   }
158 
159  private:
160   const VisitorConstness constness_;
161 };
162 
163 class DecodeNode;
164 class CompiledDecodeNode;
165 
166 // The instruction decoder is constructed from a graph of decode nodes. At each
167 // node, a number of bits are sampled from the instruction being decoded. The
168 // resulting value is used to look up the next node in the graph, which then
169 // samples other bits, and moves to other decode nodes. Eventually, a visitor
170 // node is reached, and the corresponding visitor function is called, which
171 // handles the instruction.
172 class Decoder {
173  public:
Decoder()174   Decoder() { ConstructDecodeGraph(); }
175 
176   // Top-level wrappers around the actual decoding function.
177   void Decode(const Instruction* instr);
178   void Decode(Instruction* instr);
179 
180   // Decode all instructions from start (inclusive) to end (exclusive).
181   template <typename T>
Decode(T start,T end)182   void Decode(T start, T end) {
183     for (T instr = start; instr < end; instr = instr->GetNextInstruction()) {
184       Decode(instr);
185     }
186   }
187 
188   // Register a new visitor class with the decoder.
189   // Decode() will call the corresponding visitor method from all registered
190   // visitor classes when decoding reaches the leaf node of the instruction
191   // decode tree.
192   // Visitors are called in order.
193   // A visitor can be registered multiple times.
194   //
195   //   d.AppendVisitor(V1);
196   //   d.AppendVisitor(V2);
197   //   d.PrependVisitor(V2);
198   //   d.AppendVisitor(V3);
199   //
200   //   d.Decode(i);
201   //
202   // will call in order visitor methods in V2, V1, V2, V3.
203   void AppendVisitor(DecoderVisitor* visitor);
204   void PrependVisitor(DecoderVisitor* visitor);
205   // These helpers register `new_visitor` before or after the first instance of
206   // `registered_visiter` in the list.
207   // So if
208   //   V1, V2, V1, V2
209   // are registered in this order in the decoder, calls to
210   //   d.InsertVisitorAfter(V3, V1);
211   //   d.InsertVisitorBefore(V4, V2);
212   // will yield the order
213   //   V1, V3, V4, V2, V1, V2
214   //
215   // For more complex modifications of the order of registered visitors, one can
216   // directly access and modify the list of visitors via the `visitors()'
217   // accessor.
218   void InsertVisitorBefore(DecoderVisitor* new_visitor,
219                            DecoderVisitor* registered_visitor);
220   void InsertVisitorAfter(DecoderVisitor* new_visitor,
221                           DecoderVisitor* registered_visitor);
222 
223   // Remove all instances of a previously registered visitor class from the list
224   // of visitors stored by the decoder.
225   void RemoveVisitor(DecoderVisitor* visitor);
226 
227 #define DECLARE(A) void Visit##A(const Instruction* instr);
VISITOR_LIST(DECLARE)228   VISITOR_LIST(DECLARE)
229 #undef DECLARE
230 
231   std::list<DecoderVisitor*>* visitors() { return &visitors_; }
232 
233   // Get a DecodeNode by name from the Decoder's map.
234   DecodeNode* GetDecodeNode(std::string name);
235 
236  private:
237   // Decodes an instruction and calls the visitor functions registered with the
238   // Decoder class.
239   void DecodeInstruction(const Instruction* instr);
240 
241   // Add an initialised DecodeNode to the decode_node_ map.
242   void AddDecodeNode(const DecodeNode& node);
243 
244   // Visitors are registered in a list.
245   std::list<DecoderVisitor*> visitors_;
246 
247   // Compile the dynamically generated decode graph based on the static
248   // information in kDecodeMapping and kVisitorNodes.
249   void ConstructDecodeGraph();
250 
251   // Root node for the compiled decoder graph, stored here to avoid a map lookup
252   // for every instruction decoded.
253   CompiledDecodeNode* compiled_decoder_root_;
254 
255   // Map of node names to DecodeNodes.
256   std::map<std::string, DecodeNode> decode_nodes_;
257 };
258 
259 const int kMaxDecodeSampledBits = 16;
260 const int kMaxDecodeMappings = 22;
261 typedef void (Decoder::*DecodeFnPtr)(const Instruction*);
262 typedef uint32_t (Instruction::*BitExtractFn)(void) const;
263 
264 // A Visitor node maps the name of a visitor to the function that handles it.
265 struct VisitorNode {
266   const char* name;
267   const DecodeFnPtr visitor_fn;
268 };
269 
270 // DecodePattern and DecodeMapping represent the input data to the decoder
271 // compilation stage. After compilation, the decoder is embodied in the graph
272 // of CompiledDecodeNodes pointer to by compiled_decoder_root_.
273 
274 // A DecodePattern maps a pattern of set/unset/don't care (1, 0, x) bits as a
275 // string to the name of its handler.
276 struct DecodePattern {
277   const char* pattern;
278   const char* handler;
279 };
280 
281 // A DecodeMapping consists of the name of a handler, the bits sampled in the
282 // instruction by that handler, and a mapping from the pattern that those
283 // sampled bits match to the corresponding name of a node.
284 struct DecodeMapping {
285   const char* name;
286   const uint8_t sampled_bits[kMaxDecodeSampledBits];
287   const DecodePattern mapping[kMaxDecodeMappings];
288 };
289 
290 // For speed, before nodes can be used for decoding instructions, they must
291 // be compiled. This converts the mapping "bit pattern strings to decoder name
292 // string" stored in DecodeNodes to an array look up for the pointer to the next
293 // node, stored in CompiledDecodeNodes. Compilation may also apply other
294 // optimisations for simple decode patterns.
295 class CompiledDecodeNode {
296  public:
297   // Constructor for decode node, containing a decode table and pointer to a
298   // function that extracts the bits to be sampled.
CompiledDecodeNode(BitExtractFn bit_extract_fn,size_t decode_table_size)299   CompiledDecodeNode(BitExtractFn bit_extract_fn, size_t decode_table_size)
300       : bit_extract_fn_(bit_extract_fn),
301         visitor_fn_(NULL),
302         decode_table_size_(decode_table_size),
303         decoder_(NULL) {
304     decode_table_ = new CompiledDecodeNode*[decode_table_size_];
305     memset(decode_table_, 0, decode_table_size_ * sizeof(decode_table_[0]));
306   }
307 
308   // Constructor for wrappers around visitor functions. These require no
309   // decoding, so no bit extraction function or decode table is assigned.
CompiledDecodeNode(DecodeFnPtr visitor_fn,Decoder * decoder)310   explicit CompiledDecodeNode(DecodeFnPtr visitor_fn, Decoder* decoder)
311       : bit_extract_fn_(NULL),
312         visitor_fn_(visitor_fn),
313         decode_table_(NULL),
314         decode_table_size_(0),
315         decoder_(decoder) {}
316 
~CompiledDecodeNode()317   ~CompiledDecodeNode() VIXL_NEGATIVE_TESTING_ALLOW_EXCEPTION {
318     // Free the decode table, if this is a compiled, non-leaf node.
319     if (decode_table_ != NULL) {
320       VIXL_ASSERT(!IsLeafNode());
321       delete[] decode_table_;
322     }
323   }
324 
325   // Decode the instruction by either sampling the bits using the bit extract
326   // function to find the next node, or, if we're at a leaf, calling the visitor
327   // function.
328   void Decode(const Instruction* instr) const;
329 
330   // A leaf node is a wrapper for a visitor function.
IsLeafNode()331   bool IsLeafNode() const {
332     VIXL_ASSERT(((visitor_fn_ == NULL) && (bit_extract_fn_ != NULL)) ||
333                 ((visitor_fn_ != NULL) && (bit_extract_fn_ == NULL)));
334     return visitor_fn_ != NULL;
335   }
336 
337   // Get a pointer to the next node required in the decode process, based on the
338   // bits sampled by the current node.
GetNodeForBits(uint32_t bits)339   CompiledDecodeNode* GetNodeForBits(uint32_t bits) const {
340     VIXL_ASSERT(bits < decode_table_size_);
341     return decode_table_[bits];
342   }
343 
344   // Set the next node in the decode process for the pattern of sampled bits in
345   // the current node.
SetNodeForBits(uint32_t bits,CompiledDecodeNode * n)346   void SetNodeForBits(uint32_t bits, CompiledDecodeNode* n) {
347     VIXL_ASSERT(bits < decode_table_size_);
348     VIXL_ASSERT(n != NULL);
349     decode_table_[bits] = n;
350   }
351 
352  private:
353   // Pointer to an instantiated template function for extracting the bits
354   // sampled by this node. Set to NULL for leaf nodes.
355   const BitExtractFn bit_extract_fn_;
356 
357   // Visitor function that handles the instruction identified. Set only for
358   // leaf nodes, where no extra decoding is required, otherwise NULL.
359   const DecodeFnPtr visitor_fn_;
360 
361   // Mapping table from instruction bits to next decode stage.
362   CompiledDecodeNode** decode_table_;
363   const size_t decode_table_size_;
364 
365   // Pointer to the decoder containing this node, used to call its visitor
366   // function for leaf nodes. Set to NULL for non-leaf nodes.
367   Decoder* decoder_;
368 };
369 
370 class DecodeNode {
371  public:
372   // Default constructor needed for map initialisation.
DecodeNode()373   DecodeNode() : compiled_node_(NULL) {}
374 
375   // Constructor for DecodeNode wrappers around visitor functions. These are
376   // marked as "compiled", as there is no decoding left to do.
DecodeNode(const VisitorNode & visitor,Decoder * decoder)377   explicit DecodeNode(const VisitorNode& visitor, Decoder* decoder)
378       : name_(visitor.name),
379         visitor_fn_(visitor.visitor_fn),
380         decoder_(decoder),
381         compiled_node_(NULL) {}
382 
383   // Constructor for DecodeNodes that map bit patterns to other DecodeNodes.
384   explicit DecodeNode(const DecodeMapping& map, Decoder* decoder = NULL)
385       : name_(map.name),
386         visitor_fn_(NULL),
387         decoder_(decoder),
388         compiled_node_(NULL) {
389     // The length of the bit string in the first mapping determines the number
390     // of sampled bits. When adding patterns later, we assert that all mappings
391     // sample the same number of bits.
392     VIXL_CHECK(strcmp(map.mapping[0].pattern, "otherwise") != 0);
393     int bit_count = static_cast<int>(strlen(map.mapping[0].pattern));
394     VIXL_CHECK((bit_count > 0) && (bit_count <= 32));
395     SetSampledBits(map.sampled_bits, bit_count);
396     AddPatterns(map.mapping);
397   }
398 
~DecodeNode()399   ~DecodeNode() {
400     // Delete the compiled version of this node, if one was created.
401     if (compiled_node_ != NULL) {
402       delete compiled_node_;
403     }
404   }
405 
406   // Set the bits sampled from the instruction by this node.
407   void SetSampledBits(const uint8_t* bits, int bit_count);
408 
409   // Get the bits sampled from the instruction by this node.
410   std::vector<uint8_t> GetSampledBits() const;
411 
412   // Get the number of bits sampled from the instruction by this node.
413   size_t GetSampledBitsCount() const;
414 
415   // Add patterns to this node's internal pattern table.
416   void AddPatterns(const DecodePattern* patterns);
417 
418   // A leaf node is a DecodeNode that wraps the visitor function for the
419   // identified instruction class.
IsLeafNode()420   bool IsLeafNode() const { return visitor_fn_ != NULL; }
421 
GetName()422   std::string GetName() const { return name_; }
423 
424   // Create a CompiledDecodeNode of specified table size that uses
425   // bit_extract_fn to sample bits from the instruction.
CreateCompiledNode(BitExtractFn bit_extract_fn,size_t table_size)426   void CreateCompiledNode(BitExtractFn bit_extract_fn, size_t table_size) {
427     VIXL_ASSERT(bit_extract_fn != NULL);
428     VIXL_ASSERT(table_size > 0);
429     compiled_node_ = new CompiledDecodeNode(bit_extract_fn, table_size);
430   }
431 
432   // Create a CompiledDecodeNode wrapping a visitor function. No decoding is
433   // required for this node; the visitor function is called instead.
CreateVisitorNode()434   void CreateVisitorNode() {
435     compiled_node_ = new CompiledDecodeNode(visitor_fn_, decoder_);
436   }
437 
438   // Find and compile the DecodeNode named "name", and set it as the node for
439   // the pattern "bits".
440   void CompileNodeForBits(Decoder* decoder, std::string name, uint32_t bits);
441 
442   // Get a pointer to an instruction method that extracts the instruction bits
443   // specified by the mask argument, and returns those sampled bits as a
444   // contiguous sequence, suitable for indexing an array.
445   // For example, a mask of 0b1010 returns a function that, given an instruction
446   // 0bXYZW, will return 0bXZ.
447   BitExtractFn GetBitExtractFunction(uint32_t mask);
448 
449   // Get a pointer to an Instruction method that applies a mask to the
450   // instruction bits, and tests if the result is equal to value. The returned
451   // function gives a 1 result if (inst & mask == value), 0 otherwise.
452   BitExtractFn GetBitExtractFunction(uint32_t mask, uint32_t value);
453 
454   // Compile this DecodeNode into a new CompiledDecodeNode and returns a pointer
455   // to it. This pointer is also stored inside the DecodeNode itself. Destroying
456   // a DecodeNode frees its associated CompiledDecodeNode.
457   CompiledDecodeNode* Compile(Decoder* decoder);
458 
459   // Get a pointer to the CompiledDecodeNode associated with this DecodeNode.
460   // Returns NULL if the node has not been compiled yet.
GetCompiledNode()461   CompiledDecodeNode* GetCompiledNode() const { return compiled_node_; }
IsCompiled()462   bool IsCompiled() const { return GetCompiledNode() != NULL; }
463 
464  private:
465   // Generate a mask and value pair from a string constructed from 0, 1 and x
466   // (don't care) characters.
467   // For example "10x1" should return mask = 0b1101, value = 0b1001.
468   typedef std::pair<Instr, Instr> MaskValuePair;
469   MaskValuePair GenerateMaskValuePair(std::string pattern) const;
470 
471   // Generate a pattern string ordered by the bit positions sampled by this
472   // node. The first character in the string corresponds to the lowest sampled
473   // bit.
474   // For example, a pattern of "1x0" expected when sampling bits 31, 1 and 30
475   // returns the pattern "x01"; bit 1 should be 'x', bit 30 '0' and bit 31 '1'.
476   // This output makes comparisons easier between the pattern and bits sampled
477   // from an instruction using the fast "compress" algorithm. See
478   // Instruction::Compress().
479   std::string GenerateOrderedPattern(std::string pattern) const;
480 
481   // Generate a mask with a bit set at each sample position.
482   uint32_t GenerateSampledBitsMask() const;
483 
484   // Try to compile a more optimised decode operation for this node, returning
485   // true if successful.
486   bool TryCompileOptimisedDecodeTable(Decoder* decoder);
487 
488   // Name of this decoder node, used to construct edges in the decode graph.
489   std::string name_;
490 
491   // Vector of bits sampled from an instruction to determine which node to look
492   // up next in the decode process.
493   std::vector<uint8_t> sampled_bits_;
494 
495   // Visitor function that handles the instruction identified. Set only for leaf
496   // nodes, where no extra decoding is required. For non-leaf decoding nodes,
497   // this pointer is NULL.
498   DecodeFnPtr visitor_fn_;
499 
500   // Source mapping from bit pattern to name of next decode stage.
501   std::vector<DecodePattern> pattern_table_;
502 
503   // Pointer to the decoder containing this node, used to call its visitor
504   // function for leaf nodes.
505   Decoder* decoder_;
506 
507   // Pointer to the compiled version of this node. Is this node hasn't been
508   // compiled yet, this pointer is NULL.
509   CompiledDecodeNode* compiled_node_;
510 };
511 
512 }  // namespace aarch64
513 }  // namespace vixl
514 
515 #endif  // VIXL_AARCH64_DECODER_AARCH64_H_
516