@@ -343,14 +343,12 @@ void ReplaceInstrAfterCall(PBYTE instrToReplace, MethodDesc* callMD)
343
343
{
344
344
*instrToReplace = INTERRUPT_INSTR;
345
345
}
346
- #elif defined(TARGET_LOONGARCH64)
346
+ #elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
347
347
bool protectReturn = ispointerKind;
348
348
if (protectReturn)
349
349
*(DWORD*)instrToReplace = INTERRUPT_INSTR_PROTECT_RET;
350
350
else
351
351
*(DWORD*)instrToReplace = INTERRUPT_INSTR;
352
- #elif defined(TARGET_RISCV64)
353
- _ASSERTE (!" not implemented for RISCV64 NYI" );
354
352
#else
355
353
_ASSERTE (!" not implemented for platform" );
356
354
#endif
@@ -680,6 +678,15 @@ void GCCoverageInfo::SprinkleBreakpoints(
680
678
681
679
#if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
682
680
681
+ #ifdef TARGET_RISCV64
682
+ enum
683
+ {
684
+ REG_RA = 1 ,
685
+ JAL = 0x6f ,
686
+ JALR = 0x67 ,
687
+ };
688
+ #endif
689
+
683
690
#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED
684
691
685
692
void replaceSafePointInstructionWithGcStressInstr (UINT32 safePointOffset, LPVOID pGCCover)
@@ -780,7 +787,15 @@ void replaceSafePointInstructionWithGcStressInstr(UINT32 safePointOffset, LPVOID
780
787
instructionIsACallThroughRegister = TRUE ;
781
788
}
782
789
#elif defined(TARGET_RISCV64)
783
- _ASSERTE (!" not implemented for RISCV64 NYI" );
790
+ const INT32 instr = *((INT32*)savedInstrPtr - 1 );
791
+
792
+ int opcode = instr & ~(-1 << 7 );
793
+ int linkReg = (instr >> 7 ) & ~(-1 << 5 );
794
+
795
+ if ((opcode == JAL) && (linkReg == REG_RA))
796
+ instructionIsACallThroughImmediate = TRUE ;
797
+ else if ((opcode == JALR) && (linkReg == REG_RA))
798
+ instructionIsACallThroughRegister = TRUE ;
784
799
#endif // _TARGET_XXXX_
785
800
786
801
// safe point must always be after a call instruction
@@ -1028,7 +1043,38 @@ static PBYTE getTargetOfCall(PBYTE instrPtr, PCONTEXT regs, PBYTE* nextInstr) {
1028
1043
return 0 ; // Fail
1029
1044
}
1030
1045
#elif defined(TARGET_RISCV64)
1031
- _ASSERTE (!" not implemented for RISCV64 NYI" );
1046
+ INT32 instr = *reinterpret_cast <INT32*>(instrPtr);
1047
+ int opcode = instr & ~(-1 << 7 );
1048
+ int linkReg = (instr >> 7 ) & ~(-1 << 5 );
1049
+
1050
+ if ((opcode == JAL) && (linkReg == REG_RA))
1051
+ {
1052
+ // call through immediate
1053
+ int imm = (instr >> 12 );
1054
+
1055
+ int bits12to19 = imm & ~(-1 << 8 );
1056
+ imm >>= 8 ;
1057
+ int bit11 = imm & ~(-1 << 1 );
1058
+ imm >>= 1 ;
1059
+ int bits1to10 = imm & ~(-1 << 10 );
1060
+ imm >>= 10 ;
1061
+ int signBits = imm;
1062
+
1063
+ int offset = (bits1to10 << 1 ) | (bit11 << 11 ) | (bits12to19 << 12 ) | (signBits << 20 );
1064
+
1065
+ *nextInstr = instrPtr + 4 ;
1066
+ return PC + offset;
1067
+ }
1068
+ else if ((opcode == JALR) && (linkReg == REG_RA))
1069
+ {
1070
+ // call through register
1071
+ *nextInstr = instrPtr + 4 ; // TODO: adjust once we support "C" (compressed instructions)
1072
+
1073
+ int offset = (instr >> 20 );
1074
+ int jumpBaseReg = (instr >> 15 ) & ~(-1 << 5 );
1075
+ size_t value = (getRegVal (jumpBaseReg, regs) + offset) & ~(size_t )1 ;
1076
+ return (BYTE *)value;
1077
+ }
1032
1078
#endif
1033
1079
1034
1080
#ifdef TARGET_AMD64
@@ -1495,7 +1541,7 @@ void DoGcStress (PCONTEXT regs, NativeCodeVersion nativeCodeVersion)
1495
1541
atCall = (instrVal == INTERRUPT_INSTR_CALL);
1496
1542
afterCallProtect[0 ] = (instrVal == INTERRUPT_INSTR_PROTECT_RET);
1497
1543
#elif defined(TARGET_RISCV64)
1498
- _ASSERTE (! " not implemented for RISCV64 NYI " );
1544
+
1499
1545
DWORD instrVal = *(DWORD *)instrPtr;
1500
1546
forceStack[6 ] = &instrVal; // This is so I can see it fastchecked
1501
1547
0 commit comments