Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RISC-V] Add pseudoinstructions to disassembler #102260

Merged
merged 25 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
f501f68
[RISC-V] Reworked emitDispInsName a bit to ease further development
Bajtazar May 15, 2024
344771c
[RISC-V] Little improvements
Bajtazar May 15, 2024
bac35dd
[RISC-V] Refactored code
Bajtazar May 15, 2024
ca5bf3d
[RISC-V] Added mv and nop pseudoinstructions to disasm
Bajtazar May 15, 2024
15d5830
[RISC-V] Added branch pseudos to disasm
Bajtazar May 15, 2024
f27b4f6
[RISC-V] Removed dead code
Bajtazar May 15, 2024
fb27640
[RISC-V] Fixes
Bajtazar May 15, 2024
0cf743e
[RISC-V] Added j pseudoinstruction to disasm
Bajtazar May 15, 2024
a9964cb
[RISC-V] Improved readability
Bajtazar May 15, 2024
a011c43
[RISC-V] Fixed mov pseudoinstruction
Bajtazar May 15, 2024
ebf66d9
Revert "[RISC-V] Fixed mov pseudoinstruction"
Bajtazar May 15, 2024
258b0c6
[RISC-V] Fixed mov printing name
Bajtazar May 16, 2024
dcba8e1
[RISC-V] After review changes
Bajtazar May 16, 2024
f100010
[RISC-V] More fixes after review
Bajtazar May 16, 2024
d69fa7b
[RISC-V] Adjusted 32-bit shift disasm to changes
Bajtazar May 16, 2024
92c0cd2
[RISC-V] Fixed bug
Bajtazar May 16, 2024
b7e4f65
[RISC-V] Fixed comment
Bajtazar May 16, 2024
093193b
[RISC-V] Changed constants' literal type
Bajtazar May 16, 2024
cda08a2
[RISC-V] Added more constants
Bajtazar May 16, 2024
e9b73ef
[RISC-V] Reinforced printing 1
Bajtazar May 16, 2024
5fe1e11
[RISC-V] Reinforced printing 2
Bajtazar May 16, 2024
71644f3
[RISC-V] Fixed bug
Bajtazar May 16, 2024
a3c4f19
[RISC-V] Resolved more bugs
Bajtazar May 16, 2024
6869460
[RISC-V] Removed dead assert
Bajtazar May 22, 2024
a4381bd
Merge branch 'main' into riscv-add-pseudo-to-disasm
Bajtazar May 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
209 changes: 143 additions & 66 deletions src/coreclr/jit/emitriscv64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3344,15 +3344,29 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
return sz;
}

bool emitter::emitDispBranchInstrType(unsigned opcode2) const
/*****************************************************************************/
/*****************************************************************************/

// clang-format off
static const char* const RegNames[] =
{
#define REGDEF(name, rnum, mask, sname) sname,
#include "register.h"
};
// clang-format on

bool emitter::emitDispBranchInstrType(unsigned opcode2, bool is_zero_reg, bool& print_second_reg) const
Bajtazar marked this conversation as resolved.
Show resolved Hide resolved
{
print_second_reg = true;
switch (opcode2)
{
case 0:
printf("beq ");
printf(is_zero_reg ? "beqz" : "beq ");
print_second_reg = !is_zero_reg;
break;
case 1:
printf("bne ");
printf(is_zero_reg ? "bnez" : "bne ");
print_second_reg = !is_zero_reg;
break;
case 4:
printf("blt ");
Expand Down Expand Up @@ -3404,17 +3418,19 @@ void emitter::emitDispBranchLabel(const instrDesc* id) const
printf("L_M%03u_", FMT_BB, emitComp->compMethodID, id->idAddr()->iiaBBlabel->bbNum);
}

bool emitter::emitDispBranch(unsigned opcode2,
const char* register1Name,
const char* register2Name,
const instrDesc* id,
const insGroup* ig) const
bool emitter::emitDispBranch(
unsigned opcode2, unsigned rs1, unsigned rs2, const instrDesc* id, const insGroup* ig) const
{
if (!emitDispBranchInstrType(opcode2))
bool print_second_reg = true;
if (!emitDispBranchInstrType(opcode2, rs2 == REG_ZERO, print_second_reg))
{
return false;
}
printf(" %s, %s, ", register1Name, register2Name);
printf(" %s, ", RegNames[rs1]);
if (print_second_reg)
{
printf("%s, ", RegNames[rs2]);
}
assert(id != nullptr);
if (id->idAddr()->iiaHasInstrCount())
{
Expand All @@ -3435,17 +3451,6 @@ void emitter::emitDispIllegalInstruction(code_t instructionCode)
printf("RISCV64 illegal instruction: 0x%08X\n", instructionCode);
}

/*****************************************************************************/
/*****************************************************************************/

// clang-format off
static const char* const RegNames[] =
{
#define REGDEF(name, rnum, mask, sname) sname,
#include "register.h"
};
// clang-format on

//----------------------------------------------------------------------------------------
// Disassemble the given instruction.
// The `emitter::emitDispInsName` is focused on the most important for debugging.
Expand All @@ -3467,6 +3472,8 @@ static const char* const RegNames[] =
void emitter::emitDispInsName(
code_t code, const BYTE* addr, bool doffs, unsigned insOffset, const instrDesc* id, const insGroup* ig)
{
static constexpr int kMaxInstructionLength = 14;

const BYTE* insAdr = addr - writeableOffset;

unsigned int opcode = code & 0x7f;
Expand Down Expand Up @@ -3503,51 +3510,94 @@ void emitter::emitDispInsName(
}
case 0x13:
{
unsigned int opcode2 = (code >> 12) & 0x7;
const char* rd = RegNames[(code >> 7) & 0x1f];
const char* rs1 = RegNames[(code >> 15) & 0x1f];
int imm12 = (((int)code) >> 20); // & 0xfff;
// if (imm12 & 0x800)
//{
// imm12 |= 0xfffff000;
//}
unsigned opcode2 = (code >> 12) & 0x7;
unsigned rd = (code >> 7) & 0x1f;
unsigned rs1 = (code >> 15) & 0x1f;
int imm12 = static_cast<int>(code) >> 20;
bool isHex = false;
bool hasImmediate = true;
int printLength = 0;

switch (opcode2)
{
case 0x0: // ADDI
printf("addi %s, %s, %d\n", rd, rs1, imm12);
return;
case 0x1: // SLLI
printf("slli %s, %s, %d\n", rd, rs1, imm12 & 0x3f); // 6 BITS for SHAMT in RISCV64
return;
case 0x0: // ADDI & MV & NOP
if (code == emitInsCode(INS_nop))
{
printf("nop\n");
return;
}
else if (imm12 != 0)
{
printLength = printf("addi");
}
else
{
printLength = printf("mv");
hasImmediate = false;
}
break;
case 0x1: // SLLI
{
unsigned funct6 = (imm12 >> 6) & 0x3f;
// SLLI's instruction code's upper 6 bits have to be equal to zero
if (funct6)
{
return emitDispIllegalInstruction(code);
}
printLength = printf("slli");
imm12 &= 0x3f; // 6 BITS for SHAMT in RISCV64
}
break;
case 0x2: // SLTI
printf("slti %s, %s, %d\n", rd, rs1, imm12);
return;
printLength = printf("slti");
break;
case 0x3: // SLTIU
printf("sltiu %s, %s, %d\n", rd, rs1, imm12);
return;
printLength = printf("sltiu");
break;
case 0x4: // XORI
printf("xori %s, %s, 0x%x\n", rd, rs1, imm12);
return;
printLength = printf("xori");
isHex = true;
break;
case 0x5: // SRLI & SRAI
if (((code >> 30) & 0x1) == 0)
{
printf("srli %s, %s, %d\n", rd, rs1, imm12 & 0x3f); // 6BITS for SHAMT in RISCV64
}
else
{
static constexpr unsigned kLogicalShiftFunct6 = 0x00;
static constexpr unsigned kArithmeticShiftFunct6 = 0x10;

unsigned funct6 = (imm12 >> 6) & 0x3f;
bool isLogicalShift = funct6 == kLogicalShiftFunct6;
if ((!isLogicalShift) && (funct6 != kArithmeticShiftFunct6))
{
printf("srai %s, %s, %d\n", rd, rs1, imm12 & 0x3f); // 6BITS for SHAMT in RISCV64
return emitDispIllegalInstruction(code);
}
return;
printLength = printf(isLogicalShift ? "srli" : "srai");
imm12 &= 0x3f; // 6BITS for SHAMT in RISCV64
}
break;
case 0x6: // ORI
printf("ori %s, %s, 0x%x\n", rd, rs1, imm12 & 0xfff);
return;
printLength = printf("ori");
imm12 &= 0xfff;
isHex = true;
break;
case 0x7: // ANDI
printf("andi %s, %s, 0x%x\n", rd, rs1, imm12 & 0xfff);
return;
printLength = printf("andi");
imm12 &= 0xfff;
isHex = true;
break;
default:
printf("RISCV64 illegal instruction: 0x%08X\n", code);
return;
return emitDispIllegalInstruction(code);
}
assert(printLength > 0);
int paddingLength = kMaxInstructionLength - printLength;
assert(paddingLength > 0);
Bajtazar marked this conversation as resolved.
Show resolved Hide resolved

printf("%*s %s, %s", paddingLength, "", RegNames[rd], RegNames[rs1]);
if (hasImmediate)
{
printf(isHex ? ", 0x%x" : ", %d", imm12);
}
printf("\n");

return;
}
case 0x1b:
{
Expand All @@ -3564,22 +3614,42 @@ void emitter::emitDispInsName(
case 0x0: // ADDIW
printf("addiw %s, %s, %d\n", rd, rs1, imm12);
return;
case 0x1: // SLLIW
printf("slliw %s, %s, %d\n", rd, rs1, imm12 & 0x3f); // 6 BITS for SHAMT in RISCV64
case 0x1: // SLLIW
{
unsigned funct7 = (imm12 >> 5) & 0x7f;
// SLLIW's instruction code's upper 7 bits have to be equal to zero
if (funct7 == 0)
{
printf("slliw %s, %s, %d\n", rd, rs1, imm12 & 0x1f); // 5 BITS for SHAMT in RISCV64
}
else
{
emitDispIllegalInstruction(code);
}
}
return;
case 0x5: // SRLIW & SRAIW
if (((code >> 30) & 0x1) == 0)
{
static constexpr unsigned kLogicalShiftFunct7 = 0x00;
static constexpr unsigned kArithmeticShiftFunct7 = 0x20;
Bajtazar marked this conversation as resolved.
Show resolved Hide resolved

unsigned funct7 = (imm12 >> 5) & 0x7f;
if (funct7 == kLogicalShiftFunct7)
{
printf("srliw %s, %s, %d\n", rd, rs1, imm12 & 0x1f); // 5BITS for SHAMT in RISCV64
}
else
else if (funct7 == kArithmeticShiftFunct7)
{
printf("sraiw %s, %s, %d\n", rd, rs1, imm12 & 0x1f); // 5BITS for SHAMT in RISCV64
}
else
{
emitDispIllegalInstruction(code);
}
}
return;
default:
printf("RISCV64 illegal instruction: 0x%08X\n", code);
return;
return emitDispIllegalInstruction(code);
}
}
case 0x33:
Expand Down Expand Up @@ -3777,9 +3847,9 @@ void emitter::emitDispInsName(
}
case 0x63: // BRANCH
{
unsigned int opcode2 = (code >> 12) & 0x7;
const char* rs1 = RegNames[(code >> 15) & 0x1f];
const char* rs2 = RegNames[(code >> 20) & 0x1f];
unsigned opcode2 = (code >> 12) & 0x7;
unsigned rs1 = (code >> 15) & 0x1f;
unsigned rs2 = (code >> 20) & 0x1f;
// int offset = (((code >> 31) & 0x1) << 12) | (((code >> 7) & 0x1) << 11) | (((code >> 25) & 0x3f) << 5) |
// (((code >> 8) & 0xf) << 1);
// if (offset & 0x800)
Expand Down Expand Up @@ -3856,14 +3926,21 @@ void emitter::emitDispInsName(
}
case 0x6f:
{
const char* rd = RegNames[(code >> 7) & 0x1f];
int offset = (((code >> 31) & 0x1) << 20) | (((code >> 12) & 0xff) << 12) | (((code >> 20) & 0x1) << 11) |
unsigned rd = (code >> 7) & 0x1f;
int offset = (((code >> 31) & 0x1) << 20) | (((code >> 12) & 0xff) << 12) | (((code >> 20) & 0x1) << 11) |
(((code >> 21) & 0x3ff) << 1);
if (offset & 0x80000)
{
offset |= 0xfff00000;
}
printf("jal %s, %d", rd, offset);
if (rd == REG_ZERO)
{
printf("j %d", offset);
}
else
{
printf("jal %s, %d", RegNames[rd], offset);
}
CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie;
if (handle != 0)
{
Expand Down
8 changes: 2 additions & 6 deletions src/coreclr/jit/emitriscv64.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,10 @@ bool emitInsIsLoadOrStore(instruction ins);
void emitDispInsName(
code_t code, const BYTE* addr, bool doffs, unsigned insOffset, const instrDesc* id, const insGroup* ig);
void emitDispInsInstrNum(const instrDesc* id) const;
bool emitDispBranch(unsigned opcode2,
const char* register1Name,
const char* register2Name,
const instrDesc* id,
const insGroup* ig) const;
bool emitDispBranch(unsigned opcode2, unsigned rs1, unsigned rs2, const instrDesc* id, const insGroup* ig) const;
void emitDispBranchOffset(const instrDesc* id, const insGroup* ig) const;
void emitDispBranchLabel(const instrDesc* id) const;
bool emitDispBranchInstrType(unsigned opcode2) const;
bool emitDispBranchInstrType(unsigned opcode2, bool is_zero_reg, bool& print_second_reg) const;
void emitDispIllegalInstruction(code_t instructionCode);

emitter::code_t emitInsCode(instruction ins /*, insFormat fmt*/) const;
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/instrsriscv64.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ INST(invalid, "INVALID", 0, BAD_CODE)
INST(nop, "nop", 0, 0x00000013)

//// R_R
INST(mov, "mov", 0, 0x00000013)
INST(mov, "mv", 0, 0x00000013)

////R_I
INST(lui, "lui", 0, 0x00000037)
Expand Down
Loading