void emitter::emitDispInsName()

in src/coreclr/jit/emitriscv64.cpp [3475:4460]


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;
    assert((opcode & 0x3) == 0x3);

    emitDispInsAddr(insAdr);
    emitDispInsOffs(insOffset, doffs);

    printf("      ");

    switch (opcode)
    {
        case 0x37: // LUI
        {
            const char* rd    = RegNames[(code >> 7) & 0x1f];
            int         imm20 = (code >> 12) & 0xfffff;
            if (imm20 & 0x80000)
            {
                imm20 |= 0xfff00000;
            }
            printf("lui            %s, %d\n", rd, imm20);
            return;
        }
        case 0x17: // AUIPC
        {
            const char* rd    = RegNames[(code >> 7) & 0x1f];
            int         imm20 = (code >> 12) & 0xfffff;
            if (imm20 & 0x80000)
            {
                imm20 |= 0xfff00000;
            }
            printf("auipc          %s, %d\n", rd, imm20);
            return;
        }
        case 0x13:
        {
            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 & 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
                    printLength = printf("slti");
                    break;
                case 0x3: // SLTIU
                    printLength = printf("sltiu");
                    break;
                case 0x4: // XORI
                    printLength = printf("xori");
                    isHex       = true;
                    break;
                case 0x5: // SRLI & SRAI
                {
                    static constexpr unsigned kLogicalShiftFunct6    = 0b000000;
                    static constexpr unsigned kArithmeticShiftFunct6 = 0b010000;

                    unsigned funct6         = (imm12 >> 6) & 0x3f;
                    bool     isLogicalShift = funct6 == kLogicalShiftFunct6;
                    if ((!isLogicalShift) && (funct6 != kArithmeticShiftFunct6))
                    {
                        return emitDispIllegalInstruction(code);
                    }
                    printLength = printf(isLogicalShift ? "srli" : "srai");
                    imm12 &= 0x3f; // 6BITS for SHAMT in RISCV64
                }
                break;
                case 0x6: // ORI
                    printLength = printf("ori");
                    imm12 &= 0xfff;
                    isHex = true;
                    break;
                case 0x7: // ANDI
                    printLength = printf("andi");
                    imm12 &= 0xfff;
                    isHex = true;
                    break;
                default:
                    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:
        {
            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;
            //}
            switch (opcode2)
            {
                case 0x0: // ADDIW & SEXT.W
                    if (imm12 == 0)
                    {
                        printf("sext.w         %s, %s\n", rd, rs1);
                    }
                    else
                    {
                        printf("addiw          %s, %s, %d\n", rd, rs1, imm12);
                    }
                    return;
                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
                {
                    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 if (funct7 == kArithmeticShiftFunct7)
                    {
                        printf("sraiw          %s, %s, %d\n", rd, rs1, imm12 & 0x1f); // 5BITS for SHAMT in RISCV64
                    }
                    else
                    {
                        emitDispIllegalInstruction(code);
                    }
                }
                    return;
                default:
                    return emitDispIllegalInstruction(code);
            }
        }
        case 0x33:
        {
            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];

            switch (opcode2)
            {
                case 0b0000000:
                    switch (opcode3)
                    {
                        case 0x0: // ADD
                            printf("add            %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
                            printf("srl            %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:
                            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;
                        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) & 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];

            switch (opcode2)
            {
                case 0b0000000:
                    switch (opcode3)
                    {
                        case 0x0: // ADDW
                            printf("addw           %s, %s, %s\n", rd, rs1, rs2);
                            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);
                            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:
                            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:
        {
            unsigned int opcode2 = (code >> 12) & 0x7;
            const char*  rs1     = RegNames[(code >> 15) & 0x1f];
            const char*  rs2     = RegNames[(code >> 20) & 0x1f];
            int          offset  = (((code >> 25) & 0x7f) << 5) | ((code >> 7) & 0x1f);
            if (offset & 0x800)
            {
                offset |= 0xfffff000;
            }

            switch (opcode2)
            {
                case 0: // SB
                    printf("sb             %s, %d(%s)\n", rs2, offset, rs1);
                    return;
                case 1: // SH
                    printf("sh             %s, %d(%s)\n", rs2, offset, rs1);
                    return;
                case 2: // SW
                    printf("sw             %s, %d(%s)\n", rs2, offset, rs1);
                    return;
                case 3: // SD
                    printf("sd             %s, %d(%s)\n", rs2, offset, rs1);
                    return;
                default:
                    printf("RISCV64 illegal instruction: 0x%08X\n", code);
                    return;
            }
        }
        case 0x63: // BRANCH
        {
            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)
            // {
            //     offset |= 0xfffff000;
            // }
            if (!emitDispBranch(opcode2, rs1, rs2, id, ig))
            {
                emitDispIllegalInstruction(code);
            }
            return;
        }
        case 0x03:
        {
            unsigned int opcode2 = (code >> 12) & 0x7;
            const char*  rs1     = RegNames[(code >> 15) & 0x1f];
            const char*  rd      = RegNames[(code >> 7) & 0x1f];
            int          offset  = ((code >> 20) & 0xfff);
            if (offset & 0x800)
            {
                offset |= 0xfffff000;
            }

            switch (opcode2)
            {
                case 0: // LB
                    printf("lb             %s, %d(%s)\n", rd, offset, rs1);
                    return;
                case 1: // LH
                    printf("lh             %s, %d(%s)\n", rd, offset, rs1);
                    return;
                case 2: // LW
                    printf("lw             %s, %d(%s)\n", rd, offset, rs1);
                    return;
                case 3: // LD
                    printf("ld             %s, %d(%s)\n", rd, offset, rs1);
                    return;
                case 4: // LBU
                    printf("lbu            %s, %d(%s)\n", rd, offset, rs1);
                    return;
                case 5: // LHU
                    printf("lhu            %s, %d(%s)\n", rd, offset, rs1);
                    return;
                case 6: // LWU
                    printf("lwu            %s, %d(%s)\n", rd, offset, rs1);
                    return;
                default:
                    printf("RISCV64 illegal instruction: 0x%08X\n", code);
                    return;
            }
        }
        case 0x67:
        {
            const char* rs1    = RegNames[(code >> 15) & 0x1f];
            const char* rd     = RegNames[(code >> 7) & 0x1f];
            int         offset = ((code >> 20) & 0xfff);
            if (offset & 0x800)
            {
                offset |= 0xfffff000;
            }
            printf("jalr           %s, %d(%s)", rd, offset, rs1);
            CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie;
            // Target for ret call is unclear, e.g.:
            //   jalr zero, 0(ra)
            // So, skip it
            if (handle != 0)
            {
                const char* methodName = emitComp->eeGetMethodFullName(handle);
                printf("\t\t// %s", methodName);
            }

            printf("\n");
            return;
        }
        case 0x6f:
        {
            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;
            }
            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)
            {
                const char* methodName = emitComp->eeGetMethodFullName(handle);
                printf("\t\t// %s", methodName);
            }

            printf("\n");
            return;
        }
        case 0x0f:
        {
            int pred = ((code) >> 24) & 0xf;
            int succ = ((code) >> 20) & 0xf;
            printf("fence          %d, %d\n", pred, succ);
            return;
        }
        case 0x73:
        {
            unsigned int opcode2 = (code >> 12) & 0x7;
            if (opcode2 != 0)
            {
                const char* rd      = RegNames[(code >> 7) & 0x1f];
                int         csrtype = (code >> 20);
                if (opcode2 <= 0x3)
                {
                    const char* rs1 = RegNames[(code >> 15) & 0x1f];
                    switch (opcode2)
                    {
                        case 0x1: // CSRRW
                            printf("csrrw           %s, %d, %s\n", rd, csrtype, rs1);
                            return;
                        case 0x2: // CSRRS
                            printf("csrrs           %s, %d, %s\n", rd, csrtype, rs1);
                            return;
                        case 0x3: // CSRRC
                            printf("csrrc           %s, %d, %s\n", rd, csrtype, rs1);
                            return;
                        default:
                            printf("RISCV64 illegal instruction: 0x%08X\n", code);
                            break;
                    }
                }
                else
                {
                    unsigned imm5 = ((code >> 15) & 0x1f);
                    switch (opcode2)
                    {
                        case 0x5: // CSRRWI
                            printf("csrrwi           %s, %d, %d\n", rd, csrtype, imm5);
                            return;
                        case 0x6: // CSRRSI
                            printf("csrrsi           %s, %d, %d\n", rd, csrtype, imm5);
                            return;
                        case 0x7: // CSRRCI
                            printf("csrrci           %s, %d, %d\n", rd, csrtype, imm5);
                            return;
                        default:
                            printf("RISCV64 illegal instruction: 0x%08X\n", code);
                            break;
                    }
                }
            }

            if (code == emitInsCode(INS_ebreak))
            {
                printf("ebreak\n");
            }
            else
            {
                NYI_RISCV64("illegal ins within emitDisInsName!");
            }
            return;
        }
        case 0x53:
        {
            unsigned int opcode2 = (code >> 25) & 0x7f;
            unsigned int opcode3 = (code >> 20) & 0x1f;
            unsigned int opcode4 = (code >> 12) & 0x7;
            const char*  fd      = RegNames[((code >> 7) & 0x1f) | 0x20];
            const char*  fs1     = RegNames[((code >> 15) & 0x1f) | 0x20];
            const char*  fs2     = RegNames[((code >> 20) & 0x1f) | 0x20];

            const char* xd  = RegNames[(code >> 7) & 0x1f];
            const char* xs1 = RegNames[(code >> 15) & 0x1f];
            const char* xs2 = RegNames[(code >> 20) & 0x1f];

            switch (opcode2)
            {
                case 0x00: // FADD.S
                    printf("fadd.s         %s, %s, %s\n", fd, fs1, fs2);
                    return;
                case 0x04: // FSUB.S
                    printf("fsub.s         %s, %s, %s\n", fd, fs1, fs2);
                    return;
                case 0x08: // FMUL.S
                    printf("fmul.s         %s, %s, %s\n", fd, fs1, fs2);
                    return;
                case 0x0C: // FDIV.S
                    printf("fdiv.s         %s, %s, %s\n", fd, fs1, fs2);
                    return;
                case 0x2C: // FSQRT.S
                    printf("fsqrt.s        %s, %s\n", fd, fs1);
                    return;
                case 0x10:            // FSGNJ.S & FSGNJN.S & FSGNJX.S
                    if (opcode4 == 0) // FSGNJ.S
                    {
                        printf("fsgnj.s        %s, %s, %s\n", fd, fs1, fs2);
                    }
                    else if (opcode4 == 1) // FSGNJN.S
                    {
                        printf("fsgnjn.s       %s, %s, %s\n", fd, fs1, fs2);
                    }
                    else if (opcode4 == 2) // FSGNJX.S
                    {
                        printf("fsgnjx.s       %s, %s, %s\n", fd, fs1, fs2);
                    }
                    else
                    {
                        NYI_RISCV64("illegal ins within emitDisInsName!");
                    }
                    return;
                case 0x14:            // FMIN.S & FMAX.S
                    if (opcode4 == 0) // FMIN.S
                    {
                        printf("fmin.s         %s, %s, %s\n", fd, fs1, fs2);
                    }
                    else if (opcode4 == 1) // FMAX.S
                    {
                        printf("fmax.s         %s, %s, %s\n", fd, fs1, fs2);
                    }
                    else
                    {
                        NYI_RISCV64("illegal ins within emitDisInsName!");
                    }
                    return;
                case 0x60:            // FCVT.W.S & FCVT.WU.S & FCVT.L.S & FCVT.LU.S
                    if (opcode3 == 0) // FCVT.W.S
                    {
                        printf("fcvt.w.s       %s, %s\n", xd, fs1);
                    }
                    else if (opcode3 == 1) // FCVT.WU.S
                    {
                        printf("fcvt.wu.s      %s, %s\n", xd, fs1);
                    }
                    else if (opcode3 == 2) // FCVT.L.S
                    {
                        printf("fcvt.l.s       %s, %s\n", xd, fs1);
                    }
                    else if (opcode3 == 3) // FCVT.LU.S
                    {
                        printf("fcvt.lu.s      %s, %s\n", xd, fs1);
                    }
                    else
                    {
                        NYI_RISCV64("illegal ins within emitDisInsName!");
                    }
                    return;
                case 0x70:            // FMV.X.W & FCLASS.S
                    if (opcode4 == 0) // FMV.X.W
                    {
                        printf("fmv.x.w        %s, %s\n", xd, fs1);
                    }
                    else if (opcode4 == 1) // FCLASS.S
                    {
                        printf("fclass.s       %s, %s\n", xd, fs1);
                    }
                    else
                    {
                        NYI_RISCV64("illegal ins within emitDisInsName!");
                    }
                    return;
                case 0x50:            // FLE.S & FLT.S & FEQ.S
                    if (opcode4 == 0) // FLE.S
                    {
                        printf("fle.s          %s, %s, %s\n", xd, fs1, fs2);
                    }
                    else if (opcode4 == 1) // FLT.S
                    {
                        printf("flt.s          %s, %s, %s\n", xd, fs1, fs2);
                    }
                    else if (opcode4 == 2) // FEQ.S
                    {
                        printf("feq.s          %s, %s, %s\n", xd, fs1, fs2);
                    }
                    else
                    {
                        NYI_RISCV64("illegal ins within emitDisInsName!");
                    }
                    return;
                case 0x68:            // FCVT.S.W & FCVT.S.WU & FCVT.S.L & FCVT.S.LU
                    if (opcode3 == 0) // FCVT.S.W
                    {
                        printf("fcvt.s.w       %s, %s\n", fd, xs1);
                    }
                    else if (opcode3 == 1) // FCVT.S.WU
                    {
                        printf("fcvt.s.wu      %s, %s\n", fd, xs1);
                    }
                    else if (opcode3 == 2) // FCVT.S.L
                    {
                        printf("fcvt.s.l       %s, %s\n", fd, xs1);
                    }
                    else if (opcode3 == 3) // FCVT.S.LU
                    {
                        printf("fcvt.s.lu      %s, %s\n", fd, xs1);
                    }

                    else
                    {
                        NYI_RISCV64("illegal ins within emitDisInsName!");
                    }
                    return;
                case 0x78: // FMV.W.X
                    printf("fmv.w.x        %s, %s\n", fd, xs1);
                    return;
                case 0x1: // FADD.D
                    printf("fadd.d         %s, %s, %s\n", fd, fs1, fs2);
                    return;
                case 0x5: // FSUB.D
                    printf("fsub.d         %s, %s, %s\n", fd, fs1, fs2);
                    return;
                case 0x9: // FMUL.D
                    printf("fmul.d         %s, %s, %s\n", fd, fs1, fs2);
                    return;
                case 0xd: // FDIV.D
                    printf("fdiv.d         %s, %s, %s\n", fd, fs1, fs2);
                    return;
                case 0x2d: // FSQRT.D
                    printf("fsqrt.d        %s, %s\n", fd, fs1);
                    return;
                case 0x11:            // FSGNJ.D & FSGNJN.D & FSGNJX.D
                    if (opcode4 == 0) // FSGNJ.D
                    {
                        printf("fsgnj.d        %s, %s, %s\n", fd, fs1, fs2);
                    }
                    else if (opcode4 == 1) // FSGNJN.D
                    {
                        printf("fsgnjn.d       %s, %s, %s\n", fd, fs1, fs2);
                    }
                    else if (opcode4 == 2) // FSGNJX.D
                    {
                        printf("fsgnjx.d       %s, %s, %s\n", fd, fs1, fs2);
                    }
                    else
                    {
                        NYI_RISCV64("illegal ins within emitDisInsName!");
                    }
                    return;
                case 0x15:            // FMIN.D & FMAX.D
                    if (opcode4 == 0) // FMIN.D
                    {
                        printf("fmin.d         %s, %s, %s\n", fd, fs1, fs2);
                    }
                    else if (opcode4 == 1) // FMAX.D
                    {
                        printf("fmax.d         %s, %s, %s\n", fd, fs1, fs2);
                    }
                    else
                    {
                        NYI_RISCV64("illegal ins within emitDisInsName!");
                    }
                    return;
                case 0x20:            // FCVT.S.D
                    if (opcode3 == 1) // FCVT.S.D
                    {
                        printf("fcvt.s.d       %s, %s\n", fd, fs1);
                    }
                    else
                    {
                        NYI_RISCV64("illegal ins within emitDisInsName!");
                    }
                    return;
                case 0x21:            // FCVT.D.S
                    if (opcode3 == 0) // FCVT.D.S
                    {
                        printf("fcvt.d.s       %s, %s\n", fd, fs1);
                    }
                    else
                    {
                        NYI_RISCV64("illegal ins within emitDisInsName!");
                    }
                    return;
                case 0x51:            // FLE.D & FLT.D & FEQ.D
                    if (opcode4 == 0) // FLE.D
                    {
                        printf("fle.d          %s, %s, %s\n", xd, fs1, fs2);
                    }
                    else if (opcode4 == 1) // FLT.D
                    {
                        printf("flt.d          %s, %s, %s\n", xd, fs1, fs2);
                    }
                    else if (opcode4 == 2) // FEQ.D
                    {
                        printf("feq.d          %s, %s, %s\n", xd, fs1, fs2);
                    }
                    else
                    {
                        NYI_RISCV64("illegal ins within emitDisInsName!");
                    }
                    return;
                case 0x61: // FCVT.W.D & FCVT.WU.D & FCVT.L.D & FCVT.LU.D

                    if (opcode3 == 0) // FCVT.W.D
                    {
                        printf("fcvt.w.d       %s, %s\n", xd, fs1);
                    }
                    else if (opcode3 == 1) // FCVT.WU.D
                    {
                        printf("fcvt.wu.d      %s, %s\n", xd, fs1);
                    }
                    else if (opcode3 == 2) // FCVT.L.D
                    {
                        printf("fcvt.l.d       %s, %s\n", xd, fs1);
                    }
                    else if (opcode3 == 3) // FCVT.LU.D
                    {
                        printf("fcvt.lu.d      %s, %s\n", xd, fs1);
                    }
                    else
                    {
                        NYI_RISCV64("illegal ins within emitDisInsName!");
                    }
                    return;
                case 0x69:            // FCVT.D.W & FCVT.D.WU & FCVT.D.L & FCVT.D.LU
                    if (opcode3 == 0) // FCVT.D.W
                    {
                        printf("fcvt.d.w       %s, %s\n", fd, xs1);
                    }
                    else if (opcode3 == 1) // FCVT.D.WU
                    {
                        printf("fcvt.d.wu      %s, %s\n", fd, xs1);
                    }
                    else if (opcode3 == 2)
                    {
                        printf("fcvt.d.l       %s, %s\n", fd, xs1);
                    }
                    else if (opcode3 == 3)
                    {
                        printf("fcvt.d.lu      %s, %s\n", fd, xs1);
                    }

                    else
                    {
                        NYI_RISCV64("illegal ins within emitDisInsName!");
                    }

                    return;
                case 0x71:            // FMV.X.D & FCLASS.D
                    if (opcode4 == 0) // FMV.X.D
                    {
                        printf("fmv.x.d        %s, %s\n", xd, fs1);
                    }
                    else if (opcode4 == 1) // FCLASS.D
                    {
                        printf("fclass.d       %s, %s\n", xd, fs1);
                    }
                    else
                    {
                        NYI_RISCV64("illegal ins within emitDisInsName!");
                    }
                    return;
                case 0x79: // FMV.D.X
                    assert(opcode4 == 0);
                    printf("fmv.d.x        %s, %s\n", fd, xs1);
                    return;
                default:
                    NYI_RISCV64("illegal ins within emitDisInsName!");
                    return;
            }
            return;
        }
        case 0x27:
        {
            unsigned int opcode2 = (code >> 12) & 0x7;

            const char* rs1    = RegNames[(code >> 15) & 0x1f];
            const char* rs2    = RegNames[((code >> 20) & 0x1f) | 0x20];
            int         offset = (((code >> 25) & 0x7f) << 5) | ((code >> 7) & 0x1f);
            if (offset & 0x800)
            {
                offset |= 0xfffff000;
            }
            if (opcode2 == 2) // FSW
            {
                printf("fsw            %s, %d(%s)\n", rs2, offset, rs1);
            }
            else if (opcode2 == 3) // FSD
            {
                printf("fsd            %s, %d(%s)\n", rs2, offset, rs1);
            }
            else
            {
                NYI_RISCV64("illegal ins within emitDisInsName!");
            }
            return;
        }
        case 0x7:
        {
            unsigned int opcode2 = (code >> 12) & 0x7;
            const char*  rs1     = RegNames[(code >> 15) & 0x1f];
            const char*  rd      = RegNames[((code >> 7) & 0x1f) | 0x20];
            int          offset  = ((code >> 20) & 0xfff);
            if (offset & 0x800)
            {
                offset |= 0xfffff000;
            }
            if (opcode2 == 2) // FLW
            {
                printf("flw            %s, %d(%s)\n", rd, offset, rs1);
            }
            else if (opcode2 == 3) // FLD
            {
                printf("fld            %s, %d(%s)\n", rd, offset, rs1);
            }
            else
            {
                NYI_RISCV64("illegal ins within emitDisInsName!");
            }
            return;
        }
        case 0x2f: // AMO - atomic memory operation
        {
            bool        hasDataReg = true;
            const char* name;
            switch (code >> 27) // funct5
            {
                case 0b00010:
                    name       = "lr";
                    hasDataReg = false;
                    break;
                case 0b00011:
                    name = "sc";
                    break;
                case 0b00001:
                    name = "amoswap";
                    break;
                case 0b00000:
                    name = "amoadd";
                    break;
                case 0b00100:
                    name = "amoxor";
                    break;
                case 0b01100:
                    name = "amoand";
                    break;
                case 0b01000:
                    name = "amoor";
                    break;
                case 0b10000:
                    name = "amomin";
                    break;
                case 0b10100:
                    name = "amomax";
                    break;
                case 0b11000:
                    name = "amominu";
                    break;
                case 0b11100:
                    name = "amomaxu";
                    break;
                default:
                    assert(!"Illegal funct5 within atomic memory operation, emitDisInsName");
                    name = "?";
            }

            char width;
            switch ((code >> 12) & 0x7) // funct3: width
            {
                case 0x2:
                    width = 'w';
                    break;
                case 0x3:
                    width = 'd';
                    break;
                default:
                    assert(!"Illegal width tag within atomic memory operation, emitDisInsName");
                    width = '?';
            }

            const char* aq = code & (1 << 25) ? "aq" : "";
            const char* rl = code & (1 << 26) ? "rl" : "";

            int len = printf("%s.%c.%s%s", name, width, aq, rl);
            if (len <= 0)
            {
                return;
            }
            static const int INS_LEN = 14;
            assert(len <= INS_LEN);

            const char* dest = RegNames[(code >> 7) & 0x1f];
            const char* addr = RegNames[(code >> 15) & 0x1f];

            int dataReg = (code >> 20) & 0x1f;
            if (hasDataReg)
            {
                const char* data = RegNames[dataReg];
                printf("%*s %s, %s, (%s)\n", INS_LEN - len, "", dest, data, addr);
            }
            else
            {
                assert(dataReg == REG_R0);
                printf("%*s %s, (%s)\n", INS_LEN - len, "", dest, addr);
            }
            return;
        }
        default:
            NO_WAY("illegal ins within emitDisInsName!");
    }

    NO_WAY("illegal ins within emitDisInsName!");
}