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