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)...));
49constexpr uint32_t
BEQ = 0b000;
50constexpr uint32_t
BNE = 0b001;
51constexpr uint32_t
BLT = 0b100;
52constexpr uint32_t
BGE = 0b101;
53constexpr uint32_t
BLTU = 0b110;
54constexpr uint32_t
BGEU = 0b111;
57constexpr int32_t
SignExt(uint32_t imm) {
return int32_t(imm); }
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);
70constexpr uint32_t DecodeJImm(uint32_t inst) {
71 return (uint64_t(int64_t(int32_t(inst & 0x80000000)) >> 11))
73 | ((inst >> 9) & 0x800)
74 | ((inst >> 20) & 0x7fe);
77constexpr uint32_t DecodeIImm(uint32_t inst) {
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()));
168static bool CompareB(uint64_t rs1, uint64_t rs2, uint32_t funct3) {
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>},
624 uint16_t try_rvc = uint16_t(inst & 0x0000ffff);
625 uint8_t inst_type =
RV64;
629 bool is_16b = (inst & 0b11) != 0b11;
630 bool is_32b = (inst & 0x1f) != 0x1f;
631 bool is_48b = (inst & 0x3f) != 0x1f;
632 bool is_64b = (inst & 0x7f) != 0x3f;
651 if ((inst & pat.type_mask) == pat.eigen &&
652 (inst_type & pat.inst_type) != 0) {
654 log,
"EmulateInstructionRISCV::%s: inst(%x at %" PRIx64
") was decoded to %s",
655 __FUNCTION__, inst,
m_addr, pat.name);
656 auto decoded = is_16b ? pat.decode(try_rvc) : pat.decode(inst);
660 LLDB_LOGF(log,
"EmulateInstructionRISCV::%s: inst(0x%x) was unsupported",
672 static uint64_t
size(
bool is_rvc) {
return is_rvc ? 2 : 4; }
685 return inst.rd.Write(m_emu,
686 SignExt(inst.imm) + pc);
693 return inst.rd.Write(m_emu, pc + delta()) &&
694 m_emu.WritePC(SignExt(inst.imm) + pc);
701 auto [pc, rs1] = tup;
702 return inst.rd.Write(m_emu, pc + delta()) &&
703 m_emu.WritePC((SignExt(inst.imm) + rs1) &
712 auto [pc, rs1, rs2] = tup;
714 CompareB(rs1, rs2, inst.funct3))
715 return m_emu.WritePC(SignExt(inst.imm) + pc);
721 return Load<LB, uint8_t, int8_t>(
m_emu, inst, SextW);
724 return Load<LH, uint16_t, int16_t>(
m_emu, inst, SextW);
727 return Load<LW, uint32_t, int32_t>(
m_emu, inst, SextW);
730 return Load<LBU, uint8_t, uint8_t>(
m_emu, inst, ZextD);
733 return Load<LHU, uint16_t, uint16_t>(
m_emu, inst, ZextD);
739 return transformOptional(inst.rs1.ReadI64(
m_emu),
741 return inst.rd.Write(
742 m_emu, rs1 + int64_t(SignExt(inst.imm)));
747 return transformOptional(inst.rs1.ReadI64(
m_emu),
749 return inst.rd.Write(
750 m_emu, rs1 < int64_t(SignExt(inst.imm)));
755 return transformOptional(inst.rs1.Read(
m_emu),
757 return inst.rd.Write(
758 m_emu, rs1 < uint64_t(SignExt(inst.imm)));
763 return transformOptional(inst.rs1.Read(
m_emu),
765 return inst.rd.Write(
766 m_emu, rs1 ^ uint64_t(SignExt(inst.imm)));
771 return transformOptional(inst.rs1.Read(
m_emu),
773 return inst.rd.Write(
774 m_emu, rs1 | uint64_t(SignExt(inst.imm)));
779 return transformOptional(inst.rs1.Read(
m_emu),
781 return inst.rd.Write(
782 m_emu, rs1 & uint64_t(SignExt(inst.imm)));
787 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
789 auto [rs1, rs2] = tup;
790 return inst.rd.Write(m_emu, rs1 + rs2);
795 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
797 auto [rs1, rs2] = tup;
798 return inst.rd.Write(m_emu, rs1 - rs2);
803 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
805 auto [rs1, rs2] = tup;
806 return inst.rd.Write(m_emu,
807 rs1 << (rs2 & 0b111111));
812 return transformOptional(
815 auto [rs1, rs2] = tup;
816 return inst.rd.Write(m_emu, rs1 < rs2);
821 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
823 auto [rs1, rs2] = tup;
824 return inst.rd.Write(m_emu, rs1 < rs2);
829 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
831 auto [rs1, rs2] = tup;
832 return inst.rd.Write(m_emu, rs1 ^ rs2);
837 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
839 auto [rs1, rs2] = tup;
840 return inst.rd.Write(m_emu,
841 rs1 >> (rs2 & 0b111111));
846 return transformOptional(
849 auto [rs1, rs2] = tup;
850 return inst.rd.Write(m_emu, rs1 >> (rs2 & 0b111111));
855 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
857 auto [rs1, rs2] = tup;
858 return inst.rd.Write(m_emu, rs1 | rs2);
863 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
865 auto [rs1, rs2] = tup;
866 return inst.rd.Write(m_emu, rs1 & rs2);
871 return Load<LWU, uint32_t, uint32_t>(
m_emu, inst, ZextD);
874 return Load<LD, uint64_t, uint64_t>(
m_emu, inst, ZextD);
878 return transformOptional(inst.rs1.Read(
m_emu),
880 return inst.rd.Write(m_emu, rs1 << inst.shamt);
885 return transformOptional(inst.rs1.Read(
m_emu),
887 return inst.rd.Write(m_emu, rs1 >> inst.shamt);
892 return transformOptional(inst.rs1.ReadI64(
m_emu),
894 return inst.rd.Write(m_emu, rs1 >> inst.shamt);
899 return transformOptional(inst.rs1.ReadI32(
m_emu),
901 return inst.rd.Write(
902 m_emu, SextW(rs1 + SignExt(inst.imm)));
907 return transformOptional(inst.rs1.ReadU32(
m_emu),
909 return inst.rd.Write(m_emu,
910 SextW(rs1 << inst.shamt));
915 return transformOptional(inst.rs1.ReadU32(
m_emu),
917 return inst.rd.Write(m_emu,
918 SextW(rs1 >> inst.shamt));
923 return transformOptional(inst.rs1.ReadI32(
m_emu),
925 return inst.rd.Write(m_emu,
926 SextW(rs1 >> inst.shamt));
931 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
933 auto [rs1, rs2] = tup;
934 return inst.rd.Write(m_emu,
935 SextW(uint32_t(rs1 + rs2)));
940 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
942 auto [rs1, rs2] = tup;
943 return inst.rd.Write(m_emu,
944 SextW(uint32_t(rs1 - rs2)));
949 return transformOptional(
952 auto [rs1, rs2] = tup;
953 return inst.rd.Write(m_emu, SextW(rs1 << (rs2 & 0b11111)));
958 return transformOptional(
961 auto [rs1, rs2] = tup;
962 return inst.rd.Write(m_emu, SextW(rs1 >> (rs2 & 0b11111)));
967 return transformOptional(
970 auto [rs1, rs2] = tup;
971 return inst.rd.Write(m_emu, SextW(rs1 >> (rs2 & 0b11111)));
977 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
979 auto [rs1, rs2] = tup;
980 return inst.rd.Write(m_emu, rs1 * rs2);
985 return transformOptional(
988 auto [rs1, rs2] = tup;
990 auto mul = APInt(128, rs1, true) * APInt(128, rs2, true);
991 return inst.rd.Write(m_emu,
992 mul.ashr(64).trunc(64).getZExtValue());
997 return transformOptional(
1000 auto [rs1, rs2] = tup;
1003 APInt(128, rs1, true).zext(128) * APInt(128, rs2, false);
1004 return inst.rd.Write(m_emu,
1005 mul.lshr(64).trunc(64).getZExtValue());
1010 return transformOptional(
1013 auto [rs1, rs2] = tup;
1015 auto mul = APInt(128, rs1, false) * APInt(128, rs2, false);
1016 return inst.rd.Write(m_emu,
1017 mul.lshr(64).trunc(64).getZExtValue());
1022 return transformOptional(
1025 auto [dividend, divisor] = tup;
1028 return inst.rd.Write(m_emu, UINT64_MAX);
1030 if (dividend == INT64_MIN && divisor == -1)
1031 return inst.rd.Write(m_emu, dividend);
1033 return inst.rd.Write(m_emu, dividend / divisor);
1038 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
1040 auto [dividend, divisor] = tup;
1043 return inst.rd.Write(m_emu, UINT64_MAX);
1045 return inst.rd.Write(m_emu, dividend / divisor);
1050 return transformOptional(
1053 auto [dividend, divisor] = tup;
1056 return inst.rd.Write(m_emu, dividend);
1058 if (dividend == INT64_MIN && divisor == -1)
1059 return inst.rd.Write(m_emu, 0);
1061 return inst.rd.Write(m_emu, dividend % divisor);
1066 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu), inst.rs2.Read(
m_emu)),
1068 auto [dividend, divisor] = tup;
1071 return inst.rd.Write(m_emu, dividend);
1073 return inst.rd.Write(m_emu, dividend % divisor);
1078 return transformOptional(
1081 auto [rs1, rs2] = tup;
1082 return inst.rd.Write(m_emu, SextW(rs1 * rs2));
1087 return transformOptional(
1090 auto [dividend, divisor] = tup;
1093 return inst.rd.Write(m_emu, UINT64_MAX);
1095 if (dividend == INT32_MIN && divisor == -1)
1096 return inst.rd.Write(m_emu, SextW(dividend));
1098 return inst.rd.Write(m_emu, SextW(dividend / divisor));
1103 return transformOptional(
1106 auto [dividend, divisor] = tup;
1109 return inst.rd.Write(m_emu, UINT64_MAX);
1111 return inst.rd.Write(m_emu, SextW(dividend / divisor));
1116 return transformOptional(
1119 auto [dividend, divisor] = tup;
1122 return inst.rd.Write(m_emu, SextW(dividend));
1124 if (dividend == INT32_MIN && divisor == -1)
1125 return inst.rd.Write(m_emu, 0);
1127 return inst.rd.Write(m_emu, SextW(dividend % divisor));
1132 return transformOptional(
1135 auto [dividend, divisor] = tup;
1138 return inst.rd.Write(m_emu, SextW(dividend));
1140 return inst.rd.Write(m_emu, SextW(dividend % divisor));
1148 llvm_unreachable(
"should be handled in AtomicSequence");
1151 llvm_unreachable(
"should be handled in AtomicSequence");
1154 return AtomicSwap<AMOSWAP_W, uint32_t>(
m_emu, inst, 4, SextW);
1157 return AtomicADD<AMOADD_W, uint32_t>(
m_emu, inst, 4, SextW);
1160 return AtomicBitOperate<AMOXOR_W, uint32_t>(
1161 m_emu, inst, 4, SextW, [](uint32_t a, uint32_t b) {
return a ^ b; });
1164 return AtomicBitOperate<AMOAND_W, uint32_t>(
1165 m_emu, inst, 4, SextW, [](uint32_t a, uint32_t b) {
return a & b; });
1168 return AtomicBitOperate<AMOOR_W, uint32_t>(
1169 m_emu, inst, 4, SextW, [](uint32_t a, uint32_t b) {
return a | b; });
1172 return AtomicCmp<AMOMIN_W, uint32_t>(
1173 m_emu, inst, 4, SextW, [](uint32_t a, uint32_t b) {
1174 return uint32_t(std::min(int32_t(a), int32_t(b)));
1178 return AtomicCmp<AMOMAX_W, uint32_t>(
1179 m_emu, inst, 4, SextW, [](uint32_t a, uint32_t b) {
1180 return uint32_t(std::max(int32_t(a), int32_t(b)));
1184 return AtomicCmp<AMOMINU_W, uint32_t>(
1185 m_emu, inst, 4, SextW,
1186 [](uint32_t a, uint32_t b) {
return std::min(a, b); });
1189 return AtomicCmp<AMOMAXU_W, uint32_t>(
1190 m_emu, inst, 4, SextW,
1191 [](uint32_t a, uint32_t b) {
return std::max(a, b); });
1194 return AtomicSwap<AMOSWAP_D, uint64_t>(
m_emu, inst, 8, ZextD);
1197 return AtomicADD<AMOADD_D, uint64_t>(
m_emu, inst, 8, ZextD);
1200 return AtomicBitOperate<AMOXOR_D, uint64_t>(
1201 m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) {
return a ^ b; });
1204 return AtomicBitOperate<AMOAND_D, uint64_t>(
1205 m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) {
return a & b; });
1208 return AtomicBitOperate<AMOOR_D, uint64_t>(
1209 m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) {
return a | b; });
1212 return AtomicCmp<AMOMIN_D, uint64_t>(
1213 m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) {
1214 return uint64_t(std::min(int64_t(a), int64_t(b)));
1218 return AtomicCmp<AMOMAX_D, uint64_t>(
1219 m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) {
1220 return uint64_t(std::max(int64_t(a), int64_t(b)));
1224 return AtomicCmp<AMOMINU_D, uint64_t>(
1225 m_emu, inst, 8, ZextD,
1226 [](uint64_t a, uint64_t b) {
return std::min(a, b); });
1229 return AtomicCmp<AMOMAXU_D, uint64_t>(
1230 m_emu, inst, 8, ZextD,
1231 [](uint64_t a, uint64_t b) {
return std::max(a, b); });
1233 template <
typename T>
1234 bool F_Load(T inst,
const fltSemantics &(*semantics)(),
1235 unsigned int numBits) {
1236 return transformOptional(inst.rs1.Read(
m_emu),
1238 uint64_t addr = rs1 + uint64_t(inst.imm);
1239 uint64_t bits = *m_emu.ReadMem<uint64_t>(addr);
1240 APFloat f(semantics(), APInt(numBits, bits));
1241 return inst.rd.WriteAPFloat(m_emu, f);
1246 template <
typename T>
bool F_Store(T inst,
bool isDouble) {
1247 return transformOptional(
zipOpt(inst.rs1.Read(
m_emu),
1248 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1250 auto [rs1, rs2] = tup;
1251 uint64_t addr = rs1 + uint64_t(inst.imm);
1253 rs2.bitcastToAPInt().getZExtValue();
1254 return m_emu.WriteMem<uint64_t>(addr, bits);
1265 template <
typename T>
1266 bool FMA(T inst,
bool isDouble,
float rs2_sign,
float rs3_sign) {
1267 return transformOptional(
zipOpt(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1268 inst.rs2.ReadAPFloat(
m_emu, isDouble),
1269 inst.rs3.ReadAPFloat(
m_emu, isDouble)),
1271 auto [rs1, rs2, rs3] = tup;
1272 rs2.copySign(APFloat(rs2_sign));
1273 rs3.copySign(APFloat(rs3_sign));
1274 auto [res, f] = FusedMultiplyAdd(rs1, rs2, rs3);
1275 return res && inst.rd.WriteAPFloat(m_emu, f);
1283 template <
typename T>
1285 APFloat::opStatus (APFloat::*f)(
const APFloat &RHS,
1286 APFloat::roundingMode RM)) {
1287 return transformOptional(
zipOpt(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1288 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1290 auto [rs1, rs2] = tup;
1292 ((&rs1)->*f)(rs2, m_emu.GetRoundingMode());
1293 inst.rd.WriteAPFloat(m_emu, rs1);
1294 return m_emu.SetAccruedExceptions(res);
1306 template <
typename T>
bool F_SignInj(T inst,
bool isDouble,
bool isNegate) {
1307 return transformOptional(
zipOpt(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1308 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1310 auto [rs1, rs2] = tup;
1314 return inst.rd.WriteAPFloat(m_emu, rs1);
1321 return transformOptional(
zipOpt(inst.rs1.ReadAPFloat(
m_emu, isDouble),
1322 inst.rs2.ReadAPFloat(
m_emu, isDouble)),
1324 auto [rs1, rs2] = tup;
1329 if (rs1.isNegative() == rs2.isNegative()) {
1335 return inst.rd.WriteAPFloat(
m_emu, rs1);
1339 bool operator()(FSGNJX_S inst) {
return F_SignInjXor(inst,
false); }
1340 template <
typename T>
1342 APFloat (*f)(
const APFloat &A,
const APFloat &
B)) {
1343 return transformOptional(
1344 zipOpt(inst.rs1.ReadAPFloat(m_emu, isDouble),
1345 inst.rs2.ReadAPFloat(m_emu, isDouble)),
1347 auto [rs1, rs2] = tup;
1352 if (rs1.isNaN() || rs2.isNaN())
1353 m_emu.SetAccruedExceptions(APFloat::opInvalidOp);
1354 if (rs1.isNaN() && rs2.isNaN()) {
1355 auto canonicalNaN = APFloat::getQNaN(rs1.getSemantics());
1356 return inst.rd.WriteAPFloat(m_emu, canonicalNaN);
1358 return inst.rd.WriteAPFloat(m_emu, f(rs1, rs2));
1362 bool operator()(FMIN_S inst) {
return F_MAX_MIN(inst,
false, minnum); }
1363 bool operator()(FMAX_S inst) {
return F_MAX_MIN(inst,
false, maxnum); }
1365 return FCVT_i2f<FCVT_W_S, int32_t, float>(inst,
false,
1366 &APFloat::convertToFloat);
1369 return FCVT_i2f<FCVT_WU_S, uint32_t, float>(inst,
false,
1370 &APFloat::convertToFloat);
1372 template <
typename T>
bool FMV_f2i(T inst,
bool isDouble) {
1373 return transformOptional(
1374 inst.rs1.ReadAPFloat(m_emu, isDouble),
1378 return inst.rd.Write(m_emu, 0x7ff8'0000'0000'0000);
1380 return inst.rd.Write(m_emu, 0x7fc0'0000);
1382 auto bits = rs1.bitcastToAPInt().getZExtValue();
1384 return inst.rd.Write(m_emu,
bits);
1386 return inst.rd.Write(m_emu, uint64_t(
bits & 0xffff'ffff));
1397 return transformOptional(
1398 zipOpt(inst.rs1.ReadAPFloat(m_emu, isDouble),
1399 inst.rs2.ReadAPFloat(m_emu, isDouble)),
1401 auto [rs1, rs2] = tup;
1402 if (rs1.isNaN() || rs2.isNaN()) {
1404 if (rs1.isSignaling() || rs2.isSignaling()) {
1406 m_emu.SetAccruedExceptions(APFloat::opInvalidOp);
1407 return res && inst.rd.Write(m_emu, 0);
1410 auto res = m_emu.SetAccruedExceptions(APFloat::opInvalidOp);
1411 return res && inst.rd.Write(m_emu, 0);
1415 return inst.rd.Write(m_emu,
1416 rs1.compare(rs2) == APFloat::cmpEqual);
1418 return inst.rd.Write(m_emu, rs1.compare(rs2) ==
1419 APFloat::cmpLessThan);
1421 return inst.rd.Write(m_emu, rs1.compare(rs2) !=
1422 APFloat::cmpGreaterThan);
1424 llvm_unreachable(
"unsupported F_CMP");
1429 bool operator()(FEQ_S inst) {
return F_Compare(inst,
false, FEQ); }
1430 bool operator()(FLT_S inst) {
return F_Compare(inst,
false, FLT); }
1431 bool operator()(FLE_S inst) {
return F_Compare(inst,
false, FLE); }
1432 template <
typename T>
bool FCLASS(T inst,
bool isDouble) {
1433 return transformOptional(inst.rs1.ReadAPFloat(m_emu, isDouble),
1435 uint64_t result = 0;
1436 if (rs1.isInfinity() && rs1.isNegative())
1439 if (rs1.isNormal() && rs1.isNegative())
1442 if (rs1.isDenormal() && rs1.isNegative())
1444 if (rs1.isNegZero())
1446 if (rs1.isPosZero())
1449 if (rs1.isNormal() && !rs1.isNegative())
1452 if (rs1.isDenormal() && !rs1.isNegative())
1454 if (rs1.isInfinity() && !rs1.isNegative())
1457 if (rs1.isSignaling())
1462 return inst.rd.Write(m_emu, result);
1467 template <
typename T,
typename E>
1469 const fltSemantics &semantics) {
1470 return transformOptional(((&inst.rs1)->*f)(m_emu),
1472 APFloat apf(semantics, rs1);
1473 return inst.rd.WriteAPFloat(m_emu, apf);
1478 return FCVT_f2i(inst, &
Rs::ReadI32, APFloat::IEEEsingle());
1481 return FCVT_f2i(inst, &
Rs::ReadU32, APFloat::IEEEsingle());
1483 template <
typename T,
typename E>
1484 bool FMV_i2f(T inst,
unsigned int numBits, E (APInt::*f)()
const) {
1485 return transformOptional(inst.rs1.Read(m_emu),
1487 APInt apInt(numBits, rs1);
1489 apInt = APInt(numBits, NanUnBoxing(rs1));
1490 APFloat apf((&apInt->*f)());
1491 return inst.rd.WriteAPFloat(m_emu, apf);
1496 return FMV_i2f(inst, 32, &APInt::bitsToFloat);
1498 template <
typename I,
typename E,
typename T>
1499 bool FCVT_i2f(I inst,
bool isDouble, T (APFloat::*f)()
const) {
1500 return transformOptional(inst.rs1.ReadAPFloat(m_emu, isDouble),
1502 E res = E((&rs1->*f)());
1503 return inst.rd.Write(m_emu, uint64_t(res));
1508 return FCVT_i2f<FCVT_L_S, int64_t, float>(inst,
false,
1509 &APFloat::convertToFloat);
1512 return FCVT_i2f<FCVT_LU_S, uint64_t, float>(inst,
false,
1513 &APFloat::convertToFloat);
1516 return FCVT_f2i(inst, &
Rs::ReadI64, APFloat::IEEEsingle());
1519 return FCVT_f2i(inst, &
Rs::Read, APFloat::IEEEsingle());
1521 bool operator()(FLD inst) {
return F_Load(inst, &APFloat::IEEEdouble, 64); }
1523 bool operator()(FMADD_D inst) {
return FMA(inst,
true, 1.0f, 1.0f); }
1524 bool operator()(FMSUB_D inst) {
return FMA(inst,
true, 1.0f, -1.0f); }
1525 bool operator()(FNMSUB_D inst) {
return FMA(inst,
true, -1.0f, 1.0f); }
1526 bool operator()(FNMADD_D inst) {
return FMA(inst,
true, -1.0f, -1.0f); }
1527 bool operator()(FADD_D inst) {
return F_Op(inst,
true, &APFloat::add); }
1528 bool operator()(FSUB_D inst) {
return F_Op(inst,
true, &APFloat::subtract); }
1529 bool operator()(FMUL_D inst) {
return F_Op(inst,
true, &APFloat::multiply); }
1530 bool operator()(FDIV_D inst) {
return F_Op(inst,
true, &APFloat::divide); }
1535 bool operator()(FSGNJ_D inst) {
return F_SignInj(inst,
true,
false); }
1536 bool operator()(FSGNJN_D inst) {
return F_SignInj(inst,
true,
true); }
1537 bool operator()(FSGNJX_D inst) {
return F_SignInjXor(inst,
true); }
1538 bool operator()(FMIN_D inst) {
return F_MAX_MIN(inst,
true, minnum); }
1539 bool operator()(FMAX_D inst) {
return F_MAX_MIN(inst,
true, maxnum); }
1541 return transformOptional(inst.rs1.ReadAPFloat(m_emu,
true),
1543 double d = rs1.convertToDouble();
1544 APFloat apf((float(d)));
1545 return inst.rd.WriteAPFloat(m_emu, apf);
1550 return transformOptional(inst.rs1.ReadAPFloat(m_emu,
false),
1552 float f = rs1.convertToFloat();
1553 APFloat apf((double(f)));
1554 return inst.rd.WriteAPFloat(m_emu, apf);
1558 bool operator()(FEQ_D inst) {
return F_Compare(inst,
true, FEQ); }
1559 bool operator()(FLT_D inst) {
return F_Compare(inst,
true, FLT); }
1560 bool operator()(FLE_D inst) {
return F_Compare(inst,
true, FLE); }
1563 return FCVT_i2f<FCVT_W_D, int32_t, double>(inst,
true,
1564 &APFloat::convertToDouble);
1567 return FCVT_i2f<FCVT_WU_D, uint32_t, double>(inst,
true,
1568 &APFloat::convertToDouble);
1571 return FCVT_f2i(inst, &
Rs::ReadI32, APFloat::IEEEdouble());
1574 return FCVT_f2i(inst, &
Rs::ReadU32, APFloat::IEEEdouble());
1577 return FCVT_i2f<FCVT_L_D, int64_t, double>(inst,
true,
1578 &APFloat::convertToDouble);
1581 return FCVT_i2f<FCVT_LU_D, uint64_t, double>(inst,
true,
1582 &APFloat::convertToDouble);
1586 return FCVT_f2i(inst, &
Rs::ReadI64, APFloat::IEEEdouble());
1589 return FCVT_f2i(inst, &
Rs::Read, APFloat::IEEEdouble());
1592 return FMV_i2f(inst, 64, &APInt::bitsToDouble);
1606 bool increase_pc = options & eEmulateInstructionOptionAutoAdvancePC;
1607 bool ignore_cond = options & eEmulateInstructionOptionIgnoreConditions;
1625 return new_pc != old_pc ||
1629std::optional<DecodeResult>
1631 return transformOptional(ReadMem<uint32_t>(addr),
1632 [&](uint32_t inst) {
return Decode(inst); })
1633 .value_or(std::nullopt);
1653 bool success =
false;
1656 return success ? std::optional<addr_t>(addr) : std::nullopt;
1668 bool success =
false;
1672 return RoundingMode::Invalid;
1673 auto frm = (fcsr >> 5) & 0x7;
1676 return RoundingMode::NearestTiesToEven;
1678 return RoundingMode::TowardZero;
1680 return RoundingMode::TowardNegative;
1682 return RoundingMode::TowardPositive;
1684 return RoundingMode::Dynamic;
1687 return RoundingMode::Invalid;
1692 APFloatBase::opStatus opStatus) {
1693 bool success =
false;
1699 case APFloatBase::opInvalidOp:
1702 case APFloatBase::opDivByZero:
1705 case APFloatBase::opOverflow:
1708 case APFloatBase::opUnderflow:
1711 case APFloatBase::opInexact:
1714 case APFloatBase::opOK:
1723std::optional<RegisterInfo>
1725 uint32_t reg_index) {
1727 switch (reg_index) {
1747 llvm_unreachable(
"unsupported register");
1753 const uint32_t length =
1759 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)
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)
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)
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)