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
3242using namespace lldb ;
3343using 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
8094const 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+
268358Status 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+
332492void 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
337499uint32_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+
342514std::vector<uint32_t >
343515NativeRegisterContextLinux_loongarch64::GetExpeditedRegisters (
344516 ExpeditedRegs expType) const {
0 commit comments