@@ -359,6 +359,10 @@ public int GetInstruction(RuntimeFunction rtf, int imageOffset, int rtfOffset, o
359
359
case Machine . ArmThumb2 :
360
360
break ;
361
361
362
+ case Machine . RiscV64 :
363
+ ProbeRiscV64Quirks ( rtf , imageOffset , rtfOffset , ref fixedTranslatedLine ) ;
364
+ break ;
365
+
362
366
default :
363
367
break ;
364
368
}
@@ -1209,6 +1213,185 @@ private static bool IsAnotherRuntimeFunctionWithinMethod(int rva, RuntimeFunctio
1209
1213
return false ;
1210
1214
}
1211
1215
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
+
1212
1395
/// <summary>
1213
1396
/// Determine whether a given character is an ASCII digit.
1214
1397
/// </summary>
0 commit comments