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