LLDB  mainline
EmulateInstructionRISCV.cpp
Go to the documentation of this file.
1 //===-- EmulateInstructionRISCV.cpp ---------------------------------------===//
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 
12 #include "RISCVCInstructions.h"
13 #include "RISCVInstructions.h"
14 
15 #include "lldb/Core/Address.h"
19 #include "lldb/Symbol/UnwindPlan.h"
20 #include "lldb/Utility/ArchSpec.h"
21 #include "lldb/Utility/LLDBLog.h"
22 #include "lldb/Utility/Stream.h"
23 
24 #include "llvm/ADT/STLExtras.h"
25 #include "llvm/Support/MathExtras.h"
26 
27 using namespace lldb;
28 using namespace lldb_private;
29 
31 
32 namespace lldb_private {
33 
34 /// Returns all values wrapped in Optional, or std::nullopt if any of the values
35 /// is None.
36 template <typename... Ts>
37 static llvm::Optional<std::tuple<Ts...>> zipOpt(llvm::Optional<Ts> &&...ts) {
38  if ((ts.has_value() && ...))
39  return llvm::Optional<std::tuple<Ts...>>(
40  std::make_tuple(std::move(*ts)...));
41  else
42  return std::nullopt;
43 }
44 
45 // The funct3 is the type of compare in B<CMP> instructions.
46 // funct3 means "3-bits function selector", which RISC-V ISA uses as minor
47 // opcode. It reuses the major opcode encoding space.
48 constexpr uint32_t BEQ = 0b000;
49 constexpr uint32_t BNE = 0b001;
50 constexpr uint32_t BLT = 0b100;
51 constexpr uint32_t BGE = 0b101;
52 constexpr uint32_t BLTU = 0b110;
53 constexpr uint32_t BGEU = 0b111;
54 
55 // used in decoder
56 constexpr int32_t SignExt(uint32_t imm) { return int32_t(imm); }
57 
58 // used in executor
59 template <typename T>
60 constexpr std::enable_if_t<sizeof(T) <= 4, uint64_t> SextW(T value) {
61  return uint64_t(int64_t(int32_t(value)));
62 }
63 
64 // used in executor
65 template <typename T> constexpr uint64_t ZextD(T value) {
66  return uint64_t(value);
67 }
68 
69 constexpr uint32_t DecodeJImm(uint32_t inst) {
70  return (uint64_t(int64_t(int32_t(inst & 0x80000000)) >> 11)) // imm[20]
71  | (inst & 0xff000) // imm[19:12]
72  | ((inst >> 9) & 0x800) // imm[11]
73  | ((inst >> 20) & 0x7fe); // imm[10:1]
74 }
75 
76 constexpr uint32_t DecodeIImm(uint32_t inst) {
77  return int64_t(int32_t(inst)) >> 20; // imm[11:0]
78 }
79 
80 constexpr uint32_t DecodeBImm(uint32_t inst) {
81  return (uint64_t(int64_t(int32_t(inst & 0x80000000)) >> 19)) // imm[12]
82  | ((inst & 0x80) << 4) // imm[11]
83  | ((inst >> 20) & 0x7e0) // imm[10:5]
84  | ((inst >> 7) & 0x1e); // imm[4:1]
85 }
86 
87 constexpr uint32_t DecodeSImm(uint32_t inst) {
88  return (uint64_t(int64_t(int32_t(inst & 0xFE000000)) >> 20)) // imm[11:5]
89  | ((inst & 0xF80) >> 7); // imm[4:0]
90 }
91 
92 constexpr uint32_t DecodeUImm(uint32_t inst) {
93  return SextW(inst & 0xFFFFF000); // imm[31:12]
94 }
95 
96 static uint32_t GPREncodingToLLDB(uint32_t reg_encode) {
97  if (reg_encode == 0)
98  return gpr_x0_riscv;
99  if (reg_encode >= 1 && reg_encode <= 31)
100  return gpr_x1_riscv + reg_encode - 1;
101  return LLDB_INVALID_REGNUM;
102 }
103 
104 static uint32_t FPREncodingToLLDB(uint32_t reg_encode) {
105  if (reg_encode <= 31)
106  return fpr_f0_riscv + reg_encode;
107  return LLDB_INVALID_REGNUM;
108 }
109 
110 bool Rd::Write(EmulateInstructionRISCV &emulator, uint64_t value) {
111  uint32_t lldb_reg = GPREncodingToLLDB(rd);
113  ctx.type = EmulateInstruction::eContextRegisterStore;
114  ctx.SetNoArgs();
115  RegisterValue registerValue;
116  registerValue.SetUInt64(value);
117  return emulator.WriteRegister(ctx, eRegisterKindLLDB, lldb_reg,
118  registerValue);
119 }
120 
121 bool Rd::WriteAPFloat(EmulateInstructionRISCV &emulator, llvm::APFloat value) {
122  uint32_t lldb_reg = FPREncodingToLLDB(rd);
124  ctx.type = EmulateInstruction::eContextRegisterStore;
125  ctx.SetNoArgs();
126  RegisterValue registerValue;
127  registerValue.SetUInt64(value.bitcastToAPInt().getZExtValue());
128  return emulator.WriteRegister(ctx, eRegisterKindLLDB, lldb_reg,
129  registerValue);
130 }
131 
132 llvm::Optional<uint64_t> Rs::Read(EmulateInstructionRISCV &emulator) {
133  uint32_t lldbReg = GPREncodingToLLDB(rs);
134  RegisterValue value;
135  return emulator.ReadRegister(eRegisterKindLLDB, lldbReg, value)
136  ? llvm::Optional<uint64_t>(value.GetAsUInt64())
137  : std::nullopt;
138 }
139 
140 llvm::Optional<int32_t> Rs::ReadI32(EmulateInstructionRISCV &emulator) {
141  return Read(emulator).transform(
142  [](uint64_t value) { return int32_t(uint32_t(value)); });
143 }
144 
145 llvm::Optional<int64_t> Rs::ReadI64(EmulateInstructionRISCV &emulator) {
146  return Read(emulator).transform(
147  [](uint64_t value) { return int64_t(value); });
148 }
149 
150 llvm::Optional<uint32_t> Rs::ReadU32(EmulateInstructionRISCV &emulator) {
151  return Read(emulator).transform(
152  [](uint64_t value) { return uint32_t(value); });
153 }
154 
155 llvm::Optional<llvm::APFloat> Rs::ReadAPFloat(EmulateInstructionRISCV &emulator,
156  bool isDouble) {
157  uint32_t lldbReg = FPREncodingToLLDB(rs);
158  RegisterValue value;
159  if (!emulator.ReadRegister(eRegisterKindLLDB, lldbReg, value))
160  return std::nullopt;
161  uint64_t bits = value.GetAsUInt64();
162  llvm::APInt api(64, bits, false);
163  return llvm::APFloat(isDouble ? llvm::APFloat(api.bitsToDouble())
164  : llvm::APFloat(api.bitsToFloat()));
165 }
166 
167 static bool CompareB(uint64_t rs1, uint64_t rs2, uint32_t funct3) {
168  switch (funct3) {
169  case BEQ:
170  return rs1 == rs2;
171  case BNE:
172  return rs1 != rs2;
173  case BLT:
174  return int64_t(rs1) < int64_t(rs2);
175  case BGE:
176  return int64_t(rs1) >= int64_t(rs2);
177  case BLTU:
178  return rs1 < rs2;
179  case BGEU:
180  return rs1 >= rs2;
181  default:
182  llvm_unreachable("unexpected funct3");
183  }
184 }
185 
186 template <typename T>
187 constexpr bool is_load =
188  std::is_same_v<T, LB> || std::is_same_v<T, LH> || std::is_same_v<T, LW> ||
189  std::is_same_v<T, LD> || std::is_same_v<T, LBU> || std::is_same_v<T, LHU> ||
190  std::is_same_v<T, LWU>;
191 
192 template <typename T>
193 constexpr bool is_store = std::is_same_v<T, SB> || std::is_same_v<T, SH> ||
194  std::is_same_v<T, SW> || std::is_same_v<T, SD>;
195 
196 template <typename T>
197 constexpr bool is_amo_add =
198  std::is_same_v<T, AMOADD_W> || std::is_same_v<T, AMOADD_D>;
199 
200 template <typename T>
201 constexpr bool is_amo_bit_op =
202  std::is_same_v<T, AMOXOR_W> || std::is_same_v<T, AMOXOR_D> ||
203  std::is_same_v<T, AMOAND_W> || std::is_same_v<T, AMOAND_D> ||
204  std::is_same_v<T, AMOOR_W> || std::is_same_v<T, AMOOR_D>;
205 
206 template <typename T>
207 constexpr bool is_amo_swap =
208  std::is_same_v<T, AMOSWAP_W> || std::is_same_v<T, AMOSWAP_D>;
209 
210 template <typename T>
211 constexpr bool is_amo_cmp =
212  std::is_same_v<T, AMOMIN_W> || std::is_same_v<T, AMOMIN_D> ||
213  std::is_same_v<T, AMOMAX_W> || std::is_same_v<T, AMOMAX_D> ||
214  std::is_same_v<T, AMOMINU_W> || std::is_same_v<T, AMOMINU_D> ||
215  std::is_same_v<T, AMOMAXU_W> || std::is_same_v<T, AMOMAXU_D>;
216 
217 template <typename I>
218 static std::enable_if_t<is_load<I> || is_store<I>, llvm::Optional<uint64_t>>
220  return inst.rs1.Read(emulator).transform(
221  [&](uint64_t rs1) { return rs1 + uint64_t(SignExt(inst.imm)); });
222 }
223 
224 // Read T from memory, then load its sign-extended value m_emu to register.
225 template <typename I, typename T, typename E>
226 static std::enable_if_t<is_load<I>, bool>
227 Load(EmulateInstructionRISCV &emulator, I inst, uint64_t (*extend)(E)) {
228  auto addr = LoadStoreAddr(emulator, inst);
229  if (!addr)
230  return false;
231  return emulator.ReadMem<T>(*addr)
232  .transform([&](T t) { return inst.rd.Write(emulator, extend(E(t))); })
233  .value_or(false);
234 }
235 
236 template <typename I, typename T>
237 static std::enable_if_t<is_store<I>, bool>
238 Store(EmulateInstructionRISCV &emulator, I inst) {
239  auto addr = LoadStoreAddr(emulator, inst);
240  if (!addr)
241  return false;
242  return inst.rs2.Read(emulator)
243  .transform([&](uint64_t rs2) { return emulator.WriteMem<T>(*addr, rs2); })
244  .value_or(false);
245 }
246 
247 template <typename I>
248 static std::enable_if_t<is_amo_add<I> || is_amo_bit_op<I> || is_amo_swap<I> ||
249  is_amo_cmp<I>,
250  llvm::Optional<uint64_t>>
251 AtomicAddr(EmulateInstructionRISCV &emulator, I inst, unsigned int align) {
252  return inst.rs1.Read(emulator)
253  .transform([&](uint64_t rs1) {
254  return rs1 % align == 0 ? llvm::Optional<uint64_t>(rs1) : std::nullopt;
255  })
256  .value_or(std::nullopt);
257 }
258 
259 template <typename I, typename T>
260 static std::enable_if_t<is_amo_swap<I>, bool>
261 AtomicSwap(EmulateInstructionRISCV &emulator, I inst, int align,
262  uint64_t (*extend)(T)) {
263  auto addr = AtomicAddr(emulator, inst, align);
264  if (!addr)
265  return false;
266  return zipOpt(emulator.ReadMem<T>(*addr), inst.rs2.Read(emulator))
267  .transform([&](auto &&tup) {
268  auto [tmp, rs2] = tup;
269  return emulator.WriteMem<T>(*addr, T(rs2)) &&
270  inst.rd.Write(emulator, extend(tmp));
271  })
272  .value_or(false);
273 }
274 
275 template <typename I, typename T>
276 static std::enable_if_t<is_amo_add<I>, bool>
277 AtomicADD(EmulateInstructionRISCV &emulator, I inst, int align,
278  uint64_t (*extend)(T)) {
279  auto addr = AtomicAddr(emulator, inst, align);
280  if (!addr)
281  return false;
282  return zipOpt(emulator.ReadMem<T>(*addr), inst.rs2.Read(emulator))
283  .transform([&](auto &&tup) {
284  auto [tmp, rs2] = tup;
285  return emulator.WriteMem<T>(*addr, T(tmp + rs2)) &&
286  inst.rd.Write(emulator, extend(tmp));
287  })
288  .value_or(false);
289 }
290 
291 template <typename I, typename T>
292 static std::enable_if_t<is_amo_bit_op<I>, bool>
293 AtomicBitOperate(EmulateInstructionRISCV &emulator, I inst, int align,
294  uint64_t (*extend)(T), T (*operate)(T, T)) {
295  auto addr = AtomicAddr(emulator, inst, align);
296  if (!addr)
297  return false;
298  return zipOpt(emulator.ReadMem<T>(*addr), inst.rs2.Read(emulator))
299  .transform([&](auto &&tup) {
300  auto [value, rs2] = tup;
301  return emulator.WriteMem<T>(*addr, operate(value, T(rs2))) &&
302  inst.rd.Write(emulator, extend(value));
303  })
304  .value_or(false);
305 }
306 
307 template <typename I, typename T>
308 static std::enable_if_t<is_amo_cmp<I>, bool>
309 AtomicCmp(EmulateInstructionRISCV &emulator, I inst, int align,
310  uint64_t (*extend)(T), T (*cmp)(T, T)) {
311  auto addr = AtomicAddr(emulator, inst, align);
312  if (!addr)
313  return false;
314  return zipOpt(emulator.ReadMem<T>(*addr), inst.rs2.Read(emulator))
315  .transform([&](auto &&tup) {
316  auto [value, rs2] = tup;
317  return emulator.WriteMem<T>(*addr, cmp(value, T(rs2))) &&
318  inst.rd.Write(emulator, extend(value));
319  })
320  .value_or(false);
321 }
322 
324  // The atomic sequence is always 4 instructions long:
325  // example:
326  // 110cc: 100427af lr.w a5,(s0)
327  // 110d0: 00079663 bnez a5,110dc
328  // 110d4: 1ce426af sc.w.aq a3,a4,(s0)
329  // 110d8: fe069ae3 bnez a3,110cc
330  // 110dc: ........ <next instruction>
331  const auto pc = emulator.ReadPC();
332  if (!pc)
333  return false;
334  auto current_pc = pc.value();
335  const auto entry_pc = current_pc;
336 
337  // The first instruction should be LR.W or LR.D
338  auto inst = emulator.ReadInstructionAt(current_pc);
339  if (!inst || (!std::holds_alternative<LR_W>(inst->decoded) &&
340  !std::holds_alternative<LR_D>(inst->decoded)))
341  return false;
342 
343  // The second instruction should be BNE to exit address
344  inst = emulator.ReadInstructionAt(current_pc += 4);
345  if (!inst || !std::holds_alternative<B>(inst->decoded))
346  return false;
347  auto bne_exit = std::get<B>(inst->decoded);
348  if (bne_exit.funct3 != BNE)
349  return false;
350  // save the exit address to check later
351  const auto exit_pc = current_pc + SextW(bne_exit.imm);
352 
353  // The third instruction should be SC.W or SC.D
354  inst = emulator.ReadInstructionAt(current_pc += 4);
355  if (!inst || (!std::holds_alternative<SC_W>(inst->decoded) &&
356  !std::holds_alternative<SC_D>(inst->decoded)))
357  return false;
358 
359  // The fourth instruction should be BNE to entry address
360  inst = emulator.ReadInstructionAt(current_pc += 4);
361  if (!inst || !std::holds_alternative<B>(inst->decoded))
362  return false;
363  auto bne_start = std::get<B>(inst->decoded);
364  if (bne_start.funct3 != BNE)
365  return false;
366  if (entry_pc != current_pc + SextW(bne_start.imm))
367  return false;
368 
369  current_pc += 4;
370  // check the exit address and jump to it
371  return exit_pc == current_pc && emulator.WritePC(current_pc);
372 }
373 
374 template <typename T> static RISCVInst DecodeUType(uint32_t inst) {
375  return T{Rd{DecodeRD(inst)}, DecodeUImm(inst)};
376 }
377 
378 template <typename T> static RISCVInst DecodeJType(uint32_t inst) {
379  return T{Rd{DecodeRD(inst)}, DecodeJImm(inst)};
380 }
381 
382 template <typename T> static RISCVInst DecodeIType(uint32_t inst) {
383  return T{Rd{DecodeRD(inst)}, Rs{DecodeRS1(inst)}, DecodeIImm(inst)};
384 }
385 
386 template <typename T> static RISCVInst DecodeBType(uint32_t inst) {
387  return T{Rs{DecodeRS1(inst)}, Rs{DecodeRS2(inst)}, DecodeBImm(inst),
388  DecodeFunct3(inst)};
389 }
390 
391 template <typename T> static RISCVInst DecodeSType(uint32_t inst) {
392  return T{Rs{DecodeRS1(inst)}, Rs{DecodeRS2(inst)}, DecodeSImm(inst)};
393 }
394 
395 template <typename T> static RISCVInst DecodeRType(uint32_t inst) {
396  return T{Rd{DecodeRD(inst)}, Rs{DecodeRS1(inst)}, Rs{DecodeRS2(inst)}};
397 }
398 
399 template <typename T> static RISCVInst DecodeRShamtType(uint32_t inst) {
400  return T{Rd{DecodeRD(inst)}, Rs{DecodeRS1(inst)}, DecodeRS2(inst)};
401 }
402 
403 template <typename T> static RISCVInst DecodeRRS1Type(uint32_t inst) {
404  return T{Rd{DecodeRD(inst)}, Rs{DecodeRS1(inst)}};
405 }
406 
407 template <typename T> static RISCVInst DecodeR4Type(uint32_t inst) {
408  return T{Rd{DecodeRD(inst)}, Rs{DecodeRS1(inst)}, Rs{DecodeRS2(inst)},
409  Rs{DecodeRS3(inst)}, DecodeRM(inst)};
410 }
411 
412 static const InstrPattern PATTERNS[] = {
413  // RV32I & RV64I (The base integer ISA) //
414  {"LUI", 0x7F, 0x37, DecodeUType<LUI>},
415  {"AUIPC", 0x7F, 0x17, DecodeUType<AUIPC>},
416  {"JAL", 0x7F, 0x6F, DecodeJType<JAL>},
417  {"JALR", 0x707F, 0x67, DecodeIType<JALR>},
418  {"B", 0x7F, 0x63, DecodeBType<B>},
419  {"LB", 0x707F, 0x3, DecodeIType<LB>},
420  {"LH", 0x707F, 0x1003, DecodeIType<LH>},
421  {"LW", 0x707F, 0x2003, DecodeIType<LW>},
422  {"LBU", 0x707F, 0x4003, DecodeIType<LBU>},
423  {"LHU", 0x707F, 0x5003, DecodeIType<LHU>},
424  {"SB", 0x707F, 0x23, DecodeSType<SB>},
425  {"SH", 0x707F, 0x1023, DecodeSType<SH>},
426  {"SW", 0x707F, 0x2023, DecodeSType<SW>},
427  {"ADDI", 0x707F, 0x13, DecodeIType<ADDI>},
428  {"SLTI", 0x707F, 0x2013, DecodeIType<SLTI>},
429  {"SLTIU", 0x707F, 0x3013, DecodeIType<SLTIU>},
430  {"XORI", 0x707F, 0x4013, DecodeIType<XORI>},
431  {"ORI", 0x707F, 0x6013, DecodeIType<ORI>},
432  {"ANDI", 0x707F, 0x7013, DecodeIType<ANDI>},
433  {"SLLI", 0xF800707F, 0x1013, DecodeRShamtType<SLLI>},
434  {"SRLI", 0xF800707F, 0x5013, DecodeRShamtType<SRLI>},
435  {"SRAI", 0xF800707F, 0x40005013, DecodeRShamtType<SRAI>},
436  {"ADD", 0xFE00707F, 0x33, DecodeRType<ADD>},
437  {"SUB", 0xFE00707F, 0x40000033, DecodeRType<SUB>},
438  {"SLL", 0xFE00707F, 0x1033, DecodeRType<SLL>},
439  {"SLT", 0xFE00707F, 0x2033, DecodeRType<SLT>},
440  {"SLTU", 0xFE00707F, 0x3033, DecodeRType<SLTU>},
441  {"XOR", 0xFE00707F, 0x4033, DecodeRType<XOR>},
442  {"SRL", 0xFE00707F, 0x5033, DecodeRType<SRL>},
443  {"SRA", 0xFE00707F, 0x40005033, DecodeRType<SRA>},
444  {"OR", 0xFE00707F, 0x6033, DecodeRType<OR>},
445  {"AND", 0xFE00707F, 0x7033, DecodeRType<AND>},
446  {"LWU", 0x707F, 0x6003, DecodeIType<LWU>},
447  {"LD", 0x707F, 0x3003, DecodeIType<LD>},
448  {"SD", 0x707F, 0x3023, DecodeSType<SD>},
449  {"ADDIW", 0x707F, 0x1B, DecodeIType<ADDIW>},
450  {"SLLIW", 0xFE00707F, 0x101B, DecodeRShamtType<SLLIW>},
451  {"SRLIW", 0xFE00707F, 0x501B, DecodeRShamtType<SRLIW>},
452  {"SRAIW", 0xFE00707F, 0x4000501B, DecodeRShamtType<SRAIW>},
453  {"ADDW", 0xFE00707F, 0x3B, DecodeRType<ADDW>},
454  {"SUBW", 0xFE00707F, 0x4000003B, DecodeRType<SUBW>},
455  {"SLLW", 0xFE00707F, 0x103B, DecodeRType<SLLW>},
456  {"SRLW", 0xFE00707F, 0x503B, DecodeRType<SRLW>},
457  {"SRAW", 0xFE00707F, 0x4000503B, DecodeRType<SRAW>},
458 
459  // RV32M & RV64M (The integer multiplication and division extension) //
460  {"MUL", 0xFE00707F, 0x2000033, DecodeRType<MUL>},
461  {"MULH", 0xFE00707F, 0x2001033, DecodeRType<MULH>},
462  {"MULHSU", 0xFE00707F, 0x2002033, DecodeRType<MULHSU>},
463  {"MULHU", 0xFE00707F, 0x2003033, DecodeRType<MULHU>},
464  {"DIV", 0xFE00707F, 0x2004033, DecodeRType<DIV>},
465  {"DIVU", 0xFE00707F, 0x2005033, DecodeRType<DIVU>},
466  {"REM", 0xFE00707F, 0x2006033, DecodeRType<REM>},
467  {"REMU", 0xFE00707F, 0x2007033, DecodeRType<REMU>},
468  {"MULW", 0xFE00707F, 0x200003B, DecodeRType<MULW>},
469  {"DIVW", 0xFE00707F, 0x200403B, DecodeRType<DIVW>},
470  {"DIVUW", 0xFE00707F, 0x200503B, DecodeRType<DIVUW>},
471  {"REMW", 0xFE00707F, 0x200603B, DecodeRType<REMW>},
472  {"REMUW", 0xFE00707F, 0x200703B, DecodeRType<REMUW>},
473 
474  // RV32A & RV64A (The standard atomic instruction extension) //
475  {"LR_W", 0xF9F0707F, 0x1000202F, DecodeRRS1Type<LR_W>},
476  {"LR_D", 0xF9F0707F, 0x1000302F, DecodeRRS1Type<LR_D>},
477  {"SC_W", 0xF800707F, 0x1800202F, DecodeRType<SC_W>},
478  {"SC_D", 0xF800707F, 0x1800302F, DecodeRType<SC_D>},
479  {"AMOSWAP_W", 0xF800707F, 0x800202F, DecodeRType<AMOSWAP_W>},
480  {"AMOADD_W", 0xF800707F, 0x202F, DecodeRType<AMOADD_W>},
481  {"AMOXOR_W", 0xF800707F, 0x2000202F, DecodeRType<AMOXOR_W>},
482  {"AMOAND_W", 0xF800707F, 0x6000202F, DecodeRType<AMOAND_W>},
483  {"AMOOR_W", 0xF800707F, 0x4000202F, DecodeRType<AMOOR_W>},
484  {"AMOMIN_W", 0xF800707F, 0x8000202F, DecodeRType<AMOMIN_W>},
485  {"AMOMAX_W", 0xF800707F, 0xA000202F, DecodeRType<AMOMAX_W>},
486  {"AMOMINU_W", 0xF800707F, 0xC000202F, DecodeRType<AMOMINU_W>},
487  {"AMOMAXU_W", 0xF800707F, 0xE000202F, DecodeRType<AMOMAXU_W>},
488  {"AMOSWAP_D", 0xF800707F, 0x800302F, DecodeRType<AMOSWAP_D>},
489  {"AMOADD_D", 0xF800707F, 0x302F, DecodeRType<AMOADD_D>},
490  {"AMOXOR_D", 0xF800707F, 0x2000302F, DecodeRType<AMOXOR_D>},
491  {"AMOAND_D", 0xF800707F, 0x6000302F, DecodeRType<AMOAND_D>},
492  {"AMOOR_D", 0xF800707F, 0x4000302F, DecodeRType<AMOOR_D>},
493  {"AMOMIN_D", 0xF800707F, 0x8000302F, DecodeRType<AMOMIN_D>},
494  {"AMOMAX_D", 0xF800707F, 0xA000302F, DecodeRType<AMOMAX_D>},
495  {"AMOMINU_D", 0xF800707F, 0xC000302F, DecodeRType<AMOMINU_D>},
496  {"AMOMAXU_D", 0xF800707F, 0xE000302F, DecodeRType<AMOMAXU_D>},
497 
498  // RVC (Compressed Instructions) //
499  {"C_LWSP", 0xE003, 0x4002, DecodeC_LWSP},
500  {"C_LDSP", 0xE003, 0x6002, DecodeC_LDSP},
501  {"C_SWSP", 0xE003, 0xC002, DecodeC_SWSP},
502  {"C_SDSP", 0xE003, 0xE002, DecodeC_SDSP},
503  {"C_LW", 0xE003, 0x4000, DecodeC_LW},
504  {"C_LD", 0xE003, 0x6000, DecodeC_LD},
505  {"C_SW", 0xE003, 0xC000, DecodeC_SW},
506  {"C_SD", 0xE003, 0xE000, DecodeC_SD},
507  {"C_J", 0xE003, 0xA001, DecodeC_J},
508  {"C_JR", 0xF07F, 0x8002, DecodeC_JR},
509  {"C_JALR", 0xF07F, 0x9002, DecodeC_JALR},
510  {"C_BNEZ", 0xE003, 0xE001, DecodeC_BNEZ},
511  {"C_BEQZ", 0xE003, 0xC001, DecodeC_BEQZ},
512  {"C_LI", 0xE003, 0x4001, DecodeC_LI},
513  {"C_LUI_ADDI16SP", 0xE003, 0x6001, DecodeC_LUI_ADDI16SP},
514  {"C_ADDI", 0xE003, 0x1, DecodeC_ADDI},
515  {"C_ADDIW", 0xE003, 0x2001, DecodeC_ADDIW},
516  {"C_ADDI4SPN", 0xE003, 0x0, DecodeC_ADDI4SPN},
517  {"C_SLLI", 0xE003, 0x2, DecodeC_SLLI},
518  {"C_SRLI", 0xEC03, 0x8001, DecodeC_SRLI},
519  {"C_SRAI", 0xEC03, 0x8401, DecodeC_SRAI},
520  {"C_ANDI", 0xEC03, 0x8801, DecodeC_ANDI},
521  {"C_MV", 0xF003, 0x8002, DecodeC_MV},
522  {"C_ADD", 0xF003, 0x9002, DecodeC_ADD},
523  {"C_AND", 0xFC63, 0x8C61, DecodeC_AND},
524  {"C_OR", 0xFC63, 0x8C41, DecodeC_OR},
525  {"C_XOR", 0xFC63, 0x8C21, DecodeC_XOR},
526  {"C_SUB", 0xFC63, 0x8C01, DecodeC_SUB},
527  {"C_SUBW", 0xFC63, 0x9C01, DecodeC_SUBW},
528  {"C_ADDW", 0xFC63, 0x9C21, DecodeC_ADDW},
529 
530  // RV32F (Extension for Single-Precision Floating-Point) //
531  {"FLW", 0x707F, 0x2007, DecodeIType<FLW>},
532  {"FSW", 0x707F, 0x2027, DecodeSType<FSW>},
533  {"FMADD_S", 0x600007F, 0x43, DecodeR4Type<FMADD_S>},
534  {"FMSUB_S", 0x600007F, 0x47, DecodeR4Type<FMSUB_S>},
535  {"FNMSUB_S", 0x600007F, 0x4B, DecodeR4Type<FNMSUB_S>},
536  {"FNMADD_S", 0x600007F, 0x4F, DecodeR4Type<FNMADD_S>},
537  {"FADD_S", 0xFE00007F, 0x53, DecodeRType<FADD_S>},
538  {"FSUB_S", 0xFE00007F, 0x8000053, DecodeRType<FSUB_S>},
539  {"FMUL_S", 0xFE00007F, 0x10000053, DecodeRType<FMUL_S>},
540  {"FDIV_S", 0xFE00007F, 0x18000053, DecodeRType<FDIV_S>},
541  {"FSQRT_S", 0xFFF0007F, 0x58000053, DecodeIType<FSQRT_S>},
542  {"FSGNJ_S", 0xFE00707F, 0x20000053, DecodeRType<FSGNJ_S>},
543  {"FSGNJN_S", 0xFE00707F, 0x20001053, DecodeRType<FSGNJN_S>},
544  {"FSGNJX_S", 0xFE00707F, 0x20002053, DecodeRType<FSGNJX_S>},
545  {"FMIN_S", 0xFE00707F, 0x28000053, DecodeRType<FMIN_S>},
546  {"FMAX_S", 0xFE00707F, 0x28001053, DecodeRType<FMAX_S>},
547  {"FCVT_W_S", 0xFFF0007F, 0xC0000053, DecodeIType<FCVT_W_S>},
548  {"FCVT_WU_S", 0xFFF0007F, 0xC0100053, DecodeIType<FCVT_WU_S>},
549  {"FMV_X_W", 0xFFF0707F, 0xE0000053, DecodeIType<FMV_X_W>},
550  {"FEQ_S", 0xFE00707F, 0xA2002053, DecodeRType<FEQ_S>},
551  {"FLT_S", 0xFE00707F, 0xA2001053, DecodeRType<FLT_S>},
552  {"FLE_S", 0xFE00707F, 0xA2000053, DecodeRType<FLE_S>},
553  {"FCLASS_S", 0xFFF0707F, 0xE0001053, DecodeIType<FCLASS_S>},
554  {"FCVT_S_W", 0xFFF0007F, 0xD0000053, DecodeIType<FCVT_S_W>},
555  {"FCVT_S_WU", 0xFFF0007F, 0xD0100053, DecodeIType<FCVT_S_WU>},
556  {"FMV_W_X", 0xFFF0707F, 0xF0000053, DecodeIType<FMV_W_X>},
557 
558  // RV64F (Extension for Single-Precision Floating-Point) //
559  {"FCVT_L_S", 0xFFF0007F, 0xC0200053, DecodeIType<FCVT_L_S>},
560  {"FCVT_LU_S", 0xFFF0007F, 0xC0300053, DecodeIType<FCVT_LU_S>},
561  {"FCVT_S_L", 0xFFF0007F, 0xD0200053, DecodeIType<FCVT_S_L>},
562  {"FCVT_S_LU", 0xFFF0007F, 0xD0300053, DecodeIType<FCVT_S_LU>},
563 };
564 
565 llvm::Optional<DecodeResult> EmulateInstructionRISCV::Decode(uint32_t inst) {
566  Log *log = GetLog(LLDBLog::Unwind);
567 
568  uint16_t try_rvc = uint16_t(inst & 0x0000ffff);
569  // check whether the compressed encode could be valid
570  uint16_t mask = try_rvc & 0b11;
571  bool is_rvc = try_rvc != 0 && mask != 3;
572 
573  for (const InstrPattern &pat : PATTERNS) {
574  if ((inst & pat.type_mask) == pat.eigen) {
575  LLDB_LOGF(
576  log, "EmulateInstructionRISCV::%s: inst(%x at %lx) was decoded to %s",
577  __FUNCTION__, inst, m_addr, pat.name);
578  auto decoded = is_rvc ? pat.decode(try_rvc) : pat.decode(inst);
579  return DecodeResult{decoded, inst, is_rvc, pat};
580  }
581  }
582  LLDB_LOGF(log, "EmulateInstructionRISCV::%s: inst(0x%x) was unsupported",
583  __FUNCTION__, inst);
584  return std::nullopt;
585 }
586 
587 class Executor {
590  bool m_is_rvc;
591 
592 public:
593  // also used in EvaluateInstruction()
594  static uint64_t size(bool is_rvc) { return is_rvc ? 2 : 4; }
595 
596 private:
597  uint64_t delta() { return size(m_is_rvc); }
598 
599 public:
600  Executor(EmulateInstructionRISCV &emulator, bool ignoreCond, bool is_rvc)
601  : m_emu(emulator), m_ignore_cond(ignoreCond), m_is_rvc(is_rvc) {}
602 
603  bool operator()(LUI inst) { return inst.rd.Write(m_emu, SignExt(inst.imm)); }
604  bool operator()(AUIPC inst) {
605  return m_emu.ReadPC()
606  .transform([&](uint64_t pc) {
607  return inst.rd.Write(m_emu, SignExt(inst.imm) + pc);
608  })
609  .value_or(false);
610  }
611  bool operator()(JAL inst) {
612  return m_emu.ReadPC()
613  .transform([&](uint64_t pc) {
614  return inst.rd.Write(m_emu, pc + delta()) &&
615  m_emu.WritePC(SignExt(inst.imm) + pc);
616  })
617  .value_or(false);
618  }
619  bool operator()(JALR inst) {
620  return zipOpt(m_emu.ReadPC(), inst.rs1.Read(m_emu))
621  .transform([&](auto &&tup) {
622  auto [pc, rs1] = tup;
623  return inst.rd.Write(m_emu, pc + delta()) &&
624  m_emu.WritePC((SignExt(inst.imm) + rs1) & ~1);
625  })
626  .value_or(false);
627  }
628  bool operator()(B inst) {
629  return zipOpt(m_emu.ReadPC(), inst.rs1.Read(m_emu), inst.rs2.Read(m_emu))
630  .transform([&](auto &&tup) {
631  auto [pc, rs1, rs2] = tup;
632  if (m_ignore_cond || CompareB(rs1, rs2, inst.funct3))
633  return m_emu.WritePC(SignExt(inst.imm) + pc);
634  return true;
635  })
636  .value_or(false);
637  }
638  bool operator()(LB inst) {
639  return Load<LB, uint8_t, int8_t>(m_emu, inst, SextW);
640  }
641  bool operator()(LH inst) {
642  return Load<LH, uint16_t, int16_t>(m_emu, inst, SextW);
643  }
644  bool operator()(LW inst) {
645  return Load<LW, uint32_t, int32_t>(m_emu, inst, SextW);
646  }
647  bool operator()(LBU inst) {
648  return Load<LBU, uint8_t, uint8_t>(m_emu, inst, ZextD);
649  }
650  bool operator()(LHU inst) {
651  return Load<LHU, uint16_t, uint16_t>(m_emu, inst, ZextD);
652  }
653  bool operator()(SB inst) { return Store<SB, uint8_t>(m_emu, inst); }
654  bool operator()(SH inst) { return Store<SH, uint16_t>(m_emu, inst); }
655  bool operator()(SW inst) { return Store<SW, uint32_t>(m_emu, inst); }
656  bool operator()(ADDI inst) {
657  return inst.rs1.ReadI64(m_emu)
658  .transform([&](int64_t rs1) {
659  return inst.rd.Write(m_emu, rs1 + int64_t(SignExt(inst.imm)));
660  })
661  .value_or(false);
662  }
663  bool operator()(SLTI inst) {
664  return inst.rs1.ReadI64(m_emu)
665  .transform([&](int64_t rs1) {
666  return inst.rd.Write(m_emu, rs1 < int64_t(SignExt(inst.imm)));
667  })
668  .value_or(false);
669  }
670  bool operator()(SLTIU inst) {
671  return inst.rs1.Read(m_emu)
672  .transform([&](uint64_t rs1) {
673  return inst.rd.Write(m_emu, rs1 < uint64_t(SignExt(inst.imm)));
674  })
675  .value_or(false);
676  }
677  bool operator()(XORI inst) {
678  return inst.rs1.Read(m_emu)
679  .transform([&](uint64_t rs1) {
680  return inst.rd.Write(m_emu, rs1 ^ uint64_t(SignExt(inst.imm)));
681  })
682  .value_or(false);
683  }
684  bool operator()(ORI inst) {
685  return inst.rs1.Read(m_emu)
686  .transform([&](uint64_t rs1) {
687  return inst.rd.Write(m_emu, rs1 | uint64_t(SignExt(inst.imm)));
688  })
689  .value_or(false);
690  }
691  bool operator()(ANDI inst) {
692  return inst.rs1.Read(m_emu)
693  .transform([&](uint64_t rs1) {
694  return inst.rd.Write(m_emu, rs1 & uint64_t(SignExt(inst.imm)));
695  })
696  .value_or(false);
697  }
698  bool operator()(ADD inst) {
699  return zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu))
700  .transform([&](auto &&tup) {
701  auto [rs1, rs2] = tup;
702  return inst.rd.Write(m_emu, rs1 + rs2);
703  })
704  .value_or(false);
705  }
706  bool operator()(SUB inst) {
707  return zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu))
708  .transform([&](auto &&tup) {
709  auto [rs1, rs2] = tup;
710  return inst.rd.Write(m_emu, rs1 - rs2);
711  })
712  .value_or(false);
713  }
714  bool operator()(SLL inst) {
715  return zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu))
716  .transform([&](auto &&tup) {
717  auto [rs1, rs2] = tup;
718  return inst.rd.Write(m_emu, rs1 << (rs2 & 0b111111));
719  })
720  .value_or(false);
721  }
722  bool operator()(SLT inst) {
723  return zipOpt(inst.rs1.ReadI64(m_emu), inst.rs2.ReadI64(m_emu))
724  .transform([&](auto &&tup) {
725  auto [rs1, rs2] = tup;
726  return inst.rd.Write(m_emu, rs1 < rs2);
727  })
728  .value_or(false);
729  }
730  bool operator()(SLTU inst) {
731  return zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu))
732  .transform([&](auto &&tup) {
733  auto [rs1, rs2] = tup;
734  return inst.rd.Write(m_emu, rs1 < rs2);
735  })
736  .value_or(false);
737  }
738  bool operator()(XOR inst) {
739  return zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu))
740  .transform([&](auto &&tup) {
741  auto [rs1, rs2] = tup;
742  return inst.rd.Write(m_emu, rs1 ^ rs2);
743  })
744  .value_or(false);
745  }
746  bool operator()(SRL inst) {
747  return zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu))
748  .transform([&](auto &&tup) {
749  auto [rs1, rs2] = tup;
750  return inst.rd.Write(m_emu, rs1 >> (rs2 & 0b111111));
751  })
752  .value_or(false);
753  }
754  bool operator()(SRA inst) {
755  return zipOpt(inst.rs1.ReadI64(m_emu), inst.rs2.Read(m_emu))
756  .transform([&](auto &&tup) {
757  auto [rs1, rs2] = tup;
758  return inst.rd.Write(m_emu, rs1 >> (rs2 & 0b111111));
759  })
760  .value_or(false);
761  }
762  bool operator()(OR inst) {
763  return zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu))
764  .transform([&](auto &&tup) {
765  auto [rs1, rs2] = tup;
766  return inst.rd.Write(m_emu, rs1 | rs2);
767  })
768  .value_or(false);
769  }
770  bool operator()(AND inst) {
771  return zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu))
772  .transform([&](auto &&tup) {
773  auto [rs1, rs2] = tup;
774  return inst.rd.Write(m_emu, rs1 & rs2);
775  })
776  .value_or(false);
777  }
778  bool operator()(LWU inst) {
779  return Load<LWU, uint32_t, uint32_t>(m_emu, inst, ZextD);
780  }
781  bool operator()(LD inst) {
782  return Load<LD, uint64_t, uint64_t>(m_emu, inst, ZextD);
783  }
784  bool operator()(SD inst) { return Store<SD, uint64_t>(m_emu, inst); }
785  bool operator()(SLLI inst) {
786  return inst.rs1.Read(m_emu)
787  .transform([&](uint64_t rs1) {
788  return inst.rd.Write(m_emu, rs1 << inst.shamt);
789  })
790  .value_or(false);
791  }
792  bool operator()(SRLI inst) {
793  return inst.rs1.Read(m_emu)
794  .transform([&](uint64_t rs1) {
795  return inst.rd.Write(m_emu, rs1 >> inst.shamt);
796  })
797  .value_or(false);
798  }
799  bool operator()(SRAI inst) {
800  return inst.rs1.ReadI64(m_emu)
801  .transform([&](int64_t rs1) {
802  return inst.rd.Write(m_emu, rs1 >> inst.shamt);
803  })
804  .value_or(false);
805  }
806  bool operator()(ADDIW inst) {
807  return inst.rs1.ReadI32(m_emu)
808  .transform([&](int32_t rs1) {
809  return inst.rd.Write(m_emu, SextW(rs1 + SignExt(inst.imm)));
810  })
811  .value_or(false);
812  }
813  bool operator()(SLLIW inst) {
814  return inst.rs1.ReadU32(m_emu)
815  .transform([&](uint32_t rs1) {
816  return inst.rd.Write(m_emu, SextW(rs1 << inst.shamt));
817  })
818  .value_or(false);
819  }
820  bool operator()(SRLIW inst) {
821  return inst.rs1.ReadU32(m_emu)
822  .transform([&](uint32_t rs1) {
823  return inst.rd.Write(m_emu, SextW(rs1 >> inst.shamt));
824  })
825  .value_or(false);
826  }
827  bool operator()(SRAIW inst) {
828  return inst.rs1.ReadI32(m_emu)
829  .transform([&](int32_t rs1) {
830  return inst.rd.Write(m_emu, SextW(rs1 >> inst.shamt));
831  })
832  .value_or(false);
833  }
834  bool operator()(ADDW inst) {
835  return zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu))
836  .transform([&](auto &&tup) {
837  auto [rs1, rs2] = tup;
838  return inst.rd.Write(m_emu, SextW(uint32_t(rs1 + rs2)));
839  })
840  .value_or(false);
841  }
842  bool operator()(SUBW inst) {
843  return zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu))
844  .transform([&](auto &&tup) {
845  auto [rs1, rs2] = tup;
846  return inst.rd.Write(m_emu, SextW(uint32_t(rs1 - rs2)));
847  })
848  .value_or(false);
849  }
850  bool operator()(SLLW inst) {
851  return zipOpt(inst.rs1.ReadU32(m_emu), inst.rs2.ReadU32(m_emu))
852  .transform([&](auto &&tup) {
853  auto [rs1, rs2] = tup;
854  return inst.rd.Write(m_emu, SextW(rs1 << (rs2 & 0b11111)));
855  })
856  .value_or(false);
857  }
858  bool operator()(SRLW inst) {
859  return zipOpt(inst.rs1.ReadU32(m_emu), inst.rs2.ReadU32(m_emu))
860  .transform([&](auto &&tup) {
861  auto [rs1, rs2] = tup;
862  return inst.rd.Write(m_emu, SextW(rs1 >> (rs2 & 0b11111)));
863  })
864  .value_or(false);
865  }
866  bool operator()(SRAW inst) {
867  return zipOpt(inst.rs1.ReadI32(m_emu), inst.rs2.Read(m_emu))
868  .transform([&](auto &&tup) {
869  auto [rs1, rs2] = tup;
870  return inst.rd.Write(m_emu, SextW(rs1 >> (rs2 & 0b11111)));
871  })
872  .value_or(false);
873  }
874  // RV32M & RV64M (Integer Multiplication and Division Extension) //
875  bool operator()(MUL inst) {
876  return zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu))
877  .transform([&](auto &&tup) {
878  auto [rs1, rs2] = tup;
879  return inst.rd.Write(m_emu, rs1 * rs2);
880  })
881  .value_or(false);
882  }
883  bool operator()(MULH inst) {
884  return zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu))
885  .transform([&](auto &&tup) {
886  auto [rs1, rs2] = tup;
887  // signed * signed
888  auto mul = llvm::APInt(128, rs1, true) * llvm::APInt(128, rs2, true);
889  return inst.rd.Write(m_emu, mul.ashr(64).trunc(64).getZExtValue());
890  })
891  .value_or(false);
892  }
893  bool operator()(MULHSU inst) {
894  return zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu))
895  .transform([&](auto &&tup) {
896  auto [rs1, rs2] = tup;
897  // signed * unsigned
898  auto mul = llvm::APInt(128, rs1, true).zext(128) *
899  llvm::APInt(128, rs2, false);
900  return inst.rd.Write(m_emu, mul.lshr(64).trunc(64).getZExtValue());
901  })
902  .value_or(false);
903  }
904  bool operator()(MULHU inst) {
905  return zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu))
906  .transform([&](auto &&tup) {
907  auto [rs1, rs2] = tup;
908  // unsigned * unsigned
909  auto mul =
910  llvm::APInt(128, rs1, false) * llvm::APInt(128, rs2, false);
911  return inst.rd.Write(m_emu, mul.lshr(64).trunc(64).getZExtValue());
912  })
913  .value_or(false);
914  }
915  bool operator()(DIV inst) {
916  return zipOpt(inst.rs1.ReadI64(m_emu), inst.rs2.ReadI64(m_emu))
917  .transform([&](auto &&tup) {
918  auto [dividend, divisor] = tup;
919 
920  if (divisor == 0)
921  return inst.rd.Write(m_emu, UINT64_MAX);
922 
923  if (dividend == INT64_MIN && divisor == -1)
924  return inst.rd.Write(m_emu, dividend);
925 
926  return inst.rd.Write(m_emu, dividend / divisor);
927  })
928  .value_or(false);
929  }
930  bool operator()(DIVU inst) {
931  return zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu))
932  .transform([&](auto &&tup) {
933  auto [dividend, divisor] = tup;
934 
935  if (divisor == 0)
936  return inst.rd.Write(m_emu, UINT64_MAX);
937 
938  return inst.rd.Write(m_emu, dividend / divisor);
939  })
940  .value_or(false);
941  }
942  bool operator()(REM inst) {
943  return zipOpt(inst.rs1.ReadI64(m_emu), inst.rs2.ReadI64(m_emu))
944  .transform([&](auto &&tup) {
945  auto [dividend, divisor] = tup;
946 
947  if (divisor == 0)
948  return inst.rd.Write(m_emu, dividend);
949 
950  if (dividend == INT64_MIN && divisor == -1)
951  return inst.rd.Write(m_emu, 0);
952 
953  return inst.rd.Write(m_emu, dividend % divisor);
954  })
955  .value_or(false);
956  }
957  bool operator()(REMU inst) {
958  return zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu))
959  .transform([&](auto &&tup) {
960  auto [dividend, divisor] = tup;
961 
962  if (divisor == 0)
963  return inst.rd.Write(m_emu, dividend);
964 
965  return inst.rd.Write(m_emu, dividend % divisor);
966  })
967  .value_or(false);
968  }
969  bool operator()(MULW inst) {
970  return zipOpt(inst.rs1.ReadI32(m_emu), inst.rs2.ReadI32(m_emu))
971  .transform([&](auto &&tup) {
972  auto [rs1, rs2] = tup;
973  return inst.rd.Write(m_emu, SextW(rs1 * rs2));
974  })
975  .value_or(false);
976  }
977  bool operator()(DIVW inst) {
978  return zipOpt(inst.rs1.ReadI32(m_emu), inst.rs2.ReadI32(m_emu))
979  .transform([&](auto &&tup) {
980  auto [dividend, divisor] = tup;
981 
982  if (divisor == 0)
983  return inst.rd.Write(m_emu, UINT64_MAX);
984 
985  if (dividend == INT32_MIN && divisor == -1)
986  return inst.rd.Write(m_emu, SextW(dividend));
987 
988  return inst.rd.Write(m_emu, SextW(dividend / divisor));
989  })
990  .value_or(false);
991  }
992  bool operator()(DIVUW inst) {
993  return zipOpt(inst.rs1.ReadU32(m_emu), inst.rs2.ReadU32(m_emu))
994  .transform([&](auto &&tup) {
995  auto [dividend, divisor] = tup;
996 
997  if (divisor == 0)
998  return inst.rd.Write(m_emu, UINT64_MAX);
999 
1000  return inst.rd.Write(m_emu, SextW(dividend / divisor));
1001  })
1002  .value_or(false);
1003  }
1004  bool operator()(REMW inst) {
1005  return zipOpt(inst.rs1.ReadI32(m_emu), inst.rs2.ReadI32(m_emu))
1006  .transform([&](auto &&tup) {
1007  auto [dividend, divisor] = tup;
1008 
1009  if (divisor == 0)
1010  return inst.rd.Write(m_emu, SextW(dividend));
1011 
1012  if (dividend == INT32_MIN && divisor == -1)
1013  return inst.rd.Write(m_emu, 0);
1014 
1015  return inst.rd.Write(m_emu, SextW(dividend % divisor));
1016  })
1017  .value_or(false);
1018  }
1019  bool operator()(REMUW inst) {
1020  return zipOpt(inst.rs1.ReadU32(m_emu), inst.rs2.ReadU32(m_emu))
1021  .transform([&](auto &&tup) {
1022  auto [dividend, divisor] = tup;
1023 
1024  if (divisor == 0)
1025  return inst.rd.Write(m_emu, SextW(dividend));
1026 
1027  return inst.rd.Write(m_emu, SextW(dividend % divisor));
1028  })
1029  .value_or(false);
1030  }
1031  // RV32A & RV64A (The standard atomic instruction extension) //
1032  bool operator()(LR_W) { return AtomicSequence(m_emu); }
1033  bool operator()(LR_D) { return AtomicSequence(m_emu); }
1034  bool operator()(SC_W) {
1035  llvm_unreachable("should be handled in AtomicSequence");
1036  }
1037  bool operator()(SC_D) {
1038  llvm_unreachable("should be handled in AtomicSequence");
1039  }
1040  bool operator()(AMOSWAP_W inst) {
1041  return AtomicSwap<AMOSWAP_W, uint32_t>(m_emu, inst, 4, SextW);
1042  }
1043  bool operator()(AMOADD_W inst) {
1044  return AtomicADD<AMOADD_W, uint32_t>(m_emu, inst, 4, SextW);
1045  }
1046  bool operator()(AMOXOR_W inst) {
1047  return AtomicBitOperate<AMOXOR_W, uint32_t>(
1048  m_emu, inst, 4, SextW, [](uint32_t a, uint32_t b) { return a ^ b; });
1049  }
1050  bool operator()(AMOAND_W inst) {
1051  return AtomicBitOperate<AMOAND_W, uint32_t>(
1052  m_emu, inst, 4, SextW, [](uint32_t a, uint32_t b) { return a & b; });
1053  }
1054  bool operator()(AMOOR_W inst) {
1055  return AtomicBitOperate<AMOOR_W, uint32_t>(
1056  m_emu, inst, 4, SextW, [](uint32_t a, uint32_t b) { return a | b; });
1057  }
1058  bool operator()(AMOMIN_W inst) {
1059  return AtomicCmp<AMOMIN_W, uint32_t>(
1060  m_emu, inst, 4, SextW, [](uint32_t a, uint32_t b) {
1061  return uint32_t(std::min(int32_t(a), int32_t(b)));
1062  });
1063  }
1064  bool operator()(AMOMAX_W inst) {
1065  return AtomicCmp<AMOMAX_W, uint32_t>(
1066  m_emu, inst, 4, SextW, [](uint32_t a, uint32_t b) {
1067  return uint32_t(std::max(int32_t(a), int32_t(b)));
1068  });
1069  }
1070  bool operator()(AMOMINU_W inst) {
1071  return AtomicCmp<AMOMINU_W, uint32_t>(
1072  m_emu, inst, 4, SextW,
1073  [](uint32_t a, uint32_t b) { return std::min(a, b); });
1074  }
1075  bool operator()(AMOMAXU_W inst) {
1076  return AtomicCmp<AMOMAXU_W, uint32_t>(
1077  m_emu, inst, 4, SextW,
1078  [](uint32_t a, uint32_t b) { return std::max(a, b); });
1079  }
1080  bool operator()(AMOSWAP_D inst) {
1081  return AtomicSwap<AMOSWAP_D, uint64_t>(m_emu, inst, 8, ZextD);
1082  }
1083  bool operator()(AMOADD_D inst) {
1084  return AtomicADD<AMOADD_D, uint64_t>(m_emu, inst, 8, ZextD);
1085  }
1086  bool operator()(AMOXOR_D inst) {
1087  return AtomicBitOperate<AMOXOR_D, uint64_t>(
1088  m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) { return a ^ b; });
1089  }
1090  bool operator()(AMOAND_D inst) {
1091  return AtomicBitOperate<AMOAND_D, uint64_t>(
1092  m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) { return a & b; });
1093  }
1094  bool operator()(AMOOR_D inst) {
1095  return AtomicBitOperate<AMOOR_D, uint64_t>(
1096  m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) { return a | b; });
1097  }
1098  bool operator()(AMOMIN_D inst) {
1099  return AtomicCmp<AMOMIN_D, uint64_t>(
1100  m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) {
1101  return uint64_t(std::min(int64_t(a), int64_t(b)));
1102  });
1103  }
1104  bool operator()(AMOMAX_D inst) {
1105  return AtomicCmp<AMOMAX_D, uint64_t>(
1106  m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) {
1107  return uint64_t(std::max(int64_t(a), int64_t(b)));
1108  });
1109  }
1110  bool operator()(AMOMINU_D inst) {
1111  return AtomicCmp<AMOMINU_D, uint64_t>(
1112  m_emu, inst, 8, ZextD,
1113  [](uint64_t a, uint64_t b) { return std::min(a, b); });
1114  }
1115  bool operator()(AMOMAXU_D inst) {
1116  return AtomicCmp<AMOMAXU_D, uint64_t>(
1117  m_emu, inst, 8, ZextD,
1118  [](uint64_t a, uint64_t b) { return std::max(a, b); });
1119  }
1120  bool operator()(FLW inst) {
1121  return inst.rs1.Read(m_emu)
1122  .transform([&](auto &&rs1) {
1123  uint64_t addr = rs1 + uint64_t(inst.imm);
1124  uint64_t bits = m_emu.ReadMem<uint64_t>(addr).value();
1125  llvm::APFloat f(llvm::APFloat::IEEEsingle(), llvm::APInt(32, bits));
1126  return inst.rd.WriteAPFloat(m_emu, f);
1127  })
1128  .value_or(false);
1129  }
1130  bool operator()(FSW inst) {
1131  return zipOpt(inst.rs1.Read(m_emu), inst.rs2.ReadAPFloat(m_emu, false))
1132  .transform([&](auto &&tup) {
1133  auto [rs1, rs2] = tup;
1134  uint64_t addr = rs1 + uint64_t(inst.imm);
1135  uint64_t bits = rs2.bitcastToAPInt().getZExtValue();
1136  return m_emu.WriteMem<uint64_t>(addr, bits);
1137  })
1138  .value_or(false);
1139  }
1140  bool operator()(FMADD_S inst) {
1141  return zipOpt(inst.rs1.ReadAPFloat(m_emu, false),
1142  inst.rs2.ReadAPFloat(m_emu, false),
1143  inst.rs3.ReadAPFloat(m_emu, false))
1144  .transform([&](auto &&tup) {
1145  auto [rs1, rs2, rs3] = tup;
1146  auto res = rs1.fusedMultiplyAdd(rs2, rs3, m_emu.GetRoundingMode());
1147  inst.rd.WriteAPFloat(m_emu, rs1);
1148  return m_emu.SetAccruedExceptions(res);
1149  })
1150  .value_or(false);
1151  }
1152  bool operator()(FMSUB_S inst) {
1153  return zipOpt(inst.rs1.ReadAPFloat(m_emu, false),
1154  inst.rs2.ReadAPFloat(m_emu, false),
1155  inst.rs3.ReadAPFloat(m_emu, false))
1156  .transform([&](auto &&tup) {
1157  auto [rs1, rs2, rs3] = tup;
1158  auto res = rs1.fusedMultiplyAdd(rs2, -rs3, m_emu.GetRoundingMode());
1159  inst.rd.WriteAPFloat(m_emu, rs1);
1160  return m_emu.SetAccruedExceptions(res);
1161  })
1162  .value_or(false);
1163  }
1164  bool operator()(FNMSUB_S inst) {
1165  return zipOpt(inst.rs1.ReadAPFloat(m_emu, false),
1166  inst.rs2.ReadAPFloat(m_emu, false),
1167  inst.rs3.ReadAPFloat(m_emu, false))
1168  .transform([&](auto &&tup) {
1169  auto [rs1, rs2, rs3] = tup;
1170  auto res = rs1.fusedMultiplyAdd(-rs2, rs3, m_emu.GetRoundingMode());
1171  inst.rd.WriteAPFloat(m_emu, rs1);
1172  return m_emu.SetAccruedExceptions(res);
1173  })
1174  .value_or(false);
1175  }
1176  bool operator()(FNMADD_S inst) {
1177  return zipOpt(inst.rs1.ReadAPFloat(m_emu, false),
1178  inst.rs2.ReadAPFloat(m_emu, false),
1179  inst.rs3.ReadAPFloat(m_emu, false))
1180  .transform([&](auto &&tup) {
1181  auto [rs1, rs2, rs3] = tup;
1182  auto res = rs1.fusedMultiplyAdd(-rs2, -rs3, m_emu.GetRoundingMode());
1183  inst.rd.WriteAPFloat(m_emu, rs1);
1184  return m_emu.SetAccruedExceptions(res);
1185  })
1186  .value_or(false);
1187  }
1188  bool operator()(FADD_S inst) {
1189  return zipOpt(inst.rs1.ReadAPFloat(m_emu, false),
1190  inst.rs2.ReadAPFloat(m_emu, false))
1191  .transform([&](auto &&tup) {
1192  auto [rs1, rs2] = tup;
1193  auto res = rs1.add(rs2, m_emu.GetRoundingMode());
1194  inst.rd.WriteAPFloat(m_emu, rs1);
1195  return m_emu.SetAccruedExceptions(res);
1196  })
1197  .value_or(false);
1198  }
1199  bool operator()(FSUB_S inst) {
1200  return zipOpt(inst.rs1.ReadAPFloat(m_emu, false),
1201  inst.rs2.ReadAPFloat(m_emu, false))
1202  .transform([&](auto &&tup) {
1203  auto [rs1, rs2] = tup;
1204  auto res = rs1.subtract(rs2, m_emu.GetRoundingMode());
1205  inst.rd.WriteAPFloat(m_emu, rs1);
1206  return m_emu.SetAccruedExceptions(res);
1207  })
1208  .value_or(false);
1209  }
1210  bool operator()(FMUL_S inst) {
1211  return zipOpt(inst.rs1.ReadAPFloat(m_emu, false),
1212  inst.rs2.ReadAPFloat(m_emu, false))
1213  .transform([&](auto &&tup) {
1214  auto [rs1, rs2] = tup;
1215  auto res = rs1.multiply(rs2, m_emu.GetRoundingMode());
1216  inst.rd.WriteAPFloat(m_emu, rs1);
1217  return m_emu.SetAccruedExceptions(res);
1218  })
1219  .value_or(false);
1220  }
1221  bool operator()(FDIV_S inst) {
1222  return zipOpt(inst.rs1.ReadAPFloat(m_emu, false),
1223  inst.rs2.ReadAPFloat(m_emu, false))
1224  .transform([&](auto &&tup) {
1225  auto [rs1, rs2] = tup;
1226  auto res = rs1.divide(rs2, m_emu.GetRoundingMode());
1227  inst.rd.WriteAPFloat(m_emu, rs1);
1228  return m_emu.SetAccruedExceptions(res);
1229  })
1230  .value_or(false);
1231  }
1232  bool operator()(FSQRT_S inst) {
1233  // TODO: APFloat doesn't have a sqrt function.
1234  return false;
1235  }
1236  bool operator()(FSGNJ_S inst) {
1237  return zipOpt(inst.rs1.ReadAPFloat(m_emu, false),
1238  inst.rs2.ReadAPFloat(m_emu, false))
1239  .transform([&](auto &&tup) {
1240  auto [rs1, rs2] = tup;
1241  rs1.copySign(rs2);
1242  return inst.rd.WriteAPFloat(m_emu, rs1);
1243  })
1244  .value_or(false);
1245  }
1246  bool operator()(FSGNJN_S inst) {
1247  return zipOpt(inst.rs1.ReadAPFloat(m_emu, false),
1248  inst.rs2.ReadAPFloat(m_emu, false))
1249  .transform([&](auto &&tup) {
1250  auto [rs1, rs2] = tup;
1251  rs1.copySign(-rs2);
1252  return inst.rd.WriteAPFloat(m_emu, rs1);
1253  })
1254  .value_or(false);
1255  }
1256  bool operator()(FSGNJX_S inst) {
1257  return zipOpt(inst.rs1.ReadAPFloat(m_emu, false),
1258  inst.rs2.ReadAPFloat(m_emu, false))
1259  .transform([&](auto &&tup) {
1260  auto [rs1, rs2] = tup;
1261  // spec: the sign bit is the XOR of the sign bits of rs1 and rs2.
1262  // if rs1 and rs2 have the same signs
1263  // set rs1 to positive
1264  // else set rs1 to negative
1265  if (rs1.isNegative() == rs2.isNegative()) {
1266  rs1.clearSign();
1267  } else {
1268  rs1.clearSign();
1269  rs1.changeSign();
1270  }
1271  return inst.rd.WriteAPFloat(m_emu, rs1);
1272  })
1273  .value_or(false);
1274  }
1275  bool operator()(FMIN_S inst) {
1276  return zipOpt(inst.rs1.ReadAPFloat(m_emu, false),
1277  inst.rs2.ReadAPFloat(m_emu, false))
1278  .transform([&](auto &&tup) {
1279  auto [rs1, rs2] = tup;
1280  // If both inputs are NaNs, the result is the canonical NaN.
1281  // If only one operand is a NaN, the result is the non-NaN operand.
1282  // Signaling NaN inputs set the invalid operation exception flag, even
1283  // when the result is not NaN.
1284  if (rs1.isNaN() || rs2.isNaN())
1285  m_emu.SetAccruedExceptions(llvm::APFloat::opInvalidOp);
1286  if (rs1.isNaN() && rs2.isNaN()) {
1287  auto canonicalNaN = llvm::APFloat::getQNaN(rs1.getSemantics());
1288  return inst.rd.WriteAPFloat(m_emu, canonicalNaN);
1289  }
1290  return inst.rd.WriteAPFloat(m_emu, minnum(rs1, rs2));
1291  })
1292  .value_or(false);
1293  }
1294  bool operator()(FMAX_S inst) {
1295  return zipOpt(inst.rs1.ReadAPFloat(m_emu, false),
1296  inst.rs2.ReadAPFloat(m_emu, false))
1297  .transform([&](auto &&tup) {
1298  auto [rs1, rs2] = tup;
1299  if (rs1.isNaN() || rs2.isNaN())
1300  m_emu.SetAccruedExceptions(llvm::APFloat::opInvalidOp);
1301  if (rs1.isNaN() && rs2.isNaN()) {
1302  auto canonicalNaN = llvm::APFloat::getQNaN(rs1.getSemantics());
1303  return inst.rd.WriteAPFloat(m_emu, canonicalNaN);
1304  }
1305  return inst.rd.WriteAPFloat(m_emu, maxnum(rs1, rs2));
1306  })
1307  .value_or(false);
1308  }
1309  bool operator()(FCVT_W_S inst) {
1310  return inst.rs1.ReadAPFloat(m_emu, false)
1311  .transform([&](auto &&rs1) {
1312  int32_t res = rs1.convertToFloat();
1313  return inst.rd.Write(m_emu, uint64_t(res));
1314  })
1315  .value_or(false);
1316  }
1317  bool operator()(FCVT_WU_S inst) {
1318  return inst.rs1.ReadAPFloat(m_emu, false)
1319  .transform([&](auto &&rs1) {
1320  uint32_t res = rs1.convertToFloat();
1321  return inst.rd.Write(m_emu, uint64_t(res));
1322  })
1323  .value_or(false);
1324  }
1325  bool operator()(FMV_X_W inst) {
1326  return inst.rs1.ReadAPFloat(m_emu, false)
1327  .transform([&](auto &&rs1) {
1328  if (rs1.isNaN())
1329  return inst.rd.Write(m_emu, 0x7fc00000);
1330  auto bits = rs1.bitcastToAPInt();
1331  return inst.rd.Write(m_emu, NanBoxing(uint64_t(bits.getSExtValue())));
1332  })
1333  .value_or(false);
1334  }
1335  bool operator()(FEQ_S inst) {
1336  return zipOpt(inst.rs1.ReadAPFloat(m_emu, false),
1337  inst.rs2.ReadAPFloat(m_emu, false))
1338  .transform([&](auto &&tup) {
1339  auto [rs1, rs2] = tup;
1340  if (rs1.isNaN() || rs2.isNaN()) {
1341  if (rs1.isSignaling() || rs2.isSignaling())
1342  m_emu.SetAccruedExceptions(llvm::APFloat::opInvalidOp);
1343  return inst.rd.Write(m_emu, 0);
1344  }
1345  return inst.rd.Write(m_emu,
1346  rs1.compare(rs2) == llvm::APFloat::cmpEqual);
1347  })
1348  .value_or(false);
1349  }
1350  bool operator()(FLT_S inst) {
1351  return zipOpt(inst.rs1.ReadAPFloat(m_emu, false),
1352  inst.rs2.ReadAPFloat(m_emu, false))
1353  .transform([&](auto &&tup) {
1354  auto [rs1, rs2] = tup;
1355  if (rs1.isNaN() || rs2.isNaN()) {
1356  m_emu.SetAccruedExceptions(llvm::APFloat::opInvalidOp);
1357  return inst.rd.Write(m_emu, 0);
1358  }
1359  return inst.rd.Write(m_emu,
1360  rs1.compare(rs2) == llvm::APFloat::cmpLessThan);
1361  })
1362  .value_or(false);
1363  }
1364  bool operator()(FLE_S inst) {
1365  return zipOpt(inst.rs1.ReadAPFloat(m_emu, false),
1366  inst.rs2.ReadAPFloat(m_emu, false))
1367  .transform([&](auto &&tup) {
1368  auto [rs1, rs2] = tup;
1369  if (rs1.isNaN() || rs2.isNaN()) {
1370  m_emu.SetAccruedExceptions(llvm::APFloat::opInvalidOp);
1371  return inst.rd.Write(m_emu, 0);
1372  }
1373  return inst.rd.Write(m_emu, rs1.compare(rs2) !=
1374  llvm::APFloat::cmpGreaterThan);
1375  })
1376  .value_or(false);
1377  }
1378  bool operator()(FCLASS_S inst) {
1379  return inst.rs1.ReadAPFloat(m_emu, false)
1380  .transform([&](auto &&rs1) {
1381  uint64_t result = 0;
1382  if (rs1.isInfinity() && rs1.isNegative())
1383  result |= 1 << 0;
1384  // neg normal
1385  if (rs1.isNormal() && rs1.isNegative())
1386  result |= 1 << 1;
1387  // neg subnormal
1388  if (rs1.isDenormal() && rs1.isNegative())
1389  result |= 1 << 2;
1390  if (rs1.isNegZero())
1391  result |= 1 << 3;
1392  if (rs1.isPosZero())
1393  result |= 1 << 4;
1394  // pos normal
1395  if (rs1.isNormal() && !rs1.isNegative())
1396  result |= 1 << 5;
1397  // pos subnormal
1398  if (rs1.isDenormal() && !rs1.isNegative())
1399  result |= 1 << 6;
1400  if (rs1.isInfinity() && !rs1.isNegative())
1401  result |= 1 << 7;
1402  if (rs1.isNaN()) {
1403  if (rs1.isSignaling())
1404  result |= 1 << 8;
1405  else
1406  result |= 1 << 9;
1407  }
1408  return inst.rd.Write(m_emu, result);
1409  })
1410  .value_or(false);
1411  }
1412  bool operator()(FCVT_S_W inst) {
1413  return inst.rs1.ReadI32(m_emu)
1414  .transform([&](auto &&rs1) {
1415  llvm::APFloat apf(llvm::APFloat::IEEEsingle(), rs1);
1416  return inst.rd.WriteAPFloat(m_emu, apf);
1417  })
1418  .value_or(false);
1419  }
1420  bool operator()(FCVT_S_WU inst) {
1421  return inst.rs1.ReadU32(m_emu)
1422  .transform([&](auto &&rs1) {
1423  llvm::APFloat apf(llvm::APFloat::IEEEsingle(), rs1);
1424  return inst.rd.WriteAPFloat(m_emu, apf);
1425  })
1426  .value_or(false);
1427  }
1428  bool operator()(FMV_W_X inst) {
1429  return inst.rs1.Read(m_emu)
1430  .transform([&](auto &&rs1) {
1431  llvm::APInt apInt(32, NanUnBoxing(rs1));
1432  llvm::APFloat apf(apInt.bitsToFloat());
1433  return inst.rd.WriteAPFloat(m_emu, apf);
1434  })
1435  .value_or(false);
1436  }
1437  bool operator()(FCVT_L_S inst) {
1438  return inst.rs1.ReadAPFloat(m_emu, false)
1439  .transform([&](auto &&rs1) {
1440  int64_t res = rs1.convertToFloat();
1441  return inst.rd.Write(m_emu, uint64_t(res));
1442  })
1443  .value_or(false);
1444  }
1445  bool operator()(FCVT_LU_S inst) {
1446  return inst.rs1.ReadAPFloat(m_emu, false)
1447  .transform([&](auto &&rs1) {
1448  uint64_t res = rs1.convertToFloat();
1449  return inst.rd.Write(m_emu, res);
1450  })
1451  .value_or(false);
1452  }
1453  bool operator()(FCVT_S_L inst) {
1454  return inst.rs1.ReadI64(m_emu)
1455  .transform([&](auto &&rs1) {
1456  llvm::APFloat apf(llvm::APFloat::IEEEsingle(), rs1);
1457  return inst.rd.WriteAPFloat(m_emu, apf);
1458  })
1459  .value_or(false);
1460  }
1461  bool operator()(FCVT_S_LU inst) {
1462  return inst.rs1.Read(m_emu)
1463  .transform([&](auto &&rs1) {
1464  llvm::APFloat apf(llvm::APFloat::IEEEsingle(), rs1);
1465  return inst.rd.WriteAPFloat(m_emu, apf);
1466  })
1467  .value_or(false);
1468  }
1469  bool operator()(INVALID inst) { return false; }
1470  bool operator()(RESERVED inst) { return false; }
1471  bool operator()(EBREAK inst) { return false; }
1472  bool operator()(HINT inst) { return true; }
1473  bool operator()(NOP inst) { return true; }
1474 };
1475 
1476 bool EmulateInstructionRISCV::Execute(DecodeResult inst, bool ignore_cond) {
1477  return std::visit(Executor(*this, ignore_cond, inst.is_rvc), inst.decoded);
1478 }
1479 
1480 bool EmulateInstructionRISCV::EvaluateInstruction(uint32_t options) {
1481  bool increase_pc = options & eEmulateInstructionOptionAutoAdvancePC;
1482  bool ignore_cond = options & eEmulateInstructionOptionIgnoreConditions;
1483 
1484  if (!increase_pc)
1485  return Execute(m_decoded, ignore_cond);
1486 
1487  auto old_pc = ReadPC();
1488  if (!old_pc)
1489  return false;
1490 
1491  bool success = Execute(m_decoded, ignore_cond);
1492  if (!success)
1493  return false;
1494 
1495  auto new_pc = ReadPC();
1496  if (!new_pc)
1497  return false;
1498 
1499  // If the pc is not updated during execution, we do it here.
1500  return new_pc != old_pc ||
1501  WritePC(*old_pc + Executor::size(m_decoded.is_rvc));
1502 }
1503 
1504 llvm::Optional<DecodeResult>
1505 EmulateInstructionRISCV::ReadInstructionAt(lldb::addr_t addr) {
1506  return ReadMem<uint32_t>(addr)
1507  .transform([&](uint32_t inst) { return Decode(inst); })
1508  .value_or(std::nullopt);
1509 }
1510 
1511 bool EmulateInstructionRISCV::ReadInstruction() {
1512  auto addr = ReadPC();
1513  m_addr = addr.value_or(LLDB_INVALID_ADDRESS);
1514  if (!addr)
1515  return false;
1516  auto inst = ReadInstructionAt(*addr);
1517  if (!inst)
1518  return false;
1519  m_decoded = *inst;
1520  if (inst->is_rvc)
1521  m_opcode.SetOpcode16(inst->inst, GetByteOrder());
1522  else
1523  m_opcode.SetOpcode32(inst->inst, GetByteOrder());
1524  return true;
1525 }
1526 
1527 llvm::Optional<lldb::addr_t> EmulateInstructionRISCV::ReadPC() {
1528  bool success = false;
1529  auto addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
1530  LLDB_INVALID_ADDRESS, &success);
1531  return success ? llvm::Optional<lldb::addr_t>(addr) : std::nullopt;
1532 }
1533 
1534 bool EmulateInstructionRISCV::WritePC(lldb::addr_t pc) {
1536  ctx.type = eContextAdvancePC;
1537  ctx.SetNoArgs();
1538  return WriteRegisterUnsigned(ctx, eRegisterKindGeneric,
1540 }
1541 
1542 llvm::RoundingMode EmulateInstructionRISCV::GetRoundingMode() {
1543  bool success = false;
1544  auto fcsr = ReadRegisterUnsigned(eRegisterKindLLDB, fpr_fcsr_riscv,
1545  LLDB_INVALID_ADDRESS, &success);
1546  if (!success)
1547  return llvm::RoundingMode::Invalid;
1548  auto frm = (fcsr >> 5) & 0x7;
1549  switch (frm) {
1550  case 0b000:
1551  return llvm::RoundingMode::NearestTiesToEven;
1552  case 0b001:
1553  return llvm::RoundingMode::TowardZero;
1554  case 0b010:
1555  return llvm::RoundingMode::TowardNegative;
1556  case 0b011:
1557  return llvm::RoundingMode::TowardPositive;
1558  case 0b111:
1559  return llvm::RoundingMode::Dynamic;
1560  default:
1561  // Reserved for future use.
1562  return llvm::RoundingMode::Invalid;
1563  }
1564 }
1565 
1566 bool EmulateInstructionRISCV::SetAccruedExceptions(
1567  llvm::APFloatBase::opStatus opStatus) {
1568  bool success = false;
1569  auto fcsr = ReadRegisterUnsigned(eRegisterKindLLDB, fpr_fcsr_riscv,
1570  LLDB_INVALID_ADDRESS, &success);
1571  if (!success)
1572  return false;
1573  switch (opStatus) {
1574  case llvm::APFloatBase::opInvalidOp:
1575  fcsr |= 1 << 4;
1576  break;
1577  case llvm::APFloatBase::opDivByZero:
1578  fcsr |= 1 << 3;
1579  break;
1580  case llvm::APFloatBase::opOverflow:
1581  fcsr |= 1 << 2;
1582  break;
1583  case llvm::APFloatBase::opUnderflow:
1584  fcsr |= 1 << 1;
1585  break;
1586  case llvm::APFloatBase::opInexact:
1587  fcsr |= 1 << 0;
1588  break;
1589  case llvm::APFloatBase::opOK:
1590  break;
1591  }
1593  ctx.type = eContextRegisterStore;
1594  ctx.SetNoArgs();
1595  return WriteRegisterUnsigned(ctx, eRegisterKindLLDB, fpr_fcsr_riscv, fcsr);
1596 }
1597 
1598 llvm::Optional<RegisterInfo>
1599 EmulateInstructionRISCV::GetRegisterInfo(lldb::RegisterKind reg_kind,
1600  uint32_t reg_index) {
1601  if (reg_kind == eRegisterKindGeneric) {
1602  switch (reg_index) {
1604  reg_kind = eRegisterKindLLDB;
1605  reg_index = gpr_pc_riscv;
1606  break;
1608  reg_kind = eRegisterKindLLDB;
1609  reg_index = gpr_sp_riscv;
1610  break;
1612  reg_kind = eRegisterKindLLDB;
1613  reg_index = gpr_fp_riscv;
1614  break;
1616  reg_kind = eRegisterKindLLDB;
1617  reg_index = gpr_ra_riscv;
1618  break;
1619  // We may handle LLDB_REGNUM_GENERIC_ARGx when more instructions are
1620  // supported.
1621  default:
1622  llvm_unreachable("unsupported register");
1623  }
1624  }
1625 
1626  const RegisterInfo *array =
1628  const uint32_t length =
1630 
1631  if (reg_index >= length || reg_kind != eRegisterKindLLDB)
1632  return {};
1633 
1634  return array[reg_index];
1635 }
1636 
1637 bool EmulateInstructionRISCV::SetTargetTriple(const ArchSpec &arch) {
1638  return SupportsThisArch(arch);
1639 }
1640 
1641 bool EmulateInstructionRISCV::TestEmulation(Stream *out_stream, ArchSpec &arch,
1642  OptionValueDictionary *test_data) {
1643  return false;
1644 }
1645 
1646 void EmulateInstructionRISCV::Initialize() {
1647  PluginManager::RegisterPlugin(GetPluginNameStatic(),
1648  GetPluginDescriptionStatic(), CreateInstance);
1649 }
1650 
1651 void EmulateInstructionRISCV::Terminate() {
1652  PluginManager::UnregisterPlugin(CreateInstance);
1653 }
1654 
1656 EmulateInstructionRISCV::CreateInstance(const ArchSpec &arch,
1657  InstructionType inst_type) {
1658  if (EmulateInstructionRISCV::SupportsThisInstructionType(inst_type) &&
1659  SupportsThisArch(arch)) {
1660  return new EmulateInstructionRISCV(arch);
1661  }
1662 
1663  return nullptr;
1664 }
1665 
1666 bool EmulateInstructionRISCV::SupportsThisArch(const ArchSpec &arch) {
1667  return arch.GetTriple().isRISCV();
1668 }
1669 
1670 } // namespace lldb_private
lldb_private::AtomicSequence
bool AtomicSequence(EmulateInstructionRISCV &emulator)
Definition: EmulateInstructionRISCV.cpp:323
lldb_private::Executor::operator()
bool operator()(LWU inst)
Definition: EmulateInstructionRISCV.cpp:778
RISCVInstructions.h
lldb_private::Executor::operator()
bool operator()(JAL inst)
Definition: EmulateInstructionRISCV.cpp:611
lldb_private::DecodeRType
static RISCVInst DecodeRType(uint32_t inst)
Definition: EmulateInstructionRISCV.cpp:395
lldb_private::Executor::operator()
bool operator()(FADD_S inst)
Definition: EmulateInstructionRISCV.cpp:1188
lldb_private::DecodeC_AND
RISCVInst DecodeC_AND(uint32_t inst)
Definition: RISCVCInstructions.h:273
lldb_private::NanBoxing
constexpr uint64_t NanBoxing(uint64_t val)
RISC-V spec: The upper bits of a valid NaN-boxed value must be all 1s.
Definition: RISCVInstructions.h:272
lldb_private::Executor::operator()
bool operator()(LD inst)
Definition: EmulateInstructionRISCV.cpp:781
lldb_private::Executor::m_is_rvc
bool m_is_rvc
Definition: EmulateInstructionRISCV.cpp:590
lldb_private::Executor::operator()
bool operator()(REMUW inst)
Definition: EmulateInstructionRISCV.cpp:1019
lldb_private::Executor::operator()
bool operator()(AMOADD_W inst)
Definition: EmulateInstructionRISCV.cpp:1043
lldb_private::Executor::operator()
bool operator()(REMU inst)
Definition: EmulateInstructionRISCV.cpp:957
lldb_private::Executor::operator()
bool operator()(SLTI inst)
Definition: EmulateInstructionRISCV.cpp:663
lldb_private::Executor::operator()
bool operator()(ORI inst)
Definition: EmulateInstructionRISCV.cpp:684
lldb_private::ArchSpec
Definition: ArchSpec.h:32
lldb_private::Executor::delta
uint64_t delta()
Definition: EmulateInstructionRISCV.cpp:597
lldb_private::DecodeC_SRAI
RISCVInst DecodeC_SRAI(uint32_t inst)
Definition: RISCVCInstructions.h:244
lldb_private::is_amo_cmp
constexpr bool is_amo_cmp
Definition: EmulateInstructionRISCV.cpp:211
lldb_private::Executor::operator()
bool operator()(SRL inst)
Definition: EmulateInstructionRISCV.cpp:746
LLDB_INVALID_REGNUM
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:79
lldb_private::Executor::operator()
bool operator()(RESERVED inst)
Definition: EmulateInstructionRISCV.cpp:1470
lldb_private::DecodeRD
constexpr uint32_t DecodeRD(uint32_t inst)
Definition: RISCVInstructions.h:255
lldb_private::RISCVInst
std::variant< LUI, AUIPC, JAL, JALR, B, LB, LH, LW, LBU, LHU, SB, SH, SW, ADDI, SLTI, SLTIU, XORI, ORI, ANDI, ADD, SUB, SLL, SLT, SLTU, XOR, SRL, SRA, OR, AND, LWU, LD, SD, SLLI, SRLI, SRAI, ADDIW, SLLIW, SRLIW, SRAIW, ADDW, SUBW, SLLW, SRLW, SRAW, MUL, MULH, MULHSU, MULHU, DIV, DIVU, REM, REMU, MULW, DIVW, DIVUW, REMW, REMUW, LR_W, SC_W, AMOSWAP_W, AMOADD_W, AMOXOR_W, AMOAND_W, AMOOR_W, AMOMIN_W, AMOMAX_W, AMOMINU_W, AMOMAXU_W, LR_D, SC_D, AMOSWAP_D, AMOADD_D, AMOXOR_D, AMOAND_D, AMOOR_D, AMOMIN_D, AMOMAX_D, AMOMINU_D, 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, FCVT_L_S, FCVT_LU_S, FCVT_S_L, FCVT_S_LU, INVALID, EBREAK, RESERVED, HINT, NOP > RISCVInst
Definition: RISCVInstructions.h:237
lldb_private::Executor::operator()
bool operator()(SLLIW inst)
Definition: EmulateInstructionRISCV.cpp:813
lldb_private::Executor::operator()
bool operator()(B inst)
Definition: EmulateInstructionRISCV.cpp:628
lldb_private::Executor::operator()
bool operator()(ADDI inst)
Definition: EmulateInstructionRISCV.cpp:656
lldb_private::RegisterValue
Definition: RegisterValue.h:28
lldb_private::Executor::operator()
bool operator()(DIVUW inst)
Definition: EmulateInstructionRISCV.cpp:992
lldb_private::Executor::operator()
bool operator()(AMOAND_D inst)
Definition: EmulateInstructionRISCV.cpp:1090
fpr_f0_riscv
@ fpr_f0_riscv
Definition: lldb-riscv-register-enums.h:87
lldb_private::Executor::operator()
bool operator()(INVALID inst)
Definition: EmulateInstructionRISCV.cpp:1469
lldb::eRegisterKindGeneric
@ eRegisterKindGeneric
insn ptr reg, stack ptr reg, etc not specific to any particular target
Definition: lldb-enumerations.h:231
lldb_private::Executor::operator()
bool operator()(FCVT_L_S inst)
Definition: EmulateInstructionRISCV.cpp:1437
lldb_private::Executor::operator()
bool operator()(SRLI inst)
Definition: EmulateInstructionRISCV.cpp:792
LLDB_LOGF
#define LLDB_LOGF(log,...)
Definition: Log.h:344
lldb_private::Executor::operator()
bool operator()(SUB inst)
Definition: EmulateInstructionRISCV.cpp:706
lldb_private::EmulateInstruction::Context
Definition: EmulateInstruction.h:184
lldb_private::DecodeC_SW
RISCVInst DecodeC_SW(uint32_t inst)
Definition: RISCVCInstructions.h:97
lldb_private::AtomicAddr
static std::enable_if_t< is_amo_add< I >||is_amo_bit_op< I >||is_amo_swap< I >||is_amo_cmp< I >, llvm::Optional< uint64_t > > AtomicAddr(EmulateInstructionRISCV &emulator, I inst, unsigned int align)
Definition: EmulateInstructionRISCV.cpp:251
lldb_private::Executor::operator()
bool operator()(SLLI inst)
Definition: EmulateInstructionRISCV.cpp:785
lldb_private::Executor::operator()
bool operator()(XOR inst)
Definition: EmulateInstructionRISCV.cpp:738
gpr_fp_riscv
@ gpr_fp_riscv
Definition: lldb-riscv-register-enums.h:60
lldb_private::DecodeC_OR
RISCVInst DecodeC_OR(uint32_t inst)
Definition: RISCVCInstructions.h:278
lldb_private::InstrPattern
Definition: RISCVInstructions.h:239
lldb_private::AtomicSwap
static std::enable_if_t< is_amo_swap< I >, bool > AtomicSwap(EmulateInstructionRISCV &emulator, I inst, int align, uint64_t(*extend)(T))
Definition: EmulateInstructionRISCV.cpp:261
lldb_private::Executor::operator()
bool operator()(REM inst)
Definition: EmulateInstructionRISCV.cpp:942
lldb_private::BEQ
constexpr uint32_t BEQ
Definition: EmulateInstructionRISCV.cpp:48
lldb_private::Executor::operator()
bool operator()(LR_D)
Definition: EmulateInstructionRISCV.cpp:1033
lldb_private::AtomicCmp
static std::enable_if_t< is_amo_cmp< I >, bool > AtomicCmp(EmulateInstructionRISCV &emulator, I inst, int align, uint64_t(*extend)(T), T(*cmp)(T, T))
Definition: EmulateInstructionRISCV.cpp:309
lldb_private::Executor::operator()
bool operator()(LH inst)
Definition: EmulateInstructionRISCV.cpp:641
lldb_private::DecodeC_SRLI
RISCVInst DecodeC_SRLI(uint32_t inst)
Definition: RISCVCInstructions.h:236
lldb_private::DecodeSImm
constexpr uint32_t DecodeSImm(uint32_t inst)
Definition: EmulateInstructionRISCV.cpp:87
lldb_private::Executor::operator()
bool operator()(FCVT_S_W inst)
Definition: EmulateInstructionRISCV.cpp:1412
lldb_private::Stream
Definition: Stream.h:28
lldb_private::Executor::operator()
bool operator()(AMOXOR_D inst)
Definition: EmulateInstructionRISCV.cpp:1086
lldb_private::ArchSpec::GetTriple
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:463
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
pc
@ pc
Definition: CompactUnwindInfo.cpp:1251
fpr_fcsr_riscv
@ fpr_fcsr_riscv
Definition: lldb-riscv-register-enums.h:120
lldb_private::Executor::operator()
bool operator()(FMV_X_W inst)
Definition: EmulateInstructionRISCV.cpp:1325
OptionValueDictionary.h
lldb_private::DecodeC_LI
RISCVInst DecodeC_LI(uint32_t inst)
Definition: RISCVCInstructions.h:162
lldb_private::AtomicADD
static std::enable_if_t< is_amo_add< I >, bool > AtomicADD(EmulateInstructionRISCV &emulator, I inst, int align, uint64_t(*extend)(T))
Definition: EmulateInstructionRISCV.cpp:277
lldb_private::Executor::operator()
bool operator()(FSW inst)
Definition: EmulateInstructionRISCV.cpp:1130
lldb_private::DecodeRS3
constexpr uint32_t DecodeRS3(uint32_t inst)
Definition: RISCVInstructions.h:258
lldb_private::DecodeR4Type
static RISCVInst DecodeR4Type(uint32_t inst)
Definition: EmulateInstructionRISCV.cpp:407
lldb_private::FPREncodingToLLDB
static uint32_t FPREncodingToLLDB(uint32_t reg_encode)
Definition: EmulateInstructionRISCV.cpp:104
lldb_private::Executor::size
static uint64_t size(bool is_rvc)
Definition: EmulateInstructionRISCV.cpp:594
lldb_private::is_amo_bit_op
constexpr bool is_amo_bit_op
Definition: EmulateInstructionRISCV.cpp:201
lldb_private::Executor::operator()
bool operator()(AMOOR_W inst)
Definition: EmulateInstructionRISCV.cpp:1054
lldb_private::Executor::operator()
bool operator()(AMOMAX_W inst)
Definition: EmulateInstructionRISCV.cpp:1064
lldb_private::BNE
constexpr uint32_t BNE
Definition: EmulateInstructionRISCV.cpp:49
lldb_private::DecodeC_MV
RISCVInst DecodeC_MV(uint32_t inst)
Definition: RISCVCInstructions.h:260
LLDB_PLUGIN_DEFINE_ADV
LLDB_PLUGIN_DEFINE_ADV(ObjectContainerUniversalMachO, ObjectContainerMachOArchive) void ObjectContainerUniversalMachO
Definition: ObjectContainerUniversalMachO.cpp:23
lldb_private::Executor::operator()
bool operator()(SRAIW inst)
Definition: EmulateInstructionRISCV.cpp:827
lldb_private::Executor::operator()
bool operator()(AMOMAX_D inst)
Definition: EmulateInstructionRISCV.cpp:1104
lldb_private::RegisterValue::GetAsUInt64
uint64_t GetAsUInt64(uint64_t fail_value=UINT64_MAX, bool *success_ptr=nullptr) const
Definition: RegisterValue.cpp:556
lldb_private::Executor::operator()
bool operator()(SLT inst)
Definition: EmulateInstructionRISCV.cpp:722
lldb_private::DecodeC_BEQZ
RISCVInst DecodeC_BEQZ(uint32_t inst)
Definition: RISCVCInstructions.h:154
lldb_private::EmulateInstructionRISCV::ReadPC
llvm::Optional< lldb::addr_t > ReadPC()
Definition: EmulateInstructionRISCV.cpp:1527
lldb_private::Executor::operator()
bool operator()(AMOOR_D inst)
Definition: EmulateInstructionRISCV.cpp:1094
lldb_private::Executor::operator()
bool operator()(AMOMAXU_W inst)
Definition: EmulateInstructionRISCV.cpp:1075
lldb_private::BGEU
constexpr uint32_t BGEU
Definition: EmulateInstructionRISCV.cpp:53
lldb_private::DecodeC_SWSP
RISCVInst DecodeC_SWSP(uint32_t inst)
Definition: RISCVCInstructions.h:72
lldb_private::Executor::operator()
bool operator()(FLW inst)
Definition: EmulateInstructionRISCV.cpp:1120
lldb_private::Executor::operator()
bool operator()(FSGNJX_S inst)
Definition: EmulateInstructionRISCV.cpp:1256
lldb_private::Executor::Executor
Executor(EmulateInstructionRISCV &emulator, bool ignoreCond, bool is_rvc)
Definition: EmulateInstructionRISCV.cpp:600
lldb_private::RegisterValue::SetUInt64
void SetUInt64(uint64_t uint, Type t=eTypeUInt64)
Definition: RegisterValue.h:205
lldb_private::Executor::operator()
bool operator()(HINT inst)
Definition: EmulateInstructionRISCV.cpp:1472
lldb_private::Executor::operator()
bool operator()(AMOMAXU_D inst)
Definition: EmulateInstructionRISCV.cpp:1115
lldb_private::Executor::operator()
bool operator()(FCVT_LU_S inst)
Definition: EmulateInstructionRISCV.cpp:1445
lldb::eRegisterKindLLDB
@ eRegisterKindLLDB
lldb's internal register numbers
Definition: lldb-enumerations.h:235
lldb_private::EmulateInstructionRISCV::GetRoundingMode
llvm::RoundingMode GetRoundingMode()
Definition: EmulateInstructionRISCV.cpp:1542
lldb_private::DecodeC_ANDI
RISCVInst DecodeC_ANDI(uint32_t inst)
Definition: RISCVCInstructions.h:252
lldb_private::Executor::operator()
bool operator()(AMOAND_W inst)
Definition: EmulateInstructionRISCV.cpp:1050
lldb_private::Executor::operator()
bool operator()(AMOADD_D inst)
Definition: EmulateInstructionRISCV.cpp:1083
lldb_private::Executor::operator()
bool operator()(FLE_S inst)
Definition: EmulateInstructionRISCV.cpp:1364
lldb_private::Executor::operator()
bool operator()(FNMSUB_S inst)
Definition: EmulateInstructionRISCV.cpp:1164
lldb_private::Executor::operator()
bool operator()(SLTIU inst)
Definition: EmulateInstructionRISCV.cpp:670
lldb_private::Executor::operator()
bool operator()(SD inst)
Definition: EmulateInstructionRISCV.cpp:784
lldb_private::Executor::operator()
bool operator()(AND inst)
Definition: EmulateInstructionRISCV.cpp:770
lldb_private::EmulateInstruction::Context::type
ContextType type
Definition: EmulateInstruction.h:185
lldb_private::DecodeBType
static RISCVInst DecodeBType(uint32_t inst)
Definition: EmulateInstructionRISCV.cpp:386
lldb_private::DecodeC_BNEZ
RISCVInst DecodeC_BNEZ(uint32_t inst)
Definition: RISCVCInstructions.h:146
lldb_private::DecodeIType
static RISCVInst DecodeIType(uint32_t inst)
Definition: EmulateInstructionRISCV.cpp:382
lldb_private::SignExt
constexpr int32_t SignExt(uint32_t imm)
Definition: EmulateInstructionRISCV.cpp:56
lldb_private::Executor::operator()
bool operator()(FSGNJN_S inst)
Definition: EmulateInstructionRISCV.cpp:1246
lldb_private::DecodeC_LWSP
RISCVInst DecodeC_LWSP(uint32_t inst)
Definition: RISCVCInstructions.h:52
lldb_private::Executor::operator()
bool operator()(SH inst)
Definition: EmulateInstructionRISCV.cpp:654
lldb_private::EmulateInstructionRISCV
Definition: EmulateInstructionRISCV.h:22
lldb_private::DecodeResult::is_rvc
bool is_rvc
Definition: RISCVInstructions.h:251
lldb_private::Executor::operator()
bool operator()(AUIPC inst)
Definition: EmulateInstructionRISCV.cpp:604
RegisterInfoPOSIX_riscv64::GetRegisterInfoCount
static uint32_t GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch)
Definition: RegisterInfoPOSIX_riscv64.cpp:40
RISCVCInstructions.h
gpr_pc_riscv
@ gpr_pc_riscv
Definition: lldb-riscv-register-enums.h:19
OptionValueArray.h
lldb_private::PATTERNS
static const InstrPattern PATTERNS[]
Definition: EmulateInstructionRISCV.cpp:412
lldb_private::DecodeC_LUI_ADDI16SP
RISCVInst DecodeC_LUI_ADDI16SP(uint32_t inst)
Definition: RISCVCInstructions.h:170
lldb_private::Executor::operator()
bool operator()(LHU inst)
Definition: EmulateInstructionRISCV.cpp:650
lldb-riscv-register-enums.h
lldb_private::Executor::operator()
bool operator()(FNMADD_S inst)
Definition: EmulateInstructionRISCV.cpp:1176
gpr_x0_riscv
@ gpr_x0_riscv
Definition: lldb-riscv-register-enums.h:51
lldb_private::DecodeC_XOR
RISCVInst DecodeC_XOR(uint32_t inst)
Definition: RISCVCInstructions.h:283
lldb_private::is_amo_add
constexpr bool is_amo_add
Definition: EmulateInstructionRISCV.cpp:197
arm64_dwarf::x7
@ x7
Definition: ARM64_DWARF_Registers.h:24
lldb_private::DecodeRRS1Type
static RISCVInst DecodeRRS1Type(uint32_t inst)
Definition: EmulateInstructionRISCV.cpp:403
lldb_private::Executor::operator()
bool operator()(FCVT_S_WU inst)
Definition: EmulateInstructionRISCV.cpp:1420
lldb_private::Executor::operator()
bool operator()(XORI inst)
Definition: EmulateInstructionRISCV.cpp:677
lldb_private::Executor::operator()
bool operator()(FSUB_S inst)
Definition: EmulateInstructionRISCV.cpp:1199
lldb_private::Executor::operator()
bool operator()(AMOSWAP_D inst)
Definition: EmulateInstructionRISCV.cpp:1080
lldb_private::is_amo_swap
constexpr bool is_amo_swap
Definition: EmulateInstructionRISCV.cpp:207
lldb_private::Executor::operator()
bool operator()(NOP inst)
Definition: EmulateInstructionRISCV.cpp:1473
lldb_private::Executor::operator()
bool operator()(FMIN_S inst)
Definition: EmulateInstructionRISCV.cpp:1275
Address.h
UnwindPlan.h
lldb_private::EmulateInstructionRISCV::SetAccruedExceptions
bool SetAccruedExceptions(llvm::APFloatBase::opStatus)
Definition: EmulateInstructionRISCV.cpp:1566
lldb_private::DecodeRS1
constexpr uint32_t DecodeRS1(uint32_t inst)
Definition: RISCVInstructions.h:256
lldb_private::Executor::operator()
bool operator()(SLL inst)
Definition: EmulateInstructionRISCV.cpp:714
lldb_private::Executor::operator()
bool operator()(FMSUB_S inst)
Definition: EmulateInstructionRISCV.cpp:1152
lldb_private::DecodeC_ADDIW
RISCVInst DecodeC_ADDIW(uint32_t inst)
Definition: RISCVCInstructions.h:204
lldb_private::DecodeJType
static RISCVInst DecodeJType(uint32_t inst)
Definition: EmulateInstructionRISCV.cpp:378
lldb_private::EmulateInstructionRISCV::WritePC
bool WritePC(lldb::addr_t pc)
Definition: EmulateInstructionRISCV.cpp:1534
lldb_private::Executor::operator()
bool operator()(FSQRT_S inst)
Definition: EmulateInstructionRISCV.cpp:1232
lldb_private::DecodeC_LW
RISCVInst DecodeC_LW(uint32_t inst)
Definition: RISCVCInstructions.h:84
lldb::RegisterKind
RegisterKind
Register numbering types.
Definition: lldb-enumerations.h:228
lldb_private::is_store
constexpr bool is_store
Definition: EmulateInstructionRISCV.cpp:193
lldb_private::DecodeResult::decoded
RISCVInst decoded
Definition: RISCVInstructions.h:249
lldb_private::LoadStoreAddr
static std::enable_if_t< is_load< I >||is_store< I >, llvm::Optional< uint64_t > > LoadStoreAddr(EmulateInstructionRISCV &emulator, I inst)
Definition: EmulateInstructionRISCV.cpp:219
lldb_private::Executor::operator()
bool operator()(DIV inst)
Definition: EmulateInstructionRISCV.cpp:915
lldb_private::Executor::operator()
bool operator()(AMOSWAP_W inst)
Definition: EmulateInstructionRISCV.cpp:1040
lldb_private::Executor::operator()
bool operator()(ADDW inst)
Definition: EmulateInstructionRISCV.cpp:834
lldb_private::Executor::operator()
bool operator()(SLLW inst)
Definition: EmulateInstructionRISCV.cpp:850
RegisterInfoPOSIX_riscv64::GetRegisterInfoPtr
static const lldb_private::RegisterInfo * GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch)
Definition: RegisterInfoPOSIX_riscv64.cpp:29
lldb_private::Executor::operator()
bool operator()(LBU inst)
Definition: EmulateInstructionRISCV.cpp:647
lldb_private::Executor::operator()
bool operator()(FMAX_S inst)
Definition: EmulateInstructionRISCV.cpp:1294
lldb_private::Executor::operator()
bool operator()(SRLW inst)
Definition: EmulateInstructionRISCV.cpp:858
lldb_private::Executor::operator()
bool operator()(LR_W)
Definition: EmulateInstructionRISCV.cpp:1032
lldb_private::Executor::operator()
bool operator()(SRAW inst)
Definition: EmulateInstructionRISCV.cpp:866
lldb_private::EmulateInstruction::ReadRegister
llvm::Optional< RegisterValue > ReadRegister(const RegisterInfo &reg_info)
Definition: EmulateInstruction.cpp:76
lldb_private::is_load
constexpr bool is_load
Definition: EmulateInstructionRISCV.cpp:187
lldb_private::EmulateInstruction::Context::SetNoArgs
void SetNoArgs()
Definition: EmulateInstruction.h:328
lldb_private::Executor::operator()
bool operator()(AMOXOR_W inst)
Definition: EmulateInstructionRISCV.cpp:1046
lldb_private::Store
static std::enable_if_t< is_store< I >, bool > Store(EmulateInstructionRISCV &emulator, I inst)
Definition: EmulateInstructionRISCV.cpp:238
uint32_t
lldb_private::Executor::operator()
bool operator()(FLT_S inst)
Definition: EmulateInstructionRISCV.cpp:1350
lldb_private::AtomicBitOperate
static std::enable_if_t< is_amo_bit_op< I >, bool > AtomicBitOperate(EmulateInstructionRISCV &emulator, I inst, int align, uint64_t(*extend)(T), T(*operate)(T, T))
Definition: EmulateInstructionRISCV.cpp:293
lldb_private::EmulateInstruction
Definition: EmulateInstruction.h:93
LLDB_REGNUM_GENERIC_SP
#define LLDB_REGNUM_GENERIC_SP
Definition: lldb-defines.h:52
lldb_private::DecodeC_SUBW
RISCVInst DecodeC_SUBW(uint32_t inst)
Definition: RISCVCInstructions.h:293
lldb_private::Executor::operator()
bool operator()(LB inst)
Definition: EmulateInstructionRISCV.cpp:638
lldb_private::B::imm
uint32_t imm
Definition: RISCVInstructions.h:92
lldb_private::DecodeUImm
constexpr uint32_t DecodeUImm(uint32_t inst)
Definition: EmulateInstructionRISCV.cpp:92
gpr_x1_riscv
@ gpr_x1_riscv
Definition: lldb-riscv-register-enums.h:20
lldb_private::Executor::operator()
bool operator()(DIVW inst)
Definition: EmulateInstructionRISCV.cpp:977
lldb_private::Rd
Definition: RISCVInstructions.h:22
lldb_private::B
Definition: RISCVInstructions.h:89
lldb_private::DecodeC_ADDW
RISCVInst DecodeC_ADDW(uint32_t inst)
Definition: RISCVCInstructions.h:298
lldb_private::Executor::operator()
bool operator()(LW inst)
Definition: EmulateInstructionRISCV.cpp:644
ArchSpec.h
lldb_private::Executor::operator()
bool operator()(SC_D)
Definition: EmulateInstructionRISCV.cpp:1037
EmulateInstructionRISCV.h
lldb_private::Executor::operator()
bool operator()(AMOMINU_D inst)
Definition: EmulateInstructionRISCV.cpp:1110
lldb_private::Executor::m_emu
EmulateInstructionRISCV & m_emu
Definition: EmulateInstructionRISCV.cpp:588
if
if(APPLE AND LLVM_ENABLE_LOCAL_SUBMODULE_VISIBILITY) remove_module_flags() endif() macro(add_host_subdirectory group) list(APPEND HOST_SOURCES $
Definition: Host/CMakeLists.txt:1
lldb_private::Executor::m_ignore_cond
bool m_ignore_cond
Definition: EmulateInstructionRISCV.cpp:589
lldb_private::Executor::operator()
bool operator()(MUL inst)
Definition: EmulateInstructionRISCV.cpp:875
lldb_private::B::rs2
Rs rs2
Definition: RISCVInstructions.h:91
uint16_t
lldb_private::B::funct3
uint32_t funct3
Definition: RISCVInstructions.h:93
lldb_private::DecodeC_SDSP
RISCVInst DecodeC_SDSP(uint32_t inst)
Definition: RISCVCInstructions.h:78
lldb_private::DecodeResult
Definition: RISCVInstructions.h:248
PluginManager.h
lldb_private::Executor::operator()
bool operator()(SRLIW inst)
Definition: EmulateInstructionRISCV.cpp:820
LLDB_INVALID_ADDRESS
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:74
lldb_private::Executor::operator()
bool operator()(ADD inst)
Definition: EmulateInstructionRISCV.cpp:698
lldb_private::EmulateInstructionRISCV::ReadMem
std::enable_if_t< std::is_integral_v< T >, llvm::Optional< T > > ReadMem(uint64_t addr)
Definition: EmulateInstructionRISCV.h:77
lldb_private::DecodeC_SD
RISCVInst DecodeC_SD(uint32_t inst)
Definition: RISCVCInstructions.h:104
lldb_private::Executor::operator()
bool operator()(SLTU inst)
Definition: EmulateInstructionRISCV.cpp:730
lldb_private::Executor::operator()
bool operator()(FMV_W_X inst)
Definition: EmulateInstructionRISCV.cpp:1428
lldb_private::NanUnBoxing
constexpr uint32_t NanUnBoxing(uint64_t val)
Definition: RISCVInstructions.h:275
lldb_private::Executor::operator()
bool operator()(FCVT_W_S inst)
Definition: EmulateInstructionRISCV.cpp:1309
lldb_private::InstructionType
InstructionType
Instruction types.
Definition: lldb-private-enumerations.h:118
lldb_private::DecodeC_LDSP
RISCVInst DecodeC_LDSP(uint32_t inst)
Definition: RISCVCInstructions.h:62
gpr_ra_riscv
@ gpr_ra_riscv
Definition: lldb-riscv-register-enums.h:53
lldb_private::Executor
Definition: EmulateInstructionRISCV.cpp:587
lldb_private::BGE
constexpr uint32_t BGE
Definition: EmulateInstructionRISCV.cpp:51
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::DecodeC_ADDI
RISCVInst DecodeC_ADDI(uint32_t inst)
Definition: RISCVCInstructions.h:194
lldb_private::EmulateInstructionRISCV::ReadInstructionAt
llvm::Optional< DecodeResult > ReadInstructionAt(lldb::addr_t addr)
Definition: EmulateInstructionRISCV.cpp:1505
lldb_private::Executor::operator()
bool operator()(AMOMIN_D inst)
Definition: EmulateInstructionRISCV.cpp:1098
lldb_private::Executor::operator()
bool operator()(MULH inst)
Definition: EmulateInstructionRISCV.cpp:883
lldb_private::Executor::operator()
bool operator()(FDIV_S inst)
Definition: EmulateInstructionRISCV.cpp:1221
LLDB_REGNUM_GENERIC_FP
#define LLDB_REGNUM_GENERIC_FP
Definition: lldb-defines.h:53
gpr_sp_riscv
@ gpr_sp_riscv
Definition: lldb-riscv-register-enums.h:54
lldb_private::DecodeUType
static RISCVInst DecodeUType(uint32_t inst)
Definition: EmulateInstructionRISCV.cpp:374
lldb_private::DecodeBImm
constexpr uint32_t DecodeBImm(uint32_t inst)
Definition: EmulateInstructionRISCV.cpp:80
lldb_private::Executor::operator()
bool operator()(FMADD_S inst)
Definition: EmulateInstructionRISCV.cpp:1140
lldb_private::Executor::operator()
bool operator()(FCVT_S_LU inst)
Definition: EmulateInstructionRISCV.cpp:1461
lldb_private::Executor::operator()
bool operator()(FMUL_S inst)
Definition: EmulateInstructionRISCV.cpp:1210
lldb_private::Executor::operator()
bool operator()(SC_W)
Definition: EmulateInstructionRISCV.cpp:1034
lldb_private::Executor::operator()
bool operator()(ANDI inst)
Definition: EmulateInstructionRISCV.cpp:691
lldb_private::Executor::operator()
bool operator()(FEQ_S inst)
Definition: EmulateInstructionRISCV.cpp:1335
lldb_private::Executor::operator()
bool operator()(MULHSU inst)
Definition: EmulateInstructionRISCV.cpp:893
LLDB_REGNUM_GENERIC_PC
#define LLDB_REGNUM_GENERIC_PC
Definition: lldb-defines.h:51
lldb_private::DecodeSType
static RISCVInst DecodeSType(uint32_t inst)
Definition: EmulateInstructionRISCV.cpp:391
lldb_private::DecodeRM
constexpr int32_t DecodeRM(uint32_t inst)
Definition: RISCVInstructions.h:269
lldb_private::OptionValueDictionary
Definition: OptionValueDictionary.h:19
lldb_private::Executor::operator()
bool operator()(JALR inst)
Definition: EmulateInstructionRISCV.cpp:619
lldb_private::Executor::operator()
bool operator()(MULHU inst)
Definition: EmulateInstructionRISCV.cpp:904
Stream.h
lldb_private::Log
Definition: Log.h:115
lldb_private::EmulateInstructionRISCV::WriteMem
bool WriteMem(uint64_t addr, uint64_t value)
Definition: EmulateInstructionRISCV.h:88
lldb_private::Executor::operator()
bool operator()(REMW inst)
Definition: EmulateInstructionRISCV.cpp:1004
lldb_private::B::rs1
Rs rs1
Definition: RISCVInstructions.h:90
RegisterInfoPOSIX_riscv64.h
lldb_private::BLT
constexpr uint32_t BLT
Definition: EmulateInstructionRISCV.cpp:50
lldb_private::bits
static uint32_t bits(const uint32_t val, const uint32_t msbit, const uint32_t lsbit)
Definition: ARMUtils.h:265
lldb_private::DecodeC_ADD
RISCVInst DecodeC_ADD(uint32_t inst)
Definition: RISCVCInstructions.h:268
lldb_private::Executor::operator()
bool operator()(ADDIW inst)
Definition: EmulateInstructionRISCV.cpp:806
lldb_private::Executor::operator()
bool operator()(SRAI inst)
Definition: EmulateInstructionRISCV.cpp:799
lldb_private::Executor::operator()
bool operator()(SW inst)
Definition: EmulateInstructionRISCV.cpp:655
lldb_private::Executor::operator()
bool operator()(AMOMINU_W inst)
Definition: EmulateInstructionRISCV.cpp:1070
lldb_private::GetLog
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:309
lldb_private::DecodeC_SUB
RISCVInst DecodeC_SUB(uint32_t inst)
Definition: RISCVCInstructions.h:288
lldb_private::zipOpt
static llvm::Optional< std::tuple< Ts... > > zipOpt(llvm::Optional< Ts > &&...ts)
Returns all values wrapped in Optional, or std::nullopt if any of the values is None.
Definition: EmulateInstructionRISCV.cpp:37
lldb_private::Executor::operator()
bool operator()(FCVT_S_L inst)
Definition: EmulateInstructionRISCV.cpp:1453
lldb_private::Executor::operator()
bool operator()(MULW inst)
Definition: EmulateInstructionRISCV.cpp:969
lldb_private::DecodeC_J
RISCVInst DecodeC_J(uint32_t inst)
Definition: RISCVCInstructions.h:110
lldb_private::DecodeRS2
constexpr uint32_t DecodeRS2(uint32_t inst)
Definition: RISCVInstructions.h:257
lldb_private::DecodeC_JR
RISCVInst DecodeC_JR(uint32_t inst)
Definition: RISCVCInstructions.h:124
lldb_private::Load
static std::enable_if_t< is_load< I >, bool > Load(EmulateInstructionRISCV &emulator, I inst, uint64_t(*extend)(E))
Definition: EmulateInstructionRISCV.cpp:227
lldb_private::DecodeC_JALR
RISCVInst DecodeC_JALR(uint32_t inst)
Definition: RISCVCInstructions.h:131
lldb
Definition: SBAddress.h:15
lldb_private::DecodeRShamtType
static RISCVInst DecodeRShamtType(uint32_t inst)
Definition: EmulateInstructionRISCV.cpp:399
lldb_private::Executor::operator()
bool operator()(DIVU inst)
Definition: EmulateInstructionRISCV.cpp:930
lldb_private::DecodeC_LD
RISCVInst DecodeC_LD(uint32_t inst)
Definition: RISCVCInstructions.h:91
lldb_private::DecodeFunct3
constexpr uint32_t DecodeFunct3(uint32_t inst)
Definition: RISCVInstructions.h:261
lldb_private::Executor::operator()
bool operator()(OR inst)
Definition: EmulateInstructionRISCV.cpp:762
lldb_private::CompareB
static bool CompareB(uint64_t rs1, uint64_t rs2, uint32_t funct3)
Definition: EmulateInstructionRISCV.cpp:167
lldb_private::Executor::operator()
bool operator()(FSGNJ_S inst)
Definition: EmulateInstructionRISCV.cpp:1236
lldb_private::Executor::operator()
bool operator()(SUBW inst)
Definition: EmulateInstructionRISCV.cpp:842
lldb_private::Executor::operator()
bool operator()(LUI inst)
Definition: EmulateInstructionRISCV.cpp:603
lldb_private::BLTU
constexpr uint32_t BLTU
Definition: EmulateInstructionRISCV.cpp:52
lldb_private::Executor::operator()
bool operator()(SRA inst)
Definition: EmulateInstructionRISCV.cpp:754
lldb_private::DecodeC_SLLI
RISCVInst DecodeC_SLLI(uint32_t inst)
Definition: RISCVCInstructions.h:228
LLDBLog.h
lldb_private::EmulateInstruction::WriteRegister
bool WriteRegister(const Context &context, const RegisterInfo &ref_info, const RegisterValue &reg_value)
Definition: EmulateInstruction.cpp:125
lldb_private::Rs
Definition: RISCVInstructions.h:28
lldb_private::Executor::operator()
bool operator()(SB inst)
Definition: EmulateInstructionRISCV.cpp:653
UINT64_MAX
#define UINT64_MAX
Definition: lldb-defines.h:23
lldb_private::GPREncodingToLLDB
static uint32_t GPREncodingToLLDB(uint32_t reg_encode)
Definition: EmulateInstructionRISCV.cpp:96
lldb_private::Executor::operator()
bool operator()(AMOMIN_W inst)
Definition: EmulateInstructionRISCV.cpp:1058
lldb_private::Executor::operator()
bool operator()(EBREAK inst)
Definition: EmulateInstructionRISCV.cpp:1471
lldb_private::Executor::operator()
bool operator()(FCVT_WU_S inst)
Definition: EmulateInstructionRISCV.cpp:1317
lldb_private::DecodeC_ADDI4SPN
RISCVInst DecodeC_ADDI4SPN(uint32_t inst)
Definition: RISCVCInstructions.h:214
LLDB_REGNUM_GENERIC_RA
#define LLDB_REGNUM_GENERIC_RA
Definition: lldb-defines.h:54
lldb_private::Executor::operator()
bool operator()(FCLASS_S inst)
Definition: EmulateInstructionRISCV.cpp:1378
lldb_private::Rs::Read
llvm::Optional< uint64_t > Read(EmulateInstructionRISCV &emulator)
Definition: EmulateInstructionRISCV.cpp:132