26#include "llvm/ADT/STLExtras.h"
27#include "llvm/Support/ErrorExtras.h"
28#include "llvm/Support/MathExtras.h"
45template <
typename... Ts>
46static std::optional<std::tuple<Ts...>>
zipOpt(std::optional<Ts> &&...ts) {
47 if ((ts.has_value() && ...))
48 return std::optional<std::tuple<Ts...>>(std::make_tuple(std::move(*ts)...));
56constexpr uint32_t
BEQ = 0b000;
57constexpr uint32_t
BNE = 0b001;
58constexpr uint32_t
BLT = 0b100;
59constexpr uint32_t
BGE = 0b101;
60constexpr uint32_t
BLTU = 0b110;
61constexpr uint32_t
BGEU = 0b111;
64constexpr int32_t
SignExt(uint32_t imm) {
return int32_t(imm); }
68constexpr std::enable_if_t<
sizeof(T) <= 4, uint64_t>
SextW(T value) {
69 return uint64_t(int64_t(int32_t(value)));
73template <
typename T>
constexpr uint64_t
ZextD(T value) {
74 return uint64_t(value);
78 return (uint64_t(int64_t(int32_t(inst & 0x80000000)) >> 11))
80 | ((inst >> 9) & 0x800)
81 | ((inst >> 20) & 0x7fe);
85 return int64_t(int32_t(inst)) >> 20;
89 return (uint64_t(int64_t(int32_t(inst & 0x80000000)) >> 19))
90 | ((inst & 0x80) << 4)
91 | ((inst >> 20) & 0x7e0)
92 | ((inst >> 7) & 0x1e);
96 return (uint64_t(int64_t(int32_t(inst & 0xFE000000)) >> 20))
97 | ((inst & 0xF80) >> 7);
101 return SextW(inst & 0xFFFFF000);
107 if (reg_encode >= 1 && reg_encode <= 31)
113 if (reg_encode <= 31)
119static std::optional<RegisterInfo>
121 uint32_t reg_encode) {
145 registerValue.
SetUInt64(value.bitcastToAPInt().getZExtValue());
159 return transformOptional(
160 Read(emulator), [](uint64_t value) {
return int32_t(uint32_t(value)); });
164 return transformOptional(
Read(emulator),
165 [](uint64_t value) {
return int64_t(value); });
169 return transformOptional(
Read(emulator),
170 [](uint64_t value) {
return uint32_t(value); });
180 APInt api(64,
bits,
false);
181 return APFloat(isDouble ? APFloat(api.bitsToDouble())
182 : APFloat(api.bitsToFloat()));
185static bool CompareB(uint64_t rs1, uint64_t rs2, uint32_t funct3) {
192 return int64_t(rs1) < int64_t(rs2);
194 return int64_t(rs1) >= int64_t(rs2);
200 llvm_unreachable(
"unexpected funct3");
206 std::is_same_v<T, LB> || std::is_same_v<T, LH> || std::is_same_v<T, LW> ||
207 std::is_same_v<T, LD> || std::is_same_v<T, LBU> || std::is_same_v<T, LHU> ||
208 std::is_same_v<T, LWU>;
211constexpr bool is_store = std::is_same_v<T, SB> || std::is_same_v<T, SH> ||
212 std::is_same_v<T, SW> || std::is_same_v<T, SD>;
216 std::is_same_v<T, AMOADD_W> || std::is_same_v<T, AMOADD_D>;
220 std::is_same_v<T, AMOXOR_W> || std::is_same_v<T, AMOXOR_D> ||
221 std::is_same_v<T, AMOAND_W> || std::is_same_v<T, AMOAND_D> ||
222 std::is_same_v<T, AMOOR_W> || std::is_same_v<T, AMOOR_D>;
226 std::is_same_v<T, AMOSWAP_W> || std::is_same_v<T, AMOSWAP_D>;
230 std::is_same_v<T, AMOMIN_W> || std::is_same_v<T, AMOMIN_D> ||
231 std::is_same_v<T, AMOMAX_W> || std::is_same_v<T, AMOMAX_D> ||
232 std::is_same_v<T, AMOMINU_W> || std::is_same_v<T, AMOMINU_D> ||
233 std::is_same_v<T, AMOMAXU_W> || std::is_same_v<T, AMOMAXU_D>;
236static std::enable_if_t<is_load<I> ||
is_store<I>, std::optional<uint64_t>>
238 return transformOptional(inst.rs1.Read(emulator), [&](uint64_t rs1) {
239 return rs1 + uint64_t(SignExt(inst.imm));
244template <
typename I,
typename T,
typename E>
245static std::enable_if_t<is_load<I>,
bool>
255 std::optional<RegisterInfo> reg_info_rs1 =
271 bool success =
false;
277 return inst.rd.Write(emulator, extend(E(T(value))));
280template <
typename I,
typename T>
281static std::enable_if_t<is_store<I>,
bool>
291 std::optional<RegisterInfo> reg_info_rs1 =
293 std::optional<RegisterInfo> reg_info_rs2 =
296 if (!reg_info_rs1 || !reg_info_rs2)
310 return transformOptional(inst.rs2.Read(emulator),
312 return emulator.WriteMemoryUnsigned(
313 context, *addr, rs2, sizeof(T));
321 std::optional<uint64_t>>
323 return transformOptional(inst.rs1.Read(emulator),
325 return rs1 % align == 0
326 ? std::optional<uint64_t>(rs1)
329 .value_or(std::nullopt);
332template <
typename I,
typename T>
333static std::enable_if_t<is_amo_swap<I>,
bool>
335 uint64_t (*extend)(T)) {
336 auto addr =
AtomicAddr(emulator, inst, align);
339 return transformOptional(
342 auto [tmp, rs2] = tup;
343 return emulator.WriteMem<T>(*addr, T(rs2)) &&
344 inst.rd.Write(emulator, extend(tmp));
349template <
typename I,
typename T>
350static std::enable_if_t<is_amo_add<I>,
bool>
352 uint64_t (*extend)(T)) {
353 auto addr =
AtomicAddr(emulator, inst, align);
356 return transformOptional(
359 auto [tmp, rs2] = tup;
360 return emulator.WriteMem<T>(*addr, T(tmp + rs2)) &&
361 inst.rd.Write(emulator, extend(tmp));
366template <
typename I,
typename T>
367static std::enable_if_t<is_amo_bit_op<I>,
bool>
369 uint64_t (*extend)(T), T (*operate)(T, T)) {
370 auto addr =
AtomicAddr(emulator, inst, align);
373 return transformOptional(
376 auto [value, rs2] = tup;
377 return emulator.WriteMem<T>(*addr, operate(value, T(rs2))) &&
378 inst.rd.Write(emulator, extend(value));
383template <
typename I,
typename T>
384static std::enable_if_t<is_amo_cmp<I>,
bool>
386 uint64_t (*extend)(T), T (*cmp)(T, T)) {
387 auto addr =
AtomicAddr(emulator, inst, align);
390 return transformOptional(
393 auto [value, rs2] = tup;
394 return emulator.WriteMem<T>(*addr, cmp(value, T(rs2))) &&
395 inst.rd.Write(emulator, extend(value));
411 auto current_pc = *
pc;
412 const auto entry_pc = current_pc;
416 if (!inst || (!std::holds_alternative<LR_W>(inst->decoded) &&
417 !std::holds_alternative<LR_D>(inst->decoded)))
422 if (!inst || !std::holds_alternative<B>(inst->decoded))
424 auto bne_exit = std::get<B>(inst->decoded);
425 if (bne_exit.funct3 !=
BNE)
428 const auto exit_pc = current_pc +
SextW(bne_exit.imm);
432 if (!inst || (!std::holds_alternative<SC_W>(inst->decoded) &&
433 !std::holds_alternative<SC_D>(inst->decoded)))
438 if (!inst || !std::holds_alternative<B>(inst->decoded))
440 auto bne_start = std::get<B>(inst->decoded);
441 if (bne_start.funct3 !=
BNE)
443 if (entry_pc != current_pc +
SextW(bne_start.imm))
448 return exit_pc == current_pc && emulator.
WritePC(current_pc);
691 uint16_t try_rvc = uint16_t(inst & 0x0000ffff);
692 uint8_t inst_type =
RV64;
696 bool is_16b = (inst & 0b11) != 0b11;
697 bool is_32b = (inst & 0x1f) != 0x1f;
698 bool is_48b = (inst & 0x3f) != 0x1f;
699 bool is_64b = (inst & 0x7f) != 0x3f;
718 if ((inst & pat.type_mask) == pat.eigen &&
719 (inst_type & pat.inst_type) != 0) {
721 "EmulateInstructionRISCV::%s: inst(%x at %" PRIx64
722 ") was decoded to %s",
723 __FUNCTION__, inst,
m_addr, pat.name);
724 auto decoded = is_16b ? pat.decode(try_rvc) : pat.decode(inst);
728 LLDB_LOGF(log,
"EmulateInstructionRISCV::%s: inst(0x%x) was unsupported",
740 static uint64_t
size(
bool is_rvc) {
return is_rvc ? 2 : 4; }
751 return transformOptional(
m_emu.ReadPC(),
753 return inst.rd.Write(m_emu,
754 SignExt(inst.imm) + pc);
759 return transformOptional(
m_emu.ReadPC(),
761 return inst.rd.Write(m_emu, pc + delta()) &&
762 m_emu.WritePC(SignExt(inst.imm) + pc);
769 auto [pc, rs1] = tup;
770 return inst.rd.Write(m_emu, pc + delta()) &&
771 m_emu.WritePC((SignExt(inst.imm) + rs1) &
780 auto [pc, rs1, rs2] = tup;
782 CompareB(rs1, rs2, inst.funct3))
783 return m_emu.WritePC(SignExt(inst.imm) + pc);
807 return transformOptional(
808 inst.rs1.ReadI64(
m_emu),
810 uint64_t result = rs1 + uint64_t(SignExt(inst.imm));
812 if (inst.rd.rd == RISCV_GPR_SP &&
813 inst.rs1.rs == RISCV_GPR_SP) {
814 EmulateInstruction::Context context;
816 EmulateInstruction::eContextAdjustStackPointer;
817 context.SetImmediateSigned(SignExt(inst.imm));
818 uint32_t sp_lldb_reg = GPREncodingToLLDB(RISCV_GPR_SP);
819 RegisterValue registerValue;
820 registerValue.SetUInt64(result);
821 return m_emu.WriteRegister(context, eRegisterKindLLDB,
822 sp_lldb_reg, registerValue);
828 EmulateInstruction::Context context;
829 context.type = EmulateInstruction::eContextSetFramePointer;
830 auto sp_reg_info = m_emu.GetRegisterInfo(
831 eRegisterKindLLDB, GPREncodingToLLDB(RISCV_GPR_SP));
833 context.SetRegisterPlusOffset(*sp_reg_info,
840 fp_lldb_reg, registerValue);
843 return inst.rd.Write(
m_emu, result);
848 return transformOptional(inst.rs1.ReadI64(
m_emu),
850 return inst.rd.Write(
851 m_emu, rs1 < int64_t(SignExt(inst.imm)));
856 return transformOptional(inst.rs1.Read(
m_emu),
858 return inst.rd.Write(
859 m_emu, rs1 < uint64_t(SignExt(inst.imm)));
864 return transformOptional(inst.rs1.Read(
m_emu),
866 return inst.rd.Write(
867 m_emu, rs1 ^ uint64_t(SignExt(inst.imm)));
872 return transformOptional(inst.rs1.Read(
m_emu),
874 return inst.rd.Write(
875 m_emu, rs1 | uint64_t(SignExt(inst.imm)));
880 return transformOptional(inst.rs1.Read(
m_emu),
882 return inst.rd.Write(
883 m_emu, rs1 & uint64_t(SignExt(inst.imm)));
888 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
890 auto [rs1, rs2] = tup;
891 return inst.rd.Write(m_emu, rs1 + rs2);
896 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
898 auto [rs1, rs2] = tup;
899 return inst.rd.Write(m_emu, rs1 - rs2);
904 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
906 auto [rs1, rs2] = tup;
907 return inst.rd.Write(m_emu,
908 rs1 << (rs2 & 0b111111));
913 return transformOptional(
916 auto [rs1, rs2] = tup;
917 return inst.rd.Write(m_emu, rs1 < rs2);
922 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
924 auto [rs1, rs2] = tup;
925 return inst.rd.Write(m_emu, rs1 < rs2);
930 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
932 auto [rs1, rs2] = tup;
933 return inst.rd.Write(m_emu, rs1 ^ rs2);
938 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
940 auto [rs1, rs2] = tup;
941 return inst.rd.Write(m_emu,
942 rs1 >> (rs2 & 0b111111));
947 return transformOptional(
950 auto [rs1, rs2] = tup;
951 return inst.rd.Write(m_emu, rs1 >> (rs2 & 0b111111));
956 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
958 auto [rs1, rs2] = tup;
959 return inst.rd.Write(m_emu, rs1 | rs2);
964 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
966 auto [rs1, rs2] = tup;
967 return inst.rd.Write(m_emu, rs1 & rs2);
979 return transformOptional(inst.rs1.Read(
m_emu),
981 return inst.rd.Write(m_emu, rs1 << inst.shamt);
986 return transformOptional(inst.rs1.Read(
m_emu),
988 return inst.rd.Write(m_emu, rs1 >> inst.shamt);
993 return transformOptional(inst.rs1.ReadI64(
m_emu),
995 return inst.rd.Write(m_emu, rs1 >> inst.shamt);
1000 return transformOptional(inst.rs1.ReadI32(
m_emu),
1002 return inst.rd.Write(
1003 m_emu, SextW(rs1 + SignExt(inst.imm)));
1008 return transformOptional(inst.rs1.ReadU32(
m_emu),
1010 return inst.rd.Write(m_emu,
1011 SextW(rs1 << inst.shamt));
1016 return transformOptional(inst.rs1.ReadU32(
m_emu),
1018 return inst.rd.Write(m_emu,
1019 SextW(rs1 >> inst.shamt));
1024 return transformOptional(inst.rs1.ReadI32(
m_emu),
1026 return inst.rd.Write(m_emu,
1027 SextW(rs1 >> inst.shamt));
1032 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
1034 auto [rs1, rs2] = tup;
1035 return inst.rd.Write(m_emu,
1036 SextW(uint32_t(rs1 + rs2)));
1041 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
1043 auto [rs1, rs2] = tup;
1044 return inst.rd.Write(m_emu,
1045 SextW(uint32_t(rs1 - rs2)));
1050 return transformOptional(
1053 auto [rs1, rs2] = tup;
1054 return inst.rd.Write(m_emu, SextW(rs1 << (rs2 & 0b11111)));
1059 return transformOptional(
1062 auto [rs1, rs2] = tup;
1063 return inst.rd.Write(m_emu, SextW(rs1 >> (rs2 & 0b11111)));
1068 return transformOptional(
1071 auto [rs1, rs2] = tup;
1072 return inst.rd.Write(m_emu, SextW(rs1 >> (rs2 & 0b11111)));
1078 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
1080 auto [rs1, rs2] = tup;
1081 return inst.rd.Write(m_emu, rs1 * rs2);
1086 return transformOptional(
1089 auto [rs1, rs2] = tup;
1091 auto mul = APInt(128, rs1, true) * APInt(128, rs2, true);
1092 return inst.rd.Write(m_emu,
1093 mul.ashr(64).trunc(64).getZExtValue());
1098 return transformOptional(
1101 auto [rs1, rs2] = tup;
1104 APInt(128, rs1, true).zext(128) * APInt(128, rs2, false);
1105 return inst.rd.Write(m_emu,
1106 mul.lshr(64).trunc(64).getZExtValue());
1111 return transformOptional(
1114 auto [rs1, rs2] = tup;
1116 auto mul = APInt(128, rs1, false) * APInt(128, rs2, false);
1117 return inst.rd.Write(m_emu,
1118 mul.lshr(64).trunc(64).getZExtValue());
1123 return transformOptional(
1126 auto [dividend, divisor] = tup;
1129 return inst.rd.Write(m_emu, UINT64_MAX);
1131 if (dividend == INT64_MIN && divisor == -1)
1132 return inst.rd.Write(m_emu, dividend);
1134 return inst.rd.Write(m_emu, dividend / divisor);
1139 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
1141 auto [dividend, divisor] = tup;
1144 return inst.rd.Write(m_emu, UINT64_MAX);
1146 return inst.rd.Write(m_emu, dividend / divisor);
1151 return transformOptional(
1154 auto [dividend, divisor] = tup;
1157 return inst.rd.Write(m_emu, dividend);
1159 if (dividend == INT64_MIN && divisor == -1)
1160 return inst.rd.Write(m_emu, 0);
1162 return inst.rd.Write(m_emu, dividend % divisor);
1167 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
1169 auto [dividend, divisor] = tup;
1172 return inst.rd.Write(m_emu, dividend);
1174 return inst.rd.Write(m_emu, dividend % divisor);
1179 return transformOptional(
1182 auto [rs1, rs2] = tup;
1183 return inst.rd.Write(m_emu, SextW(rs1 * rs2));
1188 return transformOptional(
1191 auto [dividend, divisor] = tup;
1194 return inst.rd.Write(m_emu, UINT64_MAX);
1196 if (dividend == INT32_MIN && divisor == -1)
1197 return inst.rd.Write(m_emu, SextW(dividend));
1199 return inst.rd.Write(m_emu, SextW(dividend / divisor));
1204 return transformOptional(
1207 auto [dividend, divisor] = tup;
1210 return inst.rd.Write(m_emu, UINT64_MAX);
1212 return inst.rd.Write(m_emu, SextW(dividend / divisor));
1217 return transformOptional(
1220 auto [dividend, divisor] = tup;
1223 return inst.rd.Write(m_emu, SextW(dividend));
1225 if (dividend == INT32_MIN && divisor == -1)
1226 return inst.rd.Write(m_emu, 0);
1228 return inst.rd.Write(m_emu, SextW(dividend % divisor));
1233 return transformOptional(
1236 auto [dividend, divisor] = tup;
1239 return inst.rd.Write(m_emu, SextW(dividend));
1241 return inst.rd.Write(m_emu, SextW(dividend % divisor));
1249 llvm_unreachable(
"should be handled in AtomicSequence");
1252 llvm_unreachable(
"should be handled in AtomicSequence");
1262 m_emu, inst, 4,
SextW, [](uint32_t a, uint32_t b) {
return a ^ b; });
1266 m_emu, inst, 4,
SextW, [](uint32_t a, uint32_t b) {
return a & b; });
1270 m_emu, inst, 4,
SextW, [](uint32_t a, uint32_t b) {
return a | b; });
1274 m_emu, inst, 4,
SextW, [](uint32_t a, uint32_t b) {
1275 return uint32_t(std::min(int32_t(a), int32_t(b)));
1280 m_emu, inst, 4,
SextW, [](uint32_t a, uint32_t b) {
1281 return uint32_t(std::max(int32_t(a), int32_t(b)));
1287 [](uint32_t a, uint32_t b) {
return std::min(a, b); });
1292 [](uint32_t a, uint32_t b) {
return std::max(a, b); });
1302 m_emu, inst, 8,
ZextD, [](uint64_t a, uint64_t b) {
return a ^ b; });
1306 m_emu, inst, 8,
ZextD, [](uint64_t a, uint64_t b) {
return a & b; });
1310 m_emu, inst, 8,
ZextD, [](uint64_t a, uint64_t b) {
return a | b; });
1314 m_emu, inst, 8,
ZextD, [](uint64_t a, uint64_t b) {
1315 return uint64_t(std::min(int64_t(a), int64_t(b)));
1320 m_emu, inst, 8,
ZextD, [](uint64_t a, uint64_t b) {
1321 return uint64_t(std::max(int64_t(a), int64_t(b)));
1327 [](uint64_t a, uint64_t b) {
return std::min(a, b); });
1332 [](uint64_t a, uint64_t b) {
return std::max(a, b); });
1334 template <
typename I,
typename T>
1335 bool F_Load(I inst,
const fltSemantics &(*semantics)()) {
1336 return transformOptional(inst.rs1.Read(
m_emu),
1339 rs1 + uint64_t(SignExt(inst.imm));
1340 uint64_t bits = *m_emu.ReadMem<T>(addr);
1341 unsigned numBits = sizeof(T) * 8;
1342 APFloat f(semantics(), APInt(numBits, bits));
1343 return inst.rd.WriteAPFloat(m_emu, f);
1350 template <
typename I,
typename T>
bool F_Store(I inst,
bool isDouble) {
1351 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu),
1352 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1354 auto [rs1, rs2] = tup;
1356 rs1 + uint64_t(SignExt(inst.imm));
1358 rs2.bitcastToAPInt().getZExtValue();
1359 return m_emu.WriteMem<T>(addr, bits);
1366 auto opStatus = rs1.fusedMultiplyAdd(rs2, rs3,
m_emu.GetRoundingMode());
1367 auto res =
m_emu.SetAccruedExceptions(opStatus);
1370 template <
typename T>
1371 bool FMA(T inst,
bool isDouble,
float rs2_sign,
float rs3_sign) {
1372 return transformOptional(
zipOpt(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1373 inst.rs2.ReadAPFloat(
m_emu, isDouble),
1374 inst.rs3.ReadAPFloat(
m_emu, isDouble)),
1376 auto [rs1, rs2, rs3] = tup;
1377 rs2.copySign(APFloat(rs2_sign));
1378 rs3.copySign(APFloat(rs3_sign));
1379 auto [res, f] = FusedMultiplyAdd(rs1, rs2, rs3);
1380 return res && inst.rd.WriteAPFloat(m_emu, f);
1388 template <
typename T>
1390 APFloat::opStatus (APFloat::*f)(
const APFloat &RHS,
1391 APFloat::roundingMode RM)) {
1392 return transformOptional(
zipOpt(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1393 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1395 auto [rs1, rs2] = tup;
1397 ((&rs1)->*f)(rs2, m_emu.GetRoundingMode());
1398 inst.rd.WriteAPFloat(m_emu, rs1);
1399 return m_emu.SetAccruedExceptions(res);
1411 template <
typename T>
bool F_SignInj(T inst,
bool isDouble,
bool isNegate) {
1412 return transformOptional(
zipOpt(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1413 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1415 auto [rs1, rs2] = tup;
1419 return inst.rd.WriteAPFloat(m_emu, rs1);
1426 return transformOptional(
zipOpt(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1427 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1429 auto [rs1, rs2] = tup;
1434 if (rs1.isNegative() == rs2.isNegative()) {
1440 return inst.rd.WriteAPFloat(
m_emu, rs1);
1445 template <
typename T>
1447 APFloat (*f)(
const APFloat &A,
const APFloat &
B)) {
1448 return transformOptional(
1450 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1452 auto [rs1, rs2] = tup;
1457 if (rs1.isNaN() || rs2.isNaN())
1458 m_emu.SetAccruedExceptions(APFloat::opInvalidOp);
1459 if (rs1.isNaN() && rs2.isNaN()) {
1460 auto canonicalNaN = APFloat::getQNaN(rs1.getSemantics());
1461 return inst.rd.WriteAPFloat(m_emu, canonicalNaN);
1463 return inst.rd.WriteAPFloat(
m_emu, f(rs1, rs2));
1471 &APFloat::convertToFloat);
1475 &APFloat::convertToFloat);
1477 template <
typename T>
bool FMV_f2i(T inst,
bool isDouble) {
1478 return transformOptional(
1479 inst.rs1.ReadAPFloat(
m_emu, isDouble),
1483 return inst.rd.Write(m_emu, 0x7ff8'0000'0000'0000);
1485 return inst.rd.Write(m_emu, 0x7fc0'0000);
1487 auto bits = rs1.bitcastToAPInt().getZExtValue();
1491 return inst.rd.Write(
m_emu, uint64_t(
bits & 0xffff'ffff));
1502 return transformOptional(
1504 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1506 auto [rs1, rs2] = tup;
1507 if (rs1.isNaN() || rs2.isNaN()) {
1509 if (rs1.isSignaling() || rs2.isSignaling()) {
1511 m_emu.SetAccruedExceptions(APFloat::opInvalidOp);
1512 return res && inst.rd.Write(m_emu, 0);
1515 auto res = m_emu.SetAccruedExceptions(APFloat::opInvalidOp);
1516 return res && inst.rd.Write(m_emu, 0);
1520 return inst.rd.Write(
m_emu,
1521 rs1.compare(rs2) == APFloat::cmpEqual);
1523 return inst.rd.Write(
m_emu, rs1.compare(rs2) ==
1524 APFloat::cmpLessThan);
1526 return inst.rd.Write(
m_emu, rs1.compare(rs2) !=
1527 APFloat::cmpGreaterThan);
1529 llvm_unreachable(
"unsupported F_CMP");
1537 template <
typename T>
bool FCLASS(T inst,
bool isDouble) {
1538 return transformOptional(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1540 uint64_t result = 0;
1541 if (rs1.isInfinity() && rs1.isNegative())
1544 if (rs1.isNormal() && rs1.isNegative())
1547 if (rs1.isDenormal() && rs1.isNegative())
1549 if (rs1.isNegZero())
1551 if (rs1.isPosZero())
1554 if (rs1.isNormal() && !rs1.isNegative())
1557 if (rs1.isDenormal() && !rs1.isNegative())
1559 if (rs1.isInfinity() && !rs1.isNegative())
1562 if (rs1.isSignaling())
1567 return inst.rd.Write(
m_emu, result);
1572 template <
typename T,
typename E>
1574 const fltSemantics &semantics) {
1575 return transformOptional(((&inst.rs1)->*f)(
m_emu),
1577 APFloat apf(semantics, rs1);
1578 return inst.rd.WriteAPFloat(m_emu, apf);
1588 template <
typename T,
typename E>
1589 bool FMV_i2f(T inst,
unsigned int numBits, E (APInt::*f)()
const) {
1590 return transformOptional(inst.rs1.Read(
m_emu),
1592 APInt apInt(numBits, rs1);
1594 apInt = APInt(numBits, NanUnBoxing(rs1));
1595 APFloat apf((&apInt->*f)());
1596 return inst.rd.WriteAPFloat(m_emu, apf);
1601 return FMV_i2f(inst, 32, &APInt::bitsToFloat);
1603 template <
typename I,
typename E,
typename T>
1604 bool FCVT_i2f(I inst,
bool isDouble, T (APFloat::*f)()
const) {
1605 return transformOptional(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1607 E res = E((&rs1->*f)());
1608 return inst.rd.Write(m_emu, uint64_t(res));
1614 &APFloat::convertToFloat);
1618 &APFloat::convertToFloat);
1648 return transformOptional(inst.rs1.ReadAPFloat(
m_emu,
true),
1650 double d = rs1.convertToDouble();
1651 APFloat apf((float(d)));
1652 return inst.rd.WriteAPFloat(m_emu, apf);
1657 return transformOptional(inst.rs1.ReadAPFloat(
m_emu,
false),
1659 float f = rs1.convertToFloat();
1660 APFloat apf((double(f)));
1661 return inst.rd.WriteAPFloat(m_emu, apf);
1671 &APFloat::convertToDouble);
1675 &APFloat::convertToDouble);
1685 &APFloat::convertToDouble);
1689 &APFloat::convertToDouble);
1699 return FMV_i2f(inst, 64, &APInt::bitsToDouble);
1713 bool increase_pc = options & eEmulateInstructionOptionAutoAdvancePC;
1714 bool ignore_cond = options & eEmulateInstructionOptionIgnoreConditions;
1732 return new_pc != old_pc ||
1736std::optional<DecodeResult>
1739 [&](uint32_t inst) {
return Decode(inst); })
1740 .value_or(std::nullopt);
1760 bool success =
false;
1764 return RoundingMode::Invalid;
1765 auto frm = (fcsr >> 5) & 0x7;
1768 return RoundingMode::NearestTiesToEven;
1770 return RoundingMode::TowardZero;
1772 return RoundingMode::TowardNegative;
1774 return RoundingMode::TowardPositive;
1776 return RoundingMode::Dynamic;
1779 return RoundingMode::Invalid;
1784 APFloatBase::opStatus opStatus) {
1785 bool success =
false;
1791 case APFloatBase::opInvalidOp:
1794 case APFloatBase::opDivByZero:
1797 case APFloatBase::opOverflow:
1800 case APFloatBase::opUnderflow:
1803 case APFloatBase::opInexact:
1806 case APFloatBase::opOK:
1815std::optional<RegisterInfo>
1817 uint32_t reg_index) {
1819 switch (reg_index) {
1839 llvm_unreachable(
"unsupported register");
1843 std::unique_ptr<RegisterInfoInterface> reg_info;
1844 switch (
m_arch.GetTriple().getArch()) {
1845 case llvm::Triple::riscv32:
1846 reg_info = std::make_unique<RegisterInfoPOSIX_riscv32>(
1849 case llvm::Triple::riscv64:
1850 reg_info = std::make_unique<RegisterInfoPOSIX_riscv64>(
1854 assert(
false &&
"unsupported triple");
1858 const RegisterInfo *array = reg_info->GetRegisterInfo();
1859 const uint32_t length = reg_info->GetRegisterCount();
1864 return array[reg_index];
1875 uint32_t inst_data = 0;
1876 const void *opcode_data =
m_opcode.GetOpcodeBytes();
1882 const uint16_t *data =
static_cast<const uint16_t *
>(opcode_data);
1884 }
else if (
m_opcode.GetByteSize() == 4) {
1886 const uint32_t *data =
static_cast<const uint32_t *
>(opcode_data);
1893 auto decoded_inst =
Decode(inst_data);
1904 unwind_plan.
Clear();
1955llvm::Expected<BreakpointLocations>
1960 std::optional<addr_t>
pc = riscv_emulator->
ReadPC();
1962 return llvm::createStringError(
"Can't read PC");
1979 "RISCVSingleStepBreakpointLocationsPredictor::%s: can't find "
1980 "corresponding load reserve instruction",
1988llvm::Expected<unsigned>
1995 return inst->is_rvc ? 2 : 4;
2000 return *last_instr_size;
2006llvm::Expected<BreakpointLocations>
2017 pc += lr_inst->is_rvc ? 2 : 4;
2019 size_t atomic_length = 0;
2020 std::optional<DecodeResult> inst;
2021 std::vector<lldb::addr_t> bp_addrs;
2025 return llvm::createStringError(
"Can't read instruction");
2027 if (
B *branch = std::get_if<B>(&inst->decoded))
2028 bp_addrs.push_back(
pc +
SignExt(branch->imm));
2030 unsigned addent = inst->is_rvc ? 2 : 4;
2032 atomic_length += addent;
2042 "RISCVSingleStepBreakpointLocationsPredictor::%s: can't find "
2043 "corresponding store conditional instruction",
2055 B *branch = std::get_if<B>(&inst->decoded);
2056 if (branch && (exit_pc +
SignExt(branch->
imm)) == entry_pc)
2057 exit_pc += inst->is_rvc ? 2 : 4;
2063 bp_addrs, [exit_pc](
lldb::addr_t bp_addr) {
return exit_pc >= bp_addr; });
2066 bp_addrs.push_back(exit_pc);
#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)
llvm::Expected< BreakpointLocations > HandleAtomicSequence(lldb::addr_t pc)
static bool FoundStoreConditional(const RISCVInst &inst)
static constexpr size_t s_max_atomic_sequence_length
llvm::Expected< BreakpointLocations > GetBreakpointLocations() override
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 llvm::Expected< BreakpointLocations > GetBreakpointLocations()
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)