1b8021494Sopenharmony_ci// Copyright 2019, VIXL authors
2b8021494Sopenharmony_ci// All rights reserved.
3b8021494Sopenharmony_ci//
4b8021494Sopenharmony_ci// Redistribution and use in source and binary forms, with or without
5b8021494Sopenharmony_ci// modification, are permitted provided that the following conditions are met:
6b8021494Sopenharmony_ci//
7b8021494Sopenharmony_ci//   * Redistributions of source code must retain the above copyright notice,
8b8021494Sopenharmony_ci//     this list of conditions and the following disclaimer.
9b8021494Sopenharmony_ci//   * Redistributions in binary form must reproduce the above copyright notice,
10b8021494Sopenharmony_ci//     this list of conditions and the following disclaimer in the documentation
11b8021494Sopenharmony_ci//     and/or other materials provided with the distribution.
12b8021494Sopenharmony_ci//   * Neither the name of ARM Limited nor the names of its contributors may be
13b8021494Sopenharmony_ci//     used to endorse or promote products derived from this software without
14b8021494Sopenharmony_ci//     specific prior written permission.
15b8021494Sopenharmony_ci//
16b8021494Sopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17b8021494Sopenharmony_ci// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18b8021494Sopenharmony_ci// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19b8021494Sopenharmony_ci// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20b8021494Sopenharmony_ci// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21b8021494Sopenharmony_ci// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22b8021494Sopenharmony_ci// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23b8021494Sopenharmony_ci// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24b8021494Sopenharmony_ci// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25b8021494Sopenharmony_ci// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26b8021494Sopenharmony_ci
27b8021494Sopenharmony_ci#ifndef VIXL_AARCH64_DECODER_AARCH64_H_
28b8021494Sopenharmony_ci#define VIXL_AARCH64_DECODER_AARCH64_H_
29b8021494Sopenharmony_ci
30b8021494Sopenharmony_ci#include <functional>
31b8021494Sopenharmony_ci#include <list>
32b8021494Sopenharmony_ci#include <map>
33b8021494Sopenharmony_ci#include <string>
34b8021494Sopenharmony_ci
35b8021494Sopenharmony_ci#include "../globals-vixl.h"
36b8021494Sopenharmony_ci#include "../utils-vixl.h"
37b8021494Sopenharmony_ci
38b8021494Sopenharmony_ci#include "instructions-aarch64.h"
39b8021494Sopenharmony_ci
40b8021494Sopenharmony_ci// List macro containing all visitors needed by the decoder class.
41b8021494Sopenharmony_ci#define VISITOR_LIST_THAT_RETURN(V)                              \
42b8021494Sopenharmony_ci  V(AddSubExtended)                                              \
43b8021494Sopenharmony_ci  V(AddSubImmediate)                                             \
44b8021494Sopenharmony_ci  V(AddSubShifted)                                               \
45b8021494Sopenharmony_ci  V(AddSubWithCarry)                                             \
46b8021494Sopenharmony_ci  V(AtomicMemory)                                                \
47b8021494Sopenharmony_ci  V(Bitfield)                                                    \
48b8021494Sopenharmony_ci  V(CompareBranch)                                               \
49b8021494Sopenharmony_ci  V(ConditionalBranch)                                           \
50b8021494Sopenharmony_ci  V(ConditionalCompareImmediate)                                 \
51b8021494Sopenharmony_ci  V(ConditionalCompareRegister)                                  \
52b8021494Sopenharmony_ci  V(ConditionalSelect)                                           \
53b8021494Sopenharmony_ci  V(Crypto2RegSHA)                                               \
54b8021494Sopenharmony_ci  V(Crypto3RegSHA)                                               \
55b8021494Sopenharmony_ci  V(CryptoAES)                                                   \
56b8021494Sopenharmony_ci  V(DataProcessing1Source)                                       \
57b8021494Sopenharmony_ci  V(DataProcessing2Source)                                       \
58b8021494Sopenharmony_ci  V(DataProcessing3Source)                                       \
59b8021494Sopenharmony_ci  V(EvaluateIntoFlags)                                           \
60b8021494Sopenharmony_ci  V(Exception)                                                   \
61b8021494Sopenharmony_ci  V(Extract)                                                     \
62b8021494Sopenharmony_ci  V(FPCompare)                                                   \
63b8021494Sopenharmony_ci  V(FPConditionalCompare)                                        \
64b8021494Sopenharmony_ci  V(FPConditionalSelect)                                         \
65b8021494Sopenharmony_ci  V(FPDataProcessing1Source)                                     \
66b8021494Sopenharmony_ci  V(FPDataProcessing2Source)                                     \
67b8021494Sopenharmony_ci  V(FPDataProcessing3Source)                                     \
68b8021494Sopenharmony_ci  V(FPFixedPointConvert)                                         \
69b8021494Sopenharmony_ci  V(FPImmediate)                                                 \
70b8021494Sopenharmony_ci  V(FPIntegerConvert)                                            \
71b8021494Sopenharmony_ci  V(LoadLiteral)                                                 \
72b8021494Sopenharmony_ci  V(LoadStoreExclusive)                                          \
73b8021494Sopenharmony_ci  V(LoadStorePAC)                                                \
74b8021494Sopenharmony_ci  V(LoadStorePairNonTemporal)                                    \
75b8021494Sopenharmony_ci  V(LoadStorePairOffset)                                         \
76b8021494Sopenharmony_ci  V(LoadStorePairPostIndex)                                      \
77b8021494Sopenharmony_ci  V(LoadStorePairPreIndex)                                       \
78b8021494Sopenharmony_ci  V(LoadStorePostIndex)                                          \
79b8021494Sopenharmony_ci  V(LoadStorePreIndex)                                           \
80b8021494Sopenharmony_ci  V(LoadStoreRCpcUnscaledOffset)                                 \
81b8021494Sopenharmony_ci  V(LoadStoreRegisterOffset)                                     \
82b8021494Sopenharmony_ci  V(LoadStoreUnscaledOffset)                                     \
83b8021494Sopenharmony_ci  V(LoadStoreUnsignedOffset)                                     \
84b8021494Sopenharmony_ci  V(LogicalImmediate)                                            \
85b8021494Sopenharmony_ci  V(LogicalShifted)                                              \
86b8021494Sopenharmony_ci  V(MoveWideImmediate)                                           \
87b8021494Sopenharmony_ci  V(NEON2RegMisc)                                                \
88b8021494Sopenharmony_ci  V(NEON2RegMiscFP16)                                            \
89b8021494Sopenharmony_ci  V(NEON3Different)                                              \
90b8021494Sopenharmony_ci  V(NEON3Same)                                                   \
91b8021494Sopenharmony_ci  V(NEON3SameExtra)                                              \
92b8021494Sopenharmony_ci  V(NEON3SameFP16)                                               \
93b8021494Sopenharmony_ci  V(NEONAcrossLanes)                                             \
94b8021494Sopenharmony_ci  V(NEONByIndexedElement)                                        \
95b8021494Sopenharmony_ci  V(NEONCopy)                                                    \
96b8021494Sopenharmony_ci  V(NEONExtract)                                                 \
97b8021494Sopenharmony_ci  V(NEONLoadStoreMultiStruct)                                    \
98b8021494Sopenharmony_ci  V(NEONLoadStoreMultiStructPostIndex)                           \
99b8021494Sopenharmony_ci  V(NEONLoadStoreSingleStruct)                                   \
100b8021494Sopenharmony_ci  V(NEONLoadStoreSingleStructPostIndex)                          \
101b8021494Sopenharmony_ci  V(NEONModifiedImmediate)                                       \
102b8021494Sopenharmony_ci  V(NEONPerm)                                                    \
103b8021494Sopenharmony_ci  V(NEONScalar2RegMisc)                                          \
104b8021494Sopenharmony_ci  V(NEONScalar2RegMiscFP16)                                      \
105b8021494Sopenharmony_ci  V(NEONScalar3Diff)                                             \
106b8021494Sopenharmony_ci  V(NEONScalar3Same)                                             \
107b8021494Sopenharmony_ci  V(NEONScalar3SameExtra)                                        \
108b8021494Sopenharmony_ci  V(NEONScalar3SameFP16)                                         \
109b8021494Sopenharmony_ci  V(NEONScalarByIndexedElement)                                  \
110b8021494Sopenharmony_ci  V(NEONScalarCopy)                                              \
111b8021494Sopenharmony_ci  V(NEONScalarPairwise)                                          \
112b8021494Sopenharmony_ci  V(NEONScalarShiftImmediate)                                    \
113b8021494Sopenharmony_ci  V(NEONShiftImmediate)                                          \
114b8021494Sopenharmony_ci  V(NEONTable)                                                   \
115b8021494Sopenharmony_ci  V(PCRelAddressing)                                             \
116b8021494Sopenharmony_ci  V(RotateRightIntoFlags)                                        \
117b8021494Sopenharmony_ci  V(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets)           \
118b8021494Sopenharmony_ci  V(SVE32BitGatherLoad_VectorPlusImm)                            \
119b8021494Sopenharmony_ci  V(SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets)    \
120b8021494Sopenharmony_ci  V(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets)        \
121b8021494Sopenharmony_ci  V(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets)         \
122b8021494Sopenharmony_ci  V(SVE32BitGatherPrefetch_VectorPlusImm)                        \
123b8021494Sopenharmony_ci  V(SVE32BitScatterStore_ScalarPlus32BitScaledOffsets)           \
124b8021494Sopenharmony_ci  V(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets)         \
125b8021494Sopenharmony_ci  V(SVE32BitScatterStore_VectorPlusImm)                          \
126b8021494Sopenharmony_ci  V(SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets)     \
127b8021494Sopenharmony_ci  V(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsets)             \
128b8021494Sopenharmony_ci  V(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets)           \
129b8021494Sopenharmony_ci  V(SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets)   \
130b8021494Sopenharmony_ci  V(SVE64BitGatherLoad_VectorPlusImm)                            \
131b8021494Sopenharmony_ci  V(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets)         \
132b8021494Sopenharmony_ci  V(SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets) \
133b8021494Sopenharmony_ci  V(SVE64BitGatherPrefetch_VectorPlusImm)                        \
134b8021494Sopenharmony_ci  V(SVE64BitScatterStore_ScalarPlus64BitScaledOffsets)           \
135b8021494Sopenharmony_ci  V(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets)         \
136b8021494Sopenharmony_ci  V(SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets)   \
137b8021494Sopenharmony_ci  V(SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets) \
138b8021494Sopenharmony_ci  V(SVE64BitScatterStore_VectorPlusImm)                          \
139b8021494Sopenharmony_ci  V(SVEAddressGeneration)                                        \
140b8021494Sopenharmony_ci  V(SVEBitwiseLogicalUnpredicated)                               \
141b8021494Sopenharmony_ci  V(SVEBitwiseShiftUnpredicated)                                 \
142b8021494Sopenharmony_ci  V(SVEFFRInitialise)                                            \
143b8021494Sopenharmony_ci  V(SVEFFRWriteFromPredicate)                                    \
144b8021494Sopenharmony_ci  V(SVEFPAccumulatingReduction)                                  \
145b8021494Sopenharmony_ci  V(SVEFPArithmeticUnpredicated)                                 \
146b8021494Sopenharmony_ci  V(SVEFPCompareVectors)                                         \
147b8021494Sopenharmony_ci  V(SVEFPCompareWithZero)                                        \
148b8021494Sopenharmony_ci  V(SVEFPComplexAddition)                                        \
149b8021494Sopenharmony_ci  V(SVEFPComplexMulAdd)                                          \
150b8021494Sopenharmony_ci  V(SVEFPComplexMulAddIndex)                                     \
151b8021494Sopenharmony_ci  V(SVEFPFastReduction)                                          \
152b8021494Sopenharmony_ci  V(SVEFPMulIndex)                                               \
153b8021494Sopenharmony_ci  V(SVEFPMulAdd)                                                 \
154b8021494Sopenharmony_ci  V(SVEFPMulAddIndex)                                            \
155b8021494Sopenharmony_ci  V(SVEFPUnaryOpUnpredicated)                                    \
156b8021494Sopenharmony_ci  V(SVEIncDecByPredicateCount)                                   \
157b8021494Sopenharmony_ci  V(SVEIndexGeneration)                                          \
158b8021494Sopenharmony_ci  V(SVEIntArithmeticUnpredicated)                                \
159b8021494Sopenharmony_ci  V(SVEIntCompareSignedImm)                                      \
160b8021494Sopenharmony_ci  V(SVEIntCompareUnsignedImm)                                    \
161b8021494Sopenharmony_ci  V(SVEIntCompareVectors)                                        \
162b8021494Sopenharmony_ci  V(SVEIntMulAddPredicated)                                      \
163b8021494Sopenharmony_ci  V(SVEIntMulAddUnpredicated)                                    \
164b8021494Sopenharmony_ci  V(SVEIntReduction)                                             \
165b8021494Sopenharmony_ci  V(SVEIntUnaryArithmeticPredicated)                             \
166b8021494Sopenharmony_ci  V(SVEMovprfx)                                                  \
167b8021494Sopenharmony_ci  V(SVEMulIndex)                                                 \
168b8021494Sopenharmony_ci  V(SVEPermuteVectorExtract)                                     \
169b8021494Sopenharmony_ci  V(SVEPermuteVectorInterleaving)                                \
170b8021494Sopenharmony_ci  V(SVEPredicateCount)                                           \
171b8021494Sopenharmony_ci  V(SVEPredicateLogical)                                         \
172b8021494Sopenharmony_ci  V(SVEPropagateBreak)                                           \
173b8021494Sopenharmony_ci  V(SVEStackFrameAdjustment)                                     \
174b8021494Sopenharmony_ci  V(SVEStackFrameSize)                                           \
175b8021494Sopenharmony_ci  V(SVEVectorSelect)                                             \
176b8021494Sopenharmony_ci  V(SVEBitwiseLogical_Predicated)                                \
177b8021494Sopenharmony_ci  V(SVEBitwiseLogicalWithImm_Unpredicated)                       \
178b8021494Sopenharmony_ci  V(SVEBitwiseShiftByImm_Predicated)                             \
179b8021494Sopenharmony_ci  V(SVEBitwiseShiftByVector_Predicated)                          \
180b8021494Sopenharmony_ci  V(SVEBitwiseShiftByWideElements_Predicated)                    \
181b8021494Sopenharmony_ci  V(SVEBroadcastBitmaskImm)                                      \
182b8021494Sopenharmony_ci  V(SVEBroadcastFPImm_Unpredicated)                              \
183b8021494Sopenharmony_ci  V(SVEBroadcastGeneralRegister)                                 \
184b8021494Sopenharmony_ci  V(SVEBroadcastIndexElement)                                    \
185b8021494Sopenharmony_ci  V(SVEBroadcastIntImm_Unpredicated)                             \
186b8021494Sopenharmony_ci  V(SVECompressActiveElements)                                   \
187b8021494Sopenharmony_ci  V(SVEConditionallyBroadcastElementToVector)                    \
188b8021494Sopenharmony_ci  V(SVEConditionallyExtractElementToSIMDFPScalar)                \
189b8021494Sopenharmony_ci  V(SVEConditionallyExtractElementToGeneralRegister)             \
190b8021494Sopenharmony_ci  V(SVEConditionallyTerminateScalars)                            \
191b8021494Sopenharmony_ci  V(SVEConstructivePrefix_Unpredicated)                          \
192b8021494Sopenharmony_ci  V(SVEContiguousFirstFaultLoad_ScalarPlusScalar)                \
193b8021494Sopenharmony_ci  V(SVEContiguousLoad_ScalarPlusImm)                             \
194b8021494Sopenharmony_ci  V(SVEContiguousLoad_ScalarPlusScalar)                          \
195b8021494Sopenharmony_ci  V(SVEContiguousNonFaultLoad_ScalarPlusImm)                     \
196b8021494Sopenharmony_ci  V(SVEContiguousNonTemporalLoad_ScalarPlusImm)                  \
197b8021494Sopenharmony_ci  V(SVEContiguousNonTemporalLoad_ScalarPlusScalar)               \
198b8021494Sopenharmony_ci  V(SVEContiguousNonTemporalStore_ScalarPlusImm)                 \
199b8021494Sopenharmony_ci  V(SVEContiguousNonTemporalStore_ScalarPlusScalar)              \
200b8021494Sopenharmony_ci  V(SVEContiguousPrefetch_ScalarPlusImm)                         \
201b8021494Sopenharmony_ci  V(SVEContiguousPrefetch_ScalarPlusScalar)                      \
202b8021494Sopenharmony_ci  V(SVEContiguousStore_ScalarPlusImm)                            \
203b8021494Sopenharmony_ci  V(SVEContiguousStore_ScalarPlusScalar)                         \
204b8021494Sopenharmony_ci  V(SVECopySIMDFPScalarRegisterToVector_Predicated)              \
205b8021494Sopenharmony_ci  V(SVECopyFPImm_Predicated)                                     \
206b8021494Sopenharmony_ci  V(SVECopyGeneralRegisterToVector_Predicated)                   \
207b8021494Sopenharmony_ci  V(SVECopyIntImm_Predicated)                                    \
208b8021494Sopenharmony_ci  V(SVEElementCount)                                             \
209b8021494Sopenharmony_ci  V(SVEExtractElementToSIMDFPScalarRegister)                     \
210b8021494Sopenharmony_ci  V(SVEExtractElementToGeneralRegister)                          \
211b8021494Sopenharmony_ci  V(SVEFPArithmetic_Predicated)                                  \
212b8021494Sopenharmony_ci  V(SVEFPArithmeticWithImm_Predicated)                           \
213b8021494Sopenharmony_ci  V(SVEFPConvertPrecision)                                       \
214b8021494Sopenharmony_ci  V(SVEFPConvertToInt)                                           \
215b8021494Sopenharmony_ci  V(SVEFPExponentialAccelerator)                                 \
216b8021494Sopenharmony_ci  V(SVEFPRoundToIntegralValue)                                   \
217b8021494Sopenharmony_ci  V(SVEFPTrigMulAddCoefficient)                                  \
218b8021494Sopenharmony_ci  V(SVEFPTrigSelectCoefficient)                                  \
219b8021494Sopenharmony_ci  V(SVEFPUnaryOp)                                                \
220b8021494Sopenharmony_ci  V(SVEIncDecRegisterByElementCount)                             \
221b8021494Sopenharmony_ci  V(SVEIncDecVectorByElementCount)                               \
222b8021494Sopenharmony_ci  V(SVEInsertSIMDFPScalarRegister)                               \
223b8021494Sopenharmony_ci  V(SVEInsertGeneralRegister)                                    \
224b8021494Sopenharmony_ci  V(SVEIntAddSubtractImm_Unpredicated)                           \
225b8021494Sopenharmony_ci  V(SVEIntAddSubtractVectors_Predicated)                         \
226b8021494Sopenharmony_ci  V(SVEIntCompareScalarCountAndLimit)                            \
227b8021494Sopenharmony_ci  V(SVEIntConvertToFP)                                           \
228b8021494Sopenharmony_ci  V(SVEIntDivideVectors_Predicated)                              \
229b8021494Sopenharmony_ci  V(SVEIntMinMaxImm_Unpredicated)                                \
230b8021494Sopenharmony_ci  V(SVEIntMinMaxDifference_Predicated)                           \
231b8021494Sopenharmony_ci  V(SVEIntMulImm_Unpredicated)                                   \
232b8021494Sopenharmony_ci  V(SVEIntMulVectors_Predicated)                                 \
233b8021494Sopenharmony_ci  V(SVELoadAndBroadcastElement)                                  \
234b8021494Sopenharmony_ci  V(SVELoadAndBroadcastQOWord_ScalarPlusImm)                     \
235b8021494Sopenharmony_ci  V(SVELoadAndBroadcastQOWord_ScalarPlusScalar)                  \
236b8021494Sopenharmony_ci  V(SVELoadMultipleStructures_ScalarPlusImm)                     \
237b8021494Sopenharmony_ci  V(SVELoadMultipleStructures_ScalarPlusScalar)                  \
238b8021494Sopenharmony_ci  V(SVELoadPredicateRegister)                                    \
239b8021494Sopenharmony_ci  V(SVELoadVectorRegister)                                       \
240b8021494Sopenharmony_ci  V(SVEPartitionBreakCondition)                                  \
241b8021494Sopenharmony_ci  V(SVEPermutePredicateElements)                                 \
242b8021494Sopenharmony_ci  V(SVEPredicateFirstActive)                                     \
243b8021494Sopenharmony_ci  V(SVEPredicateInitialize)                                      \
244b8021494Sopenharmony_ci  V(SVEPredicateNextActive)                                      \
245b8021494Sopenharmony_ci  V(SVEPredicateReadFromFFR_Predicated)                          \
246b8021494Sopenharmony_ci  V(SVEPredicateReadFromFFR_Unpredicated)                        \
247b8021494Sopenharmony_ci  V(SVEPredicateTest)                                            \
248b8021494Sopenharmony_ci  V(SVEPredicateZero)                                            \
249b8021494Sopenharmony_ci  V(SVEPropagateBreakToNextPartition)                            \
250b8021494Sopenharmony_ci  V(SVEReversePredicateElements)                                 \
251b8021494Sopenharmony_ci  V(SVEReverseVectorElements)                                    \
252b8021494Sopenharmony_ci  V(SVEReverseWithinElements)                                    \
253b8021494Sopenharmony_ci  V(SVESaturatingIncDecRegisterByElementCount)                   \
254b8021494Sopenharmony_ci  V(SVESaturatingIncDecVectorByElementCount)                     \
255b8021494Sopenharmony_ci  V(SVEStoreMultipleStructures_ScalarPlusImm)                    \
256b8021494Sopenharmony_ci  V(SVEStoreMultipleStructures_ScalarPlusScalar)                 \
257b8021494Sopenharmony_ci  V(SVEStorePredicateRegister)                                   \
258b8021494Sopenharmony_ci  V(SVEStoreVectorRegister)                                      \
259b8021494Sopenharmony_ci  V(SVETableLookup)                                              \
260b8021494Sopenharmony_ci  V(SVEUnpackPredicateElements)                                  \
261b8021494Sopenharmony_ci  V(SVEUnpackVectorElements)                                     \
262b8021494Sopenharmony_ci  V(SVEVectorSplice)                                             \
263b8021494Sopenharmony_ci  V(System)                                                      \
264b8021494Sopenharmony_ci  V(TestBranch)                                                  \
265b8021494Sopenharmony_ci  V(Unallocated)                                                 \
266b8021494Sopenharmony_ci  V(UnconditionalBranch)                                         \
267b8021494Sopenharmony_ci  V(UnconditionalBranchToRegister)                               \
268b8021494Sopenharmony_ci  V(Unimplemented)
269b8021494Sopenharmony_ci
270b8021494Sopenharmony_ci#define VISITOR_LIST_THAT_DONT_RETURN(V) V(Reserved)
271b8021494Sopenharmony_ci
272b8021494Sopenharmony_ci#define VISITOR_LIST(V)       \
273b8021494Sopenharmony_ci  VISITOR_LIST_THAT_RETURN(V) \
274b8021494Sopenharmony_ci  VISITOR_LIST_THAT_DONT_RETURN(V)
275b8021494Sopenharmony_ci
276b8021494Sopenharmony_cinamespace vixl {
277b8021494Sopenharmony_cinamespace aarch64 {
278b8021494Sopenharmony_ci
279b8021494Sopenharmony_ciusing Metadata = std::map<std::string, std::string>;
280b8021494Sopenharmony_ci
281b8021494Sopenharmony_ci// The Visitor interface consists only of the Visit() method. User classes
282b8021494Sopenharmony_ci// that inherit from this one must provide an implementation of the method.
283b8021494Sopenharmony_ci// Information about the instruction encountered by the Decoder is available
284b8021494Sopenharmony_ci// via the metadata pointer.
285b8021494Sopenharmony_ciclass DecoderVisitor {
286b8021494Sopenharmony_ci public:
287b8021494Sopenharmony_ci  enum VisitorConstness { kConstVisitor, kNonConstVisitor };
288b8021494Sopenharmony_ci  explicit DecoderVisitor(VisitorConstness constness = kConstVisitor)
289b8021494Sopenharmony_ci      : constness_(constness) {}
290b8021494Sopenharmony_ci
291b8021494Sopenharmony_ci  virtual ~DecoderVisitor() {}
292b8021494Sopenharmony_ci
293b8021494Sopenharmony_ci  virtual void Visit(Metadata* metadata, const Instruction* instr) = 0;
294b8021494Sopenharmony_ci
295b8021494Sopenharmony_ci  bool IsConstVisitor() const { return constness_ == kConstVisitor; }
296b8021494Sopenharmony_ci  Instruction* MutableInstruction(const Instruction* instr) {
297b8021494Sopenharmony_ci    VIXL_ASSERT(!IsConstVisitor());
298b8021494Sopenharmony_ci    return const_cast<Instruction*>(instr);
299b8021494Sopenharmony_ci  }
300b8021494Sopenharmony_ci
301b8021494Sopenharmony_ci protected:
302b8021494Sopenharmony_ci  template <typename T>
303b8021494Sopenharmony_ci  using FormToVisitorFnMapT = std::unordered_map<
304b8021494Sopenharmony_ci      uint32_t,
305b8021494Sopenharmony_ci      std::function<void(T*, const Instruction*)>>;
306b8021494Sopenharmony_ci
307b8021494Sopenharmony_ci private:
308b8021494Sopenharmony_ci  const VisitorConstness constness_;
309b8021494Sopenharmony_ci};
310b8021494Sopenharmony_ci
311b8021494Sopenharmony_ciclass DecodeNode;
312b8021494Sopenharmony_ciclass CompiledDecodeNode;
313b8021494Sopenharmony_ci
314b8021494Sopenharmony_ci// The instruction decoder is constructed from a graph of decode nodes. At each
315b8021494Sopenharmony_ci// node, a number of bits are sampled from the instruction being decoded. The
316b8021494Sopenharmony_ci// resulting value is used to look up the next node in the graph, which then
317b8021494Sopenharmony_ci// samples other bits, and moves to other decode nodes. Eventually, a visitor
318b8021494Sopenharmony_ci// node is reached, and the corresponding visitor function is called, which
319b8021494Sopenharmony_ci// handles the instruction.
320b8021494Sopenharmony_ciclass Decoder {
321b8021494Sopenharmony_ci public:
322b8021494Sopenharmony_ci#ifndef PANDA_BUILD
323b8021494Sopenharmony_ci  Decoder() { ConstructDecodeGraph(); }
324b8021494Sopenharmony_ci#else
325b8021494Sopenharmony_ci  Decoder(AllocatorWrapper allocator) :
326b8021494Sopenharmony_ci      allocator_(allocator),
327b8021494Sopenharmony_ci      visitors_(allocator_.Adapter()),
328b8021494Sopenharmony_ci      decode_nodes_(allocator_.Adapter()) {
329b8021494Sopenharmony_ci    ConstructDecodeGraph();
330b8021494Sopenharmony_ci  }
331b8021494Sopenharmony_ci#endif
332b8021494Sopenharmony_ci
333b8021494Sopenharmony_ci  Decoder(const Decoder&) = delete;
334b8021494Sopenharmony_ci  Decoder(Decoder&&) = delete;
335b8021494Sopenharmony_ci  Decoder& operator=(const Decoder&) = delete;
336b8021494Sopenharmony_ci  Decoder& operator=(Decoder&&) = delete;
337b8021494Sopenharmony_ci
338b8021494Sopenharmony_ci  ~Decoder() = default;
339b8021494Sopenharmony_ci
340b8021494Sopenharmony_ci  auto GetAllocator() {
341b8021494Sopenharmony_ci    return allocator_;
342b8021494Sopenharmony_ci  }
343b8021494Sopenharmony_ci
344b8021494Sopenharmony_ci  // Top-level wrappers around the actual decoding function.
345b8021494Sopenharmony_ci  void Decode(const Instruction* instr);
346b8021494Sopenharmony_ci  void Decode(Instruction* instr);
347b8021494Sopenharmony_ci
348b8021494Sopenharmony_ci  // Decode all instructions from start (inclusive) to end (exclusive).
349b8021494Sopenharmony_ci  template <typename T>
350b8021494Sopenharmony_ci  void Decode(T start, T end) {
351b8021494Sopenharmony_ci    for (T instr = start; instr < end; instr = instr->GetNextInstruction()) {
352b8021494Sopenharmony_ci      Decode(instr);
353b8021494Sopenharmony_ci    }
354b8021494Sopenharmony_ci  }
355b8021494Sopenharmony_ci
356b8021494Sopenharmony_ci  // Register a new visitor class with the decoder.
357b8021494Sopenharmony_ci  // Decode() will call the corresponding visitor method from all registered
358b8021494Sopenharmony_ci  // visitor classes when decoding reaches the leaf node of the instruction
359b8021494Sopenharmony_ci  // decode tree.
360b8021494Sopenharmony_ci  // Visitors are called in order.
361b8021494Sopenharmony_ci  // A visitor can be registered multiple times.
362b8021494Sopenharmony_ci  //
363b8021494Sopenharmony_ci  //   d.AppendVisitor(V1);
364b8021494Sopenharmony_ci  //   d.AppendVisitor(V2);
365b8021494Sopenharmony_ci  //   d.PrependVisitor(V2);
366b8021494Sopenharmony_ci  //   d.AppendVisitor(V3);
367b8021494Sopenharmony_ci  //
368b8021494Sopenharmony_ci  //   d.Decode(i);
369b8021494Sopenharmony_ci  //
370b8021494Sopenharmony_ci  // will call in order visitor methods in V2, V1, V2, V3.
371b8021494Sopenharmony_ci  void AppendVisitor(DecoderVisitor* visitor);
372b8021494Sopenharmony_ci  void PrependVisitor(DecoderVisitor* visitor);
373b8021494Sopenharmony_ci  // These helpers register `new_visitor` before or after the first instance of
374b8021494Sopenharmony_ci  // `registered_visiter` in the list.
375b8021494Sopenharmony_ci  // So if
376b8021494Sopenharmony_ci  //   V1, V2, V1, V2
377b8021494Sopenharmony_ci  // are registered in this order in the decoder, calls to
378b8021494Sopenharmony_ci  //   d.InsertVisitorAfter(V3, V1);
379b8021494Sopenharmony_ci  //   d.InsertVisitorBefore(V4, V2);
380b8021494Sopenharmony_ci  // will yield the order
381b8021494Sopenharmony_ci  //   V1, V3, V4, V2, V1, V2
382b8021494Sopenharmony_ci  //
383b8021494Sopenharmony_ci  // For more complex modifications of the order of registered visitors, one can
384b8021494Sopenharmony_ci  // directly access and modify the list of visitors via the `visitors()'
385b8021494Sopenharmony_ci  // accessor.
386b8021494Sopenharmony_ci  void InsertVisitorBefore(DecoderVisitor* new_visitor,
387b8021494Sopenharmony_ci                           DecoderVisitor* registered_visitor);
388b8021494Sopenharmony_ci  void InsertVisitorAfter(DecoderVisitor* new_visitor,
389b8021494Sopenharmony_ci                          DecoderVisitor* registered_visitor);
390b8021494Sopenharmony_ci
391b8021494Sopenharmony_ci  // Remove all instances of a previously registered visitor class from the list
392b8021494Sopenharmony_ci  // of visitors stored by the decoder.
393b8021494Sopenharmony_ci  void RemoveVisitor(DecoderVisitor* visitor);
394b8021494Sopenharmony_ci
395b8021494Sopenharmony_ci  auto GetAllocator() const {
396b8021494Sopenharmony_ci    return allocator_;
397b8021494Sopenharmony_ci  }
398b8021494Sopenharmony_ci
399b8021494Sopenharmony_ci  class ScopedAddVisitors {
400b8021494Sopenharmony_ci   public:
401b8021494Sopenharmony_ci    ScopedAddVisitors(Decoder& decoder, std::initializer_list<DecoderVisitor*> visitors)
402b8021494Sopenharmony_ci      : visitors_(decoder.visitors_)
403b8021494Sopenharmony_ci      , old_end_(visitors_.insert(visitors_.end(), visitors)) {
404b8021494Sopenharmony_ci    }
405b8021494Sopenharmony_ci
406b8021494Sopenharmony_ci    ~ScopedAddVisitors() {
407b8021494Sopenharmony_ci      visitors_.erase(old_end_, visitors_.end());
408b8021494Sopenharmony_ci    }
409b8021494Sopenharmony_ci
410b8021494Sopenharmony_ci   private:
411b8021494Sopenharmony_ci    List<DecoderVisitor*>& visitors_;
412b8021494Sopenharmony_ci    List<DecoderVisitor*>::iterator old_end_;
413b8021494Sopenharmony_ci  };
414b8021494Sopenharmony_ci
415b8021494Sopenharmony_ci  void VisitNamedInstruction(const Instruction* instr, const std::string_view name);
416b8021494Sopenharmony_ci
417b8021494Sopenharmony_ci#ifndef PANDA_BUILD
418b8021494Sopenharmony_ci  std::list<DecoderVisitor*>* visitors() { return &visitors_; }
419b8021494Sopenharmony_ci#else
420b8021494Sopenharmony_ci  List<DecoderVisitor*>* visitors() { return &visitors_; }
421b8021494Sopenharmony_ci#endif
422b8021494Sopenharmony_ci
423b8021494Sopenharmony_ci  // Get a DecodeNode by name from the Decoder's map.
424b8021494Sopenharmony_ci  DecodeNode* GetDecodeNode(const String& name);
425b8021494Sopenharmony_ci
426b8021494Sopenharmony_ci private:
427b8021494Sopenharmony_ci  // Decodes an instruction and calls the visitor functions registered with the
428b8021494Sopenharmony_ci  // Decoder class.
429b8021494Sopenharmony_ci  void DecodeInstruction(const Instruction* instr);
430b8021494Sopenharmony_ci
431b8021494Sopenharmony_ci  // Add an initialised DecodeNode to the decode_node_ map.
432b8021494Sopenharmony_ci  void AddDecodeNode(const DecodeNode& node);
433b8021494Sopenharmony_ci
434b8021494Sopenharmony_ci  AllocatorWrapper allocator_;
435b8021494Sopenharmony_ci
436b8021494Sopenharmony_ci  // Visitors are registered in a list.
437b8021494Sopenharmony_ci  List<DecoderVisitor*> visitors_;
438b8021494Sopenharmony_ci  // Map of node names to DecodeNodes.
439b8021494Sopenharmony_ci  Map<String, DecodeNode> decode_nodes_;
440b8021494Sopenharmony_ci
441b8021494Sopenharmony_ci  // Compile the dynamically generated decode graph based on the static
442b8021494Sopenharmony_ci  // information in kDecodeMapping and kVisitorNodes.
443b8021494Sopenharmony_ci  void ConstructDecodeGraph();
444b8021494Sopenharmony_ci
445b8021494Sopenharmony_ci  // Root node for the compiled decoder graph, stored here to avoid a map lookup
446b8021494Sopenharmony_ci  // for every instruction decoded.
447b8021494Sopenharmony_ci  CompiledDecodeNode* compiled_decoder_root_;
448b8021494Sopenharmony_ci};
449b8021494Sopenharmony_ci
450b8021494Sopenharmony_citypedef void (Decoder::*DecodeFnPtr)(const Instruction*);
451b8021494Sopenharmony_citypedef uint32_t (Instruction::*BitExtractFn)(void) const;
452b8021494Sopenharmony_ci
453b8021494Sopenharmony_ci// A Visitor node maps the name of a visitor to the function that handles it.
454b8021494Sopenharmony_cistruct VisitorNode {
455b8021494Sopenharmony_ci  const char* name;
456b8021494Sopenharmony_ci  const DecodeFnPtr visitor_fn;
457b8021494Sopenharmony_ci};
458b8021494Sopenharmony_ci
459b8021494Sopenharmony_ci// DecodePattern and DecodeMapping represent the input data to the decoder
460b8021494Sopenharmony_ci// compilation stage. After compilation, the decoder is embodied in the graph
461b8021494Sopenharmony_ci// of CompiledDecodeNodes pointer to by compiled_decoder_root_.
462b8021494Sopenharmony_ci
463b8021494Sopenharmony_ci// A DecodePattern maps a pattern of set/unset/don't care (1, 0, x) bits encoded
464b8021494Sopenharmony_ci// as uint32_t to its handler.
465b8021494Sopenharmony_ci// The encoding uses two bits per symbol: 0 => 0b00, 1 => 0b01, x => 0b10.
466b8021494Sopenharmony_ci// 0b11 marks the edge of the most-significant bits of the pattern, which is
467b8021494Sopenharmony_ci// required to determine the length. For example, the pattern "1x01"_b is
468b8021494Sopenharmony_ci// encoded in a uint32_t as 0b11_01_10_00_01.
469b8021494Sopenharmony_cistruct DecodePattern {
470b8021494Sopenharmony_ci  uint32_t pattern;
471b8021494Sopenharmony_ci  const char* handler;
472b8021494Sopenharmony_ci};
473b8021494Sopenharmony_ci
474b8021494Sopenharmony_ci// A DecodeMapping consists of the name of a handler, the bits sampled in the
475b8021494Sopenharmony_ci// instruction by that handler, and a mapping from the pattern that those
476b8021494Sopenharmony_ci// sampled bits match to the corresponding name of a node.
477b8021494Sopenharmony_cistruct DecodeMapping {
478b8021494Sopenharmony_ci  const char* name;
479b8021494Sopenharmony_ci  const std::vector<uint8_t> sampled_bits;
480b8021494Sopenharmony_ci  const std::vector<DecodePattern> mapping;
481b8021494Sopenharmony_ci};
482b8021494Sopenharmony_ci
483b8021494Sopenharmony_ci// For speed, before nodes can be used for decoding instructions, they must
484b8021494Sopenharmony_ci// be compiled. This converts the mapping "bit pattern strings to decoder name
485b8021494Sopenharmony_ci// string" stored in DecodeNodes to an array look up for the pointer to the next
486b8021494Sopenharmony_ci// node, stored in CompiledDecodeNodes. Compilation may also apply other
487b8021494Sopenharmony_ci// optimisations for simple decode patterns.
488b8021494Sopenharmony_ciclass CompiledDecodeNode {
489b8021494Sopenharmony_ci public:
490b8021494Sopenharmony_ci  // Constructor for decode node, containing a decode table and pointer to a
491b8021494Sopenharmony_ci  // function that extracts the bits to be sampled.
492b8021494Sopenharmony_ci#ifndef PANDA_BUILD
493b8021494Sopenharmony_ci  CompiledDecodeNode(BitExtractFn bit_extract_fn, size_t decode_table_size)
494b8021494Sopenharmony_ci#else
495b8021494Sopenharmony_ci  CompiledDecodeNode(BitExtractFn bit_extract_fn, size_t decode_table_size, AllocatorWrapper allocator)
496b8021494Sopenharmony_ci#endif
497b8021494Sopenharmony_ci      : bit_extract_fn_(bit_extract_fn),
498b8021494Sopenharmony_ci        instruction_name_("node"),
499b8021494Sopenharmony_ci        decode_table_size_(decode_table_size),
500b8021494Sopenharmony_ci        decoder_(NULL) {
501b8021494Sopenharmony_ci#ifndef PANDA_BUILD
502b8021494Sopenharmony_ci    decode_table_ = new CompiledDecodeNode*[decode_table_size_];
503b8021494Sopenharmony_ci#else
504b8021494Sopenharmony_ci    decode_table_ = allocator.New<CompiledDecodeNode*[]>(decode_table_size_);
505b8021494Sopenharmony_ci#endif
506b8021494Sopenharmony_ci    memset(decode_table_, 0, decode_table_size_ * sizeof(decode_table_[0]));
507b8021494Sopenharmony_ci  }
508b8021494Sopenharmony_ci
509b8021494Sopenharmony_ci  // Constructor for wrappers around visitor functions. These require no
510b8021494Sopenharmony_ci  // decoding, so no bit extraction function or decode table is assigned.
511b8021494Sopenharmony_ci  explicit CompiledDecodeNode(const std::string_view iname, Decoder* decoder)
512b8021494Sopenharmony_ci      : bit_extract_fn_(NULL),
513b8021494Sopenharmony_ci        instruction_name_(iname),
514b8021494Sopenharmony_ci        decode_table_(NULL),
515b8021494Sopenharmony_ci        decode_table_size_(0),
516b8021494Sopenharmony_ci        decoder_(decoder) {}
517b8021494Sopenharmony_ci
518b8021494Sopenharmony_ci  ~CompiledDecodeNode() VIXL_NEGATIVE_TESTING_ALLOW_EXCEPTION {
519b8021494Sopenharmony_ci    // Free the decode table, if this is a compiled, non-leaf node.
520b8021494Sopenharmony_ci    if (decode_table_ != NULL) {
521b8021494Sopenharmony_ci      VIXL_ASSERT(!IsLeafNode());
522b8021494Sopenharmony_ci#ifndef VIXL_USE_PANDA_ALLOC
523b8021494Sopenharmony_ci      delete[] decode_table_;
524b8021494Sopenharmony_ci#endif
525b8021494Sopenharmony_ci    }
526b8021494Sopenharmony_ci  }
527b8021494Sopenharmony_ci
528b8021494Sopenharmony_ci  // Decode the instruction by either sampling the bits using the bit extract
529b8021494Sopenharmony_ci  // function to find the next node, or, if we're at a leaf, calling the visitor
530b8021494Sopenharmony_ci  // function.
531b8021494Sopenharmony_ci  void Decode(const Instruction* instr) const;
532b8021494Sopenharmony_ci
533b8021494Sopenharmony_ci  // A leaf node is a wrapper for a visitor function.
534b8021494Sopenharmony_ci  bool IsLeafNode() const {
535b8021494Sopenharmony_ci    VIXL_ASSERT(((instruction_name_ == "node") && (bit_extract_fn_ != NULL)) ||
536b8021494Sopenharmony_ci                ((instruction_name_ != "node") && (bit_extract_fn_ == NULL)));
537b8021494Sopenharmony_ci    return instruction_name_ != "node";
538b8021494Sopenharmony_ci  }
539b8021494Sopenharmony_ci
540b8021494Sopenharmony_ci  // Get a pointer to the next node required in the decode process, based on the
541b8021494Sopenharmony_ci  // bits sampled by the current node.
542b8021494Sopenharmony_ci  CompiledDecodeNode* GetNodeForBits(uint32_t bits) const {
543b8021494Sopenharmony_ci    VIXL_ASSERT(bits < decode_table_size_);
544b8021494Sopenharmony_ci    return decode_table_[bits];
545b8021494Sopenharmony_ci  }
546b8021494Sopenharmony_ci
547b8021494Sopenharmony_ci  // Set the next node in the decode process for the pattern of sampled bits in
548b8021494Sopenharmony_ci  // the current node.
549b8021494Sopenharmony_ci  void SetNodeForBits(uint32_t bits, CompiledDecodeNode* n) {
550b8021494Sopenharmony_ci    VIXL_ASSERT(bits < decode_table_size_);
551b8021494Sopenharmony_ci    VIXL_ASSERT(n != NULL);
552b8021494Sopenharmony_ci    decode_table_[bits] = n;
553b8021494Sopenharmony_ci  }
554b8021494Sopenharmony_ci
555b8021494Sopenharmony_ci private:
556b8021494Sopenharmony_ci  // Pointer to an instantiated template function for extracting the bits
557b8021494Sopenharmony_ci  // sampled by this node. Set to NULL for leaf nodes.
558b8021494Sopenharmony_ci  const BitExtractFn bit_extract_fn_;
559b8021494Sopenharmony_ci
560b8021494Sopenharmony_ci  // Visitor function that handles the instruction identified. Set only for
561b8021494Sopenharmony_ci  // leaf nodes, where no extra decoding is required, otherwise NULL.
562b8021494Sopenharmony_ci  std::string_view instruction_name_;
563b8021494Sopenharmony_ci
564b8021494Sopenharmony_ci  // Mapping table from instruction bits to next decode stage.
565b8021494Sopenharmony_ci  CompiledDecodeNode** decode_table_;
566b8021494Sopenharmony_ci  const size_t decode_table_size_;
567b8021494Sopenharmony_ci
568b8021494Sopenharmony_ci  // Pointer to the decoder containing this node, used to call its visitor
569b8021494Sopenharmony_ci  // function for leaf nodes. Set to NULL for non-leaf nodes.
570b8021494Sopenharmony_ci  Decoder* decoder_;
571b8021494Sopenharmony_ci};
572b8021494Sopenharmony_ci
573b8021494Sopenharmony_ciclass DecodeNode {
574b8021494Sopenharmony_ci public:
575b8021494Sopenharmony_ci  // Constructor for DecodeNode wrappers around visitor functions. These are
576b8021494Sopenharmony_ci  // marked as "compiled", as there is no decoding left to do.
577b8021494Sopenharmony_ci  explicit DecodeNode(const std::string_view iname, Decoder* decoder)
578b8021494Sopenharmony_ci      :
579b8021494Sopenharmony_ci#ifdef PANDA_BUILD
580b8021494Sopenharmony_ci        allocator_(decoder->GetAllocator()),
581b8021494Sopenharmony_ci#endif
582b8021494Sopenharmony_ci        name_(iname, allocator_.Adapter()),
583b8021494Sopenharmony_ci        sampled_bits_(kEmptySampledBits),
584b8021494Sopenharmony_ci        instruction_name_(iname),
585b8021494Sopenharmony_ci        pattern_table_(kEmptyPatternTable),
586b8021494Sopenharmony_ci        decoder_(decoder),
587b8021494Sopenharmony_ci        compiled_node_(NULL) {}
588b8021494Sopenharmony_ci
589b8021494Sopenharmony_ci  // Constructor for DecodeNodes that map bit patterns to other DecodeNodes.
590b8021494Sopenharmony_ci  explicit DecodeNode(const DecodeMapping& map, Decoder* decoder)
591b8021494Sopenharmony_ci      :
592b8021494Sopenharmony_ci#ifdef PANDA_BUILD
593b8021494Sopenharmony_ci        allocator_(decoder->GetAllocator()),
594b8021494Sopenharmony_ci#endif
595b8021494Sopenharmony_ci        name_(map.name, allocator_.Adapter()),
596b8021494Sopenharmony_ci        sampled_bits_(map.sampled_bits),
597b8021494Sopenharmony_ci        instruction_name_("node"),
598b8021494Sopenharmony_ci        pattern_table_(map.mapping),
599b8021494Sopenharmony_ci        decoder_(decoder),
600b8021494Sopenharmony_ci        compiled_node_(NULL) {
601b8021494Sopenharmony_ci    // With the current two bits per symbol encoding scheme, the maximum pattern
602b8021494Sopenharmony_ci    // length is (32 - 2) / 2 = 15 bits.
603b8021494Sopenharmony_ci    VIXL_CHECK(GetPatternLength(map.mapping[0].pattern) <= 15);
604b8021494Sopenharmony_ci    for (const DecodePattern& p : map.mapping) {
605b8021494Sopenharmony_ci      VIXL_CHECK(GetPatternLength(p.pattern) == map.sampled_bits.size());
606b8021494Sopenharmony_ci    }
607b8021494Sopenharmony_ci  }
608b8021494Sopenharmony_ci
609b8021494Sopenharmony_ci  ~DecodeNode() {
610b8021494Sopenharmony_ci#ifndef VIXL_USE_PANDA_ALLOC
611b8021494Sopenharmony_ci    // Delete the compiled version of this node, if one was created.
612b8021494Sopenharmony_ci    if (compiled_node_ != NULL) {
613b8021494Sopenharmony_ci      delete compiled_node_;
614b8021494Sopenharmony_ci    }
615b8021494Sopenharmony_ci#endif
616b8021494Sopenharmony_ci  }
617b8021494Sopenharmony_ci
618b8021494Sopenharmony_ci  auto GetAllocator() const {
619b8021494Sopenharmony_ci    return allocator_;
620b8021494Sopenharmony_ci  }
621b8021494Sopenharmony_ci
622b8021494Sopenharmony_ci  // Get the bits sampled from the instruction by this node.
623b8021494Sopenharmony_ci  const std::vector<uint8_t>& GetSampledBits() const { return sampled_bits_; }
624b8021494Sopenharmony_ci
625b8021494Sopenharmony_ci  // Get the number of bits sampled from the instruction by this node.
626b8021494Sopenharmony_ci  size_t GetSampledBitsCount() const { return sampled_bits_.size(); }
627b8021494Sopenharmony_ci
628b8021494Sopenharmony_ci  // A leaf node is a DecodeNode that wraps the visitor function for the
629b8021494Sopenharmony_ci  // identified instruction class.
630b8021494Sopenharmony_ci  bool IsLeafNode() const { return instruction_name_ != "node"; }
631b8021494Sopenharmony_ci
632b8021494Sopenharmony_ci  const String& GetName() const { return name_; }
633b8021494Sopenharmony_ci
634b8021494Sopenharmony_ci  // Create a CompiledDecodeNode of specified table size that uses
635b8021494Sopenharmony_ci  // bit_extract_fn to sample bits from the instruction.
636b8021494Sopenharmony_ci  void CreateCompiledNode(BitExtractFn bit_extract_fn, size_t table_size) {
637b8021494Sopenharmony_ci    VIXL_ASSERT(bit_extract_fn != NULL);
638b8021494Sopenharmony_ci    VIXL_ASSERT(table_size > 0);
639b8021494Sopenharmony_ci#ifndef PANDA_BUILD
640b8021494Sopenharmony_ci    compiled_node_ = new CompiledDecodeNode(bit_extract_fn, table_size);
641b8021494Sopenharmony_ci#else
642b8021494Sopenharmony_ci    auto allocator{decoder_->GetAllocator()};
643b8021494Sopenharmony_ci    compiled_node_ = allocator.New<CompiledDecodeNode>(bit_extract_fn, table_size, allocator);
644b8021494Sopenharmony_ci#endif
645b8021494Sopenharmony_ci  }
646b8021494Sopenharmony_ci
647b8021494Sopenharmony_ci  // Create a CompiledDecodeNode wrapping a visitor function. No decoding is
648b8021494Sopenharmony_ci  // required for this node; the visitor function is called instead.
649b8021494Sopenharmony_ci  void CreateVisitorNode() {
650b8021494Sopenharmony_ci#ifndef PANDA_BUILD
651b8021494Sopenharmony_ci    compiled_node_ = new CompiledDecodeNode(instruction_name_, decoder_);
652b8021494Sopenharmony_ci#else
653b8021494Sopenharmony_ci    auto allocator{decoder_->GetAllocator()};
654b8021494Sopenharmony_ci    compiled_node_ = allocator.New<CompiledDecodeNode>(instruction_name_, decoder_);
655b8021494Sopenharmony_ci#endif
656b8021494Sopenharmony_ci  }
657b8021494Sopenharmony_ci
658b8021494Sopenharmony_ci  // Find and compile the DecodeNode named "name", and set it as the node for
659b8021494Sopenharmony_ci  // the pattern "bits".
660b8021494Sopenharmony_ci  void CompileNodeForBits(Decoder* decoder, const String& name, uint32_t bits);
661b8021494Sopenharmony_ci
662b8021494Sopenharmony_ci  // Get a pointer to an instruction method that extracts the instruction bits
663b8021494Sopenharmony_ci  // specified by the mask argument, and returns those sampled bits as a
664b8021494Sopenharmony_ci  // contiguous sequence, suitable for indexing an array.
665b8021494Sopenharmony_ci  // For example, a mask of 0b1010 returns a function that, given an instruction
666b8021494Sopenharmony_ci  // 0bXYZW, will return 0bXZ.
667b8021494Sopenharmony_ci  BitExtractFn GetBitExtractFunction(uint32_t mask) {
668b8021494Sopenharmony_ci    return GetBitExtractFunctionHelper(mask, 0);
669b8021494Sopenharmony_ci  }
670b8021494Sopenharmony_ci
671b8021494Sopenharmony_ci  // Get a pointer to an Instruction method that applies a mask to the
672b8021494Sopenharmony_ci  // instruction bits, and tests if the result is equal to value. The returned
673b8021494Sopenharmony_ci  // function gives a 1 result if (inst & mask == value), 0 otherwise.
674b8021494Sopenharmony_ci  BitExtractFn GetBitExtractFunction(uint32_t mask, uint32_t value) {
675b8021494Sopenharmony_ci    return GetBitExtractFunctionHelper(value, mask);
676b8021494Sopenharmony_ci  }
677b8021494Sopenharmony_ci
678b8021494Sopenharmony_ci  // Compile this DecodeNode into a new CompiledDecodeNode and returns a pointer
679b8021494Sopenharmony_ci  // to it. This pointer is also stored inside the DecodeNode itself. Destroying
680b8021494Sopenharmony_ci  // a DecodeNode frees its associated CompiledDecodeNode.
681b8021494Sopenharmony_ci  CompiledDecodeNode* Compile(Decoder* decoder);
682b8021494Sopenharmony_ci
683b8021494Sopenharmony_ci  // Get a pointer to the CompiledDecodeNode associated with this DecodeNode.
684b8021494Sopenharmony_ci  // Returns NULL if the node has not been compiled yet.
685b8021494Sopenharmony_ci  CompiledDecodeNode* GetCompiledNode() const { return compiled_node_; }
686b8021494Sopenharmony_ci  bool IsCompiled() const { return GetCompiledNode() != NULL; }
687b8021494Sopenharmony_ci
688b8021494Sopenharmony_ci  enum class PatternSymbol { kSymbol0 = 0, kSymbol1 = 1, kSymbolX = 2 };
689b8021494Sopenharmony_ci  static const uint32_t kEndOfPattern = 3;
690b8021494Sopenharmony_ci  static const uint32_t kPatternSymbolMask = 3;
691b8021494Sopenharmony_ci
692b8021494Sopenharmony_ci  size_t GetPatternLength(uint32_t pattern) const {
693b8021494Sopenharmony_ci    uint32_t hsb = HighestSetBitPosition(pattern);
694b8021494Sopenharmony_ci    // The pattern length is signified by two set bits in a two bit-aligned
695b8021494Sopenharmony_ci    // position. Ensure that the pattern has a highest set bit, it's at an odd
696b8021494Sopenharmony_ci    // bit position, and that the bit to the right of the hsb is also set.
697b8021494Sopenharmony_ci    VIXL_ASSERT(((hsb % 2) == 1) && (pattern >> (hsb - 1)) == kEndOfPattern);
698b8021494Sopenharmony_ci    return hsb / 2;
699b8021494Sopenharmony_ci  }
700b8021494Sopenharmony_ci
701b8021494Sopenharmony_ci  bool PatternContainsSymbol(uint32_t pattern, PatternSymbol symbol) const {
702b8021494Sopenharmony_ci    while ((pattern & kPatternSymbolMask) != kEndOfPattern) {
703b8021494Sopenharmony_ci      if (static_cast<PatternSymbol>(pattern & kPatternSymbolMask) == symbol)
704b8021494Sopenharmony_ci        return true;
705b8021494Sopenharmony_ci      pattern >>= 2;
706b8021494Sopenharmony_ci    }
707b8021494Sopenharmony_ci    return false;
708b8021494Sopenharmony_ci  }
709b8021494Sopenharmony_ci
710b8021494Sopenharmony_ci  PatternSymbol GetSymbolAt(uint32_t pattern, size_t pos) const {
711b8021494Sopenharmony_ci    size_t len = GetPatternLength(pattern);
712b8021494Sopenharmony_ci    VIXL_ASSERT((pos < 15) && (pos < len));
713b8021494Sopenharmony_ci    uint32_t shift = static_cast<uint32_t>(2 * (len - pos - 1));
714b8021494Sopenharmony_ci    uint32_t sym = (pattern >> shift) & kPatternSymbolMask;
715b8021494Sopenharmony_ci    return static_cast<PatternSymbol>(sym);
716b8021494Sopenharmony_ci  }
717b8021494Sopenharmony_ci
718b8021494Sopenharmony_ci private:
719b8021494Sopenharmony_ci  // Generate a mask and value pair from a pattern constructed from 0, 1 and x
720b8021494Sopenharmony_ci  // (don't care) 2-bit symbols.
721b8021494Sopenharmony_ci  // For example "10x1"_b should return mask = 0b1101, value = 0b1001.
722b8021494Sopenharmony_ci  typedef std::pair<Instr, Instr> MaskValuePair;
723b8021494Sopenharmony_ci  MaskValuePair GenerateMaskValuePair(uint32_t pattern) const;
724b8021494Sopenharmony_ci
725b8021494Sopenharmony_ci  // Generate a pattern ordered by the bit positions sampled by this node.
726b8021494Sopenharmony_ci  // The symbol corresponding to the lowest sample position is placed in the
727b8021494Sopenharmony_ci  // least-significant bits of the result pattern.
728b8021494Sopenharmony_ci  // For example, a pattern of "1x0"_b expected when sampling bits 31, 1 and 30
729b8021494Sopenharmony_ci  // returns the pattern "x01"_b; bit 1 should be 'x', bit 30 '0' and bit 31
730b8021494Sopenharmony_ci  // '1'.
731b8021494Sopenharmony_ci  // This output makes comparisons easier between the pattern and bits sampled
732b8021494Sopenharmony_ci  // from an instruction using the fast "compress" algorithm. See
733b8021494Sopenharmony_ci  // Instruction::Compress().
734b8021494Sopenharmony_ci  uint32_t GenerateOrderedPattern(uint32_t pattern) const;
735b8021494Sopenharmony_ci
736b8021494Sopenharmony_ci  // Generate a mask with a bit set at each sample position.
737b8021494Sopenharmony_ci  uint32_t GenerateSampledBitsMask() const;
738b8021494Sopenharmony_ci
739b8021494Sopenharmony_ci  // Try to compile a more optimised decode operation for this node, returning
740b8021494Sopenharmony_ci  // true if successful.
741b8021494Sopenharmony_ci  bool TryCompileOptimisedDecodeTable(Decoder* decoder);
742b8021494Sopenharmony_ci
743b8021494Sopenharmony_ci  // Helper function that returns a bit extracting function. If y is zero,
744b8021494Sopenharmony_ci  // x is a bit extraction mask. Otherwise, y is the mask, and x is the value
745b8021494Sopenharmony_ci  // to match after masking.
746b8021494Sopenharmony_ci  BitExtractFn GetBitExtractFunctionHelper(uint32_t x, uint32_t y);
747b8021494Sopenharmony_ci
748b8021494Sopenharmony_ci  AllocatorWrapper allocator_;
749b8021494Sopenharmony_ci
750b8021494Sopenharmony_ci  // Name of this decoder node, used to construct edges in the decode graph.
751b8021494Sopenharmony_ci  String name_;
752b8021494Sopenharmony_ci
753b8021494Sopenharmony_ci  // Vector of bits sampled from an instruction to determine which node to look
754b8021494Sopenharmony_ci  // up next in the decode process.
755b8021494Sopenharmony_ci  const std::vector<uint8_t>& sampled_bits_;
756b8021494Sopenharmony_ci  static const std::vector<uint8_t> kEmptySampledBits;
757b8021494Sopenharmony_ci
758b8021494Sopenharmony_ci  // For leaf nodes, this is the name of the instruction form that the node
759b8021494Sopenharmony_ci  // represents. For other nodes, this is always set to "node".
760b8021494Sopenharmony_ci  std::string_view instruction_name_;
761b8021494Sopenharmony_ci
762b8021494Sopenharmony_ci  // Source mapping from bit pattern to name of next decode stage.
763b8021494Sopenharmony_ci  const std::vector<DecodePattern>& pattern_table_;
764b8021494Sopenharmony_ci  static const std::vector<DecodePattern> kEmptyPatternTable;
765b8021494Sopenharmony_ci
766b8021494Sopenharmony_ci  // Pointer to the decoder containing this node, used to call its visitor
767b8021494Sopenharmony_ci  // function for leaf nodes.
768b8021494Sopenharmony_ci  Decoder* decoder_;
769b8021494Sopenharmony_ci
770b8021494Sopenharmony_ci  // Pointer to the compiled version of this node. Is this node hasn't been
771b8021494Sopenharmony_ci  // compiled yet, this pointer is NULL.
772b8021494Sopenharmony_ci  CompiledDecodeNode* compiled_node_;
773b8021494Sopenharmony_ci};
774b8021494Sopenharmony_ci
775b8021494Sopenharmony_ci}  // namespace aarch64
776b8021494Sopenharmony_ci}  // namespace vixl
777b8021494Sopenharmony_ci
778b8021494Sopenharmony_ci#endif  // VIXL_AARCH64_DECODER_AARCH64_H_
779