diff --git a/src/coreclr/binder/assemblybindercommon.cpp b/src/coreclr/binder/assemblybindercommon.cpp index 4e0bad0e843393..7ee601707aa10b 100644 --- a/src/coreclr/binder/assemblybindercommon.cpp +++ b/src/coreclr/binder/assemblybindercommon.cpp @@ -1326,7 +1326,7 @@ BOOL AssemblyBinderCommon::IsValidArchitecture(PEKIND kArchitecture) #elif defined(TARGET_ARM64) peARM64; #else - PORTABILITY_ASSERT("processArchitecture"); + peMSIL; #endif return (kArchitecture == processArchitecture); diff --git a/src/coreclr/debug/createdump/datatarget.cpp b/src/coreclr/debug/createdump/datatarget.cpp index 02c63822cfd8e3..d2efc6e2615f39 100644 --- a/src/coreclr/debug/createdump/datatarget.cpp +++ b/src/coreclr/debug/createdump/datatarget.cpp @@ -69,6 +69,8 @@ DumpDataTarget::GetMachineType( *machine = IMAGE_FILE_MACHINE_ARM64; #elif HOST_X86 *machine = IMAGE_FILE_MACHINE_I386; +#elif HOST_LOONGARCH64 + *machine = IMAGE_FILE_MACHINE_LOONGARCH64; #else #error Unsupported architecture #endif @@ -79,7 +81,7 @@ HRESULT STDMETHODCALLTYPE DumpDataTarget::GetPointerSize( /* [out] */ ULONG32 *size) { -#if defined(HOST_AMD64) || defined(HOST_ARM64) +#if defined(HOST_AMD64) || defined(HOST_ARM64) || defined(HOST_LOONGARCH64) *size = 8; #elif defined(HOST_ARM) || defined(HOST_X86) *size = 4; diff --git a/src/coreclr/debug/createdump/dumpwriterelf.h b/src/coreclr/debug/createdump/dumpwriterelf.h index 6da55da2f13750..cb8731871de211 100644 --- a/src/coreclr/debug/createdump/dumpwriterelf.h +++ b/src/coreclr/debug/createdump/dumpwriterelf.h @@ -21,6 +21,8 @@ #define ELF_ARCH EM_AARCH64 #elif defined(__arm__) #define ELF_ARCH EM_ARM +#elif defined(__loongarch64) +#define ELF_ARCH EM_LOONGARCH #endif #define PH_HDR_CANARY 0xFFFF diff --git a/src/coreclr/debug/createdump/memoryregion.h b/src/coreclr/debug/createdump/memoryregion.h index b5bb44f67a2cdf..c7f1765ccd02bd 100644 --- a/src/coreclr/debug/createdump/memoryregion.h +++ b/src/coreclr/debug/createdump/memoryregion.h @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if !defined(PAGE_SIZE) && (defined(__arm__) || defined(__aarch64__)) +#if !defined(PAGE_SIZE) && (defined(__arm__) || defined(__aarch64__) || defined(__loongarch64)) #define PAGE_SIZE sysconf(_SC_PAGESIZE) #endif diff --git a/src/coreclr/debug/createdump/threadinfo.h b/src/coreclr/debug/createdump/threadinfo.h index 4142b55e333dd7..ed82c1ec51a652 100644 --- a/src/coreclr/debug/createdump/threadinfo.h +++ b/src/coreclr/debug/createdump/threadinfo.h @@ -12,6 +12,14 @@ class CrashInfo; #define MCREG_Cpsr(mc) ((mc).pstate) #endif +#if defined(__loongarch64) +// See src/coreclr/pal/src/include/pal/context.h +#define MCREG_Ra(mc) ((mc).gpr[1]) +#define MCREG_Fp(mc) ((mc).gpr[22]) +#define MCREG_Sp(mc) ((mc).gpr[3]) +#define MCREG_Pc(mc) ((mc).pc) +#endif + #define FPREG_ErrorOffset(fpregs) *(DWORD*)&((fpregs).rip) #define FPREG_ErrorSelector(fpregs) *(((WORD*)&((fpregs).rip)) + 2) #define FPREG_DataOffset(fpregs) *(DWORD*)&((fpregs).rdp) @@ -19,6 +27,14 @@ class CrashInfo; #if defined(__arm__) #define user_regs_struct user_regs #define user_fpregs_struct user_fpregs +#elif defined(__loongarch64) +// struct user_regs_struct {} defined `/usr/include/loongarch64-linux-gnu/sys/user.h` + +struct user_fpregs_struct +{ + unsigned long long fpregs[32]; + unsigned long fpscr; +} __attribute__((__packed__)); #endif #if defined(__aarch64__) @@ -130,6 +146,10 @@ class ThreadInfo inline const uint64_t GetInstructionPointer() const { return MCREG_Pc(m_gpRegisters); } inline const uint64_t GetStackPointer() const { return MCREG_Sp(m_gpRegisters); } inline const uint64_t GetFramePointer() const { return MCREG_Fp(m_gpRegisters); } +#elif defined(__loongarch64) + inline const uint64_t GetInstructionPointer() const { return MCREG_Pc(m_gpRegisters); } + inline const uint64_t GetStackPointer() const { return MCREG_Sp(m_gpRegisters); } + inline const uint64_t GetFramePointer() const { return MCREG_Fp(m_gpRegisters); } #elif defined(__arm__) inline const uint64_t GetInstructionPointer() const { return m_gpRegisters.ARM_pc; } inline const uint64_t GetStackPointer() const { return m_gpRegisters.ARM_sp; } diff --git a/src/coreclr/debug/createdump/threadinfounix.cpp b/src/coreclr/debug/createdump/threadinfounix.cpp index 37af34ca2836e1..8474fcb5964bb8 100644 --- a/src/coreclr/debug/createdump/threadinfounix.cpp +++ b/src/coreclr/debug/createdump/threadinfounix.cpp @@ -57,6 +57,8 @@ ThreadInfo::Initialize() TRACE("Thread %04x PC %08lx SP %08lx\n", m_tid, (unsigned long)m_gpRegisters.ARM_pc, (unsigned long)m_gpRegisters.ARM_sp); #elif defined(__x86_64__) TRACE("Thread %04x RIP %016llx RSP %016llx\n", m_tid, (unsigned long long)m_gpRegisters.rip, (unsigned long long)m_gpRegisters.rsp); +#elif defined(__loongarch64) + TRACE("Thread %04x PC %016llx SP %016llx\n", m_tid, (unsigned long long)m_gpRegisters.pc, (unsigned long long)m_gpRegisters.gpr[3]); #else #error "Unsupported architecture" #endif @@ -221,6 +223,26 @@ ThreadInfo::GetThreadContext(uint32_t flags, CONTEXT* context) const memcpy(context->D, m_vfpRegisters.fpregs, sizeof(context->D)); #endif } +#elif defined(__loongarch64) + if ((flags & CONTEXT_CONTROL) == CONTEXT_CONTROL) + { + context->Ra = MCREG_Ra(m_gpRegisters); + context->Sp = MCREG_Sp(m_gpRegisters); + context->Fp = MCREG_Fp(m_gpRegisters); + context->Pc = MCREG_Pc(m_gpRegisters); + } + if ((flags & CONTEXT_INTEGER) == CONTEXT_INTEGER) + { + context->Tp = m_gpRegisters.gpr[2]; + memcpy(&context->A0, &m_gpRegisters.gpr[4], sizeof(context->A0)*(21 - 4 + 1)); + memcpy(&context->S0, &m_gpRegisters.gpr[23], sizeof(context->S0)*9); + } + if ((flags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) + { + assert(sizeof(context->F) == sizeof(m_fpRegisters.fpregs)); + memcpy(context->F, m_fpRegisters.fpregs, sizeof(context->F)); + context->Fcsr = m_fpRegisters.fpscr; + } #else #error Platform not supported #endif diff --git a/src/coreclr/debug/daccess/daccess.cpp b/src/coreclr/debug/daccess/daccess.cpp index 3981d2116799a5..55fb9688ffe472 100644 --- a/src/coreclr/debug/daccess/daccess.cpp +++ b/src/coreclr/debug/daccess/daccess.cpp @@ -5514,6 +5514,8 @@ ClrDataAccess::Initialize(void) CorDebugPlatform hostPlatform = CORDB_PLATFORM_POSIX_ARM; #elif defined(TARGET_ARM64) CorDebugPlatform hostPlatform = CORDB_PLATFORM_POSIX_ARM64; + #elif defined(TARGET_LOONGARCH64) + CorDebugPlatform hostPlatform = CORDB_PLATFORM_POSIX_LOONGARCH64; #else #error Unknown Processor. #endif diff --git a/src/coreclr/debug/daccess/loongarch64/primitives.cpp b/src/coreclr/debug/daccess/loongarch64/primitives.cpp new file mode 100644 index 00000000000000..34d5201c080819 --- /dev/null +++ b/src/coreclr/debug/daccess/loongarch64/primitives.cpp @@ -0,0 +1,6 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "stdafx.h" + +#include "../../shared/loongarch64/primitives.cpp" diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index 79d6e4749397c4..05450da10f90f2 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -624,6 +624,18 @@ ClrDataAccess::GetRegisterName(int regNum, unsigned int count, _Inout_updates_z_ { W("eax"), W("ecx"), W("edx"), W("ebx"), W("esp"), W("ebp"), W("esi"), W("edi"), }; +#elif defined(TARGET_LOONGARCH64) + static const WCHAR *regs[] = + { + W("R0"), W("AT"), W("V0"), W("V1"), + W("A0"), W("A1"), W("A2"), W("A3"), + W("A4"), W("A5"), W("A6"), W("A7"), + W("T0"), W("T1"), W("T2"), W("T3"), + W("T8"), W("T9"), W("S0"), W("S1"), + W("S2"), W("S3"), W("S4"), W("S5"), + W("S6"), W("S7"), W("K0"), W("K1"), + W("GP"), W("SP"), W("FP"), W("RA") + }; #endif // Caller frame registers are encoded as "-(reg+1)". diff --git a/src/coreclr/debug/dbgutil/elfreader.cpp b/src/coreclr/debug/dbgutil/elfreader.cpp index ace4d09dad19d7..b6fa979ae05b1d 100644 --- a/src/coreclr/debug/dbgutil/elfreader.cpp +++ b/src/coreclr/debug/dbgutil/elfreader.cpp @@ -554,6 +554,8 @@ Elf64_Ehdr::Elf64_Ehdr() e_machine = EM_X86_64; #elif defined(TARGET_ARM64) e_machine = EM_AARCH64; +#elif defined(TARGET_LOONGARCH64) + e_machine = EM_LOONGARCH; #endif e_flags = 0; e_version = 1; diff --git a/src/coreclr/debug/di/CMakeLists.txt b/src/coreclr/debug/di/CMakeLists.txt index b0272c4d2518d8..f45a27ac7a9d5e 100644 --- a/src/coreclr/debug/di/CMakeLists.txt +++ b/src/coreclr/debug/di/CMakeLists.txt @@ -67,7 +67,7 @@ if(CLR_CMAKE_HOST_WIN32) endif() elseif(CLR_CMAKE_HOST_UNIX) - if(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_ARM) + if(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_LOONGARCH64) set(CORDBDI_SOURCES_ASM_FILE ${ARCH_SOURCES_DIR}/floatconversion.S ) diff --git a/src/coreclr/debug/di/loongarch64/cordbregisterset.cpp b/src/coreclr/debug/di/loongarch64/cordbregisterset.cpp new file mode 100644 index 00000000000000..679509e61b2b8e --- /dev/null +++ b/src/coreclr/debug/di/loongarch64/cordbregisterset.cpp @@ -0,0 +1,295 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +//***************************************************************************** +// File: CordbRegisterSet.cpp +// + +// +//***************************************************************************** +#include "primitives.h" + + +HRESULT CordbRegisterSet::GetRegistersAvailable(ULONG64* pAvailable) +{ + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(pAvailable, ULONG64 *); + + *pAvailable = SETBITULONG64(REGISTER_LOONGARCH64_PC) + | SETBITULONG64(REGISTER_LOONGARCH64_SP) + | SETBITULONG64(REGISTER_LOONGARCH64_FP) + | SETBITULONG64(REGISTER_LOONGARCH64_RA) + | SETBITULONG64(REGISTER_LOONGARCH64_TP) + | SETBITULONG64(REGISTER_LOONGARCH64_A0) + | SETBITULONG64(REGISTER_LOONGARCH64_A1) + | SETBITULONG64(REGISTER_LOONGARCH64_A2) + | SETBITULONG64(REGISTER_LOONGARCH64_A3) + | SETBITULONG64(REGISTER_LOONGARCH64_A4) + | SETBITULONG64(REGISTER_LOONGARCH64_A5) + | SETBITULONG64(REGISTER_LOONGARCH64_A6) + | SETBITULONG64(REGISTER_LOONGARCH64_A7) + | SETBITULONG64(REGISTER_LOONGARCH64_T0) + | SETBITULONG64(REGISTER_LOONGARCH64_T1) + | SETBITULONG64(REGISTER_LOONGARCH64_T2) + | SETBITULONG64(REGISTER_LOONGARCH64_T3) + | SETBITULONG64(REGISTER_LOONGARCH64_T4) + | SETBITULONG64(REGISTER_LOONGARCH64_T5) + | SETBITULONG64(REGISTER_LOONGARCH64_T6) + | SETBITULONG64(REGISTER_LOONGARCH64_T7) + | SETBITULONG64(REGISTER_LOONGARCH64_T8) + | SETBITULONG64(REGISTER_LOONGARCH64_X0) + | SETBITULONG64(REGISTER_LOONGARCH64_S0) + | SETBITULONG64(REGISTER_LOONGARCH64_S1) + | SETBITULONG64(REGISTER_LOONGARCH64_S2) + | SETBITULONG64(REGISTER_LOONGARCH64_S3) + | SETBITULONG64(REGISTER_LOONGARCH64_S4) + | SETBITULONG64(REGISTER_LOONGARCH64_S5) + | SETBITULONG64(REGISTER_LOONGARCH64_S6) + | SETBITULONG64(REGISTER_LOONGARCH64_S7) + | SETBITULONG64(REGISTER_LOONGARCH64_S8) + | SETBITULONG64(REGISTER_LOONGARCH64_F0) + | SETBITULONG64(REGISTER_LOONGARCH64_F1) + | SETBITULONG64(REGISTER_LOONGARCH64_F2) + | SETBITULONG64(REGISTER_LOONGARCH64_F3) + | SETBITULONG64(REGISTER_LOONGARCH64_F4) + | SETBITULONG64(REGISTER_LOONGARCH64_F5) + | SETBITULONG64(REGISTER_LOONGARCH64_F6) + | SETBITULONG64(REGISTER_LOONGARCH64_F7) + | SETBITULONG64(REGISTER_LOONGARCH64_F8) + | SETBITULONG64(REGISTER_LOONGARCH64_F9) + | SETBITULONG64(REGISTER_LOONGARCH64_F10) + | SETBITULONG64(REGISTER_LOONGARCH64_F11) + | SETBITULONG64(REGISTER_LOONGARCH64_F12) + | SETBITULONG64(REGISTER_LOONGARCH64_F13) + | SETBITULONG64(REGISTER_LOONGARCH64_F14) + | SETBITULONG64(REGISTER_LOONGARCH64_F15) + | SETBITULONG64(REGISTER_LOONGARCH64_F16) + | SETBITULONG64(REGISTER_LOONGARCH64_F17) + | SETBITULONG64(REGISTER_LOONGARCH64_F18) + | SETBITULONG64(REGISTER_LOONGARCH64_F19) + | SETBITULONG64(REGISTER_LOONGARCH64_F20) + | SETBITULONG64(REGISTER_LOONGARCH64_F21) + | SETBITULONG64(REGISTER_LOONGARCH64_F22) + | SETBITULONG64(REGISTER_LOONGARCH64_F23) + | SETBITULONG64(REGISTER_LOONGARCH64_F24) + | SETBITULONG64(REGISTER_LOONGARCH64_F25) + | SETBITULONG64(REGISTER_LOONGARCH64_F26) + | SETBITULONG64(REGISTER_LOONGARCH64_F27) + | SETBITULONG64(REGISTER_LOONGARCH64_F28) + | SETBITULONG64(REGISTER_LOONGARCH64_F29) + | SETBITULONG64(REGISTER_LOONGARCH64_F30) + | SETBITULONG64(REGISTER_LOONGARCH64_F31); + + return S_OK; +} + +HRESULT CordbRegisterSet::GetRegisters(ULONG64 mask, ULONG32 regCount, + CORDB_REGISTER regBuffer[]) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); + + UINT iRegister = 0; + + VALIDATE_POINTER_TO_OBJECT_ARRAY(regBuffer, CORDB_REGISTER, regCount, true, true); + + for (int i = REGISTER_LOONGARCH64_PC; + i <= REGISTER_LOONGARCH64_F31 && iRegister < regCount; + i++) + { + if (mask & SETBITULONG64(i)) + { + _ASSERTE (iRegister < regCount); + + if ((i >= REGISTER_LOONGARCH64_A0) && (i <= REGISTER_LOONGARCH64_X0)) + { + regBuffer[iRegister++] = *(ULONG64*)((char*)(&m_rd->A0) + ((i - REGISTER_LOONGARCH64_A0) << 3)); + continue; + } + + if ((i >= REGISTER_LOONGARCH64_S0) && (i <= REGISTER_LOONGARCH64_S8)) + { + regBuffer[iRegister++] = *(ULONG64*)((char*)(&m_rd->S0) + ((i - REGISTER_LOONGARCH64_S0) << 3)); + continue; + } + + if ((i >= REGISTER_LOONGARCH64_F0) && (i <= REGISTER_LOONGARCH64_F31)) + { + if (!m_thread->m_fFloatStateValid) + { + HRESULT hr = S_OK; + EX_TRY + { + m_thread->LoadFloatState(); + } + EX_CATCH_HRESULT(hr); + + if ( !SUCCEEDED(hr) ) + { + return hr; + } + LOG( ( LF_CORDB, LL_INFO1000, "CRS::GR: Loaded float state\n" ) ); + } + + regBuffer[iRegister++] = *(CORDB_REGISTER*) + &(m_thread->m_floatValues[(i - REGISTER_LOONGARCH64_F0)]); + continue; + } + + switch (i) + { + case REGISTER_LOONGARCH64_PC: + regBuffer[iRegister++] = m_rd->PC; break; + case REGISTER_LOONGARCH64_SP: + regBuffer[iRegister++] = m_rd->SP; break; + case REGISTER_LOONGARCH64_FP: + regBuffer[iRegister++] = m_rd->FP; break; + case REGISTER_LOONGARCH64_RA: + regBuffer[iRegister++] = m_rd->RA; break; + case REGISTER_LOONGARCH64_TP: + regBuffer[iRegister++] = m_rd->TP; break; + default: + _ASSERTE(false); break; + } + } + } + + _ASSERTE (iRegister <= regCount); + return S_OK; +} + + +HRESULT CordbRegisterSet::GetRegistersAvailable(ULONG32 regCount, + BYTE pAvailable[]) +{ + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT_ARRAY(pAvailable, CORDB_REGISTER, regCount, true, true); + + for (int i = 0 ; i < (int)regCount ; ++i) + { + if (i * 8 <= REGISTER_LOONGARCH64_F31) + { + pAvailable[i] = (i * 8 == REGISTER_LOONGARCH64_F31) ? BYTE(0x1) : BYTE(0xff); + } + else + { + pAvailable[i] = 0; + } + } + + return S_OK; +} + + +HRESULT CordbRegisterSet::GetRegisters(ULONG32 maskCount, BYTE mask[], + ULONG32 regCount, CORDB_REGISTER regBuffer[]) +{ + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT_ARRAY(regBuffer, CORDB_REGISTER, regCount, true, true); + + UINT iRegister = 0; + + for (int m = 0 ; m < (int)maskCount ; ++m) + { + for (int bit = 0 ; bit < 8 ; ++bit) + { + if (mask[m] & SETBITULONG64(bit)) + { + _ASSERTE (iRegister < regCount); + + int i = m * 8 + bit; + + if ((i >= REGISTER_LOONGARCH64_A0) && (i <= REGISTER_LOONGARCH64_X0)) + { + regBuffer[iRegister++] = *(ULONG64*)((char*)(&m_rd->A0) + ((i - REGISTER_LOONGARCH64_A0) << 3)); + continue; + } + + if ((i >= REGISTER_LOONGARCH64_S0) && (i <= REGISTER_LOONGARCH64_S8)) + { + regBuffer[iRegister++] = *(ULONG64*)((char*)(&m_rd->S0) + ((i - REGISTER_LOONGARCH64_S0) << 3)); + continue; + } + + + if ((i >= REGISTER_LOONGARCH64_F0) && (i <= REGISTER_LOONGARCH64_F31)) + { + if (!m_thread->m_fFloatStateValid) + { + HRESULT hr = S_OK; + EX_TRY + { + m_thread->LoadFloatState(); + } + EX_CATCH_HRESULT(hr); + + if ( !SUCCEEDED(hr) ) + { + return hr; + } + LOG( ( LF_CORDB, LL_INFO1000, "CRS::GR: Loaded float state\n" ) ); + } + + regBuffer[iRegister++] = *(CORDB_REGISTER*) + &(m_thread->m_floatValues[(i - REGISTER_LOONGARCH64_F0)]); + continue; + } + + switch (i) + { + case REGISTER_LOONGARCH64_PC: + regBuffer[iRegister++] = m_rd->PC; break; + case REGISTER_LOONGARCH64_SP: + regBuffer[iRegister++] = m_rd->SP; break; + case REGISTER_LOONGARCH64_FP: + regBuffer[iRegister++] = m_rd->FP; break; + case REGISTER_LOONGARCH64_RA: + regBuffer[iRegister++] = m_rd->RA; break; + case REGISTER_LOONGARCH64_TP: + regBuffer[iRegister++] = m_rd->TP; break; + default: + _ASSERTE(false); break; + } + } + } + } + + return S_OK; +} + + +// This is just a convenience function to convert a regdisplay into a Context. +// Since a context has more info than a regdisplay, the conversion isn't perfect +// and the context can't be fully accurate. +void CordbRegisterSet::InternalCopyRDToContext(DT_CONTEXT *pInputContext) +{ INTERNAL_SYNC_API_ENTRY(GetProcess()); + _ASSERTE(pInputContext); + + if ((pInputContext->ContextFlags & DT_CONTEXT_INTEGER) == DT_CONTEXT_INTEGER) + { + ULONG64* pDest = &pInputContext->A0; + ULONG64* pSrc = &m_rd->A0; + for (int i = REGISTER_LOONGARCH64_A0; i < REGISTER_LOONGARCH64_X0; ++i) + { + *pDest++ = *pSrc++; + } + + pDest = &pInputContext->S0; + pSrc = &m_rd->S0; + for (int i = REGISTER_LOONGARCH64_S0; i <= REGISTER_LOONGARCH64_S8; ++i) + { + *pDest++ = *pSrc++; + } + + pInputContext->TP = m_rd->TP; + pInputContext->RA = m_rd->RA; + } + + if ((pInputContext->ContextFlags & DT_CONTEXT_CONTROL) == DT_CONTEXT_CONTROL) + { + pInputContext->SP = m_rd->SP; + pInputContext->PC = m_rd->PC; + pInputContext->FP = m_rd->FP; + } +} diff --git a/src/coreclr/debug/di/loongarch64/floatconversion.S b/src/coreclr/debug/di/loongarch64/floatconversion.S new file mode 100644 index 00000000000000..83043e4ee66ca2 --- /dev/null +++ b/src/coreclr/debug/di/loongarch64/floatconversion.S @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include + +// Arguments +// input: (in A0) the value to be converted to a double +// output: the double corresponding to the _NEON128 input value +LEAF_ENTRY FPFillR8, .TEXT + ld.d $a0, $a0, 0 + jirl $r0, $ra, 0 +LEAF_END FPFillR8, .TEXT diff --git a/src/coreclr/debug/di/loongarch64/primitives.cpp b/src/coreclr/debug/di/loongarch64/primitives.cpp new file mode 100644 index 00000000000000..1c60eb66b1dba4 --- /dev/null +++ b/src/coreclr/debug/di/loongarch64/primitives.cpp @@ -0,0 +1,4 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "../../shared/loongarch64/primitives.cpp" diff --git a/src/coreclr/debug/di/module.cpp b/src/coreclr/debug/di/module.cpp index c01ab6ce0e6d28..3e6da64f89b38a 100644 --- a/src/coreclr/debug/di/module.cpp +++ b/src/coreclr/debug/di/module.cpp @@ -4507,6 +4507,8 @@ int CordbNativeCode::GetCallInstructionLength(BYTE *ip, ULONG32 count) return 2; #elif defined(TARGET_ARM64) return MAX_INSTRUCTION_LENGTH; +#elif defined(TARGET_LOONGARCH64) + return MAX_INSTRUCTION_LENGTH; #elif defined(TARGET_X86) if (count < 2) return -1; diff --git a/src/coreclr/debug/di/platformspecific.cpp b/src/coreclr/debug/di/platformspecific.cpp index fb2d8eb92453e4..5247fd8436bc95 100644 --- a/src/coreclr/debug/di/platformspecific.cpp +++ b/src/coreclr/debug/di/platformspecific.cpp @@ -34,6 +34,9 @@ #elif TARGET_ARM64 #include "arm64/cordbregisterset.cpp" #include "arm64/primitives.cpp" +#elif TARGET_LOONGARCH64 +#include "loongarch64/cordbregisterset.cpp" +#include "loongarch64/primitives.cpp" #else #error Unsupported platform #endif diff --git a/src/coreclr/debug/di/rsthread.cpp b/src/coreclr/debug/di/rsthread.cpp index c3543ad96cdb99..7697d7a0680b1e 100644 --- a/src/coreclr/debug/di/rsthread.cpp +++ b/src/coreclr/debug/di/rsthread.cpp @@ -8328,6 +8328,9 @@ HRESULT CordbJITILFrame::GetNativeVariable(CordbType *type, #elif defined(TARGET_ARM64) hr = m_nativeFrame->GetLocalFloatingPointValue(pNativeVarInfo->loc.vlReg.vlrReg + REGISTER_ARM64_V0, type, ppValue); +#elif defined(TARGET_LOONGARCH64) + hr = m_nativeFrame->GetLocalFloatingPointValue(pNativeVarInfo->loc.vlReg.vlrReg + REGISTER_LOONGARCH64_F0, + type, ppValue); #else #error Platform not implemented #endif // TARGET_ARM @ARMTODO @@ -8764,6 +8767,8 @@ HRESULT CordbJITILFrame::GetReturnValueForType(CordbType *pType, ICorDebugValue const CorDebugRegister floatRegister = REGISTER_ARM64_V0; #elif defined(TARGET_ARM) const CorDebugRegister floatRegister = REGISTER_ARM_D0; +#elif defined(TARGET_LOONGARCH64) + const CorDebugRegister floatRegister = REGISTER_LOONGARCH64_F0; #endif #if defined(TARGET_X86) @@ -8776,7 +8781,8 @@ HRESULT CordbJITILFrame::GetReturnValueForType(CordbType *pType, ICorDebugValue #elif defined(TARGET_ARM) const CorDebugRegister ptrRegister = REGISTER_ARM_R0; const CorDebugRegister ptrHighWordRegister = REGISTER_ARM_R1; - +#elif defined(TARGET_LOONGARCH64) + const CorDebugRegister ptrRegister = REGISTER_LOONGARCH64_A0; #endif CorElementType corReturnType = pType->GetElementType(); diff --git a/src/coreclr/debug/di/shimremotedatatarget.cpp b/src/coreclr/debug/di/shimremotedatatarget.cpp index 9a01508e211585..1a5fb8562a6be3 100644 --- a/src/coreclr/debug/di/shimremotedatatarget.cpp +++ b/src/coreclr/debug/di/shimremotedatatarget.cpp @@ -230,6 +230,8 @@ ShimRemoteDataTarget::GetPlatform( *pPlatform = CORDB_PLATFORM_POSIX_ARM; #elif defined(TARGET_ARM64) *pPlatform = CORDB_PLATFORM_POSIX_ARM64; + #elif defined(TARGET_LOONGARCH64) + *pPlatform = CORDB_PLATFORM_POSIX_LOONGARCH64; #else #error Unknown Processor. #endif @@ -242,6 +244,8 @@ ShimRemoteDataTarget::GetPlatform( *pPlatform = CORDB_PLATFORM_WINDOWS_ARM; #elif defined(TARGET_ARM64) *pPlatform = CORDB_PLATFORM_WINDOWS_ARM64; + #elif defined(TARGET_LOONGARCH64) + *pPlatform = CORDB_PLATFORM_WINDOWS_LOONGARCH64; #else #error Unknown Processor. #endif diff --git a/src/coreclr/debug/ee/CMakeLists.txt b/src/coreclr/debug/ee/CMakeLists.txt index 8a9eda3da3165f..4e59f05eb96c94 100644 --- a/src/coreclr/debug/ee/CMakeLists.txt +++ b/src/coreclr/debug/ee/CMakeLists.txt @@ -65,6 +65,8 @@ elseif(CLR_CMAKE_TARGET_ARCH_ARM) list(APPEND CORDBEE_SOURCES_WKS ${ARCH_SOURCES_DIR}/armwalker.cpp) elseif(CLR_CMAKE_TARGET_ARCH_ARM64) list(APPEND CORDBEE_SOURCES_WKS ${ARCH_SOURCES_DIR}/arm64walker.cpp) +elseif(CLR_CMAKE_TARGET_ARCH_LOONGARCH64) + list(APPEND CORDBEE_SOURCES_WKS ${ARCH_SOURCES_DIR}/loongarch64walker.cpp) endif() convert_to_absolute_path(CORDBEE_SOURCES_DAC ${CORDBEE_SOURCES_DAC}) diff --git a/src/coreclr/debug/ee/debugger.cpp b/src/coreclr/debug/ee/debugger.cpp index d677d5ef297751..03b99d5c2f1e71 100644 --- a/src/coreclr/debug/ee/debugger.cpp +++ b/src/coreclr/debug/ee/debugger.cpp @@ -6629,6 +6629,8 @@ void Debugger::InitDebuggerLaunchJitInfo(Thread * pThread, EXCEPTION_POINTERS * s_DebuggerLaunchJitInfo.dwProcessorArchitecture = PROCESSOR_ARCHITECTURE_ARM; #elif defined(TARGET_ARM64) s_DebuggerLaunchJitInfo.dwProcessorArchitecture = PROCESSOR_ARCHITECTURE_ARM64; +#elif defined(TARGET_LOONGARCH64) + s_DebuggerLaunchJitInfo.dwProcessorArchitecture = PROCESSOR_ARCHITECTURE_LOONGARCH64; #else #error Unknown processor. #endif @@ -13523,6 +13525,9 @@ LONG Debugger::FirstChanceSuspendHijackWorker(CONTEXT *pContext, SPEW(fprintf(stderr, "0x%x D::FCHF: code=0x%08x, addr=0x%08x, Pc=0x%p, Sp=0x%p, EFlags=0x%08x\n", tid, pExceptionRecord->ExceptionCode, pExceptionRecord->ExceptionAddress, pContext->Pc, pContext->Sp, pContext->EFlags)); +#elif defined(TARGET_LOONGARCH64) + SPEW(fprintf(stderr, "0x%x D::FCHF: code=0x%08x, addr=0x%08x, Pc=0x%p, Sp=0x%p\n", + tid, pExceptionRecord->ExceptionCode, pExceptionRecord->ExceptionAddress, pContext->Pc, pContext->Sp)); #endif // This memory is used as IPC during the hijack. We will place a pointer to this in diff --git a/src/coreclr/debug/ee/loongarch64/dbghelpers.S b/src/coreclr/debug/ee/loongarch64/dbghelpers.S new file mode 100644 index 00000000000000..07103d6c6771b3 --- /dev/null +++ b/src/coreclr/debug/ee/loongarch64/dbghelpers.S @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "asmconstants.h" +#include "unixasmmacros.inc" + +// +// hijacking stub used to perform a func-eval, see Debugger::FuncEvalSetup() for use. +// +// on entry: +// x0 : pointer to DebuggerEval object +// + +// @dbgtodo- once we port Funceval, use the ExceptionHijack stub instead of this func-eval stub. +NESTED_ENTRY FuncEvalHijack, _TEXT, UnhandledExceptionHandlerUnix + // NOTE: FuncEvalHijackPersonalityRoutine is dependent on the stack layout so if + // you change the prolog you will also need to update the personality routine. + + // push arg to the stack so our personality routine can find it + // push lr to get good stacktrace in debugger + // $fp,$ra + PROLOG_SAVE_REG_PAIR_INDEXED 22, 1, -32 + st.d $a0, $sp, 16 + + // FuncEvalHijackWorker returns the address we should jump to. + bl C_FUNC(FuncEvalHijackWorker) + + EPILOG_STACK_FREE 32 + EPILOG_BRANCH_REG $v0 +NESTED_END FuncEvalHijack + +// This is the general purpose hijacking stub. The DacDbi Hijack primitive will +// set up the stack and then set the IP here, and so this just makes the call. +NESTED_ENTRY ExceptionHijack, _TEXT, UnhandledExceptionHandlerUnix + // make the call + bl C_FUNC(ExceptionHijackWorker) + + // effective NOP to terminate unwind ??? + nop + + // *** should never get here *** + EMIT_BREAKPOINT +// exported label so the debugger knows where the end of this function is +PATCH_LABEL ExceptionHijackEnd + +NESTED_END ExceptionHijack, _TEXT diff --git a/src/coreclr/debug/ee/loongarch64/loongarch64walker.cpp b/src/coreclr/debug/ee/loongarch64/loongarch64walker.cpp new file mode 100644 index 00000000000000..fe1bef86cd84fa --- /dev/null +++ b/src/coreclr/debug/ee/loongarch64/loongarch64walker.cpp @@ -0,0 +1,167 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +//***************************************************************************** +// File: Loongarch64walker.cpp +// + +// +// LOONGARCH64 instruction decoding/stepping logic +// +//***************************************************************************** + +#include "stdafx.h" +#include "walker.h" +#include "frames.h" +#include "openum.h" + +#ifdef TARGET_LOONGARCH64 + +void NativeWalker::Decode() +{ + PT_CONTEXT context = NULL; + int RegNum = -1; + PCODE offset = MAX_INSTRUCTION_LENGTH; + + //Reset so that we do not provide bogus info + m_type = WALK_UNKNOWN; + m_skipIP = NULL; + m_nextIP = NULL; + + if (m_registers == NULL) + { + //walker does not use WALK_NEXT + //Without registers decoding will work only for handful of instructions + return; + } + + m_skipIP = m_ip + MAX_INSTRUCTION_LENGTH; + + context = m_registers->pCurrentContext; + // Fetch first word of the current instruction.If the current instruction is a break instruction, we'll + // need to check the patch table to get the correct instruction. + PRD_TYPE opcode = CORDbgGetInstruction(m_ip); + PRD_TYPE unpatchedOpcode; + if (DebuggerController::CheckGetPatchedOpcode(m_ip, &unpatchedOpcode)) + { + opcode = unpatchedOpcode; + } + + LOG((LF_CORDB, LL_INFO100000, "LoongArch64Walker::Decode instruction at %p, opcode: %x\n", m_ip, opcode)); + + if (NativeWalker::DecodeJumpInst(opcode, RegNum, offset, m_type)) //Unconditional jump (register) instructions + { + if (m_type == WALK_RETURN) + { + m_skipIP = NULL; + } + m_nextIP = (BYTE*)GetReg(context, RegNum) + offset; + return; + } + + if (NativeWalker::DecodePCRelativeBranchInst(context, opcode, offset, m_type)) + { + if (m_type == WALK_BRANCH) + { + m_skipIP = NULL; + } + } + + m_nextIP = m_ip + offset; + + return; +} + +// Decodes PC Relative Branch Instructions +// +// This Function Decodes : +// BL offset +// B offset +// +// Output of the Function are: +// offset - Offset from current PC to which control will go next +// WALK_TYPE +BOOL NativeWalker::DecodePCRelativeBranchInst(PT_CONTEXT context, const PRD_TYPE opcode, PCODE& offset, WALK_TYPE& walk) +{ + if (((opcode >> 24) & 0xFC) == 0x50) // Decode B + { + offset = (opcode >> 10) & 0xFFFF; // Get the low-16bits offset field. + offset |= (opcode & 0x3FF) << 16; // Get the hight-10bits offset field. + + // Check whether sign extension + if ((opcode & 0x200) != 0) + { + offset = ((int)(offset << 6)) >> 4; // Also 4-bytes aligned + } + else + { + offset <<= 2; // 4-bytes aligned + } + + walk = WALK_BRANCH; //B + LOG((LF_CORDB, LL_INFO100000, "LoongArch64Walker::Decoded opcode: %x to B %x \n", opcode, offset)); + + return TRUE; + } + else if (((opcode >> 24) & 0xFC) == 0x54) // Decode BL + { + offset = (opcode >> 10) & 0xFFFF; // Get the low-16bits offset field. + offset |= (opcode & 0x3FF) << 16; // Get the hight-10bits offset field. + + // Check whether sign extension + if ((opcode & 0x200) != 0) + { + offset = ((int)(offset << 6)) >> 4; // Also 4-bytes aligned + } + else + { + offset <<= 2; // 4-bytes aligned + } + + walk = WALK_CALL; + LOG((LF_CORDB, LL_INFO100000, "LoongArch64Walker::Decoded opcode: %x to BL %x \n", opcode, offset)); + + return TRUE; + } + + return FALSE; +} + +BOOL NativeWalker::DecodeJumpInst(const PRD_TYPE opcode, int& RegNum, PCODE& offset, WALK_TYPE& walk) +{ + if ((opcode & 0xFC000000) == 0x4C000000) // jirl - Unconditional Jump (register) instructions + { + RegNum = (opcode >> 5) & 0x1F; // rj is the target registor. + + short op = opcode & 0x1F; // Checking for linker registor by rd field. + switch (op) + { + case 0: + if (RegNum == 1) + { + LOG((LF_CORDB, LL_INFO100000, "LoongArch64Walker::Decoded opcode: %x to Ret X%d\n", opcode, RegNum)); + walk = WALK_RETURN; + } + else + { + LOG((LF_CORDB, LL_INFO100000, "LoongArch64Walker::Decoded opcode: %x to jr Reg%d\n", opcode, RegNum)); + walk = WALK_BRANCH; + } + break; + case 1: LOG((LF_CORDB, LL_INFO100000, "LoongArch64Walker::Decoded opcode: %x to jirl Reg%d\n", opcode, RegNum)); + walk = WALK_CALL; + break; + default: + LOG((LF_CORDB, LL_INFO100000, "LoongArch64Walker::Simulate Unknown opcode: %x [Branch] \n", opcode)); + _ASSERTE(!("LoongArch64Walker::Decoded Unknown opcode")); + } + + offset = (short)(opcode >> 10); // get the offset fields and signExtend. + offset <<= 2; // 4-bytes aligned. + + return TRUE; + } + + return FALSE; +} +#endif diff --git a/src/coreclr/debug/ee/loongarch64/primitives.cpp b/src/coreclr/debug/ee/loongarch64/primitives.cpp new file mode 100644 index 00000000000000..bef18245f06dba --- /dev/null +++ b/src/coreclr/debug/ee/loongarch64/primitives.cpp @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "stdafx.h" +#include "threads.h" +#include "../../shared/loongarch64/primitives.cpp" + +void CopyREGDISPLAY(REGDISPLAY* pDst, REGDISPLAY* pSrc) +{ + CONTEXT tmp; + CopyRegDisplay(pSrc, pDst, &tmp); +} diff --git a/src/coreclr/debug/ee/walker.h b/src/coreclr/debug/ee/walker.h index d16d4c740c89d1..4e16dc537153db 100644 --- a/src/coreclr/debug/ee/walker.h +++ b/src/coreclr/debug/ee/walker.h @@ -215,6 +215,23 @@ class NativeWalker : public Walker static BYTE* SetupOrSimulateInstructionForPatchSkip(T_CONTEXT * context, SharedPatchBypassBuffer * m_pSharedPatchBypassBuffer, const BYTE *address, PRD_TYPE opcode); }; +#elif defined (TARGET_LOONGARCH64) +#include "controller.h" +class NativeWalker : public Walker +{ +public: + void Init(const BYTE *ip, REGDISPLAY *pregisters) + { + Walker::Init(ip, pregisters); + } + void Decode(); + static void DecodeInstructionForPatchSkip(const BYTE *address, InstructionAttribute * pInstrAttrib) + { + pInstrAttrib->Reset(); + } + static BOOL DecodePCRelativeBranchInst(PT_CONTEXT context,const PRD_TYPE opcode, PCODE& offset, WALK_TYPE& walk); + static BOOL DecodeJumpInst(const PRD_TYPE opcode, int& RegNum, PCODE& offset, WALK_TYPE& walk); +}; #else PORTABILITY_WARNING("NativeWalker not implemented on this platform"); class NativeWalker : public Walker diff --git a/src/coreclr/debug/ee/wks/CMakeLists.txt b/src/coreclr/debug/ee/wks/CMakeLists.txt index 6411b64d436ff7..f50bc8f6fb6d59 100644 --- a/src/coreclr/debug/ee/wks/CMakeLists.txt +++ b/src/coreclr/debug/ee/wks/CMakeLists.txt @@ -7,7 +7,7 @@ if (CLR_CMAKE_TARGET_WIN32) set(ASM_FILE ${CORDBEE_DIR}/${ARCH_SOURCES_DIR}/dbghelpers.asm) - if(CLR_CMAKE_HOST_ARCH_ARM OR CLR_CMAKE_HOST_ARCH_ARM64) + if(CLR_CMAKE_HOST_ARCH_ARM OR CLR_CMAKE_HOST_ARCH_ARM64 OR CLR_CMAKE_HOST_ARCH_LOONGARCH64) preprocess_files(ASM_FILE ${ASM_FILE}) if (CMAKE_GENERATOR MATCHES "Visual Studio") diff --git a/src/coreclr/debug/inc/dbgipcevents.h b/src/coreclr/debug/inc/dbgipcevents.h index e433532c29a16f..6cea497955c4fd 100644 --- a/src/coreclr/debug/inc/dbgipcevents.h +++ b/src/coreclr/debug/inc/dbgipcevents.h @@ -1136,6 +1136,40 @@ struct MSLAYOUT DebuggerREGDISPLAY SIZE_T LR; SIZE_T SP; SIZE_T PC; +#elif defined(TARGET_LOONGARCH64) + #define DebuggerIPCE_FloatCount 32 + SIZE_T RA; + SIZE_T TP; + SIZE_T SP; + SIZE_T A0; + SIZE_T A1; + SIZE_T A2; + SIZE_T A3; + SIZE_T A4; + SIZE_T A5; + SIZE_T A6; + SIZE_T A7; + SIZE_T T0; + SIZE_T T1; + SIZE_T T2; + SIZE_T T3; + SIZE_T T4; + SIZE_T T5; + SIZE_T T6; + SIZE_T T7; + SIZE_T T8; + SIZE_T X0; + SIZE_T FP; + SIZE_T S0; + SIZE_T S1; + SIZE_T S2; + SIZE_T S3; + SIZE_T S4; + SIZE_T S5; + SIZE_T S6; + SIZE_T S7; + SIZE_T S8; + SIZE_T PC; #else #define DebuggerIPCE_FloatCount 1 @@ -1853,6 +1887,13 @@ C_ASSERT(DBG_TARGET_REGNUM_AMBIENT_SP == ICorDebugInfo::REGNUM_AMBIENT_SP); C_ASSERT(DBG_TARGET_REGNUM_SP == ICorDebugInfo::REGNUM_SP); C_ASSERT(DBG_TARGET_REGNUM_AMBIENT_SP == ICorDebugInfo::REGNUM_AMBIENT_SP); #endif // TARGET_ARM64 +#elif defined(TARGET_LOONGARCH64) +#define DBG_TARGET_REGNUM_SP 3 +#define DBG_TARGET_REGNUM_AMBIENT_SP 34 +#ifdef TARGET_LOONGARCH64 +C_ASSERT(DBG_TARGET_REGNUM_SP == ICorDebugInfo::REGNUM_SP); +C_ASSERT(DBG_TARGET_REGNUM_AMBIENT_SP == ICorDebugInfo::REGNUM_AMBIENT_SP); +#endif #else #error Target registers are not defined for this platform #endif diff --git a/src/coreclr/debug/inc/dbgtargetcontext.h b/src/coreclr/debug/inc/dbgtargetcontext.h index 37eb7eb11bd712..5104c5d25d4e5a 100644 --- a/src/coreclr/debug/inc/dbgtargetcontext.h +++ b/src/coreclr/debug/inc/dbgtargetcontext.h @@ -510,38 +510,7 @@ typedef DECLSPEC_ALIGN(16) struct { // // Floating Point Registers // - DWORD64 F0; - DWORD64 F1; - DWORD64 F2; - DWORD64 F3; - DWORD64 F4; - DWORD64 F5; - DWORD64 F6; - DWORD64 F7; - DWORD64 F8; - DWORD64 F9; - DWORD64 F10; - DWORD64 F11; - DWORD64 F12; - DWORD64 F13; - DWORD64 F14; - DWORD64 F15; - DWORD64 F16; - DWORD64 F17; - DWORD64 F18; - DWORD64 F19; - DWORD64 F20; - DWORD64 F21; - DWORD64 F22; - DWORD64 F23; - DWORD64 F24; - DWORD64 F25; - DWORD64 F26; - DWORD64 F27; - DWORD64 F28; - DWORD64 F29; - DWORD64 F30; - DWORD64 F31; + ULONGLONG F[32]; } DT_CONTEXT; #else diff --git a/src/coreclr/debug/inc/loongarch64/primitives.h b/src/coreclr/debug/inc/loongarch64/primitives.h new file mode 100644 index 00000000000000..995f83a1488dd3 --- /dev/null +++ b/src/coreclr/debug/inc/loongarch64/primitives.h @@ -0,0 +1,259 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +//***************************************************************************** +// File: primitives.h +// + +// +// Platform-specific debugger primitives +// +//***************************************************************************** + +#ifndef PRIMITIVES_H_ +#define PRIMITIVES_H_ + +typedef const BYTE CORDB_ADDRESS_TYPE; +typedef DPTR(CORDB_ADDRESS_TYPE) PTR_CORDB_ADDRESS_TYPE; + +#define MAX_INSTRUCTION_LENGTH 4 + +// Given a return address retrieved during stackwalk, +// this is the offset by which it should be decremented to land at the call instruction. +#define STACKWALK_CONTROLPC_ADJUST_OFFSET 8 + +#define PRD_TYPE LONG +#define CORDbg_BREAK_INSTRUCTION_SIZE 4 +#define CORDbg_BREAK_INSTRUCTION (LONG)0x002A0005 + +inline CORDB_ADDRESS GetPatchEndAddr(CORDB_ADDRESS patchAddr) +{ + LIMITED_METHOD_DAC_CONTRACT; + return patchAddr + CORDbg_BREAK_INSTRUCTION_SIZE; +} + +#define InitializePRDToBreakInst(_pPRD) *(_pPRD) = CORDbg_BREAK_INSTRUCTION +#define PRDIsBreakInst(_pPRD) (*(_pPRD) == CORDbg_BREAK_INSTRUCTION) + + +#define CORDbgGetInstructionEx(_buffer, _requestedAddr, _patchAddr, _dummy1, _dummy2) \ + CORDbgGetInstructionExImpl((CORDB_ADDRESS_TYPE *)((_buffer) + (_patchAddr) - (_requestedAddr))); + +#define CORDbgSetInstructionEx(_buffer, _requestedAddr, _patchAddr, _opcode, _dummy2) \ + CORDbgSetInstructionExImpl((CORDB_ADDRESS_TYPE *)((_buffer) + (_patchAddr) - (_requestedAddr)), (_opcode)); + +#define CORDbgInsertBreakpointEx(_buffer, _requestedAddr, _patchAddr, _dummy1, _dummy2) \ + CORDbgInsertBreakpointExImpl((CORDB_ADDRESS_TYPE *)((_buffer) + (_patchAddr) - (_requestedAddr))); + + +constexpr CorDebugRegister g_JITToCorDbgReg[] = +{ + REGISTER_LOONGARCH64_RA, + REGISTER_LOONGARCH64_TP, + REGISTER_LOONGARCH64_SP, + REGISTER_LOONGARCH64_A0, + REGISTER_LOONGARCH64_A1, + REGISTER_LOONGARCH64_A2, + REGISTER_LOONGARCH64_A3, + REGISTER_LOONGARCH64_A4, + REGISTER_LOONGARCH64_A5, + REGISTER_LOONGARCH64_A6, + REGISTER_LOONGARCH64_A7, + REGISTER_LOONGARCH64_T0, + REGISTER_LOONGARCH64_T1, + REGISTER_LOONGARCH64_T2, + REGISTER_LOONGARCH64_T3, + REGISTER_LOONGARCH64_T4, + REGISTER_LOONGARCH64_T5, + REGISTER_LOONGARCH64_T6, + REGISTER_LOONGARCH64_T7, + REGISTER_LOONGARCH64_T8, + REGISTER_LOONGARCH64_X0, + REGISTER_LOONGARCH64_FP, + REGISTER_LOONGARCH64_S0, + REGISTER_LOONGARCH64_S1, + REGISTER_LOONGARCH64_S2, + REGISTER_LOONGARCH64_S3, + REGISTER_LOONGARCH64_S4, + REGISTER_LOONGARCH64_S5, + REGISTER_LOONGARCH64_S6, + REGISTER_LOONGARCH64_S7, + REGISTER_LOONGARCH64_S8, + REGISTER_LOONGARCH64_PC +}; + +inline void CORDbgSetIP(DT_CONTEXT *context, LPVOID ip) { + LIMITED_METHOD_CONTRACT; + + context->PC = (DWORD64)ip; +} + +inline LPVOID CORDbgGetSP(const DT_CONTEXT * context) { + LIMITED_METHOD_CONTRACT; + + return (LPVOID)(size_t)(context->SP); +} + +inline void CORDbgSetSP(DT_CONTEXT *context, LPVOID esp) { + LIMITED_METHOD_CONTRACT; + + context->SP = (DWORD64)esp; +} + +inline LPVOID CORDbgGetFP(const DT_CONTEXT * context) { + LIMITED_METHOD_CONTRACT; + + return (LPVOID)(size_t)(context->FP); +} + +inline void CORDbgSetFP(DT_CONTEXT *context, LPVOID fp) { + LIMITED_METHOD_CONTRACT; + + context->FP = (DWORD64)fp; +} + + +inline BOOL CompareControlRegisters(const DT_CONTEXT * pCtx1, const DT_CONTEXT * pCtx2) +{ + LIMITED_METHOD_DAC_CONTRACT; + + // TODO-LoongArch64: Sort out frame registers + + if ((pCtx1->PC == pCtx2->PC) && + (pCtx1->SP == pCtx2->SP) && + (pCtx1->FP == pCtx2->FP)) + { + return TRUE; + } + + return FALSE; +} + +inline void CORDbgSetInstruction(CORDB_ADDRESS_TYPE* address, + PRD_TYPE instruction) +{ + // In a DAC build, this function assumes the input is an host address. + LIMITED_METHOD_DAC_CONTRACT; + + ULONGLONG ptraddr = dac_cast(address); + *(PRD_TYPE *)ptraddr = instruction; + FlushInstructionCache(GetCurrentProcess(), + address, + sizeof(PRD_TYPE)); +} + +inline PRD_TYPE CORDbgGetInstruction(UNALIGNED CORDB_ADDRESS_TYPE* address) +{ + LIMITED_METHOD_CONTRACT; + + ULONGLONG ptraddr = dac_cast(address); + return *(PRD_TYPE *)ptraddr; +} + +// +// Mapping from ICorDebugInfo register numbers to CorDebugRegister +// numbers. Note: this must match the order in corinfo.h. +// +inline CorDebugRegister ConvertRegNumToCorDebugRegister(ICorDebugInfo::RegNum reg) +{ + LIMITED_METHOD_CONTRACT; + _ASSERTE(reg >= 0); + _ASSERTE(static_cast(reg) < ARRAY_SIZE(g_JITToCorDbgReg)); + return g_JITToCorDbgReg[reg]; +} + +inline LPVOID CORDbgGetIP(DT_CONTEXT *context) +{ + LIMITED_METHOD_CONTRACT; + + return (LPVOID)(size_t)(context->PC); +} + +inline void CORDbgSetInstructionExImpl(CORDB_ADDRESS_TYPE* address, + PRD_TYPE instruction) +{ + LIMITED_METHOD_DAC_CONTRACT; + + *(PRD_TYPE *)address = instruction; + FlushInstructionCache(GetCurrentProcess(), + address, + sizeof(PRD_TYPE)); +} + +inline PRD_TYPE CORDbgGetInstructionExImpl(UNALIGNED CORDB_ADDRESS_TYPE* address) +{ + LIMITED_METHOD_CONTRACT; + + return *(PRD_TYPE *)address; +} + +inline void CORDbgInsertBreakpoint(UNALIGNED CORDB_ADDRESS_TYPE *address) +{ + LIMITED_METHOD_CONTRACT; + + CORDbgSetInstruction(address, CORDbg_BREAK_INSTRUCTION); +} + +inline void CORDbgInsertBreakpointExImpl(UNALIGNED CORDB_ADDRESS_TYPE *address) +{ + LIMITED_METHOD_CONTRACT; + + CORDbgSetInstruction(address, CORDbg_BREAK_INSTRUCTION); +} + +// After a breakpoint exception, the CPU points to _after_ the break instruction. +// Adjust the IP so that it points at the break instruction. This lets us patch that +// opcode and re-excute what was underneath the bp. +inline void CORDbgAdjustPCForBreakInstruction(DT_CONTEXT* pContext) +{ + LIMITED_METHOD_CONTRACT; + + // LoongArch64 appears to leave the PC at the start of the breakpoint. + return; +} + +inline bool AddressIsBreakpoint(CORDB_ADDRESS_TYPE* address) +{ + LIMITED_METHOD_CONTRACT; + + return CORDbgGetInstruction(address) == CORDbg_BREAK_INSTRUCTION; +} + +inline void SetSSFlag(DT_CONTEXT *pContext) +{ + // TODO-LoongArch64: LoongArch64 doesn't support cpsr. + _ASSERTE(!"unimplemented on LOONGARCH64 yet"); +} + +inline void UnsetSSFlag(DT_CONTEXT *pContext) +{ + // TODO-LoongArch64: LoongArch64 doesn't support cpsr. + _ASSERTE(!"unimplemented on LOONGARCH64 yet"); +} + +inline bool IsSSFlagEnabled(DT_CONTEXT * pContext) +{ + // TODO-LoongArch64: LoongArch64 doesn't support cpsr. + _ASSERTE(!"unimplemented on LOONGARCH64 yet"); + return false; +} + + +inline bool PRDIsEqual(PRD_TYPE p1, PRD_TYPE p2) +{ + return p1 == p2; +} + +inline void InitializePRD(PRD_TYPE *p1) +{ + *p1 = 0; +} + +inline bool PRDIsEmpty(PRD_TYPE p1) +{ + LIMITED_METHOD_CONTRACT; + + return p1 == 0; +} + +#endif // PRIMITIVES_H_ diff --git a/src/coreclr/debug/shared/loongarch64/primitives.cpp b/src/coreclr/debug/shared/loongarch64/primitives.cpp new file mode 100644 index 00000000000000..f435989b8baef1 --- /dev/null +++ b/src/coreclr/debug/shared/loongarch64/primitives.cpp @@ -0,0 +1,96 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +//***************************************************************************** +// File: primitives.cpp +// + +// +// Platform-specific debugger primitives +// +//***************************************************************************** + +#include "primitives.h" + + +// +// CopyThreadContext() does an intelligent copy from pSrc to pDst, +// respecting the ContextFlags of both contexts. +// +void CORDbgCopyThreadContext(DT_CONTEXT* pDst, const DT_CONTEXT* pSrc) +{ + DWORD dstFlags = pDst->ContextFlags; + DWORD srcFlags = pSrc->ContextFlags; + LOG((LF_CORDB, LL_INFO1000000, + "CP::CTC: pDst=0x%08x dstFlags=0x%x, pSrc=0x%08x srcFlags=0x%x\n", + pDst, dstFlags, pSrc, srcFlags)); + + if ((dstFlags & srcFlags & DT_CONTEXT_CONTROL) == DT_CONTEXT_CONTROL) + { + LOG((LF_CORDB, LL_INFO1000000, + "CP::CTC: RA: pDst=0x%lx, pSrc=0x%lx, Flags=0x%x\n", + pDst->RA, pSrc->RA, DT_CONTEXT_CONTROL)); + pDst->RA = pSrc->RA; + + LOG((LF_CORDB, LL_INFO1000000, + "CP::CTC: SP: pDst=0x%lx, pSrc=0x%lx, Flags=0x%x\n", + pDst->SP, pSrc->SP, DT_CONTEXT_CONTROL)); + pDst->SP = pSrc->SP; + + LOG((LF_CORDB, LL_INFO1000000, + "CP::CTC: FP: pDst=0x%lx, pSrc=0x%lx, Flags=0x%x\n", + pDst->FP, pSrc->FP, DT_CONTEXT_CONTROL)); + pDst->FP = pSrc->FP; + + LOG((LF_CORDB, LL_INFO1000000, + "CP::CTC: PC: pDst=0x%lx, pSrc=0x%lx, Flags=0x%x\n", + pDst->PC, pSrc->PC, DT_CONTEXT_CONTROL)); + pDst->PC = pSrc->PC; + } + + if ((dstFlags & srcFlags & DT_CONTEXT_INTEGER) == DT_CONTEXT_INTEGER) + { + CopyContextChunk(&pDst->A0, &pSrc->A0, &pDst->FP, + DT_CONTEXT_INTEGER); + CopyContextChunk(&pDst->S0, &pSrc->S0, &pDst->PC, + DT_CONTEXT_INTEGER); + } + + if ((dstFlags & srcFlags & DT_CONTEXT_FLOATING_POINT) == DT_CONTEXT_FLOATING_POINT) + { + CopyContextChunk(&pDst->F[0], &pSrc->F[0], &pDst->F[32], + DT_CONTEXT_FLOATING_POINT); + } +} + +#if defined(ALLOW_VMPTR_ACCESS) || !defined(RIGHT_SIDE_COMPILE) +void SetDebuggerREGDISPLAYFromREGDISPLAY(DebuggerREGDISPLAY* pDRD, REGDISPLAY* pRD) +{ + SUPPORTS_DAC_HOST_ONLY; + + DT_CONTEXT* pContext = reinterpret_cast(pRD->pCurrentContext); + + // We must pay attention to the context flags so that we only use valid portions + // of the context. + DWORD flags = pContext->ContextFlags; + if ((flags & DT_CONTEXT_CONTROL) == DT_CONTEXT_CONTROL) + { + pDRD->FP = (SIZE_T)CORDbgGetFP(pContext); + pDRD->PC = (SIZE_T)pContext->PC; + pDRD->RA = (SIZE_T)pContext->RA; + } + + if ((flags & DT_CONTEXT_INTEGER) == DT_CONTEXT_INTEGER) + { + pDRD->TP = pContext->TP; + memcpy(&pDRD->A0, &pContext->A0, sizeof(pDRD->A0)*(21 - 4 + 1)); + memcpy(&pDRD->S0, &pContext->S0, sizeof(pDRD->S0)* 9); + } + + pDRD->SP = pRD->SP; + + LOG( (LF_CORDB, LL_INFO1000, "DT::TASSC:Registers:" + "SP = %x", + pDRD->SP) ); +} +#endif // ALLOW_VMPTR_ACCESS || !RIGHT_SIDE_COMPILE diff --git a/src/coreclr/inc/cordebug.idl b/src/coreclr/inc/cordebug.idl index a5f67044fb6a7b..785a00d5bda5ab 100644 --- a/src/coreclr/inc/cordebug.idl +++ b/src/coreclr/inc/cordebug.idl @@ -3919,10 +3919,11 @@ interface ICorDebugRegisterSet : IUnknown REGISTER_ARM64_V31, // LoongArch64 registers - REGISTER_LOONGARCH64_R0 = 0, + REGISTER_LOONGARCH64_PC = 0, + REGISTER_LOONGARCH64_SP, + REGISTER_LOONGARCH64_FP, REGISTER_LOONGARCH64_RA, REGISTER_LOONGARCH64_TP, - REGISTER_LOONGARCH64_SP, REGISTER_LOONGARCH64_A0, REGISTER_LOONGARCH64_A1, REGISTER_LOONGARCH64_A2, @@ -3941,7 +3942,6 @@ interface ICorDebugRegisterSet : IUnknown REGISTER_LOONGARCH64_T7, REGISTER_LOONGARCH64_T8, REGISTER_LOONGARCH64_X0, - REGISTER_LOONGARCH64_FP, REGISTER_LOONGARCH64_S0, REGISTER_LOONGARCH64_S1, REGISTER_LOONGARCH64_S2, @@ -3951,7 +3951,6 @@ interface ICorDebugRegisterSet : IUnknown REGISTER_LOONGARCH64_S6, REGISTER_LOONGARCH64_S7, REGISTER_LOONGARCH64_S8, - REGISTER_LOONGARCH64_PC, REGISTER_LOONGARCH64_F0, REGISTER_LOONGARCH64_F1, diff --git a/src/coreclr/inc/crosscomp.h b/src/coreclr/inc/crosscomp.h index 1a7fdb37b9c252..d7d8378cd1f845 100644 --- a/src/coreclr/inc/crosscomp.h +++ b/src/coreclr/inc/crosscomp.h @@ -399,7 +399,7 @@ enum #define CONTEXT_UNWOUND_TO_CALL 0x20000000 -typedef struct DECLSPEC_ALIGN(8) _T_CONTEXT { +typedef struct DECLSPEC_ALIGN(16) _T_CONTEXT { // // Control flags. @@ -448,7 +448,7 @@ typedef struct DECLSPEC_ALIGN(8) _T_CONTEXT { // Floating Point Registers // //TODO-LoongArch64: support the SIMD. - DWORD64 F[32]; + ULONGLONG F[32]; DWORD Fcsr; } T_CONTEXT, *PT_CONTEXT; diff --git a/src/coreclr/pal/inc/pal.h b/src/coreclr/pal/inc/pal.h index 272acf52119bf3..e677165299a471 100644 --- a/src/coreclr/pal/inc/pal.h +++ b/src/coreclr/pal/inc/pal.h @@ -2278,7 +2278,7 @@ typedef struct DECLSPEC_ALIGN(16) _CONTEXT { /* +0x000 */ DWORD ContextFlags; // - // Integer registers, abi=N64. + // Integer registers. // DWORD64 R0; DWORD64 Ra; @@ -2317,8 +2317,8 @@ typedef struct DECLSPEC_ALIGN(16) _CONTEXT { // // Floating Point Registers // - //TODO: support the SIMD. - DWORD64 F[32]; + // TODO-LoongArch64: support the SIMD. + ULONGLONG F[32]; DWORD Fcsr; } CONTEXT, *PCONTEXT, *LPCONTEXT; diff --git a/src/coreclr/pal/prebuilt/inc/cordebug.h b/src/coreclr/pal/prebuilt/inc/cordebug.h index 226ae1c0ca7691..a868b7f2bfabf8 100644 --- a/src/coreclr/pal/prebuilt/inc/cordebug.h +++ b/src/coreclr/pal/prebuilt/inc/cordebug.h @@ -9193,49 +9193,48 @@ enum CorDebugRegister REGISTER_ARM64_V29 = ( REGISTER_ARM64_V28 + 1 ) , REGISTER_ARM64_V30 = ( REGISTER_ARM64_V29 + 1 ) , REGISTER_ARM64_V31 = ( REGISTER_ARM64_V30 + 1 ) , - REGISTER_LOONGARCH64_R0 = 0, - REGISTER_LOONGARCH64_RA = ( REGISTER_LOONGARCH64_R0 + 1 ) , - REGISTER_LOONGARCH64_TP = ( REGISTER_LOONGARCH64_RA + 1 ) , - REGISTER_LOONGARCH64_SP = ( REGISTER_LOONGARCH64_TP + 1 ) , - REGISTER_LOONGARCH64_A0 = ( REGISTER_LOONGARCH64_SP + 1 ) , - REGISTER_LOONGARCH64_A1 = ( REGISTER_LOONGARCH64_A0 + 1 ) , - REGISTER_LOONGARCH64_A2 = ( REGISTER_LOONGARCH64_A1 + 1 ) , - REGISTER_LOONGARCH64_A3 = ( REGISTER_LOONGARCH64_A2 + 1 ) , - REGISTER_LOONGARCH64_A4 = ( REGISTER_LOONGARCH64_A3 + 1 ) , - REGISTER_LOONGARCH64_A5 = ( REGISTER_LOONGARCH64_A4 + 1 ) , - REGISTER_LOONGARCH64_A6 = ( REGISTER_LOONGARCH64_A5 + 1 ) , - REGISTER_LOONGARCH64_A7 = ( REGISTER_LOONGARCH64_A6 + 1 ) , - REGISTER_LOONGARCH64_T0 = ( REGISTER_LOONGARCH64_A7 + 1 ) , - REGISTER_LOONGARCH64_T1 = ( REGISTER_LOONGARCH64_T0 + 1 ) , - REGISTER_LOONGARCH64_T2 = ( REGISTER_LOONGARCH64_T1 + 1 ) , - REGISTER_LOONGARCH64_T3 = ( REGISTER_LOONGARCH64_T2 + 1 ) , - REGISTER_LOONGARCH64_T4 = ( REGISTER_LOONGARCH64_T3 + 1 ) , - REGISTER_LOONGARCH64_T5 = ( REGISTER_LOONGARCH64_T4 + 1 ) , - REGISTER_LOONGARCH64_T6 = ( REGISTER_LOONGARCH64_T5 + 1 ) , - REGISTER_LOONGARCH64_T7 = ( REGISTER_LOONGARCH64_T6 + 1 ) , - REGISTER_LOONGARCH64_T8 = ( REGISTER_LOONGARCH64_T7 + 1 ) , - REGISTER_LOONGARCH64_X0 = ( REGISTER_LOONGARCH64_T8 + 1 ) , - REGISTER_LOONGARCH64_FP = ( REGISTER_LOONGARCH64_X0 + 1 ) , - REGISTER_LOONGARCH64_S0 = ( REGISTER_LOONGARCH64_FP + 1 ) , - REGISTER_LOONGARCH64_S1 = ( REGISTER_LOONGARCH64_S0 + 1 ) , - REGISTER_LOONGARCH64_S2 = ( REGISTER_LOONGARCH64_S1 + 1 ) , - REGISTER_LOONGARCH64_S3 = ( REGISTER_LOONGARCH64_S2 + 1 ) , - REGISTER_LOONGARCH64_S4 = ( REGISTER_LOONGARCH64_S3 + 1 ) , - REGISTER_LOONGARCH64_S5 = ( REGISTER_LOONGARCH64_S4 + 1 ) , - REGISTER_LOONGARCH64_S6 = ( REGISTER_LOONGARCH64_S5 + 1 ) , - REGISTER_LOONGARCH64_S7 = ( REGISTER_LOONGARCH64_S6 + 1 ) , - REGISTER_LOONGARCH64_S8 = ( REGISTER_LOONGARCH64_S7 + 1 ) , - REGISTER_LOONGARCH64_PC = ( REGISTER_LOONGARCH64_S8 + 1 ) , - REGISTER_LOONGARCH64_F0 = ( REGISTER_LOONGARCH64_PC + 1 ) , - REGISTER_LOONGARCH64_F1 = ( REGISTER_LOONGARCH64_F0 + 1 ) , - REGISTER_LOONGARCH64_F2 = ( REGISTER_LOONGARCH64_F1 + 1 ) , - REGISTER_LOONGARCH64_F3 = ( REGISTER_LOONGARCH64_F2 + 1 ) , - REGISTER_LOONGARCH64_F4 = ( REGISTER_LOONGARCH64_F3 + 1 ) , - REGISTER_LOONGARCH64_F5 = ( REGISTER_LOONGARCH64_F4 + 1 ) , - REGISTER_LOONGARCH64_F6 = ( REGISTER_LOONGARCH64_F5 + 1 ) , - REGISTER_LOONGARCH64_F7 = ( REGISTER_LOONGARCH64_F6 + 1 ) , - REGISTER_LOONGARCH64_F8 = ( REGISTER_LOONGARCH64_F7 + 1 ) , - REGISTER_LOONGARCH64_F9 = ( REGISTER_LOONGARCH64_F8 + 1 ) , + REGISTER_LOONGARCH64_PC = 0, + REGISTER_LOONGARCH64_SP = ( REGISTER_LOONGARCH64_PC + 1 ) , + REGISTER_LOONGARCH64_FP = ( REGISTER_LOONGARCH64_SP + 1 ) , + REGISTER_LOONGARCH64_RA = ( REGISTER_LOONGARCH64_FP + 1 ) , + REGISTER_LOONGARCH64_TP = ( REGISTER_LOONGARCH64_RA + 1 ) , + REGISTER_LOONGARCH64_A0 = ( REGISTER_LOONGARCH64_TP + 1 ) , + REGISTER_LOONGARCH64_A1 = ( REGISTER_LOONGARCH64_A0 + 1 ) , + REGISTER_LOONGARCH64_A2 = ( REGISTER_LOONGARCH64_A1 + 1 ) , + REGISTER_LOONGARCH64_A3 = ( REGISTER_LOONGARCH64_A2 + 1 ) , + REGISTER_LOONGARCH64_A4 = ( REGISTER_LOONGARCH64_A3 + 1 ) , + REGISTER_LOONGARCH64_A5 = ( REGISTER_LOONGARCH64_A4 + 1 ) , + REGISTER_LOONGARCH64_A6 = ( REGISTER_LOONGARCH64_A5 + 1 ) , + REGISTER_LOONGARCH64_A7 = ( REGISTER_LOONGARCH64_A6 + 1 ) , + REGISTER_LOONGARCH64_T0 = ( REGISTER_LOONGARCH64_A7 + 1 ) , + REGISTER_LOONGARCH64_T1 = ( REGISTER_LOONGARCH64_T0 + 1 ) , + REGISTER_LOONGARCH64_T2 = ( REGISTER_LOONGARCH64_T1 + 1 ) , + REGISTER_LOONGARCH64_T3 = ( REGISTER_LOONGARCH64_T2 + 1 ) , + REGISTER_LOONGARCH64_T4 = ( REGISTER_LOONGARCH64_T3 + 1 ) , + REGISTER_LOONGARCH64_T5 = ( REGISTER_LOONGARCH64_T4 + 1 ) , + REGISTER_LOONGARCH64_T6 = ( REGISTER_LOONGARCH64_T5 + 1 ) , + REGISTER_LOONGARCH64_T7 = ( REGISTER_LOONGARCH64_T6 + 1 ) , + REGISTER_LOONGARCH64_T8 = ( REGISTER_LOONGARCH64_T7 + 1 ) , + REGISTER_LOONGARCH64_X0 = ( REGISTER_LOONGARCH64_T8 + 1 ) , + REGISTER_LOONGARCH64_S0 = ( REGISTER_LOONGARCH64_X0 + 1 ) , + REGISTER_LOONGARCH64_S1 = ( REGISTER_LOONGARCH64_S0 + 1 ) , + REGISTER_LOONGARCH64_S2 = ( REGISTER_LOONGARCH64_S1 + 1 ) , + REGISTER_LOONGARCH64_S3 = ( REGISTER_LOONGARCH64_S2 + 1 ) , + REGISTER_LOONGARCH64_S4 = ( REGISTER_LOONGARCH64_S3 + 1 ) , + REGISTER_LOONGARCH64_S5 = ( REGISTER_LOONGARCH64_S4 + 1 ) , + REGISTER_LOONGARCH64_S6 = ( REGISTER_LOONGARCH64_S5 + 1 ) , + REGISTER_LOONGARCH64_S7 = ( REGISTER_LOONGARCH64_S6 + 1 ) , + REGISTER_LOONGARCH64_S8 = ( REGISTER_LOONGARCH64_S7 + 1 ) , + REGISTER_LOONGARCH64_F0 = ( REGISTER_LOONGARCH64_S8 + 1 ) , + REGISTER_LOONGARCH64_F1 = ( REGISTER_LOONGARCH64_F0 + 1 ) , + REGISTER_LOONGARCH64_F2 = ( REGISTER_LOONGARCH64_F1 + 1 ) , + REGISTER_LOONGARCH64_F3 = ( REGISTER_LOONGARCH64_F2 + 1 ) , + REGISTER_LOONGARCH64_F4 = ( REGISTER_LOONGARCH64_F3 + 1 ) , + REGISTER_LOONGARCH64_F5 = ( REGISTER_LOONGARCH64_F4 + 1 ) , + REGISTER_LOONGARCH64_F6 = ( REGISTER_LOONGARCH64_F5 + 1 ) , + REGISTER_LOONGARCH64_F7 = ( REGISTER_LOONGARCH64_F6 + 1 ) , + REGISTER_LOONGARCH64_F8 = ( REGISTER_LOONGARCH64_F7 + 1 ) , + REGISTER_LOONGARCH64_F9 = ( REGISTER_LOONGARCH64_F8 + 1 ) , REGISTER_LOONGARCH64_F10 = ( REGISTER_LOONGARCH64_F9 + 1 ) , REGISTER_LOONGARCH64_F11 = ( REGISTER_LOONGARCH64_F10 + 1 ) , REGISTER_LOONGARCH64_F12 = ( REGISTER_LOONGARCH64_F11 + 1 ) , diff --git a/src/coreclr/pal/src/arch/loongarch64/context2.S b/src/coreclr/pal/src/arch/loongarch64/context2.S index ff0b6e040b42d9..97e02574fb4365 100644 --- a/src/coreclr/pal/src/arch/loongarch64/context2.S +++ b/src/coreclr/pal/src/arch/loongarch64/context2.S @@ -97,7 +97,7 @@ LOCAL_LABEL(No_Restore_CONTEXT_FLOATING_POINT): ld.d $t6, $a0, CONTEXT_T6 ld.d $t7, $a0, CONTEXT_T7 ld.d $t8, $a0, CONTEXT_T8 - //ld.d $r21,$a0, CONTEXT_X0 + ld.d $s0, $a0, CONTEXT_S0 ld.d $s1, $a0, CONTEXT_S1 ld.d $s2, $a0, CONTEXT_S2 @@ -106,10 +106,8 @@ LOCAL_LABEL(No_Restore_CONTEXT_FLOATING_POINT): ld.d $s5, $a0, CONTEXT_S5 ld.d $s6, $a0, CONTEXT_S6 ld.d $s7, $a0, CONTEXT_S7 -#ifndef CONTEXT_S8 -#error "----------------nodefine8" -#endif ld.d $s8, $a0, CONTEXT_S8 + ld.d $a0, $a0, CONTEXT_A0 LOCAL_LABEL(No_Restore_CONTEXT_INTEGER): @@ -127,7 +125,8 @@ LOCAL_LABEL(No_Restore_CONTEXT_INTEGER): LOCAL_LABEL(No_Restore_CONTEXT_CONTROL): - jirl $r0, $ra, 0 + ld.d $t4, $t4, CONTEXT_T4 + jirl $r0, $ra, 0 LEAF_END RtlRestoreContext, _TEXT // Incoming: diff --git a/src/coreclr/vm/loongarch64/cgencpu.h b/src/coreclr/vm/loongarch64/cgencpu.h index 277724276d21a1..ea682213c3aa46 100644 --- a/src/coreclr/vm/loongarch64/cgencpu.h +++ b/src/coreclr/vm/loongarch64/cgencpu.h @@ -167,6 +167,13 @@ inline void SetRA(T_CONTEXT * context, TADDR ip) { context->Ra = ip; } +inline TADDR GetReg(T_CONTEXT * context, int Regnum) +{ + LIMITED_METHOD_DAC_CONTRACT; + _ASSERTE((Regnum > 0) && (Regnum < 32)); + return (TADDR)(&context->R0 + Regnum); +} + extern "C" LPVOID __stdcall GetCurrentSP(); inline void SetSP(T_CONTEXT *context, TADDR sp) {