1*bdd1243dSDimitry Andric //===-- EmulateInstructionRISCV.cpp ---------------------------------------===// 2*bdd1243dSDimitry Andric // 3*bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*bdd1243dSDimitry Andric // 7*bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 8*bdd1243dSDimitry Andric 9*bdd1243dSDimitry Andric #include "EmulateInstructionRISCV.h" 10*bdd1243dSDimitry Andric #include "Plugins/Process/Utility/RegisterInfoPOSIX_riscv64.h" 11*bdd1243dSDimitry Andric #include "Plugins/Process/Utility/lldb-riscv-register-enums.h" 12*bdd1243dSDimitry Andric #include "RISCVCInstructions.h" 13*bdd1243dSDimitry Andric #include "RISCVInstructions.h" 14*bdd1243dSDimitry Andric 15*bdd1243dSDimitry Andric #include "lldb/Core/Address.h" 16*bdd1243dSDimitry Andric #include "lldb/Core/PluginManager.h" 17*bdd1243dSDimitry Andric #include "lldb/Interpreter/OptionValueArray.h" 18*bdd1243dSDimitry Andric #include "lldb/Interpreter/OptionValueDictionary.h" 19*bdd1243dSDimitry Andric #include "lldb/Symbol/UnwindPlan.h" 20*bdd1243dSDimitry Andric #include "lldb/Utility/ArchSpec.h" 21*bdd1243dSDimitry Andric #include "lldb/Utility/LLDBLog.h" 22*bdd1243dSDimitry Andric #include "lldb/Utility/Stream.h" 23*bdd1243dSDimitry Andric 24*bdd1243dSDimitry Andric #include "llvm/ADT/STLExtras.h" 25*bdd1243dSDimitry Andric #include "llvm/Support/MathExtras.h" 26*bdd1243dSDimitry Andric #include <optional> 27*bdd1243dSDimitry Andric 28*bdd1243dSDimitry Andric using namespace llvm; 29*bdd1243dSDimitry Andric using namespace lldb; 30*bdd1243dSDimitry Andric using namespace lldb_private; 31*bdd1243dSDimitry Andric 32*bdd1243dSDimitry Andric LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionRISCV, InstructionRISCV) 33*bdd1243dSDimitry Andric 34*bdd1243dSDimitry Andric namespace lldb_private { 35*bdd1243dSDimitry Andric 36*bdd1243dSDimitry Andric /// Returns all values wrapped in Optional, or std::nullopt if any of the values 37*bdd1243dSDimitry Andric /// is std::nullopt. 38*bdd1243dSDimitry Andric template <typename... Ts> 39*bdd1243dSDimitry Andric static std::optional<std::tuple<Ts...>> zipOpt(std::optional<Ts> &&...ts) { 40*bdd1243dSDimitry Andric if ((ts.has_value() && ...)) 41*bdd1243dSDimitry Andric return std::optional<std::tuple<Ts...>>(std::make_tuple(std::move(*ts)...)); 42*bdd1243dSDimitry Andric else 43*bdd1243dSDimitry Andric return std::nullopt; 44*bdd1243dSDimitry Andric } 45*bdd1243dSDimitry Andric 46*bdd1243dSDimitry Andric // The funct3 is the type of compare in B<CMP> instructions. 47*bdd1243dSDimitry Andric // funct3 means "3-bits function selector", which RISC-V ISA uses as minor 48*bdd1243dSDimitry Andric // opcode. It reuses the major opcode encoding space. 49*bdd1243dSDimitry Andric constexpr uint32_t BEQ = 0b000; 50*bdd1243dSDimitry Andric constexpr uint32_t BNE = 0b001; 51*bdd1243dSDimitry Andric constexpr uint32_t BLT = 0b100; 52*bdd1243dSDimitry Andric constexpr uint32_t BGE = 0b101; 53*bdd1243dSDimitry Andric constexpr uint32_t BLTU = 0b110; 54*bdd1243dSDimitry Andric constexpr uint32_t BGEU = 0b111; 55*bdd1243dSDimitry Andric 56*bdd1243dSDimitry Andric // used in decoder 57*bdd1243dSDimitry Andric constexpr int32_t SignExt(uint32_t imm) { return int32_t(imm); } 58*bdd1243dSDimitry Andric 59*bdd1243dSDimitry Andric // used in executor 60*bdd1243dSDimitry Andric template <typename T> 61*bdd1243dSDimitry Andric constexpr std::enable_if_t<sizeof(T) <= 4, uint64_t> SextW(T value) { 62*bdd1243dSDimitry Andric return uint64_t(int64_t(int32_t(value))); 63*bdd1243dSDimitry Andric } 64*bdd1243dSDimitry Andric 65*bdd1243dSDimitry Andric // used in executor 66*bdd1243dSDimitry Andric template <typename T> constexpr uint64_t ZextD(T value) { 67*bdd1243dSDimitry Andric return uint64_t(value); 68*bdd1243dSDimitry Andric } 69*bdd1243dSDimitry Andric 70*bdd1243dSDimitry Andric constexpr uint32_t DecodeJImm(uint32_t inst) { 71*bdd1243dSDimitry Andric return (uint64_t(int64_t(int32_t(inst & 0x80000000)) >> 11)) // imm[20] 72*bdd1243dSDimitry Andric | (inst & 0xff000) // imm[19:12] 73*bdd1243dSDimitry Andric | ((inst >> 9) & 0x800) // imm[11] 74*bdd1243dSDimitry Andric | ((inst >> 20) & 0x7fe); // imm[10:1] 75*bdd1243dSDimitry Andric } 76*bdd1243dSDimitry Andric 77*bdd1243dSDimitry Andric constexpr uint32_t DecodeIImm(uint32_t inst) { 78*bdd1243dSDimitry Andric return int64_t(int32_t(inst)) >> 20; // imm[11:0] 79*bdd1243dSDimitry Andric } 80*bdd1243dSDimitry Andric 81*bdd1243dSDimitry Andric constexpr uint32_t DecodeBImm(uint32_t inst) { 82*bdd1243dSDimitry Andric return (uint64_t(int64_t(int32_t(inst & 0x80000000)) >> 19)) // imm[12] 83*bdd1243dSDimitry Andric | ((inst & 0x80) << 4) // imm[11] 84*bdd1243dSDimitry Andric | ((inst >> 20) & 0x7e0) // imm[10:5] 85*bdd1243dSDimitry Andric | ((inst >> 7) & 0x1e); // imm[4:1] 86*bdd1243dSDimitry Andric } 87*bdd1243dSDimitry Andric 88*bdd1243dSDimitry Andric constexpr uint32_t DecodeSImm(uint32_t inst) { 89*bdd1243dSDimitry Andric return (uint64_t(int64_t(int32_t(inst & 0xFE000000)) >> 20)) // imm[11:5] 90*bdd1243dSDimitry Andric | ((inst & 0xF80) >> 7); // imm[4:0] 91*bdd1243dSDimitry Andric } 92*bdd1243dSDimitry Andric 93*bdd1243dSDimitry Andric constexpr uint32_t DecodeUImm(uint32_t inst) { 94*bdd1243dSDimitry Andric return SextW(inst & 0xFFFFF000); // imm[31:12] 95*bdd1243dSDimitry Andric } 96*bdd1243dSDimitry Andric 97*bdd1243dSDimitry Andric static uint32_t GPREncodingToLLDB(uint32_t reg_encode) { 98*bdd1243dSDimitry Andric if (reg_encode == 0) 99*bdd1243dSDimitry Andric return gpr_x0_riscv; 100*bdd1243dSDimitry Andric if (reg_encode >= 1 && reg_encode <= 31) 101*bdd1243dSDimitry Andric return gpr_x1_riscv + reg_encode - 1; 102*bdd1243dSDimitry Andric return LLDB_INVALID_REGNUM; 103*bdd1243dSDimitry Andric } 104*bdd1243dSDimitry Andric 105*bdd1243dSDimitry Andric static uint32_t FPREncodingToLLDB(uint32_t reg_encode) { 106*bdd1243dSDimitry Andric if (reg_encode <= 31) 107*bdd1243dSDimitry Andric return fpr_f0_riscv + reg_encode; 108*bdd1243dSDimitry Andric return LLDB_INVALID_REGNUM; 109*bdd1243dSDimitry Andric } 110*bdd1243dSDimitry Andric 111*bdd1243dSDimitry Andric bool Rd::Write(EmulateInstructionRISCV &emulator, uint64_t value) { 112*bdd1243dSDimitry Andric uint32_t lldb_reg = GPREncodingToLLDB(rd); 113*bdd1243dSDimitry Andric EmulateInstruction::Context ctx; 114*bdd1243dSDimitry Andric ctx.type = EmulateInstruction::eContextRegisterStore; 115*bdd1243dSDimitry Andric ctx.SetNoArgs(); 116*bdd1243dSDimitry Andric RegisterValue registerValue; 117*bdd1243dSDimitry Andric registerValue.SetUInt64(value); 118*bdd1243dSDimitry Andric return emulator.WriteRegister(ctx, eRegisterKindLLDB, lldb_reg, 119*bdd1243dSDimitry Andric registerValue); 120*bdd1243dSDimitry Andric } 121*bdd1243dSDimitry Andric 122*bdd1243dSDimitry Andric bool Rd::WriteAPFloat(EmulateInstructionRISCV &emulator, APFloat value) { 123*bdd1243dSDimitry Andric uint32_t lldb_reg = FPREncodingToLLDB(rd); 124*bdd1243dSDimitry Andric EmulateInstruction::Context ctx; 125*bdd1243dSDimitry Andric ctx.type = EmulateInstruction::eContextRegisterStore; 126*bdd1243dSDimitry Andric ctx.SetNoArgs(); 127*bdd1243dSDimitry Andric RegisterValue registerValue; 128*bdd1243dSDimitry Andric registerValue.SetUInt64(value.bitcastToAPInt().getZExtValue()); 129*bdd1243dSDimitry Andric return emulator.WriteRegister(ctx, eRegisterKindLLDB, lldb_reg, 130*bdd1243dSDimitry Andric registerValue); 131*bdd1243dSDimitry Andric } 132*bdd1243dSDimitry Andric 133*bdd1243dSDimitry Andric std::optional<uint64_t> Rs::Read(EmulateInstructionRISCV &emulator) { 134*bdd1243dSDimitry Andric uint32_t lldbReg = GPREncodingToLLDB(rs); 135*bdd1243dSDimitry Andric RegisterValue value; 136*bdd1243dSDimitry Andric return emulator.ReadRegister(eRegisterKindLLDB, lldbReg, value) 137*bdd1243dSDimitry Andric ? std::optional<uint64_t>(value.GetAsUInt64()) 138*bdd1243dSDimitry Andric : std::nullopt; 139*bdd1243dSDimitry Andric } 140*bdd1243dSDimitry Andric 141*bdd1243dSDimitry Andric std::optional<int32_t> Rs::ReadI32(EmulateInstructionRISCV &emulator) { 142*bdd1243dSDimitry Andric return transformOptional( 143*bdd1243dSDimitry Andric Read(emulator), [](uint64_t value) { return int32_t(uint32_t(value)); }); 144*bdd1243dSDimitry Andric } 145*bdd1243dSDimitry Andric 146*bdd1243dSDimitry Andric std::optional<int64_t> Rs::ReadI64(EmulateInstructionRISCV &emulator) { 147*bdd1243dSDimitry Andric return transformOptional(Read(emulator), 148*bdd1243dSDimitry Andric [](uint64_t value) { return int64_t(value); }); 149*bdd1243dSDimitry Andric } 150*bdd1243dSDimitry Andric 151*bdd1243dSDimitry Andric std::optional<uint32_t> Rs::ReadU32(EmulateInstructionRISCV &emulator) { 152*bdd1243dSDimitry Andric return transformOptional(Read(emulator), 153*bdd1243dSDimitry Andric [](uint64_t value) { return uint32_t(value); }); 154*bdd1243dSDimitry Andric } 155*bdd1243dSDimitry Andric 156*bdd1243dSDimitry Andric std::optional<APFloat> Rs::ReadAPFloat(EmulateInstructionRISCV &emulator, 157*bdd1243dSDimitry Andric bool isDouble) { 158*bdd1243dSDimitry Andric uint32_t lldbReg = FPREncodingToLLDB(rs); 159*bdd1243dSDimitry Andric RegisterValue value; 160*bdd1243dSDimitry Andric if (!emulator.ReadRegister(eRegisterKindLLDB, lldbReg, value)) 161*bdd1243dSDimitry Andric return std::nullopt; 162*bdd1243dSDimitry Andric uint64_t bits = value.GetAsUInt64(); 163*bdd1243dSDimitry Andric APInt api(64, bits, false); 164*bdd1243dSDimitry Andric return APFloat(isDouble ? APFloat(api.bitsToDouble()) 165*bdd1243dSDimitry Andric : APFloat(api.bitsToFloat())); 166*bdd1243dSDimitry Andric } 167*bdd1243dSDimitry Andric 168*bdd1243dSDimitry Andric static bool CompareB(uint64_t rs1, uint64_t rs2, uint32_t funct3) { 169*bdd1243dSDimitry Andric switch (funct3) { 170*bdd1243dSDimitry Andric case BEQ: 171*bdd1243dSDimitry Andric return rs1 == rs2; 172*bdd1243dSDimitry Andric case BNE: 173*bdd1243dSDimitry Andric return rs1 != rs2; 174*bdd1243dSDimitry Andric case BLT: 175*bdd1243dSDimitry Andric return int64_t(rs1) < int64_t(rs2); 176*bdd1243dSDimitry Andric case BGE: 177*bdd1243dSDimitry Andric return int64_t(rs1) >= int64_t(rs2); 178*bdd1243dSDimitry Andric case BLTU: 179*bdd1243dSDimitry Andric return rs1 < rs2; 180*bdd1243dSDimitry Andric case BGEU: 181*bdd1243dSDimitry Andric return rs1 >= rs2; 182*bdd1243dSDimitry Andric default: 183*bdd1243dSDimitry Andric llvm_unreachable("unexpected funct3"); 184*bdd1243dSDimitry Andric } 185*bdd1243dSDimitry Andric } 186*bdd1243dSDimitry Andric 187*bdd1243dSDimitry Andric template <typename T> 188*bdd1243dSDimitry Andric constexpr bool is_load = 189*bdd1243dSDimitry Andric std::is_same_v<T, LB> || std::is_same_v<T, LH> || std::is_same_v<T, LW> || 190*bdd1243dSDimitry Andric std::is_same_v<T, LD> || std::is_same_v<T, LBU> || std::is_same_v<T, LHU> || 191*bdd1243dSDimitry Andric std::is_same_v<T, LWU>; 192*bdd1243dSDimitry Andric 193*bdd1243dSDimitry Andric template <typename T> 194*bdd1243dSDimitry Andric constexpr bool is_store = std::is_same_v<T, SB> || std::is_same_v<T, SH> || 195*bdd1243dSDimitry Andric std::is_same_v<T, SW> || std::is_same_v<T, SD>; 196*bdd1243dSDimitry Andric 197*bdd1243dSDimitry Andric template <typename T> 198*bdd1243dSDimitry Andric constexpr bool is_amo_add = 199*bdd1243dSDimitry Andric std::is_same_v<T, AMOADD_W> || std::is_same_v<T, AMOADD_D>; 200*bdd1243dSDimitry Andric 201*bdd1243dSDimitry Andric template <typename T> 202*bdd1243dSDimitry Andric constexpr bool is_amo_bit_op = 203*bdd1243dSDimitry Andric std::is_same_v<T, AMOXOR_W> || std::is_same_v<T, AMOXOR_D> || 204*bdd1243dSDimitry Andric std::is_same_v<T, AMOAND_W> || std::is_same_v<T, AMOAND_D> || 205*bdd1243dSDimitry Andric std::is_same_v<T, AMOOR_W> || std::is_same_v<T, AMOOR_D>; 206*bdd1243dSDimitry Andric 207*bdd1243dSDimitry Andric template <typename T> 208*bdd1243dSDimitry Andric constexpr bool is_amo_swap = 209*bdd1243dSDimitry Andric std::is_same_v<T, AMOSWAP_W> || std::is_same_v<T, AMOSWAP_D>; 210*bdd1243dSDimitry Andric 211*bdd1243dSDimitry Andric template <typename T> 212*bdd1243dSDimitry Andric constexpr bool is_amo_cmp = 213*bdd1243dSDimitry Andric std::is_same_v<T, AMOMIN_W> || std::is_same_v<T, AMOMIN_D> || 214*bdd1243dSDimitry Andric std::is_same_v<T, AMOMAX_W> || std::is_same_v<T, AMOMAX_D> || 215*bdd1243dSDimitry Andric std::is_same_v<T, AMOMINU_W> || std::is_same_v<T, AMOMINU_D> || 216*bdd1243dSDimitry Andric std::is_same_v<T, AMOMAXU_W> || std::is_same_v<T, AMOMAXU_D>; 217*bdd1243dSDimitry Andric 218*bdd1243dSDimitry Andric template <typename I> 219*bdd1243dSDimitry Andric static std::enable_if_t<is_load<I> || is_store<I>, std::optional<uint64_t>> 220*bdd1243dSDimitry Andric LoadStoreAddr(EmulateInstructionRISCV &emulator, I inst) { 221*bdd1243dSDimitry Andric return transformOptional(inst.rs1.Read(emulator), [&](uint64_t rs1) { 222*bdd1243dSDimitry Andric return rs1 + uint64_t(SignExt(inst.imm)); 223*bdd1243dSDimitry Andric }); 224*bdd1243dSDimitry Andric } 225*bdd1243dSDimitry Andric 226*bdd1243dSDimitry Andric // Read T from memory, then load its sign-extended value m_emu to register. 227*bdd1243dSDimitry Andric template <typename I, typename T, typename E> 228*bdd1243dSDimitry Andric static std::enable_if_t<is_load<I>, bool> 229*bdd1243dSDimitry Andric Load(EmulateInstructionRISCV &emulator, I inst, uint64_t (*extend)(E)) { 230*bdd1243dSDimitry Andric auto addr = LoadStoreAddr(emulator, inst); 231*bdd1243dSDimitry Andric if (!addr) 232*bdd1243dSDimitry Andric return false; 233*bdd1243dSDimitry Andric return transformOptional( 234*bdd1243dSDimitry Andric emulator.ReadMem<T>(*addr), 235*bdd1243dSDimitry Andric [&](T t) { return inst.rd.Write(emulator, extend(E(t))); }) 236*bdd1243dSDimitry Andric .value_or(false); 237*bdd1243dSDimitry Andric } 238*bdd1243dSDimitry Andric 239*bdd1243dSDimitry Andric template <typename I, typename T> 240*bdd1243dSDimitry Andric static std::enable_if_t<is_store<I>, bool> 241*bdd1243dSDimitry Andric Store(EmulateInstructionRISCV &emulator, I inst) { 242*bdd1243dSDimitry Andric auto addr = LoadStoreAddr(emulator, inst); 243*bdd1243dSDimitry Andric if (!addr) 244*bdd1243dSDimitry Andric return false; 245*bdd1243dSDimitry Andric return transformOptional( 246*bdd1243dSDimitry Andric inst.rs2.Read(emulator), 247*bdd1243dSDimitry Andric [&](uint64_t rs2) { return emulator.WriteMem<T>(*addr, rs2); }) 248*bdd1243dSDimitry Andric .value_or(false); 249*bdd1243dSDimitry Andric } 250*bdd1243dSDimitry Andric 251*bdd1243dSDimitry Andric template <typename I> 252*bdd1243dSDimitry Andric static std::enable_if_t<is_amo_add<I> || is_amo_bit_op<I> || is_amo_swap<I> || 253*bdd1243dSDimitry Andric is_amo_cmp<I>, 254*bdd1243dSDimitry Andric std::optional<uint64_t>> 255*bdd1243dSDimitry Andric AtomicAddr(EmulateInstructionRISCV &emulator, I inst, unsigned int align) { 256*bdd1243dSDimitry Andric return transformOptional(inst.rs1.Read(emulator), 257*bdd1243dSDimitry Andric [&](uint64_t rs1) { 258*bdd1243dSDimitry Andric return rs1 % align == 0 259*bdd1243dSDimitry Andric ? std::optional<uint64_t>(rs1) 260*bdd1243dSDimitry Andric : std::nullopt; 261*bdd1243dSDimitry Andric }) 262*bdd1243dSDimitry Andric .value_or(std::nullopt); 263*bdd1243dSDimitry Andric } 264*bdd1243dSDimitry Andric 265*bdd1243dSDimitry Andric template <typename I, typename T> 266*bdd1243dSDimitry Andric static std::enable_if_t<is_amo_swap<I>, bool> 267*bdd1243dSDimitry Andric AtomicSwap(EmulateInstructionRISCV &emulator, I inst, int align, 268*bdd1243dSDimitry Andric uint64_t (*extend)(T)) { 269*bdd1243dSDimitry Andric auto addr = AtomicAddr(emulator, inst, align); 270*bdd1243dSDimitry Andric if (!addr) 271*bdd1243dSDimitry Andric return false; 272*bdd1243dSDimitry Andric return transformOptional( 273*bdd1243dSDimitry Andric zipOpt(emulator.ReadMem<T>(*addr), inst.rs2.Read(emulator)), 274*bdd1243dSDimitry Andric [&](auto &&tup) { 275*bdd1243dSDimitry Andric auto [tmp, rs2] = tup; 276*bdd1243dSDimitry Andric return emulator.WriteMem<T>(*addr, T(rs2)) && 277*bdd1243dSDimitry Andric inst.rd.Write(emulator, extend(tmp)); 278*bdd1243dSDimitry Andric }) 279*bdd1243dSDimitry Andric .value_or(false); 280*bdd1243dSDimitry Andric } 281*bdd1243dSDimitry Andric 282*bdd1243dSDimitry Andric template <typename I, typename T> 283*bdd1243dSDimitry Andric static std::enable_if_t<is_amo_add<I>, bool> 284*bdd1243dSDimitry Andric AtomicADD(EmulateInstructionRISCV &emulator, I inst, int align, 285*bdd1243dSDimitry Andric uint64_t (*extend)(T)) { 286*bdd1243dSDimitry Andric auto addr = AtomicAddr(emulator, inst, align); 287*bdd1243dSDimitry Andric if (!addr) 288*bdd1243dSDimitry Andric return false; 289*bdd1243dSDimitry Andric return transformOptional( 290*bdd1243dSDimitry Andric zipOpt(emulator.ReadMem<T>(*addr), inst.rs2.Read(emulator)), 291*bdd1243dSDimitry Andric [&](auto &&tup) { 292*bdd1243dSDimitry Andric auto [tmp, rs2] = tup; 293*bdd1243dSDimitry Andric return emulator.WriteMem<T>(*addr, T(tmp + rs2)) && 294*bdd1243dSDimitry Andric inst.rd.Write(emulator, extend(tmp)); 295*bdd1243dSDimitry Andric }) 296*bdd1243dSDimitry Andric .value_or(false); 297*bdd1243dSDimitry Andric } 298*bdd1243dSDimitry Andric 299*bdd1243dSDimitry Andric template <typename I, typename T> 300*bdd1243dSDimitry Andric static std::enable_if_t<is_amo_bit_op<I>, bool> 301*bdd1243dSDimitry Andric AtomicBitOperate(EmulateInstructionRISCV &emulator, I inst, int align, 302*bdd1243dSDimitry Andric uint64_t (*extend)(T), T (*operate)(T, T)) { 303*bdd1243dSDimitry Andric auto addr = AtomicAddr(emulator, inst, align); 304*bdd1243dSDimitry Andric if (!addr) 305*bdd1243dSDimitry Andric return false; 306*bdd1243dSDimitry Andric return transformOptional( 307*bdd1243dSDimitry Andric zipOpt(emulator.ReadMem<T>(*addr), inst.rs2.Read(emulator)), 308*bdd1243dSDimitry Andric [&](auto &&tup) { 309*bdd1243dSDimitry Andric auto [value, rs2] = tup; 310*bdd1243dSDimitry Andric return emulator.WriteMem<T>(*addr, operate(value, T(rs2))) && 311*bdd1243dSDimitry Andric inst.rd.Write(emulator, extend(value)); 312*bdd1243dSDimitry Andric }) 313*bdd1243dSDimitry Andric .value_or(false); 314*bdd1243dSDimitry Andric } 315*bdd1243dSDimitry Andric 316*bdd1243dSDimitry Andric template <typename I, typename T> 317*bdd1243dSDimitry Andric static std::enable_if_t<is_amo_cmp<I>, bool> 318*bdd1243dSDimitry Andric AtomicCmp(EmulateInstructionRISCV &emulator, I inst, int align, 319*bdd1243dSDimitry Andric uint64_t (*extend)(T), T (*cmp)(T, T)) { 320*bdd1243dSDimitry Andric auto addr = AtomicAddr(emulator, inst, align); 321*bdd1243dSDimitry Andric if (!addr) 322*bdd1243dSDimitry Andric return false; 323*bdd1243dSDimitry Andric return transformOptional( 324*bdd1243dSDimitry Andric zipOpt(emulator.ReadMem<T>(*addr), inst.rs2.Read(emulator)), 325*bdd1243dSDimitry Andric [&](auto &&tup) { 326*bdd1243dSDimitry Andric auto [value, rs2] = tup; 327*bdd1243dSDimitry Andric return emulator.WriteMem<T>(*addr, cmp(value, T(rs2))) && 328*bdd1243dSDimitry Andric inst.rd.Write(emulator, extend(value)); 329*bdd1243dSDimitry Andric }) 330*bdd1243dSDimitry Andric .value_or(false); 331*bdd1243dSDimitry Andric } 332*bdd1243dSDimitry Andric 333*bdd1243dSDimitry Andric bool AtomicSequence(EmulateInstructionRISCV &emulator) { 334*bdd1243dSDimitry Andric // The atomic sequence is always 4 instructions long: 335*bdd1243dSDimitry Andric // example: 336*bdd1243dSDimitry Andric // 110cc: 100427af lr.w a5,(s0) 337*bdd1243dSDimitry Andric // 110d0: 00079663 bnez a5,110dc 338*bdd1243dSDimitry Andric // 110d4: 1ce426af sc.w.aq a3,a4,(s0) 339*bdd1243dSDimitry Andric // 110d8: fe069ae3 bnez a3,110cc 340*bdd1243dSDimitry Andric // 110dc: ........ <next instruction> 341*bdd1243dSDimitry Andric const auto pc = emulator.ReadPC(); 342*bdd1243dSDimitry Andric if (!pc) 343*bdd1243dSDimitry Andric return false; 344*bdd1243dSDimitry Andric auto current_pc = *pc; 345*bdd1243dSDimitry Andric const auto entry_pc = current_pc; 346*bdd1243dSDimitry Andric 347*bdd1243dSDimitry Andric // The first instruction should be LR.W or LR.D 348*bdd1243dSDimitry Andric auto inst = emulator.ReadInstructionAt(current_pc); 349*bdd1243dSDimitry Andric if (!inst || (!std::holds_alternative<LR_W>(inst->decoded) && 350*bdd1243dSDimitry Andric !std::holds_alternative<LR_D>(inst->decoded))) 351*bdd1243dSDimitry Andric return false; 352*bdd1243dSDimitry Andric 353*bdd1243dSDimitry Andric // The second instruction should be BNE to exit address 354*bdd1243dSDimitry Andric inst = emulator.ReadInstructionAt(current_pc += 4); 355*bdd1243dSDimitry Andric if (!inst || !std::holds_alternative<B>(inst->decoded)) 356*bdd1243dSDimitry Andric return false; 357*bdd1243dSDimitry Andric auto bne_exit = std::get<B>(inst->decoded); 358*bdd1243dSDimitry Andric if (bne_exit.funct3 != BNE) 359*bdd1243dSDimitry Andric return false; 360*bdd1243dSDimitry Andric // save the exit address to check later 361*bdd1243dSDimitry Andric const auto exit_pc = current_pc + SextW(bne_exit.imm); 362*bdd1243dSDimitry Andric 363*bdd1243dSDimitry Andric // The third instruction should be SC.W or SC.D 364*bdd1243dSDimitry Andric inst = emulator.ReadInstructionAt(current_pc += 4); 365*bdd1243dSDimitry Andric if (!inst || (!std::holds_alternative<SC_W>(inst->decoded) && 366*bdd1243dSDimitry Andric !std::holds_alternative<SC_D>(inst->decoded))) 367*bdd1243dSDimitry Andric return false; 368*bdd1243dSDimitry Andric 369*bdd1243dSDimitry Andric // The fourth instruction should be BNE to entry address 370*bdd1243dSDimitry Andric inst = emulator.ReadInstructionAt(current_pc += 4); 371*bdd1243dSDimitry Andric if (!inst || !std::holds_alternative<B>(inst->decoded)) 372*bdd1243dSDimitry Andric return false; 373*bdd1243dSDimitry Andric auto bne_start = std::get<B>(inst->decoded); 374*bdd1243dSDimitry Andric if (bne_start.funct3 != BNE) 375*bdd1243dSDimitry Andric return false; 376*bdd1243dSDimitry Andric if (entry_pc != current_pc + SextW(bne_start.imm)) 377*bdd1243dSDimitry Andric return false; 378*bdd1243dSDimitry Andric 379*bdd1243dSDimitry Andric current_pc += 4; 380*bdd1243dSDimitry Andric // check the exit address and jump to it 381*bdd1243dSDimitry Andric return exit_pc == current_pc && emulator.WritePC(current_pc); 382*bdd1243dSDimitry Andric } 383*bdd1243dSDimitry Andric 384*bdd1243dSDimitry Andric template <typename T> static RISCVInst DecodeUType(uint32_t inst) { 385*bdd1243dSDimitry Andric return T{Rd{DecodeRD(inst)}, DecodeUImm(inst)}; 386*bdd1243dSDimitry Andric } 387*bdd1243dSDimitry Andric 388*bdd1243dSDimitry Andric template <typename T> static RISCVInst DecodeJType(uint32_t inst) { 389*bdd1243dSDimitry Andric return T{Rd{DecodeRD(inst)}, DecodeJImm(inst)}; 390*bdd1243dSDimitry Andric } 391*bdd1243dSDimitry Andric 392*bdd1243dSDimitry Andric template <typename T> static RISCVInst DecodeIType(uint32_t inst) { 393*bdd1243dSDimitry Andric return T{Rd{DecodeRD(inst)}, Rs{DecodeRS1(inst)}, DecodeIImm(inst)}; 394*bdd1243dSDimitry Andric } 395*bdd1243dSDimitry Andric 396*bdd1243dSDimitry Andric template <typename T> static RISCVInst DecodeBType(uint32_t inst) { 397*bdd1243dSDimitry Andric return T{Rs{DecodeRS1(inst)}, Rs{DecodeRS2(inst)}, DecodeBImm(inst), 398*bdd1243dSDimitry Andric DecodeFunct3(inst)}; 399*bdd1243dSDimitry Andric } 400*bdd1243dSDimitry Andric 401*bdd1243dSDimitry Andric template <typename T> static RISCVInst DecodeSType(uint32_t inst) { 402*bdd1243dSDimitry Andric return T{Rs{DecodeRS1(inst)}, Rs{DecodeRS2(inst)}, DecodeSImm(inst)}; 403*bdd1243dSDimitry Andric } 404*bdd1243dSDimitry Andric 405*bdd1243dSDimitry Andric template <typename T> static RISCVInst DecodeRType(uint32_t inst) { 406*bdd1243dSDimitry Andric return T{Rd{DecodeRD(inst)}, Rs{DecodeRS1(inst)}, Rs{DecodeRS2(inst)}}; 407*bdd1243dSDimitry Andric } 408*bdd1243dSDimitry Andric 409*bdd1243dSDimitry Andric template <typename T> static RISCVInst DecodeRShamtType(uint32_t inst) { 410*bdd1243dSDimitry Andric return T{Rd{DecodeRD(inst)}, Rs{DecodeRS1(inst)}, DecodeRS2(inst)}; 411*bdd1243dSDimitry Andric } 412*bdd1243dSDimitry Andric 413*bdd1243dSDimitry Andric template <typename T> static RISCVInst DecodeRRS1Type(uint32_t inst) { 414*bdd1243dSDimitry Andric return T{Rd{DecodeRD(inst)}, Rs{DecodeRS1(inst)}}; 415*bdd1243dSDimitry Andric } 416*bdd1243dSDimitry Andric 417*bdd1243dSDimitry Andric template <typename T> static RISCVInst DecodeR4Type(uint32_t inst) { 418*bdd1243dSDimitry Andric return T{Rd{DecodeRD(inst)}, Rs{DecodeRS1(inst)}, Rs{DecodeRS2(inst)}, 419*bdd1243dSDimitry Andric Rs{DecodeRS3(inst)}, DecodeRM(inst)}; 420*bdd1243dSDimitry Andric } 421*bdd1243dSDimitry Andric 422*bdd1243dSDimitry Andric static const InstrPattern PATTERNS[] = { 423*bdd1243dSDimitry Andric // RV32I & RV64I (The base integer ISA) // 424*bdd1243dSDimitry Andric {"LUI", 0x7F, 0x37, DecodeUType<LUI>}, 425*bdd1243dSDimitry Andric {"AUIPC", 0x7F, 0x17, DecodeUType<AUIPC>}, 426*bdd1243dSDimitry Andric {"JAL", 0x7F, 0x6F, DecodeJType<JAL>}, 427*bdd1243dSDimitry Andric {"JALR", 0x707F, 0x67, DecodeIType<JALR>}, 428*bdd1243dSDimitry Andric {"B", 0x7F, 0x63, DecodeBType<B>}, 429*bdd1243dSDimitry Andric {"LB", 0x707F, 0x3, DecodeIType<LB>}, 430*bdd1243dSDimitry Andric {"LH", 0x707F, 0x1003, DecodeIType<LH>}, 431*bdd1243dSDimitry Andric {"LW", 0x707F, 0x2003, DecodeIType<LW>}, 432*bdd1243dSDimitry Andric {"LBU", 0x707F, 0x4003, DecodeIType<LBU>}, 433*bdd1243dSDimitry Andric {"LHU", 0x707F, 0x5003, DecodeIType<LHU>}, 434*bdd1243dSDimitry Andric {"SB", 0x707F, 0x23, DecodeSType<SB>}, 435*bdd1243dSDimitry Andric {"SH", 0x707F, 0x1023, DecodeSType<SH>}, 436*bdd1243dSDimitry Andric {"SW", 0x707F, 0x2023, DecodeSType<SW>}, 437*bdd1243dSDimitry Andric {"ADDI", 0x707F, 0x13, DecodeIType<ADDI>}, 438*bdd1243dSDimitry Andric {"SLTI", 0x707F, 0x2013, DecodeIType<SLTI>}, 439*bdd1243dSDimitry Andric {"SLTIU", 0x707F, 0x3013, DecodeIType<SLTIU>}, 440*bdd1243dSDimitry Andric {"XORI", 0x707F, 0x4013, DecodeIType<XORI>}, 441*bdd1243dSDimitry Andric {"ORI", 0x707F, 0x6013, DecodeIType<ORI>}, 442*bdd1243dSDimitry Andric {"ANDI", 0x707F, 0x7013, DecodeIType<ANDI>}, 443*bdd1243dSDimitry Andric {"SLLI", 0xF800707F, 0x1013, DecodeRShamtType<SLLI>}, 444*bdd1243dSDimitry Andric {"SRLI", 0xF800707F, 0x5013, DecodeRShamtType<SRLI>}, 445*bdd1243dSDimitry Andric {"SRAI", 0xF800707F, 0x40005013, DecodeRShamtType<SRAI>}, 446*bdd1243dSDimitry Andric {"ADD", 0xFE00707F, 0x33, DecodeRType<ADD>}, 447*bdd1243dSDimitry Andric {"SUB", 0xFE00707F, 0x40000033, DecodeRType<SUB>}, 448*bdd1243dSDimitry Andric {"SLL", 0xFE00707F, 0x1033, DecodeRType<SLL>}, 449*bdd1243dSDimitry Andric {"SLT", 0xFE00707F, 0x2033, DecodeRType<SLT>}, 450*bdd1243dSDimitry Andric {"SLTU", 0xFE00707F, 0x3033, DecodeRType<SLTU>}, 451*bdd1243dSDimitry Andric {"XOR", 0xFE00707F, 0x4033, DecodeRType<XOR>}, 452*bdd1243dSDimitry Andric {"SRL", 0xFE00707F, 0x5033, DecodeRType<SRL>}, 453*bdd1243dSDimitry Andric {"SRA", 0xFE00707F, 0x40005033, DecodeRType<SRA>}, 454*bdd1243dSDimitry Andric {"OR", 0xFE00707F, 0x6033, DecodeRType<OR>}, 455*bdd1243dSDimitry Andric {"AND", 0xFE00707F, 0x7033, DecodeRType<AND>}, 456*bdd1243dSDimitry Andric {"LWU", 0x707F, 0x6003, DecodeIType<LWU>}, 457*bdd1243dSDimitry Andric {"LD", 0x707F, 0x3003, DecodeIType<LD>}, 458*bdd1243dSDimitry Andric {"SD", 0x707F, 0x3023, DecodeSType<SD>}, 459*bdd1243dSDimitry Andric {"ADDIW", 0x707F, 0x1B, DecodeIType<ADDIW>}, 460*bdd1243dSDimitry Andric {"SLLIW", 0xFE00707F, 0x101B, DecodeRShamtType<SLLIW>}, 461*bdd1243dSDimitry Andric {"SRLIW", 0xFE00707F, 0x501B, DecodeRShamtType<SRLIW>}, 462*bdd1243dSDimitry Andric {"SRAIW", 0xFE00707F, 0x4000501B, DecodeRShamtType<SRAIW>}, 463*bdd1243dSDimitry Andric {"ADDW", 0xFE00707F, 0x3B, DecodeRType<ADDW>}, 464*bdd1243dSDimitry Andric {"SUBW", 0xFE00707F, 0x4000003B, DecodeRType<SUBW>}, 465*bdd1243dSDimitry Andric {"SLLW", 0xFE00707F, 0x103B, DecodeRType<SLLW>}, 466*bdd1243dSDimitry Andric {"SRLW", 0xFE00707F, 0x503B, DecodeRType<SRLW>}, 467*bdd1243dSDimitry Andric {"SRAW", 0xFE00707F, 0x4000503B, DecodeRType<SRAW>}, 468*bdd1243dSDimitry Andric 469*bdd1243dSDimitry Andric // RV32M & RV64M (The integer multiplication and division extension) // 470*bdd1243dSDimitry Andric {"MUL", 0xFE00707F, 0x2000033, DecodeRType<MUL>}, 471*bdd1243dSDimitry Andric {"MULH", 0xFE00707F, 0x2001033, DecodeRType<MULH>}, 472*bdd1243dSDimitry Andric {"MULHSU", 0xFE00707F, 0x2002033, DecodeRType<MULHSU>}, 473*bdd1243dSDimitry Andric {"MULHU", 0xFE00707F, 0x2003033, DecodeRType<MULHU>}, 474*bdd1243dSDimitry Andric {"DIV", 0xFE00707F, 0x2004033, DecodeRType<DIV>}, 475*bdd1243dSDimitry Andric {"DIVU", 0xFE00707F, 0x2005033, DecodeRType<DIVU>}, 476*bdd1243dSDimitry Andric {"REM", 0xFE00707F, 0x2006033, DecodeRType<REM>}, 477*bdd1243dSDimitry Andric {"REMU", 0xFE00707F, 0x2007033, DecodeRType<REMU>}, 478*bdd1243dSDimitry Andric {"MULW", 0xFE00707F, 0x200003B, DecodeRType<MULW>}, 479*bdd1243dSDimitry Andric {"DIVW", 0xFE00707F, 0x200403B, DecodeRType<DIVW>}, 480*bdd1243dSDimitry Andric {"DIVUW", 0xFE00707F, 0x200503B, DecodeRType<DIVUW>}, 481*bdd1243dSDimitry Andric {"REMW", 0xFE00707F, 0x200603B, DecodeRType<REMW>}, 482*bdd1243dSDimitry Andric {"REMUW", 0xFE00707F, 0x200703B, DecodeRType<REMUW>}, 483*bdd1243dSDimitry Andric 484*bdd1243dSDimitry Andric // RV32A & RV64A (The standard atomic instruction extension) // 485*bdd1243dSDimitry Andric {"LR_W", 0xF9F0707F, 0x1000202F, DecodeRRS1Type<LR_W>}, 486*bdd1243dSDimitry Andric {"LR_D", 0xF9F0707F, 0x1000302F, DecodeRRS1Type<LR_D>}, 487*bdd1243dSDimitry Andric {"SC_W", 0xF800707F, 0x1800202F, DecodeRType<SC_W>}, 488*bdd1243dSDimitry Andric {"SC_D", 0xF800707F, 0x1800302F, DecodeRType<SC_D>}, 489*bdd1243dSDimitry Andric {"AMOSWAP_W", 0xF800707F, 0x800202F, DecodeRType<AMOSWAP_W>}, 490*bdd1243dSDimitry Andric {"AMOADD_W", 0xF800707F, 0x202F, DecodeRType<AMOADD_W>}, 491*bdd1243dSDimitry Andric {"AMOXOR_W", 0xF800707F, 0x2000202F, DecodeRType<AMOXOR_W>}, 492*bdd1243dSDimitry Andric {"AMOAND_W", 0xF800707F, 0x6000202F, DecodeRType<AMOAND_W>}, 493*bdd1243dSDimitry Andric {"AMOOR_W", 0xF800707F, 0x4000202F, DecodeRType<AMOOR_W>}, 494*bdd1243dSDimitry Andric {"AMOMIN_W", 0xF800707F, 0x8000202F, DecodeRType<AMOMIN_W>}, 495*bdd1243dSDimitry Andric {"AMOMAX_W", 0xF800707F, 0xA000202F, DecodeRType<AMOMAX_W>}, 496*bdd1243dSDimitry Andric {"AMOMINU_W", 0xF800707F, 0xC000202F, DecodeRType<AMOMINU_W>}, 497*bdd1243dSDimitry Andric {"AMOMAXU_W", 0xF800707F, 0xE000202F, DecodeRType<AMOMAXU_W>}, 498*bdd1243dSDimitry Andric {"AMOSWAP_D", 0xF800707F, 0x800302F, DecodeRType<AMOSWAP_D>}, 499*bdd1243dSDimitry Andric {"AMOADD_D", 0xF800707F, 0x302F, DecodeRType<AMOADD_D>}, 500*bdd1243dSDimitry Andric {"AMOXOR_D", 0xF800707F, 0x2000302F, DecodeRType<AMOXOR_D>}, 501*bdd1243dSDimitry Andric {"AMOAND_D", 0xF800707F, 0x6000302F, DecodeRType<AMOAND_D>}, 502*bdd1243dSDimitry Andric {"AMOOR_D", 0xF800707F, 0x4000302F, DecodeRType<AMOOR_D>}, 503*bdd1243dSDimitry Andric {"AMOMIN_D", 0xF800707F, 0x8000302F, DecodeRType<AMOMIN_D>}, 504*bdd1243dSDimitry Andric {"AMOMAX_D", 0xF800707F, 0xA000302F, DecodeRType<AMOMAX_D>}, 505*bdd1243dSDimitry Andric {"AMOMINU_D", 0xF800707F, 0xC000302F, DecodeRType<AMOMINU_D>}, 506*bdd1243dSDimitry Andric {"AMOMAXU_D", 0xF800707F, 0xE000302F, DecodeRType<AMOMAXU_D>}, 507*bdd1243dSDimitry Andric 508*bdd1243dSDimitry Andric // RVC (Compressed Instructions) // 509*bdd1243dSDimitry Andric {"C_LWSP", 0xE003, 0x4002, DecodeC_LWSP}, 510*bdd1243dSDimitry Andric {"C_LDSP", 0xE003, 0x6002, DecodeC_LDSP, RV64 | RV128}, 511*bdd1243dSDimitry Andric {"C_SWSP", 0xE003, 0xC002, DecodeC_SWSP}, 512*bdd1243dSDimitry Andric {"C_SDSP", 0xE003, 0xE002, DecodeC_SDSP, RV64 | RV128}, 513*bdd1243dSDimitry Andric {"C_LW", 0xE003, 0x4000, DecodeC_LW}, 514*bdd1243dSDimitry Andric {"C_LD", 0xE003, 0x6000, DecodeC_LD, RV64 | RV128}, 515*bdd1243dSDimitry Andric {"C_SW", 0xE003, 0xC000, DecodeC_SW}, 516*bdd1243dSDimitry Andric {"C_SD", 0xE003, 0xE000, DecodeC_SD, RV64 | RV128}, 517*bdd1243dSDimitry Andric {"C_J", 0xE003, 0xA001, DecodeC_J}, 518*bdd1243dSDimitry Andric {"C_JR", 0xF07F, 0x8002, DecodeC_JR}, 519*bdd1243dSDimitry Andric {"C_JALR", 0xF07F, 0x9002, DecodeC_JALR}, 520*bdd1243dSDimitry Andric {"C_BNEZ", 0xE003, 0xE001, DecodeC_BNEZ}, 521*bdd1243dSDimitry Andric {"C_BEQZ", 0xE003, 0xC001, DecodeC_BEQZ}, 522*bdd1243dSDimitry Andric {"C_LI", 0xE003, 0x4001, DecodeC_LI}, 523*bdd1243dSDimitry Andric {"C_LUI_ADDI16SP", 0xE003, 0x6001, DecodeC_LUI_ADDI16SP}, 524*bdd1243dSDimitry Andric {"C_ADDI", 0xE003, 0x1, DecodeC_ADDI}, 525*bdd1243dSDimitry Andric {"C_ADDIW", 0xE003, 0x2001, DecodeC_ADDIW, RV64 | RV128}, 526*bdd1243dSDimitry Andric {"C_ADDI4SPN", 0xE003, 0x0, DecodeC_ADDI4SPN}, 527*bdd1243dSDimitry Andric {"C_SLLI", 0xE003, 0x2, DecodeC_SLLI, RV64 | RV128}, 528*bdd1243dSDimitry Andric {"C_SRLI", 0xEC03, 0x8001, DecodeC_SRLI, RV64 | RV128}, 529*bdd1243dSDimitry Andric {"C_SRAI", 0xEC03, 0x8401, DecodeC_SRAI, RV64 | RV128}, 530*bdd1243dSDimitry Andric {"C_ANDI", 0xEC03, 0x8801, DecodeC_ANDI}, 531*bdd1243dSDimitry Andric {"C_MV", 0xF003, 0x8002, DecodeC_MV}, 532*bdd1243dSDimitry Andric {"C_ADD", 0xF003, 0x9002, DecodeC_ADD}, 533*bdd1243dSDimitry Andric {"C_AND", 0xFC63, 0x8C61, DecodeC_AND}, 534*bdd1243dSDimitry Andric {"C_OR", 0xFC63, 0x8C41, DecodeC_OR}, 535*bdd1243dSDimitry Andric {"C_XOR", 0xFC63, 0x8C21, DecodeC_XOR}, 536*bdd1243dSDimitry Andric {"C_SUB", 0xFC63, 0x8C01, DecodeC_SUB}, 537*bdd1243dSDimitry Andric {"C_SUBW", 0xFC63, 0x9C01, DecodeC_SUBW, RV64 | RV128}, 538*bdd1243dSDimitry Andric {"C_ADDW", 0xFC63, 0x9C21, DecodeC_ADDW, RV64 | RV128}, 539*bdd1243dSDimitry Andric // RV32FC // 540*bdd1243dSDimitry Andric {"FLW", 0xE003, 0x6000, DecodeC_FLW, RV32}, 541*bdd1243dSDimitry Andric {"FSW", 0xE003, 0xE000, DecodeC_FSW, RV32}, 542*bdd1243dSDimitry Andric {"FLWSP", 0xE003, 0x6002, DecodeC_FLWSP, RV32}, 543*bdd1243dSDimitry Andric {"FSWSP", 0xE003, 0xE002, DecodeC_FSWSP, RV32}, 544*bdd1243dSDimitry Andric // RVDC // 545*bdd1243dSDimitry Andric {"FLDSP", 0xE003, 0x2002, DecodeC_FLDSP, RV32 | RV64}, 546*bdd1243dSDimitry Andric {"FSDSP", 0xE003, 0xA002, DecodeC_FSDSP, RV32 | RV64}, 547*bdd1243dSDimitry Andric {"FLD", 0xE003, 0x2000, DecodeC_FLD, RV32 | RV64}, 548*bdd1243dSDimitry Andric {"FSD", 0xE003, 0xA000, DecodeC_FSD, RV32 | RV64}, 549*bdd1243dSDimitry Andric 550*bdd1243dSDimitry Andric // RV32F (Extension for Single-Precision Floating-Point) // 551*bdd1243dSDimitry Andric {"FLW", 0x707F, 0x2007, DecodeIType<FLW>}, 552*bdd1243dSDimitry Andric {"FSW", 0x707F, 0x2027, DecodeSType<FSW>}, 553*bdd1243dSDimitry Andric {"FMADD_S", 0x600007F, 0x43, DecodeR4Type<FMADD_S>}, 554*bdd1243dSDimitry Andric {"FMSUB_S", 0x600007F, 0x47, DecodeR4Type<FMSUB_S>}, 555*bdd1243dSDimitry Andric {"FNMSUB_S", 0x600007F, 0x4B, DecodeR4Type<FNMSUB_S>}, 556*bdd1243dSDimitry Andric {"FNMADD_S", 0x600007F, 0x4F, DecodeR4Type<FNMADD_S>}, 557*bdd1243dSDimitry Andric {"FADD_S", 0xFE00007F, 0x53, DecodeRType<FADD_S>}, 558*bdd1243dSDimitry Andric {"FSUB_S", 0xFE00007F, 0x8000053, DecodeRType<FSUB_S>}, 559*bdd1243dSDimitry Andric {"FMUL_S", 0xFE00007F, 0x10000053, DecodeRType<FMUL_S>}, 560*bdd1243dSDimitry Andric {"FDIV_S", 0xFE00007F, 0x18000053, DecodeRType<FDIV_S>}, 561*bdd1243dSDimitry Andric {"FSQRT_S", 0xFFF0007F, 0x58000053, DecodeIType<FSQRT_S>}, 562*bdd1243dSDimitry Andric {"FSGNJ_S", 0xFE00707F, 0x20000053, DecodeRType<FSGNJ_S>}, 563*bdd1243dSDimitry Andric {"FSGNJN_S", 0xFE00707F, 0x20001053, DecodeRType<FSGNJN_S>}, 564*bdd1243dSDimitry Andric {"FSGNJX_S", 0xFE00707F, 0x20002053, DecodeRType<FSGNJX_S>}, 565*bdd1243dSDimitry Andric {"FMIN_S", 0xFE00707F, 0x28000053, DecodeRType<FMIN_S>}, 566*bdd1243dSDimitry Andric {"FMAX_S", 0xFE00707F, 0x28001053, DecodeRType<FMAX_S>}, 567*bdd1243dSDimitry Andric {"FCVT_W_S", 0xFFF0007F, 0xC0000053, DecodeIType<FCVT_W_S>}, 568*bdd1243dSDimitry Andric {"FCVT_WU_S", 0xFFF0007F, 0xC0100053, DecodeIType<FCVT_WU_S>}, 569*bdd1243dSDimitry Andric {"FMV_X_W", 0xFFF0707F, 0xE0000053, DecodeIType<FMV_X_W>}, 570*bdd1243dSDimitry Andric {"FEQ_S", 0xFE00707F, 0xA0002053, DecodeRType<FEQ_S>}, 571*bdd1243dSDimitry Andric {"FLT_S", 0xFE00707F, 0xA0001053, DecodeRType<FLT_S>}, 572*bdd1243dSDimitry Andric {"FLE_S", 0xFE00707F, 0xA0000053, DecodeRType<FLE_S>}, 573*bdd1243dSDimitry Andric {"FCLASS_S", 0xFFF0707F, 0xE0001053, DecodeIType<FCLASS_S>}, 574*bdd1243dSDimitry Andric {"FCVT_S_W", 0xFFF0007F, 0xD0000053, DecodeIType<FCVT_S_W>}, 575*bdd1243dSDimitry Andric {"FCVT_S_WU", 0xFFF0007F, 0xD0100053, DecodeIType<FCVT_S_WU>}, 576*bdd1243dSDimitry Andric {"FMV_W_X", 0xFFF0707F, 0xF0000053, DecodeIType<FMV_W_X>}, 577*bdd1243dSDimitry Andric 578*bdd1243dSDimitry Andric // RV64F (Extension for Single-Precision Floating-Point) // 579*bdd1243dSDimitry Andric {"FCVT_L_S", 0xFFF0007F, 0xC0200053, DecodeIType<FCVT_L_S>}, 580*bdd1243dSDimitry Andric {"FCVT_LU_S", 0xFFF0007F, 0xC0300053, DecodeIType<FCVT_LU_S>}, 581*bdd1243dSDimitry Andric {"FCVT_S_L", 0xFFF0007F, 0xD0200053, DecodeIType<FCVT_S_L>}, 582*bdd1243dSDimitry Andric {"FCVT_S_LU", 0xFFF0007F, 0xD0300053, DecodeIType<FCVT_S_LU>}, 583*bdd1243dSDimitry Andric 584*bdd1243dSDimitry Andric // RV32D (Extension for Double-Precision Floating-Point) // 585*bdd1243dSDimitry Andric {"FLD", 0x707F, 0x3007, DecodeIType<FLD>}, 586*bdd1243dSDimitry Andric {"FSD", 0x707F, 0x3027, DecodeSType<FSD>}, 587*bdd1243dSDimitry Andric {"FMADD_D", 0x600007F, 0x2000043, DecodeR4Type<FMADD_D>}, 588*bdd1243dSDimitry Andric {"FMSUB_D", 0x600007F, 0x2000047, DecodeR4Type<FMSUB_D>}, 589*bdd1243dSDimitry Andric {"FNMSUB_D", 0x600007F, 0x200004B, DecodeR4Type<FNMSUB_D>}, 590*bdd1243dSDimitry Andric {"FNMADD_D", 0x600007F, 0x200004F, DecodeR4Type<FNMADD_D>}, 591*bdd1243dSDimitry Andric {"FADD_D", 0xFE00007F, 0x2000053, DecodeRType<FADD_D>}, 592*bdd1243dSDimitry Andric {"FSUB_D", 0xFE00007F, 0xA000053, DecodeRType<FSUB_D>}, 593*bdd1243dSDimitry Andric {"FMUL_D", 0xFE00007F, 0x12000053, DecodeRType<FMUL_D>}, 594*bdd1243dSDimitry Andric {"FDIV_D", 0xFE00007F, 0x1A000053, DecodeRType<FDIV_D>}, 595*bdd1243dSDimitry Andric {"FSQRT_D", 0xFFF0007F, 0x5A000053, DecodeIType<FSQRT_D>}, 596*bdd1243dSDimitry Andric {"FSGNJ_D", 0xFE00707F, 0x22000053, DecodeRType<FSGNJ_D>}, 597*bdd1243dSDimitry Andric {"FSGNJN_D", 0xFE00707F, 0x22001053, DecodeRType<FSGNJN_D>}, 598*bdd1243dSDimitry Andric {"FSGNJX_D", 0xFE00707F, 0x22002053, DecodeRType<FSGNJX_D>}, 599*bdd1243dSDimitry Andric {"FMIN_D", 0xFE00707F, 0x2A000053, DecodeRType<FMIN_D>}, 600*bdd1243dSDimitry Andric {"FMAX_D", 0xFE00707F, 0x2A001053, DecodeRType<FMAX_D>}, 601*bdd1243dSDimitry Andric {"FCVT_S_D", 0xFFF0007F, 0x40100053, DecodeIType<FCVT_S_D>}, 602*bdd1243dSDimitry Andric {"FCVT_D_S", 0xFFF0007F, 0x42000053, DecodeIType<FCVT_D_S>}, 603*bdd1243dSDimitry Andric {"FEQ_D", 0xFE00707F, 0xA2002053, DecodeRType<FEQ_D>}, 604*bdd1243dSDimitry Andric {"FLT_D", 0xFE00707F, 0xA2001053, DecodeRType<FLT_D>}, 605*bdd1243dSDimitry Andric {"FLE_D", 0xFE00707F, 0xA2000053, DecodeRType<FLE_D>}, 606*bdd1243dSDimitry Andric {"FCLASS_D", 0xFFF0707F, 0xE2001053, DecodeIType<FCLASS_D>}, 607*bdd1243dSDimitry Andric {"FCVT_W_D", 0xFFF0007F, 0xC2000053, DecodeIType<FCVT_W_D>}, 608*bdd1243dSDimitry Andric {"FCVT_WU_D", 0xFFF0007F, 0xC2100053, DecodeIType<FCVT_WU_D>}, 609*bdd1243dSDimitry Andric {"FCVT_D_W", 0xFFF0007F, 0xD2000053, DecodeIType<FCVT_D_W>}, 610*bdd1243dSDimitry Andric {"FCVT_D_WU", 0xFFF0007F, 0xD2100053, DecodeIType<FCVT_D_WU>}, 611*bdd1243dSDimitry Andric 612*bdd1243dSDimitry Andric // RV64D (Extension for Double-Precision Floating-Point) // 613*bdd1243dSDimitry Andric {"FCVT_L_D", 0xFFF0007F, 0xC2200053, DecodeIType<FCVT_L_D>}, 614*bdd1243dSDimitry Andric {"FCVT_LU_D", 0xFFF0007F, 0xC2300053, DecodeIType<FCVT_LU_D>}, 615*bdd1243dSDimitry Andric {"FMV_X_D", 0xFFF0707F, 0xE2000053, DecodeIType<FMV_X_D>}, 616*bdd1243dSDimitry Andric {"FCVT_D_L", 0xFFF0007F, 0xD2200053, DecodeIType<FCVT_D_L>}, 617*bdd1243dSDimitry Andric {"FCVT_D_LU", 0xFFF0007F, 0xD2300053, DecodeIType<FCVT_D_LU>}, 618*bdd1243dSDimitry Andric {"FMV_D_X", 0xFFF0707F, 0xF2000053, DecodeIType<FMV_D_X>}, 619*bdd1243dSDimitry Andric }; 620*bdd1243dSDimitry Andric 621*bdd1243dSDimitry Andric std::optional<DecodeResult> EmulateInstructionRISCV::Decode(uint32_t inst) { 622*bdd1243dSDimitry Andric Log *log = GetLog(LLDBLog::Unwind); 623*bdd1243dSDimitry Andric 624*bdd1243dSDimitry Andric uint16_t try_rvc = uint16_t(inst & 0x0000ffff); 625*bdd1243dSDimitry Andric // check whether the compressed encode could be valid 626*bdd1243dSDimitry Andric uint16_t mask = try_rvc & 0b11; 627*bdd1243dSDimitry Andric bool is_rvc = try_rvc != 0 && mask != 3; 628*bdd1243dSDimitry Andric uint8_t inst_type = RV64; 629*bdd1243dSDimitry Andric 630*bdd1243dSDimitry Andric // if we have ArchSpec::eCore_riscv128 in the future, 631*bdd1243dSDimitry Andric // we also need to check it here 632*bdd1243dSDimitry Andric if (m_arch.GetCore() == ArchSpec::eCore_riscv32) 633*bdd1243dSDimitry Andric inst_type = RV32; 634*bdd1243dSDimitry Andric 635*bdd1243dSDimitry Andric for (const InstrPattern &pat : PATTERNS) { 636*bdd1243dSDimitry Andric if ((inst & pat.type_mask) == pat.eigen && 637*bdd1243dSDimitry Andric (inst_type & pat.inst_type) != 0) { 638*bdd1243dSDimitry Andric LLDB_LOGF( 639*bdd1243dSDimitry Andric log, "EmulateInstructionRISCV::%s: inst(%x at %lx) was decoded to %s", 640*bdd1243dSDimitry Andric __FUNCTION__, inst, m_addr, pat.name); 641*bdd1243dSDimitry Andric auto decoded = is_rvc ? pat.decode(try_rvc) : pat.decode(inst); 642*bdd1243dSDimitry Andric return DecodeResult{decoded, inst, is_rvc, pat}; 643*bdd1243dSDimitry Andric } 644*bdd1243dSDimitry Andric } 645*bdd1243dSDimitry Andric LLDB_LOGF(log, "EmulateInstructionRISCV::%s: inst(0x%x) was unsupported", 646*bdd1243dSDimitry Andric __FUNCTION__, inst); 647*bdd1243dSDimitry Andric return std::nullopt; 648*bdd1243dSDimitry Andric } 649*bdd1243dSDimitry Andric 650*bdd1243dSDimitry Andric class Executor { 651*bdd1243dSDimitry Andric EmulateInstructionRISCV &m_emu; 652*bdd1243dSDimitry Andric bool m_ignore_cond; 653*bdd1243dSDimitry Andric bool m_is_rvc; 654*bdd1243dSDimitry Andric 655*bdd1243dSDimitry Andric public: 656*bdd1243dSDimitry Andric // also used in EvaluateInstruction() 657*bdd1243dSDimitry Andric static uint64_t size(bool is_rvc) { return is_rvc ? 2 : 4; } 658*bdd1243dSDimitry Andric 659*bdd1243dSDimitry Andric private: 660*bdd1243dSDimitry Andric uint64_t delta() { return size(m_is_rvc); } 661*bdd1243dSDimitry Andric 662*bdd1243dSDimitry Andric public: 663*bdd1243dSDimitry Andric Executor(EmulateInstructionRISCV &emulator, bool ignoreCond, bool is_rvc) 664*bdd1243dSDimitry Andric : m_emu(emulator), m_ignore_cond(ignoreCond), m_is_rvc(is_rvc) {} 665*bdd1243dSDimitry Andric 666*bdd1243dSDimitry Andric bool operator()(LUI inst) { return inst.rd.Write(m_emu, SignExt(inst.imm)); } 667*bdd1243dSDimitry Andric bool operator()(AUIPC inst) { 668*bdd1243dSDimitry Andric return transformOptional(m_emu.ReadPC(), 669*bdd1243dSDimitry Andric [&](uint64_t pc) { 670*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, 671*bdd1243dSDimitry Andric SignExt(inst.imm) + pc); 672*bdd1243dSDimitry Andric }) 673*bdd1243dSDimitry Andric .value_or(false); 674*bdd1243dSDimitry Andric } 675*bdd1243dSDimitry Andric bool operator()(JAL inst) { 676*bdd1243dSDimitry Andric return transformOptional(m_emu.ReadPC(), 677*bdd1243dSDimitry Andric [&](uint64_t pc) { 678*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, pc + delta()) && 679*bdd1243dSDimitry Andric m_emu.WritePC(SignExt(inst.imm) + pc); 680*bdd1243dSDimitry Andric }) 681*bdd1243dSDimitry Andric .value_or(false); 682*bdd1243dSDimitry Andric } 683*bdd1243dSDimitry Andric bool operator()(JALR inst) { 684*bdd1243dSDimitry Andric return transformOptional(zipOpt(m_emu.ReadPC(), inst.rs1.Read(m_emu)), 685*bdd1243dSDimitry Andric [&](auto &&tup) { 686*bdd1243dSDimitry Andric auto [pc, rs1] = tup; 687*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, pc + delta()) && 688*bdd1243dSDimitry Andric m_emu.WritePC((SignExt(inst.imm) + rs1) & 689*bdd1243dSDimitry Andric ~1); 690*bdd1243dSDimitry Andric }) 691*bdd1243dSDimitry Andric .value_or(false); 692*bdd1243dSDimitry Andric } 693*bdd1243dSDimitry Andric bool operator()(B inst) { 694*bdd1243dSDimitry Andric return transformOptional(zipOpt(m_emu.ReadPC(), inst.rs1.Read(m_emu), 695*bdd1243dSDimitry Andric inst.rs2.Read(m_emu)), 696*bdd1243dSDimitry Andric [&](auto &&tup) { 697*bdd1243dSDimitry Andric auto [pc, rs1, rs2] = tup; 698*bdd1243dSDimitry Andric if (m_ignore_cond || 699*bdd1243dSDimitry Andric CompareB(rs1, rs2, inst.funct3)) 700*bdd1243dSDimitry Andric return m_emu.WritePC(SignExt(inst.imm) + pc); 701*bdd1243dSDimitry Andric return true; 702*bdd1243dSDimitry Andric }) 703*bdd1243dSDimitry Andric .value_or(false); 704*bdd1243dSDimitry Andric } 705*bdd1243dSDimitry Andric bool operator()(LB inst) { 706*bdd1243dSDimitry Andric return Load<LB, uint8_t, int8_t>(m_emu, inst, SextW); 707*bdd1243dSDimitry Andric } 708*bdd1243dSDimitry Andric bool operator()(LH inst) { 709*bdd1243dSDimitry Andric return Load<LH, uint16_t, int16_t>(m_emu, inst, SextW); 710*bdd1243dSDimitry Andric } 711*bdd1243dSDimitry Andric bool operator()(LW inst) { 712*bdd1243dSDimitry Andric return Load<LW, uint32_t, int32_t>(m_emu, inst, SextW); 713*bdd1243dSDimitry Andric } 714*bdd1243dSDimitry Andric bool operator()(LBU inst) { 715*bdd1243dSDimitry Andric return Load<LBU, uint8_t, uint8_t>(m_emu, inst, ZextD); 716*bdd1243dSDimitry Andric } 717*bdd1243dSDimitry Andric bool operator()(LHU inst) { 718*bdd1243dSDimitry Andric return Load<LHU, uint16_t, uint16_t>(m_emu, inst, ZextD); 719*bdd1243dSDimitry Andric } 720*bdd1243dSDimitry Andric bool operator()(SB inst) { return Store<SB, uint8_t>(m_emu, inst); } 721*bdd1243dSDimitry Andric bool operator()(SH inst) { return Store<SH, uint16_t>(m_emu, inst); } 722*bdd1243dSDimitry Andric bool operator()(SW inst) { return Store<SW, uint32_t>(m_emu, inst); } 723*bdd1243dSDimitry Andric bool operator()(ADDI inst) { 724*bdd1243dSDimitry Andric return transformOptional(inst.rs1.ReadI64(m_emu), 725*bdd1243dSDimitry Andric [&](int64_t rs1) { 726*bdd1243dSDimitry Andric return inst.rd.Write( 727*bdd1243dSDimitry Andric m_emu, rs1 + int64_t(SignExt(inst.imm))); 728*bdd1243dSDimitry Andric }) 729*bdd1243dSDimitry Andric .value_or(false); 730*bdd1243dSDimitry Andric } 731*bdd1243dSDimitry Andric bool operator()(SLTI inst) { 732*bdd1243dSDimitry Andric return transformOptional(inst.rs1.ReadI64(m_emu), 733*bdd1243dSDimitry Andric [&](int64_t rs1) { 734*bdd1243dSDimitry Andric return inst.rd.Write( 735*bdd1243dSDimitry Andric m_emu, rs1 < int64_t(SignExt(inst.imm))); 736*bdd1243dSDimitry Andric }) 737*bdd1243dSDimitry Andric .value_or(false); 738*bdd1243dSDimitry Andric } 739*bdd1243dSDimitry Andric bool operator()(SLTIU inst) { 740*bdd1243dSDimitry Andric return transformOptional(inst.rs1.Read(m_emu), 741*bdd1243dSDimitry Andric [&](uint64_t rs1) { 742*bdd1243dSDimitry Andric return inst.rd.Write( 743*bdd1243dSDimitry Andric m_emu, rs1 < uint64_t(SignExt(inst.imm))); 744*bdd1243dSDimitry Andric }) 745*bdd1243dSDimitry Andric .value_or(false); 746*bdd1243dSDimitry Andric } 747*bdd1243dSDimitry Andric bool operator()(XORI inst) { 748*bdd1243dSDimitry Andric return transformOptional(inst.rs1.Read(m_emu), 749*bdd1243dSDimitry Andric [&](uint64_t rs1) { 750*bdd1243dSDimitry Andric return inst.rd.Write( 751*bdd1243dSDimitry Andric m_emu, rs1 ^ uint64_t(SignExt(inst.imm))); 752*bdd1243dSDimitry Andric }) 753*bdd1243dSDimitry Andric .value_or(false); 754*bdd1243dSDimitry Andric } 755*bdd1243dSDimitry Andric bool operator()(ORI inst) { 756*bdd1243dSDimitry Andric return transformOptional(inst.rs1.Read(m_emu), 757*bdd1243dSDimitry Andric [&](uint64_t rs1) { 758*bdd1243dSDimitry Andric return inst.rd.Write( 759*bdd1243dSDimitry Andric m_emu, rs1 | uint64_t(SignExt(inst.imm))); 760*bdd1243dSDimitry Andric }) 761*bdd1243dSDimitry Andric .value_or(false); 762*bdd1243dSDimitry Andric } 763*bdd1243dSDimitry Andric bool operator()(ANDI inst) { 764*bdd1243dSDimitry Andric return transformOptional(inst.rs1.Read(m_emu), 765*bdd1243dSDimitry Andric [&](uint64_t rs1) { 766*bdd1243dSDimitry Andric return inst.rd.Write( 767*bdd1243dSDimitry Andric m_emu, rs1 & uint64_t(SignExt(inst.imm))); 768*bdd1243dSDimitry Andric }) 769*bdd1243dSDimitry Andric .value_or(false); 770*bdd1243dSDimitry Andric } 771*bdd1243dSDimitry Andric bool operator()(ADD inst) { 772*bdd1243dSDimitry Andric return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), 773*bdd1243dSDimitry Andric [&](auto &&tup) { 774*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 775*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, rs1 + rs2); 776*bdd1243dSDimitry Andric }) 777*bdd1243dSDimitry Andric .value_or(false); 778*bdd1243dSDimitry Andric } 779*bdd1243dSDimitry Andric bool operator()(SUB inst) { 780*bdd1243dSDimitry Andric return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), 781*bdd1243dSDimitry Andric [&](auto &&tup) { 782*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 783*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, rs1 - rs2); 784*bdd1243dSDimitry Andric }) 785*bdd1243dSDimitry Andric .value_or(false); 786*bdd1243dSDimitry Andric } 787*bdd1243dSDimitry Andric bool operator()(SLL inst) { 788*bdd1243dSDimitry Andric return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), 789*bdd1243dSDimitry Andric [&](auto &&tup) { 790*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 791*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, 792*bdd1243dSDimitry Andric rs1 << (rs2 & 0b111111)); 793*bdd1243dSDimitry Andric }) 794*bdd1243dSDimitry Andric .value_or(false); 795*bdd1243dSDimitry Andric } 796*bdd1243dSDimitry Andric bool operator()(SLT inst) { 797*bdd1243dSDimitry Andric return transformOptional( 798*bdd1243dSDimitry Andric zipOpt(inst.rs1.ReadI64(m_emu), inst.rs2.ReadI64(m_emu)), 799*bdd1243dSDimitry Andric [&](auto &&tup) { 800*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 801*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, rs1 < rs2); 802*bdd1243dSDimitry Andric }) 803*bdd1243dSDimitry Andric .value_or(false); 804*bdd1243dSDimitry Andric } 805*bdd1243dSDimitry Andric bool operator()(SLTU inst) { 806*bdd1243dSDimitry Andric return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), 807*bdd1243dSDimitry Andric [&](auto &&tup) { 808*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 809*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, rs1 < rs2); 810*bdd1243dSDimitry Andric }) 811*bdd1243dSDimitry Andric .value_or(false); 812*bdd1243dSDimitry Andric } 813*bdd1243dSDimitry Andric bool operator()(XOR inst) { 814*bdd1243dSDimitry Andric return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), 815*bdd1243dSDimitry Andric [&](auto &&tup) { 816*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 817*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, rs1 ^ rs2); 818*bdd1243dSDimitry Andric }) 819*bdd1243dSDimitry Andric .value_or(false); 820*bdd1243dSDimitry Andric } 821*bdd1243dSDimitry Andric bool operator()(SRL inst) { 822*bdd1243dSDimitry Andric return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), 823*bdd1243dSDimitry Andric [&](auto &&tup) { 824*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 825*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, 826*bdd1243dSDimitry Andric rs1 >> (rs2 & 0b111111)); 827*bdd1243dSDimitry Andric }) 828*bdd1243dSDimitry Andric .value_or(false); 829*bdd1243dSDimitry Andric } 830*bdd1243dSDimitry Andric bool operator()(SRA inst) { 831*bdd1243dSDimitry Andric return transformOptional( 832*bdd1243dSDimitry Andric zipOpt(inst.rs1.ReadI64(m_emu), inst.rs2.Read(m_emu)), 833*bdd1243dSDimitry Andric [&](auto &&tup) { 834*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 835*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, rs1 >> (rs2 & 0b111111)); 836*bdd1243dSDimitry Andric }) 837*bdd1243dSDimitry Andric .value_or(false); 838*bdd1243dSDimitry Andric } 839*bdd1243dSDimitry Andric bool operator()(OR inst) { 840*bdd1243dSDimitry Andric return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), 841*bdd1243dSDimitry Andric [&](auto &&tup) { 842*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 843*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, rs1 | rs2); 844*bdd1243dSDimitry Andric }) 845*bdd1243dSDimitry Andric .value_or(false); 846*bdd1243dSDimitry Andric } 847*bdd1243dSDimitry Andric bool operator()(AND inst) { 848*bdd1243dSDimitry Andric return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), 849*bdd1243dSDimitry Andric [&](auto &&tup) { 850*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 851*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, rs1 & rs2); 852*bdd1243dSDimitry Andric }) 853*bdd1243dSDimitry Andric .value_or(false); 854*bdd1243dSDimitry Andric } 855*bdd1243dSDimitry Andric bool operator()(LWU inst) { 856*bdd1243dSDimitry Andric return Load<LWU, uint32_t, uint32_t>(m_emu, inst, ZextD); 857*bdd1243dSDimitry Andric } 858*bdd1243dSDimitry Andric bool operator()(LD inst) { 859*bdd1243dSDimitry Andric return Load<LD, uint64_t, uint64_t>(m_emu, inst, ZextD); 860*bdd1243dSDimitry Andric } 861*bdd1243dSDimitry Andric bool operator()(SD inst) { return Store<SD, uint64_t>(m_emu, inst); } 862*bdd1243dSDimitry Andric bool operator()(SLLI inst) { 863*bdd1243dSDimitry Andric return transformOptional(inst.rs1.Read(m_emu), 864*bdd1243dSDimitry Andric [&](uint64_t rs1) { 865*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, rs1 << inst.shamt); 866*bdd1243dSDimitry Andric }) 867*bdd1243dSDimitry Andric .value_or(false); 868*bdd1243dSDimitry Andric } 869*bdd1243dSDimitry Andric bool operator()(SRLI inst) { 870*bdd1243dSDimitry Andric return transformOptional(inst.rs1.Read(m_emu), 871*bdd1243dSDimitry Andric [&](uint64_t rs1) { 872*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, rs1 >> inst.shamt); 873*bdd1243dSDimitry Andric }) 874*bdd1243dSDimitry Andric .value_or(false); 875*bdd1243dSDimitry Andric } 876*bdd1243dSDimitry Andric bool operator()(SRAI inst) { 877*bdd1243dSDimitry Andric return transformOptional(inst.rs1.ReadI64(m_emu), 878*bdd1243dSDimitry Andric [&](int64_t rs1) { 879*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, rs1 >> inst.shamt); 880*bdd1243dSDimitry Andric }) 881*bdd1243dSDimitry Andric .value_or(false); 882*bdd1243dSDimitry Andric } 883*bdd1243dSDimitry Andric bool operator()(ADDIW inst) { 884*bdd1243dSDimitry Andric return transformOptional(inst.rs1.ReadI32(m_emu), 885*bdd1243dSDimitry Andric [&](int32_t rs1) { 886*bdd1243dSDimitry Andric return inst.rd.Write( 887*bdd1243dSDimitry Andric m_emu, SextW(rs1 + SignExt(inst.imm))); 888*bdd1243dSDimitry Andric }) 889*bdd1243dSDimitry Andric .value_or(false); 890*bdd1243dSDimitry Andric } 891*bdd1243dSDimitry Andric bool operator()(SLLIW inst) { 892*bdd1243dSDimitry Andric return transformOptional(inst.rs1.ReadU32(m_emu), 893*bdd1243dSDimitry Andric [&](uint32_t rs1) { 894*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, 895*bdd1243dSDimitry Andric SextW(rs1 << inst.shamt)); 896*bdd1243dSDimitry Andric }) 897*bdd1243dSDimitry Andric .value_or(false); 898*bdd1243dSDimitry Andric } 899*bdd1243dSDimitry Andric bool operator()(SRLIW inst) { 900*bdd1243dSDimitry Andric return transformOptional(inst.rs1.ReadU32(m_emu), 901*bdd1243dSDimitry Andric [&](uint32_t rs1) { 902*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, 903*bdd1243dSDimitry Andric SextW(rs1 >> inst.shamt)); 904*bdd1243dSDimitry Andric }) 905*bdd1243dSDimitry Andric .value_or(false); 906*bdd1243dSDimitry Andric } 907*bdd1243dSDimitry Andric bool operator()(SRAIW inst) { 908*bdd1243dSDimitry Andric return transformOptional(inst.rs1.ReadI32(m_emu), 909*bdd1243dSDimitry Andric [&](int32_t rs1) { 910*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, 911*bdd1243dSDimitry Andric SextW(rs1 >> inst.shamt)); 912*bdd1243dSDimitry Andric }) 913*bdd1243dSDimitry Andric .value_or(false); 914*bdd1243dSDimitry Andric } 915*bdd1243dSDimitry Andric bool operator()(ADDW inst) { 916*bdd1243dSDimitry Andric return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), 917*bdd1243dSDimitry Andric [&](auto &&tup) { 918*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 919*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, 920*bdd1243dSDimitry Andric SextW(uint32_t(rs1 + rs2))); 921*bdd1243dSDimitry Andric }) 922*bdd1243dSDimitry Andric .value_or(false); 923*bdd1243dSDimitry Andric } 924*bdd1243dSDimitry Andric bool operator()(SUBW inst) { 925*bdd1243dSDimitry Andric return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), 926*bdd1243dSDimitry Andric [&](auto &&tup) { 927*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 928*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, 929*bdd1243dSDimitry Andric SextW(uint32_t(rs1 - rs2))); 930*bdd1243dSDimitry Andric }) 931*bdd1243dSDimitry Andric .value_or(false); 932*bdd1243dSDimitry Andric } 933*bdd1243dSDimitry Andric bool operator()(SLLW inst) { 934*bdd1243dSDimitry Andric return transformOptional( 935*bdd1243dSDimitry Andric zipOpt(inst.rs1.ReadU32(m_emu), inst.rs2.ReadU32(m_emu)), 936*bdd1243dSDimitry Andric [&](auto &&tup) { 937*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 938*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, SextW(rs1 << (rs2 & 0b11111))); 939*bdd1243dSDimitry Andric }) 940*bdd1243dSDimitry Andric .value_or(false); 941*bdd1243dSDimitry Andric } 942*bdd1243dSDimitry Andric bool operator()(SRLW inst) { 943*bdd1243dSDimitry Andric return transformOptional( 944*bdd1243dSDimitry Andric zipOpt(inst.rs1.ReadU32(m_emu), inst.rs2.ReadU32(m_emu)), 945*bdd1243dSDimitry Andric [&](auto &&tup) { 946*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 947*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, SextW(rs1 >> (rs2 & 0b11111))); 948*bdd1243dSDimitry Andric }) 949*bdd1243dSDimitry Andric .value_or(false); 950*bdd1243dSDimitry Andric } 951*bdd1243dSDimitry Andric bool operator()(SRAW inst) { 952*bdd1243dSDimitry Andric return transformOptional( 953*bdd1243dSDimitry Andric zipOpt(inst.rs1.ReadI32(m_emu), inst.rs2.Read(m_emu)), 954*bdd1243dSDimitry Andric [&](auto &&tup) { 955*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 956*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, SextW(rs1 >> (rs2 & 0b11111))); 957*bdd1243dSDimitry Andric }) 958*bdd1243dSDimitry Andric .value_or(false); 959*bdd1243dSDimitry Andric } 960*bdd1243dSDimitry Andric // RV32M & RV64M (Integer Multiplication and Division Extension) // 961*bdd1243dSDimitry Andric bool operator()(MUL inst) { 962*bdd1243dSDimitry Andric return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), 963*bdd1243dSDimitry Andric [&](auto &&tup) { 964*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 965*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, rs1 * rs2); 966*bdd1243dSDimitry Andric }) 967*bdd1243dSDimitry Andric .value_or(false); 968*bdd1243dSDimitry Andric } 969*bdd1243dSDimitry Andric bool operator()(MULH inst) { 970*bdd1243dSDimitry Andric return transformOptional( 971*bdd1243dSDimitry Andric zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), 972*bdd1243dSDimitry Andric [&](auto &&tup) { 973*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 974*bdd1243dSDimitry Andric // signed * signed 975*bdd1243dSDimitry Andric auto mul = APInt(128, rs1, true) * APInt(128, rs2, true); 976*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, 977*bdd1243dSDimitry Andric mul.ashr(64).trunc(64).getZExtValue()); 978*bdd1243dSDimitry Andric }) 979*bdd1243dSDimitry Andric .value_or(false); 980*bdd1243dSDimitry Andric } 981*bdd1243dSDimitry Andric bool operator()(MULHSU inst) { 982*bdd1243dSDimitry Andric return transformOptional( 983*bdd1243dSDimitry Andric zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), 984*bdd1243dSDimitry Andric [&](auto &&tup) { 985*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 986*bdd1243dSDimitry Andric // signed * unsigned 987*bdd1243dSDimitry Andric auto mul = 988*bdd1243dSDimitry Andric APInt(128, rs1, true).zext(128) * APInt(128, rs2, false); 989*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, 990*bdd1243dSDimitry Andric mul.lshr(64).trunc(64).getZExtValue()); 991*bdd1243dSDimitry Andric }) 992*bdd1243dSDimitry Andric .value_or(false); 993*bdd1243dSDimitry Andric } 994*bdd1243dSDimitry Andric bool operator()(MULHU inst) { 995*bdd1243dSDimitry Andric return transformOptional( 996*bdd1243dSDimitry Andric zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), 997*bdd1243dSDimitry Andric [&](auto &&tup) { 998*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 999*bdd1243dSDimitry Andric // unsigned * unsigned 1000*bdd1243dSDimitry Andric auto mul = APInt(128, rs1, false) * APInt(128, rs2, false); 1001*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, 1002*bdd1243dSDimitry Andric mul.lshr(64).trunc(64).getZExtValue()); 1003*bdd1243dSDimitry Andric }) 1004*bdd1243dSDimitry Andric .value_or(false); 1005*bdd1243dSDimitry Andric } 1006*bdd1243dSDimitry Andric bool operator()(DIV inst) { 1007*bdd1243dSDimitry Andric return transformOptional( 1008*bdd1243dSDimitry Andric zipOpt(inst.rs1.ReadI64(m_emu), inst.rs2.ReadI64(m_emu)), 1009*bdd1243dSDimitry Andric [&](auto &&tup) { 1010*bdd1243dSDimitry Andric auto [dividend, divisor] = tup; 1011*bdd1243dSDimitry Andric 1012*bdd1243dSDimitry Andric if (divisor == 0) 1013*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, UINT64_MAX); 1014*bdd1243dSDimitry Andric 1015*bdd1243dSDimitry Andric if (dividend == INT64_MIN && divisor == -1) 1016*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, dividend); 1017*bdd1243dSDimitry Andric 1018*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, dividend / divisor); 1019*bdd1243dSDimitry Andric }) 1020*bdd1243dSDimitry Andric .value_or(false); 1021*bdd1243dSDimitry Andric } 1022*bdd1243dSDimitry Andric bool operator()(DIVU inst) { 1023*bdd1243dSDimitry Andric return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), 1024*bdd1243dSDimitry Andric [&](auto &&tup) { 1025*bdd1243dSDimitry Andric auto [dividend, divisor] = tup; 1026*bdd1243dSDimitry Andric 1027*bdd1243dSDimitry Andric if (divisor == 0) 1028*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, UINT64_MAX); 1029*bdd1243dSDimitry Andric 1030*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, dividend / divisor); 1031*bdd1243dSDimitry Andric }) 1032*bdd1243dSDimitry Andric .value_or(false); 1033*bdd1243dSDimitry Andric } 1034*bdd1243dSDimitry Andric bool operator()(REM inst) { 1035*bdd1243dSDimitry Andric return transformOptional( 1036*bdd1243dSDimitry Andric zipOpt(inst.rs1.ReadI64(m_emu), inst.rs2.ReadI64(m_emu)), 1037*bdd1243dSDimitry Andric [&](auto &&tup) { 1038*bdd1243dSDimitry Andric auto [dividend, divisor] = tup; 1039*bdd1243dSDimitry Andric 1040*bdd1243dSDimitry Andric if (divisor == 0) 1041*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, dividend); 1042*bdd1243dSDimitry Andric 1043*bdd1243dSDimitry Andric if (dividend == INT64_MIN && divisor == -1) 1044*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, 0); 1045*bdd1243dSDimitry Andric 1046*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, dividend % divisor); 1047*bdd1243dSDimitry Andric }) 1048*bdd1243dSDimitry Andric .value_or(false); 1049*bdd1243dSDimitry Andric } 1050*bdd1243dSDimitry Andric bool operator()(REMU inst) { 1051*bdd1243dSDimitry Andric return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), 1052*bdd1243dSDimitry Andric [&](auto &&tup) { 1053*bdd1243dSDimitry Andric auto [dividend, divisor] = tup; 1054*bdd1243dSDimitry Andric 1055*bdd1243dSDimitry Andric if (divisor == 0) 1056*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, dividend); 1057*bdd1243dSDimitry Andric 1058*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, dividend % divisor); 1059*bdd1243dSDimitry Andric }) 1060*bdd1243dSDimitry Andric .value_or(false); 1061*bdd1243dSDimitry Andric } 1062*bdd1243dSDimitry Andric bool operator()(MULW inst) { 1063*bdd1243dSDimitry Andric return transformOptional( 1064*bdd1243dSDimitry Andric zipOpt(inst.rs1.ReadI32(m_emu), inst.rs2.ReadI32(m_emu)), 1065*bdd1243dSDimitry Andric [&](auto &&tup) { 1066*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 1067*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, SextW(rs1 * rs2)); 1068*bdd1243dSDimitry Andric }) 1069*bdd1243dSDimitry Andric .value_or(false); 1070*bdd1243dSDimitry Andric } 1071*bdd1243dSDimitry Andric bool operator()(DIVW inst) { 1072*bdd1243dSDimitry Andric return transformOptional( 1073*bdd1243dSDimitry Andric zipOpt(inst.rs1.ReadI32(m_emu), inst.rs2.ReadI32(m_emu)), 1074*bdd1243dSDimitry Andric [&](auto &&tup) { 1075*bdd1243dSDimitry Andric auto [dividend, divisor] = tup; 1076*bdd1243dSDimitry Andric 1077*bdd1243dSDimitry Andric if (divisor == 0) 1078*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, UINT64_MAX); 1079*bdd1243dSDimitry Andric 1080*bdd1243dSDimitry Andric if (dividend == INT32_MIN && divisor == -1) 1081*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, SextW(dividend)); 1082*bdd1243dSDimitry Andric 1083*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, SextW(dividend / divisor)); 1084*bdd1243dSDimitry Andric }) 1085*bdd1243dSDimitry Andric .value_or(false); 1086*bdd1243dSDimitry Andric } 1087*bdd1243dSDimitry Andric bool operator()(DIVUW inst) { 1088*bdd1243dSDimitry Andric return transformOptional( 1089*bdd1243dSDimitry Andric zipOpt(inst.rs1.ReadU32(m_emu), inst.rs2.ReadU32(m_emu)), 1090*bdd1243dSDimitry Andric [&](auto &&tup) { 1091*bdd1243dSDimitry Andric auto [dividend, divisor] = tup; 1092*bdd1243dSDimitry Andric 1093*bdd1243dSDimitry Andric if (divisor == 0) 1094*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, UINT64_MAX); 1095*bdd1243dSDimitry Andric 1096*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, SextW(dividend / divisor)); 1097*bdd1243dSDimitry Andric }) 1098*bdd1243dSDimitry Andric .value_or(false); 1099*bdd1243dSDimitry Andric } 1100*bdd1243dSDimitry Andric bool operator()(REMW inst) { 1101*bdd1243dSDimitry Andric return transformOptional( 1102*bdd1243dSDimitry Andric zipOpt(inst.rs1.ReadI32(m_emu), inst.rs2.ReadI32(m_emu)), 1103*bdd1243dSDimitry Andric [&](auto &&tup) { 1104*bdd1243dSDimitry Andric auto [dividend, divisor] = tup; 1105*bdd1243dSDimitry Andric 1106*bdd1243dSDimitry Andric if (divisor == 0) 1107*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, SextW(dividend)); 1108*bdd1243dSDimitry Andric 1109*bdd1243dSDimitry Andric if (dividend == INT32_MIN && divisor == -1) 1110*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, 0); 1111*bdd1243dSDimitry Andric 1112*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, SextW(dividend % divisor)); 1113*bdd1243dSDimitry Andric }) 1114*bdd1243dSDimitry Andric .value_or(false); 1115*bdd1243dSDimitry Andric } 1116*bdd1243dSDimitry Andric bool operator()(REMUW inst) { 1117*bdd1243dSDimitry Andric return transformOptional( 1118*bdd1243dSDimitry Andric zipOpt(inst.rs1.ReadU32(m_emu), inst.rs2.ReadU32(m_emu)), 1119*bdd1243dSDimitry Andric [&](auto &&tup) { 1120*bdd1243dSDimitry Andric auto [dividend, divisor] = tup; 1121*bdd1243dSDimitry Andric 1122*bdd1243dSDimitry Andric if (divisor == 0) 1123*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, SextW(dividend)); 1124*bdd1243dSDimitry Andric 1125*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, SextW(dividend % divisor)); 1126*bdd1243dSDimitry Andric }) 1127*bdd1243dSDimitry Andric .value_or(false); 1128*bdd1243dSDimitry Andric } 1129*bdd1243dSDimitry Andric // RV32A & RV64A (The standard atomic instruction extension) // 1130*bdd1243dSDimitry Andric bool operator()(LR_W) { return AtomicSequence(m_emu); } 1131*bdd1243dSDimitry Andric bool operator()(LR_D) { return AtomicSequence(m_emu); } 1132*bdd1243dSDimitry Andric bool operator()(SC_W) { 1133*bdd1243dSDimitry Andric llvm_unreachable("should be handled in AtomicSequence"); 1134*bdd1243dSDimitry Andric } 1135*bdd1243dSDimitry Andric bool operator()(SC_D) { 1136*bdd1243dSDimitry Andric llvm_unreachable("should be handled in AtomicSequence"); 1137*bdd1243dSDimitry Andric } 1138*bdd1243dSDimitry Andric bool operator()(AMOSWAP_W inst) { 1139*bdd1243dSDimitry Andric return AtomicSwap<AMOSWAP_W, uint32_t>(m_emu, inst, 4, SextW); 1140*bdd1243dSDimitry Andric } 1141*bdd1243dSDimitry Andric bool operator()(AMOADD_W inst) { 1142*bdd1243dSDimitry Andric return AtomicADD<AMOADD_W, uint32_t>(m_emu, inst, 4, SextW); 1143*bdd1243dSDimitry Andric } 1144*bdd1243dSDimitry Andric bool operator()(AMOXOR_W inst) { 1145*bdd1243dSDimitry Andric return AtomicBitOperate<AMOXOR_W, uint32_t>( 1146*bdd1243dSDimitry Andric m_emu, inst, 4, SextW, [](uint32_t a, uint32_t b) { return a ^ b; }); 1147*bdd1243dSDimitry Andric } 1148*bdd1243dSDimitry Andric bool operator()(AMOAND_W inst) { 1149*bdd1243dSDimitry Andric return AtomicBitOperate<AMOAND_W, uint32_t>( 1150*bdd1243dSDimitry Andric m_emu, inst, 4, SextW, [](uint32_t a, uint32_t b) { return a & b; }); 1151*bdd1243dSDimitry Andric } 1152*bdd1243dSDimitry Andric bool operator()(AMOOR_W inst) { 1153*bdd1243dSDimitry Andric return AtomicBitOperate<AMOOR_W, uint32_t>( 1154*bdd1243dSDimitry Andric m_emu, inst, 4, SextW, [](uint32_t a, uint32_t b) { return a | b; }); 1155*bdd1243dSDimitry Andric } 1156*bdd1243dSDimitry Andric bool operator()(AMOMIN_W inst) { 1157*bdd1243dSDimitry Andric return AtomicCmp<AMOMIN_W, uint32_t>( 1158*bdd1243dSDimitry Andric m_emu, inst, 4, SextW, [](uint32_t a, uint32_t b) { 1159*bdd1243dSDimitry Andric return uint32_t(std::min(int32_t(a), int32_t(b))); 1160*bdd1243dSDimitry Andric }); 1161*bdd1243dSDimitry Andric } 1162*bdd1243dSDimitry Andric bool operator()(AMOMAX_W inst) { 1163*bdd1243dSDimitry Andric return AtomicCmp<AMOMAX_W, uint32_t>( 1164*bdd1243dSDimitry Andric m_emu, inst, 4, SextW, [](uint32_t a, uint32_t b) { 1165*bdd1243dSDimitry Andric return uint32_t(std::max(int32_t(a), int32_t(b))); 1166*bdd1243dSDimitry Andric }); 1167*bdd1243dSDimitry Andric } 1168*bdd1243dSDimitry Andric bool operator()(AMOMINU_W inst) { 1169*bdd1243dSDimitry Andric return AtomicCmp<AMOMINU_W, uint32_t>( 1170*bdd1243dSDimitry Andric m_emu, inst, 4, SextW, 1171*bdd1243dSDimitry Andric [](uint32_t a, uint32_t b) { return std::min(a, b); }); 1172*bdd1243dSDimitry Andric } 1173*bdd1243dSDimitry Andric bool operator()(AMOMAXU_W inst) { 1174*bdd1243dSDimitry Andric return AtomicCmp<AMOMAXU_W, uint32_t>( 1175*bdd1243dSDimitry Andric m_emu, inst, 4, SextW, 1176*bdd1243dSDimitry Andric [](uint32_t a, uint32_t b) { return std::max(a, b); }); 1177*bdd1243dSDimitry Andric } 1178*bdd1243dSDimitry Andric bool operator()(AMOSWAP_D inst) { 1179*bdd1243dSDimitry Andric return AtomicSwap<AMOSWAP_D, uint64_t>(m_emu, inst, 8, ZextD); 1180*bdd1243dSDimitry Andric } 1181*bdd1243dSDimitry Andric bool operator()(AMOADD_D inst) { 1182*bdd1243dSDimitry Andric return AtomicADD<AMOADD_D, uint64_t>(m_emu, inst, 8, ZextD); 1183*bdd1243dSDimitry Andric } 1184*bdd1243dSDimitry Andric bool operator()(AMOXOR_D inst) { 1185*bdd1243dSDimitry Andric return AtomicBitOperate<AMOXOR_D, uint64_t>( 1186*bdd1243dSDimitry Andric m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) { return a ^ b; }); 1187*bdd1243dSDimitry Andric } 1188*bdd1243dSDimitry Andric bool operator()(AMOAND_D inst) { 1189*bdd1243dSDimitry Andric return AtomicBitOperate<AMOAND_D, uint64_t>( 1190*bdd1243dSDimitry Andric m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) { return a & b; }); 1191*bdd1243dSDimitry Andric } 1192*bdd1243dSDimitry Andric bool operator()(AMOOR_D inst) { 1193*bdd1243dSDimitry Andric return AtomicBitOperate<AMOOR_D, uint64_t>( 1194*bdd1243dSDimitry Andric m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) { return a | b; }); 1195*bdd1243dSDimitry Andric } 1196*bdd1243dSDimitry Andric bool operator()(AMOMIN_D inst) { 1197*bdd1243dSDimitry Andric return AtomicCmp<AMOMIN_D, uint64_t>( 1198*bdd1243dSDimitry Andric m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) { 1199*bdd1243dSDimitry Andric return uint64_t(std::min(int64_t(a), int64_t(b))); 1200*bdd1243dSDimitry Andric }); 1201*bdd1243dSDimitry Andric } 1202*bdd1243dSDimitry Andric bool operator()(AMOMAX_D inst) { 1203*bdd1243dSDimitry Andric return AtomicCmp<AMOMAX_D, uint64_t>( 1204*bdd1243dSDimitry Andric m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) { 1205*bdd1243dSDimitry Andric return uint64_t(std::max(int64_t(a), int64_t(b))); 1206*bdd1243dSDimitry Andric }); 1207*bdd1243dSDimitry Andric } 1208*bdd1243dSDimitry Andric bool operator()(AMOMINU_D inst) { 1209*bdd1243dSDimitry Andric return AtomicCmp<AMOMINU_D, uint64_t>( 1210*bdd1243dSDimitry Andric m_emu, inst, 8, ZextD, 1211*bdd1243dSDimitry Andric [](uint64_t a, uint64_t b) { return std::min(a, b); }); 1212*bdd1243dSDimitry Andric } 1213*bdd1243dSDimitry Andric bool operator()(AMOMAXU_D inst) { 1214*bdd1243dSDimitry Andric return AtomicCmp<AMOMAXU_D, uint64_t>( 1215*bdd1243dSDimitry Andric m_emu, inst, 8, ZextD, 1216*bdd1243dSDimitry Andric [](uint64_t a, uint64_t b) { return std::max(a, b); }); 1217*bdd1243dSDimitry Andric } 1218*bdd1243dSDimitry Andric template <typename T> 1219*bdd1243dSDimitry Andric bool F_Load(T inst, const fltSemantics &(*semantics)(), 1220*bdd1243dSDimitry Andric unsigned int numBits) { 1221*bdd1243dSDimitry Andric return transformOptional(inst.rs1.Read(m_emu), 1222*bdd1243dSDimitry Andric [&](auto &&rs1) { 1223*bdd1243dSDimitry Andric uint64_t addr = rs1 + uint64_t(inst.imm); 1224*bdd1243dSDimitry Andric uint64_t bits = *m_emu.ReadMem<uint64_t>(addr); 1225*bdd1243dSDimitry Andric APFloat f(semantics(), APInt(numBits, bits)); 1226*bdd1243dSDimitry Andric return inst.rd.WriteAPFloat(m_emu, f); 1227*bdd1243dSDimitry Andric }) 1228*bdd1243dSDimitry Andric .value_or(false); 1229*bdd1243dSDimitry Andric } 1230*bdd1243dSDimitry Andric bool operator()(FLW inst) { return F_Load(inst, &APFloat::IEEEsingle, 32); } 1231*bdd1243dSDimitry Andric template <typename T> bool F_Store(T inst, bool isDouble) { 1232*bdd1243dSDimitry Andric return transformOptional(zipOpt(inst.rs1.Read(m_emu), 1233*bdd1243dSDimitry Andric inst.rs2.ReadAPFloat(m_emu, isDouble)), 1234*bdd1243dSDimitry Andric [&](auto &&tup) { 1235*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 1236*bdd1243dSDimitry Andric uint64_t addr = rs1 + uint64_t(inst.imm); 1237*bdd1243dSDimitry Andric uint64_t bits = 1238*bdd1243dSDimitry Andric rs2.bitcastToAPInt().getZExtValue(); 1239*bdd1243dSDimitry Andric return m_emu.WriteMem<uint64_t>(addr, bits); 1240*bdd1243dSDimitry Andric }) 1241*bdd1243dSDimitry Andric .value_or(false); 1242*bdd1243dSDimitry Andric } 1243*bdd1243dSDimitry Andric bool operator()(FSW inst) { return F_Store(inst, false); } 1244*bdd1243dSDimitry Andric std::tuple<bool, APFloat> FusedMultiplyAdd(APFloat rs1, APFloat rs2, 1245*bdd1243dSDimitry Andric APFloat rs3) { 1246*bdd1243dSDimitry Andric auto opStatus = rs1.fusedMultiplyAdd(rs2, rs3, m_emu.GetRoundingMode()); 1247*bdd1243dSDimitry Andric auto res = m_emu.SetAccruedExceptions(opStatus); 1248*bdd1243dSDimitry Andric return {res, rs1}; 1249*bdd1243dSDimitry Andric } 1250*bdd1243dSDimitry Andric template <typename T> 1251*bdd1243dSDimitry Andric bool FMA(T inst, bool isDouble, float rs2_sign, float rs3_sign) { 1252*bdd1243dSDimitry Andric return transformOptional(zipOpt(inst.rs1.ReadAPFloat(m_emu, isDouble), 1253*bdd1243dSDimitry Andric inst.rs2.ReadAPFloat(m_emu, isDouble), 1254*bdd1243dSDimitry Andric inst.rs3.ReadAPFloat(m_emu, isDouble)), 1255*bdd1243dSDimitry Andric [&](auto &&tup) { 1256*bdd1243dSDimitry Andric auto [rs1, rs2, rs3] = tup; 1257*bdd1243dSDimitry Andric rs2.copySign(APFloat(rs2_sign)); 1258*bdd1243dSDimitry Andric rs3.copySign(APFloat(rs3_sign)); 1259*bdd1243dSDimitry Andric auto [res, f] = FusedMultiplyAdd(rs1, rs2, rs3); 1260*bdd1243dSDimitry Andric return res && inst.rd.WriteAPFloat(m_emu, f); 1261*bdd1243dSDimitry Andric }) 1262*bdd1243dSDimitry Andric .value_or(false); 1263*bdd1243dSDimitry Andric } 1264*bdd1243dSDimitry Andric bool operator()(FMADD_S inst) { return FMA(inst, false, 1.0f, 1.0f); } 1265*bdd1243dSDimitry Andric bool operator()(FMSUB_S inst) { return FMA(inst, false, 1.0f, -1.0f); } 1266*bdd1243dSDimitry Andric bool operator()(FNMSUB_S inst) { return FMA(inst, false, -1.0f, 1.0f); } 1267*bdd1243dSDimitry Andric bool operator()(FNMADD_S inst) { return FMA(inst, false, -1.0f, -1.0f); } 1268*bdd1243dSDimitry Andric template <typename T> 1269*bdd1243dSDimitry Andric bool F_Op(T inst, bool isDouble, 1270*bdd1243dSDimitry Andric APFloat::opStatus (APFloat::*f)(const APFloat &RHS, 1271*bdd1243dSDimitry Andric APFloat::roundingMode RM)) { 1272*bdd1243dSDimitry Andric return transformOptional(zipOpt(inst.rs1.ReadAPFloat(m_emu, isDouble), 1273*bdd1243dSDimitry Andric inst.rs2.ReadAPFloat(m_emu, isDouble)), 1274*bdd1243dSDimitry Andric [&](auto &&tup) { 1275*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 1276*bdd1243dSDimitry Andric auto res = 1277*bdd1243dSDimitry Andric ((&rs1)->*f)(rs2, m_emu.GetRoundingMode()); 1278*bdd1243dSDimitry Andric inst.rd.WriteAPFloat(m_emu, rs1); 1279*bdd1243dSDimitry Andric return m_emu.SetAccruedExceptions(res); 1280*bdd1243dSDimitry Andric }) 1281*bdd1243dSDimitry Andric .value_or(false); 1282*bdd1243dSDimitry Andric } 1283*bdd1243dSDimitry Andric bool operator()(FADD_S inst) { return F_Op(inst, false, &APFloat::add); } 1284*bdd1243dSDimitry Andric bool operator()(FSUB_S inst) { return F_Op(inst, false, &APFloat::subtract); } 1285*bdd1243dSDimitry Andric bool operator()(FMUL_S inst) { return F_Op(inst, false, &APFloat::multiply); } 1286*bdd1243dSDimitry Andric bool operator()(FDIV_S inst) { return F_Op(inst, false, &APFloat::divide); } 1287*bdd1243dSDimitry Andric bool operator()(FSQRT_S inst) { 1288*bdd1243dSDimitry Andric // TODO: APFloat doesn't have a sqrt function. 1289*bdd1243dSDimitry Andric return false; 1290*bdd1243dSDimitry Andric } 1291*bdd1243dSDimitry Andric template <typename T> bool F_SignInj(T inst, bool isDouble, bool isNegate) { 1292*bdd1243dSDimitry Andric return transformOptional(zipOpt(inst.rs1.ReadAPFloat(m_emu, isDouble), 1293*bdd1243dSDimitry Andric inst.rs2.ReadAPFloat(m_emu, isDouble)), 1294*bdd1243dSDimitry Andric [&](auto &&tup) { 1295*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 1296*bdd1243dSDimitry Andric if (isNegate) 1297*bdd1243dSDimitry Andric rs2.changeSign(); 1298*bdd1243dSDimitry Andric rs1.copySign(rs2); 1299*bdd1243dSDimitry Andric return inst.rd.WriteAPFloat(m_emu, rs1); 1300*bdd1243dSDimitry Andric }) 1301*bdd1243dSDimitry Andric .value_or(false); 1302*bdd1243dSDimitry Andric } 1303*bdd1243dSDimitry Andric bool operator()(FSGNJ_S inst) { return F_SignInj(inst, false, false); } 1304*bdd1243dSDimitry Andric bool operator()(FSGNJN_S inst) { return F_SignInj(inst, false, true); } 1305*bdd1243dSDimitry Andric template <typename T> bool F_SignInjXor(T inst, bool isDouble) { 1306*bdd1243dSDimitry Andric return transformOptional(zipOpt(inst.rs1.ReadAPFloat(m_emu, isDouble), 1307*bdd1243dSDimitry Andric inst.rs2.ReadAPFloat(m_emu, isDouble)), 1308*bdd1243dSDimitry Andric [&](auto &&tup) { 1309*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 1310*bdd1243dSDimitry Andric // spec: the sign bit is the XOR of the sign bits 1311*bdd1243dSDimitry Andric // of rs1 and rs2. if rs1 and rs2 have the same 1312*bdd1243dSDimitry Andric // signs set rs1 to positive else set rs1 to 1313*bdd1243dSDimitry Andric // negative 1314*bdd1243dSDimitry Andric if (rs1.isNegative() == rs2.isNegative()) { 1315*bdd1243dSDimitry Andric rs1.clearSign(); 1316*bdd1243dSDimitry Andric } else { 1317*bdd1243dSDimitry Andric rs1.clearSign(); 1318*bdd1243dSDimitry Andric rs1.changeSign(); 1319*bdd1243dSDimitry Andric } 1320*bdd1243dSDimitry Andric return inst.rd.WriteAPFloat(m_emu, rs1); 1321*bdd1243dSDimitry Andric }) 1322*bdd1243dSDimitry Andric .value_or(false); 1323*bdd1243dSDimitry Andric } 1324*bdd1243dSDimitry Andric bool operator()(FSGNJX_S inst) { return F_SignInjXor(inst, false); } 1325*bdd1243dSDimitry Andric template <typename T> 1326*bdd1243dSDimitry Andric bool F_MAX_MIN(T inst, bool isDouble, 1327*bdd1243dSDimitry Andric APFloat (*f)(const APFloat &A, const APFloat &B)) { 1328*bdd1243dSDimitry Andric return transformOptional( 1329*bdd1243dSDimitry Andric zipOpt(inst.rs1.ReadAPFloat(m_emu, isDouble), 1330*bdd1243dSDimitry Andric inst.rs2.ReadAPFloat(m_emu, isDouble)), 1331*bdd1243dSDimitry Andric [&](auto &&tup) { 1332*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 1333*bdd1243dSDimitry Andric // If both inputs are NaNs, the result is the canonical NaN. 1334*bdd1243dSDimitry Andric // If only one operand is a NaN, the result is the non-NaN 1335*bdd1243dSDimitry Andric // operand. Signaling NaN inputs set the invalid operation 1336*bdd1243dSDimitry Andric // exception flag, even when the result is not NaN. 1337*bdd1243dSDimitry Andric if (rs1.isNaN() || rs2.isNaN()) 1338*bdd1243dSDimitry Andric m_emu.SetAccruedExceptions(APFloat::opInvalidOp); 1339*bdd1243dSDimitry Andric if (rs1.isNaN() && rs2.isNaN()) { 1340*bdd1243dSDimitry Andric auto canonicalNaN = APFloat::getQNaN(rs1.getSemantics()); 1341*bdd1243dSDimitry Andric return inst.rd.WriteAPFloat(m_emu, canonicalNaN); 1342*bdd1243dSDimitry Andric } 1343*bdd1243dSDimitry Andric return inst.rd.WriteAPFloat(m_emu, f(rs1, rs2)); 1344*bdd1243dSDimitry Andric }) 1345*bdd1243dSDimitry Andric .value_or(false); 1346*bdd1243dSDimitry Andric } 1347*bdd1243dSDimitry Andric bool operator()(FMIN_S inst) { return F_MAX_MIN(inst, false, minnum); } 1348*bdd1243dSDimitry Andric bool operator()(FMAX_S inst) { return F_MAX_MIN(inst, false, maxnum); } 1349*bdd1243dSDimitry Andric bool operator()(FCVT_W_S inst) { 1350*bdd1243dSDimitry Andric return FCVT_i2f<FCVT_W_S, int32_t, float>(inst, false, 1351*bdd1243dSDimitry Andric &APFloat::convertToFloat); 1352*bdd1243dSDimitry Andric } 1353*bdd1243dSDimitry Andric bool operator()(FCVT_WU_S inst) { 1354*bdd1243dSDimitry Andric return FCVT_i2f<FCVT_WU_S, uint32_t, float>(inst, false, 1355*bdd1243dSDimitry Andric &APFloat::convertToFloat); 1356*bdd1243dSDimitry Andric } 1357*bdd1243dSDimitry Andric template <typename T> bool FMV_f2i(T inst, bool isDouble) { 1358*bdd1243dSDimitry Andric return transformOptional( 1359*bdd1243dSDimitry Andric inst.rs1.ReadAPFloat(m_emu, isDouble), 1360*bdd1243dSDimitry Andric [&](auto &&rs1) { 1361*bdd1243dSDimitry Andric if (rs1.isNaN()) { 1362*bdd1243dSDimitry Andric if (isDouble) 1363*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, 0x7ff8'0000'0000'0000); 1364*bdd1243dSDimitry Andric else 1365*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, 0x7fc0'0000); 1366*bdd1243dSDimitry Andric } 1367*bdd1243dSDimitry Andric auto bits = rs1.bitcastToAPInt().getZExtValue(); 1368*bdd1243dSDimitry Andric if (isDouble) 1369*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, bits); 1370*bdd1243dSDimitry Andric else 1371*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, uint64_t(bits & 0xffff'ffff)); 1372*bdd1243dSDimitry Andric }) 1373*bdd1243dSDimitry Andric .value_or(false); 1374*bdd1243dSDimitry Andric } 1375*bdd1243dSDimitry Andric bool operator()(FMV_X_W inst) { return FMV_f2i(inst, false); } 1376*bdd1243dSDimitry Andric enum F_CMP { 1377*bdd1243dSDimitry Andric FEQ, 1378*bdd1243dSDimitry Andric FLT, 1379*bdd1243dSDimitry Andric FLE, 1380*bdd1243dSDimitry Andric }; 1381*bdd1243dSDimitry Andric template <typename T> bool F_Compare(T inst, bool isDouble, F_CMP cmp) { 1382*bdd1243dSDimitry Andric return transformOptional( 1383*bdd1243dSDimitry Andric zipOpt(inst.rs1.ReadAPFloat(m_emu, isDouble), 1384*bdd1243dSDimitry Andric inst.rs2.ReadAPFloat(m_emu, isDouble)), 1385*bdd1243dSDimitry Andric [&](auto &&tup) { 1386*bdd1243dSDimitry Andric auto [rs1, rs2] = tup; 1387*bdd1243dSDimitry Andric if (rs1.isNaN() || rs2.isNaN()) { 1388*bdd1243dSDimitry Andric if (cmp == FEQ) { 1389*bdd1243dSDimitry Andric if (rs1.isSignaling() || rs2.isSignaling()) { 1390*bdd1243dSDimitry Andric auto res = 1391*bdd1243dSDimitry Andric m_emu.SetAccruedExceptions(APFloat::opInvalidOp); 1392*bdd1243dSDimitry Andric return res && inst.rd.Write(m_emu, 0); 1393*bdd1243dSDimitry Andric } 1394*bdd1243dSDimitry Andric } 1395*bdd1243dSDimitry Andric auto res = m_emu.SetAccruedExceptions(APFloat::opInvalidOp); 1396*bdd1243dSDimitry Andric return res && inst.rd.Write(m_emu, 0); 1397*bdd1243dSDimitry Andric } 1398*bdd1243dSDimitry Andric switch (cmp) { 1399*bdd1243dSDimitry Andric case FEQ: 1400*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, 1401*bdd1243dSDimitry Andric rs1.compare(rs2) == APFloat::cmpEqual); 1402*bdd1243dSDimitry Andric case FLT: 1403*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, rs1.compare(rs2) == 1404*bdd1243dSDimitry Andric APFloat::cmpLessThan); 1405*bdd1243dSDimitry Andric case FLE: 1406*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, rs1.compare(rs2) != 1407*bdd1243dSDimitry Andric APFloat::cmpGreaterThan); 1408*bdd1243dSDimitry Andric } 1409*bdd1243dSDimitry Andric llvm_unreachable("unsupported F_CMP"); 1410*bdd1243dSDimitry Andric }) 1411*bdd1243dSDimitry Andric .value_or(false); 1412*bdd1243dSDimitry Andric } 1413*bdd1243dSDimitry Andric 1414*bdd1243dSDimitry Andric bool operator()(FEQ_S inst) { return F_Compare(inst, false, FEQ); } 1415*bdd1243dSDimitry Andric bool operator()(FLT_S inst) { return F_Compare(inst, false, FLT); } 1416*bdd1243dSDimitry Andric bool operator()(FLE_S inst) { return F_Compare(inst, false, FLE); } 1417*bdd1243dSDimitry Andric template <typename T> bool FCLASS(T inst, bool isDouble) { 1418*bdd1243dSDimitry Andric return transformOptional(inst.rs1.ReadAPFloat(m_emu, isDouble), 1419*bdd1243dSDimitry Andric [&](auto &&rs1) { 1420*bdd1243dSDimitry Andric uint64_t result = 0; 1421*bdd1243dSDimitry Andric if (rs1.isInfinity() && rs1.isNegative()) 1422*bdd1243dSDimitry Andric result |= 1 << 0; 1423*bdd1243dSDimitry Andric // neg normal 1424*bdd1243dSDimitry Andric if (rs1.isNormal() && rs1.isNegative()) 1425*bdd1243dSDimitry Andric result |= 1 << 1; 1426*bdd1243dSDimitry Andric // neg subnormal 1427*bdd1243dSDimitry Andric if (rs1.isDenormal() && rs1.isNegative()) 1428*bdd1243dSDimitry Andric result |= 1 << 2; 1429*bdd1243dSDimitry Andric if (rs1.isNegZero()) 1430*bdd1243dSDimitry Andric result |= 1 << 3; 1431*bdd1243dSDimitry Andric if (rs1.isPosZero()) 1432*bdd1243dSDimitry Andric result |= 1 << 4; 1433*bdd1243dSDimitry Andric // pos normal 1434*bdd1243dSDimitry Andric if (rs1.isNormal() && !rs1.isNegative()) 1435*bdd1243dSDimitry Andric result |= 1 << 5; 1436*bdd1243dSDimitry Andric // pos subnormal 1437*bdd1243dSDimitry Andric if (rs1.isDenormal() && !rs1.isNegative()) 1438*bdd1243dSDimitry Andric result |= 1 << 6; 1439*bdd1243dSDimitry Andric if (rs1.isInfinity() && !rs1.isNegative()) 1440*bdd1243dSDimitry Andric result |= 1 << 7; 1441*bdd1243dSDimitry Andric if (rs1.isNaN()) { 1442*bdd1243dSDimitry Andric if (rs1.isSignaling()) 1443*bdd1243dSDimitry Andric result |= 1 << 8; 1444*bdd1243dSDimitry Andric else 1445*bdd1243dSDimitry Andric result |= 1 << 9; 1446*bdd1243dSDimitry Andric } 1447*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, result); 1448*bdd1243dSDimitry Andric }) 1449*bdd1243dSDimitry Andric .value_or(false); 1450*bdd1243dSDimitry Andric } 1451*bdd1243dSDimitry Andric bool operator()(FCLASS_S inst) { return FCLASS(inst, false); } 1452*bdd1243dSDimitry Andric template <typename T, typename E> 1453*bdd1243dSDimitry Andric bool FCVT_f2i(T inst, std::optional<E> (Rs::*f)(EmulateInstructionRISCV &emu), 1454*bdd1243dSDimitry Andric const fltSemantics &semantics) { 1455*bdd1243dSDimitry Andric return transformOptional(((&inst.rs1)->*f)(m_emu), 1456*bdd1243dSDimitry Andric [&](auto &&rs1) { 1457*bdd1243dSDimitry Andric APFloat apf(semantics, rs1); 1458*bdd1243dSDimitry Andric return inst.rd.WriteAPFloat(m_emu, apf); 1459*bdd1243dSDimitry Andric }) 1460*bdd1243dSDimitry Andric .value_or(false); 1461*bdd1243dSDimitry Andric } 1462*bdd1243dSDimitry Andric bool operator()(FCVT_S_W inst) { 1463*bdd1243dSDimitry Andric return FCVT_f2i(inst, &Rs::ReadI32, APFloat::IEEEsingle()); 1464*bdd1243dSDimitry Andric } 1465*bdd1243dSDimitry Andric bool operator()(FCVT_S_WU inst) { 1466*bdd1243dSDimitry Andric return FCVT_f2i(inst, &Rs::ReadU32, APFloat::IEEEsingle()); 1467*bdd1243dSDimitry Andric } 1468*bdd1243dSDimitry Andric template <typename T, typename E> 1469*bdd1243dSDimitry Andric bool FMV_i2f(T inst, unsigned int numBits, E (APInt::*f)() const) { 1470*bdd1243dSDimitry Andric return transformOptional(inst.rs1.Read(m_emu), 1471*bdd1243dSDimitry Andric [&](auto &&rs1) { 1472*bdd1243dSDimitry Andric APInt apInt(numBits, rs1); 1473*bdd1243dSDimitry Andric if (numBits == 32) // a.k.a. float 1474*bdd1243dSDimitry Andric apInt = APInt(numBits, NanUnBoxing(rs1)); 1475*bdd1243dSDimitry Andric APFloat apf((&apInt->*f)()); 1476*bdd1243dSDimitry Andric return inst.rd.WriteAPFloat(m_emu, apf); 1477*bdd1243dSDimitry Andric }) 1478*bdd1243dSDimitry Andric .value_or(false); 1479*bdd1243dSDimitry Andric } 1480*bdd1243dSDimitry Andric bool operator()(FMV_W_X inst) { 1481*bdd1243dSDimitry Andric return FMV_i2f(inst, 32, &APInt::bitsToFloat); 1482*bdd1243dSDimitry Andric } 1483*bdd1243dSDimitry Andric template <typename I, typename E, typename T> 1484*bdd1243dSDimitry Andric bool FCVT_i2f(I inst, bool isDouble, T (APFloat::*f)() const) { 1485*bdd1243dSDimitry Andric return transformOptional(inst.rs1.ReadAPFloat(m_emu, isDouble), 1486*bdd1243dSDimitry Andric [&](auto &&rs1) { 1487*bdd1243dSDimitry Andric E res = E((&rs1->*f)()); 1488*bdd1243dSDimitry Andric return inst.rd.Write(m_emu, uint64_t(res)); 1489*bdd1243dSDimitry Andric }) 1490*bdd1243dSDimitry Andric .value_or(false); 1491*bdd1243dSDimitry Andric } 1492*bdd1243dSDimitry Andric bool operator()(FCVT_L_S inst) { 1493*bdd1243dSDimitry Andric return FCVT_i2f<FCVT_L_S, int64_t, float>(inst, false, 1494*bdd1243dSDimitry Andric &APFloat::convertToFloat); 1495*bdd1243dSDimitry Andric } 1496*bdd1243dSDimitry Andric bool operator()(FCVT_LU_S inst) { 1497*bdd1243dSDimitry Andric return FCVT_i2f<FCVT_LU_S, uint64_t, float>(inst, false, 1498*bdd1243dSDimitry Andric &APFloat::convertToFloat); 1499*bdd1243dSDimitry Andric } 1500*bdd1243dSDimitry Andric bool operator()(FCVT_S_L inst) { 1501*bdd1243dSDimitry Andric return FCVT_f2i(inst, &Rs::ReadI64, APFloat::IEEEsingle()); 1502*bdd1243dSDimitry Andric } 1503*bdd1243dSDimitry Andric bool operator()(FCVT_S_LU inst) { 1504*bdd1243dSDimitry Andric return FCVT_f2i(inst, &Rs::Read, APFloat::IEEEsingle()); 1505*bdd1243dSDimitry Andric } 1506*bdd1243dSDimitry Andric bool operator()(FLD inst) { return F_Load(inst, &APFloat::IEEEdouble, 64); } 1507*bdd1243dSDimitry Andric bool operator()(FSD inst) { return F_Store(inst, true); } 1508*bdd1243dSDimitry Andric bool operator()(FMADD_D inst) { return FMA(inst, true, 1.0f, 1.0f); } 1509*bdd1243dSDimitry Andric bool operator()(FMSUB_D inst) { return FMA(inst, true, 1.0f, -1.0f); } 1510*bdd1243dSDimitry Andric bool operator()(FNMSUB_D inst) { return FMA(inst, true, -1.0f, 1.0f); } 1511*bdd1243dSDimitry Andric bool operator()(FNMADD_D inst) { return FMA(inst, true, -1.0f, -1.0f); } 1512*bdd1243dSDimitry Andric bool operator()(FADD_D inst) { return F_Op(inst, true, &APFloat::add); } 1513*bdd1243dSDimitry Andric bool operator()(FSUB_D inst) { return F_Op(inst, true, &APFloat::subtract); } 1514*bdd1243dSDimitry Andric bool operator()(FMUL_D inst) { return F_Op(inst, true, &APFloat::multiply); } 1515*bdd1243dSDimitry Andric bool operator()(FDIV_D inst) { return F_Op(inst, true, &APFloat::divide); } 1516*bdd1243dSDimitry Andric bool operator()(FSQRT_D inst) { 1517*bdd1243dSDimitry Andric // TODO: APFloat doesn't have a sqrt function. 1518*bdd1243dSDimitry Andric return false; 1519*bdd1243dSDimitry Andric } 1520*bdd1243dSDimitry Andric bool operator()(FSGNJ_D inst) { return F_SignInj(inst, true, false); } 1521*bdd1243dSDimitry Andric bool operator()(FSGNJN_D inst) { return F_SignInj(inst, true, true); } 1522*bdd1243dSDimitry Andric bool operator()(FSGNJX_D inst) { return F_SignInjXor(inst, true); } 1523*bdd1243dSDimitry Andric bool operator()(FMIN_D inst) { return F_MAX_MIN(inst, true, minnum); } 1524*bdd1243dSDimitry Andric bool operator()(FMAX_D inst) { return F_MAX_MIN(inst, true, maxnum); } 1525*bdd1243dSDimitry Andric bool operator()(FCVT_S_D inst) { 1526*bdd1243dSDimitry Andric return transformOptional(inst.rs1.ReadAPFloat(m_emu, true), 1527*bdd1243dSDimitry Andric [&](auto &&rs1) { 1528*bdd1243dSDimitry Andric double d = rs1.convertToDouble(); 1529*bdd1243dSDimitry Andric APFloat apf((float(d))); 1530*bdd1243dSDimitry Andric return inst.rd.WriteAPFloat(m_emu, apf); 1531*bdd1243dSDimitry Andric }) 1532*bdd1243dSDimitry Andric .value_or(false); 1533*bdd1243dSDimitry Andric } 1534*bdd1243dSDimitry Andric bool operator()(FCVT_D_S inst) { 1535*bdd1243dSDimitry Andric return transformOptional(inst.rs1.ReadAPFloat(m_emu, false), 1536*bdd1243dSDimitry Andric [&](auto &&rs1) { 1537*bdd1243dSDimitry Andric float f = rs1.convertToFloat(); 1538*bdd1243dSDimitry Andric APFloat apf((double(f))); 1539*bdd1243dSDimitry Andric return inst.rd.WriteAPFloat(m_emu, apf); 1540*bdd1243dSDimitry Andric }) 1541*bdd1243dSDimitry Andric .value_or(false); 1542*bdd1243dSDimitry Andric } 1543*bdd1243dSDimitry Andric bool operator()(FEQ_D inst) { return F_Compare(inst, true, FEQ); } 1544*bdd1243dSDimitry Andric bool operator()(FLT_D inst) { return F_Compare(inst, true, FLT); } 1545*bdd1243dSDimitry Andric bool operator()(FLE_D inst) { return F_Compare(inst, true, FLE); } 1546*bdd1243dSDimitry Andric bool operator()(FCLASS_D inst) { return FCLASS(inst, true); } 1547*bdd1243dSDimitry Andric bool operator()(FCVT_W_D inst) { 1548*bdd1243dSDimitry Andric return FCVT_i2f<FCVT_W_D, int32_t, double>(inst, true, 1549*bdd1243dSDimitry Andric &APFloat::convertToDouble); 1550*bdd1243dSDimitry Andric } 1551*bdd1243dSDimitry Andric bool operator()(FCVT_WU_D inst) { 1552*bdd1243dSDimitry Andric return FCVT_i2f<FCVT_WU_D, uint32_t, double>(inst, true, 1553*bdd1243dSDimitry Andric &APFloat::convertToDouble); 1554*bdd1243dSDimitry Andric } 1555*bdd1243dSDimitry Andric bool operator()(FCVT_D_W inst) { 1556*bdd1243dSDimitry Andric return FCVT_f2i(inst, &Rs::ReadI32, APFloat::IEEEdouble()); 1557*bdd1243dSDimitry Andric } 1558*bdd1243dSDimitry Andric bool operator()(FCVT_D_WU inst) { 1559*bdd1243dSDimitry Andric return FCVT_f2i(inst, &Rs::ReadU32, APFloat::IEEEdouble()); 1560*bdd1243dSDimitry Andric } 1561*bdd1243dSDimitry Andric bool operator()(FCVT_L_D inst) { 1562*bdd1243dSDimitry Andric return FCVT_i2f<FCVT_L_D, int64_t, double>(inst, true, 1563*bdd1243dSDimitry Andric &APFloat::convertToDouble); 1564*bdd1243dSDimitry Andric } 1565*bdd1243dSDimitry Andric bool operator()(FCVT_LU_D inst) { 1566*bdd1243dSDimitry Andric return FCVT_i2f<FCVT_LU_D, uint64_t, double>(inst, true, 1567*bdd1243dSDimitry Andric &APFloat::convertToDouble); 1568*bdd1243dSDimitry Andric } 1569*bdd1243dSDimitry Andric bool operator()(FMV_X_D inst) { return FMV_f2i(inst, true); } 1570*bdd1243dSDimitry Andric bool operator()(FCVT_D_L inst) { 1571*bdd1243dSDimitry Andric return FCVT_f2i(inst, &Rs::ReadI64, APFloat::IEEEdouble()); 1572*bdd1243dSDimitry Andric } 1573*bdd1243dSDimitry Andric bool operator()(FCVT_D_LU inst) { 1574*bdd1243dSDimitry Andric return FCVT_f2i(inst, &Rs::Read, APFloat::IEEEdouble()); 1575*bdd1243dSDimitry Andric } 1576*bdd1243dSDimitry Andric bool operator()(FMV_D_X inst) { 1577*bdd1243dSDimitry Andric return FMV_i2f(inst, 64, &APInt::bitsToDouble); 1578*bdd1243dSDimitry Andric } 1579*bdd1243dSDimitry Andric bool operator()(INVALID inst) { return false; } 1580*bdd1243dSDimitry Andric bool operator()(RESERVED inst) { return false; } 1581*bdd1243dSDimitry Andric bool operator()(EBREAK inst) { return false; } 1582*bdd1243dSDimitry Andric bool operator()(HINT inst) { return true; } 1583*bdd1243dSDimitry Andric bool operator()(NOP inst) { return true; } 1584*bdd1243dSDimitry Andric }; 1585*bdd1243dSDimitry Andric 1586*bdd1243dSDimitry Andric bool EmulateInstructionRISCV::Execute(DecodeResult inst, bool ignore_cond) { 1587*bdd1243dSDimitry Andric return std::visit(Executor(*this, ignore_cond, inst.is_rvc), inst.decoded); 1588*bdd1243dSDimitry Andric } 1589*bdd1243dSDimitry Andric 1590*bdd1243dSDimitry Andric bool EmulateInstructionRISCV::EvaluateInstruction(uint32_t options) { 1591*bdd1243dSDimitry Andric bool increase_pc = options & eEmulateInstructionOptionAutoAdvancePC; 1592*bdd1243dSDimitry Andric bool ignore_cond = options & eEmulateInstructionOptionIgnoreConditions; 1593*bdd1243dSDimitry Andric 1594*bdd1243dSDimitry Andric if (!increase_pc) 1595*bdd1243dSDimitry Andric return Execute(m_decoded, ignore_cond); 1596*bdd1243dSDimitry Andric 1597*bdd1243dSDimitry Andric auto old_pc = ReadPC(); 1598*bdd1243dSDimitry Andric if (!old_pc) 1599*bdd1243dSDimitry Andric return false; 1600*bdd1243dSDimitry Andric 1601*bdd1243dSDimitry Andric bool success = Execute(m_decoded, ignore_cond); 1602*bdd1243dSDimitry Andric if (!success) 1603*bdd1243dSDimitry Andric return false; 1604*bdd1243dSDimitry Andric 1605*bdd1243dSDimitry Andric auto new_pc = ReadPC(); 1606*bdd1243dSDimitry Andric if (!new_pc) 1607*bdd1243dSDimitry Andric return false; 1608*bdd1243dSDimitry Andric 1609*bdd1243dSDimitry Andric // If the pc is not updated during execution, we do it here. 1610*bdd1243dSDimitry Andric return new_pc != old_pc || 1611*bdd1243dSDimitry Andric WritePC(*old_pc + Executor::size(m_decoded.is_rvc)); 1612*bdd1243dSDimitry Andric } 1613*bdd1243dSDimitry Andric 1614*bdd1243dSDimitry Andric std::optional<DecodeResult> 1615*bdd1243dSDimitry Andric EmulateInstructionRISCV::ReadInstructionAt(addr_t addr) { 1616*bdd1243dSDimitry Andric return transformOptional(ReadMem<uint32_t>(addr), 1617*bdd1243dSDimitry Andric [&](uint32_t inst) { return Decode(inst); }) 1618*bdd1243dSDimitry Andric .value_or(std::nullopt); 1619*bdd1243dSDimitry Andric } 1620*bdd1243dSDimitry Andric 1621*bdd1243dSDimitry Andric bool EmulateInstructionRISCV::ReadInstruction() { 1622*bdd1243dSDimitry Andric auto addr = ReadPC(); 1623*bdd1243dSDimitry Andric m_addr = addr.value_or(LLDB_INVALID_ADDRESS); 1624*bdd1243dSDimitry Andric if (!addr) 1625*bdd1243dSDimitry Andric return false; 1626*bdd1243dSDimitry Andric auto inst = ReadInstructionAt(*addr); 1627*bdd1243dSDimitry Andric if (!inst) 1628*bdd1243dSDimitry Andric return false; 1629*bdd1243dSDimitry Andric m_decoded = *inst; 1630*bdd1243dSDimitry Andric if (inst->is_rvc) 1631*bdd1243dSDimitry Andric m_opcode.SetOpcode16(inst->inst, GetByteOrder()); 1632*bdd1243dSDimitry Andric else 1633*bdd1243dSDimitry Andric m_opcode.SetOpcode32(inst->inst, GetByteOrder()); 1634*bdd1243dSDimitry Andric return true; 1635*bdd1243dSDimitry Andric } 1636*bdd1243dSDimitry Andric 1637*bdd1243dSDimitry Andric std::optional<addr_t> EmulateInstructionRISCV::ReadPC() { 1638*bdd1243dSDimitry Andric bool success = false; 1639*bdd1243dSDimitry Andric auto addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 1640*bdd1243dSDimitry Andric LLDB_INVALID_ADDRESS, &success); 1641*bdd1243dSDimitry Andric return success ? std::optional<addr_t>(addr) : std::nullopt; 1642*bdd1243dSDimitry Andric } 1643*bdd1243dSDimitry Andric 1644*bdd1243dSDimitry Andric bool EmulateInstructionRISCV::WritePC(addr_t pc) { 1645*bdd1243dSDimitry Andric EmulateInstruction::Context ctx; 1646*bdd1243dSDimitry Andric ctx.type = eContextAdvancePC; 1647*bdd1243dSDimitry Andric ctx.SetNoArgs(); 1648*bdd1243dSDimitry Andric return WriteRegisterUnsigned(ctx, eRegisterKindGeneric, 1649*bdd1243dSDimitry Andric LLDB_REGNUM_GENERIC_PC, pc); 1650*bdd1243dSDimitry Andric } 1651*bdd1243dSDimitry Andric 1652*bdd1243dSDimitry Andric RoundingMode EmulateInstructionRISCV::GetRoundingMode() { 1653*bdd1243dSDimitry Andric bool success = false; 1654*bdd1243dSDimitry Andric auto fcsr = ReadRegisterUnsigned(eRegisterKindLLDB, fpr_fcsr_riscv, 1655*bdd1243dSDimitry Andric LLDB_INVALID_ADDRESS, &success); 1656*bdd1243dSDimitry Andric if (!success) 1657*bdd1243dSDimitry Andric return RoundingMode::Invalid; 1658*bdd1243dSDimitry Andric auto frm = (fcsr >> 5) & 0x7; 1659*bdd1243dSDimitry Andric switch (frm) { 1660*bdd1243dSDimitry Andric case 0b000: 1661*bdd1243dSDimitry Andric return RoundingMode::NearestTiesToEven; 1662*bdd1243dSDimitry Andric case 0b001: 1663*bdd1243dSDimitry Andric return RoundingMode::TowardZero; 1664*bdd1243dSDimitry Andric case 0b010: 1665*bdd1243dSDimitry Andric return RoundingMode::TowardNegative; 1666*bdd1243dSDimitry Andric case 0b011: 1667*bdd1243dSDimitry Andric return RoundingMode::TowardPositive; 1668*bdd1243dSDimitry Andric case 0b111: 1669*bdd1243dSDimitry Andric return RoundingMode::Dynamic; 1670*bdd1243dSDimitry Andric default: 1671*bdd1243dSDimitry Andric // Reserved for future use. 1672*bdd1243dSDimitry Andric return RoundingMode::Invalid; 1673*bdd1243dSDimitry Andric } 1674*bdd1243dSDimitry Andric } 1675*bdd1243dSDimitry Andric 1676*bdd1243dSDimitry Andric bool EmulateInstructionRISCV::SetAccruedExceptions( 1677*bdd1243dSDimitry Andric APFloatBase::opStatus opStatus) { 1678*bdd1243dSDimitry Andric bool success = false; 1679*bdd1243dSDimitry Andric auto fcsr = ReadRegisterUnsigned(eRegisterKindLLDB, fpr_fcsr_riscv, 1680*bdd1243dSDimitry Andric LLDB_INVALID_ADDRESS, &success); 1681*bdd1243dSDimitry Andric if (!success) 1682*bdd1243dSDimitry Andric return false; 1683*bdd1243dSDimitry Andric switch (opStatus) { 1684*bdd1243dSDimitry Andric case APFloatBase::opInvalidOp: 1685*bdd1243dSDimitry Andric fcsr |= 1 << 4; 1686*bdd1243dSDimitry Andric break; 1687*bdd1243dSDimitry Andric case APFloatBase::opDivByZero: 1688*bdd1243dSDimitry Andric fcsr |= 1 << 3; 1689*bdd1243dSDimitry Andric break; 1690*bdd1243dSDimitry Andric case APFloatBase::opOverflow: 1691*bdd1243dSDimitry Andric fcsr |= 1 << 2; 1692*bdd1243dSDimitry Andric break; 1693*bdd1243dSDimitry Andric case APFloatBase::opUnderflow: 1694*bdd1243dSDimitry Andric fcsr |= 1 << 1; 1695*bdd1243dSDimitry Andric break; 1696*bdd1243dSDimitry Andric case APFloatBase::opInexact: 1697*bdd1243dSDimitry Andric fcsr |= 1 << 0; 1698*bdd1243dSDimitry Andric break; 1699*bdd1243dSDimitry Andric case APFloatBase::opOK: 1700*bdd1243dSDimitry Andric break; 1701*bdd1243dSDimitry Andric } 1702*bdd1243dSDimitry Andric EmulateInstruction::Context ctx; 1703*bdd1243dSDimitry Andric ctx.type = eContextRegisterStore; 1704*bdd1243dSDimitry Andric ctx.SetNoArgs(); 1705*bdd1243dSDimitry Andric return WriteRegisterUnsigned(ctx, eRegisterKindLLDB, fpr_fcsr_riscv, fcsr); 1706*bdd1243dSDimitry Andric } 1707*bdd1243dSDimitry Andric 1708*bdd1243dSDimitry Andric std::optional<RegisterInfo> 1709*bdd1243dSDimitry Andric EmulateInstructionRISCV::GetRegisterInfo(RegisterKind reg_kind, 1710*bdd1243dSDimitry Andric uint32_t reg_index) { 1711*bdd1243dSDimitry Andric if (reg_kind == eRegisterKindGeneric) { 1712*bdd1243dSDimitry Andric switch (reg_index) { 1713*bdd1243dSDimitry Andric case LLDB_REGNUM_GENERIC_PC: 1714*bdd1243dSDimitry Andric reg_kind = eRegisterKindLLDB; 1715*bdd1243dSDimitry Andric reg_index = gpr_pc_riscv; 1716*bdd1243dSDimitry Andric break; 1717*bdd1243dSDimitry Andric case LLDB_REGNUM_GENERIC_SP: 1718*bdd1243dSDimitry Andric reg_kind = eRegisterKindLLDB; 1719*bdd1243dSDimitry Andric reg_index = gpr_sp_riscv; 1720*bdd1243dSDimitry Andric break; 1721*bdd1243dSDimitry Andric case LLDB_REGNUM_GENERIC_FP: 1722*bdd1243dSDimitry Andric reg_kind = eRegisterKindLLDB; 1723*bdd1243dSDimitry Andric reg_index = gpr_fp_riscv; 1724*bdd1243dSDimitry Andric break; 1725*bdd1243dSDimitry Andric case LLDB_REGNUM_GENERIC_RA: 1726*bdd1243dSDimitry Andric reg_kind = eRegisterKindLLDB; 1727*bdd1243dSDimitry Andric reg_index = gpr_ra_riscv; 1728*bdd1243dSDimitry Andric break; 1729*bdd1243dSDimitry Andric // We may handle LLDB_REGNUM_GENERIC_ARGx when more instructions are 1730*bdd1243dSDimitry Andric // supported. 1731*bdd1243dSDimitry Andric default: 1732*bdd1243dSDimitry Andric llvm_unreachable("unsupported register"); 1733*bdd1243dSDimitry Andric } 1734*bdd1243dSDimitry Andric } 1735*bdd1243dSDimitry Andric 1736*bdd1243dSDimitry Andric const RegisterInfo *array = 1737*bdd1243dSDimitry Andric RegisterInfoPOSIX_riscv64::GetRegisterInfoPtr(m_arch); 1738*bdd1243dSDimitry Andric const uint32_t length = 1739*bdd1243dSDimitry Andric RegisterInfoPOSIX_riscv64::GetRegisterInfoCount(m_arch); 1740*bdd1243dSDimitry Andric 1741*bdd1243dSDimitry Andric if (reg_index >= length || reg_kind != eRegisterKindLLDB) 1742*bdd1243dSDimitry Andric return {}; 1743*bdd1243dSDimitry Andric 1744*bdd1243dSDimitry Andric return array[reg_index]; 1745*bdd1243dSDimitry Andric } 1746*bdd1243dSDimitry Andric 1747*bdd1243dSDimitry Andric bool EmulateInstructionRISCV::SetTargetTriple(const ArchSpec &arch) { 1748*bdd1243dSDimitry Andric return SupportsThisArch(arch); 1749*bdd1243dSDimitry Andric } 1750*bdd1243dSDimitry Andric 1751*bdd1243dSDimitry Andric bool EmulateInstructionRISCV::TestEmulation(Stream *out_stream, ArchSpec &arch, 1752*bdd1243dSDimitry Andric OptionValueDictionary *test_data) { 1753*bdd1243dSDimitry Andric return false; 1754*bdd1243dSDimitry Andric } 1755*bdd1243dSDimitry Andric 1756*bdd1243dSDimitry Andric void EmulateInstructionRISCV::Initialize() { 1757*bdd1243dSDimitry Andric PluginManager::RegisterPlugin(GetPluginNameStatic(), 1758*bdd1243dSDimitry Andric GetPluginDescriptionStatic(), CreateInstance); 1759*bdd1243dSDimitry Andric } 1760*bdd1243dSDimitry Andric 1761*bdd1243dSDimitry Andric void EmulateInstructionRISCV::Terminate() { 1762*bdd1243dSDimitry Andric PluginManager::UnregisterPlugin(CreateInstance); 1763*bdd1243dSDimitry Andric } 1764*bdd1243dSDimitry Andric 1765*bdd1243dSDimitry Andric lldb_private::EmulateInstruction * 1766*bdd1243dSDimitry Andric EmulateInstructionRISCV::CreateInstance(const ArchSpec &arch, 1767*bdd1243dSDimitry Andric InstructionType inst_type) { 1768*bdd1243dSDimitry Andric if (EmulateInstructionRISCV::SupportsThisInstructionType(inst_type) && 1769*bdd1243dSDimitry Andric SupportsThisArch(arch)) { 1770*bdd1243dSDimitry Andric return new EmulateInstructionRISCV(arch); 1771*bdd1243dSDimitry Andric } 1772*bdd1243dSDimitry Andric 1773*bdd1243dSDimitry Andric return nullptr; 1774*bdd1243dSDimitry Andric } 1775*bdd1243dSDimitry Andric 1776*bdd1243dSDimitry Andric bool EmulateInstructionRISCV::SupportsThisArch(const ArchSpec &arch) { 1777*bdd1243dSDimitry Andric return arch.GetTriple().isRISCV(); 1778*bdd1243dSDimitry Andric } 1779*bdd1243dSDimitry Andric 1780*bdd1243dSDimitry Andric } // namespace lldb_private 1781