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