Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 165 additions & 3 deletions src/coreclr/debug/di/riscv64/cordbregisterset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,25 +83,187 @@ HRESULT CordbRegisterSet::GetRegistersAvailable(ULONG64* pAvailable)
return S_OK;
}

// Reads the value of a single register (identified by a CorDebugRegister index) into *pValue.
// Shared by both GetRegisters overloads to avoid duplicating the per-register mapping.
static HRESULT GetRegisterValue(CordbThread * pThread, const DT_CONTEXT * pContext, int regIndex, CORDB_REGISTER * pValue)
{
if ((regIndex >= REGISTER_RISCV64_F0) && (regIndex <= REGISTER_RISCV64_F31))
{
if (!pThread->m_fFloatStateValid)
{
HRESULT hr = S_OK;
EX_TRY
{
pThread->LoadFloatState();
}
EX_CATCH_HRESULT(hr);

if ( !SUCCEEDED(hr) )
{
return hr;
}
LOG( ( LF_CORDB, LL_INFO1000, "CRS::GR: Loaded float state\n" ) );
}

*pValue = *(CORDB_REGISTER*)&(pThread->m_floatValues[(regIndex - REGISTER_RISCV64_F0)]);
return S_OK;
}

switch (regIndex)
{
case REGISTER_RISCV64_PC:
*pValue = pContext->Pc; break;
case REGISTER_RISCV64_RA:
*pValue = pContext->Ra; break;
case REGISTER_RISCV64_SP:
*pValue = pContext->Sp; break;
case REGISTER_RISCV64_GP:
*pValue = pContext->Gp; break;
case REGISTER_RISCV64_TP:
*pValue = pContext->Tp; break;
case REGISTER_RISCV64_T0:
*pValue = pContext->T0; break;
case REGISTER_RISCV64_T1:
*pValue = pContext->T1; break;
case REGISTER_RISCV64_T2:
*pValue = pContext->T2; break;
case REGISTER_RISCV64_FP:
*pValue = pContext->Fp; break;
case REGISTER_RISCV64_S1:
*pValue = pContext->S1; break;
case REGISTER_RISCV64_A0:
*pValue = pContext->A0; break;
case REGISTER_RISCV64_A1:
*pValue = pContext->A1; break;
case REGISTER_RISCV64_A2:
*pValue = pContext->A2; break;
case REGISTER_RISCV64_A3:
*pValue = pContext->A3; break;
case REGISTER_RISCV64_A4:
*pValue = pContext->A4; break;
case REGISTER_RISCV64_A5:
*pValue = pContext->A5; break;
case REGISTER_RISCV64_A6:
*pValue = pContext->A6; break;
case REGISTER_RISCV64_A7:
*pValue = pContext->A7; break;
case REGISTER_RISCV64_S2:
*pValue = pContext->S2; break;
case REGISTER_RISCV64_S3:
*pValue = pContext->S3; break;
case REGISTER_RISCV64_S4:
*pValue = pContext->S4; break;
case REGISTER_RISCV64_S5:
*pValue = pContext->S5; break;
case REGISTER_RISCV64_S6:
*pValue = pContext->S6; break;
case REGISTER_RISCV64_S7:
*pValue = pContext->S7; break;
case REGISTER_RISCV64_S8:
*pValue = pContext->S8; break;
case REGISTER_RISCV64_S9:
*pValue = pContext->S9; break;
case REGISTER_RISCV64_S10:
*pValue = pContext->S10; break;
case REGISTER_RISCV64_S11:
*pValue = pContext->S11; break;
case REGISTER_RISCV64_T3:
*pValue = pContext->T3; break;
case REGISTER_RISCV64_T4:
*pValue = pContext->T4; break;
case REGISTER_RISCV64_T5:
*pValue = pContext->T5; break;
case REGISTER_RISCV64_T6:
*pValue = pContext->T6; break;
default:
_ASSERTE(false); break;
}

return S_OK;
}

HRESULT CordbRegisterSet::GetRegisters(ULONG64 mask, ULONG32 regCount,
CORDB_REGISTER regBuffer[])
{
_ASSERTE(!"RISCV64:NYI");
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_RISCV64_PC;
i <= REGISTER_RISCV64_F31 && iRegister < regCount;
i++)
{
if (mask & SETBITULONG64(i))
{
_ASSERTE (iRegister < regCount);

HRESULT hr = GetRegisterValue(m_thread, &m_context, i, &regBuffer[iRegister]);
if (FAILED(hr))
{
return hr;
}
iRegister++;
}
}

_ASSERTE (iRegister <= regCount);
return S_OK;
}


HRESULT CordbRegisterSet::GetRegistersAvailable(ULONG32 regCount,
BYTE pAvailable[])
{
_ASSERTE(!"RISCV64:NYI");
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_RISCV64_F31)
{
pAvailable[i] = (i * 8 == REGISTER_RISCV64_F31) ? BYTE(0x1) : BYTE(0xff);
}
else
{
pAvailable[i] = 0;
}
}

return S_OK;
}


HRESULT CordbRegisterSet::GetRegisters(ULONG32 maskCount, BYTE mask[],
ULONG32 regCount, CORDB_REGISTER regBuffer[])
{
_ASSERTE(!"RISCV64:NYI");
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;

HRESULT hr = GetRegisterValue(m_thread, &m_context, i, &regBuffer[iRegister]);
if (FAILED(hr))
{
return hr;
}
iRegister++;
}
}
}

return S_OK;
}
4 changes: 4 additions & 0 deletions src/coreclr/debug/di/rspriv.h
Original file line number Diff line number Diff line change
Expand Up @@ -6084,6 +6084,10 @@ class CordbThread : public CordbBase, public ICorDebugThread,
// Converts the values in the floating point register area of the context to real number values.
void Get64bitFPRegisters(FPRegister64 * rgContextFPRegisters, int start, int nRegisters);

#elif defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)
// Copies the scalar 64-bit IEEE-754 value of each floating point register from the context.
void GetRawFPRegisters(ULONGLONG * pFPRegisters, int slotsPerRegister, int nRegisters);

#endif // TARGET_X86

// Initializes the float state members of this instance of CordbThread. This function gets the context and
Expand Down
29 changes: 29 additions & 0 deletions src/coreclr/debug/di/rsthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1546,6 +1546,28 @@ void CordbThread::Get64bitFPRegisters(FPRegister64 * rgContextFPRegisters, int s
}
} // CordbThread::Get64bitFPRegisters

#elif defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)

// CordbThread::GetRawFPRegisters
// Copies the scalar 64-bit IEEE-754 value of each floating point register directly from the
// context. On these platforms the floating point registers are already stored as raw doubles, so
// no hardware conversion (FPFillR8) is needed. slotsPerRegister is the number of ULONGLONG slots
// each register occupies in the context: 1 for RISC-V64, and 4 for LoongArch64, whose FPR64/LSX/LASX
// layout stores the scalar value in the first 64-bit slot of each group.
// Arguments:
// input: pFPRegisters - starting address of the floating point register storage of the CONTEXT
// slotsPerRegister - the number of ULONGLONG slots each register occupies
// nRegisters - the number of registers to be initialized
// output: none (initializes m_floatValues)

void CordbThread::GetRawFPRegisters(ULONGLONG * pFPRegisters, int slotsPerRegister, int nRegisters)
{
for (int reg = 0; reg < nRegisters; reg++)
{
m_floatValues[reg] = *(double*)&(pFPRegisters[reg * slotsPerRegister]);
}
} // CordbThread::GetRawFPRegisters

#endif // TARGET_X86

// CordbThread::LoadFloatState
Expand Down Expand Up @@ -1580,6 +1602,13 @@ void CordbThread::LoadFloatState()
Get64bitFPRegisters((FPRegister64*) &(tempContext.V), 0, 32);
#elif defined (TARGET_ARM)
Get64bitFPRegisters((FPRegister64*) &(tempContext.D), 0, 32);
#elif defined(TARGET_RISCV64)
// RISC-V64 stores each F register as a single raw 64-bit IEEE-754 value in the context.
GetRawFPRegisters((ULONGLONG*) &(tempContext.F), 1, DebuggerIPCE_FloatCount);
#elif defined(TARGET_LOONGARCH64)
// LoongArch64 stores floating point registers in a SIMD-capable layout (FPR64/LSX/LASX), where
// each F register occupies 4 ULONGLONG slots and the scalar value is the first 64-bit slot.
GetRawFPRegisters((ULONGLONG*) &(tempContext.F), 4, DebuggerIPCE_FloatCount);
#else
_ASSERTE(!"nyi for platform");
#endif // !TARGET_X86
Expand Down
Loading