diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index f1451dc83ef2c..e72777a296e61 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -3347,15 +3347,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 +{ + 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 "); @@ -3407,17 +3421,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()) { @@ -3438,17 +3454,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. @@ -3470,6 +3475,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; @@ -3506,51 +3513,95 @@ 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(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 + { + static constexpr unsigned kSlliFunct6 = 0b000000; + + unsigned funct6 = (imm12 >> 6) & 0x3f; + // SLLI's instruction code's upper 6 bits have to be equal to zero + if (funct6 != kSlliFunct6) + { + 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 = 0b000000; + static constexpr unsigned kArithmeticShiftFunct6 = 0b010000; + + 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; + + printf("%*s %s, %s", paddingLength, "", RegNames[rd], RegNames[rs1]); + if (hasImmediate) + { + printf(isHex ? ", 0x%x" : ", %d", imm12); + } + printf("\n"); + + return; } case 0x1b: { @@ -3574,185 +3625,198 @@ void emitter::emitDispInsName( 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 + { + static constexpr unsigned kSlliwFunct7 = 0b0000000; + + unsigned funct7 = (imm12 >> 5) & 0x7f; + // SLLIW's instruction code's upper 7 bits have to be equal to zero + if (funct7 == kSlliwFunct7) + { + 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 = 0b0000000; + static constexpr unsigned kArithmeticShiftFunct7 = 0b0100000; + + 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: { - unsigned int opcode2 = (code >> 25) & 0x3; + unsigned int opcode2 = (code >> 25) & 0x7f; unsigned int opcode3 = (code >> 12) & 0x7; const char* rd = RegNames[(code >> 7) & 0x1f]; const char* rs1 = RegNames[(code >> 15) & 0x1f]; const char* rs2 = RegNames[(code >> 20) & 0x1f]; - if (opcode2 == 0) + + switch (opcode2) { - switch (opcode3) - { - case 0x0: // ADD & SUB - if (((code >> 30) & 0x1) == 0) - { + case 0b0000000: + switch (opcode3) + { + case 0x0: // ADD printf("add %s, %s, %s\n", rd, rs1, rs2); - } - else - { - printf("sub %s, %s, %s\n", rd, rs1, rs2); - } - return; - case 0x1: // SLL - printf("sll %s, %s, %s\n", rd, rs1, rs2); - return; - case 0x2: // SLT - printf("slt %s, %s, %s\n", rd, rs1, rs2); - return; - case 0x3: // SLTU - printf("sltu %s, %s, %s\n", rd, rs1, rs2); - return; - case 0x4: // XOR - printf("xor %s, %s, %s\n", rd, rs1, rs2); - return; - case 0x5: // SRL & SRA - if (((code >> 30) & 0x1) == 0) - { + return; + case 0x1: // SLL + printf("sll %s, %s, %s\n", rd, rs1, rs2); + return; + case 0x2: // SLT + printf("slt %s, %s, %s\n", rd, rs1, rs2); + return; + case 0x3: // SLTU + printf("sltu %s, %s, %s\n", rd, rs1, rs2); + return; + case 0x4: // XOR + printf("xor %s, %s, %s\n", rd, rs1, rs2); + return; + case 0x5: // SRL printf("srl %s, %s, %s\n", rd, rs1, rs2); - } - else - { + return; + case 0x6: // OR + printf("or %s, %s, %s\n", rd, rs1, rs2); + return; + case 0x7: // AND + printf("and %s, %s, %s\n", rd, rs1, rs2); + return; + default: + return emitDispIllegalInstruction(code); + } + return; + case 0b0100000: + switch (opcode3) + { + case 0x0: // SUB + printf("sub %s, %s, %s\n", rd, rs1, rs2); + return; + case 0x5: // SRA printf("sra %s, %s, %s\n", rd, rs1, rs2); - } - return; - case 0x6: // OR - printf("or %s, %s, %s\n", rd, rs1, rs2); - return; - case 0x7: // AND - printf("and %s, %s, %s\n", rd, rs1, rs2); - return; - default: - printf("RISCV64 illegal instruction: 0x%08X\n", code); - return; - } - } - else if (opcode2 == 0x1) - { - switch (opcode3) - { - case 0x0: // MUL - printf("mul %s, %s, %s\n", rd, rs1, rs2); - return; - case 0x1: // MULH - printf("mulh %s, %s, %s\n", rd, rs1, rs2); - return; - case 0x2: // MULHSU - printf("mulhsu %s, %s, %s\n", rd, rs1, rs2); - return; - case 0x3: // MULHU - printf("mulhu %s, %s, %s\n", rd, rs1, rs2); - return; - case 0x4: // DIV - printf("div %s, %s, %s\n", rd, rs1, rs2); - return; - case 0x5: // DIVU - printf("divu %s, %s, %s\n", rd, rs1, rs2); - return; - case 0x6: // REM - printf("rem %s, %s, %s\n", rd, rs1, rs2); - return; - case 0x7: // REMU - printf("remu %s, %s, %s\n", rd, rs1, rs2); - return; - default: - printf("RISCV64 illegal instruction: 0x%08X\n", code); - return; - } - } - else - { - printf("RISCV64 illegal instruction: 0x%08X\n", code); - return; + return; + default: + return emitDispIllegalInstruction(code); + } + return; + case 0b0000001: + switch (opcode3) + { + case 0x0: // MUL + printf("mul %s, %s, %s\n", rd, rs1, rs2); + return; + case 0x1: // MULH + printf("mulh %s, %s, %s\n", rd, rs1, rs2); + return; + case 0x2: // MULHSU + printf("mulhsu %s, %s, %s\n", rd, rs1, rs2); + return; + case 0x3: // MULHU + printf("mulhu %s, %s, %s\n", rd, rs1, rs2); + return; + case 0x4: // DIV + printf("div %s, %s, %s\n", rd, rs1, rs2); + return; + case 0x5: // DIVU + printf("divu %s, %s, %s\n", rd, rs1, rs2); + return; + case 0x6: // REM + printf("rem %s, %s, %s\n", rd, rs1, rs2); + return; + case 0x7: // REMU + printf("remu %s, %s, %s\n", rd, rs1, rs2); + return; + default: + return emitDispIllegalInstruction(code); + } + return; + default: + return emitDispIllegalInstruction(code); } } case 0x3b: { - unsigned int opcode2 = (code >> 25) & 0x3; + unsigned int opcode2 = (code >> 25) & 0x7f; unsigned int opcode3 = (code >> 12) & 0x7; const char* rd = RegNames[(code >> 7) & 0x1f]; const char* rs1 = RegNames[(code >> 15) & 0x1f]; const char* rs2 = RegNames[(code >> 20) & 0x1f]; - if (opcode2 == 0) + switch (opcode2) { - switch (opcode3) - { - case 0x0: // ADDW & SUBW - if (((code >> 30) & 0x1) == 0) - { + case 0b0000000: + switch (opcode3) + { + case 0x0: // ADDW printf("addw %s, %s, %s\n", rd, rs1, rs2); - } - else - { - printf("subw %s, %s, %s\n", rd, rs1, rs2); - } - return; - case 0x1: // SLLW - printf("sllw %s, %s, %s\n", rd, rs1, rs2); - return; - case 0x5: // SRLW & SRAW - if (((code >> 30) & 0x1) == 0) - { + return; + case 0x1: // SLLW + printf("sllw %s, %s, %s\n", rd, rs1, rs2); + return; + case 0x5: // SRLW printf("srlw %s, %s, %s\n", rd, rs1, rs2); - } - else - { + return; + default: + return emitDispIllegalInstruction(code); + } + return; + case 0b0100000: + switch (opcode3) + { + case 0x0: // SUBW + printf("subw %s, %s, %s\n", rd, rs1, rs2); + return; + case 0x5: // SRAW printf("sraw %s, %s, %s\n", rd, rs1, rs2); - } - return; - default: - printf("RISCV64 illegal instruction: 0x%08X\n", code); - return; - } - } - else if (opcode2 == 1) - { - switch (opcode3) - { - case 0x0: // MULW - printf("mulw %s, %s, %s\n", rd, rs1, rs2); - return; - case 0x4: // DIVW - printf("divw %s, %s, %s\n", rd, rs1, rs2); - return; - case 0x5: // DIVUW - printf("divuw %s, %s, %s\n", rd, rs1, rs2); - return; - case 0x6: // REMW - printf("remw %s, %s, %s\n", rd, rs1, rs2); - return; - case 0x7: // REMUW - printf("remuw %s, %s, %s\n", rd, rs1, rs2); - return; - default: - printf("RISCV64 illegal instruction: 0x%08X\n", code); - return; - } - } - else - { - printf("RISCV64 illegal instruction: 0x%08X\n", code); - return; + return; + default: + return emitDispIllegalInstruction(code); + } + return; + case 0b0000001: + switch (opcode3) + { + case 0x0: // MULW + printf("mulw %s, %s, %s\n", rd, rs1, rs2); + return; + case 0x4: // DIVW + printf("divw %s, %s, %s\n", rd, rs1, rs2); + return; + case 0x5: // DIVUW + printf("divuw %s, %s, %s\n", rd, rs1, rs2); + return; + case 0x6: // REMW + printf("remw %s, %s, %s\n", rd, rs1, rs2); + return; + case 0x7: // REMUW + printf("remuw %s, %s, %s\n", rd, rs1, rs2); + return; + default: + return emitDispIllegalInstruction(code); + } + return; + default: + return emitDispIllegalInstruction(code); } } case 0x23: @@ -3787,9 +3851,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) @@ -3866,14 +3930,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) { diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 5409c76233de9..6c73f3fe577fc 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -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; diff --git a/src/coreclr/jit/instrsriscv64.h b/src/coreclr/jit/instrsriscv64.h index 281dacaeec5dc..b1f690b3088b7 100644 --- a/src/coreclr/jit/instrsriscv64.h +++ b/src/coreclr/jit/instrsriscv64.h @@ -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) INST(sext_w, "sext.w", 0, 0x0000001b) ////R_I