xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1*0fca6ea1SDimitry Andric //===-- RegisterFlagsDetector_arm64.h ---------------------------*- C++ -*-===//
2*0fca6ea1SDimitry Andric //
3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0fca6ea1SDimitry Andric //
7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
8*0fca6ea1SDimitry Andric 
9*0fca6ea1SDimitry Andric #ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERFLAGSDETECTOR_ARM64_H
10*0fca6ea1SDimitry Andric #define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERFLAGSDETECTOR_ARM64_H
11*0fca6ea1SDimitry Andric 
12*0fca6ea1SDimitry Andric #include "lldb/Target/RegisterFlags.h"
13*0fca6ea1SDimitry Andric #include "llvm/ADT/StringRef.h"
14*0fca6ea1SDimitry Andric #include <functional>
15*0fca6ea1SDimitry Andric 
16*0fca6ea1SDimitry Andric namespace lldb_private {
17*0fca6ea1SDimitry Andric 
18*0fca6ea1SDimitry Andric struct RegisterInfo;
19*0fca6ea1SDimitry Andric 
20*0fca6ea1SDimitry Andric /// This class manages the storage and detection of register field information.
21*0fca6ea1SDimitry Andric /// The same register may have different fields on different CPUs. This class
22*0fca6ea1SDimitry Andric /// abstracts out the field detection process so we can use it on live processes
23*0fca6ea1SDimitry Andric /// and core files.
24*0fca6ea1SDimitry Andric ///
25*0fca6ea1SDimitry Andric /// The way to use this class is:
26*0fca6ea1SDimitry Andric /// * Make an instance somewhere that will last as long as the debug session
27*0fca6ea1SDimitry Andric ///   (because your final register info will point to this instance).
28*0fca6ea1SDimitry Andric /// * Read hardware capabilities from a core note, binary, prctl, etc.
29*0fca6ea1SDimitry Andric /// * Pass those to DetectFields.
30*0fca6ea1SDimitry Andric /// * Call UpdateRegisterInfo with your RegisterInfo to add pointers
31*0fca6ea1SDimitry Andric ///   to the detected fields for all registers listed in this class.
32*0fca6ea1SDimitry Andric ///
33*0fca6ea1SDimitry Andric /// This must be done in that order, and you should ensure that if multiple
34*0fca6ea1SDimitry Andric /// threads will reference the information, a mutex is used to make sure only
35*0fca6ea1SDimitry Andric /// one calls DetectFields.
36*0fca6ea1SDimitry Andric class Arm64RegisterFlagsDetector {
37*0fca6ea1SDimitry Andric public:
38*0fca6ea1SDimitry Andric   /// For the registers listed in this class, detect which fields are
39*0fca6ea1SDimitry Andric   /// present. Must be called before UpdateRegisterInfos.
40*0fca6ea1SDimitry Andric   /// If called more than once, fields will be redetected each time from
41*0fca6ea1SDimitry Andric   /// scratch. If the target would not have this register at all, the list of
42*0fca6ea1SDimitry Andric   /// fields will be left empty.
43*0fca6ea1SDimitry Andric   void DetectFields(uint64_t hwcap, uint64_t hwcap2);
44*0fca6ea1SDimitry Andric 
45*0fca6ea1SDimitry Andric   /// Add the field information of any registers named in this class,
46*0fca6ea1SDimitry Andric   /// to the relevant RegisterInfo instances. Note that this will be done
47*0fca6ea1SDimitry Andric   /// with a pointer to the instance of this class that you call this on, so
48*0fca6ea1SDimitry Andric   /// the lifetime of that instance must be at least that of the register info.
49*0fca6ea1SDimitry Andric   void UpdateRegisterInfo(const RegisterInfo *reg_info, uint32_t num_regs);
50*0fca6ea1SDimitry Andric 
51*0fca6ea1SDimitry Andric   /// Returns true if field detection has been run at least once.
52*0fca6ea1SDimitry Andric   bool HasDetected() const { return m_has_detected; }
53*0fca6ea1SDimitry Andric 
54*0fca6ea1SDimitry Andric private:
55*0fca6ea1SDimitry Andric   using Fields = std::vector<RegisterFlags::Field>;
56*0fca6ea1SDimitry Andric   using DetectorFn = std::function<Fields(uint64_t, uint64_t)>;
57*0fca6ea1SDimitry Andric 
58*0fca6ea1SDimitry Andric   static Fields DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2);
59*0fca6ea1SDimitry Andric   static Fields DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2);
60*0fca6ea1SDimitry Andric   static Fields DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2);
61*0fca6ea1SDimitry Andric   static Fields DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2);
62*0fca6ea1SDimitry Andric   static Fields DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2);
63*0fca6ea1SDimitry Andric 
64*0fca6ea1SDimitry Andric   struct RegisterEntry {
65*0fca6ea1SDimitry Andric     RegisterEntry(llvm::StringRef name, unsigned size, DetectorFn detector)
66*0fca6ea1SDimitry Andric         : m_name(name), m_flags(std::string(name) + "_flags", size, {}),
67*0fca6ea1SDimitry Andric           m_detector(detector) {}
68*0fca6ea1SDimitry Andric 
69*0fca6ea1SDimitry Andric     llvm::StringRef m_name;
70*0fca6ea1SDimitry Andric     RegisterFlags m_flags;
71*0fca6ea1SDimitry Andric     DetectorFn m_detector;
72*0fca6ea1SDimitry Andric   } m_registers[5] = {
73*0fca6ea1SDimitry Andric       RegisterEntry("cpsr", 4, DetectCPSRFields),
74*0fca6ea1SDimitry Andric       RegisterEntry("fpsr", 4, DetectFPSRFields),
75*0fca6ea1SDimitry Andric       RegisterEntry("fpcr", 4, DetectFPCRFields),
76*0fca6ea1SDimitry Andric       RegisterEntry("mte_ctrl", 8, DetectMTECtrlFields),
77*0fca6ea1SDimitry Andric       RegisterEntry("svcr", 8, DetectSVCRFields),
78*0fca6ea1SDimitry Andric   };
79*0fca6ea1SDimitry Andric 
80*0fca6ea1SDimitry Andric   // Becomes true once field detection has been run for all registers.
81*0fca6ea1SDimitry Andric   bool m_has_detected = false;
82*0fca6ea1SDimitry Andric };
83*0fca6ea1SDimitry Andric 
84*0fca6ea1SDimitry Andric } // namespace lldb_private
85*0fca6ea1SDimitry Andric 
86*0fca6ea1SDimitry Andric #endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERFLAGSDETECTOR_ARM64_H
87