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 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits