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: GetPluginNameStatic()25 static llvm::StringRef GetPluginNameStatic() { return "riscv"; } 26 GetPluginDescriptionStatic()27 static llvm::StringRef GetPluginDescriptionStatic() { 28 return "Emulate instructions for the RISC-V architecture."; 29 } 30 SupportsThisInstructionType(InstructionType inst_type)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: EmulateInstructionRISCV(const ArchSpec & arch)53 EmulateInstructionRISCV(const ArchSpec &arch) : EmulateInstruction(arch) {} 54 GetPluginName()55 llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } 56 SupportsEmulatingInstructionsOfType(InstructionType inst_type)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; GetLastInstrSize()63 std::optional<uint32_t> GetLastInstrSize() override { return m_last_size; } 64 bool EvaluateInstruction(uint32_t options) override; 65 bool TestEmulation(Stream &out_stream, ArchSpec &arch, 66 OptionValueDictionary *test_data) override; 67 std::optional<RegisterInfo> GetRegisterInfo(lldb::RegisterKind reg_kind, 68 uint32_t reg_num) override; 69 70 std::optional<lldb::addr_t> ReadPC(); 71 bool WritePC(lldb::addr_t pc); 72 73 std::optional<DecodeResult> ReadInstructionAt(lldb::addr_t addr); 74 std::optional<DecodeResult> Decode(uint32_t inst); 75 bool Execute(DecodeResult inst, bool ignore_cond); 76 77 template <typename T> 78 std::enable_if_t<std::is_integral_v<T>, std::optional<T>> ReadMem(uint64_t addr)79 ReadMem(uint64_t addr) { 80 EmulateInstructionRISCV::Context ctx; 81 ctx.type = EmulateInstruction::eContextRegisterLoad; 82 ctx.SetNoArgs(); 83 bool success = false; 84 T result = ReadMemoryUnsigned(ctx, addr, sizeof(T), T(), &success); 85 if (!success) 86 return {}; // aka return false 87 return result; 88 } 89 WriteMem(uint64_t addr,uint64_t value)90 template <typename T> bool WriteMem(uint64_t addr, uint64_t value) { 91 EmulateInstructionRISCV::Context ctx; 92 ctx.type = EmulateInstruction::eContextRegisterStore; 93 ctx.SetNoArgs(); 94 return WriteMemoryUnsigned(ctx, addr, value, sizeof(T)); 95 } 96 97 llvm::RoundingMode GetRoundingMode(); 98 bool SetAccruedExceptions(llvm::APFloatBase::opStatus); 99 100 private: 101 /// Last decoded instruction from m_opcode 102 DecodeResult m_decoded; 103 /// Last decoded instruction size estimate. 104 std::optional<uint32_t> m_last_size; 105 }; 106 107 } // namespace lldb_private 108 109 #endif // LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_EMULATEINSTRUCTIONRISCV_H 110