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