xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.h (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
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