1*f6aab3d8Srobert //===-- EmulateInstructionRISCV.h -----------------------------------------===// 2*f6aab3d8Srobert // 3*f6aab3d8Srobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*f6aab3d8Srobert // See https://llvm.org/LICENSE.txt for license information. 5*f6aab3d8Srobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*f6aab3d8Srobert // 7*f6aab3d8Srobert //===----------------------------------------------------------------------===// 8*f6aab3d8Srobert 9*f6aab3d8Srobert #ifndef LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_EMULATEINSTRUCTIONRISCV_H 10*f6aab3d8Srobert #define LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_EMULATEINSTRUCTIONRISCV_H 11*f6aab3d8Srobert 12*f6aab3d8Srobert #include "RISCVInstructions.h" 13*f6aab3d8Srobert 14*f6aab3d8Srobert #include "lldb/Core/EmulateInstruction.h" 15*f6aab3d8Srobert #include "lldb/Interpreter/OptionValue.h" 16*f6aab3d8Srobert #include "lldb/Utility/Log.h" 17*f6aab3d8Srobert #include "lldb/Utility/RegisterValue.h" 18*f6aab3d8Srobert #include "lldb/Utility/Status.h" 19*f6aab3d8Srobert #include <optional> 20*f6aab3d8Srobert 21*f6aab3d8Srobert namespace lldb_private { 22*f6aab3d8Srobert 23*f6aab3d8Srobert class EmulateInstructionRISCV : public EmulateInstruction { 24*f6aab3d8Srobert public: GetPluginNameStatic()25*f6aab3d8Srobert static llvm::StringRef GetPluginNameStatic() { return "riscv"; } 26*f6aab3d8Srobert GetPluginDescriptionStatic()27*f6aab3d8Srobert static llvm::StringRef GetPluginDescriptionStatic() { 28*f6aab3d8Srobert return "Emulate instructions for the RISC-V architecture."; 29*f6aab3d8Srobert } 30*f6aab3d8Srobert SupportsThisInstructionType(InstructionType inst_type)31*f6aab3d8Srobert static bool SupportsThisInstructionType(InstructionType inst_type) { 32*f6aab3d8Srobert switch (inst_type) { 33*f6aab3d8Srobert case eInstructionTypeAny: 34*f6aab3d8Srobert case eInstructionTypePCModifying: 35*f6aab3d8Srobert return true; 36*f6aab3d8Srobert case eInstructionTypePrologueEpilogue: 37*f6aab3d8Srobert case eInstructionTypeAll: 38*f6aab3d8Srobert return false; 39*f6aab3d8Srobert } 40*f6aab3d8Srobert llvm_unreachable("Fully covered switch above!"); 41*f6aab3d8Srobert } 42*f6aab3d8Srobert 43*f6aab3d8Srobert static bool SupportsThisArch(const ArchSpec &arch); 44*f6aab3d8Srobert 45*f6aab3d8Srobert static lldb_private::EmulateInstruction * 46*f6aab3d8Srobert CreateInstance(const lldb_private::ArchSpec &arch, InstructionType inst_type); 47*f6aab3d8Srobert 48*f6aab3d8Srobert static void Initialize(); 49*f6aab3d8Srobert 50*f6aab3d8Srobert static void Terminate(); 51*f6aab3d8Srobert 52*f6aab3d8Srobert public: EmulateInstructionRISCV(const ArchSpec & arch)53*f6aab3d8Srobert EmulateInstructionRISCV(const ArchSpec &arch) : EmulateInstruction(arch) {} 54*f6aab3d8Srobert GetPluginName()55*f6aab3d8Srobert llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } 56*f6aab3d8Srobert SupportsEmulatingInstructionsOfType(InstructionType inst_type)57*f6aab3d8Srobert bool SupportsEmulatingInstructionsOfType(InstructionType inst_type) override { 58*f6aab3d8Srobert return SupportsThisInstructionType(inst_type); 59*f6aab3d8Srobert } 60*f6aab3d8Srobert 61*f6aab3d8Srobert bool SetTargetTriple(const ArchSpec &arch) override; 62*f6aab3d8Srobert bool ReadInstruction() override; 63*f6aab3d8Srobert bool EvaluateInstruction(uint32_t options) override; 64*f6aab3d8Srobert bool TestEmulation(Stream *out_stream, ArchSpec &arch, 65*f6aab3d8Srobert OptionValueDictionary *test_data) override; 66*f6aab3d8Srobert std::optional<RegisterInfo> GetRegisterInfo(lldb::RegisterKind reg_kind, 67*f6aab3d8Srobert uint32_t reg_num) override; 68*f6aab3d8Srobert 69*f6aab3d8Srobert std::optional<lldb::addr_t> ReadPC(); 70*f6aab3d8Srobert bool WritePC(lldb::addr_t pc); 71*f6aab3d8Srobert 72*f6aab3d8Srobert std::optional<DecodeResult> ReadInstructionAt(lldb::addr_t addr); 73*f6aab3d8Srobert std::optional<DecodeResult> Decode(uint32_t inst); 74*f6aab3d8Srobert bool Execute(DecodeResult inst, bool ignore_cond); 75*f6aab3d8Srobert 76*f6aab3d8Srobert template <typename T> 77*f6aab3d8Srobert std::enable_if_t<std::is_integral_v<T>, std::optional<T>> ReadMem(uint64_t addr)78*f6aab3d8Srobert ReadMem(uint64_t addr) { 79*f6aab3d8Srobert EmulateInstructionRISCV::Context ctx; 80*f6aab3d8Srobert ctx.type = EmulateInstruction::eContextRegisterLoad; 81*f6aab3d8Srobert ctx.SetNoArgs(); 82*f6aab3d8Srobert bool success = false; 83*f6aab3d8Srobert T result = ReadMemoryUnsigned(ctx, addr, sizeof(T), T(), &success); 84*f6aab3d8Srobert if (!success) 85*f6aab3d8Srobert return {}; // aka return false 86*f6aab3d8Srobert return result; 87*f6aab3d8Srobert } 88*f6aab3d8Srobert WriteMem(uint64_t addr,uint64_t value)89*f6aab3d8Srobert template <typename T> bool WriteMem(uint64_t addr, uint64_t value) { 90*f6aab3d8Srobert EmulateInstructionRISCV::Context ctx; 91*f6aab3d8Srobert ctx.type = EmulateInstruction::eContextRegisterStore; 92*f6aab3d8Srobert ctx.SetNoArgs(); 93*f6aab3d8Srobert return WriteMemoryUnsigned(ctx, addr, value, sizeof(T)); 94*f6aab3d8Srobert } 95*f6aab3d8Srobert 96*f6aab3d8Srobert llvm::RoundingMode GetRoundingMode(); 97*f6aab3d8Srobert bool SetAccruedExceptions(llvm::APFloatBase::opStatus); 98*f6aab3d8Srobert 99*f6aab3d8Srobert private: 100*f6aab3d8Srobert /// Last decoded instruction from m_opcode 101*f6aab3d8Srobert DecodeResult m_decoded; 102*f6aab3d8Srobert }; 103*f6aab3d8Srobert 104*f6aab3d8Srobert } // namespace lldb_private 105*f6aab3d8Srobert 106*f6aab3d8Srobert #endif // LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_EMULATEINSTRUCTIONRISCV_H 107