xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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(&reg_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