Skip to content

Commit 5ea1c87

Browse files
authored
[LLDB][LoongArch] Add LSX and LASX register definitions and operations
With this patch, vector registers can be read and written when debugging a live process. Note: We currently assume that all LoongArch64 processors include the LSX and LASX extensions. To add test cases, the following modifications were also made: lldb/packages/Python/lldbsuite/test/lldbtest.py lldb/packages/Python/lldbsuite/test/make/Makefile.rules Reviewed By: DavidSpickett, SixWeining Pull Request: llvm#120664
1 parent 1908c41 commit 5ea1c87

14 files changed

+728
-6
lines changed

lldb/packages/Python/lldbsuite/test/lldbtest.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,6 +1379,17 @@ def isAArch64Windows(self):
13791379
return arch in ["aarch64", "arm64", "arm64e"]
13801380
return False
13811381

1382+
def isLoongArch(self):
1383+
"""Returns true if the architecture is LoongArch."""
1384+
arch = self.getArchitecture().lower()
1385+
return arch in ["loongarch64", "loongarch32"]
1386+
1387+
def isLoongArchLSX(self):
1388+
return self.isLoongArch() and "lsx" in self.getCPUInfo()
1389+
1390+
def isLoongArchLASX(self):
1391+
return self.isLoongArch() and "lasx" in self.getCPUInfo()
1392+
13821393
def getArchitecture(self):
13831394
"""Returns the architecture in effect the test suite is running with."""
13841395
return lldbplatformutil.getArchitecture()

lldb/packages/Python/lldbsuite/test/make/Makefile.rules

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,10 @@ else
210210
ifeq "$(findstring mips,$(ARCH))" "mips"
211211
override ARCHFLAG := -
212212
endif
213+
ifeq "$(findstring loongarch,$(ARCH))" "loongarch"
214+
override ARCH :=
215+
override ARCHFLAG :=
216+
endif
213217

214218
ifeq "$(SPLIT_DEBUG_SYMBOLS)" "YES"
215219
DSYM = $(EXE).debug

lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_loongarch64.cpp

Lines changed: 174 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,17 @@
2727
// struct iovec definition
2828
#include <sys/uio.h>
2929

30-
#define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize())
30+
#ifndef NT_LOONGARCH_LSX
31+
#define NT_LOONGARCH_LSX 0xa02 /* LoongArch SIMD eXtension registers */
32+
#endif
33+
34+
#ifndef NT_LOONGARCH_LASX
35+
#define NT_LOONGARCH_LASX \
36+
0xa03 /* LoongArch Advanced SIMD eXtension registers */
37+
#endif
38+
39+
#define REG_CONTEXT_SIZE \
40+
(GetGPRSize() + GetFPRSize() + sizeof(m_lsx) + sizeof(m_lasx))
3141

3242
using namespace lldb;
3343
using namespace lldb_private;
@@ -62,6 +72,8 @@ NativeRegisterContextLinux_loongarch64::NativeRegisterContextLinux_loongarch64(
6272
NativeRegisterContextLinux(native_thread) {
6373
::memset(&m_fpr, 0, sizeof(m_fpr));
6474
::memset(&m_gpr, 0, sizeof(m_gpr));
75+
::memset(&m_lsx, 0, sizeof(m_lsx));
76+
::memset(&m_lasx, 0, sizeof(m_lasx));
6577

6678
::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs));
6779
::memset(&m_hbp_regs, 0, sizeof(m_hbp_regs));
@@ -75,6 +87,8 @@ NativeRegisterContextLinux_loongarch64::NativeRegisterContextLinux_loongarch64(
7587

7688
m_gpr_is_valid = false;
7789
m_fpu_is_valid = false;
90+
m_lsx_is_valid = false;
91+
m_lasx_is_valid = false;
7892
}
7993

8094
const RegisterInfoPOSIX_loongarch64 &
@@ -135,6 +149,22 @@ Status NativeRegisterContextLinux_loongarch64::ReadRegister(
135149
offset = CalculateFprOffset(reg_info);
136150
assert(offset < GetFPRSize());
137151
src = (uint8_t *)GetFPRBuffer() + offset;
152+
} else if (IsLSX(reg)) {
153+
error = ReadLSX();
154+
if (error.Fail())
155+
return error;
156+
157+
offset = CalculateLsxOffset(reg_info);
158+
assert(offset < sizeof(m_lsx));
159+
src = (uint8_t *)&m_lsx + offset;
160+
} else if (IsLASX(reg)) {
161+
error = ReadLASX();
162+
if (error.Fail())
163+
return error;
164+
165+
offset = CalculateLasxOffset(reg_info);
166+
assert(offset < sizeof(m_lasx));
167+
src = (uint8_t *)&m_lasx + offset;
138168
} else
139169
return Status::FromErrorString(
140170
"failed - register wasn't recognized to be a GPR or an FPR, "
@@ -184,6 +214,28 @@ Status NativeRegisterContextLinux_loongarch64::WriteRegister(
184214
::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
185215

186216
return WriteFPR();
217+
} else if (IsLSX(reg)) {
218+
error = ReadLSX();
219+
if (error.Fail())
220+
return error;
221+
222+
offset = CalculateLsxOffset(reg_info);
223+
assert(offset < sizeof(m_lsx));
224+
dst = (uint8_t *)&m_lsx + offset;
225+
::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
226+
227+
return WriteLSX();
228+
} else if (IsLASX(reg)) {
229+
error = ReadLASX();
230+
if (error.Fail())
231+
return error;
232+
233+
offset = CalculateLasxOffset(reg_info);
234+
assert(offset < sizeof(m_lasx));
235+
dst = (uint8_t *)&m_lasx + offset;
236+
::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
237+
238+
return WriteLASX();
187239
}
188240

189241
return Status::FromErrorString("Failed to write register value");
@@ -203,10 +255,22 @@ Status NativeRegisterContextLinux_loongarch64::ReadAllRegisterValues(
203255
if (error.Fail())
204256
return error;
205257

258+
error = ReadLSX();
259+
if (error.Fail())
260+
return error;
261+
262+
error = ReadLASX();
263+
if (error.Fail())
264+
return error;
265+
206266
uint8_t *dst = data_sp->GetBytes();
207267
::memcpy(dst, GetGPRBuffer(), GetGPRSize());
208268
dst += GetGPRSize();
209269
::memcpy(dst, GetFPRBuffer(), GetFPRSize());
270+
dst += GetFPRSize();
271+
::memcpy(dst, &m_lsx, sizeof(m_lsx));
272+
dst += sizeof(m_lsx);
273+
::memcpy(dst, &m_lasx, sizeof(m_lasx));
210274

211275
return error;
212276
}
@@ -247,11 +311,27 @@ Status NativeRegisterContextLinux_loongarch64::WriteAllRegisterValues(
247311

248312
src += GetRegisterInfoInterface().GetGPRSize();
249313
::memcpy(GetFPRBuffer(), src, GetFPRSize());
250-
314+
m_fpu_is_valid = true;
251315
error = WriteFPR();
252316
if (error.Fail())
253317
return error;
254318

319+
// Currently, we assume that LoongArch always support LASX.
320+
// TODO: check whether LSX/LASX exists.
321+
src += GetFPRSize();
322+
::memcpy(&m_lsx, src, sizeof(m_lsx));
323+
m_lsx_is_valid = true;
324+
error = WriteLSX();
325+
if (error.Fail())
326+
return error;
327+
328+
src += sizeof(m_lsx);
329+
::memcpy(&m_lasx, src, sizeof(m_lasx));
330+
m_lasx_is_valid = true;
331+
error = WriteLASX();
332+
if (error.Fail())
333+
return error;
334+
255335
return error;
256336
}
257337

@@ -265,6 +345,16 @@ bool NativeRegisterContextLinux_loongarch64::IsFPR(unsigned reg) const {
265345
RegisterInfoPOSIX_loongarch64::FPRegSet;
266346
}
267347

348+
bool NativeRegisterContextLinux_loongarch64::IsLSX(unsigned reg) const {
349+
return GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
350+
RegisterInfoPOSIX_loongarch64::LSXRegSet;
351+
}
352+
353+
bool NativeRegisterContextLinux_loongarch64::IsLASX(unsigned reg) const {
354+
return GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
355+
RegisterInfoPOSIX_loongarch64::LASXRegSet;
356+
}
357+
268358
Status NativeRegisterContextLinux_loongarch64::ReadGPR() {
269359
Status error;
270360

@@ -325,20 +415,102 @@ Status NativeRegisterContextLinux_loongarch64::WriteFPR() {
325415
ioVec.iov_len = GetFPRSize();
326416

327417
m_fpu_is_valid = false;
418+
m_lsx_is_valid = false;
419+
m_lasx_is_valid = false;
328420

329421
return WriteRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
330422
}
331423

424+
Status NativeRegisterContextLinux_loongarch64::ReadLSX() {
425+
Status error;
426+
427+
if (m_lsx_is_valid)
428+
return error;
429+
430+
struct iovec ioVec;
431+
ioVec.iov_base = &m_lsx;
432+
ioVec.iov_len = sizeof(m_lsx);
433+
434+
error = ReadRegisterSet(&ioVec, sizeof(m_lsx), NT_LOONGARCH_LSX);
435+
436+
if (error.Success())
437+
m_lsx_is_valid = true;
438+
439+
return error;
440+
}
441+
442+
Status NativeRegisterContextLinux_loongarch64::WriteLSX() {
443+
Status error = ReadLSX();
444+
if (error.Fail())
445+
return error;
446+
447+
struct iovec ioVec;
448+
ioVec.iov_base = &m_lsx;
449+
ioVec.iov_len = sizeof(m_lsx);
450+
451+
m_fpu_is_valid = false;
452+
m_lsx_is_valid = false;
453+
m_lasx_is_valid = false;
454+
455+
return WriteRegisterSet(&ioVec, sizeof(m_lsx), NT_LOONGARCH_LSX);
456+
}
457+
458+
Status NativeRegisterContextLinux_loongarch64::ReadLASX() {
459+
Status error;
460+
461+
if (m_lasx_is_valid)
462+
return error;
463+
464+
struct iovec ioVec;
465+
ioVec.iov_base = &m_lasx;
466+
ioVec.iov_len = sizeof(m_lasx);
467+
468+
error = ReadRegisterSet(&ioVec, sizeof(m_lasx), NT_LOONGARCH_LASX);
469+
470+
if (error.Success())
471+
m_lasx_is_valid = true;
472+
473+
return error;
474+
}
475+
476+
Status NativeRegisterContextLinux_loongarch64::WriteLASX() {
477+
Status error = ReadLASX();
478+
if (error.Fail())
479+
return error;
480+
481+
struct iovec ioVec;
482+
ioVec.iov_base = &m_lasx;
483+
ioVec.iov_len = sizeof(m_lasx);
484+
485+
m_fpu_is_valid = false;
486+
m_lsx_is_valid = false;
487+
m_lasx_is_valid = false;
488+
489+
return WriteRegisterSet(&ioVec, sizeof(m_lasx), NT_LOONGARCH_LASX);
490+
}
491+
332492
void NativeRegisterContextLinux_loongarch64::InvalidateAllRegisters() {
333493
m_gpr_is_valid = false;
334494
m_fpu_is_valid = false;
495+
m_lsx_is_valid = false;
496+
m_lasx_is_valid = false;
335497
}
336498

337499
uint32_t NativeRegisterContextLinux_loongarch64::CalculateFprOffset(
338500
const RegisterInfo *reg_info) const {
339501
return reg_info->byte_offset - GetGPRSize();
340502
}
341503

504+
uint32_t NativeRegisterContextLinux_loongarch64::CalculateLsxOffset(
505+
const RegisterInfo *reg_info) const {
506+
return reg_info->byte_offset - GetGPRSize() - sizeof(m_fpr);
507+
}
508+
509+
uint32_t NativeRegisterContextLinux_loongarch64::CalculateLasxOffset(
510+
const RegisterInfo *reg_info) const {
511+
return reg_info->byte_offset - GetGPRSize() - sizeof(m_fpr) - sizeof(m_lsx);
512+
}
513+
342514
std::vector<uint32_t>
343515
NativeRegisterContextLinux_loongarch64::GetExpeditedRegisters(
344516
ExpeditedRegs expType) const {

lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_loongarch64.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,14 @@ class NativeRegisterContextLinux_loongarch64
6262

6363
Status WriteFPR() override;
6464

65+
Status ReadLSX();
66+
67+
Status WriteLSX();
68+
69+
Status ReadLASX();
70+
71+
Status WriteLASX();
72+
6573
void *GetGPRBuffer() override { return &m_gpr; }
6674

6775
void *GetFPRBuffer() override { return &m_fpr; }
@@ -73,18 +81,29 @@ class NativeRegisterContextLinux_loongarch64
7381
private:
7482
bool m_gpr_is_valid;
7583
bool m_fpu_is_valid;
84+
bool m_lsx_is_valid;
85+
bool m_lasx_is_valid;
7686
bool m_refresh_hwdebug_info;
7787

7888
RegisterInfoPOSIX_loongarch64::GPR m_gpr;
79-
8089
RegisterInfoPOSIX_loongarch64::FPR m_fpr;
90+
RegisterInfoPOSIX_loongarch64::LSX m_lsx;
91+
RegisterInfoPOSIX_loongarch64::LASX m_lasx;
8192

8293
bool IsGPR(unsigned reg) const;
8394

8495
bool IsFPR(unsigned reg) const;
8596

97+
bool IsLSX(unsigned reg) const;
98+
99+
bool IsLASX(unsigned reg) const;
100+
86101
uint32_t CalculateFprOffset(const RegisterInfo *reg_info) const;
87102

103+
uint32_t CalculateLsxOffset(const RegisterInfo *reg_info) const;
104+
105+
uint32_t CalculateLasxOffset(const RegisterInfo *reg_info) const;
106+
88107
const RegisterInfoPOSIX_loongarch64 &GetRegisterInfo() const;
89108

90109
llvm::Error ReadHardwareDebugInfo() override;

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,13 @@ bool RegisterContextPOSIX_loongarch64::IsFPR(unsigned int reg) {
8080
return m_register_info_up->GetRegisterSetFromRegisterIndex(reg) ==
8181
RegisterInfoPOSIX_loongarch64::FPRegSet;
8282
}
83+
84+
bool RegisterContextPOSIX_loongarch64::IsLSX(unsigned int reg) {
85+
return m_register_info_up->GetRegisterSetFromRegisterIndex(reg) ==
86+
RegisterInfoPOSIX_loongarch64::LSXRegSet;
87+
}
88+
89+
bool RegisterContextPOSIX_loongarch64::IsLASX(unsigned int reg) {
90+
return m_register_info_up->GetRegisterSetFromRegisterIndex(reg) ==
91+
RegisterInfoPOSIX_loongarch64::LASXRegSet;
92+
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,22 @@ class RegisterContextPOSIX_loongarch64 : public lldb_private::RegisterContext {
5050

5151
bool IsFPR(unsigned reg);
5252

53+
bool IsLSX(unsigned reg);
54+
55+
bool IsLASX(unsigned reg);
56+
5357
size_t GetFPRSize() { return sizeof(RegisterInfoPOSIX_loongarch64::FPR); }
5458

5559
uint32_t GetRegNumFCSR() const { return fpr_fcsr_loongarch; }
5660

5761
virtual bool ReadGPR() = 0;
5862
virtual bool ReadFPR() = 0;
63+
virtual bool ReadLSX() { return false; }
64+
virtual bool ReadLASX() { return false; }
5965
virtual bool WriteGPR() = 0;
6066
virtual bool WriteFPR() = 0;
67+
virtual bool WriteLSX() { return false; }
68+
virtual bool WriteLASX() { return false; }
6169
};
6270

6371
#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_LOONGARCH64_H

0 commit comments

Comments
 (0)