Index: lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp =================================================================== --- lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp +++ lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp @@ -526,6 +526,11 @@ {"C_SUB", 0xFC63, 0x8C01, DecodeC_SUB}, {"C_SUBW", 0xFC63, 0x9C01, DecodeC_SUBW}, {"C_ADDW", 0xFC63, 0x9C21, DecodeC_ADDW}, + // 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,15 @@ // check whether the compressed encode could be valid uint16_t mask = try_rvc & 0b11; bool is_rvc = try_rvc != 0 && mask != 3; + RISCVInstrType 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) { 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,12 @@ FCVT_S_WU, FMV_W_X, FCVT_L_S, FCVT_LU_S, FCVT_S_L, FCVT_S_LU, INVALID, EBREAK, RESERVED, HINT, NOP>; +enum RISCVInstrType { + RV32, + RV64, + RV128, +}; + struct InstrPattern { const char *name; /// Bit mask to check the type of a instruction (B-Type, I-Type, J-Type, etc.) @@ -243,6 +249,8 @@ /// Characteristic value after bitwise-and with type_mask. uint32_t eigen; RISCVInst (*decode)(uint32_t inst); + /// We suppose the default of `inst_type` is RV64. + RISCVInstrType inst_type = RV64; }; 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`