Skip to content

Commit e3d750c

Browse files
[lldb][AArch64][Linux] Add fields for FPCR register (#71694)
Follows the format laid out in the Arm manual, AArch32 only fields are ignored. ``` (lldb) register read fpcr fpcr = 0x00000000 = (AHP = 0, DN = 0, FZ = 0, RMMode = 0, FZ16 = 0, IDE = 0, IXE = 0, UFE = 0, OFE = 0, DZE = 0, IOE = 0) ``` Tests use the first 4 fields that we know are always present. Converted all the HCWAP defines to `UL` because I'm bound to forget one if I don't do it now.
1 parent 74a76a2 commit e3d750c

File tree

4 files changed

+55
-5
lines changed

4 files changed

+55
-5
lines changed

lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,54 @@
1212
// This file is built on all systems because it is used by native processes and
1313
// core files, so we manually define the needed HWCAP values here.
1414

15-
#define HWCAP_DIT (1 << 24)
16-
#define HWCAP_SSBS (1 << 28)
15+
#define HWCAP_FPHP (1UL << 9)
16+
#define HWCAP_ASIMDHP (1UL << 10)
17+
#define HWCAP_DIT (1UL << 24)
18+
#define HWCAP_SSBS (1UL << 28)
1719

18-
#define HWCAP2_BTI (1 << 17)
19-
#define HWCAP2_MTE (1 << 18)
20+
#define HWCAP2_BTI (1UL << 17)
21+
#define HWCAP2_MTE (1UL << 18)
22+
#define HWCAP2_AFP (1UL << 20)
23+
#define HWCAP2_EBF16 (1UL << 32)
2024

2125
using namespace lldb_private;
2226

27+
LinuxArm64RegisterFlags::Fields
28+
LinuxArm64RegisterFlags::DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2) {
29+
std::vector<RegisterFlags::Field> fpcr_fields{
30+
{"AHP", 26}, {"DN", 25}, {"FZ", 24}, {"RMMode", 22, 23},
31+
// Bits 21-20 are "Stride" which is unused in AArch64 state.
32+
};
33+
34+
// FEAT_FP16 is indicated by the presence of FPHP (floating point half
35+
// precision) and ASIMDHP (Advanced SIMD half precision) features.
36+
if ((hwcap & HWCAP_FPHP) && (hwcap & HWCAP_ASIMDHP))
37+
fpcr_fields.push_back({"FZ16", 19});
38+
39+
// Bits 18-16 are "Len" which is unused in AArch64 state.
40+
41+
fpcr_fields.push_back({"IDE", 15});
42+
43+
// Bit 14 is unused.
44+
if (hwcap2 & HWCAP2_EBF16)
45+
fpcr_fields.push_back({"EBF", 13});
46+
47+
fpcr_fields.push_back({"IXE", 12});
48+
fpcr_fields.push_back({"UFE", 11});
49+
fpcr_fields.push_back({"OFE", 10});
50+
fpcr_fields.push_back({"DZE", 9});
51+
fpcr_fields.push_back({"IOE", 8});
52+
// Bits 7-3 reserved.
53+
54+
if (hwcap2 & HWCAP2_AFP) {
55+
fpcr_fields.push_back({"NEP", 2});
56+
fpcr_fields.push_back({"AH", 1});
57+
fpcr_fields.push_back({"FIZ", 0});
58+
}
59+
60+
return fpcr_fields;
61+
}
62+
2363
LinuxArm64RegisterFlags::Fields
2464
LinuxArm64RegisterFlags::DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2) {
2565
// fpsr's contents are constant.

lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class LinuxArm64RegisterFlags {
5757

5858
static Fields DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2);
5959
static Fields DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2);
60+
static Fields DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2);
6061

6162
struct RegisterEntry {
6263
RegisterEntry(llvm::StringRef name, unsigned size, DetectorFn detector)
@@ -66,9 +67,10 @@ class LinuxArm64RegisterFlags {
6667
llvm::StringRef m_name;
6768
RegisterFlags m_flags;
6869
DetectorFn m_detector;
69-
} m_registers[2] = {
70+
} m_registers[3] = {
7071
RegisterEntry("cpsr", 4, DetectCPSRFields),
7172
RegisterEntry("fpsr", 4, DetectFPSRFields),
73+
RegisterEntry("fpcr", 4, DetectFPCRFields),
7274
};
7375

7476
// Becomes true once field detection has been run for all registers.

lldb/test/API/commands/register/register/register_command/TestRegisters.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,10 @@ def test_register_read_fields(self):
630630
# N/Z/C/V bits will always be present, so check only for those.
631631
self.expect("register read cpsr", substrs=["= (N = 0, Z = 1, C = 1, V = 0"])
632632
self.expect("register read fpsr", substrs=["= (QC = 0, IDC = 0, IXC = 0"])
633+
# AHP/DN/FZ/RMMode always present, others may vary.
634+
self.expect(
635+
"register read fpcr", substrs=["= (AHP = 0, DN = 0, FZ = 0, RMMode = 0"]
636+
)
633637

634638
@skipUnlessPlatform(["linux"])
635639
@skipIf(archs=no_match(["x86_64"]))

lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,10 @@ def test_aarch64_sve_regs_full(self):
578578
# The N/Z/C/V bits are always present so just check for those.
579579
self.expect("register read cpsr", substrs=["= (N = 0, Z = 0, C = 0, V = 0"])
580580
self.expect("register read fpsr", substrs=["= (QC = 0, IDC = 0, IXC = 0"])
581+
# AHP/DN/FZ/RMMode always present, others may vary.
582+
self.expect(
583+
"register read fpcr", substrs=["= (AHP = 0, DN = 0, FZ = 0, RMMode = 0"]
584+
)
581585

582586
@skipIfLLVMTargetMissing("AArch64")
583587
def test_aarch64_pac_regs(self):

0 commit comments

Comments
 (0)