diff --git a/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp b/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp --- a/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp +++ b/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp @@ -538,22 +538,28 @@ {"FSUB_S", 0xFE00007F, 0x8000053, DecodeRType}, {"FMUL_S", 0xFE00007F, 0x10000053, DecodeRType}, {"FDIV_S", 0xFE00007F, 0x18000053, DecodeRType}, - {"FSQRT_S", 0xFFF0007F, 0x58000053, DecodeRType}, + {"FSQRT_S", 0xFFF0007F, 0x58000053, DecodeIType}, {"FSGNJ_S", 0xFE00707F, 0x20000053, DecodeRType}, {"FSGNJN_S", 0xFE00707F, 0x20001053, DecodeRType}, {"FSGNJX_S", 0xFE00707F, 0x20002053, DecodeRType}, {"FMIN_S", 0xFE00707F, 0x28000053, DecodeRType}, {"FMAX_S", 0xFE00707F, 0x28001053, DecodeRType}, - {"FCVT_W_S", 0xFFF0007F, 0xC0000053, DecodeRType}, - {"FCVT_WU_S", 0xFFF0007F, 0xC0100053, DecodeRType}, - {"FMV_X_W", 0xFFF0707F, 0xE0000053, DecodeRType}, + {"FCVT_W_S", 0xFFF0007F, 0xC0000053, DecodeIType}, + {"FCVT_WU_S", 0xFFF0007F, 0xC0100053, DecodeIType}, + {"FMV_X_W", 0xFFF0707F, 0xE0000053, DecodeIType}, {"FEQ_S", 0xFE00707F, 0xA2002053, DecodeRType}, {"FLT_S", 0xFE00707F, 0xA2001053, DecodeRType}, {"FLE_S", 0xFE00707F, 0xA2000053, DecodeRType}, - {"FCLASS_S", 0xFFF0707F, 0xE0001053, DecodeRType}, - {"FCVT_S_W", 0xFFF0007F, 0xD0000053, DecodeRType}, - {"FCVT_S_WU", 0xFFF0007F, 0xD0100053, DecodeRType}, - {"FMV_W_X", 0xFFF0707F, 0xF0000053, DecodeRType}, + {"FCLASS_S", 0xFFF0707F, 0xE0001053, DecodeIType}, + {"FCVT_S_W", 0xFFF0007F, 0xD0000053, DecodeIType}, + {"FCVT_S_WU", 0xFFF0007F, 0xD0100053, DecodeIType}, + {"FMV_W_X", 0xFFF0707F, 0xF0000053, DecodeIType}, + + // RV64F (Extension for Single-Precision Floating-Point) // + {"FCVT_L_S", 0xFFF0007F, 0xC0200053, DecodeIType}, + {"FCVT_LU_S", 0xFFF0007F, 0xC0300053, DecodeIType}, + {"FCVT_S_L", 0xFFF0007F, 0xD0200053, DecodeIType}, + {"FCVT_S_LU", 0xFFF0007F, 0xD0300053, DecodeIType}, }; llvm::Optional EmulateInstructionRISCV::Decode(uint32_t inst) { @@ -1428,6 +1434,38 @@ }) .value_or(false); } + bool operator()(FCVT_L_S inst) { + return inst.rs1.ReadAPFloat(m_emu, false) + .transform([&](auto &&rs1) { + int64_t res = rs1.convertToFloat(); + return inst.rd.Write(m_emu, uint64_t(res)); + }) + .value_or(false); + } + bool operator()(FCVT_LU_S inst) { + return inst.rs1.ReadAPFloat(m_emu, false) + .transform([&](auto &&rs1) { + uint64_t res = rs1.convertToFloat(); + return inst.rd.Write(m_emu, res); + }) + .value_or(false); + } + bool operator()(FCVT_S_L inst) { + return inst.rs1.ReadI64(m_emu) + .transform([&](auto &&rs1) { + llvm::APFloat apf(llvm::APFloat::IEEEsingle(), rs1); + return inst.rd.WriteAPFloat(m_emu, apf); + }) + .value_or(false); + } + bool operator()(FCVT_S_LU inst) { + return inst.rs1.Read(m_emu) + .transform([&](auto &&rs1) { + llvm::APFloat apf(llvm::APFloat::IEEEsingle(), rs1); + return inst.rd.WriteAPFloat(m_emu, apf); + }) + .value_or(false); + } bool operator()(INVALID inst) { return false; } bool operator()(RESERVED inst) { return false; } bool operator()(EBREAK inst) { return false; } diff --git a/lldb/source/Plugins/Instruction/RISCV/RISCVInstructions.h b/lldb/source/Plugins/Instruction/RISCV/RISCVInstructions.h --- a/lldb/source/Plugins/Instruction/RISCV/RISCVInstructions.h +++ b/lldb/source/Plugins/Instruction/RISCV/RISCVInstructions.h @@ -192,22 +192,28 @@ R_TYPE_INST(FSUB_S); R_TYPE_INST(FMUL_S); R_TYPE_INST(FDIV_S); -R_TYPE_INST(FSQRT_S); +I_TYPE_INST(FSQRT_S); R_TYPE_INST(FSGNJ_S); R_TYPE_INST(FSGNJN_S); R_TYPE_INST(FSGNJX_S); R_TYPE_INST(FMIN_S); R_TYPE_INST(FMAX_S); -R_TYPE_INST(FCVT_W_S); -R_TYPE_INST(FCVT_WU_S); -R_TYPE_INST(FMV_X_W); +I_TYPE_INST(FCVT_W_S); +I_TYPE_INST(FCVT_WU_S); +I_TYPE_INST(FMV_X_W); R_TYPE_INST(FEQ_S); R_TYPE_INST(FLT_S); R_TYPE_INST(FLE_S); -R_TYPE_INST(FCLASS_S); -R_TYPE_INST(FCVT_S_W); -R_TYPE_INST(FCVT_S_WU); -R_TYPE_INST(FMV_W_X); +I_TYPE_INST(FCLASS_S); +I_TYPE_INST(FCVT_S_W); +I_TYPE_INST(FCVT_S_WU); +I_TYPE_INST(FMV_W_X); + +// RV64F inst (The standard single-precision floating-point extension) +I_TYPE_INST(FCVT_L_S); +I_TYPE_INST(FCVT_LU_S); +I_TYPE_INST(FCVT_S_L); +I_TYPE_INST(FCVT_S_LU); /// Invalid and reserved instructions, the `inst` fields are used for debugging. INVALID_INST(INVALID); @@ -227,7 +233,8 @@ AMOMAXU_D, FLW, FSW, FMADD_S, FMSUB_S, FNMADD_S, FNMSUB_S, FADD_S, FSUB_S, FMUL_S, FDIV_S, FSQRT_S, FSGNJ_S, FSGNJN_S, FSGNJX_S, FMIN_S, FMAX_S, FCVT_W_S, FCVT_WU_S, FMV_X_W, FEQ_S, FLT_S, FLE_S, FCLASS_S, FCVT_S_W, - FCVT_S_WU, FMV_W_X, INVALID, EBREAK, RESERVED, HINT, NOP>; + FCVT_S_WU, FMV_W_X, FCVT_L_S, FCVT_LU_S, FCVT_S_L, FCVT_S_LU, INVALID, + EBREAK, RESERVED, HINT, NOP>; struct InstrPattern { const char *name; diff --git a/lldb/unittests/Instruction/RISCV/TestRISCVEmulator.cpp b/lldb/unittests/Instruction/RISCV/TestRISCVEmulator.cpp --- a/lldb/unittests/Instruction/RISCV/TestRISCVEmulator.cpp +++ b/lldb/unittests/Instruction/RISCV/TestRISCVEmulator.cpp @@ -584,10 +584,10 @@ TEST_F(RISCVEmulatorTester, TestFCVTInst) { std::vector tests = { - {0xC001F253, "FCVT_W_S"}, - {0xC011F253, "FCVT_WU_S"}, - {0xD001F253, "FCVT_S_W"}, - {0xD011F253, "FCVT_S_WU"}, + {0xC001F253, "FCVT_W_S"}, {0xC011F253, "FCVT_WU_S"}, + {0xD001F253, "FCVT_S_W"}, {0xD011F253, "FCVT_S_WU"}, + {0xC021F253, "FCVT_L_S"}, {0xC031F253, "FCVT_LU_S"}, + {0xD021F253, "FCVT_S_L"}, {0xD031F253, "FCVT_S_LU"}, }; for (auto i : tests) { auto decode = this->Decode(i.inst);