Index: lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp =================================================================== --- lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp +++ lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp @@ -497,13 +497,13 @@ // RVC (Compressed Instructions) // {"C_LWSP", 0xE003, 0x4002, DecodeC_LWSP}, - {"C_LDSP", 0xE003, 0x6002, DecodeC_LDSP}, + {"C_LDSP", 0xE003, 0x6002, DecodeC_LDSP, RV64 | RV128}, {"C_SWSP", 0xE003, 0xC002, DecodeC_SWSP}, - {"C_SDSP", 0xE003, 0xE002, DecodeC_SDSP}, + {"C_SDSP", 0xE003, 0xE002, DecodeC_SDSP, RV64 | RV128}, {"C_LW", 0xE003, 0x4000, DecodeC_LW}, - {"C_LD", 0xE003, 0x6000, DecodeC_LD}, + {"C_LD", 0xE003, 0x6000, DecodeC_LD, RV64 | RV128}, {"C_SW", 0xE003, 0xC000, DecodeC_SW}, - {"C_SD", 0xE003, 0xE000, DecodeC_SD}, + {"C_SD", 0xE003, 0xE000, DecodeC_SD, RV64 | RV128}, {"C_J", 0xE003, 0xA001, DecodeC_J}, {"C_JR", 0xF07F, 0x8002, DecodeC_JR}, {"C_JALR", 0xF07F, 0x9002, DecodeC_JALR}, @@ -512,11 +512,11 @@ {"C_LI", 0xE003, 0x4001, DecodeC_LI}, {"C_LUI_ADDI16SP", 0xE003, 0x6001, DecodeC_LUI_ADDI16SP}, {"C_ADDI", 0xE003, 0x1, DecodeC_ADDI}, - {"C_ADDIW", 0xE003, 0x2001, DecodeC_ADDIW}, + {"C_ADDIW", 0xE003, 0x2001, DecodeC_ADDIW, RV64 | RV128}, {"C_ADDI4SPN", 0xE003, 0x0, DecodeC_ADDI4SPN}, - {"C_SLLI", 0xE003, 0x2, DecodeC_SLLI}, - {"C_SRLI", 0xEC03, 0x8001, DecodeC_SRLI}, - {"C_SRAI", 0xEC03, 0x8401, DecodeC_SRAI}, + {"C_SLLI", 0xE003, 0x2, DecodeC_SLLI, RV64 | RV128}, + {"C_SRLI", 0xEC03, 0x8001, DecodeC_SRLI, RV64 | RV128}, + {"C_SRAI", 0xEC03, 0x8401, DecodeC_SRAI, RV64 | RV128}, {"C_ANDI", 0xEC03, 0x8801, DecodeC_ANDI}, {"C_MV", 0xF003, 0x8002, DecodeC_MV}, {"C_ADD", 0xF003, 0x9002, DecodeC_ADD}, @@ -524,8 +524,13 @@ {"C_OR", 0xFC63, 0x8C41, DecodeC_OR}, {"C_XOR", 0xFC63, 0x8C21, DecodeC_XOR}, {"C_SUB", 0xFC63, 0x8C01, DecodeC_SUB}, - {"C_SUBW", 0xFC63, 0x9C01, DecodeC_SUBW}, - {"C_ADDW", 0xFC63, 0x9C21, DecodeC_ADDW}, + {"C_SUBW", 0xFC63, 0x9C01, DecodeC_SUBW, RV64 | RV128}, + {"C_ADDW", 0xFC63, 0x9C21, DecodeC_ADDW, RV64 | RV128}, + // RV32FC // + {"FLW", 0xE003, 0x6000, DecodeC_FLW, RV32}, + {"FSW", 0xE003, 0xE000, DecodeC_FSW, RV32}, + {"FLWSP", 0xE003, 0x6002, DecodeC_FLWSP, RV32}, + {"FSWSP", 0xE003, 0xE002, DecodeC_FSWSP, RV32}, // RV32F (Extension for Single-Precision Floating-Point) // {"FLW", 0x707F, 0x2007, DecodeIType}, @@ -569,9 +574,16 @@ // check whether the compressed encode could be valid uint16_t mask = try_rvc & 0b11; bool is_rvc = try_rvc != 0 && mask != 3; + uint8_t inst_type = RV64; + + // if we have ArchSpec::eCore_riscv128 in the future, + // we also need to check it here + if (m_arch.GetCore() == ArchSpec::eCore_riscv32) + inst_type = RV32; for (const InstrPattern &pat : PATTERNS) { - if ((inst & pat.type_mask) == pat.eigen) { + if ((inst & pat.type_mask) == pat.eigen && + (inst_type & pat.inst_type) != 0) { LLDB_LOGF( log, "EmulateInstructionRISCV::%s: inst(%x at %lx) was decoded to %s", __FUNCTION__, inst, m_addr, pat.name); Index: lldb/source/Plugins/Instruction/RISCV/RISCVCInstructions.h =================================================================== --- lldb/source/Plugins/Instruction/RISCV/RISCVCInstructions.h +++ lldb/source/Plugins/Instruction/RISCV/RISCVCInstructions.h @@ -299,6 +299,33 @@ auto rd = DecodeCA_RD(inst); return ADDW{rd, rd, DecodeCA_RS2(inst)}; } +RISCVInst DecodeC_FLW(uint32_t inst) { + uint16_t offset = ((inst << 1) & 0x40) // imm[6] + | ((inst >> 7) & 0x38) // imm[5:3] + | ((inst >> 4) & 0x4); // imm[2] + return FLW{DecodeCL_RD(inst), DecodeCL_RS1(inst), uint32_t(offset)}; +} + +RISCVInst DecodeC_FSW(uint32_t inst) { + uint16_t offset = ((inst << 1) & 0x40) // imm[6] + | ((inst >> 7) & 0x38) // imm[5:3] + | ((inst >> 4) & 0x4); // imm[2] + return FSW{DecodeCS_RS1(inst), DecodeCS_RS2(inst), uint32_t(offset)}; +} + +RISCVInst DecodeC_FLWSP(uint32_t inst) { + auto rd = DecodeCI_RD(inst); + uint16_t offset = ((inst << 4) & 0xc0) // offset[7:6] + | ((inst >> 7) & 0x20) // offset[5] + | ((inst >> 2) & 0x1c); // offset[4:2] + return FLW{rd, Rs{gpr_sp_riscv}, uint32_t(offset)}; +} + +RISCVInst DecodeC_FSWSP(uint32_t inst) { + uint16_t offset = ((inst >> 1) & 0xc0) // offset[7:6] + | ((inst >> 7) & 0x3c); // offset[5:2] + return FSW{Rs{gpr_sp_riscv}, DecodeCSS_RS2(inst), uint32_t(offset)}; +} } // namespace lldb_private #endif // LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVCINSTRUCTION_H Index: lldb/source/Plugins/Instruction/RISCV/RISCVInstructions.h =================================================================== --- lldb/source/Plugins/Instruction/RISCV/RISCVInstructions.h +++ lldb/source/Plugins/Instruction/RISCV/RISCVInstructions.h @@ -236,6 +236,10 @@ FCVT_S_WU, FMV_W_X, FCVT_L_S, FCVT_LU_S, FCVT_S_L, FCVT_S_LU, INVALID, EBREAK, RESERVED, HINT, NOP>; +constexpr uint8_t RV32 = 1; +constexpr uint8_t RV64 = 2; +constexpr uint8_t RV128 = 4; + struct InstrPattern { const char *name; /// Bit mask to check the type of a instruction (B-Type, I-Type, J-Type, etc.) @@ -243,6 +247,8 @@ /// Characteristic value after bitwise-and with type_mask. uint32_t eigen; RISCVInst (*decode)(uint32_t inst); + /// If not specified, the inst will be supported by all RV versions. + uint8_t inst_type = RV32 | RV64 | RV128; }; struct DecodeResult { Index: lldb/unittests/Instruction/RISCV/TestRISCVEmulator.cpp =================================================================== --- lldb/unittests/Instruction/RISCV/TestRISCVEmulator.cpp +++ lldb/unittests/Instruction/RISCV/TestRISCVEmulator.cpp @@ -27,8 +27,8 @@ RegisterInfoPOSIX_riscv64::FPR fpr; uint8_t memory[1024] = {0}; - RISCVEmulatorTester() - : EmulateInstructionRISCV(ArchSpec("riscv64-unknown-linux-gnu")) { + RISCVEmulatorTester(std::string triple = "riscv64-unknown-linux-gnu") + : EmulateInstructionRISCV(ArchSpec(triple)) { EmulateInstruction::SetReadRegCallback(ReadRegisterCallback); EmulateInstruction::SetWriteRegCallback(WriteRegisterCallback); EmulateInstruction::SetReadMemCallback(ReadMemoryCallback); @@ -356,6 +356,26 @@ } } +class RISCVEmulatorTester32 : public RISCVEmulatorTester { +public: + RISCVEmulatorTester32() : RISCVEmulatorTester("riscv32-unknown-linux-gnu") {} +}; + +TEST_F(RISCVEmulatorTester32, TestCDecodeRV32) { + std::vector tests = { + {0x6002, FLW{Rd{0}, Rs{2}, 0}}, + {0xE006, FSW{Rs{2}, Rs{1}, 0}}, + {0x6000, FLW{Rd{8}, Rs{8}, 0}}, + {0xE000, FSW{Rs{8}, Rs{8}, 0}}, + }; + + for (auto i : tests) { + auto decode = this->Decode(i.inst); + ASSERT_TRUE(decode.has_value()); + ASSERT_TRUE(compareInst(decode->decoded, i.inst_type)); + } +} + // GEN_BRANCH_TEST(opcode, imm1, imm2, imm3): // It should branch for instruction `opcode imm1, imm2` // It should do nothing for instruction `opcode imm1, imm3`