[RISCV] Add RVVConstraint to SiFive custom matrix multiply instructions. (#124055)
[llvm-project.git] / lldb / source / Plugins / Process / Utility / RegisterFlagsDetector_arm64.cpp
blob9f82c935c0e7ed6df64a03b906195418d385520d
1 //===-- RegisterFlagsDetector_arm64.cpp -----------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
9 #include "RegisterFlagsDetector_arm64.h"
10 #include "lldb/lldb-private-types.h"
12 // This file is built on all systems because it is used by native processes and
13 // core files, so we manually define the needed HWCAP values here.
14 // These values are the same for Linux and FreeBSD.
16 #define HWCAP_FPHP (1ULL << 9)
17 #define HWCAP_ASIMDHP (1ULL << 10)
18 #define HWCAP_DIT (1ULL << 24)
19 #define HWCAP_SSBS (1ULL << 28)
21 #define HWCAP2_BTI (1ULL << 17)
22 #define HWCAP2_MTE (1ULL << 18)
23 #define HWCAP2_AFP (1ULL << 20)
24 #define HWCAP2_SME (1ULL << 23)
25 #define HWCAP2_EBF16 (1ULL << 32)
26 #define HWCAP2_FPMR (1ULL << 48)
28 using namespace lldb_private;
30 Arm64RegisterFlagsDetector::Fields
31 Arm64RegisterFlagsDetector::DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2) {
32 (void)hwcap;
34 if (!(hwcap2 & HWCAP2_FPMR))
35 return {};
37 static const FieldEnum fp8_format_enum("fp8_format_enum", {
38 {0, "FP8_E5M2"},
39 {1, "FP8_E4M3"},
40 });
41 return {
42 {"LSCALE2", 32, 37},
43 {"NSCALE", 24, 31},
44 {"LSCALE", 16, 22},
45 {"OSC", 15},
46 {"OSM", 14},
47 {"F8D", 6, 8, &fp8_format_enum},
48 {"F8S2", 3, 5, &fp8_format_enum},
49 {"F8S1", 0, 2, &fp8_format_enum},
53 Arm64RegisterFlagsDetector::Fields
54 Arm64RegisterFlagsDetector::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2) {
55 (void)hwcap;
57 if (!(hwcap2 & HWCAP2_SME))
58 return {};
60 // Represents the pseudo register that lldb-server builds, which itself
61 // matches the architectural register SCVR. The fields match SVCR in the Arm
62 // manual.
63 return {
64 {"ZA", 1},
65 {"SM", 0},
69 Arm64RegisterFlagsDetector::Fields
70 Arm64RegisterFlagsDetector::DetectMTECtrlFields(uint64_t hwcap,
71 uint64_t hwcap2) {
72 (void)hwcap;
74 if (!(hwcap2 & HWCAP2_MTE))
75 return {};
77 // Represents the contents of NT_ARM_TAGGED_ADDR_CTRL and the value passed
78 // to prctl(PR_TAGGED_ADDR_CTRL...). Fields are derived from the defines
79 // used to build the value.
81 static const FieldEnum tcf_enum(
82 "tcf_enum",
83 {{0, "TCF_NONE"}, {1, "TCF_SYNC"}, {2, "TCF_ASYNC"}, {3, "TCF_ASYMM"}});
84 return {{"TAGS", 3, 18}, // 16 bit bitfield shifted up by PR_MTE_TAG_SHIFT.
85 {"TCF", 1, 2, &tcf_enum},
86 {"TAGGED_ADDR_ENABLE", 0}};
89 Arm64RegisterFlagsDetector::Fields
90 Arm64RegisterFlagsDetector::DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2) {
91 static const FieldEnum rmode_enum(
92 "rmode_enum", {{0, "RN"}, {1, "RP"}, {2, "RM"}, {3, "RZ"}});
94 std::vector<RegisterFlags::Field> fpcr_fields{
95 {"AHP", 26}, {"DN", 25}, {"FZ", 24}, {"RMode", 22, 23, &rmode_enum},
96 // Bits 21-20 are "Stride" which is unused in AArch64 state.
99 // FEAT_FP16 is indicated by the presence of FPHP (floating point half
100 // precision) and ASIMDHP (Advanced SIMD half precision) features.
101 if ((hwcap & HWCAP_FPHP) && (hwcap & HWCAP_ASIMDHP))
102 fpcr_fields.push_back({"FZ16", 19});
104 // Bits 18-16 are "Len" which is unused in AArch64 state.
106 fpcr_fields.push_back({"IDE", 15});
108 // Bit 14 is unused.
109 if (hwcap2 & HWCAP2_EBF16)
110 fpcr_fields.push_back({"EBF", 13});
112 fpcr_fields.push_back({"IXE", 12});
113 fpcr_fields.push_back({"UFE", 11});
114 fpcr_fields.push_back({"OFE", 10});
115 fpcr_fields.push_back({"DZE", 9});
116 fpcr_fields.push_back({"IOE", 8});
117 // Bits 7-3 reserved.
119 if (hwcap2 & HWCAP2_AFP) {
120 fpcr_fields.push_back({"NEP", 2});
121 fpcr_fields.push_back({"AH", 1});
122 fpcr_fields.push_back({"FIZ", 0});
125 return fpcr_fields;
128 Arm64RegisterFlagsDetector::Fields
129 Arm64RegisterFlagsDetector::DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2) {
130 // fpsr's contents are constant.
131 (void)hwcap;
132 (void)hwcap2;
134 return {
135 // Bits 31-28 are N/Z/C/V, only used by AArch32.
136 {"QC", 27},
137 // Bits 26-8 reserved.
138 {"IDC", 7},
139 // Bits 6-5 reserved.
140 {"IXC", 4},
141 {"UFC", 3},
142 {"OFC", 2},
143 {"DZC", 1},
144 {"IOC", 0},
148 Arm64RegisterFlagsDetector::Fields
149 Arm64RegisterFlagsDetector::DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2) {
150 // The fields here are a combination of the Arm manual's SPSR_EL1,
151 // plus a few changes where Linux has decided not to make use of them at all,
152 // or at least not from userspace.
154 // Status bits that are always present.
155 std::vector<RegisterFlags::Field> cpsr_fields{
156 {"N", 31}, {"Z", 30}, {"C", 29}, {"V", 28},
157 // Bits 27-26 reserved.
160 if (hwcap2 & HWCAP2_MTE)
161 cpsr_fields.push_back({"TCO", 25});
162 if (hwcap & HWCAP_DIT)
163 cpsr_fields.push_back({"DIT", 24});
165 // UAO and PAN are bits 23 and 22 and have no meaning for userspace so
166 // are treated as reserved by the kernels.
168 cpsr_fields.push_back({"SS", 21});
169 cpsr_fields.push_back({"IL", 20});
170 // Bits 19-14 reserved.
172 // Bit 13, ALLINT, requires FEAT_NMI that isn't relevant to userspace, and we
173 // can't detect either, don't show this field.
174 if (hwcap & HWCAP_SSBS)
175 cpsr_fields.push_back({"SSBS", 12});
176 if (hwcap2 & HWCAP2_BTI)
177 cpsr_fields.push_back({"BTYPE", 10, 11});
179 cpsr_fields.push_back({"D", 9});
180 cpsr_fields.push_back({"A", 8});
181 cpsr_fields.push_back({"I", 7});
182 cpsr_fields.push_back({"F", 6});
183 // Bit 5 reserved
184 // Called "M" in the ARMARM.
185 cpsr_fields.push_back({"nRW", 4});
186 // This is a 4 bit field M[3:0] in the ARMARM, we split it into parts.
187 cpsr_fields.push_back({"EL", 2, 3});
188 // Bit 1 is unused and expected to be 0.
189 cpsr_fields.push_back({"SP", 0});
191 return cpsr_fields;
194 void Arm64RegisterFlagsDetector::DetectFields(uint64_t hwcap, uint64_t hwcap2) {
195 for (auto &reg : m_registers)
196 reg.m_flags.SetFields(reg.m_detector(hwcap, hwcap2));
197 m_has_detected = true;
200 void Arm64RegisterFlagsDetector::UpdateRegisterInfo(
201 const RegisterInfo *reg_info, uint32_t num_regs) {
202 assert(m_has_detected &&
203 "Must call DetectFields before updating register info.");
205 // Register names will not be duplicated, so we do not want to compare against
206 // one if it has already been found. Each time we find one, we erase it from
207 // this list.
208 std::vector<std::pair<llvm::StringRef, const RegisterFlags *>>
209 search_registers;
210 for (const auto &reg : m_registers) {
211 // It is possible that a register is all extension dependent fields, and
212 // none of them are present.
213 if (reg.m_flags.GetFields().size())
214 search_registers.push_back({reg.m_name, &reg.m_flags});
217 // Walk register information while there are registers we know need
218 // to be updated. Example:
219 // Register information: [a, b, c, d]
220 // To be patched: [b, c]
221 // * a != b, a != c, do nothing and move on.
222 // * b == b, patch b, new patch list is [c], move on.
223 // * c == c, patch c, patch list is empty, exit early without looking at d.
224 for (uint32_t idx = 0; idx < num_regs && search_registers.size();
225 ++idx, ++reg_info) {
226 auto reg_it = std::find_if(
227 search_registers.cbegin(), search_registers.cend(),
228 [reg_info](auto reg) { return reg.first == reg_info->name; });
230 if (reg_it != search_registers.end()) {
231 // Attach the field information.
232 reg_info->flags_type = reg_it->second;
233 // We do not expect to see this name again so don't look for it again.
234 search_registers.erase(reg_it);
238 // We do not assert that search_registers is empty here, because it may
239 // contain registers from optional extensions that are not present on the
240 // current target.