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