Index: lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp =================================================================== --- lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp +++ lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp @@ -71,6 +71,39 @@ .Default(LLDB_INVALID_REGNUM); } +static void AddPartialRegister(lldb_private::DynamicRegisterInfo &info, + const lldb_private::RegisterInfo *full_reg, + uint32_t full_reg_size, + const std::string &partial_reg_name, + uint32_t partial_reg_size, + lldb::Encoding encoding, lldb::Format format, + uint32_t &next_regnum_lldb) { + if (!full_reg || full_reg->byte_size != full_reg_size) + return; + if (info.GetRegisterInfo(partial_reg_name)) + return; + + lldb_private::ConstString group{"partial registers"}; + + lldb_private::ConstString partial_reg_name_const{partial_reg_name}; + uint32_t value_regs[] = { + full_reg->kinds[lldb::eRegisterKindProcessPlugin], + LLDB_INVALID_REGNUM, + }; + + struct lldb_private::RegisterInfo partial_reg { + partial_reg_name_const.AsCString(), + nullptr, partial_reg_size, LLDB_INVALID_INDEX32, encoding, format, + { + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, next_regnum_lldb++, + }, + value_regs, nullptr, nullptr, 0 + }; + + info.AddSupplementaryRegister(partial_reg, group); +} + void ABIAArch64::AugmentRegisterInfo( lldb_private::DynamicRegisterInfo &dyn_info) { lldb_private::MCBasedABI::AugmentRegisterInfo(dyn_info); @@ -80,4 +113,25 @@ if (!strcmp(sp->name, "sp") && !sp->alt_name) sp->alt_name = "x31"; } + + uint32_t next_regnum_lldb = dyn_info.GetNumRegisters(); + + // Create aliases for partial registers: wN for xN, and sN/dN for vN. + for (int i = 0; i < 32; i++) + AddPartialRegister(dyn_info, + dyn_info.GetRegisterInfo(llvm::formatv("x{0}", i).str()), + 8, llvm::formatv("w{0}", i), 4, lldb::eEncodingUint, + lldb::eFormatHex, next_regnum_lldb); + + for (int i = 0; i < 32; i++) + AddPartialRegister(dyn_info, + dyn_info.GetRegisterInfo(llvm::formatv("v{0}", i).str()), + 16, llvm::formatv("s{0}", i), 4, lldb::eEncodingIEEE754, + lldb::eFormatFloat, next_regnum_lldb); + + for (int i = 0; i < 32; i++) + AddPartialRegister(dyn_info, + dyn_info.GetRegisterInfo(llvm::formatv("v{0}", i).str()), + 16, llvm::formatv("d{0}", i), 8, lldb::eEncodingIEEE754, + lldb::eFormatFloat, next_regnum_lldb); } Index: lldb/source/Target/DynamicRegisterInfo.cpp =================================================================== --- lldb/source/Target/DynamicRegisterInfo.cpp +++ lldb/source/Target/DynamicRegisterInfo.cpp @@ -832,16 +832,18 @@ const lldb_private::RegisterInfo * DynamicRegisterInfo::GetRegisterInfo(llvm::StringRef reg_name) const { + assert(!reg_name.empty()); for (auto ®_info : m_regs) - if (reg_info.name == reg_name) + if (reg_info.name == reg_name || reg_info.alt_name == reg_name) return ®_info; return nullptr; } lldb_private::RegisterInfo * DynamicRegisterInfo::GetRegisterInfo(llvm::StringRef reg_name) { + assert(!reg_name.empty()); for (auto ®_info : m_regs) - if (reg_info.name == reg_name) + if (reg_info.name == reg_name || reg_info.alt_name == reg_name) return ®_info; return nullptr; } Index: lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py =================================================================== --- lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py +++ lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py @@ -380,6 +380,7 @@ return "".join(reg_data) def writeRegisters(self, reg_hex): + reg_data[:] = [reg_hex] return "OK" def haltReason(self): @@ -429,3 +430,43 @@ ["v0 = {0x81 0x82 0x83 0x84 0x85 0x86 0x87 0x88 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f 0x90}"]) self.match("register read v31", ["v31 = {0xa1 0xa2 0xa3 0xa4 0xa5 0xa6 0xa7 0xa8 0xa9 0xaa 0xab 0xac 0xad 0xae 0xaf 0xb0}"]) + + # test partial registers + self.match("register read w0", + ["w0 = 0x04030201"]) + self.runCmd("register write w0 0xfffefdfc") + self.match("register read x0", + ["x0 = 0x08070605fffefdfc"]) + + self.match("register read w1", + ["w1 = 0x14131211"]) + self.runCmd("register write w1 0xefeeedec") + self.match("register read x1", + ["x1 = 0x18171615efeeedec"]) + + self.match("register read w30", + ["w30 = 0x44434241"]) + self.runCmd("register write w30 0xdfdedddc") + self.match("register read x30", + ["x30 = 0x48474645dfdedddc"]) + + self.match("register read w31", + ["w31 = 0x54535251"]) + self.runCmd("register write w31 0xcfcecdcc") + self.match("register read x31", + ["sp = 0x58575655cfcecdcc"]) + + # test FPU registers (overlapping with vector registers) + self.runCmd("register write d0 16") + self.match("register read v0", + ["v0 = {0x00 0x00 0x00 0x00 0x00 0x00 0x30 0x40 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f 0x90}"]) + self.runCmd("register write v31 '{0x00 0x00 0x00 0x00 0x00 0x00 0x50 0x40 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff}'") + self.match("register read d31", + ["d31 = 64"]) + + self.runCmd("register write s0 32") + self.match("register read v0", + ["v0 = {0x00 0x00 0x00 0x42 0x00 0x00 0x30 0x40 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f 0x90}"]) + self.runCmd("register write v31 '{0x00 0x00 0x00 0x43 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff}'") + self.match("register read s31", + ["s31 = 128"])