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