24#include "llvm/ADT/STLExtras.h"
25#include "llvm/Support/MathExtras.h"
38template <
typename... Ts>
39static std::optional<std::tuple<Ts...>>
zipOpt(std::optional<Ts> &&...ts) {
40 if ((ts.has_value() && ...))
41 return std::optional<std::tuple<Ts...>>(std::make_tuple(std::move(*ts)...));
61constexpr std::enable_if_t<
sizeof(T) <= 4, uint64_t> SextW(T value) {
62 return uint64_t(int64_t(int32_t(value)));
66template <
typename T>
constexpr uint64_t ZextD(T value) {
67 return uint64_t(value);
71 return (uint64_t(int64_t(int32_t(inst & 0x80000000)) >> 11))
73 | ((inst >> 9) & 0x800)
74 | ((inst >> 20) & 0x7fe);
78 return int64_t(int32_t(inst)) >> 20;
82 return (uint64_t(int64_t(int32_t(inst & 0x80000000)) >> 19))
83 | ((inst & 0x80) << 4)
84 | ((inst >> 20) & 0x7e0)
85 | ((inst >> 7) & 0x1e);
89 return (uint64_t(int64_t(int32_t(inst & 0xFE000000)) >> 20))
90 | ((inst & 0xF80) >> 7);
94 return SextW(inst & 0xFFFFF000);
100 if (reg_encode >= 1 && reg_encode <= 31)
106 if (reg_encode <= 31)
128 registerValue.
SetUInt64(value.bitcastToAPInt().getZExtValue());
142 return transformOptional(
143 Read(emulator), [](uint64_t value) {
return int32_t(
uint32_t(value)); });
147 return transformOptional(
Read(emulator),
148 [](uint64_t value) {
return int64_t(value); });
152 return transformOptional(
Read(emulator),
153 [](uint64_t value) {
return uint32_t(value); });
163 APInt api(64,
bits,
false);
164 return APFloat(isDouble ? APFloat(api.bitsToDouble())
165 : APFloat(api.bitsToFloat()));
175 return int64_t(rs1) < int64_t(rs2);
177 return int64_t(rs1) >= int64_t(rs2);
183 llvm_unreachable(
"unexpected funct3");
189 std::is_same_v<T, LB> || std::is_same_v<T, LH> || std::is_same_v<T, LW> ||
190 std::is_same_v<T, LD> || std::is_same_v<T, LBU> || std::is_same_v<T, LHU> ||
191 std::is_same_v<T, LWU>;
194constexpr bool is_store = std::is_same_v<T, SB> || std::is_same_v<T, SH> ||
195 std::is_same_v<T, SW> || std::is_same_v<T, SD>;
199 std::is_same_v<T, AMOADD_W> || std::is_same_v<T, AMOADD_D>;
203 std::is_same_v<T, AMOXOR_W> || std::is_same_v<T, AMOXOR_D> ||
204 std::is_same_v<T, AMOAND_W> || std::is_same_v<T, AMOAND_D> ||
205 std::is_same_v<T, AMOOR_W> || std::is_same_v<T, AMOOR_D>;
209 std::is_same_v<T, AMOSWAP_W> || std::is_same_v<T, AMOSWAP_D>;
213 std::is_same_v<T, AMOMIN_W> || std::is_same_v<T, AMOMIN_D> ||
214 std::is_same_v<T, AMOMAX_W> || std::is_same_v<T, AMOMAX_D> ||
215 std::is_same_v<T, AMOMINU_W> || std::is_same_v<T, AMOMINU_D> ||
216 std::is_same_v<T, AMOMAXU_W> || std::is_same_v<T, AMOMAXU_D>;
219static std::enable_if_t<is_load<I> || is_store<I>, std::optional<uint64_t>>
221 return transformOptional(inst.rs1.Read(emulator), [&](uint64_t rs1) {
222 return rs1 + uint64_t(SignExt(inst.imm));
227template <
typename I,
typename T,
typename E>
228static std::enable_if_t<is_load<I>,
bool>
233 return transformOptional(
235 [&](T t) { return inst.rd.Write(emulator, extend(E(t))); })
239template <
typename I,
typename T>
240static std::enable_if_t<is_store<I>,
bool>
245 return transformOptional(
246 inst.rs2.Read(emulator),
247 [&](uint64_t rs2) { return emulator.WriteMem<T>(*addr, rs2); })
252static std::enable_if_t<is_amo_add<I> || is_amo_bit_op<I> || is_amo_swap<I> ||
254 std::optional<uint64_t>>
256 return transformOptional(inst.rs1.Read(emulator),
258 return rs1 % align == 0
259 ? std::optional<uint64_t>(rs1)
262 .value_or(std::nullopt);
265template <
typename I,
typename T>
266static std::enable_if_t<is_amo_swap<I>,
bool>
268 uint64_t (*extend)(T)) {
269 auto addr =
AtomicAddr(emulator, inst, align);
272 return transformOptional(
275 auto [tmp, rs2] = tup;
276 return emulator.WriteMem<T>(*addr, T(rs2)) &&
277 inst.rd.Write(emulator, extend(tmp));
282template <
typename I,
typename T>
283static std::enable_if_t<is_amo_add<I>,
bool>
285 uint64_t (*extend)(T)) {
286 auto addr =
AtomicAddr(emulator, inst, align);
289 return transformOptional(
292 auto [tmp, rs2] = tup;
293 return emulator.WriteMem<T>(*addr, T(tmp + rs2)) &&
294 inst.rd.Write(emulator, extend(tmp));
299template <
typename I,
typename T>
300static std::enable_if_t<is_amo_bit_op<I>,
bool>
302 uint64_t (*extend)(T), T (*operate)(T, T)) {
303 auto addr =
AtomicAddr(emulator, inst, align);
306 return transformOptional(
309 auto [value, rs2] = tup;
310 return emulator.WriteMem<T>(*addr, operate(value, T(rs2))) &&
311 inst.rd.Write(emulator, extend(value));
316template <
typename I,
typename T>
317static std::enable_if_t<is_amo_cmp<I>,
bool>
319 uint64_t (*extend)(T), T (*cmp)(T, T)) {
320 auto addr =
AtomicAddr(emulator, inst, align);
323 return transformOptional(
326 auto [value, rs2] = tup;
327 return emulator.WriteMem<T>(*addr, cmp(value, T(rs2))) &&
328 inst.rd.Write(emulator, extend(value));
344 auto current_pc = *
pc;
345 const auto entry_pc = current_pc;
349 if (!inst || (!std::holds_alternative<LR_W>(inst->decoded) &&
350 !std::holds_alternative<LR_D>(inst->decoded)))
355 if (!inst || !std::holds_alternative<B>(inst->decoded))
357 auto bne_exit = std::get<B>(inst->decoded);
358 if (bne_exit.funct3 !=
BNE)
361 const auto exit_pc = current_pc + SextW(bne_exit.imm);
365 if (!inst || (!std::holds_alternative<SC_W>(inst->decoded) &&
366 !std::holds_alternative<SC_D>(inst->decoded)))
371 if (!inst || !std::holds_alternative<B>(inst->decoded))
373 auto bne_start = std::get<B>(inst->decoded);
374 if (bne_start.funct3 !=
BNE)
376 if (entry_pc != current_pc + SextW(bne_start.imm))
381 return exit_pc == current_pc && emulator.
WritePC(current_pc);
389 return T{
Rd{
DecodeRD(inst)}, DecodeJImm(inst)};
424 {
"LUI", 0x7F, 0x37, DecodeUType<LUI>},
425 {
"AUIPC", 0x7F, 0x17, DecodeUType<AUIPC>},
426 {
"JAL", 0x7F, 0x6F, DecodeJType<JAL>},
427 {
"JALR", 0x707F, 0x67, DecodeIType<JALR>},
428 {
"B", 0x7F, 0x63, DecodeBType<B>},
429 {
"LB", 0x707F, 0x3, DecodeIType<LB>},
430 {
"LH", 0x707F, 0x1003, DecodeIType<LH>},
431 {
"LW", 0x707F, 0x2003, DecodeIType<LW>},
432 {
"LBU", 0x707F, 0x4003, DecodeIType<LBU>},
433 {
"LHU", 0x707F, 0x5003, DecodeIType<LHU>},
434 {
"SB", 0x707F, 0x23, DecodeSType<SB>},
435 {
"SH", 0x707F, 0x1023, DecodeSType<SH>},
436 {
"SW", 0x707F, 0x2023, DecodeSType<SW>},
437 {
"ADDI", 0x707F, 0x13, DecodeIType<ADDI>},
438 {
"SLTI", 0x707F, 0x2013, DecodeIType<SLTI>},
439 {
"SLTIU", 0x707F, 0x3013, DecodeIType<SLTIU>},
440 {
"XORI", 0x707F, 0x4013, DecodeIType<XORI>},
441 {
"ORI", 0x707F, 0x6013, DecodeIType<ORI>},
442 {
"ANDI", 0x707F, 0x7013, DecodeIType<ANDI>},
443 {
"SLLI", 0xF800707F, 0x1013, DecodeRShamtType<SLLI>},
444 {
"SRLI", 0xF800707F, 0x5013, DecodeRShamtType<SRLI>},
445 {
"SRAI", 0xF800707F, 0x40005013, DecodeRShamtType<SRAI>},
446 {
"ADD", 0xFE00707F, 0x33, DecodeRType<ADD>},
447 {
"SUB", 0xFE00707F, 0x40000033, DecodeRType<SUB>},
448 {
"SLL", 0xFE00707F, 0x1033, DecodeRType<SLL>},
449 {
"SLT", 0xFE00707F, 0x2033, DecodeRType<SLT>},
450 {
"SLTU", 0xFE00707F, 0x3033, DecodeRType<SLTU>},
451 {
"XOR", 0xFE00707F, 0x4033, DecodeRType<XOR>},
452 {
"SRL", 0xFE00707F, 0x5033, DecodeRType<SRL>},
453 {
"SRA", 0xFE00707F, 0x40005033, DecodeRType<SRA>},
454 {
"OR", 0xFE00707F, 0x6033, DecodeRType<OR>},
455 {
"AND", 0xFE00707F, 0x7033, DecodeRType<AND>},
456 {
"LWU", 0x707F, 0x6003, DecodeIType<LWU>},
457 {
"LD", 0x707F, 0x3003, DecodeIType<LD>},
458 {
"SD", 0x707F, 0x3023, DecodeSType<SD>},
459 {
"ADDIW", 0x707F, 0x1B, DecodeIType<ADDIW>},
460 {
"SLLIW", 0xFE00707F, 0x101B, DecodeRShamtType<SLLIW>},
461 {
"SRLIW", 0xFE00707F, 0x501B, DecodeRShamtType<SRLIW>},
462 {
"SRAIW", 0xFE00707F, 0x4000501B, DecodeRShamtType<SRAIW>},
463 {
"ADDW", 0xFE00707F, 0x3B, DecodeRType<ADDW>},
464 {
"SUBW", 0xFE00707F, 0x4000003B, DecodeRType<SUBW>},
465 {
"SLLW", 0xFE00707F, 0x103B, DecodeRType<SLLW>},
466 {
"SRLW", 0xFE00707F, 0x503B, DecodeRType<SRLW>},
467 {
"SRAW", 0xFE00707F, 0x4000503B, DecodeRType<SRAW>},
470 {
"MUL", 0xFE00707F, 0x2000033, DecodeRType<MUL>},
471 {
"MULH", 0xFE00707F, 0x2001033, DecodeRType<MULH>},
472 {
"MULHSU", 0xFE00707F, 0x2002033, DecodeRType<MULHSU>},
473 {
"MULHU", 0xFE00707F, 0x2003033, DecodeRType<MULHU>},
474 {
"DIV", 0xFE00707F, 0x2004033, DecodeRType<DIV>},
475 {
"DIVU", 0xFE00707F, 0x2005033, DecodeRType<DIVU>},
476 {
"REM", 0xFE00707F, 0x2006033, DecodeRType<REM>},
477 {
"REMU", 0xFE00707F, 0x2007033, DecodeRType<REMU>},
478 {
"MULW", 0xFE00707F, 0x200003B, DecodeRType<MULW>},
479 {
"DIVW", 0xFE00707F, 0x200403B, DecodeRType<DIVW>},
480 {
"DIVUW", 0xFE00707F, 0x200503B, DecodeRType<DIVUW>},
481 {
"REMW", 0xFE00707F, 0x200603B, DecodeRType<REMW>},
482 {
"REMUW", 0xFE00707F, 0x200703B, DecodeRType<REMUW>},
485 {
"LR_W", 0xF9F0707F, 0x1000202F, DecodeRRS1Type<LR_W>},
486 {
"LR_D", 0xF9F0707F, 0x1000302F, DecodeRRS1Type<LR_D>},
487 {
"SC_W", 0xF800707F, 0x1800202F, DecodeRType<SC_W>},
488 {
"SC_D", 0xF800707F, 0x1800302F, DecodeRType<SC_D>},
489 {
"AMOSWAP_W", 0xF800707F, 0x800202F, DecodeRType<AMOSWAP_W>},
490 {
"AMOADD_W", 0xF800707F, 0x202F, DecodeRType<AMOADD_W>},
491 {
"AMOXOR_W", 0xF800707F, 0x2000202F, DecodeRType<AMOXOR_W>},
492 {
"AMOAND_W", 0xF800707F, 0x6000202F, DecodeRType<AMOAND_W>},
493 {
"AMOOR_W", 0xF800707F, 0x4000202F, DecodeRType<AMOOR_W>},
494 {
"AMOMIN_W", 0xF800707F, 0x8000202F, DecodeRType<AMOMIN_W>},
495 {
"AMOMAX_W", 0xF800707F, 0xA000202F, DecodeRType<AMOMAX_W>},
496 {
"AMOMINU_W", 0xF800707F, 0xC000202F, DecodeRType<AMOMINU_W>},
497 {
"AMOMAXU_W", 0xF800707F, 0xE000202F, DecodeRType<AMOMAXU_W>},
498 {
"AMOSWAP_D", 0xF800707F, 0x800302F, DecodeRType<AMOSWAP_D>},
499 {
"AMOADD_D", 0xF800707F, 0x302F, DecodeRType<AMOADD_D>},
500 {
"AMOXOR_D", 0xF800707F, 0x2000302F, DecodeRType<AMOXOR_D>},
501 {
"AMOAND_D", 0xF800707F, 0x6000302F, DecodeRType<AMOAND_D>},
502 {
"AMOOR_D", 0xF800707F, 0x4000302F, DecodeRType<AMOOR_D>},
503 {
"AMOMIN_D", 0xF800707F, 0x8000302F, DecodeRType<AMOMIN_D>},
504 {
"AMOMAX_D", 0xF800707F, 0xA000302F, DecodeRType<AMOMAX_D>},
505 {
"AMOMINU_D", 0xF800707F, 0xC000302F, DecodeRType<AMOMINU_D>},
506 {
"AMOMAXU_D", 0xF800707F, 0xE000302F, DecodeRType<AMOMAXU_D>},
551 {
"FLW", 0x707F, 0x2007, DecodeIType<FLW>},
552 {
"FSW", 0x707F, 0x2027, DecodeSType<FSW>},
553 {
"FMADD_S", 0x600007F, 0x43, DecodeR4Type<FMADD_S>},
554 {
"FMSUB_S", 0x600007F, 0x47, DecodeR4Type<FMSUB_S>},
555 {
"FNMSUB_S", 0x600007F, 0x4B, DecodeR4Type<FNMSUB_S>},
556 {
"FNMADD_S", 0x600007F, 0x4F, DecodeR4Type<FNMADD_S>},
557 {
"FADD_S", 0xFE00007F, 0x53, DecodeRType<FADD_S>},
558 {
"FSUB_S", 0xFE00007F, 0x8000053, DecodeRType<FSUB_S>},
559 {
"FMUL_S", 0xFE00007F, 0x10000053, DecodeRType<FMUL_S>},
560 {
"FDIV_S", 0xFE00007F, 0x18000053, DecodeRType<FDIV_S>},
561 {
"FSQRT_S", 0xFFF0007F, 0x58000053, DecodeIType<FSQRT_S>},
562 {
"FSGNJ_S", 0xFE00707F, 0x20000053, DecodeRType<FSGNJ_S>},
563 {
"FSGNJN_S", 0xFE00707F, 0x20001053, DecodeRType<FSGNJN_S>},
564 {
"FSGNJX_S", 0xFE00707F, 0x20002053, DecodeRType<FSGNJX_S>},
565 {
"FMIN_S", 0xFE00707F, 0x28000053, DecodeRType<FMIN_S>},
566 {
"FMAX_S", 0xFE00707F, 0x28001053, DecodeRType<FMAX_S>},
567 {
"FCVT_W_S", 0xFFF0007F, 0xC0000053, DecodeIType<FCVT_W_S>},
568 {
"FCVT_WU_S", 0xFFF0007F, 0xC0100053, DecodeIType<FCVT_WU_S>},
569 {
"FMV_X_W", 0xFFF0707F, 0xE0000053, DecodeIType<FMV_X_W>},
570 {
"FEQ_S", 0xFE00707F, 0xA0002053, DecodeRType<FEQ_S>},
571 {
"FLT_S", 0xFE00707F, 0xA0001053, DecodeRType<FLT_S>},
572 {
"FLE_S", 0xFE00707F, 0xA0000053, DecodeRType<FLE_S>},
573 {
"FCLASS_S", 0xFFF0707F, 0xE0001053, DecodeIType<FCLASS_S>},
574 {
"FCVT_S_W", 0xFFF0007F, 0xD0000053, DecodeIType<FCVT_S_W>},
575 {
"FCVT_S_WU", 0xFFF0007F, 0xD0100053, DecodeIType<FCVT_S_WU>},
576 {
"FMV_W_X", 0xFFF0707F, 0xF0000053, DecodeIType<FMV_W_X>},
579 {
"FCVT_L_S", 0xFFF0007F, 0xC0200053, DecodeIType<FCVT_L_S>},
580 {
"FCVT_LU_S", 0xFFF0007F, 0xC0300053, DecodeIType<FCVT_LU_S>},
581 {
"FCVT_S_L", 0xFFF0007F, 0xD0200053, DecodeIType<FCVT_S_L>},
582 {
"FCVT_S_LU", 0xFFF0007F, 0xD0300053, DecodeIType<FCVT_S_LU>},
585 {
"FLD", 0x707F, 0x3007, DecodeIType<FLD>},
586 {
"FSD", 0x707F, 0x3027, DecodeSType<FSD>},
587 {
"FMADD_D", 0x600007F, 0x2000043, DecodeR4Type<FMADD_D>},
588 {
"FMSUB_D", 0x600007F, 0x2000047, DecodeR4Type<FMSUB_D>},
589 {
"FNMSUB_D", 0x600007F, 0x200004B, DecodeR4Type<FNMSUB_D>},
590 {
"FNMADD_D", 0x600007F, 0x200004F, DecodeR4Type<FNMADD_D>},
591 {
"FADD_D", 0xFE00007F, 0x2000053, DecodeRType<FADD_D>},
592 {
"FSUB_D", 0xFE00007F, 0xA000053, DecodeRType<FSUB_D>},
593 {
"FMUL_D", 0xFE00007F, 0x12000053, DecodeRType<FMUL_D>},
594 {
"FDIV_D", 0xFE00007F, 0x1A000053, DecodeRType<FDIV_D>},
595 {
"FSQRT_D", 0xFFF0007F, 0x5A000053, DecodeIType<FSQRT_D>},
596 {
"FSGNJ_D", 0xFE00707F, 0x22000053, DecodeRType<FSGNJ_D>},
597 {
"FSGNJN_D", 0xFE00707F, 0x22001053, DecodeRType<FSGNJN_D>},
598 {
"FSGNJX_D", 0xFE00707F, 0x22002053, DecodeRType<FSGNJX_D>},
599 {
"FMIN_D", 0xFE00707F, 0x2A000053, DecodeRType<FMIN_D>},
600 {
"FMAX_D", 0xFE00707F, 0x2A001053, DecodeRType<FMAX_D>},
601 {
"FCVT_S_D", 0xFFF0007F, 0x40100053, DecodeIType<FCVT_S_D>},
602 {
"FCVT_D_S", 0xFFF0007F, 0x42000053, DecodeIType<FCVT_D_S>},
603 {
"FEQ_D", 0xFE00707F, 0xA2002053, DecodeRType<FEQ_D>},
604 {
"FLT_D", 0xFE00707F, 0xA2001053, DecodeRType<FLT_D>},
605 {
"FLE_D", 0xFE00707F, 0xA2000053, DecodeRType<FLE_D>},
606 {
"FCLASS_D", 0xFFF0707F, 0xE2001053, DecodeIType<FCLASS_D>},
607 {
"FCVT_W_D", 0xFFF0007F, 0xC2000053, DecodeIType<FCVT_W_D>},
608 {
"FCVT_WU_D", 0xFFF0007F, 0xC2100053, DecodeIType<FCVT_WU_D>},
609 {
"FCVT_D_W", 0xFFF0007F, 0xD2000053, DecodeIType<FCVT_D_W>},
610 {
"FCVT_D_WU", 0xFFF0007F, 0xD2100053, DecodeIType<FCVT_D_WU>},
613 {
"FCVT_L_D", 0xFFF0007F, 0xC2200053, DecodeIType<FCVT_L_D>},
614 {
"FCVT_LU_D", 0xFFF0007F, 0xC2300053, DecodeIType<FCVT_LU_D>},
615 {
"FMV_X_D", 0xFFF0707F, 0xE2000053, DecodeIType<FMV_X_D>},
616 {
"FCVT_D_L", 0xFFF0007F, 0xD2200053, DecodeIType<FCVT_D_L>},
617 {
"FCVT_D_LU", 0xFFF0007F, 0xD2300053, DecodeIType<FCVT_D_LU>},
618 {
"FMV_D_X", 0xFFF0707F, 0xF2000053, DecodeIType<FMV_D_X>},
627 bool is_rvc = try_rvc != 0 && mask != 3;
628 uint8_t inst_type =
RV64;
636 if ((inst & pat.type_mask) == pat.eigen &&
637 (inst_type & pat.inst_type) != 0) {
639 log,
"EmulateInstructionRISCV::%s: inst(%x at %" PRIx64
") was decoded to %s",
640 __FUNCTION__, inst,
m_addr, pat.name);
641 auto decoded = is_rvc ? pat.decode(try_rvc) : pat.decode(inst);
645 LLDB_LOGF(log,
"EmulateInstructionRISCV::%s: inst(0x%x) was unsupported",
657 static uint64_t
size(
bool is_rvc) {
return is_rvc ? 2 : 4; }
670 return inst.rd.Write(m_emu,
671 SignExt(inst.imm) + pc);
678 return inst.rd.Write(m_emu, pc + delta()) &&
679 m_emu.WritePC(SignExt(inst.imm) + pc);
686 auto [pc, rs1] = tup;
687 return inst.rd.Write(m_emu, pc + delta()) &&
688 m_emu.WritePC((SignExt(inst.imm) + rs1) &
697 auto [pc, rs1, rs2] = tup;
699 CompareB(rs1, rs2, inst.funct3))
700 return m_emu.WritePC(SignExt(inst.imm) + pc);
706 return Load<LB, uint8_t, int8_t>(
m_emu, inst, SextW);
709 return Load<LH, uint16_t, int16_t>(
m_emu, inst, SextW);
712 return Load<LW, uint32_t, int32_t>(
m_emu, inst, SextW);
715 return Load<LBU, uint8_t, uint8_t>(
m_emu, inst, ZextD);
718 return Load<LHU, uint16_t, uint16_t>(
m_emu, inst, ZextD);
724 return transformOptional(inst.rs1.ReadI64(
m_emu),
726 return inst.rd.Write(
727 m_emu, rs1 + int64_t(SignExt(inst.imm)));
732 return transformOptional(inst.rs1.ReadI64(
m_emu),
734 return inst.rd.Write(
735 m_emu, rs1 < int64_t(SignExt(inst.imm)));
740 return transformOptional(inst.rs1.Read(
m_emu),
742 return inst.rd.Write(
743 m_emu, rs1 < uint64_t(SignExt(inst.imm)));
748 return transformOptional(inst.rs1.Read(
m_emu),
750 return inst.rd.Write(
751 m_emu, rs1 ^ uint64_t(SignExt(inst.imm)));
756 return transformOptional(inst.rs1.Read(
m_emu),
758 return inst.rd.Write(
759 m_emu, rs1 | uint64_t(SignExt(inst.imm)));
764 return transformOptional(inst.rs1.Read(
m_emu),
766 return inst.rd.Write(
767 m_emu, rs1 & uint64_t(SignExt(inst.imm)));
772 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
774 auto [rs1, rs2] = tup;
775 return inst.rd.Write(m_emu, rs1 + rs2);
780 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
782 auto [rs1, rs2] = tup;
783 return inst.rd.Write(m_emu, rs1 - rs2);
788 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
790 auto [rs1, rs2] = tup;
791 return inst.rd.Write(m_emu,
792 rs1 << (rs2 & 0b111111));
797 return transformOptional(
800 auto [rs1, rs2] = tup;
801 return inst.rd.Write(m_emu, rs1 < rs2);
806 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
808 auto [rs1, rs2] = tup;
809 return inst.rd.Write(m_emu, rs1 < rs2);
814 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
816 auto [rs1, rs2] = tup;
817 return inst.rd.Write(m_emu, rs1 ^ rs2);
822 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
824 auto [rs1, rs2] = tup;
825 return inst.rd.Write(m_emu,
826 rs1 >> (rs2 & 0b111111));
831 return transformOptional(
834 auto [rs1, rs2] = tup;
835 return inst.rd.Write(m_emu, rs1 >> (rs2 & 0b111111));
840 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
842 auto [rs1, rs2] = tup;
843 return inst.rd.Write(m_emu, rs1 | rs2);
848 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
850 auto [rs1, rs2] = tup;
851 return inst.rd.Write(m_emu, rs1 & rs2);
856 return Load<LWU, uint32_t, uint32_t>(
m_emu, inst, ZextD);
859 return Load<LD, uint64_t, uint64_t>(
m_emu, inst, ZextD);
863 return transformOptional(inst.rs1.Read(
m_emu),
865 return inst.rd.Write(m_emu, rs1 << inst.shamt);
870 return transformOptional(inst.rs1.Read(
m_emu),
872 return inst.rd.Write(m_emu, rs1 >> inst.shamt);
877 return transformOptional(inst.rs1.ReadI64(
m_emu),
879 return inst.rd.Write(m_emu, rs1 >> inst.shamt);
884 return transformOptional(inst.rs1.ReadI32(
m_emu),
886 return inst.rd.Write(
887 m_emu, SextW(rs1 + SignExt(inst.imm)));
892 return transformOptional(inst.rs1.ReadU32(
m_emu),
894 return inst.rd.Write(m_emu,
895 SextW(rs1 << inst.shamt));
900 return transformOptional(inst.rs1.ReadU32(
m_emu),
902 return inst.rd.Write(m_emu,
903 SextW(rs1 >> inst.shamt));
908 return transformOptional(inst.rs1.ReadI32(
m_emu),
910 return inst.rd.Write(m_emu,
911 SextW(rs1 >> inst.shamt));
916 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
918 auto [rs1, rs2] = tup;
919 return inst.rd.Write(m_emu,
920 SextW(uint32_t(rs1 + rs2)));
925 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
927 auto [rs1, rs2] = tup;
928 return inst.rd.Write(m_emu,
929 SextW(uint32_t(rs1 - rs2)));
934 return transformOptional(
937 auto [rs1, rs2] = tup;
938 return inst.rd.Write(m_emu, SextW(rs1 << (rs2 & 0b11111)));
943 return transformOptional(
946 auto [rs1, rs2] = tup;
947 return inst.rd.Write(m_emu, SextW(rs1 >> (rs2 & 0b11111)));
952 return transformOptional(
955 auto [rs1, rs2] = tup;
956 return inst.rd.Write(m_emu, SextW(rs1 >> (rs2 & 0b11111)));
962 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
964 auto [rs1, rs2] = tup;
965 return inst.rd.Write(m_emu, rs1 * rs2);
970 return transformOptional(
973 auto [rs1, rs2] = tup;
975 auto mul = APInt(128, rs1, true) * APInt(128, rs2, true);
976 return inst.rd.Write(m_emu,
977 mul.ashr(64).trunc(64).getZExtValue());
982 return transformOptional(
985 auto [rs1, rs2] = tup;
988 APInt(128, rs1, true).zext(128) * APInt(128, rs2, false);
989 return inst.rd.Write(m_emu,
990 mul.lshr(64).trunc(64).getZExtValue());
995 return transformOptional(
998 auto [rs1, rs2] = tup;
1000 auto mul = APInt(128, rs1, false) * APInt(128, rs2, false);
1001 return inst.rd.Write(m_emu,
1002 mul.lshr(64).trunc(64).getZExtValue());
1007 return transformOptional(
1010 auto [dividend, divisor] = tup;
1013 return inst.rd.Write(m_emu, UINT64_MAX);
1015 if (dividend == INT64_MIN && divisor == -1)
1016 return inst.rd.Write(m_emu, dividend);
1018 return inst.rd.Write(m_emu, dividend / divisor);
1023 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
1025 auto [dividend, divisor] = tup;
1028 return inst.rd.Write(m_emu, UINT64_MAX);
1030 return inst.rd.Write(m_emu, dividend / divisor);
1035 return transformOptional(
1038 auto [dividend, divisor] = tup;
1041 return inst.rd.Write(m_emu, dividend);
1043 if (dividend == INT64_MIN && divisor == -1)
1044 return inst.rd.Write(m_emu, 0);
1046 return inst.rd.Write(m_emu, dividend % divisor);
1051 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
1053 auto [dividend, divisor] = tup;
1056 return inst.rd.Write(m_emu, dividend);
1058 return inst.rd.Write(m_emu, dividend % divisor);
1063 return transformOptional(
1066 auto [rs1, rs2] = tup;
1067 return inst.rd.Write(m_emu, SextW(rs1 * rs2));
1072 return transformOptional(
1075 auto [dividend, divisor] = tup;
1078 return inst.rd.Write(m_emu, UINT64_MAX);
1080 if (dividend == INT32_MIN && divisor == -1)
1081 return inst.rd.Write(m_emu, SextW(dividend));
1083 return inst.rd.Write(m_emu, SextW(dividend / divisor));
1088 return transformOptional(
1091 auto [dividend, divisor] = tup;
1094 return inst.rd.Write(m_emu, UINT64_MAX);
1096 return inst.rd.Write(m_emu, SextW(dividend / divisor));
1101 return transformOptional(
1104 auto [dividend, divisor] = tup;
1107 return inst.rd.Write(m_emu, SextW(dividend));
1109 if (dividend == INT32_MIN && divisor == -1)
1110 return inst.rd.Write(m_emu, 0);
1112 return inst.rd.Write(m_emu, SextW(dividend % divisor));
1117 return transformOptional(
1120 auto [dividend, divisor] = tup;
1123 return inst.rd.Write(m_emu, SextW(dividend));
1125 return inst.rd.Write(m_emu, SextW(dividend % divisor));
1133 llvm_unreachable(
"should be handled in AtomicSequence");
1136 llvm_unreachable(
"should be handled in AtomicSequence");
1139 return AtomicSwap<AMOSWAP_W, uint32_t>(
m_emu, inst, 4, SextW);
1142 return AtomicADD<AMOADD_W, uint32_t>(
m_emu, inst, 4, SextW);
1145 return AtomicBitOperate<AMOXOR_W, uint32_t>(
1149 return AtomicBitOperate<AMOAND_W, uint32_t>(
1153 return AtomicBitOperate<AMOOR_W, uint32_t>(
1157 return AtomicCmp<AMOMIN_W, uint32_t>(
1159 return uint32_t(std::min(int32_t(a), int32_t(b)));
1163 return AtomicCmp<AMOMAX_W, uint32_t>(
1165 return uint32_t(std::max(int32_t(a), int32_t(b)));
1169 return AtomicCmp<AMOMINU_W, uint32_t>(
1170 m_emu, inst, 4, SextW,
1174 return AtomicCmp<AMOMAXU_W, uint32_t>(
1175 m_emu, inst, 4, SextW,
1179 return AtomicSwap<AMOSWAP_D, uint64_t>(
m_emu, inst, 8, ZextD);
1182 return AtomicADD<AMOADD_D, uint64_t>(
m_emu, inst, 8, ZextD);
1185 return AtomicBitOperate<AMOXOR_D, uint64_t>(
1186 m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) {
return a ^ b; });
1189 return AtomicBitOperate<AMOAND_D, uint64_t>(
1190 m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) {
return a & b; });
1193 return AtomicBitOperate<AMOOR_D, uint64_t>(
1194 m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) {
return a | b; });
1197 return AtomicCmp<AMOMIN_D, uint64_t>(
1198 m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) {
1199 return uint64_t(std::min(int64_t(a), int64_t(b)));
1203 return AtomicCmp<AMOMAX_D, uint64_t>(
1204 m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) {
1205 return uint64_t(std::max(int64_t(a), int64_t(b)));
1209 return AtomicCmp<AMOMINU_D, uint64_t>(
1210 m_emu, inst, 8, ZextD,
1211 [](uint64_t a, uint64_t b) {
return std::min(a, b); });
1214 return AtomicCmp<AMOMAXU_D, uint64_t>(
1215 m_emu, inst, 8, ZextD,
1216 [](uint64_t a, uint64_t b) {
return std::max(a, b); });
1218 template <
typename T>
1219 bool F_Load(T inst,
const fltSemantics &(*semantics)(),
1220 unsigned int numBits) {
1221 return transformOptional(inst.rs1.Read(
m_emu),
1223 uint64_t addr = rs1 + uint64_t(inst.imm);
1224 uint64_t bits = *m_emu.ReadMem<uint64_t>(addr);
1225 APFloat f(semantics(), APInt(numBits, bits));
1226 return inst.rd.WriteAPFloat(m_emu, f);
1231 template <
typename T>
bool F_Store(T inst,
bool isDouble) {
1232 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu),
1233 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1235 auto [rs1, rs2] = tup;
1236 uint64_t addr = rs1 + uint64_t(inst.imm);
1238 rs2.bitcastToAPInt().getZExtValue();
1239 return m_emu.WriteMem<uint64_t>(addr, bits);
1250 template <
typename T>
1251 bool FMA(T inst,
bool isDouble,
float rs2_sign,
float rs3_sign) {
1252 return transformOptional(
zipOpt(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1253 inst.rs2.ReadAPFloat(
m_emu, isDouble),
1254 inst.rs3.ReadAPFloat(
m_emu, isDouble)),
1256 auto [rs1, rs2, rs3] = tup;
1257 rs2.copySign(APFloat(rs2_sign));
1258 rs3.copySign(APFloat(rs3_sign));
1259 auto [res, f] = FusedMultiplyAdd(rs1, rs2, rs3);
1260 return res && inst.rd.WriteAPFloat(m_emu, f);
1268 template <
typename T>
1270 APFloat::opStatus (APFloat::*f)(
const APFloat &RHS,
1271 APFloat::roundingMode RM)) {
1272 return transformOptional(
zipOpt(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1273 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1275 auto [rs1, rs2] = tup;
1277 ((&rs1)->*f)(rs2, m_emu.GetRoundingMode());
1278 inst.rd.WriteAPFloat(m_emu, rs1);
1279 return m_emu.SetAccruedExceptions(res);
1291 template <
typename T>
bool F_SignInj(T inst,
bool isDouble,
bool isNegate) {
1292 return transformOptional(
zipOpt(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1293 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1295 auto [rs1, rs2] = tup;
1299 return inst.rd.WriteAPFloat(m_emu, rs1);
1306 return transformOptional(
zipOpt(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1307 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1309 auto [rs1, rs2] = tup;
1314 if (rs1.isNegative() == rs2.isNegative()) {
1320 return inst.rd.WriteAPFloat(
m_emu, rs1);
1324 bool operator()(FSGNJX_S inst) {
return F_SignInjXor(inst,
false); }
1325 template <
typename T>
1327 APFloat (*f)(
const APFloat &A,
const APFloat &
B)) {
1328 return transformOptional(
1329 zipOpt(inst.rs1.ReadAPFloat(m_emu, isDouble),
1330 inst.rs2.ReadAPFloat(m_emu, isDouble)),
1332 auto [rs1, rs2] = tup;
1337 if (rs1.isNaN() || rs2.isNaN())
1338 m_emu.SetAccruedExceptions(APFloat::opInvalidOp);
1339 if (rs1.isNaN() && rs2.isNaN()) {
1340 auto canonicalNaN = APFloat::getQNaN(rs1.getSemantics());
1341 return inst.rd.WriteAPFloat(m_emu, canonicalNaN);
1343 return inst.rd.WriteAPFloat(m_emu, f(rs1, rs2));
1347 bool operator()(FMIN_S inst) {
return F_MAX_MIN(inst,
false, minnum); }
1348 bool operator()(FMAX_S inst) {
return F_MAX_MIN(inst,
false, maxnum); }
1350 return FCVT_i2f<FCVT_W_S, int32_t, float>(inst,
false,
1351 &APFloat::convertToFloat);
1354 return FCVT_i2f<FCVT_WU_S, uint32_t, float>(inst,
false,
1355 &APFloat::convertToFloat);
1357 template <
typename T>
bool FMV_f2i(T inst,
bool isDouble) {
1358 return transformOptional(
1359 inst.rs1.ReadAPFloat(m_emu, isDouble),
1363 return inst.rd.Write(m_emu, 0x7ff8'0000'0000'0000);
1365 return inst.rd.Write(m_emu, 0x7fc0'0000);
1367 auto bits = rs1.bitcastToAPInt().getZExtValue();
1369 return inst.rd.Write(m_emu,
bits);
1371 return inst.rd.Write(m_emu, uint64_t(
bits & 0xffff'ffff));
1382 return transformOptional(
1383 zipOpt(inst.rs1.ReadAPFloat(m_emu, isDouble),
1384 inst.rs2.ReadAPFloat(m_emu, isDouble)),
1386 auto [rs1, rs2] = tup;
1387 if (rs1.isNaN() || rs2.isNaN()) {
1389 if (rs1.isSignaling() || rs2.isSignaling()) {
1391 m_emu.SetAccruedExceptions(APFloat::opInvalidOp);
1392 return res && inst.rd.Write(m_emu, 0);
1395 auto res = m_emu.SetAccruedExceptions(APFloat::opInvalidOp);
1396 return res && inst.rd.Write(m_emu, 0);
1400 return inst.rd.Write(m_emu,
1401 rs1.compare(rs2) == APFloat::cmpEqual);
1403 return inst.rd.Write(m_emu, rs1.compare(rs2) ==
1404 APFloat::cmpLessThan);
1406 return inst.rd.Write(m_emu, rs1.compare(rs2) !=
1407 APFloat::cmpGreaterThan);
1409 llvm_unreachable(
"unsupported F_CMP");
1414 bool operator()(FEQ_S inst) {
return F_Compare(inst,
false, FEQ); }
1415 bool operator()(FLT_S inst) {
return F_Compare(inst,
false, FLT); }
1416 bool operator()(FLE_S inst) {
return F_Compare(inst,
false, FLE); }
1417 template <
typename T>
bool FCLASS(T inst,
bool isDouble) {
1418 return transformOptional(inst.rs1.ReadAPFloat(m_emu, isDouble),
1420 uint64_t result = 0;
1421 if (rs1.isInfinity() && rs1.isNegative())
1424 if (rs1.isNormal() && rs1.isNegative())
1427 if (rs1.isDenormal() && rs1.isNegative())
1429 if (rs1.isNegZero())
1431 if (rs1.isPosZero())
1434 if (rs1.isNormal() && !rs1.isNegative())
1437 if (rs1.isDenormal() && !rs1.isNegative())
1439 if (rs1.isInfinity() && !rs1.isNegative())
1442 if (rs1.isSignaling())
1447 return inst.rd.Write(m_emu, result);
1452 template <
typename T,
typename E>
1454 const fltSemantics &semantics) {
1455 return transformOptional(((&inst.rs1)->*f)(m_emu),
1457 APFloat apf(semantics, rs1);
1458 return inst.rd.WriteAPFloat(m_emu, apf);
1463 return FCVT_f2i(inst, &
Rs::ReadI32, APFloat::IEEEsingle());
1466 return FCVT_f2i(inst, &
Rs::ReadU32, APFloat::IEEEsingle());
1468 template <
typename T,
typename E>
1469 bool FMV_i2f(T inst,
unsigned int numBits, E (APInt::*f)()
const) {
1470 return transformOptional(inst.rs1.Read(m_emu),
1472 APInt apInt(numBits, rs1);
1474 apInt = APInt(numBits, NanUnBoxing(rs1));
1475 APFloat apf((&apInt->*f)());
1476 return inst.rd.WriteAPFloat(m_emu, apf);
1481 return FMV_i2f(inst, 32, &APInt::bitsToFloat);
1483 template <
typename I,
typename E,
typename T>
1484 bool FCVT_i2f(I inst,
bool isDouble, T (APFloat::*f)()
const) {
1485 return transformOptional(inst.rs1.ReadAPFloat(m_emu, isDouble),
1487 E res = E((&rs1->*f)());
1488 return inst.rd.Write(m_emu, uint64_t(res));
1493 return FCVT_i2f<FCVT_L_S, int64_t, float>(inst,
false,
1494 &APFloat::convertToFloat);
1497 return FCVT_i2f<FCVT_LU_S, uint64_t, float>(inst,
false,
1498 &APFloat::convertToFloat);
1501 return FCVT_f2i(inst, &
Rs::ReadI64, APFloat::IEEEsingle());
1504 return FCVT_f2i(inst, &
Rs::Read, APFloat::IEEEsingle());
1506 bool operator()(FLD inst) {
return F_Load(inst, &APFloat::IEEEdouble, 64); }
1508 bool operator()(FMADD_D inst) {
return FMA(inst,
true, 1.0f, 1.0f); }
1509 bool operator()(FMSUB_D inst) {
return FMA(inst,
true, 1.0f, -1.0f); }
1510 bool operator()(FNMSUB_D inst) {
return FMA(inst,
true, -1.0f, 1.0f); }
1511 bool operator()(FNMADD_D inst) {
return FMA(inst,
true, -1.0f, -1.0f); }
1512 bool operator()(FADD_D inst) {
return F_Op(inst,
true, &APFloat::add); }
1513 bool operator()(FSUB_D inst) {
return F_Op(inst,
true, &APFloat::subtract); }
1514 bool operator()(FMUL_D inst) {
return F_Op(inst,
true, &APFloat::multiply); }
1515 bool operator()(FDIV_D inst) {
return F_Op(inst,
true, &APFloat::divide); }
1520 bool operator()(FSGNJ_D inst) {
return F_SignInj(inst,
true,
false); }
1521 bool operator()(FSGNJN_D inst) {
return F_SignInj(inst,
true,
true); }
1522 bool operator()(FSGNJX_D inst) {
return F_SignInjXor(inst,
true); }
1523 bool operator()(FMIN_D inst) {
return F_MAX_MIN(inst,
true, minnum); }
1524 bool operator()(FMAX_D inst) {
return F_MAX_MIN(inst,
true, maxnum); }
1526 return transformOptional(inst.rs1.ReadAPFloat(m_emu,
true),
1528 double d = rs1.convertToDouble();
1529 APFloat apf((float(d)));
1530 return inst.rd.WriteAPFloat(m_emu, apf);
1535 return transformOptional(inst.rs1.ReadAPFloat(m_emu,
false),
1537 float f = rs1.convertToFloat();
1538 APFloat apf((double(f)));
1539 return inst.rd.WriteAPFloat(m_emu, apf);
1543 bool operator()(FEQ_D inst) {
return F_Compare(inst,
true, FEQ); }
1544 bool operator()(FLT_D inst) {
return F_Compare(inst,
true, FLT); }
1545 bool operator()(FLE_D inst) {
return F_Compare(inst,
true, FLE); }
1548 return FCVT_i2f<FCVT_W_D, int32_t, double>(inst,
true,
1549 &APFloat::convertToDouble);
1552 return FCVT_i2f<FCVT_WU_D, uint32_t, double>(inst,
true,
1553 &APFloat::convertToDouble);
1556 return FCVT_f2i(inst, &
Rs::ReadI32, APFloat::IEEEdouble());
1559 return FCVT_f2i(inst, &
Rs::ReadU32, APFloat::IEEEdouble());
1562 return FCVT_i2f<FCVT_L_D, int64_t, double>(inst,
true,
1563 &APFloat::convertToDouble);
1566 return FCVT_i2f<FCVT_LU_D, uint64_t, double>(inst,
true,
1567 &APFloat::convertToDouble);
1571 return FCVT_f2i(inst, &
Rs::ReadI64, APFloat::IEEEdouble());
1574 return FCVT_f2i(inst, &
Rs::Read, APFloat::IEEEdouble());
1577 return FMV_i2f(inst, 64, &APInt::bitsToDouble);
1591 bool increase_pc = options & eEmulateInstructionOptionAutoAdvancePC;
1592 bool ignore_cond = options & eEmulateInstructionOptionIgnoreConditions;
1610 return new_pc != old_pc ||
1614std::optional<DecodeResult>
1616 return transformOptional(ReadMem<uint32_t>(addr),
1618 .value_or(std::nullopt);
1638 bool success =
false;
1641 return success ? std::optional<addr_t>(addr) : std::nullopt;
1653 bool success =
false;
1657 return RoundingMode::Invalid;
1658 auto frm = (fcsr >> 5) & 0x7;
1661 return RoundingMode::NearestTiesToEven;
1663 return RoundingMode::TowardZero;
1665 return RoundingMode::TowardNegative;
1667 return RoundingMode::TowardPositive;
1669 return RoundingMode::Dynamic;
1672 return RoundingMode::Invalid;
1677 APFloatBase::opStatus opStatus) {
1678 bool success =
false;
1684 case APFloatBase::opInvalidOp:
1687 case APFloatBase::opDivByZero:
1690 case APFloatBase::opOverflow:
1693 case APFloatBase::opUnderflow:
1696 case APFloatBase::opInexact:
1699 case APFloatBase::opOK:
1708std::optional<RegisterInfo>
1712 switch (reg_index) {
1732 llvm_unreachable(
"unsupported register");
1736 const RegisterInfo *array =
1744 return array[reg_index];
#define LLDB_LOGF(log,...)
#define LLDB_PLUGIN_DEFINE_ADV(ClassName, PluginName)
static const lldb_private::RegisterInfo * GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch)
static uint32_t GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch)
An architecture specification class.
llvm::Triple & GetTriple()
Architecture triple accessor.
std::optional< DecodeResult > ReadInstructionAt(lldb::addr_t addr)
bool WritePC(lldb::addr_t pc)
std::optional< RegisterInfo > GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num) override
bool SetTargetTriple(const ArchSpec &arch) override
bool SetAccruedExceptions(llvm::APFloatBase::opStatus)
bool ReadInstruction() override
static llvm::StringRef GetPluginNameStatic()
static bool SupportsThisArch(const ArchSpec &arch)
bool TestEmulation(Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) override
llvm::RoundingMode GetRoundingMode()
std::optional< DecodeResult > Decode(uint32_t inst)
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< lldb::addr_t > ReadPC()
bool EvaluateInstruction(uint32_t options) 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.
lldb::ByteOrder GetByteOrder() const
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)
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)
void SetOpcode16(uint16_t inst, lldb::ByteOrder order)
void SetOpcode32(uint32_t inst, lldb::ByteOrder order)
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
void SetUInt64(uint64_t uint, Type t=eTypeUInt64)
uint64_t GetAsUInt64(uint64_t fail_value=UINT64_MAX, bool *success_ptr=nullptr) const
A stream class that can stream formatted output to a file.
#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)
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)
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)
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
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 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 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)
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)
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)
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)
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))
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)
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)
RegisterKind
Register numbering types.
@ eRegisterKindGeneric
insn ptr reg, stack ptr reg, etc not specific to any particular target
@ eRegisterKindLLDB
lldb's internal register numbers
bool Write(EmulateInstructionRISCV &emulator, uint64_t value)
bool WriteAPFloat(EmulateInstructionRISCV &emulator, llvm::APFloat value)
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)