summaryrefslogtreecommitdiff
path: root/disassembler
diff options
context:
space:
mode:
Diffstat (limited to 'disassembler')
-rw-r--r--disassembler/disassembler_riscv64.cc33
1 files changed, 32 insertions, 1 deletions
diff --git a/disassembler/disassembler_riscv64.cc b/disassembler/disassembler_riscv64.cc
index cdb0390ce0..1dcf1a31cd 100644
--- a/disassembler/disassembler_riscv64.cc
+++ b/disassembler/disassembler_riscv64.cc
@@ -393,6 +393,19 @@ void DisassemblerRiscv64::Printer::Print32BinOpImm(uint32_t insn32) {
os_ << "zextb " << XRegName(rd) << ", " << XRegName(rs1);
} else if (!narrow && funct3 == /*SLTIU*/ 3u && imm == 1) {
os_ << "seqz " << XRegName(rd) << ", " << XRegName(rs1);
+ } else if ((insn32 & 0xfc00707fu) == 0x0800101bu) {
+ os_ << "slli.uw " << XRegName(rd) << ", " << XRegName(rs1) << ", " << (imm & 0x3fu);
+ } else if ((imm ^ 0x600u) < 3u && funct3 == 1u) {
+ static const char* const kBitOpcodes[] = { "clz", "ctz", "cpop" };
+ os_ << kBitOpcodes[imm ^ 0x600u] << (narrow ? "w " : " ")
+ << XRegName(rd) << ", " << XRegName(rs1);
+ } else if ((imm ^ 0x600u) < (narrow ? 32 : 64) && funct3 == 5u) {
+ os_ << "rori" << (narrow ? "w " : " ")
+ << XRegName(rd) << ", " << XRegName(rs1) << ", " << (imm ^ 0x600u);
+ } else if (imm == 0x287u && !narrow && funct3 == 5u) {
+ os_ << "orc.b " << XRegName(rd) << ", " << XRegName(rs1);
+ } else if (imm == 0x6b8u && !narrow && funct3 == 5u) {
+ os_ << "rev8 " << XRegName(rd) << ", " << XRegName(rs1);
} else {
bool bad_high_bits = false;
if (funct3 == /*SLLI*/ 1u || funct3 == /*SRLI/SRAI*/ 5u) {
@@ -439,16 +452,34 @@ void DisassemblerRiscv64::Printer::Print32BinOp(uint32_t insn32) {
os_ << "sgtz " << XRegName(rd) << ", " << XRegName(rs2);
} else if (!narrow && funct3 == /*SLTU*/ 3u && rs1 == Zero) {
os_ << "snez " << XRegName(rd) << ", " << XRegName(rs2);
+ } else if (narrow && high_bits == 0x08000000u && funct3 == /*ADD.UW*/ 0u && rs2 == Zero) {
+ os_ << "zext.w " << XRegName(rd) << ", " << XRegName(rs1);
} else {
bool bad_high_bits = false;
if (high_bits == 0x40000000u && (funct3 == /*SUB*/ 0u || funct3 == /*SRA*/ 5u)) {
os_ << ((funct3 == /*SUB*/ 0u) ? "sub" : "sra");
- } else if (high_bits == 0x02000000 &&
+ } else if (high_bits == 0x02000000u &&
(!narrow || (funct3 == /*MUL*/ 0u || funct3 >= /*DIV/DIVU/REM/REMU*/ 4u))) {
static const char* const kOpcodes[] = {
"mul", "mulh", "mulhsu", "mulhu", "div", "divu", "rem", "remu"
};
os_ << kOpcodes[funct3];
+ } else if (high_bits == 0x08000000u && narrow && funct3 == /*ADD.UW*/ 0u) {
+ os_ << "add.u"; // "w" is added below.
+ } else if (high_bits == 0x20000000u && (funct3 & 1u) == 0u && funct3 != 0u) {
+ static const char* const kZbaOpcodes[] = { nullptr, "sh1add", "sh2add", "sh3add" };
+ DCHECK(kZbaOpcodes[funct3 >> 1] != nullptr);
+ os_ << kZbaOpcodes[funct3 >> 1] << (narrow ? ".u" /* "w" is added below. */ : "");
+ } else if (high_bits == 0x40000000u && !narrow && funct3 >= 4u && funct3 != 5u) {
+ static const char* const kZbbNegOpcodes[] = { "xnor", nullptr, "orn", "andn" };
+ DCHECK(kZbbNegOpcodes[funct3 - 4u] != nullptr);
+ os_ << kZbbNegOpcodes[funct3 - 4u];
+ } else if (high_bits == 0x0a000000u && !narrow && funct3 >= 4u) {
+ static const char* const kZbbMinMaxOpcodes[] = { "min", "minu", "max", "maxu" };
+ DCHECK(kZbbMinMaxOpcodes[funct3 - 4u] != nullptr);
+ os_ << kZbbMinMaxOpcodes[funct3 - 4u];
+ } else if (high_bits == 0x60000000u && (funct3 == /*ROL*/ 1u || funct3 == /*ROL*/ 5u)) {
+ os_ << (funct3 == /*ROL*/ 1u ? "rol" : "ror");
} else if (!narrow || (funct3 == /*ADD*/ 0u || funct3 == /*SLL*/ 1u || funct3 == /*SRL*/ 5u)) {
static const char* const kOpcodes[] = {
"add", "sll", "slt", "sltu", "xor", "srl", "or", "and"