26#include "llvm/ADT/STLExtras.h"
27#include "llvm/Support/MathExtras.h"
44template <
typename... Ts>
45static std::optional<std::tuple<Ts...>>
zipOpt(std::optional<Ts> &&...ts) {
46 if ((ts.has_value() && ...))
47 return std::optional<std::tuple<Ts...>>(std::make_tuple(std::move(*ts)...));
55constexpr uint32_t
BEQ = 0b000;
56constexpr uint32_t
BNE = 0b001;
57constexpr uint32_t
BLT = 0b100;
58constexpr uint32_t
BGE = 0b101;
59constexpr uint32_t
BLTU = 0b110;
60constexpr uint32_t
BGEU = 0b111;
63constexpr int32_t
SignExt(uint32_t imm) {
return int32_t(imm); }
67constexpr std::enable_if_t<
sizeof(T) <= 4, uint64_t>
SextW(T value) {
68 return uint64_t(int64_t(int32_t(value)));
72template <
typename T>
constexpr uint64_t
ZextD(T value) {
73 return uint64_t(value);
77 return (uint64_t(int64_t(int32_t(inst & 0x80000000)) >> 11))
79 | ((inst >> 9) & 0x800)
80 | ((inst >> 20) & 0x7fe);
84 return int64_t(int32_t(inst)) >> 20;
88 return (uint64_t(int64_t(int32_t(inst & 0x80000000)) >> 19))
89 | ((inst & 0x80) << 4)
90 | ((inst >> 20) & 0x7e0)
91 | ((inst >> 7) & 0x1e);
95 return (uint64_t(int64_t(int32_t(inst & 0xFE000000)) >> 20))
96 | ((inst & 0xF80) >> 7);
100 return SextW(inst & 0xFFFFF000);
106 if (reg_encode >= 1 && reg_encode <= 31)
112 if (reg_encode <= 31)
118static std::optional<RegisterInfo>
120 uint32_t reg_encode) {
144 registerValue.
SetUInt64(value.bitcastToAPInt().getZExtValue());
158 return transformOptional(
159 Read(emulator), [](uint64_t value) {
return int32_t(uint32_t(value)); });
163 return transformOptional(
Read(emulator),
164 [](uint64_t value) {
return int64_t(value); });
168 return transformOptional(
Read(emulator),
169 [](uint64_t value) {
return uint32_t(value); });
179 APInt api(64,
bits,
false);
180 return APFloat(isDouble ? APFloat(api.bitsToDouble())
181 : APFloat(api.bitsToFloat()));
184static bool CompareB(uint64_t rs1, uint64_t rs2, uint32_t funct3) {
191 return int64_t(rs1) < int64_t(rs2);
193 return int64_t(rs1) >= int64_t(rs2);
199 llvm_unreachable(
"unexpected funct3");
205 std::is_same_v<T, LB> || std::is_same_v<T, LH> || std::is_same_v<T, LW> ||
206 std::is_same_v<T, LD> || std::is_same_v<T, LBU> || std::is_same_v<T, LHU> ||
207 std::is_same_v<T, LWU>;
210constexpr bool is_store = std::is_same_v<T, SB> || std::is_same_v<T, SH> ||
211 std::is_same_v<T, SW> || std::is_same_v<T, SD>;
215 std::is_same_v<T, AMOADD_W> || std::is_same_v<T, AMOADD_D>;
219 std::is_same_v<T, AMOXOR_W> || std::is_same_v<T, AMOXOR_D> ||
220 std::is_same_v<T, AMOAND_W> || std::is_same_v<T, AMOAND_D> ||
221 std::is_same_v<T, AMOOR_W> || std::is_same_v<T, AMOOR_D>;
225 std::is_same_v<T, AMOSWAP_W> || std::is_same_v<T, AMOSWAP_D>;
229 std::is_same_v<T, AMOMIN_W> || std::is_same_v<T, AMOMIN_D> ||
230 std::is_same_v<T, AMOMAX_W> || std::is_same_v<T, AMOMAX_D> ||
231 std::is_same_v<T, AMOMINU_W> || std::is_same_v<T, AMOMINU_D> ||
232 std::is_same_v<T, AMOMAXU_W> || std::is_same_v<T, AMOMAXU_D>;
235static std::enable_if_t<is_load<I> ||
is_store<I>, std::optional<uint64_t>>
237 return transformOptional(inst.rs1.Read(emulator), [&](uint64_t rs1) {
238 return rs1 + uint64_t(SignExt(inst.imm));
243template <
typename I,
typename T,
typename E>
244static std::enable_if_t<is_load<I>,
bool>
254 std::optional<RegisterInfo> reg_info_rs1 =
270 bool success =
false;
276 return inst.rd.Write(emulator, extend(E(T(value))));
279template <
typename I,
typename T>
280static std::enable_if_t<is_store<I>,
bool>
290 std::optional<RegisterInfo> reg_info_rs1 =
292 std::optional<RegisterInfo> reg_info_rs2 =
295 if (!reg_info_rs1 || !reg_info_rs2)
309 return transformOptional(inst.rs2.Read(emulator),
311 return emulator.WriteMemoryUnsigned(
312 context, *addr, rs2, sizeof(T));
320 std::optional<uint64_t>>
322 return transformOptional(inst.rs1.Read(emulator),
324 return rs1 % align == 0
325 ? std::optional<uint64_t>(rs1)
328 .value_or(std::nullopt);
331template <
typename I,
typename T>
332static std::enable_if_t<is_amo_swap<I>,
bool>
334 uint64_t (*extend)(T)) {
335 auto addr =
AtomicAddr(emulator, inst, align);
338 return transformOptional(
341 auto [tmp, rs2] = tup;
342 return emulator.WriteMem<T>(*addr, T(rs2)) &&
343 inst.rd.Write(emulator, extend(tmp));
348template <
typename I,
typename T>
349static std::enable_if_t<is_amo_add<I>,
bool>
351 uint64_t (*extend)(T)) {
352 auto addr =
AtomicAddr(emulator, inst, align);
355 return transformOptional(
358 auto [tmp, rs2] = tup;
359 return emulator.WriteMem<T>(*addr, T(tmp + rs2)) &&
360 inst.rd.Write(emulator, extend(tmp));
365template <
typename I,
typename T>
366static std::enable_if_t<is_amo_bit_op<I>,
bool>
368 uint64_t (*extend)(T), T (*operate)(T, T)) {
369 auto addr =
AtomicAddr(emulator, inst, align);
372 return transformOptional(
375 auto [value, rs2] = tup;
376 return emulator.WriteMem<T>(*addr, operate(value, T(rs2))) &&
377 inst.rd.Write(emulator, extend(value));
382template <
typename I,
typename T>
383static std::enable_if_t<is_amo_cmp<I>,
bool>
385 uint64_t (*extend)(T), T (*cmp)(T, T)) {
386 auto addr =
AtomicAddr(emulator, inst, align);
389 return transformOptional(
392 auto [value, rs2] = tup;
393 return emulator.WriteMem<T>(*addr, cmp(value, T(rs2))) &&
394 inst.rd.Write(emulator, extend(value));
410 auto current_pc = *
pc;
411 const auto entry_pc = current_pc;
415 if (!inst || (!std::holds_alternative<LR_W>(inst->decoded) &&
416 !std::holds_alternative<LR_D>(inst->decoded)))
421 if (!inst || !std::holds_alternative<B>(inst->decoded))
423 auto bne_exit = std::get<B>(inst->decoded);
424 if (bne_exit.funct3 !=
BNE)
427 const auto exit_pc = current_pc +
SextW(bne_exit.imm);
431 if (!inst || (!std::holds_alternative<SC_W>(inst->decoded) &&
432 !std::holds_alternative<SC_D>(inst->decoded)))
437 if (!inst || !std::holds_alternative<B>(inst->decoded))
439 auto bne_start = std::get<B>(inst->decoded);
440 if (bne_start.funct3 !=
BNE)
442 if (entry_pc != current_pc +
SextW(bne_start.imm))
447 return exit_pc == current_pc && emulator.
WritePC(current_pc);
690 uint16_t try_rvc = uint16_t(inst & 0x0000ffff);
691 uint8_t inst_type =
RV64;
695 bool is_16b = (inst & 0b11) != 0b11;
696 bool is_32b = (inst & 0x1f) != 0x1f;
697 bool is_48b = (inst & 0x3f) != 0x1f;
698 bool is_64b = (inst & 0x7f) != 0x3f;
717 if ((inst & pat.type_mask) == pat.eigen &&
718 (inst_type & pat.inst_type) != 0) {
720 "EmulateInstructionRISCV::%s: inst(%x at %" PRIx64
721 ") was decoded to %s",
722 __FUNCTION__, inst,
m_addr, pat.name);
723 auto decoded = is_16b ? pat.decode(try_rvc) : pat.decode(inst);
727 LLDB_LOGF(log,
"EmulateInstructionRISCV::%s: inst(0x%x) was unsupported",
739 static uint64_t
size(
bool is_rvc) {
return is_rvc ? 2 : 4; }
750 return transformOptional(
m_emu.ReadPC(),
752 return inst.rd.Write(m_emu,
753 SignExt(inst.imm) + pc);
758 return transformOptional(
m_emu.ReadPC(),
760 return inst.rd.Write(m_emu, pc + delta()) &&
761 m_emu.WritePC(SignExt(inst.imm) + pc);
768 auto [pc, rs1] = tup;
769 return inst.rd.Write(m_emu, pc + delta()) &&
770 m_emu.WritePC((SignExt(inst.imm) + rs1) &
779 auto [pc, rs1, rs2] = tup;
781 CompareB(rs1, rs2, inst.funct3))
782 return m_emu.WritePC(SignExt(inst.imm) + pc);
806 return transformOptional(
807 inst.rs1.ReadI64(
m_emu),
809 uint64_t result = rs1 + uint64_t(SignExt(inst.imm));
811 if (inst.rd.rd == RISCV_GPR_SP &&
812 inst.rs1.rs == RISCV_GPR_SP) {
813 EmulateInstruction::Context context;
815 EmulateInstruction::eContextAdjustStackPointer;
816 context.SetImmediateSigned(SignExt(inst.imm));
817 uint32_t sp_lldb_reg = GPREncodingToLLDB(RISCV_GPR_SP);
818 RegisterValue registerValue;
819 registerValue.SetUInt64(result);
820 return m_emu.WriteRegister(context, eRegisterKindLLDB,
821 sp_lldb_reg, registerValue);
827 EmulateInstruction::Context context;
828 context.type = EmulateInstruction::eContextSetFramePointer;
829 auto sp_reg_info = m_emu.GetRegisterInfo(
830 eRegisterKindLLDB, GPREncodingToLLDB(RISCV_GPR_SP));
832 context.SetRegisterPlusOffset(*sp_reg_info,
839 fp_lldb_reg, registerValue);
842 return inst.rd.Write(
m_emu, result);
847 return transformOptional(inst.rs1.ReadI64(
m_emu),
849 return inst.rd.Write(
850 m_emu, rs1 < int64_t(SignExt(inst.imm)));
855 return transformOptional(inst.rs1.Read(
m_emu),
857 return inst.rd.Write(
858 m_emu, rs1 < uint64_t(SignExt(inst.imm)));
863 return transformOptional(inst.rs1.Read(
m_emu),
865 return inst.rd.Write(
866 m_emu, rs1 ^ uint64_t(SignExt(inst.imm)));
871 return transformOptional(inst.rs1.Read(
m_emu),
873 return inst.rd.Write(
874 m_emu, rs1 | uint64_t(SignExt(inst.imm)));
879 return transformOptional(inst.rs1.Read(
m_emu),
881 return inst.rd.Write(
882 m_emu, rs1 & uint64_t(SignExt(inst.imm)));
887 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
889 auto [rs1, rs2] = tup;
890 return inst.rd.Write(m_emu, rs1 + rs2);
895 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
897 auto [rs1, rs2] = tup;
898 return inst.rd.Write(m_emu, rs1 - rs2);
903 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
905 auto [rs1, rs2] = tup;
906 return inst.rd.Write(m_emu,
907 rs1 << (rs2 & 0b111111));
912 return transformOptional(
915 auto [rs1, rs2] = tup;
916 return inst.rd.Write(m_emu, rs1 < rs2);
921 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
923 auto [rs1, rs2] = tup;
924 return inst.rd.Write(m_emu, rs1 < rs2);
929 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
931 auto [rs1, rs2] = tup;
932 return inst.rd.Write(m_emu, rs1 ^ rs2);
937 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
939 auto [rs1, rs2] = tup;
940 return inst.rd.Write(m_emu,
941 rs1 >> (rs2 & 0b111111));
946 return transformOptional(
949 auto [rs1, rs2] = tup;
950 return inst.rd.Write(m_emu, rs1 >> (rs2 & 0b111111));
955 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
957 auto [rs1, rs2] = tup;
958 return inst.rd.Write(m_emu, rs1 | rs2);
963 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
965 auto [rs1, rs2] = tup;
966 return inst.rd.Write(m_emu, rs1 & rs2);
978 return transformOptional(inst.rs1.Read(
m_emu),
980 return inst.rd.Write(m_emu, rs1 << inst.shamt);
985 return transformOptional(inst.rs1.Read(
m_emu),
987 return inst.rd.Write(m_emu, rs1 >> inst.shamt);
992 return transformOptional(inst.rs1.ReadI64(
m_emu),
994 return inst.rd.Write(m_emu, rs1 >> inst.shamt);
999 return transformOptional(inst.rs1.ReadI32(
m_emu),
1001 return inst.rd.Write(
1002 m_emu, SextW(rs1 + SignExt(inst.imm)));
1007 return transformOptional(inst.rs1.ReadU32(
m_emu),
1009 return inst.rd.Write(m_emu,
1010 SextW(rs1 << inst.shamt));
1015 return transformOptional(inst.rs1.ReadU32(
m_emu),
1017 return inst.rd.Write(m_emu,
1018 SextW(rs1 >> inst.shamt));
1023 return transformOptional(inst.rs1.ReadI32(
m_emu),
1025 return inst.rd.Write(m_emu,
1026 SextW(rs1 >> inst.shamt));
1031 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
1033 auto [rs1, rs2] = tup;
1034 return inst.rd.Write(m_emu,
1035 SextW(uint32_t(rs1 + rs2)));
1040 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
1042 auto [rs1, rs2] = tup;
1043 return inst.rd.Write(m_emu,
1044 SextW(uint32_t(rs1 - rs2)));
1049 return transformOptional(
1052 auto [rs1, rs2] = tup;
1053 return inst.rd.Write(m_emu, SextW(rs1 << (rs2 & 0b11111)));
1058 return transformOptional(
1061 auto [rs1, rs2] = tup;
1062 return inst.rd.Write(m_emu, SextW(rs1 >> (rs2 & 0b11111)));
1067 return transformOptional(
1070 auto [rs1, rs2] = tup;
1071 return inst.rd.Write(m_emu, SextW(rs1 >> (rs2 & 0b11111)));
1077 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
1079 auto [rs1, rs2] = tup;
1080 return inst.rd.Write(m_emu, rs1 * rs2);
1085 return transformOptional(
1088 auto [rs1, rs2] = tup;
1090 auto mul = APInt(128, rs1, true) * APInt(128, rs2, true);
1091 return inst.rd.Write(m_emu,
1092 mul.ashr(64).trunc(64).getZExtValue());
1097 return transformOptional(
1100 auto [rs1, rs2] = tup;
1103 APInt(128, rs1, true).zext(128) * APInt(128, rs2, false);
1104 return inst.rd.Write(m_emu,
1105 mul.lshr(64).trunc(64).getZExtValue());
1110 return transformOptional(
1113 auto [rs1, rs2] = tup;
1115 auto mul = APInt(128, rs1, false) * APInt(128, rs2, false);
1116 return inst.rd.Write(m_emu,
1117 mul.lshr(64).trunc(64).getZExtValue());
1122 return transformOptional(
1125 auto [dividend, divisor] = tup;
1128 return inst.rd.Write(m_emu, UINT64_MAX);
1130 if (dividend == INT64_MIN && divisor == -1)
1131 return inst.rd.Write(m_emu, dividend);
1133 return inst.rd.Write(m_emu, dividend / divisor);
1138 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
1140 auto [dividend, divisor] = tup;
1143 return inst.rd.Write(m_emu, UINT64_MAX);
1145 return inst.rd.Write(m_emu, dividend / divisor);
1150 return transformOptional(
1153 auto [dividend, divisor] = tup;
1156 return inst.rd.Write(m_emu, dividend);
1158 if (dividend == INT64_MIN && divisor == -1)
1159 return inst.rd.Write(m_emu, 0);
1161 return inst.rd.Write(m_emu, dividend % divisor);
1166 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
1168 auto [dividend, divisor] = tup;
1171 return inst.rd.Write(m_emu, dividend);
1173 return inst.rd.Write(m_emu, dividend % divisor);
1178 return transformOptional(
1181 auto [rs1, rs2] = tup;
1182 return inst.rd.Write(m_emu, SextW(rs1 * rs2));
1187 return transformOptional(
1190 auto [dividend, divisor] = tup;
1193 return inst.rd.Write(m_emu, UINT64_MAX);
1195 if (dividend == INT32_MIN && divisor == -1)
1196 return inst.rd.Write(m_emu, SextW(dividend));
1198 return inst.rd.Write(m_emu, SextW(dividend / divisor));
1203 return transformOptional(
1206 auto [dividend, divisor] = tup;
1209 return inst.rd.Write(m_emu, UINT64_MAX);
1211 return inst.rd.Write(m_emu, SextW(dividend / divisor));
1216 return transformOptional(
1219 auto [dividend, divisor] = tup;
1222 return inst.rd.Write(m_emu, SextW(dividend));
1224 if (dividend == INT32_MIN && divisor == -1)
1225 return inst.rd.Write(m_emu, 0);
1227 return inst.rd.Write(m_emu, SextW(dividend % divisor));
1232 return transformOptional(
1235 auto [dividend, divisor] = tup;
1238 return inst.rd.Write(m_emu, SextW(dividend));
1240 return inst.rd.Write(m_emu, SextW(dividend % divisor));
1248 llvm_unreachable(
"should be handled in AtomicSequence");
1251 llvm_unreachable(
"should be handled in AtomicSequence");
1261 m_emu, inst, 4,
SextW, [](uint32_t a, uint32_t b) {
return a ^ b; });
1265 m_emu, inst, 4,
SextW, [](uint32_t a, uint32_t b) {
return a & b; });
1269 m_emu, inst, 4,
SextW, [](uint32_t a, uint32_t b) {
return a | b; });
1273 m_emu, inst, 4,
SextW, [](uint32_t a, uint32_t b) {
1274 return uint32_t(std::min(int32_t(a), int32_t(b)));
1279 m_emu, inst, 4,
SextW, [](uint32_t a, uint32_t b) {
1280 return uint32_t(std::max(int32_t(a), int32_t(b)));
1286 [](uint32_t a, uint32_t b) {
return std::min(a, b); });
1291 [](uint32_t a, uint32_t b) {
return std::max(a, b); });
1301 m_emu, inst, 8,
ZextD, [](uint64_t a, uint64_t b) {
return a ^ b; });
1305 m_emu, inst, 8,
ZextD, [](uint64_t a, uint64_t b) {
return a & b; });
1309 m_emu, inst, 8,
ZextD, [](uint64_t a, uint64_t b) {
return a | b; });
1313 m_emu, inst, 8,
ZextD, [](uint64_t a, uint64_t b) {
1314 return uint64_t(std::min(int64_t(a), int64_t(b)));
1319 m_emu, inst, 8,
ZextD, [](uint64_t a, uint64_t b) {
1320 return uint64_t(std::max(int64_t(a), int64_t(b)));
1326 [](uint64_t a, uint64_t b) {
return std::min(a, b); });
1331 [](uint64_t a, uint64_t b) {
return std::max(a, b); });
1333 template <
typename I,
typename T>
1334 bool F_Load(I inst,
const fltSemantics &(*semantics)()) {
1335 return transformOptional(inst.rs1.Read(
m_emu),
1338 rs1 + uint64_t(SignExt(inst.imm));
1339 uint64_t bits = *m_emu.ReadMem<T>(addr);
1340 unsigned numBits = sizeof(T) * 8;
1341 APFloat f(semantics(), APInt(numBits, bits));
1342 return inst.rd.WriteAPFloat(m_emu, f);
1349 template <
typename I,
typename T>
bool F_Store(I inst,
bool isDouble) {
1350 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu),
1351 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1353 auto [rs1, rs2] = tup;
1355 rs1 + uint64_t(SignExt(inst.imm));
1357 rs2.bitcastToAPInt().getZExtValue();
1358 return m_emu.WriteMem<T>(addr, bits);
1365 auto opStatus = rs1.fusedMultiplyAdd(rs2, rs3,
m_emu.GetRoundingMode());
1366 auto res =
m_emu.SetAccruedExceptions(opStatus);
1369 template <
typename T>
1370 bool FMA(T inst,
bool isDouble,
float rs2_sign,
float rs3_sign) {
1371 return transformOptional(
zipOpt(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1372 inst.rs2.ReadAPFloat(
m_emu, isDouble),
1373 inst.rs3.ReadAPFloat(
m_emu, isDouble)),
1375 auto [rs1, rs2, rs3] = tup;
1376 rs2.copySign(APFloat(rs2_sign));
1377 rs3.copySign(APFloat(rs3_sign));
1378 auto [res, f] = FusedMultiplyAdd(rs1, rs2, rs3);
1379 return res && inst.rd.WriteAPFloat(m_emu, f);
1387 template <
typename T>
1389 APFloat::opStatus (APFloat::*f)(
const APFloat &RHS,
1390 APFloat::roundingMode RM)) {
1391 return transformOptional(
zipOpt(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1392 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1394 auto [rs1, rs2] = tup;
1396 ((&rs1)->*f)(rs2, m_emu.GetRoundingMode());
1397 inst.rd.WriteAPFloat(m_emu, rs1);
1398 return m_emu.SetAccruedExceptions(res);
1410 template <
typename T>
bool F_SignInj(T inst,
bool isDouble,
bool isNegate) {
1411 return transformOptional(
zipOpt(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1412 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1414 auto [rs1, rs2] = tup;
1418 return inst.rd.WriteAPFloat(m_emu, rs1);
1425 return transformOptional(
zipOpt(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1426 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1428 auto [rs1, rs2] = tup;
1433 if (rs1.isNegative() == rs2.isNegative()) {
1439 return inst.rd.WriteAPFloat(
m_emu, rs1);
1444 template <
typename T>
1446 APFloat (*f)(
const APFloat &A,
const APFloat &
B)) {
1447 return transformOptional(
1449 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1451 auto [rs1, rs2] = tup;
1456 if (rs1.isNaN() || rs2.isNaN())
1457 m_emu.SetAccruedExceptions(APFloat::opInvalidOp);
1458 if (rs1.isNaN() && rs2.isNaN()) {
1459 auto canonicalNaN = APFloat::getQNaN(rs1.getSemantics());
1460 return inst.rd.WriteAPFloat(m_emu, canonicalNaN);
1462 return inst.rd.WriteAPFloat(
m_emu, f(rs1, rs2));
1470 &APFloat::convertToFloat);
1474 &APFloat::convertToFloat);
1476 template <
typename T>
bool FMV_f2i(T inst,
bool isDouble) {
1477 return transformOptional(
1478 inst.rs1.ReadAPFloat(
m_emu, isDouble),
1482 return inst.rd.Write(m_emu, 0x7ff8'0000'0000'0000);
1484 return inst.rd.Write(m_emu, 0x7fc0'0000);
1486 auto bits = rs1.bitcastToAPInt().getZExtValue();
1490 return inst.rd.Write(
m_emu, uint64_t(
bits & 0xffff'ffff));
1501 return transformOptional(
1503 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1505 auto [rs1, rs2] = tup;
1506 if (rs1.isNaN() || rs2.isNaN()) {
1508 if (rs1.isSignaling() || rs2.isSignaling()) {
1510 m_emu.SetAccruedExceptions(APFloat::opInvalidOp);
1511 return res && inst.rd.Write(m_emu, 0);
1514 auto res = m_emu.SetAccruedExceptions(APFloat::opInvalidOp);
1515 return res && inst.rd.Write(m_emu, 0);
1519 return inst.rd.Write(
m_emu,
1520 rs1.compare(rs2) == APFloat::cmpEqual);
1522 return inst.rd.Write(
m_emu, rs1.compare(rs2) ==
1523 APFloat::cmpLessThan);
1525 return inst.rd.Write(
m_emu, rs1.compare(rs2) !=
1526 APFloat::cmpGreaterThan);
1528 llvm_unreachable(
"unsupported F_CMP");
1536 template <
typename T>
bool FCLASS(T inst,
bool isDouble) {
1537 return transformOptional(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1539 uint64_t result = 0;
1540 if (rs1.isInfinity() && rs1.isNegative())
1543 if (rs1.isNormal() && rs1.isNegative())
1546 if (rs1.isDenormal() && rs1.isNegative())
1548 if (rs1.isNegZero())
1550 if (rs1.isPosZero())
1553 if (rs1.isNormal() && !rs1.isNegative())
1556 if (rs1.isDenormal() && !rs1.isNegative())
1558 if (rs1.isInfinity() && !rs1.isNegative())
1561 if (rs1.isSignaling())
1566 return inst.rd.Write(
m_emu, result);
1571 template <
typename T,
typename E>
1573 const fltSemantics &semantics) {
1574 return transformOptional(((&inst.rs1)->*f)(
m_emu),
1576 APFloat apf(semantics, rs1);
1577 return inst.rd.WriteAPFloat(m_emu, apf);
1587 template <
typename T,
typename E>
1588 bool FMV_i2f(T inst,
unsigned int numBits, E (APInt::*f)()
const) {
1589 return transformOptional(inst.rs1.Read(
m_emu),
1591 APInt apInt(numBits, rs1);
1593 apInt = APInt(numBits, NanUnBoxing(rs1));
1594 APFloat apf((&apInt->*f)());
1595 return inst.rd.WriteAPFloat(m_emu, apf);
1600 return FMV_i2f(inst, 32, &APInt::bitsToFloat);
1602 template <
typename I,
typename E,
typename T>
1603 bool FCVT_i2f(I inst,
bool isDouble, T (APFloat::*f)()
const) {
1604 return transformOptional(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1606 E res = E((&rs1->*f)());
1607 return inst.rd.Write(m_emu, uint64_t(res));
1613 &APFloat::convertToFloat);
1617 &APFloat::convertToFloat);
1647 return transformOptional(inst.rs1.ReadAPFloat(
m_emu,
true),
1649 double d = rs1.convertToDouble();
1650 APFloat apf((float(d)));
1651 return inst.rd.WriteAPFloat(m_emu, apf);
1656 return transformOptional(inst.rs1.ReadAPFloat(
m_emu,
false),
1658 float f = rs1.convertToFloat();
1659 APFloat apf((double(f)));
1660 return inst.rd.WriteAPFloat(m_emu, apf);
1670 &APFloat::convertToDouble);
1674 &APFloat::convertToDouble);
1684 &APFloat::convertToDouble);
1688 &APFloat::convertToDouble);
1698 return FMV_i2f(inst, 64, &APInt::bitsToDouble);
1712 bool increase_pc = options & eEmulateInstructionOptionAutoAdvancePC;
1713 bool ignore_cond = options & eEmulateInstructionOptionIgnoreConditions;
1731 return new_pc != old_pc ||
1735std::optional<DecodeResult>
1738 [&](uint32_t inst) {
return Decode(inst); })
1739 .value_or(std::nullopt);
1759 bool success =
false;
1763 return RoundingMode::Invalid;
1764 auto frm = (fcsr >> 5) & 0x7;
1767 return RoundingMode::NearestTiesToEven;
1769 return RoundingMode::TowardZero;
1771 return RoundingMode::TowardNegative;
1773 return RoundingMode::TowardPositive;
1775 return RoundingMode::Dynamic;
1778 return RoundingMode::Invalid;
1783 APFloatBase::opStatus opStatus) {
1784 bool success =
false;
1790 case APFloatBase::opInvalidOp:
1793 case APFloatBase::opDivByZero:
1796 case APFloatBase::opOverflow:
1799 case APFloatBase::opUnderflow:
1802 case APFloatBase::opInexact:
1805 case APFloatBase::opOK:
1814std::optional<RegisterInfo>
1816 uint32_t reg_index) {
1818 switch (reg_index) {
1838 llvm_unreachable(
"unsupported register");
1842 std::unique_ptr<RegisterInfoInterface> reg_info;
1843 switch (
m_arch.GetTriple().getArch()) {
1844 case llvm::Triple::riscv32:
1845 reg_info = std::make_unique<RegisterInfoPOSIX_riscv32>(
1848 case llvm::Triple::riscv64:
1849 reg_info = std::make_unique<RegisterInfoPOSIX_riscv64>(
1853 assert(
false &&
"unsupported triple");
1857 const RegisterInfo *array = reg_info->GetRegisterInfo();
1858 const uint32_t length = reg_info->GetRegisterCount();
1863 return array[reg_index];
1874 uint32_t inst_data = 0;
1875 const void *opcode_data =
m_opcode.GetOpcodeBytes();
1881 const uint16_t *data =
static_cast<const uint16_t *
>(opcode_data);
1883 }
else if (
m_opcode.GetByteSize() == 4) {
1885 const uint32_t *data =
static_cast<const uint32_t *
>(opcode_data);
1892 auto decoded_inst =
Decode(inst_data);
1903 unwind_plan.
Clear();
1960 auto pc = riscv_emulator->
ReadPC();
1962 status =
Status(
"Can't read PC");
1982 "RISCVSingleStepBreakpointLocationsPredictor::%s: can't find "
1983 "corresponding load reserve instruction",
1985 return {*
pc + (inst->is_rvc ? 2u : 4u)};
1991llvm::Expected<unsigned>
1998 return inst->is_rvc ? 2 : 4;
2003 return *last_instr_size;
2020 pc += lr_inst->is_rvc ? 2 : 4;
2022 size_t atomic_length = 0;
2023 std::optional<DecodeResult> inst;
2024 std::vector<lldb::addr_t> bp_addrs;
2032 if (
B *branch = std::get_if<B>(&inst->decoded))
2033 bp_addrs.push_back(
pc +
SignExt(branch->imm));
2035 unsigned addent = inst->is_rvc ? 2 : 4;
2037 atomic_length += addent;
2047 "RISCVSingleStepBreakpointLocationsPredictor::%s: can't find "
2048 "corresponding store conditional instruction",
2050 return {entry_pc + (lr_inst->is_rvc ? 2u : 4u)};
2060 B *branch = std::get_if<B>(&inst->decoded);
2061 if (branch && (exit_pc +
SignExt(branch->
imm)) == entry_pc)
2062 exit_pc += inst->is_rvc ? 2 : 4;
2068 bp_addrs, [exit_pc](
lldb::addr_t bp_addr) {
return exit_pc >= bp_addr; });
2071 bp_addrs.push_back(exit_pc);
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOGF(log,...)
#define LLDB_PLUGIN_DEFINE_ADV(ClassName, PluginName)
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 F_Store(I inst, bool isDouble)
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 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 F_Load(I inst, const fltSemantics &(*semantics)())
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 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)