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 #include "decoder-aarch64.h" 36 #include "decoder-visitor-map-aarch64.h" 37 38 namespace vixl { 39 namespace aarch64 { 40 41 // This visitor records the CPU features that each decoded instruction requires. 42 // It provides: 43 // - the set of CPU features required by the most recently decoded instruction, 44 // - a cumulative set of encountered CPU features, 45 // - an optional list of 'available' CPU features. 46 // 47 // Primarily, this allows the Disassembler and Simulator to share the same CPU 48 // features logic. However, it can be used standalone to scan code blocks for 49 // CPU features. 50 class CPUFeaturesAuditor : public DecoderVisitor { 51 public: 52 // Construction arguments: 53 // - If a decoder is specified, the CPUFeaturesAuditor automatically 54 // registers itself as a visitor. Otherwise, this can be done manually. 55 // 56 // - If an `available` features list is provided, it is used as a hint in 57 // cases where instructions may be provided by multiple separate features. 58 // An example of this is FP&SIMD loads and stores: some of these are used 59 // in both FP and integer SIMD code. If exactly one of those features is 60 // in `available` when one of these instructions is encountered, then the 61 // auditor will record that feature. Otherwise, it will record _both_ 62 // features. 63 explicit CPUFeaturesAuditor( 64 Decoder* decoder, const CPUFeatures& available = CPUFeatures::None()) available_(available)65 : available_(available), decoder_(decoder) { 66 if (decoder_ != NULL) decoder_->AppendVisitor(this); 67 } 68 69 explicit CPUFeaturesAuditor( 70 const CPUFeatures& available = CPUFeatures::None()) available_(available)71 : available_(available), decoder_(NULL) {} 72 ~CPUFeaturesAuditor()73 virtual ~CPUFeaturesAuditor() { 74 if (decoder_ != NULL) decoder_->RemoveVisitor(this); 75 } 76 ResetSeenFeatures()77 void ResetSeenFeatures() { 78 seen_ = CPUFeatures::None(); 79 last_instruction_ = CPUFeatures::None(); 80 } 81 82 // Query or set available CPUFeatures. GetAvailableFeatures()83 const CPUFeatures& GetAvailableFeatures() const { return available_; } SetAvailableFeatures(const CPUFeatures & available)84 void SetAvailableFeatures(const CPUFeatures& available) { 85 available_ = available; 86 } 87 88 // Query CPUFeatures seen since construction (or the last call to `Reset()`). GetSeenFeatures()89 const CPUFeatures& GetSeenFeatures() const { return seen_; } 90 91 // Query CPUFeatures from the last instruction visited by this auditor. GetInstructionFeatures()92 const CPUFeatures& GetInstructionFeatures() const { 93 return last_instruction_; 94 } 95 InstructionIsAvailable()96 bool InstructionIsAvailable() const { 97 return available_.Has(last_instruction_); 98 } 99 100 // The common CPUFeatures interface operates on the available_ list. GetCPUFeatures()101 CPUFeatures* GetCPUFeatures() { return &available_; } SetCPUFeatures(const CPUFeatures & available)102 void SetCPUFeatures(const CPUFeatures& available) { 103 SetAvailableFeatures(available); 104 } 105 106 virtual void Visit(Metadata* metadata, 107 const Instruction* instr) VIXL_OVERRIDE; 108 109 private: 110 class RecordInstructionFeaturesScope; 111 112 #define DECLARE(A) virtual void Visit##A(const Instruction* instr); 113 VISITOR_LIST(DECLARE) 114 #undef DECLARE 115 116 void LoadStoreHelper(const Instruction* instr); 117 void LoadStorePairHelper(const Instruction* instr); 118 119 CPUFeatures seen_; 120 CPUFeatures last_instruction_; 121 CPUFeatures available_; 122 123 Decoder* decoder_; 124 125 using FormToVisitorFnMap = FormToVisitorFnMapT<CPUFeaturesAuditor>; 126 127 static const FormToVisitorFnMap FORM_TO_VISITOR; 128 129 static const FormToVisitorFnMap* GetFormToVisitorFnMap(); 130 }; 131 132 } // namespace aarch64 133 } // namespace vixl 134 135 #endif // VIXL_AARCH64_CPU_FEATURES_AUDITOR_AARCH64_H_ 136