mirror of
https://github.com/intel/llvm.git
synced 2026-01-16 05:32:28 +08:00
[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: https://github.com/llvm/llvm-project/pull/120664
This commit is contained in:
@@ -1379,6 +1379,17 @@ class Base(unittest.TestCase):
|
||||
return arch in ["aarch64", "arm64", "arm64e"]
|
||||
return False
|
||||
|
||||
def isLoongArch(self):
|
||||
"""Returns true if the architecture is LoongArch."""
|
||||
arch = self.getArchitecture().lower()
|
||||
return arch in ["loongarch64", "loongarch32"]
|
||||
|
||||
def isLoongArchLSX(self):
|
||||
return self.isLoongArch() and "lsx" in self.getCPUInfo()
|
||||
|
||||
def isLoongArchLASX(self):
|
||||
return self.isLoongArch() and "lasx" in self.getCPUInfo()
|
||||
|
||||
def getArchitecture(self):
|
||||
"""Returns the architecture in effect the test suite is running with."""
|
||||
return lldbplatformutil.getArchitecture()
|
||||
|
||||
@@ -210,6 +210,10 @@ else
|
||||
ifeq "$(findstring mips,$(ARCH))" "mips"
|
||||
override ARCHFLAG := -
|
||||
endif
|
||||
ifeq "$(findstring loongarch,$(ARCH))" "loongarch"
|
||||
override ARCH :=
|
||||
override ARCHFLAG :=
|
||||
endif
|
||||
|
||||
ifeq "$(SPLIT_DEBUG_SYMBOLS)" "YES"
|
||||
DSYM = $(EXE).debug
|
||||
|
||||
@@ -27,7 +27,17 @@
|
||||
// struct iovec definition
|
||||
#include <sys/uio.h>
|
||||
|
||||
#define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize())
|
||||
#ifndef NT_LOONGARCH_LSX
|
||||
#define NT_LOONGARCH_LSX 0xa02 /* LoongArch SIMD eXtension registers */
|
||||
#endif
|
||||
|
||||
#ifndef NT_LOONGARCH_LASX
|
||||
#define NT_LOONGARCH_LASX \
|
||||
0xa03 /* LoongArch Advanced SIMD eXtension registers */
|
||||
#endif
|
||||
|
||||
#define REG_CONTEXT_SIZE \
|
||||
(GetGPRSize() + GetFPRSize() + sizeof(m_lsx) + sizeof(m_lasx))
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
@@ -62,6 +72,8 @@ NativeRegisterContextLinux_loongarch64::NativeRegisterContextLinux_loongarch64(
|
||||
NativeRegisterContextLinux(native_thread) {
|
||||
::memset(&m_fpr, 0, sizeof(m_fpr));
|
||||
::memset(&m_gpr, 0, sizeof(m_gpr));
|
||||
::memset(&m_lsx, 0, sizeof(m_lsx));
|
||||
::memset(&m_lasx, 0, sizeof(m_lasx));
|
||||
|
||||
::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs));
|
||||
::memset(&m_hbp_regs, 0, sizeof(m_hbp_regs));
|
||||
@@ -75,6 +87,8 @@ NativeRegisterContextLinux_loongarch64::NativeRegisterContextLinux_loongarch64(
|
||||
|
||||
m_gpr_is_valid = false;
|
||||
m_fpu_is_valid = false;
|
||||
m_lsx_is_valid = false;
|
||||
m_lasx_is_valid = false;
|
||||
}
|
||||
|
||||
const RegisterInfoPOSIX_loongarch64 &
|
||||
@@ -135,6 +149,22 @@ Status NativeRegisterContextLinux_loongarch64::ReadRegister(
|
||||
offset = CalculateFprOffset(reg_info);
|
||||
assert(offset < GetFPRSize());
|
||||
src = (uint8_t *)GetFPRBuffer() + offset;
|
||||
} else if (IsLSX(reg)) {
|
||||
error = ReadLSX();
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
offset = CalculateLsxOffset(reg_info);
|
||||
assert(offset < sizeof(m_lsx));
|
||||
src = (uint8_t *)&m_lsx + offset;
|
||||
} else if (IsLASX(reg)) {
|
||||
error = ReadLASX();
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
offset = CalculateLasxOffset(reg_info);
|
||||
assert(offset < sizeof(m_lasx));
|
||||
src = (uint8_t *)&m_lasx + offset;
|
||||
} else
|
||||
return Status::FromErrorString(
|
||||
"failed - register wasn't recognized to be a GPR or an FPR, "
|
||||
@@ -184,6 +214,28 @@ Status NativeRegisterContextLinux_loongarch64::WriteRegister(
|
||||
::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
|
||||
|
||||
return WriteFPR();
|
||||
} else if (IsLSX(reg)) {
|
||||
error = ReadLSX();
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
offset = CalculateLsxOffset(reg_info);
|
||||
assert(offset < sizeof(m_lsx));
|
||||
dst = (uint8_t *)&m_lsx + offset;
|
||||
::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
|
||||
|
||||
return WriteLSX();
|
||||
} else if (IsLASX(reg)) {
|
||||
error = ReadLASX();
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
offset = CalculateLasxOffset(reg_info);
|
||||
assert(offset < sizeof(m_lasx));
|
||||
dst = (uint8_t *)&m_lasx + offset;
|
||||
::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
|
||||
|
||||
return WriteLASX();
|
||||
}
|
||||
|
||||
return Status::FromErrorString("Failed to write register value");
|
||||
@@ -203,10 +255,22 @@ Status NativeRegisterContextLinux_loongarch64::ReadAllRegisterValues(
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
error = ReadLSX();
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
error = ReadLASX();
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
uint8_t *dst = data_sp->GetBytes();
|
||||
::memcpy(dst, GetGPRBuffer(), GetGPRSize());
|
||||
dst += GetGPRSize();
|
||||
::memcpy(dst, GetFPRBuffer(), GetFPRSize());
|
||||
dst += GetFPRSize();
|
||||
::memcpy(dst, &m_lsx, sizeof(m_lsx));
|
||||
dst += sizeof(m_lsx);
|
||||
::memcpy(dst, &m_lasx, sizeof(m_lasx));
|
||||
|
||||
return error;
|
||||
}
|
||||
@@ -247,11 +311,27 @@ Status NativeRegisterContextLinux_loongarch64::WriteAllRegisterValues(
|
||||
|
||||
src += GetRegisterInfoInterface().GetGPRSize();
|
||||
::memcpy(GetFPRBuffer(), src, GetFPRSize());
|
||||
|
||||
m_fpu_is_valid = true;
|
||||
error = WriteFPR();
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
// Currently, we assume that LoongArch always support LASX.
|
||||
// TODO: check whether LSX/LASX exists.
|
||||
src += GetFPRSize();
|
||||
::memcpy(&m_lsx, src, sizeof(m_lsx));
|
||||
m_lsx_is_valid = true;
|
||||
error = WriteLSX();
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
src += sizeof(m_lsx);
|
||||
::memcpy(&m_lasx, src, sizeof(m_lasx));
|
||||
m_lasx_is_valid = true;
|
||||
error = WriteLASX();
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -265,6 +345,16 @@ bool NativeRegisterContextLinux_loongarch64::IsFPR(unsigned reg) const {
|
||||
RegisterInfoPOSIX_loongarch64::FPRegSet;
|
||||
}
|
||||
|
||||
bool NativeRegisterContextLinux_loongarch64::IsLSX(unsigned reg) const {
|
||||
return GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
|
||||
RegisterInfoPOSIX_loongarch64::LSXRegSet;
|
||||
}
|
||||
|
||||
bool NativeRegisterContextLinux_loongarch64::IsLASX(unsigned reg) const {
|
||||
return GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
|
||||
RegisterInfoPOSIX_loongarch64::LASXRegSet;
|
||||
}
|
||||
|
||||
Status NativeRegisterContextLinux_loongarch64::ReadGPR() {
|
||||
Status error;
|
||||
|
||||
@@ -325,13 +415,85 @@ Status NativeRegisterContextLinux_loongarch64::WriteFPR() {
|
||||
ioVec.iov_len = GetFPRSize();
|
||||
|
||||
m_fpu_is_valid = false;
|
||||
m_lsx_is_valid = false;
|
||||
m_lasx_is_valid = false;
|
||||
|
||||
return WriteRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
|
||||
}
|
||||
|
||||
Status NativeRegisterContextLinux_loongarch64::ReadLSX() {
|
||||
Status error;
|
||||
|
||||
if (m_lsx_is_valid)
|
||||
return error;
|
||||
|
||||
struct iovec ioVec;
|
||||
ioVec.iov_base = &m_lsx;
|
||||
ioVec.iov_len = sizeof(m_lsx);
|
||||
|
||||
error = ReadRegisterSet(&ioVec, sizeof(m_lsx), NT_LOONGARCH_LSX);
|
||||
|
||||
if (error.Success())
|
||||
m_lsx_is_valid = true;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Status NativeRegisterContextLinux_loongarch64::WriteLSX() {
|
||||
Status error = ReadLSX();
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
struct iovec ioVec;
|
||||
ioVec.iov_base = &m_lsx;
|
||||
ioVec.iov_len = sizeof(m_lsx);
|
||||
|
||||
m_fpu_is_valid = false;
|
||||
m_lsx_is_valid = false;
|
||||
m_lasx_is_valid = false;
|
||||
|
||||
return WriteRegisterSet(&ioVec, sizeof(m_lsx), NT_LOONGARCH_LSX);
|
||||
}
|
||||
|
||||
Status NativeRegisterContextLinux_loongarch64::ReadLASX() {
|
||||
Status error;
|
||||
|
||||
if (m_lasx_is_valid)
|
||||
return error;
|
||||
|
||||
struct iovec ioVec;
|
||||
ioVec.iov_base = &m_lasx;
|
||||
ioVec.iov_len = sizeof(m_lasx);
|
||||
|
||||
error = ReadRegisterSet(&ioVec, sizeof(m_lasx), NT_LOONGARCH_LASX);
|
||||
|
||||
if (error.Success())
|
||||
m_lasx_is_valid = true;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Status NativeRegisterContextLinux_loongarch64::WriteLASX() {
|
||||
Status error = ReadLASX();
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
struct iovec ioVec;
|
||||
ioVec.iov_base = &m_lasx;
|
||||
ioVec.iov_len = sizeof(m_lasx);
|
||||
|
||||
m_fpu_is_valid = false;
|
||||
m_lsx_is_valid = false;
|
||||
m_lasx_is_valid = false;
|
||||
|
||||
return WriteRegisterSet(&ioVec, sizeof(m_lasx), NT_LOONGARCH_LASX);
|
||||
}
|
||||
|
||||
void NativeRegisterContextLinux_loongarch64::InvalidateAllRegisters() {
|
||||
m_gpr_is_valid = false;
|
||||
m_fpu_is_valid = false;
|
||||
m_lsx_is_valid = false;
|
||||
m_lasx_is_valid = false;
|
||||
}
|
||||
|
||||
uint32_t NativeRegisterContextLinux_loongarch64::CalculateFprOffset(
|
||||
@@ -339,6 +501,16 @@ uint32_t NativeRegisterContextLinux_loongarch64::CalculateFprOffset(
|
||||
return reg_info->byte_offset - GetGPRSize();
|
||||
}
|
||||
|
||||
uint32_t NativeRegisterContextLinux_loongarch64::CalculateLsxOffset(
|
||||
const RegisterInfo *reg_info) const {
|
||||
return reg_info->byte_offset - GetGPRSize() - sizeof(m_fpr);
|
||||
}
|
||||
|
||||
uint32_t NativeRegisterContextLinux_loongarch64::CalculateLasxOffset(
|
||||
const RegisterInfo *reg_info) const {
|
||||
return reg_info->byte_offset - GetGPRSize() - sizeof(m_fpr) - sizeof(m_lsx);
|
||||
}
|
||||
|
||||
std::vector<uint32_t>
|
||||
NativeRegisterContextLinux_loongarch64::GetExpeditedRegisters(
|
||||
ExpeditedRegs expType) const {
|
||||
|
||||
@@ -62,6 +62,14 @@ protected:
|
||||
|
||||
Status WriteFPR() override;
|
||||
|
||||
Status ReadLSX();
|
||||
|
||||
Status WriteLSX();
|
||||
|
||||
Status ReadLASX();
|
||||
|
||||
Status WriteLASX();
|
||||
|
||||
void *GetGPRBuffer() override { return &m_gpr; }
|
||||
|
||||
void *GetFPRBuffer() override { return &m_fpr; }
|
||||
@@ -73,18 +81,29 @@ protected:
|
||||
private:
|
||||
bool m_gpr_is_valid;
|
||||
bool m_fpu_is_valid;
|
||||
bool m_lsx_is_valid;
|
||||
bool m_lasx_is_valid;
|
||||
bool m_refresh_hwdebug_info;
|
||||
|
||||
RegisterInfoPOSIX_loongarch64::GPR m_gpr;
|
||||
|
||||
RegisterInfoPOSIX_loongarch64::FPR m_fpr;
|
||||
RegisterInfoPOSIX_loongarch64::LSX m_lsx;
|
||||
RegisterInfoPOSIX_loongarch64::LASX m_lasx;
|
||||
|
||||
bool IsGPR(unsigned reg) const;
|
||||
|
||||
bool IsFPR(unsigned reg) const;
|
||||
|
||||
bool IsLSX(unsigned reg) const;
|
||||
|
||||
bool IsLASX(unsigned reg) const;
|
||||
|
||||
uint32_t CalculateFprOffset(const RegisterInfo *reg_info) const;
|
||||
|
||||
uint32_t CalculateLsxOffset(const RegisterInfo *reg_info) const;
|
||||
|
||||
uint32_t CalculateLasxOffset(const RegisterInfo *reg_info) const;
|
||||
|
||||
const RegisterInfoPOSIX_loongarch64 &GetRegisterInfo() const;
|
||||
|
||||
llvm::Error ReadHardwareDebugInfo() override;
|
||||
|
||||
@@ -80,3 +80,13 @@ bool RegisterContextPOSIX_loongarch64::IsFPR(unsigned int reg) {
|
||||
return m_register_info_up->GetRegisterSetFromRegisterIndex(reg) ==
|
||||
RegisterInfoPOSIX_loongarch64::FPRegSet;
|
||||
}
|
||||
|
||||
bool RegisterContextPOSIX_loongarch64::IsLSX(unsigned int reg) {
|
||||
return m_register_info_up->GetRegisterSetFromRegisterIndex(reg) ==
|
||||
RegisterInfoPOSIX_loongarch64::LSXRegSet;
|
||||
}
|
||||
|
||||
bool RegisterContextPOSIX_loongarch64::IsLASX(unsigned int reg) {
|
||||
return m_register_info_up->GetRegisterSetFromRegisterIndex(reg) ==
|
||||
RegisterInfoPOSIX_loongarch64::LASXRegSet;
|
||||
}
|
||||
|
||||
@@ -50,14 +50,22 @@ protected:
|
||||
|
||||
bool IsFPR(unsigned reg);
|
||||
|
||||
bool IsLSX(unsigned reg);
|
||||
|
||||
bool IsLASX(unsigned reg);
|
||||
|
||||
size_t GetFPRSize() { return sizeof(RegisterInfoPOSIX_loongarch64::FPR); }
|
||||
|
||||
uint32_t GetRegNumFCSR() const { return fpr_fcsr_loongarch; }
|
||||
|
||||
virtual bool ReadGPR() = 0;
|
||||
virtual bool ReadFPR() = 0;
|
||||
virtual bool ReadLSX() { return false; }
|
||||
virtual bool ReadLASX() { return false; }
|
||||
virtual bool WriteGPR() = 0;
|
||||
virtual bool WriteFPR() = 0;
|
||||
virtual bool WriteLSX() { return false; }
|
||||
virtual bool WriteLASX() { return false; }
|
||||
};
|
||||
|
||||
#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_LOONGARCH64_H
|
||||
|
||||
@@ -19,10 +19,19 @@
|
||||
#define FPR_OFFSET(idx) ((idx)*8 + sizeof(RegisterInfoPOSIX_loongarch64::GPR))
|
||||
#define FCC_OFFSET(idx) ((idx)*1 + 32 * 8 + sizeof(RegisterInfoPOSIX_loongarch64::GPR))
|
||||
#define FCSR_OFFSET (8 * 1 + 32 * 8 + sizeof(RegisterInfoPOSIX_loongarch64::GPR))
|
||||
#define LSX_OFFSET(idx) \
|
||||
((idx) * 16 + sizeof(RegisterInfoPOSIX_loongarch64::GPR) + \
|
||||
sizeof(RegisterInfoPOSIX_loongarch64::FPR))
|
||||
#define LASX_OFFSET(idx) \
|
||||
((idx) * 32 + sizeof(RegisterInfoPOSIX_loongarch64::GPR) + \
|
||||
sizeof(RegisterInfoPOSIX_loongarch64::FPR) + \
|
||||
sizeof(RegisterInfoPOSIX_loongarch64::LSX))
|
||||
|
||||
#define REG_CONTEXT_SIZE \
|
||||
(sizeof(RegisterInfoPOSIX_loongarch64::GPR) + \
|
||||
sizeof(RegisterInfoPOSIX_loongarch64::FPR))
|
||||
sizeof(RegisterInfoPOSIX_loongarch64::FPR) + \
|
||||
sizeof(RegisterInfoPOSIX_loongarch64::LSX) + \
|
||||
sizeof(RegisterInfoPOSIX_loongarch64::LASX))
|
||||
|
||||
#define DECLARE_REGISTER_INFOS_LOONGARCH64_STRUCT
|
||||
#include "RegisterInfos_loongarch64.h"
|
||||
@@ -56,7 +65,9 @@ uint32_t RegisterInfoPOSIX_loongarch64::GetRegisterInfoCount(
|
||||
enum {
|
||||
k_num_gpr_registers = gpr_last_loongarch - gpr_first_loongarch + 1,
|
||||
k_num_fpr_registers = fpr_last_loongarch - fpr_first_loongarch + 1,
|
||||
k_num_register_sets = 2
|
||||
k_num_lsx_registers = lsx_last_loongarch - lsx_first_loongarch + 1,
|
||||
k_num_lasx_registers = lasx_last_loongarch - lasx_first_loongarch + 1,
|
||||
k_num_register_sets = 4
|
||||
};
|
||||
|
||||
// LoongArch64 general purpose registers.
|
||||
@@ -105,13 +116,55 @@ static_assert(((sizeof g_fpr_regnums_loongarch64 /
|
||||
1) == k_num_fpr_registers,
|
||||
"g_fpr_regnums_loongarch64 has wrong number of register infos");
|
||||
|
||||
// LoongArch64 lsx vector registers.
|
||||
static const uint32_t g_lsx_regnums_loongarch64[] = {
|
||||
lsx_vr0_loongarch, lsx_vr1_loongarch, lsx_vr2_loongarch,
|
||||
lsx_vr3_loongarch, lsx_vr4_loongarch, lsx_vr5_loongarch,
|
||||
lsx_vr6_loongarch, lsx_vr7_loongarch, lsx_vr8_loongarch,
|
||||
lsx_vr9_loongarch, lsx_vr10_loongarch, lsx_vr11_loongarch,
|
||||
lsx_vr12_loongarch, lsx_vr13_loongarch, lsx_vr14_loongarch,
|
||||
lsx_vr15_loongarch, lsx_vr16_loongarch, lsx_vr17_loongarch,
|
||||
lsx_vr18_loongarch, lsx_vr19_loongarch, lsx_vr20_loongarch,
|
||||
lsx_vr21_loongarch, lsx_vr22_loongarch, lsx_vr23_loongarch,
|
||||
lsx_vr24_loongarch, lsx_vr25_loongarch, lsx_vr26_loongarch,
|
||||
lsx_vr27_loongarch, lsx_vr28_loongarch, lsx_vr29_loongarch,
|
||||
lsx_vr30_loongarch, lsx_vr31_loongarch, LLDB_INVALID_REGNUM};
|
||||
|
||||
static_assert(((sizeof g_lsx_regnums_loongarch64 /
|
||||
sizeof g_lsx_regnums_loongarch64[0]) -
|
||||
1) == k_num_lsx_registers,
|
||||
"g_lsx_regnums_loongarch64 has wrong number of register infos");
|
||||
|
||||
// LoongArch64 lasx vector registers.
|
||||
static const uint32_t g_lasx_regnums_loongarch64[] = {
|
||||
lasx_xr0_loongarch, lasx_xr1_loongarch, lasx_xr2_loongarch,
|
||||
lasx_xr3_loongarch, lasx_xr4_loongarch, lasx_xr5_loongarch,
|
||||
lasx_xr6_loongarch, lasx_xr7_loongarch, lasx_xr8_loongarch,
|
||||
lasx_xr9_loongarch, lasx_xr10_loongarch, lasx_xr11_loongarch,
|
||||
lasx_xr12_loongarch, lasx_xr13_loongarch, lasx_xr14_loongarch,
|
||||
lasx_xr15_loongarch, lasx_xr16_loongarch, lasx_xr17_loongarch,
|
||||
lasx_xr18_loongarch, lasx_xr19_loongarch, lasx_xr20_loongarch,
|
||||
lasx_xr21_loongarch, lasx_xr22_loongarch, lasx_xr23_loongarch,
|
||||
lasx_xr24_loongarch, lasx_xr25_loongarch, lasx_xr26_loongarch,
|
||||
lasx_xr27_loongarch, lasx_xr28_loongarch, lasx_xr29_loongarch,
|
||||
lasx_xr30_loongarch, lasx_xr31_loongarch, LLDB_INVALID_REGNUM};
|
||||
|
||||
static_assert(((sizeof g_lasx_regnums_loongarch64 /
|
||||
sizeof g_lasx_regnums_loongarch64[0]) -
|
||||
1) == k_num_lasx_registers,
|
||||
"g_lasx_regnums_loongarch64 has wrong number of register infos");
|
||||
|
||||
// Register sets for LoongArch64.
|
||||
static const lldb_private::RegisterSet
|
||||
g_reg_sets_loongarch64[k_num_register_sets] = {
|
||||
{"General Purpose Registers", "gpr", k_num_gpr_registers,
|
||||
g_gpr_regnums_loongarch64},
|
||||
{"Floating Point Registers", "fpr", k_num_fpr_registers,
|
||||
g_fpr_regnums_loongarch64}};
|
||||
g_fpr_regnums_loongarch64},
|
||||
{"LSX Vector Registers", "lsx", k_num_lsx_registers,
|
||||
g_lsx_regnums_loongarch64},
|
||||
{"LASX Vector Registers", "lasx", k_num_lasx_registers,
|
||||
g_lasx_regnums_loongarch64}};
|
||||
|
||||
RegisterInfoPOSIX_loongarch64::RegisterInfoPOSIX_loongarch64(
|
||||
const lldb_private::ArchSpec &target_arch, lldb_private::Flags flags)
|
||||
@@ -147,6 +200,10 @@ size_t RegisterInfoPOSIX_loongarch64::GetRegisterSetFromRegisterIndex(
|
||||
return GPRegSet;
|
||||
if (reg_index >= fpr_first_loongarch && reg_index <= fpr_last_loongarch)
|
||||
return FPRegSet;
|
||||
if (reg_index >= lsx_first_loongarch && reg_index <= lsx_last_loongarch)
|
||||
return LSXRegSet;
|
||||
if (reg_index >= lasx_first_loongarch && reg_index <= lasx_last_loongarch)
|
||||
return LASXRegSet;
|
||||
return LLDB_INVALID_REGNUM;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@ public:
|
||||
enum RegSetKind {
|
||||
GPRegSet,
|
||||
FPRegSet,
|
||||
LSXRegSet,
|
||||
LASXRegSet,
|
||||
};
|
||||
|
||||
struct GPR {
|
||||
@@ -43,6 +45,16 @@ public:
|
||||
uint32_t fcsr;
|
||||
};
|
||||
|
||||
/* 32 registers, 128 bits width per register. */
|
||||
struct LSX {
|
||||
uint64_t vr[32 * 2];
|
||||
};
|
||||
|
||||
/* 32 registers, 256 bits width per register. */
|
||||
struct LASX {
|
||||
uint64_t xr[32 * 4];
|
||||
};
|
||||
|
||||
RegisterInfoPOSIX_loongarch64(const lldb_private::ArchSpec &target_arch,
|
||||
lldb_private::Flags flags);
|
||||
|
||||
|
||||
@@ -25,6 +25,14 @@
|
||||
#error FPR_OFFSET must be defined before including this header file
|
||||
#endif
|
||||
|
||||
#ifndef LSX_OFFSET
|
||||
#error LSX_OFFSET must be defined before including this header file
|
||||
#endif
|
||||
|
||||
#ifndef LASX_OFFSET
|
||||
#error LASX_OFFSET must be defined before including this header file
|
||||
#endif
|
||||
|
||||
using namespace loongarch_dwarf;
|
||||
|
||||
// clang-format off
|
||||
@@ -74,6 +82,21 @@ using namespace loongarch_dwarf;
|
||||
FPR64_KIND(fpr_##reg, generic_kind), nullptr, nullptr, nullptr, \
|
||||
}
|
||||
|
||||
#define DEFINE_LSX(reg, generic_kind) \
|
||||
{ \
|
||||
#reg, nullptr, 16, LSX_OFFSET(lsx_##reg##_loongarch - lsx_first_loongarch),\
|
||||
lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, \
|
||||
KIND_HELPER(lsx_##reg, generic_kind), nullptr, nullptr, nullptr, \
|
||||
}
|
||||
|
||||
#define DEFINE_LASX(reg, generic_kind) \
|
||||
{ \
|
||||
#reg, nullptr, 32, \
|
||||
LASX_OFFSET(lasx_##reg##_loongarch - lasx_first_loongarch), \
|
||||
lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, \
|
||||
KIND_HELPER(lasx_##reg, generic_kind), nullptr, nullptr, nullptr, \
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
|
||||
static lldb_private::RegisterInfo g_register_infos_loongarch64[] = {
|
||||
@@ -166,6 +189,72 @@ static lldb_private::RegisterInfo g_register_infos_loongarch64[] = {
|
||||
DEFINE_FCC(fcc6, LLDB_INVALID_REGNUM),
|
||||
DEFINE_FCC(fcc7, LLDB_INVALID_REGNUM),
|
||||
DEFINE_FCSR(fcsr, LLDB_INVALID_REGNUM),
|
||||
|
||||
DEFINE_LSX(vr0, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr1, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr2, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr3, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr4, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr5, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr6, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr7, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr8, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr9, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr10, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr11, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr12, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr13, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr14, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr15, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr16, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr17, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr18, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr19, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr20, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr21, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr22, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr23, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr24, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr25, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr26, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr27, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr28, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr29, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr30, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LSX(vr31, LLDB_INVALID_REGNUM),
|
||||
|
||||
DEFINE_LASX(xr0, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr1, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr2, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr3, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr4, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr5, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr6, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr7, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr8, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr9, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr10, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr11, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr12, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr13, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr14, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr15, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr16, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr17, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr18, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr19, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr20, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr21, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr22, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr23, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr24, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr25, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr26, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr27, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr28, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr29, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr30, LLDB_INVALID_REGNUM),
|
||||
DEFINE_LASX(xr31, LLDB_INVALID_REGNUM),
|
||||
};
|
||||
|
||||
#endif // DECLARE_REGISTER_INFOS_LOONGARCH64_STRUCT
|
||||
|
||||
@@ -172,6 +172,76 @@ enum {
|
||||
fpr_fs6_loongarch = fpr_f30_loongarch,
|
||||
fpr_fs7_loongarch = fpr_f31_loongarch,
|
||||
|
||||
lsx_first_loongarch = fpr_last_loongarch + 1,
|
||||
lsx_vr0_loongarch = lsx_first_loongarch,
|
||||
lsx_vr1_loongarch,
|
||||
lsx_vr2_loongarch,
|
||||
lsx_vr3_loongarch,
|
||||
lsx_vr4_loongarch,
|
||||
lsx_vr5_loongarch,
|
||||
lsx_vr6_loongarch,
|
||||
lsx_vr7_loongarch,
|
||||
lsx_vr8_loongarch,
|
||||
lsx_vr9_loongarch,
|
||||
lsx_vr10_loongarch,
|
||||
lsx_vr11_loongarch,
|
||||
lsx_vr12_loongarch,
|
||||
lsx_vr13_loongarch,
|
||||
lsx_vr14_loongarch,
|
||||
lsx_vr15_loongarch,
|
||||
lsx_vr16_loongarch,
|
||||
lsx_vr17_loongarch,
|
||||
lsx_vr18_loongarch,
|
||||
lsx_vr19_loongarch,
|
||||
lsx_vr20_loongarch,
|
||||
lsx_vr21_loongarch,
|
||||
lsx_vr22_loongarch,
|
||||
lsx_vr23_loongarch,
|
||||
lsx_vr24_loongarch,
|
||||
lsx_vr25_loongarch,
|
||||
lsx_vr26_loongarch,
|
||||
lsx_vr27_loongarch,
|
||||
lsx_vr28_loongarch,
|
||||
lsx_vr29_loongarch,
|
||||
lsx_vr30_loongarch,
|
||||
lsx_vr31_loongarch,
|
||||
lsx_last_loongarch = lsx_vr31_loongarch,
|
||||
|
||||
lasx_first_loongarch = lsx_last_loongarch + 1,
|
||||
lasx_xr0_loongarch = lasx_first_loongarch,
|
||||
lasx_xr1_loongarch,
|
||||
lasx_xr2_loongarch,
|
||||
lasx_xr3_loongarch,
|
||||
lasx_xr4_loongarch,
|
||||
lasx_xr5_loongarch,
|
||||
lasx_xr6_loongarch,
|
||||
lasx_xr7_loongarch,
|
||||
lasx_xr8_loongarch,
|
||||
lasx_xr9_loongarch,
|
||||
lasx_xr10_loongarch,
|
||||
lasx_xr11_loongarch,
|
||||
lasx_xr12_loongarch,
|
||||
lasx_xr13_loongarch,
|
||||
lasx_xr14_loongarch,
|
||||
lasx_xr15_loongarch,
|
||||
lasx_xr16_loongarch,
|
||||
lasx_xr17_loongarch,
|
||||
lasx_xr18_loongarch,
|
||||
lasx_xr19_loongarch,
|
||||
lasx_xr20_loongarch,
|
||||
lasx_xr21_loongarch,
|
||||
lasx_xr22_loongarch,
|
||||
lasx_xr23_loongarch,
|
||||
lasx_xr24_loongarch,
|
||||
lasx_xr25_loongarch,
|
||||
lasx_xr26_loongarch,
|
||||
lasx_xr27_loongarch,
|
||||
lasx_xr28_loongarch,
|
||||
lasx_xr29_loongarch,
|
||||
lasx_xr30_loongarch,
|
||||
lasx_xr31_loongarch,
|
||||
lasx_last_loongarch = lasx_xr31_loongarch,
|
||||
|
||||
k_num_registers_loongarch
|
||||
};
|
||||
|
||||
|
||||
@@ -90,6 +90,72 @@ enum {
|
||||
dwarf_fpr_fcc7,
|
||||
dwarf_fpr_fcsr,
|
||||
|
||||
dwarf_lsx_vr0,
|
||||
dwarf_lsx_vr1,
|
||||
dwarf_lsx_vr2,
|
||||
dwarf_lsx_vr3,
|
||||
dwarf_lsx_vr4,
|
||||
dwarf_lsx_vr5,
|
||||
dwarf_lsx_vr6,
|
||||
dwarf_lsx_vr7,
|
||||
dwarf_lsx_vr8,
|
||||
dwarf_lsx_vr9,
|
||||
dwarf_lsx_vr10,
|
||||
dwarf_lsx_vr11,
|
||||
dwarf_lsx_vr12,
|
||||
dwarf_lsx_vr13,
|
||||
dwarf_lsx_vr14,
|
||||
dwarf_lsx_vr15,
|
||||
dwarf_lsx_vr16,
|
||||
dwarf_lsx_vr17,
|
||||
dwarf_lsx_vr18,
|
||||
dwarf_lsx_vr19,
|
||||
dwarf_lsx_vr20,
|
||||
dwarf_lsx_vr21,
|
||||
dwarf_lsx_vr22,
|
||||
dwarf_lsx_vr23,
|
||||
dwarf_lsx_vr24,
|
||||
dwarf_lsx_vr25,
|
||||
dwarf_lsx_vr26,
|
||||
dwarf_lsx_vr27,
|
||||
dwarf_lsx_vr28,
|
||||
dwarf_lsx_vr29,
|
||||
dwarf_lsx_vr30,
|
||||
dwarf_lsx_vr31,
|
||||
|
||||
dwarf_lasx_xr0,
|
||||
dwarf_lasx_xr1,
|
||||
dwarf_lasx_xr2,
|
||||
dwarf_lasx_xr3,
|
||||
dwarf_lasx_xr4,
|
||||
dwarf_lasx_xr5,
|
||||
dwarf_lasx_xr6,
|
||||
dwarf_lasx_xr7,
|
||||
dwarf_lasx_xr8,
|
||||
dwarf_lasx_xr9,
|
||||
dwarf_lasx_xr10,
|
||||
dwarf_lasx_xr11,
|
||||
dwarf_lasx_xr12,
|
||||
dwarf_lasx_xr13,
|
||||
dwarf_lasx_xr14,
|
||||
dwarf_lasx_xr15,
|
||||
dwarf_lasx_xr16,
|
||||
dwarf_lasx_xr17,
|
||||
dwarf_lasx_xr18,
|
||||
dwarf_lasx_xr19,
|
||||
dwarf_lasx_xr20,
|
||||
dwarf_lasx_xr21,
|
||||
dwarf_lasx_xr22,
|
||||
dwarf_lasx_xr23,
|
||||
dwarf_lasx_xr24,
|
||||
dwarf_lasx_xr25,
|
||||
dwarf_lasx_xr26,
|
||||
dwarf_lasx_xr27,
|
||||
dwarf_lasx_xr28,
|
||||
dwarf_lasx_xr29,
|
||||
dwarf_lasx_xr30,
|
||||
dwarf_lasx_xr31,
|
||||
|
||||
// register name alias
|
||||
dwarf_gpr_zero = dwarf_gpr_r0,
|
||||
dwarf_gpr_ra = dwarf_gpr_r1,
|
||||
|
||||
3
lldb/test/API/linux/loongarch64/simd_registers/Makefile
Normal file
3
lldb/test/API/linux/loongarch64/simd_registers/Makefile
Normal file
@@ -0,0 +1,3 @@
|
||||
C_SOURCES := main.c
|
||||
|
||||
include Makefile.rules
|
||||
@@ -0,0 +1,93 @@
|
||||
"""
|
||||
Test lldb's ability to read and write the LoongArch SIMD registers.
|
||||
"""
|
||||
|
||||
from enum import Enum
|
||||
import lldb
|
||||
from lldbsuite.test.decorators import *
|
||||
from lldbsuite.test.lldbtest import *
|
||||
from lldbsuite.test import lldbutil
|
||||
|
||||
|
||||
class Mode(Enum):
|
||||
LSX = 0
|
||||
LASX = 1
|
||||
|
||||
|
||||
class LoongArch64LinuxRegisters(TestBase):
|
||||
NO_DEBUG_INFO_TESTCASE = True
|
||||
|
||||
def get_build_flags(self, mode):
|
||||
cflags = "-march=la464"
|
||||
if mode == Mode.LASX:
|
||||
cflags += " -DLASX"
|
||||
|
||||
return {"CFLAGS_EXTRAS": cflags}
|
||||
|
||||
def make_simd_value(self, n, mode):
|
||||
count = 32 if mode == Mode.LASX else 16
|
||||
return "{" + " ".join(["0x{:02x}".format(n)] * count) + "}"
|
||||
|
||||
def check_simd_values(self, value_offset, mode):
|
||||
reg_prefix = "xr" if mode == Mode.LASX else "vr"
|
||||
for i in range(32):
|
||||
self.expect(
|
||||
"register read {}{}".format(reg_prefix, i),
|
||||
substrs=[self.make_simd_value(i + value_offset, mode)],
|
||||
)
|
||||
|
||||
def simd_registers_impl(self, mode):
|
||||
self.build(dictionary=self.get_build_flags(mode))
|
||||
self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
|
||||
|
||||
lldbutil.run_break_set_by_file_and_line(
|
||||
self,
|
||||
"main.c",
|
||||
line_number("main.c", "// Set break point at this line."),
|
||||
num_expected_locations=1,
|
||||
)
|
||||
|
||||
self.runCmd("run", RUN_SUCCEEDED)
|
||||
|
||||
if self.process().GetState() == lldb.eStateExited:
|
||||
self.fail("Test program failed to run.")
|
||||
|
||||
self.expect(
|
||||
"thread list",
|
||||
STOPPED_DUE_TO_BREAKPOINT,
|
||||
substrs=["stopped", "stop reason = breakpoint"],
|
||||
)
|
||||
|
||||
self.check_simd_values(0, mode)
|
||||
self.runCmd("expression write_simd_regs(1)")
|
||||
self.check_simd_values(0, mode)
|
||||
|
||||
reg_prefix = "xr" if mode == Mode.LASX else "vr"
|
||||
for i in range(32):
|
||||
self.runCmd(
|
||||
'register write {}{} "{}"'.format(
|
||||
reg_prefix, i, self.make_simd_value(i + 1, mode)
|
||||
)
|
||||
)
|
||||
|
||||
# Should be visible within lldb.
|
||||
self.check_simd_values(1, mode)
|
||||
|
||||
# The program should agree with lldb.
|
||||
self.expect("continue", substrs=["exited with status = 0"])
|
||||
|
||||
@skipUnlessArch("loongarch64")
|
||||
@skipUnlessPlatform(["linux"])
|
||||
def test_lsx(self):
|
||||
"""Test read/write of LSX registers."""
|
||||
if not self.isLoongArchLSX():
|
||||
self.skipTest("LSX must be present.")
|
||||
self.simd_registers_impl(Mode.LSX)
|
||||
|
||||
@skipUnlessArch("loongarch64")
|
||||
@skipUnlessPlatform(["linux"])
|
||||
def test_lasx(self):
|
||||
"""Test read/write of LASX registers."""
|
||||
if not self.isLoongArchLASX():
|
||||
self.skipTest("LASX must be present.")
|
||||
self.simd_registers_impl(Mode.LASX)
|
||||
108
lldb/test/API/linux/loongarch64/simd_registers/main.c
Normal file
108
lldb/test/API/linux/loongarch64/simd_registers/main.c
Normal file
@@ -0,0 +1,108 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef LASX
|
||||
#define ELEM_COUNT 32
|
||||
#define REPLGR2VR_B "xvreplgr2vr.b $xr"
|
||||
#define ST "xvst $xr"
|
||||
#else
|
||||
#define ELEM_COUNT 16
|
||||
#define REPLGR2VR_B "vreplgr2vr.b $vr"
|
||||
#define ST "vst $vr"
|
||||
#endif
|
||||
|
||||
// base is added to each value. If base = 2, then
|
||||
// assume the vector element type is char:
|
||||
// $reg0 = { 0x02 * $ELEM_COUNT }
|
||||
// $reg1 = { 0x03 * $ELEM_COUNT } etc.
|
||||
void write_simd_regs(unsigned base) {
|
||||
#define WRITE_SIMD(NUM) \
|
||||
asm volatile(REPLGR2VR_B #NUM ", %0\n\t" ::"r"(base + NUM))
|
||||
WRITE_SIMD(0);
|
||||
WRITE_SIMD(1);
|
||||
WRITE_SIMD(2);
|
||||
WRITE_SIMD(3);
|
||||
WRITE_SIMD(4);
|
||||
WRITE_SIMD(5);
|
||||
WRITE_SIMD(6);
|
||||
WRITE_SIMD(7);
|
||||
WRITE_SIMD(8);
|
||||
WRITE_SIMD(9);
|
||||
WRITE_SIMD(10);
|
||||
WRITE_SIMD(11);
|
||||
WRITE_SIMD(12);
|
||||
WRITE_SIMD(13);
|
||||
WRITE_SIMD(14);
|
||||
WRITE_SIMD(15);
|
||||
WRITE_SIMD(16);
|
||||
WRITE_SIMD(17);
|
||||
WRITE_SIMD(18);
|
||||
WRITE_SIMD(19);
|
||||
WRITE_SIMD(20);
|
||||
WRITE_SIMD(21);
|
||||
WRITE_SIMD(22);
|
||||
WRITE_SIMD(23);
|
||||
WRITE_SIMD(24);
|
||||
WRITE_SIMD(25);
|
||||
WRITE_SIMD(26);
|
||||
WRITE_SIMD(27);
|
||||
WRITE_SIMD(28);
|
||||
WRITE_SIMD(29);
|
||||
WRITE_SIMD(30);
|
||||
WRITE_SIMD(31);
|
||||
}
|
||||
|
||||
unsigned verify_simd_regs() {
|
||||
uint8_t simd_reg[ELEM_COUNT];
|
||||
uint8_t target = 0;
|
||||
|
||||
#define VERIFY_SIMD(NUM) \
|
||||
do { \
|
||||
for (int i = 0; i < ELEM_COUNT; ++i) \
|
||||
simd_reg[i] = 0; \
|
||||
asm volatile(ST #NUM ", %0\n\t" ::"m"(simd_reg)); \
|
||||
target = NUM + 1; \
|
||||
for (int i = 0; i < ELEM_COUNT; ++i) \
|
||||
if (simd_reg[i] != target) \
|
||||
return 1; \
|
||||
} while (0)
|
||||
|
||||
VERIFY_SIMD(0);
|
||||
VERIFY_SIMD(1);
|
||||
VERIFY_SIMD(2);
|
||||
VERIFY_SIMD(3);
|
||||
VERIFY_SIMD(4);
|
||||
VERIFY_SIMD(5);
|
||||
VERIFY_SIMD(6);
|
||||
VERIFY_SIMD(7);
|
||||
VERIFY_SIMD(8);
|
||||
VERIFY_SIMD(9);
|
||||
VERIFY_SIMD(10);
|
||||
VERIFY_SIMD(11);
|
||||
VERIFY_SIMD(12);
|
||||
VERIFY_SIMD(13);
|
||||
VERIFY_SIMD(14);
|
||||
VERIFY_SIMD(15);
|
||||
VERIFY_SIMD(16);
|
||||
VERIFY_SIMD(17);
|
||||
VERIFY_SIMD(18);
|
||||
VERIFY_SIMD(19);
|
||||
VERIFY_SIMD(20);
|
||||
VERIFY_SIMD(21);
|
||||
VERIFY_SIMD(22);
|
||||
VERIFY_SIMD(23);
|
||||
VERIFY_SIMD(24);
|
||||
VERIFY_SIMD(25);
|
||||
VERIFY_SIMD(26);
|
||||
VERIFY_SIMD(27);
|
||||
VERIFY_SIMD(28);
|
||||
VERIFY_SIMD(29);
|
||||
VERIFY_SIMD(30);
|
||||
VERIFY_SIMD(31);
|
||||
|
||||
return 0;
|
||||
}
|
||||
int main(int argc, char *argv[]) {
|
||||
write_simd_regs(0);
|
||||
|
||||
return verify_simd_regs(); // Set break point at this line.
|
||||
}
|
||||
Reference in New Issue
Block a user