15ffd83dbSDimitry Andric //===-- EmulateInstructionMIPS64.cpp --------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "EmulateInstructionMIPS64.h"
100b57cec5SDimitry Andric
11fe6060f1SDimitry Andric #include <cstdlib>
12bdd1243dSDimitry Andric #include <optional>
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "lldb/Core/Address.h"
150b57cec5SDimitry Andric #include "lldb/Core/Opcode.h"
160b57cec5SDimitry Andric #include "lldb/Core/PluginManager.h"
170b57cec5SDimitry Andric #include "lldb/Host/PosixApi.h"
180b57cec5SDimitry Andric #include "lldb/Symbol/UnwindPlan.h"
190b57cec5SDimitry Andric #include "lldb/Utility/ArchSpec.h"
200b57cec5SDimitry Andric #include "lldb/Utility/ConstString.h"
210b57cec5SDimitry Andric #include "lldb/Utility/DataExtractor.h"
220b57cec5SDimitry Andric #include "lldb/Utility/RegisterValue.h"
230b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
240b57cec5SDimitry Andric #include "llvm-c/Disassembler.h"
250b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
270b57cec5SDimitry Andric #include "llvm/MC/MCDisassembler/MCDisassembler.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
290b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
300b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
310b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
32480093f4SDimitry Andric #include "llvm/MC/MCTargetOptions.h"
33349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
340b57cec5SDimitry Andric #include "llvm/Support/TargetSelect.h"
350b57cec5SDimitry Andric
360b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
370b57cec5SDimitry Andric
380b57cec5SDimitry Andric #include "Plugins/Process/Utility/InstructionUtils.h"
390b57cec5SDimitry Andric #include "Plugins/Process/Utility/RegisterContext_mips.h"
400b57cec5SDimitry Andric
410b57cec5SDimitry Andric using namespace lldb;
420b57cec5SDimitry Andric using namespace lldb_private;
430b57cec5SDimitry Andric
LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionMIPS64,InstructionMIPS64)445ffd83dbSDimitry Andric LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionMIPS64, InstructionMIPS64)
455ffd83dbSDimitry Andric
460b57cec5SDimitry Andric #define UInt(x) ((uint64_t)x)
470b57cec5SDimitry Andric #define integer int64_t
480b57cec5SDimitry Andric
490b57cec5SDimitry Andric //
500b57cec5SDimitry Andric // EmulateInstructionMIPS64 implementation
510b57cec5SDimitry Andric //
520b57cec5SDimitry Andric
530b57cec5SDimitry Andric #ifdef __mips__
540b57cec5SDimitry Andric extern "C" {
550b57cec5SDimitry Andric void LLVMInitializeMipsTargetInfo();
560b57cec5SDimitry Andric void LLVMInitializeMipsTarget();
570b57cec5SDimitry Andric void LLVMInitializeMipsAsmPrinter();
580b57cec5SDimitry Andric void LLVMInitializeMipsTargetMC();
590b57cec5SDimitry Andric void LLVMInitializeMipsDisassembler();
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric #endif
620b57cec5SDimitry Andric
EmulateInstructionMIPS64(const lldb_private::ArchSpec & arch)630b57cec5SDimitry Andric EmulateInstructionMIPS64::EmulateInstructionMIPS64(
640b57cec5SDimitry Andric const lldb_private::ArchSpec &arch)
650b57cec5SDimitry Andric : EmulateInstruction(arch) {
660b57cec5SDimitry Andric /* Create instance of llvm::MCDisassembler */
670b57cec5SDimitry Andric std::string Status;
680b57cec5SDimitry Andric llvm::Triple triple = arch.GetTriple();
690b57cec5SDimitry Andric const llvm::Target *target =
700b57cec5SDimitry Andric llvm::TargetRegistry::lookupTarget(triple.getTriple(), Status);
710b57cec5SDimitry Andric
720b57cec5SDimitry Andric /*
730b57cec5SDimitry Andric * If we fail to get the target then we haven't registered it. The
740b57cec5SDimitry Andric * SystemInitializerCommon
750b57cec5SDimitry Andric * does not initialize targets, MCs and disassemblers. However we need the
760b57cec5SDimitry Andric * MCDisassembler
770b57cec5SDimitry Andric * to decode the instructions so that the decoding complexity stays with LLVM.
780b57cec5SDimitry Andric * Initialize the MIPS targets and disassemblers.
790b57cec5SDimitry Andric */
800b57cec5SDimitry Andric #ifdef __mips__
810b57cec5SDimitry Andric if (!target) {
820b57cec5SDimitry Andric LLVMInitializeMipsTargetInfo();
830b57cec5SDimitry Andric LLVMInitializeMipsTarget();
840b57cec5SDimitry Andric LLVMInitializeMipsAsmPrinter();
850b57cec5SDimitry Andric LLVMInitializeMipsTargetMC();
860b57cec5SDimitry Andric LLVMInitializeMipsDisassembler();
870b57cec5SDimitry Andric target = llvm::TargetRegistry::lookupTarget(triple.getTriple(), Status);
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric #endif
900b57cec5SDimitry Andric
910b57cec5SDimitry Andric assert(target);
920b57cec5SDimitry Andric
930b57cec5SDimitry Andric llvm::StringRef cpu;
940b57cec5SDimitry Andric
950b57cec5SDimitry Andric switch (arch.GetCore()) {
960b57cec5SDimitry Andric case ArchSpec::eCore_mips32:
970b57cec5SDimitry Andric case ArchSpec::eCore_mips32el:
980b57cec5SDimitry Andric cpu = "mips32";
990b57cec5SDimitry Andric break;
1000b57cec5SDimitry Andric case ArchSpec::eCore_mips32r2:
1010b57cec5SDimitry Andric case ArchSpec::eCore_mips32r2el:
1020b57cec5SDimitry Andric cpu = "mips32r2";
1030b57cec5SDimitry Andric break;
1040b57cec5SDimitry Andric case ArchSpec::eCore_mips32r3:
1050b57cec5SDimitry Andric case ArchSpec::eCore_mips32r3el:
1060b57cec5SDimitry Andric cpu = "mips32r3";
1070b57cec5SDimitry Andric break;
1080b57cec5SDimitry Andric case ArchSpec::eCore_mips32r5:
1090b57cec5SDimitry Andric case ArchSpec::eCore_mips32r5el:
1100b57cec5SDimitry Andric cpu = "mips32r5";
1110b57cec5SDimitry Andric break;
1120b57cec5SDimitry Andric case ArchSpec::eCore_mips32r6:
1130b57cec5SDimitry Andric case ArchSpec::eCore_mips32r6el:
1140b57cec5SDimitry Andric cpu = "mips32r6";
1150b57cec5SDimitry Andric break;
1160b57cec5SDimitry Andric case ArchSpec::eCore_mips64:
1170b57cec5SDimitry Andric case ArchSpec::eCore_mips64el:
1180b57cec5SDimitry Andric cpu = "mips64";
1190b57cec5SDimitry Andric break;
1200b57cec5SDimitry Andric case ArchSpec::eCore_mips64r2:
1210b57cec5SDimitry Andric case ArchSpec::eCore_mips64r2el:
1220b57cec5SDimitry Andric cpu = "mips64r2";
1230b57cec5SDimitry Andric break;
1240b57cec5SDimitry Andric case ArchSpec::eCore_mips64r3:
1250b57cec5SDimitry Andric case ArchSpec::eCore_mips64r3el:
1260b57cec5SDimitry Andric cpu = "mips64r3";
1270b57cec5SDimitry Andric break;
1280b57cec5SDimitry Andric case ArchSpec::eCore_mips64r5:
1290b57cec5SDimitry Andric case ArchSpec::eCore_mips64r5el:
1300b57cec5SDimitry Andric cpu = "mips64r5";
1310b57cec5SDimitry Andric break;
1320b57cec5SDimitry Andric case ArchSpec::eCore_mips64r6:
1330b57cec5SDimitry Andric case ArchSpec::eCore_mips64r6el:
1340b57cec5SDimitry Andric cpu = "mips64r6";
1350b57cec5SDimitry Andric break;
1360b57cec5SDimitry Andric default:
1370b57cec5SDimitry Andric cpu = "generic";
1380b57cec5SDimitry Andric break;
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric
14104eeddc0SDimitry Andric std::string features;
1420b57cec5SDimitry Andric uint32_t arch_flags = arch.GetFlags();
1430b57cec5SDimitry Andric if (arch_flags & ArchSpec::eMIPSAse_msa)
1440b57cec5SDimitry Andric features += "+msa,";
1450b57cec5SDimitry Andric if (arch_flags & ArchSpec::eMIPSAse_dsp)
1460b57cec5SDimitry Andric features += "+dsp,";
1470b57cec5SDimitry Andric if (arch_flags & ArchSpec::eMIPSAse_dspr2)
1480b57cec5SDimitry Andric features += "+dspr2,";
1490b57cec5SDimitry Andric if (arch_flags & ArchSpec::eMIPSAse_mips16)
1500b57cec5SDimitry Andric features += "+mips16,";
1510b57cec5SDimitry Andric if (arch_flags & ArchSpec::eMIPSAse_micromips)
1520b57cec5SDimitry Andric features += "+micromips,";
1530b57cec5SDimitry Andric
1540b57cec5SDimitry Andric m_reg_info.reset(target->createMCRegInfo(triple.getTriple()));
1550b57cec5SDimitry Andric assert(m_reg_info.get());
1560b57cec5SDimitry Andric
1570b57cec5SDimitry Andric m_insn_info.reset(target->createMCInstrInfo());
1580b57cec5SDimitry Andric assert(m_insn_info.get());
1590b57cec5SDimitry Andric
160480093f4SDimitry Andric llvm::MCTargetOptions MCOptions;
161480093f4SDimitry Andric m_asm_info.reset(
162480093f4SDimitry Andric target->createMCAsmInfo(*m_reg_info, triple.getTriple(), MCOptions));
1630b57cec5SDimitry Andric m_subtype_info.reset(
1640b57cec5SDimitry Andric target->createMCSubtargetInfo(triple.getTriple(), cpu, features));
1650b57cec5SDimitry Andric assert(m_asm_info.get() && m_subtype_info.get());
1660b57cec5SDimitry Andric
167fe6060f1SDimitry Andric m_context = std::make_unique<llvm::MCContext>(
168fe6060f1SDimitry Andric triple, m_asm_info.get(), m_reg_info.get(), m_subtype_info.get());
1690b57cec5SDimitry Andric assert(m_context.get());
1700b57cec5SDimitry Andric
1710b57cec5SDimitry Andric m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context));
1720b57cec5SDimitry Andric assert(m_disasm.get());
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric
Initialize()1750b57cec5SDimitry Andric void EmulateInstructionMIPS64::Initialize() {
1760b57cec5SDimitry Andric PluginManager::RegisterPlugin(GetPluginNameStatic(),
1770b57cec5SDimitry Andric GetPluginDescriptionStatic(), CreateInstance);
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric
Terminate()1800b57cec5SDimitry Andric void EmulateInstructionMIPS64::Terminate() {
1810b57cec5SDimitry Andric PluginManager::UnregisterPlugin(CreateInstance);
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric
GetPluginDescriptionStatic()184349cc55cSDimitry Andric llvm::StringRef EmulateInstructionMIPS64::GetPluginDescriptionStatic() {
1850b57cec5SDimitry Andric return "Emulate instructions for the MIPS64 architecture.";
1860b57cec5SDimitry Andric }
1870b57cec5SDimitry Andric
1880b57cec5SDimitry Andric EmulateInstruction *
CreateInstance(const ArchSpec & arch,InstructionType inst_type)1890b57cec5SDimitry Andric EmulateInstructionMIPS64::CreateInstance(const ArchSpec &arch,
1900b57cec5SDimitry Andric InstructionType inst_type) {
1910b57cec5SDimitry Andric if (EmulateInstructionMIPS64::SupportsEmulatingInstructionsOfTypeStatic(
1920b57cec5SDimitry Andric inst_type)) {
1930b57cec5SDimitry Andric if (arch.GetTriple().getArch() == llvm::Triple::mips64 ||
1940b57cec5SDimitry Andric arch.GetTriple().getArch() == llvm::Triple::mips64el) {
1950b57cec5SDimitry Andric return new EmulateInstructionMIPS64(arch);
1960b57cec5SDimitry Andric }
1970b57cec5SDimitry Andric }
1980b57cec5SDimitry Andric
1990b57cec5SDimitry Andric return nullptr;
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric
SetTargetTriple(const ArchSpec & arch)2020b57cec5SDimitry Andric bool EmulateInstructionMIPS64::SetTargetTriple(const ArchSpec &arch) {
2030b57cec5SDimitry Andric return arch.GetTriple().getArch() == llvm::Triple::mips64 ||
2040b57cec5SDimitry Andric arch.GetTriple().getArch() == llvm::Triple::mips64el;
2050b57cec5SDimitry Andric }
2060b57cec5SDimitry Andric
GetRegisterName(unsigned reg_num,bool alternate_name)2070b57cec5SDimitry Andric const char *EmulateInstructionMIPS64::GetRegisterName(unsigned reg_num,
2080b57cec5SDimitry Andric bool alternate_name) {
2090b57cec5SDimitry Andric if (alternate_name) {
2100b57cec5SDimitry Andric switch (reg_num) {
2110b57cec5SDimitry Andric case dwarf_sp_mips64:
2120b57cec5SDimitry Andric return "r29";
2130b57cec5SDimitry Andric case dwarf_r30_mips64:
2140b57cec5SDimitry Andric return "r30";
2150b57cec5SDimitry Andric case dwarf_ra_mips64:
2160b57cec5SDimitry Andric return "r31";
2170b57cec5SDimitry Andric case dwarf_f0_mips64:
2180b57cec5SDimitry Andric return "f0";
2190b57cec5SDimitry Andric case dwarf_f1_mips64:
2200b57cec5SDimitry Andric return "f1";
2210b57cec5SDimitry Andric case dwarf_f2_mips64:
2220b57cec5SDimitry Andric return "f2";
2230b57cec5SDimitry Andric case dwarf_f3_mips64:
2240b57cec5SDimitry Andric return "f3";
2250b57cec5SDimitry Andric case dwarf_f4_mips64:
2260b57cec5SDimitry Andric return "f4";
2270b57cec5SDimitry Andric case dwarf_f5_mips64:
2280b57cec5SDimitry Andric return "f5";
2290b57cec5SDimitry Andric case dwarf_f6_mips64:
2300b57cec5SDimitry Andric return "f6";
2310b57cec5SDimitry Andric case dwarf_f7_mips64:
2320b57cec5SDimitry Andric return "f7";
2330b57cec5SDimitry Andric case dwarf_f8_mips64:
2340b57cec5SDimitry Andric return "f8";
2350b57cec5SDimitry Andric case dwarf_f9_mips64:
2360b57cec5SDimitry Andric return "f9";
2370b57cec5SDimitry Andric case dwarf_f10_mips64:
2380b57cec5SDimitry Andric return "f10";
2390b57cec5SDimitry Andric case dwarf_f11_mips64:
2400b57cec5SDimitry Andric return "f11";
2410b57cec5SDimitry Andric case dwarf_f12_mips64:
2420b57cec5SDimitry Andric return "f12";
2430b57cec5SDimitry Andric case dwarf_f13_mips64:
2440b57cec5SDimitry Andric return "f13";
2450b57cec5SDimitry Andric case dwarf_f14_mips64:
2460b57cec5SDimitry Andric return "f14";
2470b57cec5SDimitry Andric case dwarf_f15_mips64:
2480b57cec5SDimitry Andric return "f15";
2490b57cec5SDimitry Andric case dwarf_f16_mips64:
2500b57cec5SDimitry Andric return "f16";
2510b57cec5SDimitry Andric case dwarf_f17_mips64:
2520b57cec5SDimitry Andric return "f17";
2530b57cec5SDimitry Andric case dwarf_f18_mips64:
2540b57cec5SDimitry Andric return "f18";
2550b57cec5SDimitry Andric case dwarf_f19_mips64:
2560b57cec5SDimitry Andric return "f19";
2570b57cec5SDimitry Andric case dwarf_f20_mips64:
2580b57cec5SDimitry Andric return "f20";
2590b57cec5SDimitry Andric case dwarf_f21_mips64:
2600b57cec5SDimitry Andric return "f21";
2610b57cec5SDimitry Andric case dwarf_f22_mips64:
2620b57cec5SDimitry Andric return "f22";
2630b57cec5SDimitry Andric case dwarf_f23_mips64:
2640b57cec5SDimitry Andric return "f23";
2650b57cec5SDimitry Andric case dwarf_f24_mips64:
2660b57cec5SDimitry Andric return "f24";
2670b57cec5SDimitry Andric case dwarf_f25_mips64:
2680b57cec5SDimitry Andric return "f25";
2690b57cec5SDimitry Andric case dwarf_f26_mips64:
2700b57cec5SDimitry Andric return "f26";
2710b57cec5SDimitry Andric case dwarf_f27_mips64:
2720b57cec5SDimitry Andric return "f27";
2730b57cec5SDimitry Andric case dwarf_f28_mips64:
2740b57cec5SDimitry Andric return "f28";
2750b57cec5SDimitry Andric case dwarf_f29_mips64:
2760b57cec5SDimitry Andric return "f29";
2770b57cec5SDimitry Andric case dwarf_f30_mips64:
2780b57cec5SDimitry Andric return "f30";
2790b57cec5SDimitry Andric case dwarf_f31_mips64:
2800b57cec5SDimitry Andric return "f31";
2810b57cec5SDimitry Andric case dwarf_w0_mips64:
2820b57cec5SDimitry Andric return "w0";
2830b57cec5SDimitry Andric case dwarf_w1_mips64:
2840b57cec5SDimitry Andric return "w1";
2850b57cec5SDimitry Andric case dwarf_w2_mips64:
2860b57cec5SDimitry Andric return "w2";
2870b57cec5SDimitry Andric case dwarf_w3_mips64:
2880b57cec5SDimitry Andric return "w3";
2890b57cec5SDimitry Andric case dwarf_w4_mips64:
2900b57cec5SDimitry Andric return "w4";
2910b57cec5SDimitry Andric case dwarf_w5_mips64:
2920b57cec5SDimitry Andric return "w5";
2930b57cec5SDimitry Andric case dwarf_w6_mips64:
2940b57cec5SDimitry Andric return "w6";
2950b57cec5SDimitry Andric case dwarf_w7_mips64:
2960b57cec5SDimitry Andric return "w7";
2970b57cec5SDimitry Andric case dwarf_w8_mips64:
2980b57cec5SDimitry Andric return "w8";
2990b57cec5SDimitry Andric case dwarf_w9_mips64:
3000b57cec5SDimitry Andric return "w9";
3010b57cec5SDimitry Andric case dwarf_w10_mips64:
3020b57cec5SDimitry Andric return "w10";
3030b57cec5SDimitry Andric case dwarf_w11_mips64:
3040b57cec5SDimitry Andric return "w11";
3050b57cec5SDimitry Andric case dwarf_w12_mips64:
3060b57cec5SDimitry Andric return "w12";
3070b57cec5SDimitry Andric case dwarf_w13_mips64:
3080b57cec5SDimitry Andric return "w13";
3090b57cec5SDimitry Andric case dwarf_w14_mips64:
3100b57cec5SDimitry Andric return "w14";
3110b57cec5SDimitry Andric case dwarf_w15_mips64:
3120b57cec5SDimitry Andric return "w15";
3130b57cec5SDimitry Andric case dwarf_w16_mips64:
3140b57cec5SDimitry Andric return "w16";
3150b57cec5SDimitry Andric case dwarf_w17_mips64:
3160b57cec5SDimitry Andric return "w17";
3170b57cec5SDimitry Andric case dwarf_w18_mips64:
3180b57cec5SDimitry Andric return "w18";
3190b57cec5SDimitry Andric case dwarf_w19_mips64:
3200b57cec5SDimitry Andric return "w19";
3210b57cec5SDimitry Andric case dwarf_w20_mips64:
3220b57cec5SDimitry Andric return "w20";
3230b57cec5SDimitry Andric case dwarf_w21_mips64:
3240b57cec5SDimitry Andric return "w21";
3250b57cec5SDimitry Andric case dwarf_w22_mips64:
3260b57cec5SDimitry Andric return "w22";
3270b57cec5SDimitry Andric case dwarf_w23_mips64:
3280b57cec5SDimitry Andric return "w23";
3290b57cec5SDimitry Andric case dwarf_w24_mips64:
3300b57cec5SDimitry Andric return "w24";
3310b57cec5SDimitry Andric case dwarf_w25_mips64:
3320b57cec5SDimitry Andric return "w25";
3330b57cec5SDimitry Andric case dwarf_w26_mips64:
3340b57cec5SDimitry Andric return "w26";
3350b57cec5SDimitry Andric case dwarf_w27_mips64:
3360b57cec5SDimitry Andric return "w27";
3370b57cec5SDimitry Andric case dwarf_w28_mips64:
3380b57cec5SDimitry Andric return "w28";
3390b57cec5SDimitry Andric case dwarf_w29_mips64:
3400b57cec5SDimitry Andric return "w29";
3410b57cec5SDimitry Andric case dwarf_w30_mips64:
3420b57cec5SDimitry Andric return "w30";
3430b57cec5SDimitry Andric case dwarf_w31_mips64:
3440b57cec5SDimitry Andric return "w31";
3450b57cec5SDimitry Andric case dwarf_mir_mips64:
3460b57cec5SDimitry Andric return "mir";
3470b57cec5SDimitry Andric case dwarf_mcsr_mips64:
3480b57cec5SDimitry Andric return "mcsr";
3490b57cec5SDimitry Andric case dwarf_config5_mips64:
3500b57cec5SDimitry Andric return "config5";
3510b57cec5SDimitry Andric default:
3520b57cec5SDimitry Andric break;
3530b57cec5SDimitry Andric }
3540b57cec5SDimitry Andric return nullptr;
3550b57cec5SDimitry Andric }
3560b57cec5SDimitry Andric
3570b57cec5SDimitry Andric switch (reg_num) {
3580b57cec5SDimitry Andric case dwarf_zero_mips64:
3590b57cec5SDimitry Andric return "r0";
3600b57cec5SDimitry Andric case dwarf_r1_mips64:
3610b57cec5SDimitry Andric return "r1";
3620b57cec5SDimitry Andric case dwarf_r2_mips64:
3630b57cec5SDimitry Andric return "r2";
3640b57cec5SDimitry Andric case dwarf_r3_mips64:
3650b57cec5SDimitry Andric return "r3";
3660b57cec5SDimitry Andric case dwarf_r4_mips64:
3670b57cec5SDimitry Andric return "r4";
3680b57cec5SDimitry Andric case dwarf_r5_mips64:
3690b57cec5SDimitry Andric return "r5";
3700b57cec5SDimitry Andric case dwarf_r6_mips64:
3710b57cec5SDimitry Andric return "r6";
3720b57cec5SDimitry Andric case dwarf_r7_mips64:
3730b57cec5SDimitry Andric return "r7";
3740b57cec5SDimitry Andric case dwarf_r8_mips64:
3750b57cec5SDimitry Andric return "r8";
3760b57cec5SDimitry Andric case dwarf_r9_mips64:
3770b57cec5SDimitry Andric return "r9";
3780b57cec5SDimitry Andric case dwarf_r10_mips64:
3790b57cec5SDimitry Andric return "r10";
3800b57cec5SDimitry Andric case dwarf_r11_mips64:
3810b57cec5SDimitry Andric return "r11";
3820b57cec5SDimitry Andric case dwarf_r12_mips64:
3830b57cec5SDimitry Andric return "r12";
3840b57cec5SDimitry Andric case dwarf_r13_mips64:
3850b57cec5SDimitry Andric return "r13";
3860b57cec5SDimitry Andric case dwarf_r14_mips64:
3870b57cec5SDimitry Andric return "r14";
3880b57cec5SDimitry Andric case dwarf_r15_mips64:
3890b57cec5SDimitry Andric return "r15";
3900b57cec5SDimitry Andric case dwarf_r16_mips64:
3910b57cec5SDimitry Andric return "r16";
3920b57cec5SDimitry Andric case dwarf_r17_mips64:
3930b57cec5SDimitry Andric return "r17";
3940b57cec5SDimitry Andric case dwarf_r18_mips64:
3950b57cec5SDimitry Andric return "r18";
3960b57cec5SDimitry Andric case dwarf_r19_mips64:
3970b57cec5SDimitry Andric return "r19";
3980b57cec5SDimitry Andric case dwarf_r20_mips64:
3990b57cec5SDimitry Andric return "r20";
4000b57cec5SDimitry Andric case dwarf_r21_mips64:
4010b57cec5SDimitry Andric return "r21";
4020b57cec5SDimitry Andric case dwarf_r22_mips64:
4030b57cec5SDimitry Andric return "r22";
4040b57cec5SDimitry Andric case dwarf_r23_mips64:
4050b57cec5SDimitry Andric return "r23";
4060b57cec5SDimitry Andric case dwarf_r24_mips64:
4070b57cec5SDimitry Andric return "r24";
4080b57cec5SDimitry Andric case dwarf_r25_mips64:
4090b57cec5SDimitry Andric return "r25";
4100b57cec5SDimitry Andric case dwarf_r26_mips64:
4110b57cec5SDimitry Andric return "r26";
4120b57cec5SDimitry Andric case dwarf_r27_mips64:
4130b57cec5SDimitry Andric return "r27";
4140b57cec5SDimitry Andric case dwarf_gp_mips64:
4150b57cec5SDimitry Andric return "gp";
4160b57cec5SDimitry Andric case dwarf_sp_mips64:
4170b57cec5SDimitry Andric return "sp";
4180b57cec5SDimitry Andric case dwarf_r30_mips64:
4190b57cec5SDimitry Andric return "fp";
4200b57cec5SDimitry Andric case dwarf_ra_mips64:
4210b57cec5SDimitry Andric return "ra";
4220b57cec5SDimitry Andric case dwarf_sr_mips64:
4230b57cec5SDimitry Andric return "sr";
4240b57cec5SDimitry Andric case dwarf_lo_mips64:
4250b57cec5SDimitry Andric return "lo";
4260b57cec5SDimitry Andric case dwarf_hi_mips64:
4270b57cec5SDimitry Andric return "hi";
4280b57cec5SDimitry Andric case dwarf_bad_mips64:
4290b57cec5SDimitry Andric return "bad";
4300b57cec5SDimitry Andric case dwarf_cause_mips64:
4310b57cec5SDimitry Andric return "cause";
4320b57cec5SDimitry Andric case dwarf_pc_mips64:
4330b57cec5SDimitry Andric return "pc";
4340b57cec5SDimitry Andric case dwarf_f0_mips64:
4350b57cec5SDimitry Andric return "f0";
4360b57cec5SDimitry Andric case dwarf_f1_mips64:
4370b57cec5SDimitry Andric return "f1";
4380b57cec5SDimitry Andric case dwarf_f2_mips64:
4390b57cec5SDimitry Andric return "f2";
4400b57cec5SDimitry Andric case dwarf_f3_mips64:
4410b57cec5SDimitry Andric return "f3";
4420b57cec5SDimitry Andric case dwarf_f4_mips64:
4430b57cec5SDimitry Andric return "f4";
4440b57cec5SDimitry Andric case dwarf_f5_mips64:
4450b57cec5SDimitry Andric return "f5";
4460b57cec5SDimitry Andric case dwarf_f6_mips64:
4470b57cec5SDimitry Andric return "f6";
4480b57cec5SDimitry Andric case dwarf_f7_mips64:
4490b57cec5SDimitry Andric return "f7";
4500b57cec5SDimitry Andric case dwarf_f8_mips64:
4510b57cec5SDimitry Andric return "f8";
4520b57cec5SDimitry Andric case dwarf_f9_mips64:
4530b57cec5SDimitry Andric return "f9";
4540b57cec5SDimitry Andric case dwarf_f10_mips64:
4550b57cec5SDimitry Andric return "f10";
4560b57cec5SDimitry Andric case dwarf_f11_mips64:
4570b57cec5SDimitry Andric return "f11";
4580b57cec5SDimitry Andric case dwarf_f12_mips64:
4590b57cec5SDimitry Andric return "f12";
4600b57cec5SDimitry Andric case dwarf_f13_mips64:
4610b57cec5SDimitry Andric return "f13";
4620b57cec5SDimitry Andric case dwarf_f14_mips64:
4630b57cec5SDimitry Andric return "f14";
4640b57cec5SDimitry Andric case dwarf_f15_mips64:
4650b57cec5SDimitry Andric return "f15";
4660b57cec5SDimitry Andric case dwarf_f16_mips64:
4670b57cec5SDimitry Andric return "f16";
4680b57cec5SDimitry Andric case dwarf_f17_mips64:
4690b57cec5SDimitry Andric return "f17";
4700b57cec5SDimitry Andric case dwarf_f18_mips64:
4710b57cec5SDimitry Andric return "f18";
4720b57cec5SDimitry Andric case dwarf_f19_mips64:
4730b57cec5SDimitry Andric return "f19";
4740b57cec5SDimitry Andric case dwarf_f20_mips64:
4750b57cec5SDimitry Andric return "f20";
4760b57cec5SDimitry Andric case dwarf_f21_mips64:
4770b57cec5SDimitry Andric return "f21";
4780b57cec5SDimitry Andric case dwarf_f22_mips64:
4790b57cec5SDimitry Andric return "f22";
4800b57cec5SDimitry Andric case dwarf_f23_mips64:
4810b57cec5SDimitry Andric return "f23";
4820b57cec5SDimitry Andric case dwarf_f24_mips64:
4830b57cec5SDimitry Andric return "f24";
4840b57cec5SDimitry Andric case dwarf_f25_mips64:
4850b57cec5SDimitry Andric return "f25";
4860b57cec5SDimitry Andric case dwarf_f26_mips64:
4870b57cec5SDimitry Andric return "f26";
4880b57cec5SDimitry Andric case dwarf_f27_mips64:
4890b57cec5SDimitry Andric return "f27";
4900b57cec5SDimitry Andric case dwarf_f28_mips64:
4910b57cec5SDimitry Andric return "f28";
4920b57cec5SDimitry Andric case dwarf_f29_mips64:
4930b57cec5SDimitry Andric return "f29";
4940b57cec5SDimitry Andric case dwarf_f30_mips64:
4950b57cec5SDimitry Andric return "f30";
4960b57cec5SDimitry Andric case dwarf_f31_mips64:
4970b57cec5SDimitry Andric return "f31";
4980b57cec5SDimitry Andric case dwarf_fcsr_mips64:
4990b57cec5SDimitry Andric return "fcsr";
5000b57cec5SDimitry Andric case dwarf_fir_mips64:
5010b57cec5SDimitry Andric return "fir";
5020b57cec5SDimitry Andric case dwarf_w0_mips64:
5030b57cec5SDimitry Andric return "w0";
5040b57cec5SDimitry Andric case dwarf_w1_mips64:
5050b57cec5SDimitry Andric return "w1";
5060b57cec5SDimitry Andric case dwarf_w2_mips64:
5070b57cec5SDimitry Andric return "w2";
5080b57cec5SDimitry Andric case dwarf_w3_mips64:
5090b57cec5SDimitry Andric return "w3";
5100b57cec5SDimitry Andric case dwarf_w4_mips64:
5110b57cec5SDimitry Andric return "w4";
5120b57cec5SDimitry Andric case dwarf_w5_mips64:
5130b57cec5SDimitry Andric return "w5";
5140b57cec5SDimitry Andric case dwarf_w6_mips64:
5150b57cec5SDimitry Andric return "w6";
5160b57cec5SDimitry Andric case dwarf_w7_mips64:
5170b57cec5SDimitry Andric return "w7";
5180b57cec5SDimitry Andric case dwarf_w8_mips64:
5190b57cec5SDimitry Andric return "w8";
5200b57cec5SDimitry Andric case dwarf_w9_mips64:
5210b57cec5SDimitry Andric return "w9";
5220b57cec5SDimitry Andric case dwarf_w10_mips64:
5230b57cec5SDimitry Andric return "w10";
5240b57cec5SDimitry Andric case dwarf_w11_mips64:
5250b57cec5SDimitry Andric return "w11";
5260b57cec5SDimitry Andric case dwarf_w12_mips64:
5270b57cec5SDimitry Andric return "w12";
5280b57cec5SDimitry Andric case dwarf_w13_mips64:
5290b57cec5SDimitry Andric return "w13";
5300b57cec5SDimitry Andric case dwarf_w14_mips64:
5310b57cec5SDimitry Andric return "w14";
5320b57cec5SDimitry Andric case dwarf_w15_mips64:
5330b57cec5SDimitry Andric return "w15";
5340b57cec5SDimitry Andric case dwarf_w16_mips64:
5350b57cec5SDimitry Andric return "w16";
5360b57cec5SDimitry Andric case dwarf_w17_mips64:
5370b57cec5SDimitry Andric return "w17";
5380b57cec5SDimitry Andric case dwarf_w18_mips64:
5390b57cec5SDimitry Andric return "w18";
5400b57cec5SDimitry Andric case dwarf_w19_mips64:
5410b57cec5SDimitry Andric return "w19";
5420b57cec5SDimitry Andric case dwarf_w20_mips64:
5430b57cec5SDimitry Andric return "w20";
5440b57cec5SDimitry Andric case dwarf_w21_mips64:
5450b57cec5SDimitry Andric return "w21";
5460b57cec5SDimitry Andric case dwarf_w22_mips64:
5470b57cec5SDimitry Andric return "w22";
5480b57cec5SDimitry Andric case dwarf_w23_mips64:
5490b57cec5SDimitry Andric return "w23";
5500b57cec5SDimitry Andric case dwarf_w24_mips64:
5510b57cec5SDimitry Andric return "w24";
5520b57cec5SDimitry Andric case dwarf_w25_mips64:
5530b57cec5SDimitry Andric return "w25";
5540b57cec5SDimitry Andric case dwarf_w26_mips64:
5550b57cec5SDimitry Andric return "w26";
5560b57cec5SDimitry Andric case dwarf_w27_mips64:
5570b57cec5SDimitry Andric return "w27";
5580b57cec5SDimitry Andric case dwarf_w28_mips64:
5590b57cec5SDimitry Andric return "w28";
5600b57cec5SDimitry Andric case dwarf_w29_mips64:
5610b57cec5SDimitry Andric return "w29";
5620b57cec5SDimitry Andric case dwarf_w30_mips64:
5630b57cec5SDimitry Andric return "w30";
5640b57cec5SDimitry Andric case dwarf_w31_mips64:
5650b57cec5SDimitry Andric return "w31";
5660b57cec5SDimitry Andric case dwarf_mcsr_mips64:
5670b57cec5SDimitry Andric return "mcsr";
5680b57cec5SDimitry Andric case dwarf_mir_mips64:
5690b57cec5SDimitry Andric return "mir";
5700b57cec5SDimitry Andric case dwarf_config5_mips64:
5710b57cec5SDimitry Andric return "config5";
5720b57cec5SDimitry Andric }
5730b57cec5SDimitry Andric return nullptr;
5740b57cec5SDimitry Andric }
5750b57cec5SDimitry Andric
576bdd1243dSDimitry Andric std::optional<RegisterInfo>
GetRegisterInfo(RegisterKind reg_kind,uint32_t reg_num)577bdd1243dSDimitry Andric EmulateInstructionMIPS64::GetRegisterInfo(RegisterKind reg_kind,
578bdd1243dSDimitry Andric uint32_t reg_num) {
5790b57cec5SDimitry Andric if (reg_kind == eRegisterKindGeneric) {
5800b57cec5SDimitry Andric switch (reg_num) {
5810b57cec5SDimitry Andric case LLDB_REGNUM_GENERIC_PC:
5820b57cec5SDimitry Andric reg_kind = eRegisterKindDWARF;
5830b57cec5SDimitry Andric reg_num = dwarf_pc_mips64;
5840b57cec5SDimitry Andric break;
5850b57cec5SDimitry Andric case LLDB_REGNUM_GENERIC_SP:
5860b57cec5SDimitry Andric reg_kind = eRegisterKindDWARF;
5870b57cec5SDimitry Andric reg_num = dwarf_sp_mips64;
5880b57cec5SDimitry Andric break;
5890b57cec5SDimitry Andric case LLDB_REGNUM_GENERIC_FP:
5900b57cec5SDimitry Andric reg_kind = eRegisterKindDWARF;
5910b57cec5SDimitry Andric reg_num = dwarf_r30_mips64;
5920b57cec5SDimitry Andric break;
5930b57cec5SDimitry Andric case LLDB_REGNUM_GENERIC_RA:
5940b57cec5SDimitry Andric reg_kind = eRegisterKindDWARF;
5950b57cec5SDimitry Andric reg_num = dwarf_ra_mips64;
5960b57cec5SDimitry Andric break;
5970b57cec5SDimitry Andric case LLDB_REGNUM_GENERIC_FLAGS:
5980b57cec5SDimitry Andric reg_kind = eRegisterKindDWARF;
5990b57cec5SDimitry Andric reg_num = dwarf_sr_mips64;
6000b57cec5SDimitry Andric break;
6010b57cec5SDimitry Andric default:
602bdd1243dSDimitry Andric return {};
6030b57cec5SDimitry Andric }
6040b57cec5SDimitry Andric }
6050b57cec5SDimitry Andric
6060b57cec5SDimitry Andric if (reg_kind == eRegisterKindDWARF) {
607bdd1243dSDimitry Andric RegisterInfo reg_info;
6080b57cec5SDimitry Andric ::memset(®_info, 0, sizeof(RegisterInfo));
6090b57cec5SDimitry Andric ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
6100b57cec5SDimitry Andric
6110b57cec5SDimitry Andric if (reg_num == dwarf_sr_mips64 || reg_num == dwarf_fcsr_mips64 ||
6120b57cec5SDimitry Andric reg_num == dwarf_fir_mips64 || reg_num == dwarf_mcsr_mips64 ||
6130b57cec5SDimitry Andric reg_num == dwarf_mir_mips64 || reg_num == dwarf_config5_mips64) {
6140b57cec5SDimitry Andric reg_info.byte_size = 4;
6150b57cec5SDimitry Andric reg_info.format = eFormatHex;
6160b57cec5SDimitry Andric reg_info.encoding = eEncodingUint;
6170b57cec5SDimitry Andric } else if ((int)reg_num >= dwarf_zero_mips64 &&
6180b57cec5SDimitry Andric (int)reg_num <= dwarf_f31_mips64) {
6190b57cec5SDimitry Andric reg_info.byte_size = 8;
6200b57cec5SDimitry Andric reg_info.format = eFormatHex;
6210b57cec5SDimitry Andric reg_info.encoding = eEncodingUint;
6220b57cec5SDimitry Andric } else if ((int)reg_num >= dwarf_w0_mips64 &&
6230b57cec5SDimitry Andric (int)reg_num <= dwarf_w31_mips64) {
6240b57cec5SDimitry Andric reg_info.byte_size = 16;
6250b57cec5SDimitry Andric reg_info.format = eFormatVectorOfUInt8;
6260b57cec5SDimitry Andric reg_info.encoding = eEncodingVector;
6270b57cec5SDimitry Andric } else {
628bdd1243dSDimitry Andric return {};
6290b57cec5SDimitry Andric }
6300b57cec5SDimitry Andric
6310b57cec5SDimitry Andric reg_info.name = GetRegisterName(reg_num, false);
6320b57cec5SDimitry Andric reg_info.alt_name = GetRegisterName(reg_num, true);
6330b57cec5SDimitry Andric reg_info.kinds[eRegisterKindDWARF] = reg_num;
6340b57cec5SDimitry Andric
6350b57cec5SDimitry Andric switch (reg_num) {
6360b57cec5SDimitry Andric case dwarf_r30_mips64:
6370b57cec5SDimitry Andric reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
6380b57cec5SDimitry Andric break;
6390b57cec5SDimitry Andric case dwarf_ra_mips64:
6400b57cec5SDimitry Andric reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
6410b57cec5SDimitry Andric break;
6420b57cec5SDimitry Andric case dwarf_sp_mips64:
6430b57cec5SDimitry Andric reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
6440b57cec5SDimitry Andric break;
6450b57cec5SDimitry Andric case dwarf_pc_mips64:
6460b57cec5SDimitry Andric reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
6470b57cec5SDimitry Andric break;
6480b57cec5SDimitry Andric case dwarf_sr_mips64:
6490b57cec5SDimitry Andric reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
6500b57cec5SDimitry Andric break;
6510b57cec5SDimitry Andric default:
6520b57cec5SDimitry Andric break;
6530b57cec5SDimitry Andric }
654bdd1243dSDimitry Andric return reg_info;
6550b57cec5SDimitry Andric }
656bdd1243dSDimitry Andric return {};
6570b57cec5SDimitry Andric }
6580b57cec5SDimitry Andric
6590b57cec5SDimitry Andric EmulateInstructionMIPS64::MipsOpcode *
GetOpcodeForInstruction(llvm::StringRef op_name)66081ad6265SDimitry Andric EmulateInstructionMIPS64::GetOpcodeForInstruction(llvm::StringRef op_name) {
6610b57cec5SDimitry Andric static EmulateInstructionMIPS64::MipsOpcode g_opcodes[] = {
6620b57cec5SDimitry Andric // Prologue/Epilogue instructions
6630b57cec5SDimitry Andric {"DADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu,
6640b57cec5SDimitry Andric "DADDIU rt, rs, immediate"},
6650b57cec5SDimitry Andric {"ADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu,
6660b57cec5SDimitry Andric "ADDIU rt, rs, immediate"},
6670b57cec5SDimitry Andric {"SD", &EmulateInstructionMIPS64::Emulate_SD, "SD rt, offset(rs)"},
6680b57cec5SDimitry Andric {"LD", &EmulateInstructionMIPS64::Emulate_LD, "LD rt, offset(base)"},
6690b57cec5SDimitry Andric {"DSUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
6700b57cec5SDimitry Andric "DSUBU rd, rs, rt"},
6710b57cec5SDimitry Andric {"SUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
6720b57cec5SDimitry Andric "SUBU rd, rs, rt"},
6730b57cec5SDimitry Andric {"DADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
6740b57cec5SDimitry Andric "DADDU rd, rs, rt"},
6750b57cec5SDimitry Andric {"ADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
6760b57cec5SDimitry Andric "ADDU rd, rs, rt"},
6770b57cec5SDimitry Andric {"LUI", &EmulateInstructionMIPS64::Emulate_LUI, "LUI rt, immediate"},
6780b57cec5SDimitry Andric
6790b57cec5SDimitry Andric // Load/Store instructions
6800b57cec5SDimitry Andric /* Following list of emulated instructions are required by implementation
6810b57cec5SDimitry Andric of hardware watchpoint
6820b57cec5SDimitry Andric for MIPS in lldb. As we just need the address accessed by instructions,
6830b57cec5SDimitry Andric we have generalised
6840b57cec5SDimitry Andric all these instructions in 2 functions depending on their addressing
6850b57cec5SDimitry Andric modes */
6860b57cec5SDimitry Andric
6870b57cec5SDimitry Andric {"LB", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
6880b57cec5SDimitry Andric "LB rt, offset(base)"},
6890b57cec5SDimitry Andric {"LBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
6900b57cec5SDimitry Andric "LBE rt, offset(base)"},
6910b57cec5SDimitry Andric {"LBU", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
6920b57cec5SDimitry Andric "LBU rt, offset(base)"},
6930b57cec5SDimitry Andric {"LBUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
6940b57cec5SDimitry Andric "LBUE rt, offset(base)"},
6950b57cec5SDimitry Andric {"LDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
6960b57cec5SDimitry Andric "LDC1 ft, offset(base)"},
6970b57cec5SDimitry Andric {"LDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
6980b57cec5SDimitry Andric "LDL rt, offset(base)"},
6990b57cec5SDimitry Andric {"LDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7000b57cec5SDimitry Andric "LDR rt, offset(base)"},
7010b57cec5SDimitry Andric {"LLD", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7020b57cec5SDimitry Andric "LLD rt, offset(base)"},
7030b57cec5SDimitry Andric {"LDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7040b57cec5SDimitry Andric "LDC2 rt, offset(base)"},
7050b57cec5SDimitry Andric {"LDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
7060b57cec5SDimitry Andric "LDXC1 fd, index (base)"},
7070b57cec5SDimitry Andric {"LH", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7080b57cec5SDimitry Andric "LH rt, offset(base)"},
7090b57cec5SDimitry Andric {"LHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7100b57cec5SDimitry Andric "LHE rt, offset(base)"},
7110b57cec5SDimitry Andric {"LHU", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7120b57cec5SDimitry Andric "LHU rt, offset(base)"},
7130b57cec5SDimitry Andric {"LHUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7140b57cec5SDimitry Andric "LHUE rt, offset(base)"},
7150b57cec5SDimitry Andric {"LL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7160b57cec5SDimitry Andric "LL rt, offset(base)"},
7170b57cec5SDimitry Andric {"LLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7180b57cec5SDimitry Andric "LLE rt, offset(base)"},
7190b57cec5SDimitry Andric {"LUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
7200b57cec5SDimitry Andric "LUXC1 fd, index (base)"},
7210b57cec5SDimitry Andric {"LW", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7220b57cec5SDimitry Andric "LW rt, offset(rs)"},
7230b57cec5SDimitry Andric {"LWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7240b57cec5SDimitry Andric "LWC1 ft, offset(base)"},
7250b57cec5SDimitry Andric {"LWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7260b57cec5SDimitry Andric "LWC2 rt, offset(base)"},
7270b57cec5SDimitry Andric {"LWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7280b57cec5SDimitry Andric "LWE rt, offset(base)"},
7290b57cec5SDimitry Andric {"LWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7300b57cec5SDimitry Andric "LWL rt, offset(base)"},
7310b57cec5SDimitry Andric {"LWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7320b57cec5SDimitry Andric "LWLE rt, offset(base)"},
7330b57cec5SDimitry Andric {"LWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7340b57cec5SDimitry Andric "LWR rt, offset(base)"},
7350b57cec5SDimitry Andric {"LWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7360b57cec5SDimitry Andric "LWRE rt, offset(base)"},
7370b57cec5SDimitry Andric {"LWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
7380b57cec5SDimitry Andric "LWXC1 fd, index (base)"},
7390b57cec5SDimitry Andric
7400b57cec5SDimitry Andric {"SB", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7410b57cec5SDimitry Andric "SB rt, offset(base)"},
7420b57cec5SDimitry Andric {"SBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7430b57cec5SDimitry Andric "SBE rt, offset(base)"},
7440b57cec5SDimitry Andric {"SC", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7450b57cec5SDimitry Andric "SC rt, offset(base)"},
7460b57cec5SDimitry Andric {"SCE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7470b57cec5SDimitry Andric "SCE rt, offset(base)"},
7480b57cec5SDimitry Andric {"SCD", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7490b57cec5SDimitry Andric "SCD rt, offset(base)"},
7500b57cec5SDimitry Andric {"SDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7510b57cec5SDimitry Andric "SDL rt, offset(base)"},
7520b57cec5SDimitry Andric {"SDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7530b57cec5SDimitry Andric "SDR rt, offset(base)"},
7540b57cec5SDimitry Andric {"SDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7550b57cec5SDimitry Andric "SDC1 ft, offset(base)"},
7560b57cec5SDimitry Andric {"SDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7570b57cec5SDimitry Andric "SDC2 rt, offset(base)"},
7580b57cec5SDimitry Andric {"SDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
7590b57cec5SDimitry Andric "SDXC1 fs, index (base)"},
7600b57cec5SDimitry Andric {"SH", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7610b57cec5SDimitry Andric "SH rt, offset(base)"},
7620b57cec5SDimitry Andric {"SHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7630b57cec5SDimitry Andric "SHE rt, offset(base)"},
7640b57cec5SDimitry Andric {"SUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
7650b57cec5SDimitry Andric "SUXC1 fs, index (base)"},
7660b57cec5SDimitry Andric {"SW", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7670b57cec5SDimitry Andric "SW rt, offset(rs)"},
7680b57cec5SDimitry Andric {"SWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7690b57cec5SDimitry Andric "SWC1 ft, offset(base)"},
7700b57cec5SDimitry Andric {"SWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7710b57cec5SDimitry Andric "SWC2 rt, offset(base)"},
7720b57cec5SDimitry Andric {"SWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7730b57cec5SDimitry Andric "SWE rt, offset(base)"},
7740b57cec5SDimitry Andric {"SWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7750b57cec5SDimitry Andric "SWL rt, offset(base)"},
7760b57cec5SDimitry Andric {"SWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7770b57cec5SDimitry Andric "SWLE rt, offset(base)"},
7780b57cec5SDimitry Andric {"SWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7790b57cec5SDimitry Andric "SWR rt, offset(base)"},
7800b57cec5SDimitry Andric {"SWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
7810b57cec5SDimitry Andric "SWRE rt, offset(base)"},
7820b57cec5SDimitry Andric {"SWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
7830b57cec5SDimitry Andric "SWXC1 fs, index (base)"},
7840b57cec5SDimitry Andric
7850b57cec5SDimitry Andric // Branch instructions
7860b57cec5SDimitry Andric {"BEQ", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"},
7870b57cec5SDimitry Andric {"BEQ64", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"},
7880b57cec5SDimitry Andric {"BNE", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"},
7890b57cec5SDimitry Andric {"BNE64", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"},
7900b57cec5SDimitry Andric {"BEQL", &EmulateInstructionMIPS64::Emulate_BXX_3ops,
7910b57cec5SDimitry Andric "BEQL rs,rt,offset"},
7920b57cec5SDimitry Andric {"BNEL", &EmulateInstructionMIPS64::Emulate_BXX_3ops,
7930b57cec5SDimitry Andric "BNEL rs,rt,offset"},
7940b57cec5SDimitry Andric {"BGEZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
7950b57cec5SDimitry Andric "BGEZALL rt,offset"},
7960b57cec5SDimitry Andric {"BAL", &EmulateInstructionMIPS64::Emulate_BAL, "BAL offset"},
7970b57cec5SDimitry Andric {"BGEZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
7980b57cec5SDimitry Andric "BGEZAL rs,offset"},
7990b57cec5SDimitry Andric {"BALC", &EmulateInstructionMIPS64::Emulate_BALC, "BALC offset"},
8000b57cec5SDimitry Andric {"BC", &EmulateInstructionMIPS64::Emulate_BC, "BC offset"},
8010b57cec5SDimitry Andric {"BGEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"},
8020b57cec5SDimitry Andric {"BGEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"},
8030b57cec5SDimitry Andric {"BLEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
8040b57cec5SDimitry Andric "BLEZALC rs,offset"},
8050b57cec5SDimitry Andric {"BGEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
8060b57cec5SDimitry Andric "BGEZALC rs,offset"},
8070b57cec5SDimitry Andric {"BLTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
8080b57cec5SDimitry Andric "BLTZALC rs,offset"},
8090b57cec5SDimitry Andric {"BGTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
8100b57cec5SDimitry Andric "BGTZALC rs,offset"},
8110b57cec5SDimitry Andric {"BEQZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
8120b57cec5SDimitry Andric "BEQZALC rs,offset"},
8130b57cec5SDimitry Andric {"BNEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
8140b57cec5SDimitry Andric "BNEZALC rs,offset"},
8150b57cec5SDimitry Andric {"BEQC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
8160b57cec5SDimitry Andric "BEQC rs,rt,offset"},
8170b57cec5SDimitry Andric {"BEQC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
8180b57cec5SDimitry Andric "BEQC rs,rt,offset"},
8190b57cec5SDimitry Andric {"BNEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
8200b57cec5SDimitry Andric "BNEC rs,rt,offset"},
8210b57cec5SDimitry Andric {"BNEC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
8220b57cec5SDimitry Andric "BNEC rs,rt,offset"},
8230b57cec5SDimitry Andric {"BLTC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
8240b57cec5SDimitry Andric "BLTC rs,rt,offset"},
8250b57cec5SDimitry Andric {"BLTC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
8260b57cec5SDimitry Andric "BLTC rs,rt,offset"},
8270b57cec5SDimitry Andric {"BGEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
8280b57cec5SDimitry Andric "BGEC rs,rt,offset"},
8290b57cec5SDimitry Andric {"BGEC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
8300b57cec5SDimitry Andric "BGEC rs,rt,offset"},
8310b57cec5SDimitry Andric {"BLTUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
8320b57cec5SDimitry Andric "BLTUC rs,rt,offset"},
8330b57cec5SDimitry Andric {"BLTUC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
8340b57cec5SDimitry Andric "BLTUC rs,rt,offset"},
8350b57cec5SDimitry Andric {"BGEUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
8360b57cec5SDimitry Andric "BGEUC rs,rt,offset"},
8370b57cec5SDimitry Andric {"BGEUC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
8380b57cec5SDimitry Andric "BGEUC rs,rt,offset"},
8390b57cec5SDimitry Andric {"BLTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
8400b57cec5SDimitry Andric "BLTZC rt,offset"},
8410b57cec5SDimitry Andric {"BLTZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
8420b57cec5SDimitry Andric "BLTZC rt,offset"},
8430b57cec5SDimitry Andric {"BLEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
8440b57cec5SDimitry Andric "BLEZC rt,offset"},
8450b57cec5SDimitry Andric {"BLEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
8460b57cec5SDimitry Andric "BLEZC rt,offset"},
8470b57cec5SDimitry Andric {"BGEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
8480b57cec5SDimitry Andric "BGEZC rt,offset"},
8490b57cec5SDimitry Andric {"BGEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
8500b57cec5SDimitry Andric "BGEZC rt,offset"},
8510b57cec5SDimitry Andric {"BGTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
8520b57cec5SDimitry Andric "BGTZC rt,offset"},
8530b57cec5SDimitry Andric {"BGTZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
8540b57cec5SDimitry Andric "BGTZC rt,offset"},
8550b57cec5SDimitry Andric {"BEQZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
8560b57cec5SDimitry Andric "BEQZC rt,offset"},
8570b57cec5SDimitry Andric {"BEQZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
8580b57cec5SDimitry Andric "BEQZC rt,offset"},
8590b57cec5SDimitry Andric {"BNEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
8600b57cec5SDimitry Andric "BNEZC rt,offset"},
8610b57cec5SDimitry Andric {"BNEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
8620b57cec5SDimitry Andric "BNEZC rt,offset"},
8630b57cec5SDimitry Andric {"BGEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZL rt,offset"},
8640b57cec5SDimitry Andric {"BGTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"},
8650b57cec5SDimitry Andric {"BGTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"},
8660b57cec5SDimitry Andric {"BGTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZL rt,offset"},
8670b57cec5SDimitry Andric {"BLEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"},
8680b57cec5SDimitry Andric {"BLEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"},
8690b57cec5SDimitry Andric {"BLEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZL rt,offset"},
8700b57cec5SDimitry Andric {"BLTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"},
8710b57cec5SDimitry Andric {"BLTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"},
8720b57cec5SDimitry Andric {"BLTZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
8730b57cec5SDimitry Andric "BLTZAL rt,offset"},
8740b57cec5SDimitry Andric {"BLTZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
8750b57cec5SDimitry Andric "BLTZALL rt,offset"},
8760b57cec5SDimitry Andric {"BLTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZL rt,offset"},
8770b57cec5SDimitry Andric {"BOVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
8780b57cec5SDimitry Andric "BOVC rs,rt,offset"},
8790b57cec5SDimitry Andric {"BNVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
8800b57cec5SDimitry Andric "BNVC rs,rt,offset"},
8810b57cec5SDimitry Andric {"J", &EmulateInstructionMIPS64::Emulate_J, "J target"},
8820b57cec5SDimitry Andric {"JAL", &EmulateInstructionMIPS64::Emulate_JAL, "JAL target"},
8830b57cec5SDimitry Andric {"JALX", &EmulateInstructionMIPS64::Emulate_JAL, "JALX target"},
8840b57cec5SDimitry Andric {"JALR", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target"},
8850b57cec5SDimitry Andric {"JALR64", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target"},
8860b57cec5SDimitry Andric {"JALR_HB", &EmulateInstructionMIPS64::Emulate_JALR, "JALR.HB target"},
8870b57cec5SDimitry Andric {"JIALC", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"},
8880b57cec5SDimitry Andric {"JIALC64", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"},
8890b57cec5SDimitry Andric {"JIC", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"},
8900b57cec5SDimitry Andric {"JIC64", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"},
8910b57cec5SDimitry Andric {"JR", &EmulateInstructionMIPS64::Emulate_JR, "JR target"},
8920b57cec5SDimitry Andric {"JR64", &EmulateInstructionMIPS64::Emulate_JR, "JR target"},
8930b57cec5SDimitry Andric {"JR_HB", &EmulateInstructionMIPS64::Emulate_JR, "JR.HB target"},
8940b57cec5SDimitry Andric {"BC1F", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1F cc, offset"},
8950b57cec5SDimitry Andric {"BC1T", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1T cc, offset"},
8960b57cec5SDimitry Andric {"BC1FL", &EmulateInstructionMIPS64::Emulate_FP_branch,
8970b57cec5SDimitry Andric "BC1FL cc, offset"},
8980b57cec5SDimitry Andric {"BC1TL", &EmulateInstructionMIPS64::Emulate_FP_branch,
8990b57cec5SDimitry Andric "BC1TL cc, offset"},
9000b57cec5SDimitry Andric {"BC1EQZ", &EmulateInstructionMIPS64::Emulate_BC1EQZ,
9010b57cec5SDimitry Andric "BC1EQZ ft, offset"},
9020b57cec5SDimitry Andric {"BC1NEZ", &EmulateInstructionMIPS64::Emulate_BC1NEZ,
9030b57cec5SDimitry Andric "BC1NEZ ft, offset"},
9040b57cec5SDimitry Andric {"BC1ANY2F", &EmulateInstructionMIPS64::Emulate_3D_branch,
9050b57cec5SDimitry Andric "BC1ANY2F cc, offset"},
9060b57cec5SDimitry Andric {"BC1ANY2T", &EmulateInstructionMIPS64::Emulate_3D_branch,
9070b57cec5SDimitry Andric "BC1ANY2T cc, offset"},
9080b57cec5SDimitry Andric {"BC1ANY4F", &EmulateInstructionMIPS64::Emulate_3D_branch,
9090b57cec5SDimitry Andric "BC1ANY4F cc, offset"},
9100b57cec5SDimitry Andric {"BC1ANY4T", &EmulateInstructionMIPS64::Emulate_3D_branch,
9110b57cec5SDimitry Andric "BC1ANY4T cc, offset"},
9120b57cec5SDimitry Andric {"BNZ_B", &EmulateInstructionMIPS64::Emulate_BNZB, "BNZ.b wt,s16"},
9130b57cec5SDimitry Andric {"BNZ_H", &EmulateInstructionMIPS64::Emulate_BNZH, "BNZ.h wt,s16"},
9140b57cec5SDimitry Andric {"BNZ_W", &EmulateInstructionMIPS64::Emulate_BNZW, "BNZ.w wt,s16"},
9150b57cec5SDimitry Andric {"BNZ_D", &EmulateInstructionMIPS64::Emulate_BNZD, "BNZ.d wt,s16"},
9160b57cec5SDimitry Andric {"BZ_B", &EmulateInstructionMIPS64::Emulate_BZB, "BZ.b wt,s16"},
9170b57cec5SDimitry Andric {"BZ_H", &EmulateInstructionMIPS64::Emulate_BZH, "BZ.h wt,s16"},
9180b57cec5SDimitry Andric {"BZ_W", &EmulateInstructionMIPS64::Emulate_BZW, "BZ.w wt,s16"},
9190b57cec5SDimitry Andric {"BZ_D", &EmulateInstructionMIPS64::Emulate_BZD, "BZ.d wt,s16"},
9200b57cec5SDimitry Andric {"BNZ_V", &EmulateInstructionMIPS64::Emulate_BNZV, "BNZ.V wt,s16"},
9210b57cec5SDimitry Andric {"BZ_V", &EmulateInstructionMIPS64::Emulate_BZV, "BZ.V wt,s16"},
9220b57cec5SDimitry Andric };
9230b57cec5SDimitry Andric
92481ad6265SDimitry Andric for (MipsOpcode &opcode : g_opcodes) {
92581ad6265SDimitry Andric if (op_name.equals_insensitive(opcode.op_name))
92681ad6265SDimitry Andric return &opcode;
9270b57cec5SDimitry Andric }
9280b57cec5SDimitry Andric return nullptr;
9290b57cec5SDimitry Andric }
9300b57cec5SDimitry Andric
ReadInstruction()9310b57cec5SDimitry Andric bool EmulateInstructionMIPS64::ReadInstruction() {
9320b57cec5SDimitry Andric bool success = false;
9330b57cec5SDimitry Andric m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
9340b57cec5SDimitry Andric LLDB_INVALID_ADDRESS, &success);
9350b57cec5SDimitry Andric if (success) {
9360b57cec5SDimitry Andric Context read_inst_context;
9370b57cec5SDimitry Andric read_inst_context.type = eContextReadOpcode;
9380b57cec5SDimitry Andric read_inst_context.SetNoArgs();
9390b57cec5SDimitry Andric m_opcode.SetOpcode32(
9400b57cec5SDimitry Andric ReadMemoryUnsigned(read_inst_context, m_addr, 4, 0, &success),
9410b57cec5SDimitry Andric GetByteOrder());
9420b57cec5SDimitry Andric }
9430b57cec5SDimitry Andric if (!success)
9440b57cec5SDimitry Andric m_addr = LLDB_INVALID_ADDRESS;
9450b57cec5SDimitry Andric return success;
9460b57cec5SDimitry Andric }
9470b57cec5SDimitry Andric
EvaluateInstruction(uint32_t evaluate_options)9480b57cec5SDimitry Andric bool EmulateInstructionMIPS64::EvaluateInstruction(uint32_t evaluate_options) {
9490b57cec5SDimitry Andric bool success = false;
9500b57cec5SDimitry Andric llvm::MCInst mc_insn;
9510b57cec5SDimitry Andric uint64_t insn_size;
9520b57cec5SDimitry Andric DataExtractor data;
9530b57cec5SDimitry Andric
9540b57cec5SDimitry Andric /* Keep the complexity of the decode logic with the llvm::MCDisassembler
9550b57cec5SDimitry Andric * class. */
9560b57cec5SDimitry Andric if (m_opcode.GetData(data)) {
9570b57cec5SDimitry Andric llvm::MCDisassembler::DecodeStatus decode_status;
9580b57cec5SDimitry Andric llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());
959480093f4SDimitry Andric decode_status = m_disasm->getInstruction(mc_insn, insn_size, raw_insn,
960480093f4SDimitry Andric m_addr, llvm::nulls());
9610b57cec5SDimitry Andric if (decode_status != llvm::MCDisassembler::Success)
9620b57cec5SDimitry Andric return false;
9630b57cec5SDimitry Andric }
9640b57cec5SDimitry Andric
9650b57cec5SDimitry Andric /*
9660b57cec5SDimitry Andric * mc_insn.getOpcode() returns decoded opcode. However to make use
9670b57cec5SDimitry Andric * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc".
9680b57cec5SDimitry Andric */
96981ad6265SDimitry Andric llvm::StringRef op_name = m_insn_info->getName(mc_insn.getOpcode());
9700b57cec5SDimitry Andric
9710b57cec5SDimitry Andric /*
9720b57cec5SDimitry Andric * Decoding has been done already. Just get the call-back function
9730b57cec5SDimitry Andric * and emulate the instruction.
9740b57cec5SDimitry Andric */
9750b57cec5SDimitry Andric MipsOpcode *opcode_data = GetOpcodeForInstruction(op_name);
9760b57cec5SDimitry Andric
9770b57cec5SDimitry Andric if (opcode_data == nullptr)
9780b57cec5SDimitry Andric return false;
9790b57cec5SDimitry Andric
9800b57cec5SDimitry Andric uint64_t old_pc = 0, new_pc = 0;
9810b57cec5SDimitry Andric const bool auto_advance_pc =
9820b57cec5SDimitry Andric evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
9830b57cec5SDimitry Andric
9840b57cec5SDimitry Andric if (auto_advance_pc) {
9850b57cec5SDimitry Andric old_pc =
9860b57cec5SDimitry Andric ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
9870b57cec5SDimitry Andric if (!success)
9880b57cec5SDimitry Andric return false;
9890b57cec5SDimitry Andric }
9900b57cec5SDimitry Andric
9910b57cec5SDimitry Andric /* emulate instruction */
9920b57cec5SDimitry Andric success = (this->*opcode_data->callback)(mc_insn);
9930b57cec5SDimitry Andric if (!success)
9940b57cec5SDimitry Andric return false;
9950b57cec5SDimitry Andric
9960b57cec5SDimitry Andric if (auto_advance_pc) {
9970b57cec5SDimitry Andric new_pc =
9980b57cec5SDimitry Andric ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
9990b57cec5SDimitry Andric if (!success)
10000b57cec5SDimitry Andric return false;
10010b57cec5SDimitry Andric
10020b57cec5SDimitry Andric /* If we haven't changed the PC, change it here */
10030b57cec5SDimitry Andric if (old_pc == new_pc) {
10040b57cec5SDimitry Andric new_pc += 4;
10050b57cec5SDimitry Andric Context context;
10060b57cec5SDimitry Andric if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
10070b57cec5SDimitry Andric new_pc))
10080b57cec5SDimitry Andric return false;
10090b57cec5SDimitry Andric }
10100b57cec5SDimitry Andric }
10110b57cec5SDimitry Andric
10120b57cec5SDimitry Andric return true;
10130b57cec5SDimitry Andric }
10140b57cec5SDimitry Andric
CreateFunctionEntryUnwind(UnwindPlan & unwind_plan)10150b57cec5SDimitry Andric bool EmulateInstructionMIPS64::CreateFunctionEntryUnwind(
10160b57cec5SDimitry Andric UnwindPlan &unwind_plan) {
10170b57cec5SDimitry Andric unwind_plan.Clear();
10180b57cec5SDimitry Andric unwind_plan.SetRegisterKind(eRegisterKindDWARF);
10190b57cec5SDimitry Andric
10200b57cec5SDimitry Andric UnwindPlan::RowSP row(new UnwindPlan::Row);
10210b57cec5SDimitry Andric const bool can_replace = false;
10220b57cec5SDimitry Andric
10230b57cec5SDimitry Andric // Our previous Call Frame Address is the stack pointer
10240b57cec5SDimitry Andric row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips64, 0);
10250b57cec5SDimitry Andric
10260b57cec5SDimitry Andric // Our previous PC is in the RA
10270b57cec5SDimitry Andric row->SetRegisterLocationToRegister(dwarf_pc_mips64, dwarf_ra_mips64,
10280b57cec5SDimitry Andric can_replace);
10290b57cec5SDimitry Andric
10300b57cec5SDimitry Andric unwind_plan.AppendRow(row);
10310b57cec5SDimitry Andric
10320b57cec5SDimitry Andric // All other registers are the same.
10330b57cec5SDimitry Andric unwind_plan.SetSourceName("EmulateInstructionMIPS64");
10340b57cec5SDimitry Andric unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
10350b57cec5SDimitry Andric unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
10369dba64beSDimitry Andric unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
10370b57cec5SDimitry Andric unwind_plan.SetReturnAddressRegister(dwarf_ra_mips64);
10380b57cec5SDimitry Andric
10390b57cec5SDimitry Andric return true;
10400b57cec5SDimitry Andric }
10410b57cec5SDimitry Andric
nonvolatile_reg_p(uint64_t regnum)10420b57cec5SDimitry Andric bool EmulateInstructionMIPS64::nonvolatile_reg_p(uint64_t regnum) {
10430b57cec5SDimitry Andric switch (regnum) {
10440b57cec5SDimitry Andric case dwarf_r16_mips64:
10450b57cec5SDimitry Andric case dwarf_r17_mips64:
10460b57cec5SDimitry Andric case dwarf_r18_mips64:
10470b57cec5SDimitry Andric case dwarf_r19_mips64:
10480b57cec5SDimitry Andric case dwarf_r20_mips64:
10490b57cec5SDimitry Andric case dwarf_r21_mips64:
10500b57cec5SDimitry Andric case dwarf_r22_mips64:
10510b57cec5SDimitry Andric case dwarf_r23_mips64:
10520b57cec5SDimitry Andric case dwarf_gp_mips64:
10530b57cec5SDimitry Andric case dwarf_sp_mips64:
10540b57cec5SDimitry Andric case dwarf_r30_mips64:
10550b57cec5SDimitry Andric case dwarf_ra_mips64:
10560b57cec5SDimitry Andric return true;
10570b57cec5SDimitry Andric default:
10580b57cec5SDimitry Andric return false;
10590b57cec5SDimitry Andric }
10600b57cec5SDimitry Andric return false;
10610b57cec5SDimitry Andric }
10620b57cec5SDimitry Andric
Emulate_DADDiu(llvm::MCInst & insn)10630b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_DADDiu(llvm::MCInst &insn) {
10640b57cec5SDimitry Andric // DADDIU rt, rs, immediate
10650b57cec5SDimitry Andric // GPR[rt] <- GPR[rs] + sign_extend(immediate)
10660b57cec5SDimitry Andric
10670b57cec5SDimitry Andric uint8_t dst, src;
10680b57cec5SDimitry Andric bool success = false;
10690b57cec5SDimitry Andric const uint32_t imm16 = insn.getOperand(2).getImm();
10700b57cec5SDimitry Andric int64_t imm = SignedBits(imm16, 15, 0);
10710b57cec5SDimitry Andric
10720b57cec5SDimitry Andric dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
10730b57cec5SDimitry Andric src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
10740b57cec5SDimitry Andric
10750b57cec5SDimitry Andric // If immediate is greater than 2^16 - 1 then clang generate LUI,
10760b57cec5SDimitry Andric // (D)ADDIU,(D)SUBU instructions in prolog. Example lui $1, 0x2 daddiu $1,
10770b57cec5SDimitry Andric // $1, -0x5920 dsubu $sp, $sp, $1 In this case, (D)ADDIU dst and src will be
10780b57cec5SDimitry Andric // same and not equal to sp
10790b57cec5SDimitry Andric if (dst == src) {
10800b57cec5SDimitry Andric Context context;
10810b57cec5SDimitry Andric
10820b57cec5SDimitry Andric /* read <src> register */
10830b57cec5SDimitry Andric const uint64_t src_opd_val = ReadRegisterUnsigned(
10840b57cec5SDimitry Andric eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
10850b57cec5SDimitry Andric if (!success)
10860b57cec5SDimitry Andric return false;
10870b57cec5SDimitry Andric
10880b57cec5SDimitry Andric /* Check if this is daddiu sp, sp, imm16 */
10890b57cec5SDimitry Andric if (dst == dwarf_sp_mips64) {
10900b57cec5SDimitry Andric /*
10910b57cec5SDimitry Andric * From the MIPS IV spec:
10920b57cec5SDimitry Andric *
10930b57cec5SDimitry Andric * The term “unsigned” in the instruction name is a misnomer; this
10940b57cec5SDimitry Andric * operation is 64-bit modulo arithmetic that does not trap on overflow.
10950b57cec5SDimitry Andric * It is appropriate for arithmetic which is not signed, such as address
10960b57cec5SDimitry Andric * arithmetic, or integer arithmetic environments that ignore overflow,
10970b57cec5SDimitry Andric * such as “C” language arithmetic.
10980b57cec5SDimitry Andric *
10990b57cec5SDimitry Andric * Assume 2's complement and rely on unsigned overflow here.
11000b57cec5SDimitry Andric */
11010b57cec5SDimitry Andric uint64_t result = src_opd_val + imm;
1102bdd1243dSDimitry Andric std::optional<RegisterInfo> reg_info_sp =
1103bdd1243dSDimitry Andric GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64);
1104bdd1243dSDimitry Andric if (reg_info_sp)
1105bdd1243dSDimitry Andric context.SetRegisterPlusOffset(*reg_info_sp, imm);
11060b57cec5SDimitry Andric
11070b57cec5SDimitry Andric /* We are allocating bytes on stack */
11080b57cec5SDimitry Andric context.type = eContextAdjustStackPointer;
11090b57cec5SDimitry Andric
11100b57cec5SDimitry Andric WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips64,
11110b57cec5SDimitry Andric result);
11120b57cec5SDimitry Andric return true;
11130b57cec5SDimitry Andric }
11140b57cec5SDimitry Andric
11150b57cec5SDimitry Andric imm += src_opd_val;
11160b57cec5SDimitry Andric context.SetImmediateSigned(imm);
11170b57cec5SDimitry Andric context.type = eContextImmediate;
11180b57cec5SDimitry Andric
11190b57cec5SDimitry Andric if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
11200b57cec5SDimitry Andric dwarf_zero_mips64 + dst, imm))
11210b57cec5SDimitry Andric return false;
11220b57cec5SDimitry Andric }
11230b57cec5SDimitry Andric
11240b57cec5SDimitry Andric return true;
11250b57cec5SDimitry Andric }
11260b57cec5SDimitry Andric
Emulate_SD(llvm::MCInst & insn)11270b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_SD(llvm::MCInst &insn) {
11280b57cec5SDimitry Andric uint64_t address;
11290b57cec5SDimitry Andric bool success = false;
11300b57cec5SDimitry Andric uint32_t imm16 = insn.getOperand(2).getImm();
11310b57cec5SDimitry Andric uint64_t imm = SignedBits(imm16, 15, 0);
11320b57cec5SDimitry Andric uint32_t src, base;
11330b57cec5SDimitry Andric Context bad_vaddr_context;
11340b57cec5SDimitry Andric
11350b57cec5SDimitry Andric src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
11360b57cec5SDimitry Andric base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
11370b57cec5SDimitry Andric
1138bdd1243dSDimitry Andric std::optional<RegisterInfo> reg_info_base =
1139bdd1243dSDimitry Andric GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base);
1140bdd1243dSDimitry Andric std::optional<RegisterInfo> reg_info_src =
1141bdd1243dSDimitry Andric GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src);
1142bdd1243dSDimitry Andric if (!reg_info_base || !reg_info_src)
11430b57cec5SDimitry Andric return false;
11440b57cec5SDimitry Andric
11450b57cec5SDimitry Andric /* read SP */
11460b57cec5SDimitry Andric address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + base,
11470b57cec5SDimitry Andric 0, &success);
11480b57cec5SDimitry Andric if (!success)
11490b57cec5SDimitry Andric return false;
11500b57cec5SDimitry Andric
11510b57cec5SDimitry Andric /* destination address */
11520b57cec5SDimitry Andric address = address + imm;
11530b57cec5SDimitry Andric
11540b57cec5SDimitry Andric /* We look for sp based non-volatile register stores */
11550b57cec5SDimitry Andric if (nonvolatile_reg_p(src)) {
11560b57cec5SDimitry Andric Context context;
11570b57cec5SDimitry Andric context.type = eContextPushRegisterOnStack;
1158bdd1243dSDimitry Andric context.SetRegisterToRegisterPlusOffset(*reg_info_src, *reg_info_base, 0);
11590b57cec5SDimitry Andric
1160bdd1243dSDimitry Andric std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);
1161bdd1243dSDimitry Andric if (!data_src)
11620b57cec5SDimitry Andric return false;
11630b57cec5SDimitry Andric
1164*06c3fb27SDimitry Andric Status error;
1165*06c3fb27SDimitry Andric RegisterValue::BytesContainer buffer(reg_info_src->byte_size);
1166*06c3fb27SDimitry Andric if (data_src->GetAsMemoryData(*reg_info_src, buffer.data(),
1167bdd1243dSDimitry Andric reg_info_src->byte_size, eByteOrderLittle,
1168bdd1243dSDimitry Andric error) == 0)
11690b57cec5SDimitry Andric return false;
11700b57cec5SDimitry Andric
1171*06c3fb27SDimitry Andric if (!WriteMemory(context, address, buffer.data(), reg_info_src->byte_size))
11720b57cec5SDimitry Andric return false;
11730b57cec5SDimitry Andric }
11740b57cec5SDimitry Andric
11750b57cec5SDimitry Andric /* Set the bad_vaddr register with base address used in the instruction */
11760b57cec5SDimitry Andric bad_vaddr_context.type = eContextInvalid;
11770b57cec5SDimitry Andric WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64,
11780b57cec5SDimitry Andric address);
11790b57cec5SDimitry Andric
11800b57cec5SDimitry Andric return true;
11810b57cec5SDimitry Andric }
11820b57cec5SDimitry Andric
Emulate_LD(llvm::MCInst & insn)11830b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_LD(llvm::MCInst &insn) {
11840b57cec5SDimitry Andric bool success = false;
11850b57cec5SDimitry Andric uint32_t src, base;
11860b57cec5SDimitry Andric int64_t imm, address;
11870b57cec5SDimitry Andric Context bad_vaddr_context;
11880b57cec5SDimitry Andric
11890b57cec5SDimitry Andric src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
11900b57cec5SDimitry Andric base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
11910b57cec5SDimitry Andric imm = insn.getOperand(2).getImm();
11920b57cec5SDimitry Andric
1193bdd1243dSDimitry Andric if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base))
11940b57cec5SDimitry Andric return false;
11950b57cec5SDimitry Andric
11960b57cec5SDimitry Andric /* read base register */
11970b57cec5SDimitry Andric address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + base,
11980b57cec5SDimitry Andric 0, &success);
11990b57cec5SDimitry Andric if (!success)
12000b57cec5SDimitry Andric return false;
12010b57cec5SDimitry Andric
12020b57cec5SDimitry Andric /* destination address */
12030b57cec5SDimitry Andric address = address + imm;
12040b57cec5SDimitry Andric
12050b57cec5SDimitry Andric /* Set the bad_vaddr register with base address used in the instruction */
12060b57cec5SDimitry Andric bad_vaddr_context.type = eContextInvalid;
12070b57cec5SDimitry Andric WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64,
12080b57cec5SDimitry Andric address);
12090b57cec5SDimitry Andric
12100b57cec5SDimitry Andric if (nonvolatile_reg_p(src)) {
12110b57cec5SDimitry Andric RegisterValue data_src;
1212bdd1243dSDimitry Andric std::optional<RegisterInfo> reg_info_src =
1213bdd1243dSDimitry Andric GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src);
1214bdd1243dSDimitry Andric if (!reg_info_src)
12150b57cec5SDimitry Andric return false;
12160b57cec5SDimitry Andric
12170b57cec5SDimitry Andric Context context;
12180b57cec5SDimitry Andric context.type = eContextRegisterLoad;
12190b57cec5SDimitry Andric
1220bdd1243dSDimitry Andric return WriteRegister(context, *reg_info_src, data_src);
12210b57cec5SDimitry Andric }
12220b57cec5SDimitry Andric
12230b57cec5SDimitry Andric return false;
12240b57cec5SDimitry Andric }
12250b57cec5SDimitry Andric
Emulate_LUI(llvm::MCInst & insn)12260b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_LUI(llvm::MCInst &insn) {
12270b57cec5SDimitry Andric // LUI rt, immediate
12280b57cec5SDimitry Andric // GPR[rt] <- sign_extend(immediate << 16)
12290b57cec5SDimitry Andric
12300b57cec5SDimitry Andric const uint32_t imm32 = insn.getOperand(1).getImm() << 16;
12310b57cec5SDimitry Andric int64_t imm = SignedBits(imm32, 31, 0);
12320b57cec5SDimitry Andric uint8_t rt;
12330b57cec5SDimitry Andric Context context;
12340b57cec5SDimitry Andric
12350b57cec5SDimitry Andric rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
12360b57cec5SDimitry Andric context.SetImmediateSigned(imm);
12370b57cec5SDimitry Andric context.type = eContextImmediate;
12380b57cec5SDimitry Andric
12390b57cec5SDimitry Andric return WriteRegisterUnsigned(context, eRegisterKindDWARF,
12400b57cec5SDimitry Andric dwarf_zero_mips64 + rt, imm);
12410b57cec5SDimitry Andric }
12420b57cec5SDimitry Andric
Emulate_DSUBU_DADDU(llvm::MCInst & insn)12430b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_DSUBU_DADDU(llvm::MCInst &insn) {
12440b57cec5SDimitry Andric // DSUBU sp, <src>, <rt>
12450b57cec5SDimitry Andric // DADDU sp, <src>, <rt>
12460b57cec5SDimitry Andric // DADDU dst, sp, <rt>
12470b57cec5SDimitry Andric
12480b57cec5SDimitry Andric bool success = false;
12490b57cec5SDimitry Andric uint64_t result;
12500b57cec5SDimitry Andric uint8_t src, dst, rt;
125181ad6265SDimitry Andric llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
12520b57cec5SDimitry Andric
12530b57cec5SDimitry Andric dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
12540b57cec5SDimitry Andric src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
12550b57cec5SDimitry Andric
12560b57cec5SDimitry Andric /* Check if sp is destination register */
12570b57cec5SDimitry Andric if (dst == dwarf_sp_mips64) {
12580b57cec5SDimitry Andric rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
12590b57cec5SDimitry Andric
12600b57cec5SDimitry Andric /* read <src> register */
12610b57cec5SDimitry Andric uint64_t src_opd_val = ReadRegisterUnsigned(
12620b57cec5SDimitry Andric eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
12630b57cec5SDimitry Andric if (!success)
12640b57cec5SDimitry Andric return false;
12650b57cec5SDimitry Andric
12660b57cec5SDimitry Andric /* read <rt > register */
12670b57cec5SDimitry Andric uint64_t rt_opd_val = ReadRegisterUnsigned(
12680b57cec5SDimitry Andric eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
12690b57cec5SDimitry Andric if (!success)
12700b57cec5SDimitry Andric return false;
12710b57cec5SDimitry Andric
127281ad6265SDimitry Andric if (op_name.equals_insensitive("DSUBU") ||
127381ad6265SDimitry Andric op_name.equals_insensitive("SUBU"))
12740b57cec5SDimitry Andric result = src_opd_val - rt_opd_val;
12750b57cec5SDimitry Andric else
12760b57cec5SDimitry Andric result = src_opd_val + rt_opd_val;
12770b57cec5SDimitry Andric
12780b57cec5SDimitry Andric Context context;
1279bdd1243dSDimitry Andric std::optional<RegisterInfo> reg_info_sp =
1280bdd1243dSDimitry Andric GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64);
1281bdd1243dSDimitry Andric if (reg_info_sp)
1282bdd1243dSDimitry Andric context.SetRegisterPlusOffset(*reg_info_sp, rt_opd_val);
12830b57cec5SDimitry Andric
12840b57cec5SDimitry Andric /* We are allocating bytes on stack */
12850b57cec5SDimitry Andric context.type = eContextAdjustStackPointer;
12860b57cec5SDimitry Andric
12870b57cec5SDimitry Andric WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips64, result);
12880b57cec5SDimitry Andric
12890b57cec5SDimitry Andric return true;
12900b57cec5SDimitry Andric } else if (src == dwarf_sp_mips64) {
12910b57cec5SDimitry Andric rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
12920b57cec5SDimitry Andric
12930b57cec5SDimitry Andric /* read <src> register */
12940b57cec5SDimitry Andric uint64_t src_opd_val = ReadRegisterUnsigned(
12950b57cec5SDimitry Andric eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
12960b57cec5SDimitry Andric if (!success)
12970b57cec5SDimitry Andric return false;
12980b57cec5SDimitry Andric
12990b57cec5SDimitry Andric /* read <rt> register */
13000b57cec5SDimitry Andric uint64_t rt_opd_val = ReadRegisterUnsigned(
13010b57cec5SDimitry Andric eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
13020b57cec5SDimitry Andric if (!success)
13030b57cec5SDimitry Andric return false;
13040b57cec5SDimitry Andric
13050b57cec5SDimitry Andric Context context;
13060b57cec5SDimitry Andric
130781ad6265SDimitry Andric if (op_name.equals_insensitive("DSUBU") ||
130881ad6265SDimitry Andric op_name.equals_insensitive("SUBU"))
13090b57cec5SDimitry Andric result = src_opd_val - rt_opd_val;
13100b57cec5SDimitry Andric else
13110b57cec5SDimitry Andric result = src_opd_val + rt_opd_val;
13120b57cec5SDimitry Andric
13130b57cec5SDimitry Andric context.SetImmediateSigned(result);
13140b57cec5SDimitry Andric context.type = eContextImmediate;
13150b57cec5SDimitry Andric
13160b57cec5SDimitry Andric if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
13170b57cec5SDimitry Andric dwarf_zero_mips64 + dst, result))
13180b57cec5SDimitry Andric return false;
13190b57cec5SDimitry Andric }
13200b57cec5SDimitry Andric
13210b57cec5SDimitry Andric return true;
13220b57cec5SDimitry Andric }
13230b57cec5SDimitry Andric
13240b57cec5SDimitry Andric /*
13250b57cec5SDimitry Andric Emulate below MIPS branch instructions.
13260b57cec5SDimitry Andric BEQ, BNE : Branch on condition
13270b57cec5SDimitry Andric BEQL, BNEL : Branch likely
13280b57cec5SDimitry Andric */
Emulate_BXX_3ops(llvm::MCInst & insn)13290b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_BXX_3ops(llvm::MCInst &insn) {
13300b57cec5SDimitry Andric bool success = false;
13310b57cec5SDimitry Andric uint32_t rs, rt;
13320b57cec5SDimitry Andric int64_t offset, pc, rs_val, rt_val, target = 0;
133381ad6265SDimitry Andric llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
13340b57cec5SDimitry Andric
13350b57cec5SDimitry Andric rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
13360b57cec5SDimitry Andric rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
13370b57cec5SDimitry Andric offset = insn.getOperand(2).getImm();
13380b57cec5SDimitry Andric
13390b57cec5SDimitry Andric pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
13400b57cec5SDimitry Andric if (!success)
13410b57cec5SDimitry Andric return false;
13420b57cec5SDimitry Andric
13430b57cec5SDimitry Andric rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
13440b57cec5SDimitry Andric dwarf_zero_mips64 + rs, 0, &success);
13450b57cec5SDimitry Andric if (!success)
13460b57cec5SDimitry Andric return false;
13470b57cec5SDimitry Andric
13480b57cec5SDimitry Andric rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
13490b57cec5SDimitry Andric dwarf_zero_mips64 + rt, 0, &success);
13500b57cec5SDimitry Andric if (!success)
13510b57cec5SDimitry Andric return false;
13520b57cec5SDimitry Andric
135381ad6265SDimitry Andric if (op_name.equals_insensitive("BEQ") || op_name.equals_insensitive("BEQL") ||
135481ad6265SDimitry Andric op_name.equals_insensitive("BEQ64")) {
13550b57cec5SDimitry Andric if (rs_val == rt_val)
13560b57cec5SDimitry Andric target = pc + offset;
13570b57cec5SDimitry Andric else
13580b57cec5SDimitry Andric target = pc + 8;
135981ad6265SDimitry Andric } else if (op_name.equals_insensitive("BNE") ||
136081ad6265SDimitry Andric op_name.equals_insensitive("BNEL") ||
136181ad6265SDimitry Andric op_name.equals_insensitive("BNE64")) {
13620b57cec5SDimitry Andric if (rs_val != rt_val)
13630b57cec5SDimitry Andric target = pc + offset;
13640b57cec5SDimitry Andric else
13650b57cec5SDimitry Andric target = pc + 8;
13660b57cec5SDimitry Andric }
13670b57cec5SDimitry Andric
13680b57cec5SDimitry Andric Context context;
13690b57cec5SDimitry Andric context.type = eContextRelativeBranchImmediate;
13700b57cec5SDimitry Andric context.SetImmediate(offset);
13710b57cec5SDimitry Andric
13720b57cec5SDimitry Andric return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
13730b57cec5SDimitry Andric target);
13740b57cec5SDimitry Andric }
13750b57cec5SDimitry Andric
13760b57cec5SDimitry Andric /*
13770b57cec5SDimitry Andric Emulate below MIPS Non-Compact conditional branch and link instructions.
13780b57cec5SDimitry Andric BLTZAL, BGEZAL :
13790b57cec5SDimitry Andric BLTZALL, BGEZALL : Branch likely
13800b57cec5SDimitry Andric */
Emulate_Bcond_Link(llvm::MCInst & insn)13810b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_Bcond_Link(llvm::MCInst &insn) {
13820b57cec5SDimitry Andric bool success = false;
13830b57cec5SDimitry Andric uint32_t rs;
13840b57cec5SDimitry Andric int64_t offset, pc, target = 0;
13850b57cec5SDimitry Andric int64_t rs_val;
138681ad6265SDimitry Andric llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
13870b57cec5SDimitry Andric
13880b57cec5SDimitry Andric rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
13890b57cec5SDimitry Andric offset = insn.getOperand(1).getImm();
13900b57cec5SDimitry Andric
13910b57cec5SDimitry Andric pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
13920b57cec5SDimitry Andric if (!success)
13930b57cec5SDimitry Andric return false;
13940b57cec5SDimitry Andric
13950b57cec5SDimitry Andric rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
13960b57cec5SDimitry Andric dwarf_zero_mips64 + rs, 0, &success);
13970b57cec5SDimitry Andric if (!success)
13980b57cec5SDimitry Andric return false;
13990b57cec5SDimitry Andric
140081ad6265SDimitry Andric if (op_name.equals_insensitive("BLTZAL") ||
140181ad6265SDimitry Andric op_name.equals_insensitive("BLTZALL")) {
14020b57cec5SDimitry Andric if (rs_val < 0)
14030b57cec5SDimitry Andric target = pc + offset;
14040b57cec5SDimitry Andric else
14050b57cec5SDimitry Andric target = pc + 8;
140681ad6265SDimitry Andric } else if (op_name.equals_insensitive("BGEZAL") ||
140781ad6265SDimitry Andric op_name.equals_insensitive("BGEZALL")) {
14080b57cec5SDimitry Andric if (rs_val >= 0)
14090b57cec5SDimitry Andric target = pc + offset;
14100b57cec5SDimitry Andric else
14110b57cec5SDimitry Andric target = pc + 8;
14120b57cec5SDimitry Andric }
14130b57cec5SDimitry Andric
14140b57cec5SDimitry Andric Context context;
14150b57cec5SDimitry Andric
14160b57cec5SDimitry Andric if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
14170b57cec5SDimitry Andric target))
14180b57cec5SDimitry Andric return false;
14190b57cec5SDimitry Andric
14200b57cec5SDimitry Andric if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
14210b57cec5SDimitry Andric pc + 8))
14220b57cec5SDimitry Andric return false;
14230b57cec5SDimitry Andric
14240b57cec5SDimitry Andric return true;
14250b57cec5SDimitry Andric }
14260b57cec5SDimitry Andric
Emulate_BAL(llvm::MCInst & insn)14270b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_BAL(llvm::MCInst &insn) {
14280b57cec5SDimitry Andric bool success = false;
14290b57cec5SDimitry Andric int64_t offset, pc, target;
14300b57cec5SDimitry Andric
14310b57cec5SDimitry Andric /*
14320b57cec5SDimitry Andric * BAL offset
14330b57cec5SDimitry Andric * offset = sign_ext (offset << 2)
14340b57cec5SDimitry Andric * RA = PC + 8
14350b57cec5SDimitry Andric * PC = PC + offset
14360b57cec5SDimitry Andric */
14370b57cec5SDimitry Andric offset = insn.getOperand(0).getImm();
14380b57cec5SDimitry Andric
14390b57cec5SDimitry Andric pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
14400b57cec5SDimitry Andric if (!success)
14410b57cec5SDimitry Andric return false;
14420b57cec5SDimitry Andric
14430b57cec5SDimitry Andric target = pc + offset;
14440b57cec5SDimitry Andric
14450b57cec5SDimitry Andric Context context;
14460b57cec5SDimitry Andric
14470b57cec5SDimitry Andric if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
14480b57cec5SDimitry Andric target))
14490b57cec5SDimitry Andric return false;
14500b57cec5SDimitry Andric
14510b57cec5SDimitry Andric if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
14520b57cec5SDimitry Andric pc + 8))
14530b57cec5SDimitry Andric return false;
14540b57cec5SDimitry Andric
14550b57cec5SDimitry Andric return true;
14560b57cec5SDimitry Andric }
14570b57cec5SDimitry Andric
Emulate_BALC(llvm::MCInst & insn)14580b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_BALC(llvm::MCInst &insn) {
14590b57cec5SDimitry Andric bool success = false;
14600b57cec5SDimitry Andric int64_t offset, pc, target;
14610b57cec5SDimitry Andric
14620b57cec5SDimitry Andric /*
14630b57cec5SDimitry Andric * BALC offset
14640b57cec5SDimitry Andric * offset = sign_ext (offset << 2)
14650b57cec5SDimitry Andric * RA = PC + 4
14660b57cec5SDimitry Andric * PC = PC + 4 + offset
14670b57cec5SDimitry Andric */
14680b57cec5SDimitry Andric offset = insn.getOperand(0).getImm();
14690b57cec5SDimitry Andric
14700b57cec5SDimitry Andric pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
14710b57cec5SDimitry Andric if (!success)
14720b57cec5SDimitry Andric return false;
14730b57cec5SDimitry Andric
14740b57cec5SDimitry Andric target = pc + offset;
14750b57cec5SDimitry Andric
14760b57cec5SDimitry Andric Context context;
14770b57cec5SDimitry Andric
14780b57cec5SDimitry Andric if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
14790b57cec5SDimitry Andric target))
14800b57cec5SDimitry Andric return false;
14810b57cec5SDimitry Andric
14820b57cec5SDimitry Andric if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
14830b57cec5SDimitry Andric pc + 4))
14840b57cec5SDimitry Andric return false;
14850b57cec5SDimitry Andric
14860b57cec5SDimitry Andric return true;
14870b57cec5SDimitry Andric }
14880b57cec5SDimitry Andric
14890b57cec5SDimitry Andric /*
14900b57cec5SDimitry Andric Emulate below MIPS conditional branch and link instructions.
14910b57cec5SDimitry Andric BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches
14920b57cec5SDimitry Andric */
Emulate_Bcond_Link_C(llvm::MCInst & insn)14930b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_Bcond_Link_C(llvm::MCInst &insn) {
14940b57cec5SDimitry Andric bool success = false;
14950b57cec5SDimitry Andric uint32_t rs;
14960b57cec5SDimitry Andric int64_t offset, pc, rs_val, target = 0;
149781ad6265SDimitry Andric llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
14980b57cec5SDimitry Andric
14990b57cec5SDimitry Andric rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
15000b57cec5SDimitry Andric offset = insn.getOperand(1).getImm();
15010b57cec5SDimitry Andric
15020b57cec5SDimitry Andric pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
15030b57cec5SDimitry Andric if (!success)
15040b57cec5SDimitry Andric return false;
15050b57cec5SDimitry Andric
15060b57cec5SDimitry Andric rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
15070b57cec5SDimitry Andric dwarf_zero_mips64 + rs, 0, &success);
15080b57cec5SDimitry Andric if (!success)
15090b57cec5SDimitry Andric return false;
15100b57cec5SDimitry Andric
151181ad6265SDimitry Andric if (op_name.equals_insensitive("BLEZALC")) {
15120b57cec5SDimitry Andric if (rs_val <= 0)
15130b57cec5SDimitry Andric target = pc + offset;
15140b57cec5SDimitry Andric else
15150b57cec5SDimitry Andric target = pc + 4;
151681ad6265SDimitry Andric } else if (op_name.equals_insensitive("BGEZALC")) {
15170b57cec5SDimitry Andric if (rs_val >= 0)
15180b57cec5SDimitry Andric target = pc + offset;
15190b57cec5SDimitry Andric else
15200b57cec5SDimitry Andric target = pc + 4;
152181ad6265SDimitry Andric } else if (op_name.equals_insensitive("BLTZALC")) {
15220b57cec5SDimitry Andric if (rs_val < 0)
15230b57cec5SDimitry Andric target = pc + offset;
15240b57cec5SDimitry Andric else
15250b57cec5SDimitry Andric target = pc + 4;
152681ad6265SDimitry Andric } else if (op_name.equals_insensitive("BGTZALC")) {
15270b57cec5SDimitry Andric if (rs_val > 0)
15280b57cec5SDimitry Andric target = pc + offset;
15290b57cec5SDimitry Andric else
15300b57cec5SDimitry Andric target = pc + 4;
153181ad6265SDimitry Andric } else if (op_name.equals_insensitive("BEQZALC")) {
15320b57cec5SDimitry Andric if (rs_val == 0)
15330b57cec5SDimitry Andric target = pc + offset;
15340b57cec5SDimitry Andric else
15350b57cec5SDimitry Andric target = pc + 4;
153681ad6265SDimitry Andric } else if (op_name.equals_insensitive("BNEZALC")) {
15370b57cec5SDimitry Andric if (rs_val != 0)
15380b57cec5SDimitry Andric target = pc + offset;
15390b57cec5SDimitry Andric else
15400b57cec5SDimitry Andric target = pc + 4;
15410b57cec5SDimitry Andric }
15420b57cec5SDimitry Andric
15430b57cec5SDimitry Andric Context context;
15440b57cec5SDimitry Andric
15450b57cec5SDimitry Andric if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
15460b57cec5SDimitry Andric target))
15470b57cec5SDimitry Andric return false;
15480b57cec5SDimitry Andric
15490b57cec5SDimitry Andric if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
15500b57cec5SDimitry Andric pc + 4))
15510b57cec5SDimitry Andric return false;
15520b57cec5SDimitry Andric
15530b57cec5SDimitry Andric return true;
15540b57cec5SDimitry Andric }
15550b57cec5SDimitry Andric
15560b57cec5SDimitry Andric /*
15570b57cec5SDimitry Andric Emulate below MIPS branch instructions.
15580b57cec5SDimitry Andric BLTZL, BGEZL, BGTZL, BLEZL : Branch likely
15590b57cec5SDimitry Andric BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches
15600b57cec5SDimitry Andric */
Emulate_BXX_2ops(llvm::MCInst & insn)15610b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_BXX_2ops(llvm::MCInst &insn) {
15620b57cec5SDimitry Andric bool success = false;
15630b57cec5SDimitry Andric uint32_t rs;
15640b57cec5SDimitry Andric int64_t offset, pc, rs_val, target = 0;
156581ad6265SDimitry Andric llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
15660b57cec5SDimitry Andric
15670b57cec5SDimitry Andric rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
15680b57cec5SDimitry Andric offset = insn.getOperand(1).getImm();
15690b57cec5SDimitry Andric
15700b57cec5SDimitry Andric pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
15710b57cec5SDimitry Andric if (!success)
15720b57cec5SDimitry Andric return false;
15730b57cec5SDimitry Andric
15740b57cec5SDimitry Andric rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
15750b57cec5SDimitry Andric dwarf_zero_mips64 + rs, 0, &success);
15760b57cec5SDimitry Andric if (!success)
15770b57cec5SDimitry Andric return false;
15780b57cec5SDimitry Andric
157981ad6265SDimitry Andric if (op_name.equals_insensitive("BLTZL") ||
158081ad6265SDimitry Andric op_name.equals_insensitive("BLTZ") ||
158181ad6265SDimitry Andric op_name.equals_insensitive("BLTZ64")) {
15820b57cec5SDimitry Andric if (rs_val < 0)
15830b57cec5SDimitry Andric target = pc + offset;
15840b57cec5SDimitry Andric else
15850b57cec5SDimitry Andric target = pc + 8;
158681ad6265SDimitry Andric } else if (op_name.equals_insensitive("BGEZL") ||
158781ad6265SDimitry Andric op_name.equals_insensitive("BGEZ") ||
158881ad6265SDimitry Andric op_name.equals_insensitive("BGEZ64")) {
15890b57cec5SDimitry Andric if (rs_val >= 0)
15900b57cec5SDimitry Andric target = pc + offset;
15910b57cec5SDimitry Andric else
15920b57cec5SDimitry Andric target = pc + 8;
159381ad6265SDimitry Andric } else if (op_name.equals_insensitive("BGTZL") ||
159481ad6265SDimitry Andric op_name.equals_insensitive("BGTZ") ||
159581ad6265SDimitry Andric op_name.equals_insensitive("BGTZ64")) {
15960b57cec5SDimitry Andric if (rs_val > 0)
15970b57cec5SDimitry Andric target = pc + offset;
15980b57cec5SDimitry Andric else
15990b57cec5SDimitry Andric target = pc + 8;
160081ad6265SDimitry Andric } else if (op_name.equals_insensitive("BLEZL") ||
160181ad6265SDimitry Andric op_name.equals_insensitive("BLEZ") ||
160281ad6265SDimitry Andric op_name.equals_insensitive("BLEZ64")) {
16030b57cec5SDimitry Andric if (rs_val <= 0)
16040b57cec5SDimitry Andric target = pc + offset;
16050b57cec5SDimitry Andric else
16060b57cec5SDimitry Andric target = pc + 8;
16070b57cec5SDimitry Andric }
16080b57cec5SDimitry Andric
16090b57cec5SDimitry Andric Context context;
16100b57cec5SDimitry Andric context.type = eContextRelativeBranchImmediate;
16110b57cec5SDimitry Andric context.SetImmediate(offset);
16120b57cec5SDimitry Andric
16130b57cec5SDimitry Andric return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
16140b57cec5SDimitry Andric target);
16150b57cec5SDimitry Andric }
16160b57cec5SDimitry Andric
Emulate_BC(llvm::MCInst & insn)16170b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_BC(llvm::MCInst &insn) {
16180b57cec5SDimitry Andric bool success = false;
16190b57cec5SDimitry Andric int64_t offset, pc, target;
16200b57cec5SDimitry Andric
16210b57cec5SDimitry Andric /*
16220b57cec5SDimitry Andric * BC offset
16230b57cec5SDimitry Andric * offset = sign_ext (offset << 2)
16240b57cec5SDimitry Andric * PC = PC + 4 + offset
16250b57cec5SDimitry Andric */
16260b57cec5SDimitry Andric offset = insn.getOperand(0).getImm();
16270b57cec5SDimitry Andric
16280b57cec5SDimitry Andric pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
16290b57cec5SDimitry Andric if (!success)
16300b57cec5SDimitry Andric return false;
16310b57cec5SDimitry Andric
16320b57cec5SDimitry Andric target = pc + offset;
16330b57cec5SDimitry Andric
16340b57cec5SDimitry Andric Context context;
16350b57cec5SDimitry Andric
16360b57cec5SDimitry Andric return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
16370b57cec5SDimitry Andric target);
16380b57cec5SDimitry Andric }
16390b57cec5SDimitry Andric
IsAdd64bitOverflow(int64_t a,int64_t b)16400b57cec5SDimitry Andric static int IsAdd64bitOverflow(int64_t a, int64_t b) {
16410b57cec5SDimitry Andric int64_t r = (uint64_t)a + (uint64_t)b;
16420b57cec5SDimitry Andric return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
16430b57cec5SDimitry Andric }
16440b57cec5SDimitry Andric
16450b57cec5SDimitry Andric /*
16460b57cec5SDimitry Andric Emulate below MIPS branch instructions.
16470b57cec5SDimitry Andric BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch
16480b57cec5SDimitry Andric instructions with no delay slot
16490b57cec5SDimitry Andric */
Emulate_BXX_3ops_C(llvm::MCInst & insn)16500b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_BXX_3ops_C(llvm::MCInst &insn) {
16510b57cec5SDimitry Andric bool success = false;
16520b57cec5SDimitry Andric uint32_t rs, rt;
16530b57cec5SDimitry Andric int64_t offset, pc, rs_val, rt_val, target = 0;
165481ad6265SDimitry Andric llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
16550b57cec5SDimitry Andric uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
16560b57cec5SDimitry Andric
16570b57cec5SDimitry Andric rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
16580b57cec5SDimitry Andric rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
16590b57cec5SDimitry Andric offset = insn.getOperand(2).getImm();
16600b57cec5SDimitry Andric
16610b57cec5SDimitry Andric pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
16620b57cec5SDimitry Andric if (!success)
16630b57cec5SDimitry Andric return false;
16640b57cec5SDimitry Andric
16650b57cec5SDimitry Andric rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
16660b57cec5SDimitry Andric dwarf_zero_mips64 + rs, 0, &success);
16670b57cec5SDimitry Andric if (!success)
16680b57cec5SDimitry Andric return false;
16690b57cec5SDimitry Andric
16700b57cec5SDimitry Andric rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
16710b57cec5SDimitry Andric dwarf_zero_mips64 + rt, 0, &success);
16720b57cec5SDimitry Andric if (!success)
16730b57cec5SDimitry Andric return false;
16740b57cec5SDimitry Andric
167581ad6265SDimitry Andric if (op_name.equals_insensitive("BEQC") ||
167681ad6265SDimitry Andric op_name.equals_insensitive("BEQC64")) {
16770b57cec5SDimitry Andric if (rs_val == rt_val)
16780b57cec5SDimitry Andric target = pc + offset;
16790b57cec5SDimitry Andric else
16800b57cec5SDimitry Andric target = pc + 4;
168181ad6265SDimitry Andric } else if (op_name.equals_insensitive("BNEC") ||
168281ad6265SDimitry Andric op_name.equals_insensitive("BNEC64")) {
16830b57cec5SDimitry Andric if (rs_val != rt_val)
16840b57cec5SDimitry Andric target = pc + offset;
16850b57cec5SDimitry Andric else
16860b57cec5SDimitry Andric target = pc + 4;
168781ad6265SDimitry Andric } else if (op_name.equals_insensitive("BLTC") ||
168881ad6265SDimitry Andric op_name.equals_insensitive("BLTC64")) {
16890b57cec5SDimitry Andric if (rs_val < rt_val)
16900b57cec5SDimitry Andric target = pc + offset;
16910b57cec5SDimitry Andric else
16920b57cec5SDimitry Andric target = pc + 4;
169381ad6265SDimitry Andric } else if (op_name.equals_insensitive("BGEC64") ||
169481ad6265SDimitry Andric op_name.equals_insensitive("BGEC")) {
16950b57cec5SDimitry Andric if (rs_val >= rt_val)
16960b57cec5SDimitry Andric target = pc + offset;
16970b57cec5SDimitry Andric else
16980b57cec5SDimitry Andric target = pc + 4;
169981ad6265SDimitry Andric } else if (op_name.equals_insensitive("BLTUC") ||
170081ad6265SDimitry Andric op_name.equals_insensitive("BLTUC64")) {
17010b57cec5SDimitry Andric if (rs_val < rt_val)
17020b57cec5SDimitry Andric target = pc + offset;
17030b57cec5SDimitry Andric else
17040b57cec5SDimitry Andric target = pc + 4;
170581ad6265SDimitry Andric } else if (op_name.equals_insensitive("BGEUC") ||
170681ad6265SDimitry Andric op_name.equals_insensitive("BGEUC64")) {
17070b57cec5SDimitry Andric if ((uint32_t)rs_val >= (uint32_t)rt_val)
17080b57cec5SDimitry Andric target = pc + offset;
17090b57cec5SDimitry Andric else
17100b57cec5SDimitry Andric target = pc + 4;
171181ad6265SDimitry Andric } else if (op_name.equals_insensitive("BOVC")) {
17120b57cec5SDimitry Andric if (IsAdd64bitOverflow(rs_val, rt_val))
17130b57cec5SDimitry Andric target = pc + offset;
17140b57cec5SDimitry Andric else
17150b57cec5SDimitry Andric target = pc + 4;
171681ad6265SDimitry Andric } else if (op_name.equals_insensitive("BNVC")) {
17170b57cec5SDimitry Andric if (!IsAdd64bitOverflow(rs_val, rt_val))
17180b57cec5SDimitry Andric target = pc + offset;
17190b57cec5SDimitry Andric else
17200b57cec5SDimitry Andric target = pc + 4;
17210b57cec5SDimitry Andric }
17220b57cec5SDimitry Andric
17230b57cec5SDimitry Andric Context context;
17240b57cec5SDimitry Andric context.type = eContextRelativeBranchImmediate;
17250b57cec5SDimitry Andric context.SetImmediate(current_inst_size + offset);
17260b57cec5SDimitry Andric
17270b57cec5SDimitry Andric return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
17280b57cec5SDimitry Andric target);
17290b57cec5SDimitry Andric }
17300b57cec5SDimitry Andric
17310b57cec5SDimitry Andric /*
17320b57cec5SDimitry Andric Emulate below MIPS branch instructions.
17330b57cec5SDimitry Andric BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches
17340b57cec5SDimitry Andric */
Emulate_BXX_2ops_C(llvm::MCInst & insn)17350b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_BXX_2ops_C(llvm::MCInst &insn) {
17360b57cec5SDimitry Andric bool success = false;
17370b57cec5SDimitry Andric uint32_t rs;
17380b57cec5SDimitry Andric int64_t offset, pc, target = 0;
17390b57cec5SDimitry Andric int64_t rs_val;
174081ad6265SDimitry Andric llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
17410b57cec5SDimitry Andric uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
17420b57cec5SDimitry Andric
17430b57cec5SDimitry Andric rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
17440b57cec5SDimitry Andric offset = insn.getOperand(1).getImm();
17450b57cec5SDimitry Andric
17460b57cec5SDimitry Andric pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
17470b57cec5SDimitry Andric if (!success)
17480b57cec5SDimitry Andric return false;
17490b57cec5SDimitry Andric
17500b57cec5SDimitry Andric rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
17510b57cec5SDimitry Andric dwarf_zero_mips64 + rs, 0, &success);
17520b57cec5SDimitry Andric if (!success)
17530b57cec5SDimitry Andric return false;
17540b57cec5SDimitry Andric
175581ad6265SDimitry Andric if (op_name.equals_insensitive("BLTZC") ||
175681ad6265SDimitry Andric op_name.equals_insensitive("BLTZC64")) {
17570b57cec5SDimitry Andric if (rs_val < 0)
17580b57cec5SDimitry Andric target = pc + offset;
17590b57cec5SDimitry Andric else
17600b57cec5SDimitry Andric target = pc + 4;
176181ad6265SDimitry Andric } else if (op_name.equals_insensitive("BLEZC") ||
176281ad6265SDimitry Andric op_name.equals_insensitive("BLEZC64")) {
17630b57cec5SDimitry Andric if (rs_val <= 0)
17640b57cec5SDimitry Andric target = pc + offset;
17650b57cec5SDimitry Andric else
17660b57cec5SDimitry Andric target = pc + 4;
176781ad6265SDimitry Andric } else if (op_name.equals_insensitive("BGEZC") ||
176881ad6265SDimitry Andric op_name.equals_insensitive("BGEZC64")) {
17690b57cec5SDimitry Andric if (rs_val >= 0)
17700b57cec5SDimitry Andric target = pc + offset;
17710b57cec5SDimitry Andric else
17720b57cec5SDimitry Andric target = pc + 4;
177381ad6265SDimitry Andric } else if (op_name.equals_insensitive("BGTZC") ||
177481ad6265SDimitry Andric op_name.equals_insensitive("BGTZC64")) {
17750b57cec5SDimitry Andric if (rs_val > 0)
17760b57cec5SDimitry Andric target = pc + offset;
17770b57cec5SDimitry Andric else
17780b57cec5SDimitry Andric target = pc + 4;
177981ad6265SDimitry Andric } else if (op_name.equals_insensitive("BEQZC") ||
178081ad6265SDimitry Andric op_name.equals_insensitive("BEQZC64")) {
17810b57cec5SDimitry Andric if (rs_val == 0)
17820b57cec5SDimitry Andric target = pc + offset;
17830b57cec5SDimitry Andric else
17840b57cec5SDimitry Andric target = pc + 4;
178581ad6265SDimitry Andric } else if (op_name.equals_insensitive("BNEZC") ||
178681ad6265SDimitry Andric op_name.equals_insensitive("BNEZC64")) {
17870b57cec5SDimitry Andric if (rs_val != 0)
17880b57cec5SDimitry Andric target = pc + offset;
17890b57cec5SDimitry Andric else
17900b57cec5SDimitry Andric target = pc + 4;
17910b57cec5SDimitry Andric }
17920b57cec5SDimitry Andric
17930b57cec5SDimitry Andric Context context;
17940b57cec5SDimitry Andric context.type = eContextRelativeBranchImmediate;
17950b57cec5SDimitry Andric context.SetImmediate(current_inst_size + offset);
17960b57cec5SDimitry Andric
17970b57cec5SDimitry Andric return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
17980b57cec5SDimitry Andric target);
17990b57cec5SDimitry Andric }
18000b57cec5SDimitry Andric
Emulate_J(llvm::MCInst & insn)18010b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_J(llvm::MCInst &insn) {
18020b57cec5SDimitry Andric bool success = false;
18030b57cec5SDimitry Andric uint64_t offset, pc;
18040b57cec5SDimitry Andric
18050b57cec5SDimitry Andric /*
18060b57cec5SDimitry Andric * J offset
18070b57cec5SDimitry Andric * offset = sign_ext (offset << 2)
18080b57cec5SDimitry Andric * PC = PC[63-28] | offset
18090b57cec5SDimitry Andric */
18100b57cec5SDimitry Andric offset = insn.getOperand(0).getImm();
18110b57cec5SDimitry Andric
18120b57cec5SDimitry Andric pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
18130b57cec5SDimitry Andric if (!success)
18140b57cec5SDimitry Andric return false;
18150b57cec5SDimitry Andric
18160b57cec5SDimitry Andric /* This is a PC-region branch and not PC-relative */
18170b57cec5SDimitry Andric pc = (pc & 0xFFFFFFFFF0000000ULL) | offset;
18180b57cec5SDimitry Andric
18190b57cec5SDimitry Andric Context context;
18200b57cec5SDimitry Andric
18210b57cec5SDimitry Andric return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
18220b57cec5SDimitry Andric pc);
18230b57cec5SDimitry Andric }
18240b57cec5SDimitry Andric
Emulate_JAL(llvm::MCInst & insn)18250b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_JAL(llvm::MCInst &insn) {
18260b57cec5SDimitry Andric bool success = false;
18270b57cec5SDimitry Andric uint64_t offset, target, pc;
18280b57cec5SDimitry Andric
18290b57cec5SDimitry Andric /*
18300b57cec5SDimitry Andric * JAL offset
18310b57cec5SDimitry Andric * offset = sign_ext (offset << 2)
18320b57cec5SDimitry Andric * PC = PC[63-28] | offset
18330b57cec5SDimitry Andric */
18340b57cec5SDimitry Andric offset = insn.getOperand(0).getImm();
18350b57cec5SDimitry Andric
18360b57cec5SDimitry Andric pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
18370b57cec5SDimitry Andric if (!success)
18380b57cec5SDimitry Andric return false;
18390b57cec5SDimitry Andric
18400b57cec5SDimitry Andric /* This is a PC-region branch and not PC-relative */
18410b57cec5SDimitry Andric target = (pc & 0xFFFFFFFFF0000000ULL) | offset;
18420b57cec5SDimitry Andric
18430b57cec5SDimitry Andric Context context;
18440b57cec5SDimitry Andric
18450b57cec5SDimitry Andric if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
18460b57cec5SDimitry Andric target))
18470b57cec5SDimitry Andric return false;
18480b57cec5SDimitry Andric
18490b57cec5SDimitry Andric if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
18500b57cec5SDimitry Andric pc + 8))
18510b57cec5SDimitry Andric return false;
18520b57cec5SDimitry Andric
18530b57cec5SDimitry Andric return true;
18540b57cec5SDimitry Andric }
18550b57cec5SDimitry Andric
Emulate_JALR(llvm::MCInst & insn)18560b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_JALR(llvm::MCInst &insn) {
18570b57cec5SDimitry Andric bool success = false;
18580b57cec5SDimitry Andric uint32_t rs, rt;
18590b57cec5SDimitry Andric uint64_t pc, rs_val;
18600b57cec5SDimitry Andric
18610b57cec5SDimitry Andric /*
18620b57cec5SDimitry Andric * JALR rt, rs
18630b57cec5SDimitry Andric * GPR[rt] = PC + 8
18640b57cec5SDimitry Andric * PC = GPR[rs]
18650b57cec5SDimitry Andric */
18660b57cec5SDimitry Andric rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
18670b57cec5SDimitry Andric rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
18680b57cec5SDimitry Andric
18690b57cec5SDimitry Andric pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
18700b57cec5SDimitry Andric if (!success)
18710b57cec5SDimitry Andric return false;
18720b57cec5SDimitry Andric
18730b57cec5SDimitry Andric rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0,
18740b57cec5SDimitry Andric &success);
18750b57cec5SDimitry Andric if (!success)
18760b57cec5SDimitry Andric return false;
18770b57cec5SDimitry Andric
18780b57cec5SDimitry Andric Context context;
18790b57cec5SDimitry Andric
18800b57cec5SDimitry Andric if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
18810b57cec5SDimitry Andric rs_val))
18820b57cec5SDimitry Andric return false;
18830b57cec5SDimitry Andric
18840b57cec5SDimitry Andric if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
18850b57cec5SDimitry Andric dwarf_zero_mips64 + rt, pc + 8))
18860b57cec5SDimitry Andric return false;
18870b57cec5SDimitry Andric
18880b57cec5SDimitry Andric return true;
18890b57cec5SDimitry Andric }
18900b57cec5SDimitry Andric
Emulate_JIALC(llvm::MCInst & insn)18910b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_JIALC(llvm::MCInst &insn) {
18920b57cec5SDimitry Andric bool success = false;
18930b57cec5SDimitry Andric uint32_t rt;
18940b57cec5SDimitry Andric int64_t target, offset, pc, rt_val;
18950b57cec5SDimitry Andric
18960b57cec5SDimitry Andric /*
18970b57cec5SDimitry Andric * JIALC rt, offset
18980b57cec5SDimitry Andric * offset = sign_ext (offset)
18990b57cec5SDimitry Andric * PC = GPR[rt] + offset
19000b57cec5SDimitry Andric * RA = PC + 4
19010b57cec5SDimitry Andric */
19020b57cec5SDimitry Andric rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
19030b57cec5SDimitry Andric offset = insn.getOperand(1).getImm();
19040b57cec5SDimitry Andric
19050b57cec5SDimitry Andric pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
19060b57cec5SDimitry Andric if (!success)
19070b57cec5SDimitry Andric return false;
19080b57cec5SDimitry Andric
19090b57cec5SDimitry Andric rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
19100b57cec5SDimitry Andric dwarf_zero_mips64 + rt, 0, &success);
19110b57cec5SDimitry Andric if (!success)
19120b57cec5SDimitry Andric return false;
19130b57cec5SDimitry Andric
19140b57cec5SDimitry Andric target = rt_val + offset;
19150b57cec5SDimitry Andric
19160b57cec5SDimitry Andric Context context;
19170b57cec5SDimitry Andric
19180b57cec5SDimitry Andric if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
19190b57cec5SDimitry Andric target))
19200b57cec5SDimitry Andric return false;
19210b57cec5SDimitry Andric
19220b57cec5SDimitry Andric if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
19230b57cec5SDimitry Andric pc + 4))
19240b57cec5SDimitry Andric return false;
19250b57cec5SDimitry Andric
19260b57cec5SDimitry Andric return true;
19270b57cec5SDimitry Andric }
19280b57cec5SDimitry Andric
Emulate_JIC(llvm::MCInst & insn)19290b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_JIC(llvm::MCInst &insn) {
19300b57cec5SDimitry Andric bool success = false;
19310b57cec5SDimitry Andric uint32_t rt;
19320b57cec5SDimitry Andric int64_t target, offset, rt_val;
19330b57cec5SDimitry Andric
19340b57cec5SDimitry Andric /*
19350b57cec5SDimitry Andric * JIC rt, offset
19360b57cec5SDimitry Andric * offset = sign_ext (offset)
19370b57cec5SDimitry Andric * PC = GPR[rt] + offset
19380b57cec5SDimitry Andric */
19390b57cec5SDimitry Andric rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
19400b57cec5SDimitry Andric offset = insn.getOperand(1).getImm();
19410b57cec5SDimitry Andric
19420b57cec5SDimitry Andric rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
19430b57cec5SDimitry Andric dwarf_zero_mips64 + rt, 0, &success);
19440b57cec5SDimitry Andric if (!success)
19450b57cec5SDimitry Andric return false;
19460b57cec5SDimitry Andric
19470b57cec5SDimitry Andric target = rt_val + offset;
19480b57cec5SDimitry Andric
19490b57cec5SDimitry Andric Context context;
19500b57cec5SDimitry Andric
19510b57cec5SDimitry Andric return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
19520b57cec5SDimitry Andric target);
19530b57cec5SDimitry Andric }
19540b57cec5SDimitry Andric
Emulate_JR(llvm::MCInst & insn)19550b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_JR(llvm::MCInst &insn) {
19560b57cec5SDimitry Andric bool success = false;
19570b57cec5SDimitry Andric uint32_t rs;
19580b57cec5SDimitry Andric uint64_t rs_val;
19590b57cec5SDimitry Andric
19600b57cec5SDimitry Andric /*
19610b57cec5SDimitry Andric * JR rs
19620b57cec5SDimitry Andric * PC = GPR[rs]
19630b57cec5SDimitry Andric */
19640b57cec5SDimitry Andric rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
19650b57cec5SDimitry Andric
19660b57cec5SDimitry Andric rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0,
19670b57cec5SDimitry Andric &success);
19680b57cec5SDimitry Andric if (!success)
19690b57cec5SDimitry Andric return false;
19700b57cec5SDimitry Andric
19710b57cec5SDimitry Andric Context context;
19720b57cec5SDimitry Andric
19730b57cec5SDimitry Andric return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
19740b57cec5SDimitry Andric rs_val);
19750b57cec5SDimitry Andric }
19760b57cec5SDimitry Andric
19770b57cec5SDimitry Andric /*
19780b57cec5SDimitry Andric Emulate Branch on FP True/False
19790b57cec5SDimitry Andric BC1F, BC1FL : Branch on FP False (L stands for branch likely)
19800b57cec5SDimitry Andric BC1T, BC1TL : Branch on FP True (L stands for branch likely)
19810b57cec5SDimitry Andric */
Emulate_FP_branch(llvm::MCInst & insn)19820b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_FP_branch(llvm::MCInst &insn) {
19830b57cec5SDimitry Andric bool success = false;
19840b57cec5SDimitry Andric uint32_t cc, fcsr;
19850b57cec5SDimitry Andric int64_t pc, offset, target = 0;
198681ad6265SDimitry Andric llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
19870b57cec5SDimitry Andric
19880b57cec5SDimitry Andric /*
19890b57cec5SDimitry Andric * BC1F cc, offset
19900b57cec5SDimitry Andric * condition <- (FPConditionCode(cc) == 0)
19910b57cec5SDimitry Andric * if condition then
19920b57cec5SDimitry Andric * offset = sign_ext (offset)
19930b57cec5SDimitry Andric * PC = PC + offset
19940b57cec5SDimitry Andric */
19950b57cec5SDimitry Andric cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
19960b57cec5SDimitry Andric offset = insn.getOperand(1).getImm();
19970b57cec5SDimitry Andric
19980b57cec5SDimitry Andric pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
19990b57cec5SDimitry Andric if (!success)
20000b57cec5SDimitry Andric return false;
20010b57cec5SDimitry Andric
20020b57cec5SDimitry Andric fcsr =
20030b57cec5SDimitry Andric ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
20040b57cec5SDimitry Andric if (!success)
20050b57cec5SDimitry Andric return false;
20060b57cec5SDimitry Andric
20070b57cec5SDimitry Andric /* fcsr[23], fcsr[25-31] are vaild condition bits */
20080b57cec5SDimitry Andric fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
20090b57cec5SDimitry Andric
201081ad6265SDimitry Andric if (op_name.equals_insensitive("BC1F") ||
201181ad6265SDimitry Andric op_name.equals_insensitive("BC1FL")) {
20120b57cec5SDimitry Andric if ((fcsr & (1 << cc)) == 0)
20130b57cec5SDimitry Andric target = pc + offset;
20140b57cec5SDimitry Andric else
20150b57cec5SDimitry Andric target = pc + 8;
201681ad6265SDimitry Andric } else if (op_name.equals_insensitive("BC1T") ||
201781ad6265SDimitry Andric op_name.equals_insensitive("BC1TL")) {
20180b57cec5SDimitry Andric if ((fcsr & (1 << cc)) != 0)
20190b57cec5SDimitry Andric target = pc + offset;
20200b57cec5SDimitry Andric else
20210b57cec5SDimitry Andric target = pc + 8;
20220b57cec5SDimitry Andric }
20230b57cec5SDimitry Andric
20240b57cec5SDimitry Andric Context context;
20250b57cec5SDimitry Andric
20260b57cec5SDimitry Andric return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
20270b57cec5SDimitry Andric target);
20280b57cec5SDimitry Andric }
20290b57cec5SDimitry Andric
Emulate_BC1EQZ(llvm::MCInst & insn)20300b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_BC1EQZ(llvm::MCInst &insn) {
20310b57cec5SDimitry Andric bool success = false;
20320b57cec5SDimitry Andric uint32_t ft;
20330b57cec5SDimitry Andric uint64_t ft_val;
20340b57cec5SDimitry Andric int64_t target, pc, offset;
20350b57cec5SDimitry Andric
20360b57cec5SDimitry Andric /*
20370b57cec5SDimitry Andric * BC1EQZ ft, offset
20380b57cec5SDimitry Andric * condition <- (FPR[ft].bit0 == 0)
20390b57cec5SDimitry Andric * if condition then
20400b57cec5SDimitry Andric * offset = sign_ext (offset)
20410b57cec5SDimitry Andric * PC = PC + 4 + offset
20420b57cec5SDimitry Andric */
20430b57cec5SDimitry Andric ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
20440b57cec5SDimitry Andric offset = insn.getOperand(1).getImm();
20450b57cec5SDimitry Andric
20460b57cec5SDimitry Andric pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
20470b57cec5SDimitry Andric if (!success)
20480b57cec5SDimitry Andric return false;
20490b57cec5SDimitry Andric
20500b57cec5SDimitry Andric ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0,
20510b57cec5SDimitry Andric &success);
20520b57cec5SDimitry Andric if (!success)
20530b57cec5SDimitry Andric return false;
20540b57cec5SDimitry Andric
20550b57cec5SDimitry Andric if ((ft_val & 1) == 0)
20560b57cec5SDimitry Andric target = pc + 4 + offset;
20570b57cec5SDimitry Andric else
20580b57cec5SDimitry Andric target = pc + 8;
20590b57cec5SDimitry Andric
20600b57cec5SDimitry Andric Context context;
20610b57cec5SDimitry Andric
20620b57cec5SDimitry Andric return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
20630b57cec5SDimitry Andric target);
20640b57cec5SDimitry Andric }
20650b57cec5SDimitry Andric
Emulate_BC1NEZ(llvm::MCInst & insn)20660b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_BC1NEZ(llvm::MCInst &insn) {
20670b57cec5SDimitry Andric bool success = false;
20680b57cec5SDimitry Andric uint32_t ft;
20690b57cec5SDimitry Andric uint64_t ft_val;
20700b57cec5SDimitry Andric int64_t target, pc, offset;
20710b57cec5SDimitry Andric
20720b57cec5SDimitry Andric /*
20730b57cec5SDimitry Andric * BC1NEZ ft, offset
20740b57cec5SDimitry Andric * condition <- (FPR[ft].bit0 != 0)
20750b57cec5SDimitry Andric * if condition then
20760b57cec5SDimitry Andric * offset = sign_ext (offset)
20770b57cec5SDimitry Andric * PC = PC + 4 + offset
20780b57cec5SDimitry Andric */
20790b57cec5SDimitry Andric ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
20800b57cec5SDimitry Andric offset = insn.getOperand(1).getImm();
20810b57cec5SDimitry Andric
20820b57cec5SDimitry Andric pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
20830b57cec5SDimitry Andric if (!success)
20840b57cec5SDimitry Andric return false;
20850b57cec5SDimitry Andric
20860b57cec5SDimitry Andric ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0,
20870b57cec5SDimitry Andric &success);
20880b57cec5SDimitry Andric if (!success)
20890b57cec5SDimitry Andric return false;
20900b57cec5SDimitry Andric
20910b57cec5SDimitry Andric if ((ft_val & 1) != 0)
20920b57cec5SDimitry Andric target = pc + 4 + offset;
20930b57cec5SDimitry Andric else
20940b57cec5SDimitry Andric target = pc + 8;
20950b57cec5SDimitry Andric
20960b57cec5SDimitry Andric Context context;
20970b57cec5SDimitry Andric
20980b57cec5SDimitry Andric return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
20990b57cec5SDimitry Andric target);
21000b57cec5SDimitry Andric }
21010b57cec5SDimitry Andric
21020b57cec5SDimitry Andric /*
21030b57cec5SDimitry Andric Emulate MIPS-3D Branch instructions
21040b57cec5SDimitry Andric BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes
21050b57cec5SDimitry Andric False/True
21060b57cec5SDimitry Andric BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes
21070b57cec5SDimitry Andric False/True
21080b57cec5SDimitry Andric */
Emulate_3D_branch(llvm::MCInst & insn)21090b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_3D_branch(llvm::MCInst &insn) {
21100b57cec5SDimitry Andric bool success = false;
21110b57cec5SDimitry Andric uint32_t cc, fcsr;
21120b57cec5SDimitry Andric int64_t pc, offset, target = 0;
211381ad6265SDimitry Andric llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
21140b57cec5SDimitry Andric
21150b57cec5SDimitry Andric cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
21160b57cec5SDimitry Andric offset = insn.getOperand(1).getImm();
21170b57cec5SDimitry Andric
21180b57cec5SDimitry Andric pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
21190b57cec5SDimitry Andric if (!success)
21200b57cec5SDimitry Andric return false;
21210b57cec5SDimitry Andric
21220b57cec5SDimitry Andric fcsr = (uint32_t)ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips64,
21230b57cec5SDimitry Andric 0, &success);
21240b57cec5SDimitry Andric if (!success)
21250b57cec5SDimitry Andric return false;
21260b57cec5SDimitry Andric
21270b57cec5SDimitry Andric /* fcsr[23], fcsr[25-31] are vaild condition bits */
21280b57cec5SDimitry Andric fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
21290b57cec5SDimitry Andric
213081ad6265SDimitry Andric if (op_name.equals_insensitive("BC1ANY2F")) {
21310b57cec5SDimitry Andric /* if any one bit is 0 */
21320b57cec5SDimitry Andric if (((fcsr >> cc) & 3) != 3)
21330b57cec5SDimitry Andric target = pc + offset;
21340b57cec5SDimitry Andric else
21350b57cec5SDimitry Andric target = pc + 8;
213681ad6265SDimitry Andric } else if (op_name.equals_insensitive("BC1ANY2T")) {
21370b57cec5SDimitry Andric /* if any one bit is 1 */
21380b57cec5SDimitry Andric if (((fcsr >> cc) & 3) != 0)
21390b57cec5SDimitry Andric target = pc + offset;
21400b57cec5SDimitry Andric else
21410b57cec5SDimitry Andric target = pc + 8;
214281ad6265SDimitry Andric } else if (op_name.equals_insensitive("BC1ANY4F")) {
21430b57cec5SDimitry Andric /* if any one bit is 0 */
21440b57cec5SDimitry Andric if (((fcsr >> cc) & 0xf) != 0xf)
21450b57cec5SDimitry Andric target = pc + offset;
21460b57cec5SDimitry Andric else
21470b57cec5SDimitry Andric target = pc + 8;
214881ad6265SDimitry Andric } else if (op_name.equals_insensitive("BC1ANY4T")) {
21490b57cec5SDimitry Andric /* if any one bit is 1 */
21500b57cec5SDimitry Andric if (((fcsr >> cc) & 0xf) != 0)
21510b57cec5SDimitry Andric target = pc + offset;
21520b57cec5SDimitry Andric else
21530b57cec5SDimitry Andric target = pc + 8;
21540b57cec5SDimitry Andric }
21550b57cec5SDimitry Andric
21560b57cec5SDimitry Andric Context context;
21570b57cec5SDimitry Andric
21580b57cec5SDimitry Andric return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
21590b57cec5SDimitry Andric target);
21600b57cec5SDimitry Andric }
21610b57cec5SDimitry Andric
Emulate_BNZB(llvm::MCInst & insn)21620b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_BNZB(llvm::MCInst &insn) {
21630b57cec5SDimitry Andric return Emulate_MSA_Branch_DF(insn, 1, true);
21640b57cec5SDimitry Andric }
21650b57cec5SDimitry Andric
Emulate_BNZH(llvm::MCInst & insn)21660b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_BNZH(llvm::MCInst &insn) {
21670b57cec5SDimitry Andric return Emulate_MSA_Branch_DF(insn, 2, true);
21680b57cec5SDimitry Andric }
21690b57cec5SDimitry Andric
Emulate_BNZW(llvm::MCInst & insn)21700b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_BNZW(llvm::MCInst &insn) {
21710b57cec5SDimitry Andric return Emulate_MSA_Branch_DF(insn, 4, true);
21720b57cec5SDimitry Andric }
21730b57cec5SDimitry Andric
Emulate_BNZD(llvm::MCInst & insn)21740b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_BNZD(llvm::MCInst &insn) {
21750b57cec5SDimitry Andric return Emulate_MSA_Branch_DF(insn, 8, true);
21760b57cec5SDimitry Andric }
21770b57cec5SDimitry Andric
Emulate_BZB(llvm::MCInst & insn)21780b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_BZB(llvm::MCInst &insn) {
21790b57cec5SDimitry Andric return Emulate_MSA_Branch_DF(insn, 1, false);
21800b57cec5SDimitry Andric }
21810b57cec5SDimitry Andric
Emulate_BZH(llvm::MCInst & insn)21820b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_BZH(llvm::MCInst &insn) {
21830b57cec5SDimitry Andric return Emulate_MSA_Branch_DF(insn, 2, false);
21840b57cec5SDimitry Andric }
21850b57cec5SDimitry Andric
Emulate_BZW(llvm::MCInst & insn)21860b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_BZW(llvm::MCInst &insn) {
21870b57cec5SDimitry Andric return Emulate_MSA_Branch_DF(insn, 4, false);
21880b57cec5SDimitry Andric }
21890b57cec5SDimitry Andric
Emulate_BZD(llvm::MCInst & insn)21900b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_BZD(llvm::MCInst &insn) {
21910b57cec5SDimitry Andric return Emulate_MSA_Branch_DF(insn, 8, false);
21920b57cec5SDimitry Andric }
21930b57cec5SDimitry Andric
Emulate_MSA_Branch_DF(llvm::MCInst & insn,int element_byte_size,bool bnz)21940b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_MSA_Branch_DF(llvm::MCInst &insn,
21950b57cec5SDimitry Andric int element_byte_size,
21960b57cec5SDimitry Andric bool bnz) {
21970b57cec5SDimitry Andric bool success = false, branch_hit = true;
21980b57cec5SDimitry Andric int64_t target = 0;
21990b57cec5SDimitry Andric RegisterValue reg_value;
22000b57cec5SDimitry Andric const uint8_t *ptr = nullptr;
22010b57cec5SDimitry Andric
22020b57cec5SDimitry Andric uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
22030b57cec5SDimitry Andric int64_t offset = insn.getOperand(1).getImm();
22040b57cec5SDimitry Andric
22050b57cec5SDimitry Andric int64_t pc =
22060b57cec5SDimitry Andric ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
22070b57cec5SDimitry Andric if (!success)
22080b57cec5SDimitry Andric return false;
22090b57cec5SDimitry Andric
22100b57cec5SDimitry Andric if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value))
22110b57cec5SDimitry Andric ptr = (const uint8_t *)reg_value.GetBytes();
22120b57cec5SDimitry Andric else
22130b57cec5SDimitry Andric return false;
22140b57cec5SDimitry Andric
22150b57cec5SDimitry Andric for (int i = 0; i < 16 / element_byte_size; i++) {
22160b57cec5SDimitry Andric switch (element_byte_size) {
22170b57cec5SDimitry Andric case 1:
22180b57cec5SDimitry Andric if ((*ptr == 0 && bnz) || (*ptr != 0 && !bnz))
22190b57cec5SDimitry Andric branch_hit = false;
22200b57cec5SDimitry Andric break;
22210b57cec5SDimitry Andric case 2:
22220b57cec5SDimitry Andric if ((*(const uint16_t *)ptr == 0 && bnz) ||
22230b57cec5SDimitry Andric (*(const uint16_t *)ptr != 0 && !bnz))
22240b57cec5SDimitry Andric branch_hit = false;
22250b57cec5SDimitry Andric break;
22260b57cec5SDimitry Andric case 4:
22270b57cec5SDimitry Andric if ((*(const uint32_t *)ptr == 0 && bnz) ||
22280b57cec5SDimitry Andric (*(const uint32_t *)ptr != 0 && !bnz))
22290b57cec5SDimitry Andric branch_hit = false;
22300b57cec5SDimitry Andric break;
22310b57cec5SDimitry Andric case 8:
22320b57cec5SDimitry Andric if ((*(const uint64_t *)ptr == 0 && bnz) ||
22330b57cec5SDimitry Andric (*(const uint64_t *)ptr != 0 && !bnz))
22340b57cec5SDimitry Andric branch_hit = false;
22350b57cec5SDimitry Andric break;
22360b57cec5SDimitry Andric }
22370b57cec5SDimitry Andric if (!branch_hit)
22380b57cec5SDimitry Andric break;
22390b57cec5SDimitry Andric ptr = ptr + element_byte_size;
22400b57cec5SDimitry Andric }
22410b57cec5SDimitry Andric
22420b57cec5SDimitry Andric if (branch_hit)
22430b57cec5SDimitry Andric target = pc + offset;
22440b57cec5SDimitry Andric else
22450b57cec5SDimitry Andric target = pc + 8;
22460b57cec5SDimitry Andric
22470b57cec5SDimitry Andric Context context;
22480b57cec5SDimitry Andric context.type = eContextRelativeBranchImmediate;
22490b57cec5SDimitry Andric
22500b57cec5SDimitry Andric return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
22510b57cec5SDimitry Andric target);
22520b57cec5SDimitry Andric }
22530b57cec5SDimitry Andric
Emulate_BNZV(llvm::MCInst & insn)22540b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_BNZV(llvm::MCInst &insn) {
22550b57cec5SDimitry Andric return Emulate_MSA_Branch_V(insn, true);
22560b57cec5SDimitry Andric }
22570b57cec5SDimitry Andric
Emulate_BZV(llvm::MCInst & insn)22580b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_BZV(llvm::MCInst &insn) {
22590b57cec5SDimitry Andric return Emulate_MSA_Branch_V(insn, false);
22600b57cec5SDimitry Andric }
22610b57cec5SDimitry Andric
Emulate_MSA_Branch_V(llvm::MCInst & insn,bool bnz)22620b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_MSA_Branch_V(llvm::MCInst &insn,
22630b57cec5SDimitry Andric bool bnz) {
22640b57cec5SDimitry Andric bool success = false;
22650b57cec5SDimitry Andric int64_t target = 0;
2266349cc55cSDimitry Andric llvm::APInt wr_val = llvm::APInt::getZero(128);
22670b57cec5SDimitry Andric llvm::APInt fail_value = llvm::APInt::getMaxValue(128);
2268349cc55cSDimitry Andric llvm::APInt zero_value = llvm::APInt::getZero(128);
22690b57cec5SDimitry Andric RegisterValue reg_value;
22700b57cec5SDimitry Andric
22710b57cec5SDimitry Andric uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
22720b57cec5SDimitry Andric int64_t offset = insn.getOperand(1).getImm();
22730b57cec5SDimitry Andric
22740b57cec5SDimitry Andric int64_t pc =
22750b57cec5SDimitry Andric ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
22760b57cec5SDimitry Andric if (!success)
22770b57cec5SDimitry Andric return false;
22780b57cec5SDimitry Andric
22790b57cec5SDimitry Andric if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value))
22800b57cec5SDimitry Andric wr_val = reg_value.GetAsUInt128(fail_value);
22810b57cec5SDimitry Andric else
22820b57cec5SDimitry Andric return false;
22830b57cec5SDimitry Andric
22840b57cec5SDimitry Andric if ((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) ||
22850b57cec5SDimitry Andric (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz))
22860b57cec5SDimitry Andric target = pc + offset;
22870b57cec5SDimitry Andric else
22880b57cec5SDimitry Andric target = pc + 8;
22890b57cec5SDimitry Andric
22900b57cec5SDimitry Andric Context context;
22910b57cec5SDimitry Andric context.type = eContextRelativeBranchImmediate;
22920b57cec5SDimitry Andric
22930b57cec5SDimitry Andric return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
22940b57cec5SDimitry Andric target);
22950b57cec5SDimitry Andric }
22960b57cec5SDimitry Andric
Emulate_LDST_Imm(llvm::MCInst & insn)22970b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_LDST_Imm(llvm::MCInst &insn) {
22980b57cec5SDimitry Andric bool success = false;
22990b57cec5SDimitry Andric uint32_t base;
23000b57cec5SDimitry Andric int64_t imm, address;
23010b57cec5SDimitry Andric Context bad_vaddr_context;
23020b57cec5SDimitry Andric
23030b57cec5SDimitry Andric uint32_t num_operands = insn.getNumOperands();
23040b57cec5SDimitry Andric base =
23050b57cec5SDimitry Andric m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
23060b57cec5SDimitry Andric imm = insn.getOperand(num_operands - 1).getImm();
23070b57cec5SDimitry Andric
2308bdd1243dSDimitry Andric if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))
23090b57cec5SDimitry Andric return false;
23100b57cec5SDimitry Andric
23110b57cec5SDimitry Andric /* read base register */
23120b57cec5SDimitry Andric address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0,
23130b57cec5SDimitry Andric &success);
23140b57cec5SDimitry Andric if (!success)
23150b57cec5SDimitry Andric return false;
23160b57cec5SDimitry Andric
23170b57cec5SDimitry Andric /* destination address */
23180b57cec5SDimitry Andric address = address + imm;
23190b57cec5SDimitry Andric
23200b57cec5SDimitry Andric /* Set the bad_vaddr register with base address used in the instruction */
23210b57cec5SDimitry Andric bad_vaddr_context.type = eContextInvalid;
23220b57cec5SDimitry Andric WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
23230b57cec5SDimitry Andric address);
23240b57cec5SDimitry Andric
23250b57cec5SDimitry Andric return true;
23260b57cec5SDimitry Andric }
23270b57cec5SDimitry Andric
Emulate_LDST_Reg(llvm::MCInst & insn)23280b57cec5SDimitry Andric bool EmulateInstructionMIPS64::Emulate_LDST_Reg(llvm::MCInst &insn) {
23290b57cec5SDimitry Andric bool success = false;
23300b57cec5SDimitry Andric uint32_t base, index;
23310b57cec5SDimitry Andric int64_t address, index_address;
23320b57cec5SDimitry Andric Context bad_vaddr_context;
23330b57cec5SDimitry Andric
23340b57cec5SDimitry Andric uint32_t num_operands = insn.getNumOperands();
23350b57cec5SDimitry Andric base =
23360b57cec5SDimitry Andric m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
23370b57cec5SDimitry Andric index =
23380b57cec5SDimitry Andric m_reg_info->getEncodingValue(insn.getOperand(num_operands - 1).getReg());
23390b57cec5SDimitry Andric
2340bdd1243dSDimitry Andric if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))
23410b57cec5SDimitry Andric return false;
23420b57cec5SDimitry Andric
2343bdd1243dSDimitry Andric if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + index))
23440b57cec5SDimitry Andric return false;
23450b57cec5SDimitry Andric
23460b57cec5SDimitry Andric /* read base register */
23470b57cec5SDimitry Andric address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0,
23480b57cec5SDimitry Andric &success);
23490b57cec5SDimitry Andric if (!success)
23500b57cec5SDimitry Andric return false;
23510b57cec5SDimitry Andric
23520b57cec5SDimitry Andric /* read index register */
23530b57cec5SDimitry Andric index_address = ReadRegisterUnsigned(eRegisterKindDWARF,
23540b57cec5SDimitry Andric dwarf_zero_mips + index, 0, &success);
23550b57cec5SDimitry Andric if (!success)
23560b57cec5SDimitry Andric return false;
23570b57cec5SDimitry Andric
23580b57cec5SDimitry Andric /* destination address */
23590b57cec5SDimitry Andric address = address + index_address;
23600b57cec5SDimitry Andric
23610b57cec5SDimitry Andric /* Set the bad_vaddr register with base address used in the instruction */
23620b57cec5SDimitry Andric bad_vaddr_context.type = eContextInvalid;
23630b57cec5SDimitry Andric WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
23640b57cec5SDimitry Andric address);
23650b57cec5SDimitry Andric
23660b57cec5SDimitry Andric return true;
23670b57cec5SDimitry Andric }
2368