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!");
}