[Lldb-commits] [lldb] [lldb][AArch64][Linux] Add fields for FPCR register (PR #71694)

via lldb-commits lldb-commits at lists.llvm.org
Wed Nov 8 07:43:19 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: David Spickett (DavidSpickett)

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/71694.diff


4 Files Affected:

- (modified) lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp (+64-4) 
- (modified) lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h (+5-1) 
- (modified) lldb/test/API/commands/register/register/register_command/TestRegisters.py (+7-2) 
- (modified) lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py (+5) 


``````````diff
diff --git a/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp
index 043789bd6d21e47..ba1a0d5599e7703 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp
@@ -12,14 +12,74 @@
 // This file is built on all systems because it is used by native processes and
 // core files, so we manually define the needed HWCAP values here.
 
-#define HWCAP_DIT (1 << 24)
-#define HWCAP_SSBS (1 << 28)
+#define HWCAP_FPHP (1UL << 9)
+#define HWCAP_ASIMDHP (1UL << 10)
+#define HWCAP_DIT (1UL << 24)
+#define HWCAP_SSBS (1UL << 28)
 
-#define HWCAP2_BTI (1 << 17)
-#define HWCAP2_MTE (1 << 18)
+#define HWCAP2_BTI (1UL << 17)
+#define HWCAP2_MTE (1UL << 18)
+#define HWCAP2_AFP (1UL << 20)
+#define HWCAP2_EBF16 (1UL << 32)
 
 using namespace lldb_private;
 
+LinuxArm64RegisterFlags::Fields
+LinuxArm64RegisterFlags::DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2) {
+  std::vector<RegisterFlags::Field> fpcr_fields{
+      {"AHP", 26}, {"DN", 25}, {"FZ", 24}, {"RMMode", 22, 23},
+      // Bits 21-20 are "Stride" which is unused in AArch64 state.
+  };
+
+  // FEAT_FP16 is indicated by the presence of FPHP (floating point half
+  // precision) and ASIMDHP (Advanced SIMD half precision) features.
+  if ((hwcap & HWCAP_FPHP) && (hwcap & HWCAP_ASIMDHP))
+    fpcr_fields.push_back({"FZ16", 19});
+
+  // Bits 18-16 are "Len" which is unused in AArch64 state.
+
+  fpcr_fields.push_back({"IDE", 15});
+
+  // Bit 14 is unused.
+  if (hwcap2 & HWCAP2_EBF16)
+    fpcr_fields.push_back({"EBF", 13});
+
+  fpcr_fields.push_back({"IXE", 12});
+  fpcr_fields.push_back({"UFE", 11});
+  fpcr_fields.push_back({"OFE", 10});
+  fpcr_fields.push_back({"DZE", 9});
+  fpcr_fields.push_back({"IOE", 8});
+  // Bits 7-3 reserved.
+
+  if (hwcap2 & HWCAP2_AFP) {
+    fpcr_fields.push_back({"NEP", 2});
+    fpcr_fields.push_back({"AH", 1});
+    fpcr_fields.push_back({"FIZ", 0});
+  }
+
+  return fpcr_fields;
+}
+
+LinuxArm64RegisterFlags::Fields
+LinuxArm64RegisterFlags::DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2) {
+  // fpsr's contents are constant.
+  (void)hwcap;
+  (void)hwcap2;
+
+  return {
+      // Bits 31-28 are N/Z/C/V, only used by AArch32.
+      {"QC", 27},
+      // Bits 26-8 reserved.
+      {"IDC", 7},
+      // Bits 6-5 reserved.
+      {"IXC", 4},
+      {"UFC", 3},
+      {"OFC", 2},
+      {"DZC", 1},
+      {"IOC", 0},
+  };
+}
+
 LinuxArm64RegisterFlags::Fields
 LinuxArm64RegisterFlags::DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2) {
   // The fields here are a combination of the Arm manual's SPSR_EL1,
diff --git a/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h
index 6c7a3b61a1425ee..651a8c86f7c86a9 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h
@@ -56,6 +56,8 @@ class LinuxArm64RegisterFlags {
   using DetectorFn = std::function<Fields(uint64_t, uint64_t)>;
 
   static Fields DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2);
+  static Fields DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2);
+  static Fields DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2);
 
   struct RegisterEntry {
     RegisterEntry(llvm::StringRef name, unsigned size, DetectorFn detector)
@@ -65,8 +67,10 @@ class LinuxArm64RegisterFlags {
     llvm::StringRef m_name;
     RegisterFlags m_flags;
     DetectorFn m_detector;
-  } m_registers[1] = {
+  } m_registers[3] = {
       RegisterEntry("cpsr", 4, DetectCPSRFields),
+      RegisterEntry("fpsr", 4, DetectFPSRFields),
+      RegisterEntry("fpcr", 4, DetectFPCRFields),
   };
 
   // Becomes true once field detection has been run for all registers.
diff --git a/lldb/test/API/commands/register/register/register_command/TestRegisters.py b/lldb/test/API/commands/register/register/register_command/TestRegisters.py
index f29b2ab5d8f259d..386991c18db7c8c 100644
--- a/lldb/test/API/commands/register/register/register_command/TestRegisters.py
+++ b/lldb/test/API/commands/register/register/register_command/TestRegisters.py
@@ -622,13 +622,18 @@ def test_info_register(self):
     @skipUnlessPlatform(["linux"])
     @skipIf(archs=no_match(["aarch64"]))
     def test_register_read_fields(self):
-        """Test that when debugging a live process, we see the fields of the
-        CPSR register."""
+        """Test that when debugging a live process, we see the fields of certain
+        registers."""
         self.build()
         self.common_setup()
 
         # N/Z/C/V bits will always be present, so check only for those.
         self.expect("register read cpsr", substrs=["= (N = 0, Z = 1, C = 1, V = 0"])
+        self.expect("register read fpsr", substrs=["= (QC = 0, IDC = 0, IXC = 0"])
+        # AHP/DN/FZ/RMMode always present, others may vary.
+        self.expect(
+            "register read fpcr", substrs=["= (AHP = 0, DN = 0, FZ = 0, RMMode = 0"]
+        )
 
     @skipUnlessPlatform(["linux"])
     @skipIf(archs=no_match(["x86_64"]))
diff --git a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
index a083fab18eabcbc..58f104eb49de245 100644
--- a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
+++ b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
@@ -577,6 +577,11 @@ def test_aarch64_sve_regs_full(self):
         # Register field information should work with core files as it does a live process.
         # The N/Z/C/V bits are always present so just check for those.
         self.expect("register read cpsr", substrs=["= (N = 0, Z = 0, C = 0, V = 0"])
+        self.expect("register read fpsr", substrs=["= (QC = 0, IDC = 0, IXC = 0"])
+        # AHP/DN/FZ/RMMode always present, others may vary.
+        self.expect(
+            "register read fpcr", substrs=["= (AHP = 0, DN = 0, FZ = 0, RMMode = 0"]
+        )
 
     @skipIfLLVMTargetMissing("AArch64")
     def test_aarch64_pac_regs(self):

``````````

</details>


https://github.com/llvm/llvm-project/pull/71694


More information about the lldb-commits mailing list