1*bdd1243dSDimitry Andric //===---EmulateInstructionLoongArch.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 <cstdlib> 10*bdd1243dSDimitry Andric #include <optional> 11*bdd1243dSDimitry Andric 12*bdd1243dSDimitry Andric #include "EmulateInstructionLoongArch.h" 13*bdd1243dSDimitry Andric #include "Plugins/Process/Utility/InstructionUtils.h" 14*bdd1243dSDimitry Andric #include "Plugins/Process/Utility/RegisterInfoPOSIX_loongarch64.h" 15*bdd1243dSDimitry Andric #include "Plugins/Process/Utility/lldb-loongarch-register-enums.h" 16*bdd1243dSDimitry Andric #include "lldb/Core/Address.h" 17*bdd1243dSDimitry Andric #include "lldb/Core/PluginManager.h" 18*bdd1243dSDimitry Andric #include "lldb/Interpreter/OptionValueArray.h" 19*bdd1243dSDimitry Andric #include "lldb/Interpreter/OptionValueDictionary.h" 20*bdd1243dSDimitry Andric #include "lldb/Symbol/UnwindPlan.h" 21*bdd1243dSDimitry Andric #include "lldb/Utility/ArchSpec.h" 22*bdd1243dSDimitry Andric #include "lldb/Utility/LLDBLog.h" 23*bdd1243dSDimitry Andric #include "lldb/Utility/RegisterValue.h" 24*bdd1243dSDimitry Andric #include "lldb/Utility/Stream.h" 25*bdd1243dSDimitry Andric #include "llvm/ADT/STLExtras.h" 26*bdd1243dSDimitry Andric #include "llvm/Support/MathExtras.h" 27*bdd1243dSDimitry Andric 28*bdd1243dSDimitry Andric using namespace lldb; 29*bdd1243dSDimitry Andric using namespace lldb_private; 30*bdd1243dSDimitry Andric 31*bdd1243dSDimitry Andric LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionLoongArch, InstructionLoongArch) 32*bdd1243dSDimitry Andric 33*bdd1243dSDimitry Andric namespace lldb_private { 34*bdd1243dSDimitry Andric 35*bdd1243dSDimitry Andric EmulateInstructionLoongArch::Opcode * 36*bdd1243dSDimitry Andric EmulateInstructionLoongArch::GetOpcodeForInstruction(uint32_t inst) { 37*bdd1243dSDimitry Andric // TODO: Add the mask for other instruction. 38*bdd1243dSDimitry Andric static EmulateInstructionLoongArch::Opcode g_opcodes[] = { 39*bdd1243dSDimitry Andric {0xfc000000, 0x40000000, &EmulateInstructionLoongArch::EmulateBEQZ, 40*bdd1243dSDimitry Andric "beqz rj, offs21"}, 41*bdd1243dSDimitry Andric {0xfc000000, 0x44000000, &EmulateInstructionLoongArch::EmulateBNEZ, 42*bdd1243dSDimitry Andric "bnez rj, offs21"}, 43*bdd1243dSDimitry Andric {0xfc000300, 0x48000000, &EmulateInstructionLoongArch::EmulateBCEQZ, 44*bdd1243dSDimitry Andric "bceqz cj, offs21"}, 45*bdd1243dSDimitry Andric {0xfc000300, 0x48000100, &EmulateInstructionLoongArch::EmulateBCNEZ, 46*bdd1243dSDimitry Andric "bcnez cj, offs21"}, 47*bdd1243dSDimitry Andric {0xfc000000, 0x4c000000, &EmulateInstructionLoongArch::EmulateJIRL, 48*bdd1243dSDimitry Andric "jirl rd, rj, offs16"}, 49*bdd1243dSDimitry Andric {0xfc000000, 0x50000000, &EmulateInstructionLoongArch::EmulateB, 50*bdd1243dSDimitry Andric " b offs26"}, 51*bdd1243dSDimitry Andric {0xfc000000, 0x54000000, &EmulateInstructionLoongArch::EmulateBL, 52*bdd1243dSDimitry Andric "bl offs26"}, 53*bdd1243dSDimitry Andric {0xfc000000, 0x58000000, &EmulateInstructionLoongArch::EmulateBEQ, 54*bdd1243dSDimitry Andric "beq rj, rd, offs16"}, 55*bdd1243dSDimitry Andric {0xfc000000, 0x5c000000, &EmulateInstructionLoongArch::EmulateBNE, 56*bdd1243dSDimitry Andric "bne rj, rd, offs16"}, 57*bdd1243dSDimitry Andric {0xfc000000, 0x60000000, &EmulateInstructionLoongArch::EmulateBLT, 58*bdd1243dSDimitry Andric "blt rj, rd, offs16"}, 59*bdd1243dSDimitry Andric {0xfc000000, 0x64000000, &EmulateInstructionLoongArch::EmulateBGE, 60*bdd1243dSDimitry Andric "bge rj, rd, offs16"}, 61*bdd1243dSDimitry Andric {0xfc000000, 0x68000000, &EmulateInstructionLoongArch::EmulateBLTU, 62*bdd1243dSDimitry Andric "bltu rj, rd, offs16"}, 63*bdd1243dSDimitry Andric {0xfc000000, 0x6c000000, &EmulateInstructionLoongArch::EmulateBGEU, 64*bdd1243dSDimitry Andric "bgeu rj, rd, offs16"}, 65*bdd1243dSDimitry Andric {0x00000000, 0x00000000, &EmulateInstructionLoongArch::EmulateNonJMP, 66*bdd1243dSDimitry Andric "NonJMP"}}; 67*bdd1243dSDimitry Andric static const size_t num_loongarch_opcodes = std::size(g_opcodes); 68*bdd1243dSDimitry Andric 69*bdd1243dSDimitry Andric for (size_t i = 0; i < num_loongarch_opcodes; ++i) 70*bdd1243dSDimitry Andric if ((g_opcodes[i].mask & inst) == g_opcodes[i].value) 71*bdd1243dSDimitry Andric return &g_opcodes[i]; 72*bdd1243dSDimitry Andric return nullptr; 73*bdd1243dSDimitry Andric } 74*bdd1243dSDimitry Andric 75*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::TestExecute(uint32_t inst) { 76*bdd1243dSDimitry Andric Opcode *opcode_data = GetOpcodeForInstruction(inst); 77*bdd1243dSDimitry Andric if (!opcode_data) 78*bdd1243dSDimitry Andric return false; 79*bdd1243dSDimitry Andric // Call the Emulate... function. 80*bdd1243dSDimitry Andric if (!(this->*opcode_data->callback)(inst)) 81*bdd1243dSDimitry Andric return false; 82*bdd1243dSDimitry Andric return true; 83*bdd1243dSDimitry Andric } 84*bdd1243dSDimitry Andric 85*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EvaluateInstruction(uint32_t options) { 86*bdd1243dSDimitry Andric uint32_t inst_size = m_opcode.GetByteSize(); 87*bdd1243dSDimitry Andric uint32_t inst = m_opcode.GetOpcode32(); 88*bdd1243dSDimitry Andric bool increase_pc = options & eEmulateInstructionOptionAutoAdvancePC; 89*bdd1243dSDimitry Andric bool success = false; 90*bdd1243dSDimitry Andric 91*bdd1243dSDimitry Andric Opcode *opcode_data = GetOpcodeForInstruction(inst); 92*bdd1243dSDimitry Andric if (!opcode_data) 93*bdd1243dSDimitry Andric return false; 94*bdd1243dSDimitry Andric 95*bdd1243dSDimitry Andric lldb::addr_t old_pc = 0; 96*bdd1243dSDimitry Andric if (increase_pc) { 97*bdd1243dSDimitry Andric old_pc = ReadPC(&success); 98*bdd1243dSDimitry Andric if (!success) 99*bdd1243dSDimitry Andric return false; 100*bdd1243dSDimitry Andric } 101*bdd1243dSDimitry Andric 102*bdd1243dSDimitry Andric // Call the Emulate... function. 103*bdd1243dSDimitry Andric if (!(this->*opcode_data->callback)(inst)) 104*bdd1243dSDimitry Andric return false; 105*bdd1243dSDimitry Andric 106*bdd1243dSDimitry Andric if (increase_pc) { 107*bdd1243dSDimitry Andric lldb::addr_t new_pc = ReadPC(&success); 108*bdd1243dSDimitry Andric if (!success) 109*bdd1243dSDimitry Andric return false; 110*bdd1243dSDimitry Andric 111*bdd1243dSDimitry Andric if (new_pc == old_pc && !WritePC(old_pc + inst_size)) 112*bdd1243dSDimitry Andric return false; 113*bdd1243dSDimitry Andric } 114*bdd1243dSDimitry Andric return true; 115*bdd1243dSDimitry Andric } 116*bdd1243dSDimitry Andric 117*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::ReadInstruction() { 118*bdd1243dSDimitry Andric bool success = false; 119*bdd1243dSDimitry Andric m_addr = ReadPC(&success); 120*bdd1243dSDimitry Andric if (!success) { 121*bdd1243dSDimitry Andric m_addr = LLDB_INVALID_ADDRESS; 122*bdd1243dSDimitry Andric return false; 123*bdd1243dSDimitry Andric } 124*bdd1243dSDimitry Andric 125*bdd1243dSDimitry Andric Context ctx; 126*bdd1243dSDimitry Andric ctx.type = eContextReadOpcode; 127*bdd1243dSDimitry Andric ctx.SetNoArgs(); 128*bdd1243dSDimitry Andric uint32_t inst = (uint32_t)ReadMemoryUnsigned(ctx, m_addr, 4, 0, &success); 129*bdd1243dSDimitry Andric m_opcode.SetOpcode32(inst, GetByteOrder()); 130*bdd1243dSDimitry Andric 131*bdd1243dSDimitry Andric return true; 132*bdd1243dSDimitry Andric } 133*bdd1243dSDimitry Andric 134*bdd1243dSDimitry Andric lldb::addr_t EmulateInstructionLoongArch::ReadPC(bool *success) { 135*bdd1243dSDimitry Andric return ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 136*bdd1243dSDimitry Andric LLDB_INVALID_ADDRESS, success); 137*bdd1243dSDimitry Andric } 138*bdd1243dSDimitry Andric 139*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::WritePC(lldb::addr_t pc) { 140*bdd1243dSDimitry Andric EmulateInstruction::Context ctx; 141*bdd1243dSDimitry Andric ctx.type = eContextAdvancePC; 142*bdd1243dSDimitry Andric ctx.SetNoArgs(); 143*bdd1243dSDimitry Andric return WriteRegisterUnsigned(ctx, eRegisterKindGeneric, 144*bdd1243dSDimitry Andric LLDB_REGNUM_GENERIC_PC, pc); 145*bdd1243dSDimitry Andric } 146*bdd1243dSDimitry Andric 147*bdd1243dSDimitry Andric std::optional<RegisterInfo> 148*bdd1243dSDimitry Andric EmulateInstructionLoongArch::GetRegisterInfo(lldb::RegisterKind reg_kind, 149*bdd1243dSDimitry Andric uint32_t reg_index) { 150*bdd1243dSDimitry Andric if (reg_kind == eRegisterKindGeneric) { 151*bdd1243dSDimitry Andric switch (reg_index) { 152*bdd1243dSDimitry Andric case LLDB_REGNUM_GENERIC_PC: 153*bdd1243dSDimitry Andric reg_kind = eRegisterKindLLDB; 154*bdd1243dSDimitry Andric reg_index = gpr_pc_loongarch; 155*bdd1243dSDimitry Andric break; 156*bdd1243dSDimitry Andric case LLDB_REGNUM_GENERIC_SP: 157*bdd1243dSDimitry Andric reg_kind = eRegisterKindLLDB; 158*bdd1243dSDimitry Andric reg_index = gpr_sp_loongarch; 159*bdd1243dSDimitry Andric break; 160*bdd1243dSDimitry Andric case LLDB_REGNUM_GENERIC_FP: 161*bdd1243dSDimitry Andric reg_kind = eRegisterKindLLDB; 162*bdd1243dSDimitry Andric reg_index = gpr_fp_loongarch; 163*bdd1243dSDimitry Andric break; 164*bdd1243dSDimitry Andric case LLDB_REGNUM_GENERIC_RA: 165*bdd1243dSDimitry Andric reg_kind = eRegisterKindLLDB; 166*bdd1243dSDimitry Andric reg_index = gpr_ra_loongarch; 167*bdd1243dSDimitry Andric break; 168*bdd1243dSDimitry Andric // We may handle LLDB_REGNUM_GENERIC_ARGx when more instructions are 169*bdd1243dSDimitry Andric // supported. 170*bdd1243dSDimitry Andric default: 171*bdd1243dSDimitry Andric llvm_unreachable("unsupported register"); 172*bdd1243dSDimitry Andric } 173*bdd1243dSDimitry Andric } 174*bdd1243dSDimitry Andric 175*bdd1243dSDimitry Andric const RegisterInfo *array = 176*bdd1243dSDimitry Andric RegisterInfoPOSIX_loongarch64::GetRegisterInfoPtr(m_arch); 177*bdd1243dSDimitry Andric const uint32_t length = 178*bdd1243dSDimitry Andric RegisterInfoPOSIX_loongarch64::GetRegisterInfoCount(m_arch); 179*bdd1243dSDimitry Andric 180*bdd1243dSDimitry Andric if (reg_index >= length || reg_kind != eRegisterKindLLDB) 181*bdd1243dSDimitry Andric return {}; 182*bdd1243dSDimitry Andric return array[reg_index]; 183*bdd1243dSDimitry Andric } 184*bdd1243dSDimitry Andric 185*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::SetTargetTriple(const ArchSpec &arch) { 186*bdd1243dSDimitry Andric return SupportsThisArch(arch); 187*bdd1243dSDimitry Andric } 188*bdd1243dSDimitry Andric 189*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::TestEmulation( 190*bdd1243dSDimitry Andric Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) { 191*bdd1243dSDimitry Andric return false; 192*bdd1243dSDimitry Andric } 193*bdd1243dSDimitry Andric 194*bdd1243dSDimitry Andric void EmulateInstructionLoongArch::Initialize() { 195*bdd1243dSDimitry Andric PluginManager::RegisterPlugin(GetPluginNameStatic(), 196*bdd1243dSDimitry Andric GetPluginDescriptionStatic(), CreateInstance); 197*bdd1243dSDimitry Andric } 198*bdd1243dSDimitry Andric 199*bdd1243dSDimitry Andric void EmulateInstructionLoongArch::Terminate() { 200*bdd1243dSDimitry Andric PluginManager::UnregisterPlugin(CreateInstance); 201*bdd1243dSDimitry Andric } 202*bdd1243dSDimitry Andric 203*bdd1243dSDimitry Andric lldb_private::EmulateInstruction * 204*bdd1243dSDimitry Andric EmulateInstructionLoongArch::CreateInstance(const ArchSpec &arch, 205*bdd1243dSDimitry Andric InstructionType inst_type) { 206*bdd1243dSDimitry Andric if (EmulateInstructionLoongArch::SupportsThisInstructionType(inst_type) && 207*bdd1243dSDimitry Andric SupportsThisArch(arch)) 208*bdd1243dSDimitry Andric return new EmulateInstructionLoongArch(arch); 209*bdd1243dSDimitry Andric return nullptr; 210*bdd1243dSDimitry Andric } 211*bdd1243dSDimitry Andric 212*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::SupportsThisArch(const ArchSpec &arch) { 213*bdd1243dSDimitry Andric return arch.GetTriple().isLoongArch(); 214*bdd1243dSDimitry Andric } 215*bdd1243dSDimitry Andric 216*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateBEQZ(uint32_t inst) { 217*bdd1243dSDimitry Andric return IsLoongArch64() ? EmulateBEQZ64(inst) : false; 218*bdd1243dSDimitry Andric } 219*bdd1243dSDimitry Andric 220*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateBNEZ(uint32_t inst) { 221*bdd1243dSDimitry Andric return IsLoongArch64() ? EmulateBNEZ64(inst) : false; 222*bdd1243dSDimitry Andric } 223*bdd1243dSDimitry Andric 224*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateBCEQZ(uint32_t inst) { 225*bdd1243dSDimitry Andric return IsLoongArch64() ? EmulateBCEQZ64(inst) : false; 226*bdd1243dSDimitry Andric } 227*bdd1243dSDimitry Andric 228*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateBCNEZ(uint32_t inst) { 229*bdd1243dSDimitry Andric return IsLoongArch64() ? EmulateBCNEZ64(inst) : false; 230*bdd1243dSDimitry Andric } 231*bdd1243dSDimitry Andric 232*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateJIRL(uint32_t inst) { 233*bdd1243dSDimitry Andric return IsLoongArch64() ? EmulateJIRL64(inst) : false; 234*bdd1243dSDimitry Andric } 235*bdd1243dSDimitry Andric 236*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateB(uint32_t inst) { 237*bdd1243dSDimitry Andric return IsLoongArch64() ? EmulateB64(inst) : false; 238*bdd1243dSDimitry Andric } 239*bdd1243dSDimitry Andric 240*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateBL(uint32_t inst) { 241*bdd1243dSDimitry Andric return IsLoongArch64() ? EmulateBL64(inst) : false; 242*bdd1243dSDimitry Andric } 243*bdd1243dSDimitry Andric 244*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateBEQ(uint32_t inst) { 245*bdd1243dSDimitry Andric return IsLoongArch64() ? EmulateBEQ64(inst) : false; 246*bdd1243dSDimitry Andric } 247*bdd1243dSDimitry Andric 248*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateBNE(uint32_t inst) { 249*bdd1243dSDimitry Andric return IsLoongArch64() ? EmulateBNE64(inst) : false; 250*bdd1243dSDimitry Andric } 251*bdd1243dSDimitry Andric 252*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateBLT(uint32_t inst) { 253*bdd1243dSDimitry Andric return IsLoongArch64() ? EmulateBLT64(inst) : false; 254*bdd1243dSDimitry Andric } 255*bdd1243dSDimitry Andric 256*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateBGE(uint32_t inst) { 257*bdd1243dSDimitry Andric return IsLoongArch64() ? EmulateBGE64(inst) : false; 258*bdd1243dSDimitry Andric } 259*bdd1243dSDimitry Andric 260*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateBLTU(uint32_t inst) { 261*bdd1243dSDimitry Andric return IsLoongArch64() ? EmulateBLTU64(inst) : false; 262*bdd1243dSDimitry Andric } 263*bdd1243dSDimitry Andric 264*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateBGEU(uint32_t inst) { 265*bdd1243dSDimitry Andric return IsLoongArch64() ? EmulateBGEU64(inst) : false; 266*bdd1243dSDimitry Andric } 267*bdd1243dSDimitry Andric 268*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateNonJMP(uint32_t inst) { return false; } 269*bdd1243dSDimitry Andric 270*bdd1243dSDimitry Andric // beqz rj, offs21 271*bdd1243dSDimitry Andric // if GR[rj] == 0: 272*bdd1243dSDimitry Andric // PC = PC + SignExtend({offs21, 2'b0}, GRLEN) 273*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateBEQZ64(uint32_t inst) { 274*bdd1243dSDimitry Andric bool success = false; 275*bdd1243dSDimitry Andric uint32_t rj = Bits32(inst, 9, 5); 276*bdd1243dSDimitry Andric uint64_t pc = ReadPC(&success); 277*bdd1243dSDimitry Andric if (!success) 278*bdd1243dSDimitry Andric return false; 279*bdd1243dSDimitry Andric uint32_t offs21 = Bits32(inst, 25, 10) + (Bits32(inst, 4, 0) << 16); 280*bdd1243dSDimitry Andric uint64_t rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); 281*bdd1243dSDimitry Andric if (!success) 282*bdd1243dSDimitry Andric return false; 283*bdd1243dSDimitry Andric if (rj_val == 0) { 284*bdd1243dSDimitry Andric uint64_t next_pc = pc + llvm::SignExtend64<23>(offs21 << 2); 285*bdd1243dSDimitry Andric return WritePC(next_pc); 286*bdd1243dSDimitry Andric } else 287*bdd1243dSDimitry Andric return WritePC(pc + 4); 288*bdd1243dSDimitry Andric } 289*bdd1243dSDimitry Andric 290*bdd1243dSDimitry Andric // bnez rj, offs21 291*bdd1243dSDimitry Andric // if GR[rj] != 0: 292*bdd1243dSDimitry Andric // PC = PC + SignExtend({offs21, 2'b0}, GRLEN) 293*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateBNEZ64(uint32_t inst) { 294*bdd1243dSDimitry Andric bool success = false; 295*bdd1243dSDimitry Andric uint32_t rj = Bits32(inst, 9, 5); 296*bdd1243dSDimitry Andric uint64_t pc = ReadPC(&success); 297*bdd1243dSDimitry Andric if (!success) 298*bdd1243dSDimitry Andric return false; 299*bdd1243dSDimitry Andric uint32_t offs21 = Bits32(inst, 25, 10) + (Bits32(inst, 4, 0) << 16); 300*bdd1243dSDimitry Andric uint64_t rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); 301*bdd1243dSDimitry Andric if (!success) 302*bdd1243dSDimitry Andric return false; 303*bdd1243dSDimitry Andric if (rj_val != 0) { 304*bdd1243dSDimitry Andric uint64_t next_pc = pc + llvm::SignExtend64<23>(offs21 << 2); 305*bdd1243dSDimitry Andric return WritePC(next_pc); 306*bdd1243dSDimitry Andric } else 307*bdd1243dSDimitry Andric return WritePC(pc + 4); 308*bdd1243dSDimitry Andric } 309*bdd1243dSDimitry Andric 310*bdd1243dSDimitry Andric // bceqz cj, offs21 311*bdd1243dSDimitry Andric // if CFR[cj] == 0: 312*bdd1243dSDimitry Andric // PC = PC + SignExtend({offs21, 2'b0}, GRLEN) 313*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateBCEQZ64(uint32_t inst) { 314*bdd1243dSDimitry Andric bool success = false; 315*bdd1243dSDimitry Andric uint32_t cj = Bits32(inst, 7, 5) + fpr_fcc0_loongarch; 316*bdd1243dSDimitry Andric uint64_t pc = ReadPC(&success); 317*bdd1243dSDimitry Andric if (!success) 318*bdd1243dSDimitry Andric return false; 319*bdd1243dSDimitry Andric uint32_t offs21 = Bits32(inst, 25, 10) + (Bits32(inst, 4, 0) << 16); 320*bdd1243dSDimitry Andric uint8_t cj_val = 321*bdd1243dSDimitry Andric (uint8_t)ReadRegisterUnsigned(eRegisterKindLLDB, cj, 0, &success); 322*bdd1243dSDimitry Andric if (!success) 323*bdd1243dSDimitry Andric return false; 324*bdd1243dSDimitry Andric if (cj_val == 0) { 325*bdd1243dSDimitry Andric uint64_t next_pc = pc + llvm::SignExtend64<23>(offs21 << 2); 326*bdd1243dSDimitry Andric return WritePC(next_pc); 327*bdd1243dSDimitry Andric } else 328*bdd1243dSDimitry Andric return WritePC(pc + 4); 329*bdd1243dSDimitry Andric return false; 330*bdd1243dSDimitry Andric } 331*bdd1243dSDimitry Andric 332*bdd1243dSDimitry Andric // bcnez cj, offs21 333*bdd1243dSDimitry Andric // if CFR[cj] != 0: 334*bdd1243dSDimitry Andric // PC = PC + SignExtend({offs21, 2'b0}, GRLEN) 335*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateBCNEZ64(uint32_t inst) { 336*bdd1243dSDimitry Andric bool success = false; 337*bdd1243dSDimitry Andric uint32_t cj = Bits32(inst, 7, 5) + fpr_fcc0_loongarch; 338*bdd1243dSDimitry Andric uint64_t pc = ReadPC(&success); 339*bdd1243dSDimitry Andric if (!success) 340*bdd1243dSDimitry Andric return false; 341*bdd1243dSDimitry Andric uint32_t offs21 = Bits32(inst, 25, 10) + (Bits32(inst, 4, 0) << 16); 342*bdd1243dSDimitry Andric uint8_t cj_val = 343*bdd1243dSDimitry Andric (uint8_t)ReadRegisterUnsigned(eRegisterKindLLDB, cj, 0, &success); 344*bdd1243dSDimitry Andric if (!success) 345*bdd1243dSDimitry Andric return false; 346*bdd1243dSDimitry Andric if (cj_val != 0) { 347*bdd1243dSDimitry Andric uint64_t next_pc = pc + llvm::SignExtend64<23>(offs21 << 2); 348*bdd1243dSDimitry Andric return WritePC(next_pc); 349*bdd1243dSDimitry Andric } else 350*bdd1243dSDimitry Andric return WritePC(pc + 4); 351*bdd1243dSDimitry Andric return false; 352*bdd1243dSDimitry Andric } 353*bdd1243dSDimitry Andric 354*bdd1243dSDimitry Andric // jirl rd, rj, offs16 355*bdd1243dSDimitry Andric // GR[rd] = PC + 4 356*bdd1243dSDimitry Andric // PC = GR[rj] + SignExtend({offs16, 2'b0}, GRLEN) 357*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateJIRL64(uint32_t inst) { 358*bdd1243dSDimitry Andric uint32_t rj = Bits32(inst, 9, 5); 359*bdd1243dSDimitry Andric uint32_t rd = Bits32(inst, 4, 0); 360*bdd1243dSDimitry Andric bool success = false; 361*bdd1243dSDimitry Andric uint64_t pc = ReadPC(&success); 362*bdd1243dSDimitry Andric if (!success) 363*bdd1243dSDimitry Andric return false; 364*bdd1243dSDimitry Andric EmulateInstruction::Context ctx; 365*bdd1243dSDimitry Andric if (!WriteRegisterUnsigned(ctx, eRegisterKindLLDB, rd, pc + 4)) 366*bdd1243dSDimitry Andric return false; 367*bdd1243dSDimitry Andric uint64_t rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); 368*bdd1243dSDimitry Andric if (!success) 369*bdd1243dSDimitry Andric return false; 370*bdd1243dSDimitry Andric uint64_t next_pc = rj_val + llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); 371*bdd1243dSDimitry Andric return WritePC(next_pc); 372*bdd1243dSDimitry Andric } 373*bdd1243dSDimitry Andric 374*bdd1243dSDimitry Andric // b offs26 375*bdd1243dSDimitry Andric // PC = PC + SignExtend({offs26, 2' b0}, GRLEN) 376*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateB64(uint32_t inst) { 377*bdd1243dSDimitry Andric bool success = false; 378*bdd1243dSDimitry Andric uint64_t pc = ReadPC(&success); 379*bdd1243dSDimitry Andric if (!success) 380*bdd1243dSDimitry Andric return false; 381*bdd1243dSDimitry Andric uint32_t offs26 = Bits32(inst, 25, 10) + (Bits32(inst, 9, 0) << 16); 382*bdd1243dSDimitry Andric uint64_t next_pc = pc + llvm::SignExtend64<28>(offs26 << 2); 383*bdd1243dSDimitry Andric return WritePC(next_pc); 384*bdd1243dSDimitry Andric } 385*bdd1243dSDimitry Andric 386*bdd1243dSDimitry Andric // bl offs26 387*bdd1243dSDimitry Andric // GR[1] = PC + 4 388*bdd1243dSDimitry Andric // PC = PC + SignExtend({offs26, 2'b0}, GRLEN) 389*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateBL64(uint32_t inst) { 390*bdd1243dSDimitry Andric bool success = false; 391*bdd1243dSDimitry Andric uint64_t pc = ReadPC(&success); 392*bdd1243dSDimitry Andric if (!success) 393*bdd1243dSDimitry Andric return false; 394*bdd1243dSDimitry Andric EmulateInstruction::Context ctx; 395*bdd1243dSDimitry Andric if (!WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_r1_loongarch, pc + 4)) 396*bdd1243dSDimitry Andric return false; 397*bdd1243dSDimitry Andric uint32_t offs26 = Bits32(inst, 25, 10) + (Bits32(inst, 9, 0) << 16); 398*bdd1243dSDimitry Andric uint64_t next_pc = pc + llvm::SignExtend64<28>(offs26 << 2); 399*bdd1243dSDimitry Andric return WritePC(next_pc); 400*bdd1243dSDimitry Andric } 401*bdd1243dSDimitry Andric 402*bdd1243dSDimitry Andric // beq rj, rd, offs16 403*bdd1243dSDimitry Andric // if GR[rj] == GR[rd]: 404*bdd1243dSDimitry Andric // PC = PC + SignExtend({offs16, 2'b0}, GRLEN) 405*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateBEQ64(uint32_t inst) { 406*bdd1243dSDimitry Andric bool success = false; 407*bdd1243dSDimitry Andric uint32_t rj = Bits32(inst, 9, 5); 408*bdd1243dSDimitry Andric uint32_t rd = Bits32(inst, 4, 0); 409*bdd1243dSDimitry Andric uint64_t pc = ReadPC(&success); 410*bdd1243dSDimitry Andric if (!success) 411*bdd1243dSDimitry Andric return false; 412*bdd1243dSDimitry Andric uint64_t rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); 413*bdd1243dSDimitry Andric if (!success) 414*bdd1243dSDimitry Andric return false; 415*bdd1243dSDimitry Andric uint64_t rd_val = ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); 416*bdd1243dSDimitry Andric if (!success) 417*bdd1243dSDimitry Andric return false; 418*bdd1243dSDimitry Andric if (rj_val == rd_val) { 419*bdd1243dSDimitry Andric uint64_t next_pc = pc + llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); 420*bdd1243dSDimitry Andric return WritePC(next_pc); 421*bdd1243dSDimitry Andric } else 422*bdd1243dSDimitry Andric return WritePC(pc + 4); 423*bdd1243dSDimitry Andric } 424*bdd1243dSDimitry Andric 425*bdd1243dSDimitry Andric // bne rj, rd, offs16 426*bdd1243dSDimitry Andric // if GR[rj] != GR[rd]: 427*bdd1243dSDimitry Andric // PC = PC + SignExtend({offs16, 2'b0}, GRLEN) 428*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateBNE64(uint32_t inst) { 429*bdd1243dSDimitry Andric bool success = false; 430*bdd1243dSDimitry Andric uint32_t rj = Bits32(inst, 9, 5); 431*bdd1243dSDimitry Andric uint32_t rd = Bits32(inst, 4, 0); 432*bdd1243dSDimitry Andric uint64_t pc = ReadPC(&success); 433*bdd1243dSDimitry Andric if (!success) 434*bdd1243dSDimitry Andric return false; 435*bdd1243dSDimitry Andric uint64_t rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); 436*bdd1243dSDimitry Andric if (!success) 437*bdd1243dSDimitry Andric return false; 438*bdd1243dSDimitry Andric uint64_t rd_val = ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); 439*bdd1243dSDimitry Andric if (!success) 440*bdd1243dSDimitry Andric return false; 441*bdd1243dSDimitry Andric if (rj_val != rd_val) { 442*bdd1243dSDimitry Andric uint64_t next_pc = pc + llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); 443*bdd1243dSDimitry Andric return WritePC(next_pc); 444*bdd1243dSDimitry Andric } else 445*bdd1243dSDimitry Andric return WritePC(pc + 4); 446*bdd1243dSDimitry Andric } 447*bdd1243dSDimitry Andric 448*bdd1243dSDimitry Andric // blt rj, rd, offs16 449*bdd1243dSDimitry Andric // if signed(GR[rj]) < signed(GR[rd]): 450*bdd1243dSDimitry Andric // PC = PC + SignExtend({offs16, 2'b0}, GRLEN) 451*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateBLT64(uint32_t inst) { 452*bdd1243dSDimitry Andric bool success = false; 453*bdd1243dSDimitry Andric uint32_t rj = Bits32(inst, 9, 5); 454*bdd1243dSDimitry Andric uint32_t rd = Bits32(inst, 4, 0); 455*bdd1243dSDimitry Andric uint64_t pc = ReadPC(&success); 456*bdd1243dSDimitry Andric if (!success) 457*bdd1243dSDimitry Andric return false; 458*bdd1243dSDimitry Andric int64_t rj_val = 459*bdd1243dSDimitry Andric (int64_t)ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); 460*bdd1243dSDimitry Andric if (!success) 461*bdd1243dSDimitry Andric return false; 462*bdd1243dSDimitry Andric int64_t rd_val = 463*bdd1243dSDimitry Andric (int64_t)ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); 464*bdd1243dSDimitry Andric if (!success) 465*bdd1243dSDimitry Andric return false; 466*bdd1243dSDimitry Andric if (rj_val < rd_val) { 467*bdd1243dSDimitry Andric uint64_t next_pc = pc + llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); 468*bdd1243dSDimitry Andric return WritePC(next_pc); 469*bdd1243dSDimitry Andric } else 470*bdd1243dSDimitry Andric return WritePC(pc + 4); 471*bdd1243dSDimitry Andric } 472*bdd1243dSDimitry Andric 473*bdd1243dSDimitry Andric // bge rj, rd, offs16 474*bdd1243dSDimitry Andric // if signed(GR[rj]) >= signed(GR[rd]): 475*bdd1243dSDimitry Andric // PC = PC + SignExtend({offs16, 2'b0}, GRLEN) 476*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateBGE64(uint32_t inst) { 477*bdd1243dSDimitry Andric bool success = false; 478*bdd1243dSDimitry Andric uint32_t rj = Bits32(inst, 9, 5); 479*bdd1243dSDimitry Andric uint32_t rd = Bits32(inst, 4, 0); 480*bdd1243dSDimitry Andric uint64_t pc = ReadPC(&success); 481*bdd1243dSDimitry Andric if (!success) 482*bdd1243dSDimitry Andric return false; 483*bdd1243dSDimitry Andric int64_t rj_val = 484*bdd1243dSDimitry Andric (int64_t)ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); 485*bdd1243dSDimitry Andric if (!success) 486*bdd1243dSDimitry Andric return false; 487*bdd1243dSDimitry Andric int64_t rd_val = 488*bdd1243dSDimitry Andric (int64_t)ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); 489*bdd1243dSDimitry Andric if (!success) 490*bdd1243dSDimitry Andric return false; 491*bdd1243dSDimitry Andric if (rj_val >= rd_val) { 492*bdd1243dSDimitry Andric uint64_t next_pc = pc + llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); 493*bdd1243dSDimitry Andric return WritePC(next_pc); 494*bdd1243dSDimitry Andric } else 495*bdd1243dSDimitry Andric return WritePC(pc + 4); 496*bdd1243dSDimitry Andric } 497*bdd1243dSDimitry Andric 498*bdd1243dSDimitry Andric // bltu rj, rd, offs16 499*bdd1243dSDimitry Andric // if unsigned(GR[rj]) < unsigned(GR[rd]): 500*bdd1243dSDimitry Andric // PC = PC + SignExtend({offs16, 2'b0}, GRLEN) 501*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateBLTU64(uint32_t inst) { 502*bdd1243dSDimitry Andric bool success = false; 503*bdd1243dSDimitry Andric uint32_t rj = Bits32(inst, 9, 5); 504*bdd1243dSDimitry Andric uint32_t rd = Bits32(inst, 4, 0); 505*bdd1243dSDimitry Andric uint64_t pc = ReadPC(&success); 506*bdd1243dSDimitry Andric if (!success) 507*bdd1243dSDimitry Andric return false; 508*bdd1243dSDimitry Andric uint64_t rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); 509*bdd1243dSDimitry Andric if (!success) 510*bdd1243dSDimitry Andric return false; 511*bdd1243dSDimitry Andric uint64_t rd_val = ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); 512*bdd1243dSDimitry Andric if (!success) 513*bdd1243dSDimitry Andric return false; 514*bdd1243dSDimitry Andric if (rj_val < rd_val) { 515*bdd1243dSDimitry Andric uint64_t next_pc = pc + llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); 516*bdd1243dSDimitry Andric return WritePC(next_pc); 517*bdd1243dSDimitry Andric } else 518*bdd1243dSDimitry Andric return WritePC(pc + 4); 519*bdd1243dSDimitry Andric } 520*bdd1243dSDimitry Andric 521*bdd1243dSDimitry Andric // bgeu rj, rd, offs16 522*bdd1243dSDimitry Andric // if unsigned(GR[rj]) >= unsigned(GR[rd]): 523*bdd1243dSDimitry Andric // PC = PC + SignExtend({offs16, 2'b0}, GRLEN) 524*bdd1243dSDimitry Andric bool EmulateInstructionLoongArch::EmulateBGEU64(uint32_t inst) { 525*bdd1243dSDimitry Andric bool success = false; 526*bdd1243dSDimitry Andric uint32_t rj = Bits32(inst, 9, 5); 527*bdd1243dSDimitry Andric uint32_t rd = Bits32(inst, 4, 0); 528*bdd1243dSDimitry Andric uint64_t pc = ReadPC(&success); 529*bdd1243dSDimitry Andric if (!success) 530*bdd1243dSDimitry Andric return false; 531*bdd1243dSDimitry Andric uint64_t rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); 532*bdd1243dSDimitry Andric if (!success) 533*bdd1243dSDimitry Andric return false; 534*bdd1243dSDimitry Andric uint64_t rd_val = ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); 535*bdd1243dSDimitry Andric if (!success) 536*bdd1243dSDimitry Andric return false; 537*bdd1243dSDimitry Andric if (rj_val >= rd_val) { 538*bdd1243dSDimitry Andric uint64_t next_pc = pc + llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); 539*bdd1243dSDimitry Andric return WritePC(next_pc); 540*bdd1243dSDimitry Andric } else 541*bdd1243dSDimitry Andric return WritePC(pc + 4); 542*bdd1243dSDimitry Andric } 543*bdd1243dSDimitry Andric 544*bdd1243dSDimitry Andric } // namespace lldb_private 545