@@ -131,6 +131,11 @@ internal sealed class Disassembler : IDisposable
131131 /// </summary>
132132 private int _addInstructionTarget ;
133133
134+ /// <summary>
135+ /// RISC-V: temporary address for combos like "auipc temp, hi20; jalr/addi/ld rd, temp, lo12"
136+ /// </summary>
137+ private ( uint Register , int Value ) _address ;
138+
134139 /// <summary>
135140 /// Indentation of instruction mnemonics.
136141 /// </summary>
@@ -358,7 +363,7 @@ public int GetInstruction(RuntimeFunction rtf, int imageOffset, int rtfOffset, o
358363 break ;
359364
360365 case Machine . RiscV64 :
361- // TODO-RISCV64-RVC: Add back ProbeRiscV64Quirks here once it's modified to support compressed instructions.
366+ ProbeRiscV64Quirks ( rtf , imageOffset , rtfOffset , instrSize , ref fixedTranslatedLine ) ;
362367 break ;
363368
364369 default :
@@ -1217,178 +1222,73 @@ private static bool IsAnotherRuntimeFunctionWithinMethod(int rva, RuntimeFunctio
12171222 /// <param name="rtf">Runtime function</param>
12181223 /// <param name="imageOffset">Offset within the image byte array</param>
12191224 /// <param name="rtfOffset">Offset within the runtime function</param>
1225+ /// <param name="instrSize">Instruction size</param>
12201226 /// <param name="instruction">Textual representation of the instruction</param>
1221- private void ProbeRiscV64Quirks ( RuntimeFunction rtf , int imageOffset , int rtfOffset , ref string instruction )
1227+ private void ProbeRiscV64Quirks ( RuntimeFunction rtf , int imageOffset , int rtfOffset , int instrSize , ref string instruction )
12221228 {
1223- // TODO-RISCV64-RVC: Modify this method to detect patterns in forward traversal. See ProbeArm64Quirks implementation.
1224- const int InstructionSize = 4 ;
1225- uint instr = BitConverter . ToUInt32 ( _reader . Image , imageOffset + rtfOffset ) ;
1229+ uint instr = ( instrSize == 4 )
1230+ ? BitConverter . ToUInt32 ( _reader . Image , imageOffset + rtfOffset )
1231+ : BitConverter . ToUInt16 ( _reader . Image , imageOffset + rtfOffset ) ;
1232+ Debug . Assert ( ( instrSize == 4 ) == ( ( instr & 0b11 ) == 0b11 ) , "instruction size mismatch" ) ;
12261233
1227- if ( IsRiscV64JalrInstruction ( instr ) )
1234+ // Lookup cell name for auipc + jalr/ld/addi
1235+ if ( AnalyzeRiscV64Auipc ( instr , ref _address . Register , out int imm ) )
12281236 {
1229- /*
1230- Supported patterns:
1231- auipc
1232- addi
1233- ld
1234- jalr
1235-
1236- auipc
1237- ld
1238- jalr
1239-
1240- auipc
1241- addi
1242- ld
1243- ld
1244- jalr
1245-
1246- Irrelevant instructions for calle address calculations are skiped.
1247- */
1248-
1249- AnalyzeRiscV64Itype ( instr , out uint rd , out uint rs1 , out int imm ) ;
1250- uint register = rs1 ;
1251- int target = imm ;
1252-
1253- bool isFound = false ;
1254- int currentInstrOffset = rtfOffset - InstructionSize ;
1255- int currentPC = rtf . StartAddress + currentInstrOffset ;
1256- do
1257- {
1258- instr = BitConverter . ToUInt32 ( _reader . Image , imageOffset + currentInstrOffset ) ;
1259-
1260- if ( IsRiscV64LdInstruction ( instr ) )
1261- {
1262- AnalyzeRiscV64Itype ( instr , out rd , out rs1 , out imm ) ;
1263- if ( rd == register )
1264- {
1265- target = imm ;
1266- register = rs1 ;
1267- }
1268- }
1269- else if ( IsRiscV64AddiInstruction ( instr ) )
1270- {
1271- AnalyzeRiscV64Itype ( instr , out rd , out rs1 , out imm ) ;
1272- if ( rd == register )
1273- {
1274- target = + imm ;
1275- register = rs1 ;
1276- }
1277- }
1278- else if ( IsRiscV64AuipcInstruction ( instr ) )
1279- {
1280- AnalyzeRiscV64Utype ( instr , out rd , out imm ) ;
1281- if ( rd == register )
1282- {
1283- target += currentPC + imm ;
1284- isFound = true ;
1285- break ;
1286- }
1287- }
1288- else
1289- {
1290- // check if callee address is calculated using an unsupported instruction
1291- rd = ( instr >> 7 ) & 0b_11111U ;
1292- if ( rd == register )
1293- {
1294- break ;
1295- }
1296- }
1297-
1298- currentInstrOffset -= InstructionSize ;
1299- currentPC -= InstructionSize ;
1300- } while ( currentInstrOffset > 0 ) ;
1301-
1302- if ( isFound )
1303- {
1304- if ( ! TryGetImportCellName ( target , out string targetName ) || string . IsNullOrWhiteSpace ( targetName ) )
1305- {
1306- return ;
1307- }
1308-
1309- instruction = $ "{ instruction } // { targetName } ";
1310- }
1237+ _address . Value = rtf . StartAddress + rtfOffset + imm ;
1238+ return ;
13111239 }
1240+ else if ( _address . Register != 0 && AnalyzeRiscV64Itype ( instr , _address . Register , out imm ) )
1241+ {
1242+ _address . Value += imm ;
1243+ if ( TryGetImportCellName ( _address . Value , out string name ) && ! string . IsNullOrWhiteSpace ( name ) )
1244+ instruction = $ "{ instruction } // { name } ";
1245+ }
1246+ _address . Register = 0 ;
13121247 }
13131248
13141249 /// <summary>
1315- /// Checks if instruction is auipc.
1316- /// </summary>
1317- /// <param name="instruction">Assembly code of instruction</param>
1318- /// <returns>It returns true if instruction is auipc. Otherwise false</returns>
1319- private bool IsRiscV64AuipcInstruction ( uint instruction )
1320- {
1321- const uint OpcodeAuipc = 0b_0010111 ;
1322- return ( instruction & 0x7f ) == OpcodeAuipc ;
1323- }
1324-
1325- /// <summary>
1326- /// Checks if instruction is jalr.
1327- /// </summary>
1328- /// <param name="instruction">Assembly code of instruction</param>
1329- /// <returns>It returns true if instruction is jalr. Otherwise false</returns>
1330- private bool IsRiscV64JalrInstruction ( uint instruction )
1331- {
1332- const uint OpcodeJalr = 0b_1100111 ;
1333- const uint Funct3Jalr = 0b_000 ;
1334- return ( instruction & 0x7f ) == OpcodeJalr &&
1335- ( ( instruction >> 12 ) & 0b_111 ) == Funct3Jalr ;
1336- }
1337-
1338- /// <summary>
1339- /// Checks if instruction is addi.
1340- /// </summary>
1341- /// <param name="instruction">Assembly code of instruction</param>
1342- /// <returns>It returns true if instruction is addi. Otherwise false</returns>
1343- private bool IsRiscV64AddiInstruction ( uint instruction )
1344- {
1345- const uint OpcodeAddi = 0b_0010011 ;
1346- const uint Funct3Addi = 0b_000 ;
1347- return ( instruction & 0x7f ) == OpcodeAddi &&
1348- ( ( instruction >> 12 ) & 0b_111 ) == Funct3Addi ;
1349- }
1350-
1351- /// <summary>
1352- /// Checks if instruction is ld.
1353- /// </summary>
1354- /// <param name="instruction">Assembly code of instruction</param>
1355- /// <returns>It returns true if instruction is ld. Otherwise false</returns>
1356- private bool IsRiscV64LdInstruction ( uint instruction )
1357- {
1358- const uint OpcodeLd = 0b_0000011 ;
1359- const uint Funct3Ld = 0b_011 ;
1360- return ( instruction & 0x7f ) == OpcodeLd &&
1361- ( ( instruction >> 12 ) & 0b_111 ) == Funct3Ld ;
1362- }
1363-
1364- /// <summary>
1365- /// Retrieves output register and immediate value from U-type instruction.
1250+ /// Retrieves destination register and immediate value from an auipc instruction.
13661251 /// </summary>
13671252 /// <param name="instruction">Assembly code of instruction</param>
1368- /// <param name="rd">Output register</param>
1253+ /// <param name="rd">Destination register</param>
13691254 /// <param name="imm">Immediate value</param>
1370- private void AnalyzeRiscV64Utype ( uint instruction , out uint rd , out int imm )
1255+ /// <returns>Whether the instruction is an auipc</returns>
1256+ private bool AnalyzeRiscV64Auipc ( uint instruction , ref uint rd , out int imm )
13711257 {
13721258 // U-type 31 12 11 7 6 0
13731259 // [ imm ] [ rd ] [ opcode ]
1260+ const uint Auipc = 0b_0010111 ;
1261+ if ( ( instruction & 0x7f ) != Auipc )
1262+ {
1263+ imm = 0 ;
1264+ return false ;
1265+ }
13741266 rd = ( instruction >> 7 ) & 0b_11111U ;
13751267 imm = unchecked ( ( int ) ( instruction & ( 0xfffff << 12 ) ) ) ;
1268+ return true ;
13761269 }
13771270
13781271 /// <summary>
1379- /// Retrieves output register, resource register and immediate value from U-type instruction.
1272+ /// Retrieves immediate value from an I-type instruction that is interesting,
1273+ /// i.e. jalr, ld, addi with source register matching the address register.
13801274 /// </summary>
13811275 /// <param name="instruction">Assembly code of instruction</param>
1382- /// <param name="rd">Output register</param>
1383- /// <param name="rs1">Resource register</param>
1276+ /// <param name="addrReg">address register</param>
13841277 /// <param name="imm">Immediate value</param>
1385- private void AnalyzeRiscV64Itype ( uint instruction , out uint rd , out uint rs1 , out int imm )
1278+ /// <returns>Whether the instruction is an interesting I-type</returns>
1279+ private bool AnalyzeRiscV64Itype ( uint instruction , uint addrReg , out int imm )
13861280 {
13871281 // I-type 31 20 19 15 14 12 11 7 6 0
13881282 // [ imm ] [ rs1 ] [ funct3 ] [ rd ] [ opcode ]
1389- rd = ( instruction >> 7 ) & 0b_11111U ;
1390- rs1 = ( instruction >> 15 ) & 0b_11111U ;
1391- imm = unchecked ( ( int ) instruction ) >> 20 ;
1283+ const uint Mask = 0b_111_00000_1111111 ;
1284+ const uint Jalr = 0b_000_00000_1100111 ;
1285+ const uint Ld = 0b_011_00000_0000011 ;
1286+ const uint Addi = 0b_000_00000_0010011 ;
1287+
1288+ uint rs1 = ( instruction >> 15 ) & 0b_11111U ;
1289+ bool isInteresting = ( ( instruction & Mask ) is Jalr or Ld or Addi ) && ( rs1 == addrReg ) ;
1290+ imm = isInteresting ? unchecked ( ( int ) instruction ) >> 20 : 0 ;
1291+ return isInteresting ;
13921292 }
13931293
13941294 /// <summary>
0 commit comments