Skip to content

Commit dafaf4a

Browse files
authored
[RISC-V] Add quirks for riscv to R2RDump (#101683)
* [RISC-V] Add quirks for riscv * [RISC-V] minimize code
1 parent 9c710c4 commit dafaf4a

File tree

1 file changed

+183
-0
lines changed

1 file changed

+183
-0
lines changed

src/coreclr/tools/r2rdump/CoreDisTools.cs

+183
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)