1 // Copyright 2018, VIXL authors 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are met: 6 // 7 // * Redistributions of source code must retain the above copyright notice, 8 // this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above copyright notice, 10 // this list of conditions and the following disclaimer in the documentation 11 // and/or other materials provided with the distribution. 12 // * Neither the name of Arm Limited nor the names of its contributors may be 13 // used to endorse or promote products derived from this software without 14 // specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27 #ifndef VIXL_AARCH64_CPU_FEATURES_AUDITOR_AARCH64_H_ 28 #define VIXL_AARCH64_CPU_FEATURES_AUDITOR_AARCH64_H_ 29 30 #include <functional> 31 #include <iostream> 32 #include <unordered_map> 33 34 #include "../cpu-features.h" 35 36 #include "decoder-aarch64.h" 37 #include "decoder-visitor-map-aarch64.h" 38 39 namespace vixl { 40 namespace aarch64 { 41 42 // This visitor records the CPU features that each decoded instruction requires. 43 // It provides: 44 // - the set of CPU features required by the most recently decoded instruction, 45 // - a cumulative set of encountered CPU features, 46 // - an optional list of 'available' CPU features. 47 // 48 // Primarily, this allows the Disassembler and Simulator to share the same CPU 49 // features logic. However, it can be used standalone to scan code blocks for 50 // CPU features. 51 class CPUFeaturesAuditor : public DecoderVisitor { 52 public: 53 // Construction arguments: 54 // - If a decoder is specified, the CPUFeaturesAuditor automatically 55 // registers itself as a visitor. Otherwise, this can be done manually. 56 // 57 // - If an `available` features list is provided, it is used as a hint in 58 // cases where instructions may be provided by multiple separate features. 59 // An example of this is FP&SIMD loads and stores: some of these are used 60 // in both FP and integer SIMD code. If exactly one of those features is 61 // in `available` when one of these instructions is encountered, then the 62 // auditor will record that feature. Otherwise, it will record _both_ 63 // features. 64 explicit CPUFeaturesAuditor( 65 Decoder* decoder, const CPUFeatures& available = CPUFeatures::None()) available_(available)66 : available_(available), decoder_(decoder) { 67 if (decoder_ != NULL) decoder_->AppendVisitor(this); 68 } 69 70 explicit CPUFeaturesAuditor( 71 const CPUFeatures& available = CPUFeatures::None()) available_(available)72 : available_(available), decoder_(NULL) {} 73 ~CPUFeaturesAuditor()74 virtual ~CPUFeaturesAuditor() { 75 if (decoder_ != NULL) decoder_->RemoveVisitor(this); 76 } 77 ResetSeenFeatures()78 void ResetSeenFeatures() { 79 seen_ = CPUFeatures::None(); 80 last_instruction_ = CPUFeatures::None(); 81 } 82 83 // Query or set available CPUFeatures. GetAvailableFeatures()84 const CPUFeatures& GetAvailableFeatures() const { return available_; } SetAvailableFeatures(const CPUFeatures & available)85 void SetAvailableFeatures(const CPUFeatures& available) { 86 available_ = available; 87 } 88 89 // Query CPUFeatures seen since construction (or the last call to `Reset()`). GetSeenFeatures()90 const CPUFeatures& GetSeenFeatures() const { return seen_; } 91 92 // Query CPUFeatures from the last instruction visited by this auditor. GetInstructionFeatures()93 const CPUFeatures& GetInstructionFeatures() const { 94 return last_instruction_; 95 } 96 InstructionIsAvailable()97 bool InstructionIsAvailable() const { 98 return available_.Has(last_instruction_); 99 } 100 101 // The common CPUFeatures interface operates on the available_ list. GetCPUFeatures()102 CPUFeatures* GetCPUFeatures() { return &available_; } SetCPUFeatures(const CPUFeatures & available)103 void SetCPUFeatures(const CPUFeatures& available) { 104 SetAvailableFeatures(available); 105 } 106 107 virtual void Visit(Metadata* metadata, 108 const Instruction* instr) VIXL_OVERRIDE; 109 110 private: 111 class RecordInstructionFeaturesScope; 112 113 #define DECLARE(A) virtual void Visit##A(const Instruction* instr); 114 VISITOR_LIST(DECLARE) 115 #undef DECLARE 116 void VisitCryptoSM3(const Instruction* instr); 117 void VisitCryptoSM4(const Instruction* instr); 118 119 void LoadStoreHelper(const Instruction* instr); 120 void LoadStorePairHelper(const Instruction* instr); 121 122 CPUFeatures seen_; 123 CPUFeatures last_instruction_; 124 CPUFeatures available_; 125 126 Decoder* decoder_; 127 128 using FormToVisitorFnMap = std::unordered_map< 129 uint32_t, 130 std::function<void(CPUFeaturesAuditor*, const Instruction*)>>; 131 static const FormToVisitorFnMap* GetFormToVisitorFnMap(); 132 uint32_t form_hash_; 133 }; 134 135 } // namespace aarch64 136 } // namespace vixl 137 138 #endif // VIXL_AARCH64_CPU_FEATURES_AUDITOR_AARCH64_H_ 139