@@ -359,6 +359,10 @@ public int GetInstruction(RuntimeFunction rtf, int imageOffset, int rtfOffset, o
359359 case Machine . ArmThumb2 :
360360 break ;
361361
362+ case Machine . RiscV64 :
363+ ProbeRiscV64Quirks ( rtf , imageOffset , rtfOffset , ref fixedTranslatedLine ) ;
364+ break ;
365+
362366 default :
363367 break ;
364368 }
@@ -1209,6 +1213,185 @@ private static bool IsAnotherRuntimeFunctionWithinMethod(int rva, RuntimeFunctio
12091213 return false ;
12101214 }
12111215
1216+ /// <summary>
1217+ /// Improves disassembler output for RiscV64 by adding comments at the end of instructions.
1218+ /// </summary>
1219+ /// <param name="rtf">Runtime function</param>
1220+ /// <param name="imageOffset">Offset within the image byte array</param>
1221+ /// <param name="rtfOffset">Offset within the runtime function</param>
1222+ /// <param name="instruction">Textual representation of the instruction</param>
1223+ private void ProbeRiscV64Quirks ( RuntimeFunction rtf , int imageOffset , int rtfOffset , ref string instruction )
1224+ {
1225+ const int InstructionSize = 4 ;
1226+ uint instr = BitConverter . ToUInt32 ( _reader . Image , imageOffset + rtfOffset ) ;
1227+
1228+ if ( IsRiscV64JalrInstruction ( instr ) )
1229+ {
1230+ /*
1231+ Supported patterns:
1232+ auipc
1233+ addi
1234+ ld
1235+ jalr
1236+
1237+ auipc
1238+ ld
1239+ jalr
1240+
1241+ auipc
1242+ addi
1243+ ld
1244+ ld
1245+ jalr
1246+
1247+ Irrelevant instructions for calle address calculations are skiped.
1248+ */
1249+
1250+ AnalyzeRiscV64Itype ( instr , out uint rd , out uint rs1 , out int imm ) ;
1251+ uint register = rs1 ;
1252+ int target = imm ;
1253+
1254+ bool isFound = false ;
1255+ int currentInstrOffset = rtfOffset - InstructionSize ;
1256+ int currentPC = rtf . StartAddress + currentInstrOffset ;
1257+ do
1258+ {
1259+ instr = BitConverter . ToUInt32 ( _reader . Image , imageOffset + currentInstrOffset ) ;
1260+
1261+ if ( IsRiscV64LdInstruction ( instr ) )
1262+ {
1263+ AnalyzeRiscV64Itype ( instr , out rd , out rs1 , out imm ) ;
1264+ if ( rd == register )
1265+ {
1266+ target = imm ;
1267+ register = rs1 ;
1268+ }
1269+ }
1270+ else if ( IsRiscV64AddiInstruction ( instr ) )
1271+ {
1272+ AnalyzeRiscV64Itype ( instr , out rd , out rs1 , out imm ) ;
1273+ if ( rd == register )
1274+ {
1275+ target = + imm ;
1276+ register = rs1 ;
1277+ }
1278+ }
1279+ else if ( IsRiscV64AuipcInstruction ( instr ) )
1280+ {
1281+ AnalyzeRiscV64Utype ( instr , out rd , out imm ) ;
1282+ if ( rd == register )
1283+ {
1284+ target += currentPC + imm ;
1285+ isFound = true ;
1286+ break ;
1287+ }
1288+ }
1289+ else
1290+ {
1291+ // check if callee address is calculated using an unsupported instruction
1292+ rd = ( instr >> 7 ) & 0b_11111U ;
1293+ if ( rd == register )
1294+ {
1295+ break ;
1296+ }
1297+ }
1298+
1299+ currentInstrOffset -= InstructionSize ;
1300+ currentPC -= InstructionSize ;
1301+ } while ( currentInstrOffset > 0 ) ;
1302+
1303+ if ( isFound )
1304+ {
1305+ if ( ! TryGetImportCellName ( target , out string targetName ) || string . IsNullOrWhiteSpace ( targetName ) )
1306+ {
1307+ return ;
1308+ }
1309+
1310+ instruction = $ "{ instruction } // { targetName } ";
1311+ }
1312+ }
1313+ }
1314+
1315+ /// <summary>
1316+ /// Checks if instruction is auipc.
1317+ /// </summary>
1318+ /// <param name="instruction">Assembly code of instruction</param>
1319+ /// <returns>It returns true if instruction is auipc. Otherwise false</returns>
1320+ private bool IsRiscV64AuipcInstruction ( uint instruction )
1321+ {
1322+ const uint OpcodeAuipc = 0b_0010111 ;
1323+ return ( instruction & 0x7f ) == OpcodeAuipc ;
1324+ }
1325+
1326+ /// <summary>
1327+ /// Checks if instruction is jalr.
1328+ /// </summary>
1329+ /// <param name="instruction">Assembly code of instruction</param>
1330+ /// <returns>It returns true if instruction is jalr. Otherwise false</returns>
1331+ private bool IsRiscV64JalrInstruction ( uint instruction )
1332+ {
1333+ const uint OpcodeJalr = 0b_1100111 ;
1334+ const uint Funct3Jalr = 0b_000 ;
1335+ return ( instruction & 0x7f ) == OpcodeJalr &&
1336+ ( ( instruction >> 12 ) & 0b_111 ) == Funct3Jalr ;
1337+ }
1338+
1339+ /// <summary>
1340+ /// Checks if instruction is addi.
1341+ /// </summary>
1342+ /// <param name="instruction">Assembly code of instruction</param>
1343+ /// <returns>It returns true if instruction is addi. Otherwise false</returns>
1344+ private bool IsRiscV64AddiInstruction ( uint instruction )
1345+ {
1346+ const uint OpcodeAddi = 0b_0010011 ;
1347+ const uint Funct3Addi = 0b_000 ;
1348+ return ( instruction & 0x7f ) == OpcodeAddi &&
1349+ ( ( instruction >> 12 ) & 0b_111 ) == Funct3Addi ;
1350+ }
1351+
1352+ /// <summary>
1353+ /// Checks if instruction is ld.
1354+ /// </summary>
1355+ /// <param name="instruction">Assembly code of instruction</param>
1356+ /// <returns>It returns true if instruction is ld. Otherwise false</returns>
1357+ private bool IsRiscV64LdInstruction ( uint instruction )
1358+ {
1359+ const uint OpcodeLd = 0b_0000011 ;
1360+ const uint Funct3Ld = 0b_011 ;
1361+ return ( instruction & 0x7f ) == OpcodeLd &&
1362+ ( ( instruction >> 12 ) & 0b_111 ) == Funct3Ld ;
1363+ }
1364+
1365+ /// <summary>
1366+ /// Retrieves output register and immediate value from U-type instruction.
1367+ /// </summary>
1368+ /// <param name="instruction">Assembly code of instruction</param>
1369+ /// <param name="rd">Output register</param>
1370+ /// <param name="imm">Immediate value</param>
1371+ private void AnalyzeRiscV64Utype ( uint instruction , out uint rd , out int imm )
1372+ {
1373+ // U-type 31 12 11 7 6 0
1374+ // [ imm ] [ rd ] [ opcode ]
1375+ rd = ( instruction >> 7 ) & 0b_11111U ;
1376+ imm = unchecked ( ( int ) ( instruction & ( 0xfffff << 12 ) ) ) ;
1377+ }
1378+
1379+ /// <summary>
1380+ /// Retrieves output register, resource register and immediate value from U-type instruction.
1381+ /// </summary>
1382+ /// <param name="instruction">Assembly code of instruction</param>
1383+ /// <param name="rd">Output register</param>
1384+ /// <param name="rs1">Resource register</param>
1385+ /// <param name="imm">Immediate value</param>
1386+ private void AnalyzeRiscV64Itype ( uint instruction , out uint rd , out uint rs1 , out int imm )
1387+ {
1388+ // I-type 31 20 19 15 14 12 11 7 6 0
1389+ // [ imm ] [ rs1 ] [ funct3 ] [ rd ] [ opcode ]
1390+ rd = ( instruction >> 7 ) & 0b_11111U ;
1391+ rs1 = ( instruction >> 15 ) & 0b_11111U ;
1392+ imm = unchecked ( ( int ) instruction ) >> 20 ;
1393+ }
1394+
12121395 /// <summary>
12131396 /// Determine whether a given character is an ASCII digit.
12141397 /// </summary>
0 commit comments