24#include "llvm/ADT/STLExtras.h"
25#include "llvm/Support/MathExtras.h"
42template <
typename... Ts>
43static std::optional<std::tuple<Ts...>>
zipOpt(std::optional<Ts> &&...ts) {
44 if ((ts.has_value() && ...))
45 return std::optional<std::tuple<Ts...>>(std::make_tuple(std::move(*ts)...));
53constexpr uint32_t
BEQ = 0b000;
54constexpr uint32_t
BNE = 0b001;
55constexpr uint32_t
BLT = 0b100;
56constexpr uint32_t
BGE = 0b101;
57constexpr uint32_t
BLTU = 0b110;
58constexpr uint32_t
BGEU = 0b111;
61constexpr int32_t
SignExt(uint32_t imm) {
return int32_t(imm); }
65constexpr std::enable_if_t<
sizeof(T) <= 4, uint64_t>
SextW(T value) {
66 return uint64_t(int64_t(int32_t(value)));
70template <
typename T>
constexpr uint64_t
ZextD(T value) {
71 return uint64_t(value);
75 return (uint64_t(int64_t(int32_t(inst & 0x80000000)) >> 11))
77 | ((inst >> 9) & 0x800)
78 | ((inst >> 20) & 0x7fe);
82 return int64_t(int32_t(inst)) >> 20;
86 return (uint64_t(int64_t(int32_t(inst & 0x80000000)) >> 19))
87 | ((inst & 0x80) << 4)
88 | ((inst >> 20) & 0x7e0)
89 | ((inst >> 7) & 0x1e);
93 return (uint64_t(int64_t(int32_t(inst & 0xFE000000)) >> 20))
94 | ((inst & 0xF80) >> 7);
98 return SextW(inst & 0xFFFFF000);
104 if (reg_encode >= 1 && reg_encode <= 31)
110 if (reg_encode <= 31)
116static std::optional<RegisterInfo>
118 uint32_t reg_encode) {
142 registerValue.
SetUInt64(value.bitcastToAPInt().getZExtValue());
156 return transformOptional(
157 Read(emulator), [](uint64_t value) {
return int32_t(uint32_t(value)); });
161 return transformOptional(
Read(emulator),
162 [](uint64_t value) {
return int64_t(value); });
166 return transformOptional(
Read(emulator),
167 [](uint64_t value) {
return uint32_t(value); });
177 APInt api(64,
bits,
false);
178 return APFloat(isDouble ? APFloat(api.bitsToDouble())
179 : APFloat(api.bitsToFloat()));
182static bool CompareB(uint64_t rs1, uint64_t rs2, uint32_t funct3) {
189 return int64_t(rs1) < int64_t(rs2);
191 return int64_t(rs1) >= int64_t(rs2);
197 llvm_unreachable(
"unexpected funct3");
203 std::is_same_v<T, LB> || std::is_same_v<T, LH> || std::is_same_v<T, LW> ||
204 std::is_same_v<T, LD> || std::is_same_v<T, LBU> || std::is_same_v<T, LHU> ||
205 std::is_same_v<T, LWU>;
208constexpr bool is_store = std::is_same_v<T, SB> || std::is_same_v<T, SH> ||
209 std::is_same_v<T, SW> || std::is_same_v<T, SD>;
213 std::is_same_v<T, AMOADD_W> || std::is_same_v<T, AMOADD_D>;
217 std::is_same_v<T, AMOXOR_W> || std::is_same_v<T, AMOXOR_D> ||
218 std::is_same_v<T, AMOAND_W> || std::is_same_v<T, AMOAND_D> ||
219 std::is_same_v<T, AMOOR_W> || std::is_same_v<T, AMOOR_D>;
223 std::is_same_v<T, AMOSWAP_W> || std::is_same_v<T, AMOSWAP_D>;
227 std::is_same_v<T, AMOMIN_W> || std::is_same_v<T, AMOMIN_D> ||
228 std::is_same_v<T, AMOMAX_W> || std::is_same_v<T, AMOMAX_D> ||
229 std::is_same_v<T, AMOMINU_W> || std::is_same_v<T, AMOMINU_D> ||
230 std::is_same_v<T, AMOMAXU_W> || std::is_same_v<T, AMOMAXU_D>;
233static std::enable_if_t<is_load<I> ||
is_store<I>, std::optional<uint64_t>>
235 return transformOptional(inst.rs1.Read(emulator), [&](uint64_t rs1) {
236 return rs1 + uint64_t(SignExt(inst.imm));
241template <
typename I,
typename T,
typename E>
242static std::enable_if_t<is_load<I>,
bool>
252 std::optional<RegisterInfo> reg_info_rs1 =
268 bool success =
false;
274 return inst.rd.Write(emulator, extend(E(T(value))));
277template <
typename I,
typename T>
278static std::enable_if_t<is_store<I>,
bool>
288 std::optional<RegisterInfo> reg_info_rs1 =
290 std::optional<RegisterInfo> reg_info_rs2 =
293 if (!reg_info_rs1 || !reg_info_rs2)
307 return transformOptional(inst.rs2.Read(emulator),
309 return emulator.WriteMemoryUnsigned(
310 context, *addr, rs2, sizeof(T));
318 std::optional<uint64_t>>
320 return transformOptional(inst.rs1.Read(emulator),
322 return rs1 % align == 0
323 ? std::optional<uint64_t>(rs1)
326 .value_or(std::nullopt);
329template <
typename I,
typename T>
330static std::enable_if_t<is_amo_swap<I>,
bool>
332 uint64_t (*extend)(T)) {
333 auto addr =
AtomicAddr(emulator, inst, align);
336 return transformOptional(
339 auto [tmp, rs2] = tup;
340 return emulator.WriteMem<T>(*addr, T(rs2)) &&
341 inst.rd.Write(emulator, extend(tmp));
346template <
typename I,
typename T>
347static std::enable_if_t<is_amo_add<I>,
bool>
349 uint64_t (*extend)(T)) {
350 auto addr =
AtomicAddr(emulator, inst, align);
353 return transformOptional(
356 auto [tmp, rs2] = tup;
357 return emulator.WriteMem<T>(*addr, T(tmp + rs2)) &&
358 inst.rd.Write(emulator, extend(tmp));
363template <
typename I,
typename T>
364static std::enable_if_t<is_amo_bit_op<I>,
bool>
366 uint64_t (*extend)(T), T (*operate)(T, T)) {
367 auto addr =
AtomicAddr(emulator, inst, align);
370 return transformOptional(
373 auto [value, rs2] = tup;
374 return emulator.WriteMem<T>(*addr, operate(value, T(rs2))) &&
375 inst.rd.Write(emulator, extend(value));
380template <
typename I,
typename T>
381static std::enable_if_t<is_amo_cmp<I>,
bool>
383 uint64_t (*extend)(T), T (*cmp)(T, T)) {
384 auto addr =
AtomicAddr(emulator, inst, align);
387 return transformOptional(
390 auto [value, rs2] = tup;
391 return emulator.WriteMem<T>(*addr, cmp(value, T(rs2))) &&
392 inst.rd.Write(emulator, extend(value));
408 auto current_pc = *
pc;
409 const auto entry_pc = current_pc;
413 if (!inst || (!std::holds_alternative<LR_W>(inst->decoded) &&
414 !std::holds_alternative<LR_D>(inst->decoded)))
419 if (!inst || !std::holds_alternative<B>(inst->decoded))
421 auto bne_exit = std::get<B>(inst->decoded);
422 if (bne_exit.funct3 !=
BNE)
425 const auto exit_pc = current_pc +
SextW(bne_exit.imm);
429 if (!inst || (!std::holds_alternative<SC_W>(inst->decoded) &&
430 !std::holds_alternative<SC_D>(inst->decoded)))
435 if (!inst || !std::holds_alternative<B>(inst->decoded))
437 auto bne_start = std::get<B>(inst->decoded);
438 if (bne_start.funct3 !=
BNE)
440 if (entry_pc != current_pc +
SextW(bne_start.imm))
445 return exit_pc == current_pc && emulator.
WritePC(current_pc);
688 uint16_t try_rvc = uint16_t(inst & 0x0000ffff);
689 uint8_t inst_type =
RV64;
693 bool is_16b = (inst & 0b11) != 0b11;
694 bool is_32b = (inst & 0x1f) != 0x1f;
695 bool is_48b = (inst & 0x3f) != 0x1f;
696 bool is_64b = (inst & 0x7f) != 0x3f;
715 if ((inst & pat.type_mask) == pat.eigen &&
716 (inst_type & pat.inst_type) != 0) {
718 "EmulateInstructionRISCV::%s: inst(%x at %" PRIx64
719 ") was decoded to %s",
720 __FUNCTION__, inst,
m_addr, pat.name);
721 auto decoded = is_16b ? pat.decode(try_rvc) : pat.decode(inst);
725 LLDB_LOGF(log,
"EmulateInstructionRISCV::%s: inst(0x%x) was unsupported",
737 static uint64_t
size(
bool is_rvc) {
return is_rvc ? 2 : 4; }
748 return transformOptional(
m_emu.ReadPC(),
750 return inst.rd.Write(m_emu,
751 SignExt(inst.imm) + pc);
756 return transformOptional(
m_emu.ReadPC(),
758 return inst.rd.Write(m_emu, pc + delta()) &&
759 m_emu.WritePC(SignExt(inst.imm) + pc);
766 auto [pc, rs1] = tup;
767 return inst.rd.Write(m_emu, pc + delta()) &&
768 m_emu.WritePC((SignExt(inst.imm) + rs1) &
777 auto [pc, rs1, rs2] = tup;
779 CompareB(rs1, rs2, inst.funct3))
780 return m_emu.WritePC(SignExt(inst.imm) + pc);
804 return transformOptional(
805 inst.rs1.ReadI64(
m_emu),
807 int64_t result = rs1 + int64_t(SignExt(inst.imm));
809 if (inst.rd.rd == RISCV_GPR_SP &&
810 inst.rs1.rs == RISCV_GPR_SP) {
811 EmulateInstruction::Context context;
813 EmulateInstruction::eContextAdjustStackPointer;
814 context.SetImmediateSigned(SignExt(inst.imm));
815 uint32_t sp_lldb_reg = GPREncodingToLLDB(RISCV_GPR_SP);
816 RegisterValue registerValue;
817 registerValue.SetUInt64(result);
818 return m_emu.WriteRegister(context, eRegisterKindLLDB,
819 sp_lldb_reg, registerValue);
825 EmulateInstruction::Context context;
826 context.type = EmulateInstruction::eContextSetFramePointer;
827 auto sp_reg_info = m_emu.GetRegisterInfo(
828 eRegisterKindLLDB, GPREncodingToLLDB(RISCV_GPR_SP));
830 context.SetRegisterPlusOffset(*sp_reg_info,
837 fp_lldb_reg, registerValue);
840 return inst.rd.Write(
m_emu, result);
845 return transformOptional(inst.rs1.ReadI64(
m_emu),
847 return inst.rd.Write(
848 m_emu, rs1 < int64_t(SignExt(inst.imm)));
853 return transformOptional(inst.rs1.Read(
m_emu),
855 return inst.rd.Write(
856 m_emu, rs1 < uint64_t(SignExt(inst.imm)));
861 return transformOptional(inst.rs1.Read(
m_emu),
863 return inst.rd.Write(
864 m_emu, rs1 ^ uint64_t(SignExt(inst.imm)));
869 return transformOptional(inst.rs1.Read(
m_emu),
871 return inst.rd.Write(
872 m_emu, rs1 | uint64_t(SignExt(inst.imm)));
877 return transformOptional(inst.rs1.Read(
m_emu),
879 return inst.rd.Write(
880 m_emu, rs1 & uint64_t(SignExt(inst.imm)));
885 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
887 auto [rs1, rs2] = tup;
888 return inst.rd.Write(m_emu, rs1 + rs2);
893 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
895 auto [rs1, rs2] = tup;
896 return inst.rd.Write(m_emu, rs1 - rs2);
901 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
903 auto [rs1, rs2] = tup;
904 return inst.rd.Write(m_emu,
905 rs1 << (rs2 & 0b111111));
910 return transformOptional(
913 auto [rs1, rs2] = tup;
914 return inst.rd.Write(m_emu, rs1 < rs2);
919 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
921 auto [rs1, rs2] = tup;
922 return inst.rd.Write(m_emu, rs1 < rs2);
927 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
929 auto [rs1, rs2] = tup;
930 return inst.rd.Write(m_emu, rs1 ^ rs2);
935 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
937 auto [rs1, rs2] = tup;
938 return inst.rd.Write(m_emu,
939 rs1 >> (rs2 & 0b111111));
944 return transformOptional(
947 auto [rs1, rs2] = tup;
948 return inst.rd.Write(m_emu, rs1 >> (rs2 & 0b111111));
953 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
955 auto [rs1, rs2] = tup;
956 return inst.rd.Write(m_emu, rs1 | rs2);
961 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
963 auto [rs1, rs2] = tup;
964 return inst.rd.Write(m_emu, rs1 & rs2);
976 return transformOptional(inst.rs1.Read(
m_emu),
978 return inst.rd.Write(m_emu, rs1 << inst.shamt);
983 return transformOptional(inst.rs1.Read(
m_emu),
985 return inst.rd.Write(m_emu, rs1 >> inst.shamt);
990 return transformOptional(inst.rs1.ReadI64(
m_emu),
992 return inst.rd.Write(m_emu, rs1 >> inst.shamt);
997 return transformOptional(inst.rs1.ReadI32(
m_emu),
999 return inst.rd.Write(
1000 m_emu, SextW(rs1 + SignExt(inst.imm)));
1005 return transformOptional(inst.rs1.ReadU32(
m_emu),
1007 return inst.rd.Write(m_emu,
1008 SextW(rs1 << inst.shamt));
1013 return transformOptional(inst.rs1.ReadU32(
m_emu),
1015 return inst.rd.Write(m_emu,
1016 SextW(rs1 >> inst.shamt));
1021 return transformOptional(inst.rs1.ReadI32(
m_emu),
1023 return inst.rd.Write(m_emu,
1024 SextW(rs1 >> inst.shamt));
1029 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
1031 auto [rs1, rs2] = tup;
1032 return inst.rd.Write(m_emu,
1033 SextW(uint32_t(rs1 + rs2)));
1038 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
1040 auto [rs1, rs2] = tup;
1041 return inst.rd.Write(m_emu,
1042 SextW(uint32_t(rs1 - rs2)));
1047 return transformOptional(
1050 auto [rs1, rs2] = tup;
1051 return inst.rd.Write(m_emu, SextW(rs1 << (rs2 & 0b11111)));
1056 return transformOptional(
1059 auto [rs1, rs2] = tup;
1060 return inst.rd.Write(m_emu, SextW(rs1 >> (rs2 & 0b11111)));
1065 return transformOptional(
1068 auto [rs1, rs2] = tup;
1069 return inst.rd.Write(m_emu, SextW(rs1 >> (rs2 & 0b11111)));
1075 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
1077 auto [rs1, rs2] = tup;
1078 return inst.rd.Write(m_emu, rs1 * rs2);
1083 return transformOptional(
1086 auto [rs1, rs2] = tup;
1088 auto mul = APInt(128, rs1, true) * APInt(128, rs2, true);
1089 return inst.rd.Write(m_emu,
1090 mul.ashr(64).trunc(64).getZExtValue());
1095 return transformOptional(
1098 auto [rs1, rs2] = tup;
1101 APInt(128, rs1, true).zext(128) * APInt(128, rs2, false);
1102 return inst.rd.Write(m_emu,
1103 mul.lshr(64).trunc(64).getZExtValue());
1108 return transformOptional(
1111 auto [rs1, rs2] = tup;
1113 auto mul = APInt(128, rs1, false) * APInt(128, rs2, false);
1114 return inst.rd.Write(m_emu,
1115 mul.lshr(64).trunc(64).getZExtValue());
1120 return transformOptional(
1123 auto [dividend, divisor] = tup;
1126 return inst.rd.Write(m_emu, UINT64_MAX);
1128 if (dividend == INT64_MIN && divisor == -1)
1129 return inst.rd.Write(m_emu, dividend);
1131 return inst.rd.Write(m_emu, dividend / divisor);
1136 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
1138 auto [dividend, divisor] = tup;
1141 return inst.rd.Write(m_emu, UINT64_MAX);
1143 return inst.rd.Write(m_emu, dividend / divisor);
1148 return transformOptional(
1151 auto [dividend, divisor] = tup;
1154 return inst.rd.Write(m_emu, dividend);
1156 if (dividend == INT64_MIN && divisor == -1)
1157 return inst.rd.Write(m_emu, 0);
1159 return inst.rd.Write(m_emu, dividend % divisor);
1164 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
1166 auto [dividend, divisor] = tup;
1169 return inst.rd.Write(m_emu, dividend);
1171 return inst.rd.Write(m_emu, dividend % divisor);
1176 return transformOptional(
1179 auto [rs1, rs2] = tup;
1180 return inst.rd.Write(m_emu, SextW(rs1 * rs2));
1185 return transformOptional(
1188 auto [dividend, divisor] = tup;
1191 return inst.rd.Write(m_emu, UINT64_MAX);
1193 if (dividend == INT32_MIN && divisor == -1)
1194 return inst.rd.Write(m_emu, SextW(dividend));
1196 return inst.rd.Write(m_emu, SextW(dividend / divisor));
1201 return transformOptional(
1204 auto [dividend, divisor] = tup;
1207 return inst.rd.Write(m_emu, UINT64_MAX);
1209 return inst.rd.Write(m_emu, SextW(dividend / divisor));
1214 return transformOptional(
1217 auto [dividend, divisor] = tup;
1220 return inst.rd.Write(m_emu, SextW(dividend));
1222 if (dividend == INT32_MIN && divisor == -1)
1223 return inst.rd.Write(m_emu, 0);
1225 return inst.rd.Write(m_emu, SextW(dividend % divisor));
1230 return transformOptional(
1233 auto [dividend, divisor] = tup;
1236 return inst.rd.Write(m_emu, SextW(dividend));
1238 return inst.rd.Write(m_emu, SextW(dividend % divisor));
1246 llvm_unreachable(
"should be handled in AtomicSequence");
1249 llvm_unreachable(
"should be handled in AtomicSequence");
1259 m_emu, inst, 4,
SextW, [](uint32_t a, uint32_t b) {
return a ^ b; });
1263 m_emu, inst, 4,
SextW, [](uint32_t a, uint32_t b) {
return a & b; });
1267 m_emu, inst, 4,
SextW, [](uint32_t a, uint32_t b) {
return a | b; });
1271 m_emu, inst, 4,
SextW, [](uint32_t a, uint32_t b) {
1272 return uint32_t(std::min(int32_t(a), int32_t(b)));
1277 m_emu, inst, 4,
SextW, [](uint32_t a, uint32_t b) {
1278 return uint32_t(std::max(int32_t(a), int32_t(b)));
1284 [](uint32_t a, uint32_t b) {
return std::min(a, b); });
1289 [](uint32_t a, uint32_t b) {
return std::max(a, b); });
1299 m_emu, inst, 8,
ZextD, [](uint64_t a, uint64_t b) {
return a ^ b; });
1303 m_emu, inst, 8,
ZextD, [](uint64_t a, uint64_t b) {
return a & b; });
1307 m_emu, inst, 8,
ZextD, [](uint64_t a, uint64_t b) {
return a | b; });
1311 m_emu, inst, 8,
ZextD, [](uint64_t a, uint64_t b) {
1312 return uint64_t(std::min(int64_t(a), int64_t(b)));
1317 m_emu, inst, 8,
ZextD, [](uint64_t a, uint64_t b) {
1318 return uint64_t(std::max(int64_t(a), int64_t(b)));
1324 [](uint64_t a, uint64_t b) {
return std::min(a, b); });
1329 [](uint64_t a, uint64_t b) {
return std::max(a, b); });
1331 template <
typename T>
1332 bool F_Load(T inst,
const fltSemantics &(*semantics)(),
1333 unsigned int numBits) {
1334 return transformOptional(inst.rs1.Read(
m_emu),
1336 uint64_t addr = rs1 + uint64_t(inst.imm);
1337 uint64_t bits = *m_emu.ReadMem<uint64_t>(addr);
1338 APFloat f(semantics(), APInt(numBits, bits));
1339 return inst.rd.WriteAPFloat(m_emu, f);
1344 template <
typename T>
bool F_Store(T inst,
bool isDouble) {
1345 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu),
1346 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1348 auto [rs1, rs2] = tup;
1349 uint64_t addr = rs1 + uint64_t(inst.imm);
1351 rs2.bitcastToAPInt().getZExtValue();
1352 return m_emu.WriteMem<uint64_t>(addr, bits);
1359 auto opStatus = rs1.fusedMultiplyAdd(rs2, rs3,
m_emu.GetRoundingMode());
1360 auto res =
m_emu.SetAccruedExceptions(opStatus);
1363 template <
typename T>
1364 bool FMA(T inst,
bool isDouble,
float rs2_sign,
float rs3_sign) {
1365 return transformOptional(
zipOpt(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1366 inst.rs2.ReadAPFloat(
m_emu, isDouble),
1367 inst.rs3.ReadAPFloat(
m_emu, isDouble)),
1369 auto [rs1, rs2, rs3] = tup;
1370 rs2.copySign(APFloat(rs2_sign));
1371 rs3.copySign(APFloat(rs3_sign));
1372 auto [res, f] = FusedMultiplyAdd(rs1, rs2, rs3);
1373 return res && inst.rd.WriteAPFloat(m_emu, f);
1381 template <
typename T>
1383 APFloat::opStatus (APFloat::*f)(
const APFloat &RHS,
1384 APFloat::roundingMode RM)) {
1385 return transformOptional(
zipOpt(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1386 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1388 auto [rs1, rs2] = tup;
1390 ((&rs1)->*f)(rs2, m_emu.GetRoundingMode());
1391 inst.rd.WriteAPFloat(m_emu, rs1);
1392 return m_emu.SetAccruedExceptions(res);
1404 template <
typename T>
bool F_SignInj(T inst,
bool isDouble,
bool isNegate) {
1405 return transformOptional(
zipOpt(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1406 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1408 auto [rs1, rs2] = tup;
1412 return inst.rd.WriteAPFloat(m_emu, rs1);
1419 return transformOptional(
zipOpt(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1420 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1422 auto [rs1, rs2] = tup;
1427 if (rs1.isNegative() == rs2.isNegative()) {
1433 return inst.rd.WriteAPFloat(
m_emu, rs1);
1438 template <
typename T>
1440 APFloat (*f)(
const APFloat &A,
const APFloat &
B)) {
1441 return transformOptional(
1443 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1445 auto [rs1, rs2] = tup;
1450 if (rs1.isNaN() || rs2.isNaN())
1451 m_emu.SetAccruedExceptions(APFloat::opInvalidOp);
1452 if (rs1.isNaN() && rs2.isNaN()) {
1453 auto canonicalNaN = APFloat::getQNaN(rs1.getSemantics());
1454 return inst.rd.WriteAPFloat(m_emu, canonicalNaN);
1456 return inst.rd.WriteAPFloat(
m_emu, f(rs1, rs2));
1464 &APFloat::convertToFloat);
1468 &APFloat::convertToFloat);
1470 template <
typename T>
bool FMV_f2i(T inst,
bool isDouble) {
1471 return transformOptional(
1472 inst.rs1.ReadAPFloat(
m_emu, isDouble),
1476 return inst.rd.Write(m_emu, 0x7ff8'0000'0000'0000);
1478 return inst.rd.Write(m_emu, 0x7fc0'0000);
1480 auto bits = rs1.bitcastToAPInt().getZExtValue();
1484 return inst.rd.Write(
m_emu, uint64_t(
bits & 0xffff'ffff));
1495 return transformOptional(
1497 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1499 auto [rs1, rs2] = tup;
1500 if (rs1.isNaN() || rs2.isNaN()) {
1502 if (rs1.isSignaling() || rs2.isSignaling()) {
1504 m_emu.SetAccruedExceptions(APFloat::opInvalidOp);
1505 return res && inst.rd.Write(m_emu, 0);
1508 auto res = m_emu.SetAccruedExceptions(APFloat::opInvalidOp);
1509 return res && inst.rd.Write(m_emu, 0);
1513 return inst.rd.Write(
m_emu,
1514 rs1.compare(rs2) == APFloat::cmpEqual);
1516 return inst.rd.Write(
m_emu, rs1.compare(rs2) ==
1517 APFloat::cmpLessThan);
1519 return inst.rd.Write(
m_emu, rs1.compare(rs2) !=
1520 APFloat::cmpGreaterThan);
1522 llvm_unreachable(
"unsupported F_CMP");
1530 template <
typename T>
bool FCLASS(T inst,
bool isDouble) {
1531 return transformOptional(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1533 uint64_t result = 0;
1534 if (rs1.isInfinity() && rs1.isNegative())
1537 if (rs1.isNormal() && rs1.isNegative())
1540 if (rs1.isDenormal() && rs1.isNegative())
1542 if (rs1.isNegZero())
1544 if (rs1.isPosZero())
1547 if (rs1.isNormal() && !rs1.isNegative())
1550 if (rs1.isDenormal() && !rs1.isNegative())
1552 if (rs1.isInfinity() && !rs1.isNegative())
1555 if (rs1.isSignaling())
1560 return inst.rd.Write(
m_emu, result);
1565 template <
typename T,
typename E>
1567 const fltSemantics &semantics) {
1568 return transformOptional(((&inst.rs1)->*f)(
m_emu),
1570 APFloat apf(semantics, rs1);
1571 return inst.rd.WriteAPFloat(m_emu, apf);
1581 template <
typename T,
typename E>
1582 bool FMV_i2f(T inst,
unsigned int numBits, E (APInt::*f)()
const) {
1583 return transformOptional(inst.rs1.Read(
m_emu),
1585 APInt apInt(numBits, rs1);
1587 apInt = APInt(numBits, NanUnBoxing(rs1));
1588 APFloat apf((&apInt->*f)());
1589 return inst.rd.WriteAPFloat(m_emu, apf);
1594 return FMV_i2f(inst, 32, &APInt::bitsToFloat);
1596 template <
typename I,
typename E,
typename T>
1597 bool FCVT_i2f(I inst,
bool isDouble, T (APFloat::*f)()
const) {
1598 return transformOptional(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1600 E res = E((&rs1->*f)());
1601 return inst.rd.Write(m_emu, uint64_t(res));
1607 &APFloat::convertToFloat);
1611 &APFloat::convertToFloat);
1639 return transformOptional(inst.rs1.ReadAPFloat(
m_emu,
true),
1641 double d = rs1.convertToDouble();
1642 APFloat apf((float(d)));
1643 return inst.rd.WriteAPFloat(m_emu, apf);
1648 return transformOptional(inst.rs1.ReadAPFloat(
m_emu,
false),
1650 float f = rs1.convertToFloat();
1651 APFloat apf((double(f)));
1652 return inst.rd.WriteAPFloat(m_emu, apf);
1662 &APFloat::convertToDouble);
1666 &APFloat::convertToDouble);
1676 &APFloat::convertToDouble);
1680 &APFloat::convertToDouble);
1690 return FMV_i2f(inst, 64, &APInt::bitsToDouble);
1704 bool increase_pc = options & eEmulateInstructionOptionAutoAdvancePC;
1705 bool ignore_cond = options & eEmulateInstructionOptionIgnoreConditions;
1723 return new_pc != old_pc ||
1727std::optional<DecodeResult>
1730 [&](uint32_t inst) {
return Decode(inst); })
1731 .value_or(std::nullopt);
1751 bool success =
false;
1755 return RoundingMode::Invalid;
1756 auto frm = (fcsr >> 5) & 0x7;
1759 return RoundingMode::NearestTiesToEven;
1761 return RoundingMode::TowardZero;
1763 return RoundingMode::TowardNegative;
1765 return RoundingMode::TowardPositive;
1767 return RoundingMode::Dynamic;
1770 return RoundingMode::Invalid;
1775 APFloatBase::opStatus opStatus) {
1776 bool success =
false;
1782 case APFloatBase::opInvalidOp:
1785 case APFloatBase::opDivByZero:
1788 case APFloatBase::opOverflow:
1791 case APFloatBase::opUnderflow:
1794 case APFloatBase::opInexact:
1797 case APFloatBase::opOK:
1806std::optional<RegisterInfo>
1808 uint32_t reg_index) {
1810 switch (reg_index) {
1830 llvm_unreachable(
"unsupported register");
1842 return array[reg_index];
1853 uint32_t inst_data = 0;
1854 const void *opcode_data =
m_opcode.GetOpcodeBytes();
1860 const uint16_t *data =
static_cast<const uint16_t *
>(opcode_data);
1862 }
else if (
m_opcode.GetByteSize() == 4) {
1864 const uint32_t *data =
static_cast<const uint32_t *
>(opcode_data);
1871 auto decoded_inst =
Decode(inst_data);
1882 unwind_plan.
Clear();
1939 auto pc = riscv_emulator->
ReadPC();
1941 status =
Status(
"Can't read PC");
1961 "RISCVSingleStepBreakpointLocationsPredictor::%s: can't find "
1962 "corresponding load reserve instruction",
1964 return {*
pc + (inst->is_rvc ? 2u : 4u)};
1970llvm::Expected<unsigned>
1977 return inst->is_rvc ? 2 : 4;
1982 return *last_instr_size;
1999 pc += lr_inst->is_rvc ? 2 : 4;
2001 size_t atomic_length = 0;
2002 std::optional<DecodeResult> inst;
2003 std::vector<lldb::addr_t> bp_addrs;
2011 if (
B *branch = std::get_if<B>(&inst->decoded))
2012 bp_addrs.push_back(
pc +
SignExt(branch->imm));
2014 unsigned addent = inst->is_rvc ? 2 : 4;
2016 atomic_length += addent;
2026 "RISCVSingleStepBreakpointLocationsPredictor::%s: can't find "
2027 "corresponding store conditional instruction",
2029 return {entry_pc + (lr_inst->is_rvc ? 2u : 4u)};
2039 B *branch = std::get_if<B>(&inst->decoded);
2040 if (branch && (exit_pc +
SignExt(branch->
imm)) == entry_pc)
2041 exit_pc += inst->is_rvc ? 2 : 4;
2047 bp_addrs, [exit_pc](
lldb::addr_t bp_addr) {
return exit_pc >= bp_addr; });
2050 bp_addrs.push_back(exit_pc);
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOGF(log,...)
#define LLDB_PLUGIN_DEFINE_ADV(ClassName, PluginName)
uint32_t GetRegisterCount() const override
const lldb_private::RegisterInfo * GetRegisterInfo() const override
A section + offset based address class.
An architecture specification class.
llvm::Triple & GetTriple()
Architecture triple accessor.
std::optional< DecodeResult > ReadInstructionAt(lldb::addr_t addr)
EmulateInstructionRISCV(const ArchSpec &arch)
std::optional< RegisterInfo > GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num) override
bool SetTargetTriple(const ArchSpec &arch) override
bool SetAccruedExceptions(llvm::APFloatBase::opStatus)
std::optional< uint32_t > m_last_size
Last decoded instruction size estimate.
bool ReadInstruction() override
bool TestEmulation(Stream &out_stream, ArchSpec &arch, OptionValueDictionary *test_data) override
static llvm::StringRef GetPluginNameStatic()
static bool SupportsThisArch(const ArchSpec &arch)
llvm::RoundingMode GetRoundingMode()
std::optional< DecodeResult > Decode(uint32_t inst)
bool CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) override
static llvm::StringRef GetPluginDescriptionStatic()
bool Execute(DecodeResult inst, bool ignore_cond)
std::enable_if_t< std::is_integral_v< T >, std::optional< T > > ReadMem(uint64_t addr)
std::optional< uint32_t > GetLastInstrSize() override
bool EvaluateInstruction(uint32_t options) override
bool SetInstruction(const Opcode &opcode, const Address &inst_addr, Target *target) override
static lldb_private::EmulateInstruction * CreateInstance(const lldb_private::ArchSpec &arch, InstructionType inst_type)
static bool SupportsThisInstructionType(InstructionType inst_type)
DecodeResult m_decoded
Last decoded instruction from m_opcode.
"lldb/Core/EmulateInstruction.h" A class that allows emulation of CPU opcodes.
@ eContextPushRegisterOnStack
@ eContextPopRegisterOffStack
lldb::ByteOrder GetByteOrder() const
std::optional< lldb::addr_t > ReadPC()
std::optional< RegisterValue > ReadRegister(const RegisterInfo ®_info)
bool WriteRegister(const Context &context, const RegisterInfo &ref_info, const RegisterValue ®_value)
bool WriteRegisterUnsigned(const Context &context, const RegisterInfo ®_info, uint64_t reg_value)
bool WritePC(lldb::addr_t addr)
uint64_t ReadMemoryUnsigned(const Context &context, lldb::addr_t addr, size_t byte_size, uint64_t fail_value, bool *success_ptr)
virtual bool SetInstruction(const Opcode &insn_opcode, const Address &inst_addr, Target *target)
uint64_t ReadRegisterUnsigned(const RegisterInfo ®_info, uint64_t fail_value, bool *success_ptr)
bool operator()(FEQ_S inst)
bool operator()(REM inst)
bool operator()(AUIPC inst)
bool operator()(FLE_D inst)
bool operator()(FMSUB_S inst)
bool operator()(FMADD_S inst)
bool F_Op(T inst, bool isDouble, APFloat::opStatus(APFloat::*f)(const APFloat &RHS, APFloat::roundingMode RM))
bool operator()(MULHSU inst)
bool operator()(AMOSWAP_W inst)
bool operator()(DIVUW inst)
bool operator()(SUBW inst)
bool operator()(XOR inst)
bool operator()(JAL inst)
bool operator()(AMOMAX_D inst)
bool F_Compare(T inst, bool isDouble, F_CMP cmp)
bool operator()(SLTIU inst)
bool operator()(DIVU inst)
bool operator()(FMADD_D inst)
bool operator()(FSD inst)
bool operator()(FCVT_L_D inst)
bool operator()(AMOADD_D inst)
bool operator()(SRLIW inst)
bool operator()(MUL inst)
bool operator()(ORI inst)
bool operator()(FLD inst)
bool operator()(LWU inst)
bool operator()(FSGNJX_D inst)
bool operator()(FSW inst)
bool operator()(FMSUB_D inst)
bool operator()(FLW inst)
bool operator()(FADD_S inst)
bool operator()(FADD_D inst)
bool operator()(FCVT_LU_D inst)
bool operator()(LUI inst)
static uint64_t size(bool is_rvc)
bool operator()(FCVT_L_S inst)
bool operator()(AMOMAXU_D inst)
bool operator()(FSGNJX_S inst)
bool operator()(FCVT_D_WU inst)
bool operator()(FDIV_D inst)
bool operator()(REMW inst)
bool operator()(FMIN_S inst)
bool operator()(FCVT_S_W inst)
bool operator()(ADDIW inst)
bool operator()(SRLW inst)
bool operator()(SRAIW inst)
bool operator()(FMUL_S inst)
bool operator()(AMOAND_D inst)
bool operator()(FEQ_D inst)
bool operator()(AMOXOR_W inst)
bool operator()(SRAI inst)
bool operator()(AMOMINU_D inst)
bool operator()(FNMSUB_S inst)
bool F_SignInjXor(T inst, bool isDouble)
bool FMA(T inst, bool isDouble, float rs2_sign, float rs3_sign)
bool operator()(REMUW inst)
bool operator()(FSUB_S inst)
bool operator()(FMIN_D inst)
bool operator()(JALR inst)
bool operator()(FSUB_D inst)
bool operator()(AMOMIN_D inst)
bool operator()(FMV_D_X inst)
bool operator()(MULW inst)
bool operator()(FSGNJ_D inst)
bool operator()(FCVT_S_L inst)
bool operator()(FCVT_WU_D inst)
bool operator()(FSGNJN_D inst)
bool operator()(SLT inst)
bool operator()(FMAX_S inst)
bool FCLASS(T inst, bool isDouble)
EmulateInstructionRISCV & m_emu
bool operator()(SRAW inst)
bool operator()(FCVT_S_LU inst)
bool operator()(FCVT_D_LU inst)
bool operator()(SRA inst)
bool operator()(FNMSUB_D inst)
bool operator()(SLLI inst)
bool operator()(RESERVED inst)
bool operator()(FLT_D inst)
bool operator()(DIVW inst)
bool operator()(AMOAND_W inst)
bool operator()(HINT inst)
bool operator()(SLLW inst)
bool operator()(FMV_W_X inst)
bool operator()(SLTI inst)
bool operator()(FSGNJ_S inst)
bool operator()(FCVT_LU_S inst)
bool operator()(FMV_X_D inst)
bool operator()(MULH inst)
bool F_Store(T inst, bool isDouble)
bool operator()(FCVT_W_S inst)
bool FCVT_i2f(I inst, bool isDouble, T(APFloat::*f)() const)
bool operator()(FCLASS_S inst)
bool operator()(AMOXOR_D inst)
bool F_SignInj(T inst, bool isDouble, bool isNegate)
bool operator()(SLLIW inst)
bool operator()(AMOOR_W inst)
bool operator()(FLT_S inst)
bool operator()(AMOMAX_W inst)
bool operator()(ADDW inst)
bool operator()(INVALID inst)
bool FMV_i2f(T inst, unsigned int numBits, E(APInt::*f)() const)
bool operator()(LHU inst)
bool operator()(FMV_X_W inst)
bool operator()(FNMADD_S inst)
bool FCVT_f2i(T inst, std::optional< E >(Rs::*f)(EmulateInstructionRISCV &emu), const fltSemantics &semantics)
bool operator()(FCVT_D_S inst)
bool operator()(FCVT_S_WU inst)
bool operator()(SUB inst)
bool operator()(AMOMINU_W inst)
bool operator()(FCVT_WU_S inst)
bool operator()(AMOSWAP_D inst)
bool operator()(FMUL_D inst)
bool operator()(FLE_S inst)
bool operator()(FMAX_D inst)
bool operator()(AMOMAXU_W inst)
bool operator()(FCLASS_D inst)
bool operator()(ANDI inst)
bool operator()(SRL inst)
bool operator()(EBREAK inst)
bool operator()(SLL inst)
bool operator()(AMOMIN_W inst)
bool operator()(AMOADD_W inst)
bool operator()(SRLI inst)
bool operator()(FCVT_S_D inst)
bool operator()(FSGNJN_S inst)
bool operator()(XORI inst)
bool F_MAX_MIN(T inst, bool isDouble, APFloat(*f)(const APFloat &A, const APFloat &B))
bool operator()(AND inst)
bool operator()(LBU inst)
bool operator()(FSQRT_S inst)
bool operator()(FDIV_S inst)
bool F_Load(T inst, const fltSemantics &(*semantics)(), unsigned int numBits)
bool operator()(ADD inst)
bool operator()(AMOOR_D inst)
bool operator()(MULHU inst)
bool operator()(FCVT_W_D inst)
bool operator()(DIV inst)
bool operator()(FCVT_D_L inst)
bool operator()(FCVT_D_W inst)
bool operator()(FNMADD_D inst)
bool operator()(SLTU inst)
bool FMV_f2i(T inst, bool isDouble)
std::tuple< bool, APFloat > FusedMultiplyAdd(APFloat rs1, APFloat rs2, APFloat rs3)
bool operator()(REMU inst)
bool operator()(NOP inst)
bool operator()(ADDI inst)
bool operator()(FSQRT_D inst)
Executor(EmulateInstructionRISCV &emulator, bool ignoreCond, bool is_rvc)
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
static bool FoundLoadReserve(const RISCVInst &inst)
BreakpointLocations GetBreakpointLocations(Status &status) override
static bool FoundStoreConditional(const RISCVInst &inst)
BreakpointLocations HandleAtomicSequence(lldb::addr_t pc, Status &error)
static constexpr size_t s_max_atomic_sequence_length
llvm::Expected< unsigned > GetBreakpointSize(lldb::addr_t bp_addr) override
void SetUInt64(uint64_t uint, Type t=eTypeUInt64)
uint64_t GetAsUInt64(uint64_t fail_value=UINT64_MAX, bool *success_ptr=nullptr) const
std::unique_ptr< EmulateInstruction > m_emulator_up
virtual BreakpointLocations GetBreakpointLocations(Status &status)
A stream class that can stream formatted output to a file.
void SetIsRegisterPlusOffset(uint32_t reg_num, int32_t offset)
bool SetRegisterLocationToSame(uint32_t reg_num, bool must_replace)
const FAValue & GetCFAValue() const
void SetUnwindPlanForSignalTrap(lldb_private::LazyBool is_for_signal_trap)
void SetRegisterKind(lldb::RegisterKind kind)
void SetReturnAddressRegister(uint32_t regnum)
void SetSourcedFromCompiler(lldb_private::LazyBool from_compiler)
void SetSourceName(const char *)
void SetUnwindPlanValidAtAllInstructions(lldb_private::LazyBool valid_at_all_insn)
#define LLDB_REGNUM_GENERIC_RA
#define LLDB_REGNUM_GENERIC_SP
#define LLDB_INVALID_ADDRESS
#define LLDB_INVALID_REGNUM
#define LLDB_REGNUM_GENERIC_PC
#define LLDB_REGNUM_GENERIC_FP
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
static std::optional< std::tuple< Ts... > > zipOpt(std::optional< Ts > &&...ts)
Returns all values wrapped in Optional, or std::nullopt if any of the values is std::nullopt.
RISCVInst DecodeC_LD(uint32_t inst)
constexpr uint32_t DecodeIImm(uint32_t inst)
static RISCVInst DecodeRType(uint32_t inst)
RISCVInst DecodeC_SLLI(uint32_t inst)
RISCVInst DecodeC_LW(uint32_t inst)
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))
constexpr uint32_t DecodeRS2(uint32_t inst)
constexpr bool is_amo_cmp
static RISCVInst DecodeR4Type(uint32_t inst)
RISCVInst DecodeC_SUBW(uint32_t inst)
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, FLD, FSD, FMADD_D, FMSUB_D, FNMSUB_D, FNMADD_D, FADD_D, FSUB_D, FMUL_D, FDIV_D, FSQRT_D, FSGNJ_D, FSGNJN_D, FSGNJX_D, FMIN_D, FMAX_D, FCVT_S_D, FCVT_D_S, FEQ_D, FLT_D, FLE_D, FCLASS_D, FCVT_W_D, FCVT_WU_D, FCVT_D_W, FCVT_D_WU, FCVT_L_D, FCVT_LU_D, FMV_X_D, FCVT_D_L, FCVT_D_LU, FMV_D_X, INVALID, EBREAK, RESERVED, HINT, NOP > RISCVInst
RISCVInst DecodeC_ADDW(uint32_t inst)
RISCVInst DecodeC_SRLI(uint32_t inst)
static uint32_t FPREncodingToLLDB(uint32_t reg_encode)
RISCVInst DecodeC_J(uint32_t inst)
constexpr uint32_t DecodeRS3(uint32_t inst)
constexpr int32_t DecodeRM(uint32_t inst)
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))
constexpr uint32_t DecodeUImm(uint32_t inst)
static std::enable_if_t< is_store< I >, bool > Store(EmulateInstructionRISCV &emulator, I inst)
constexpr bool is_amo_swap
RISCVInst DecodeC_ADDI(uint32_t inst)
RISCVInst DecodeC_OR(uint32_t inst)
RISCVInst DecodeC_SWSP(uint32_t inst)
constexpr bool is_amo_bit_op
RISCVInst DecodeC_XOR(uint32_t inst)
static constexpr uint32_t RISCV_GPR_SP
static std::enable_if_t< is_load< I >||is_store< I >, std::optional< uint64_t > > LoadStoreAddr(EmulateInstructionRISCV &emulator, I inst)
RISCVInst DecodeC_LUI_ADDI16SP(uint32_t inst)
InstructionType
Instruction types.
static const InstrPattern PATTERNS[]
constexpr std::enable_if_t< sizeof(T)<=4, uint64_t > SextW(T value)
constexpr uint32_t DecodeRS1(uint32_t inst)
RISCVInst DecodeC_FLDSP(uint32_t inst)
constexpr uint32_t DecodeBImm(uint32_t inst)
static uint32_t GPREncodingToLLDB(uint32_t reg_encode)
static std::enable_if_t< is_amo_add< I >||is_amo_bit_op< I >||is_amo_swap< I >||is_amo_cmp< I >, std::optional< uint64_t > > AtomicAddr(EmulateInstructionRISCV &emulator, I inst, unsigned int align)
RISCVInst DecodeC_SW(uint32_t inst)
RISCVInst DecodeC_SUB(uint32_t inst)
constexpr bool is_amo_add
RISCVInst DecodeC_BEQZ(uint32_t inst)
RISCVInst DecodeC_FLWSP(uint32_t inst)
static std::optional< RegisterInfo > GPREncodingToRegisterInfo(EmulateInstructionRISCV &emulator, uint32_t reg_encode)
RISCVInst DecodeC_FSD(uint32_t inst)
RISCVInst DecodeC_ADD(uint32_t inst)
RISCVInst DecodeC_AND(uint32_t inst)
static bool CompareB(uint64_t rs1, uint64_t rs2, uint32_t funct3)
RISCVInst DecodeC_SRAI(uint32_t inst)
RISCVInst DecodeC_JR(uint32_t inst)
RISCVInst DecodeC_JALR(uint32_t inst)
RISCVInst DecodeC_FSWSP(uint32_t inst)
static std::enable_if_t< is_amo_add< I >, bool > AtomicADD(EmulateInstructionRISCV &emulator, I inst, int align, uint64_t(*extend)(T))
static RISCVInst DecodeIType(uint32_t inst)
RISCVInst DecodeC_LWSP(uint32_t inst)
static RISCVInst DecodeBType(uint32_t inst)
std::vector< lldb::addr_t > BreakpointLocations
static RISCVInst DecodeJType(uint32_t inst)
RISCVInst DecodeC_FLD(uint32_t inst)
constexpr uint32_t DecodeRD(uint32_t inst)
RISCVInst DecodeC_MV(uint32_t inst)
constexpr uint32_t DecodeSImm(uint32_t inst)
RISCVInst DecodeC_FSDSP(uint32_t inst)
bool AtomicSequence(EmulateInstructionRISCV &emulator)
constexpr int32_t SignExt(uint32_t imm)
RISCVInst DecodeC_LDSP(uint32_t inst)
RISCVInst DecodeC_FLW(uint32_t inst)
constexpr uint32_t DecodeFunct3(uint32_t inst)
RISCVInst DecodeC_ANDI(uint32_t inst)
RISCVInst DecodeC_ADDI4SPN(uint32_t inst)
constexpr uint32_t DecodeJImm(uint32_t inst)
static constexpr uint32_t RISCV_GPR_FP
RISCVInst DecodeC_FSW(uint32_t inst)
RISCVInst DecodeC_SDSP(uint32_t inst)
static RISCVInst DecodeRShamtType(uint32_t inst)
static std::enable_if_t< is_load< I >, bool > Load(EmulateInstructionRISCV &emulator, I inst, uint64_t(*extend)(E))
constexpr uint64_t ZextD(T value)
static RISCVInst DecodeRRS1Type(uint32_t inst)
static uint32_t bits(const uint32_t val, const uint32_t msbit, const uint32_t lsbit)
static std::enable_if_t< is_amo_swap< I >, bool > AtomicSwap(EmulateInstructionRISCV &emulator, I inst, int align, uint64_t(*extend)(T))
RISCVInst DecodeC_SD(uint32_t inst)
RISCVInst DecodeC_LI(uint32_t inst)
RISCVInst DecodeC_BNEZ(uint32_t inst)
static RISCVInst DecodeUType(uint32_t inst)
RISCVInst DecodeC_ADDIW(uint32_t inst)
static RISCVInst DecodeSType(uint32_t inst)
RegisterKind
Register numbering types.
@ eRegisterKindGeneric
insn ptr reg, stack ptr reg, etc not specific to any particular target
@ eRegisterKindLLDB
lldb's internal register numbers
void SetRegisterToRegisterPlusOffset(RegisterInfo data_reg, RegisterInfo base_reg, int64_t offset)
void SetAddress(lldb::addr_t address)
bool Write(EmulateInstructionRISCV &emulator, uint64_t value)
bool WriteAPFloat(EmulateInstructionRISCV &emulator, llvm::APFloat value)
Every register is described in detail including its name, alternate name (optional),...
std::optional< llvm::APFloat > ReadAPFloat(EmulateInstructionRISCV &emulator, bool isDouble)
std::optional< uint64_t > Read(EmulateInstructionRISCV &emulator)
std::optional< int64_t > ReadI64(EmulateInstructionRISCV &emulator)
std::optional< uint32_t > ReadU32(EmulateInstructionRISCV &emulator)
std::optional< int32_t > ReadI32(EmulateInstructionRISCV &emulator)