xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
15ffd83dbSDimitry Andric //===-- EmulateInstructionMIPS.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 "EmulateInstructionMIPS.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/Symbol/UnwindPlan.h"
180b57cec5SDimitry Andric #include "lldb/Target/Target.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(EmulateInstructionMIPS,InstructionMIPS)445ffd83dbSDimitry Andric LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionMIPS, InstructionMIPS)
455ffd83dbSDimitry Andric 
460b57cec5SDimitry Andric #define UInt(x) ((uint64_t)x)
470b57cec5SDimitry Andric #define integer int64_t
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric //
500b57cec5SDimitry Andric // EmulateInstructionMIPS 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 
EmulateInstructionMIPS(const lldb_private::ArchSpec & arch)630b57cec5SDimitry Andric EmulateInstructionMIPS::EmulateInstructionMIPS(
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 
1500b57cec5SDimitry Andric   m_reg_info.reset(target->createMCRegInfo(triple.getTriple()));
1510b57cec5SDimitry Andric   assert(m_reg_info.get());
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric   m_insn_info.reset(target->createMCInstrInfo());
1540b57cec5SDimitry Andric   assert(m_insn_info.get());
1550b57cec5SDimitry Andric 
156480093f4SDimitry Andric   llvm::MCTargetOptions MCOptions;
157480093f4SDimitry Andric   m_asm_info.reset(
158480093f4SDimitry Andric       target->createMCAsmInfo(*m_reg_info, triple.getTriple(), MCOptions));
1590b57cec5SDimitry Andric   m_subtype_info.reset(
1600b57cec5SDimitry Andric       target->createMCSubtargetInfo(triple.getTriple(), cpu, features));
1610b57cec5SDimitry Andric   assert(m_asm_info.get() && m_subtype_info.get());
1620b57cec5SDimitry Andric 
163fe6060f1SDimitry Andric   m_context = std::make_unique<llvm::MCContext>(
164fe6060f1SDimitry Andric       triple, m_asm_info.get(), m_reg_info.get(), m_subtype_info.get());
1650b57cec5SDimitry Andric   assert(m_context.get());
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric   m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context));
1680b57cec5SDimitry Andric   assert(m_disasm.get());
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric   /* Create alternate disassembler for microMIPS */
1710b57cec5SDimitry Andric   if (arch_flags & ArchSpec::eMIPSAse_mips16)
1720b57cec5SDimitry Andric     features += "+mips16,";
1730b57cec5SDimitry Andric   else if (arch_flags & ArchSpec::eMIPSAse_micromips)
1740b57cec5SDimitry Andric     features += "+micromips,";
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric   m_alt_subtype_info.reset(
1770b57cec5SDimitry Andric       target->createMCSubtargetInfo(triple.getTriple(), cpu, features));
1780b57cec5SDimitry Andric   assert(m_alt_subtype_info.get());
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric   m_alt_disasm.reset(
1810b57cec5SDimitry Andric       target->createMCDisassembler(*m_alt_subtype_info, *m_context));
1820b57cec5SDimitry Andric   assert(m_alt_disasm.get());
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric   m_next_inst_size = 0;
1850b57cec5SDimitry Andric   m_use_alt_disaasm = false;
1860b57cec5SDimitry Andric }
1870b57cec5SDimitry Andric 
Initialize()1880b57cec5SDimitry Andric void EmulateInstructionMIPS::Initialize() {
1890b57cec5SDimitry Andric   PluginManager::RegisterPlugin(GetPluginNameStatic(),
1900b57cec5SDimitry Andric                                 GetPluginDescriptionStatic(), CreateInstance);
1910b57cec5SDimitry Andric }
1920b57cec5SDimitry Andric 
Terminate()1930b57cec5SDimitry Andric void EmulateInstructionMIPS::Terminate() {
1940b57cec5SDimitry Andric   PluginManager::UnregisterPlugin(CreateInstance);
1950b57cec5SDimitry Andric }
1960b57cec5SDimitry Andric 
GetPluginDescriptionStatic()197349cc55cSDimitry Andric llvm::StringRef EmulateInstructionMIPS::GetPluginDescriptionStatic() {
1980b57cec5SDimitry Andric   return "Emulate instructions for the MIPS32 architecture.";
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric EmulateInstruction *
CreateInstance(const ArchSpec & arch,InstructionType inst_type)2020b57cec5SDimitry Andric EmulateInstructionMIPS::CreateInstance(const ArchSpec &arch,
2030b57cec5SDimitry Andric                                        InstructionType inst_type) {
2040b57cec5SDimitry Andric   if (EmulateInstructionMIPS::SupportsEmulatingInstructionsOfTypeStatic(
2050b57cec5SDimitry Andric           inst_type)) {
2060b57cec5SDimitry Andric     if (arch.GetTriple().getArch() == llvm::Triple::mips ||
2070b57cec5SDimitry Andric         arch.GetTriple().getArch() == llvm::Triple::mipsel) {
2080b57cec5SDimitry Andric       return new EmulateInstructionMIPS(arch);
2090b57cec5SDimitry Andric     }
2100b57cec5SDimitry Andric   }
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric   return nullptr;
2130b57cec5SDimitry Andric }
2140b57cec5SDimitry Andric 
SetTargetTriple(const ArchSpec & arch)2150b57cec5SDimitry Andric bool EmulateInstructionMIPS::SetTargetTriple(const ArchSpec &arch) {
2160b57cec5SDimitry Andric   return arch.GetTriple().getArch() == llvm::Triple::mips ||
2170b57cec5SDimitry Andric          arch.GetTriple().getArch() == llvm::Triple::mipsel;
2180b57cec5SDimitry Andric }
2190b57cec5SDimitry Andric 
GetRegisterName(unsigned reg_num,bool alternate_name)2200b57cec5SDimitry Andric const char *EmulateInstructionMIPS::GetRegisterName(unsigned reg_num,
2210b57cec5SDimitry Andric                                                     bool alternate_name) {
2220b57cec5SDimitry Andric   if (alternate_name) {
2230b57cec5SDimitry Andric     switch (reg_num) {
2240b57cec5SDimitry Andric     case dwarf_sp_mips:
2250b57cec5SDimitry Andric       return "r29";
2260b57cec5SDimitry Andric     case dwarf_r30_mips:
2270b57cec5SDimitry Andric       return "r30";
2280b57cec5SDimitry Andric     case dwarf_ra_mips:
2290b57cec5SDimitry Andric       return "r31";
2300b57cec5SDimitry Andric     case dwarf_f0_mips:
2310b57cec5SDimitry Andric       return "f0";
2320b57cec5SDimitry Andric     case dwarf_f1_mips:
2330b57cec5SDimitry Andric       return "f1";
2340b57cec5SDimitry Andric     case dwarf_f2_mips:
2350b57cec5SDimitry Andric       return "f2";
2360b57cec5SDimitry Andric     case dwarf_f3_mips:
2370b57cec5SDimitry Andric       return "f3";
2380b57cec5SDimitry Andric     case dwarf_f4_mips:
2390b57cec5SDimitry Andric       return "f4";
2400b57cec5SDimitry Andric     case dwarf_f5_mips:
2410b57cec5SDimitry Andric       return "f5";
2420b57cec5SDimitry Andric     case dwarf_f6_mips:
2430b57cec5SDimitry Andric       return "f6";
2440b57cec5SDimitry Andric     case dwarf_f7_mips:
2450b57cec5SDimitry Andric       return "f7";
2460b57cec5SDimitry Andric     case dwarf_f8_mips:
2470b57cec5SDimitry Andric       return "f8";
2480b57cec5SDimitry Andric     case dwarf_f9_mips:
2490b57cec5SDimitry Andric       return "f9";
2500b57cec5SDimitry Andric     case dwarf_f10_mips:
2510b57cec5SDimitry Andric       return "f10";
2520b57cec5SDimitry Andric     case dwarf_f11_mips:
2530b57cec5SDimitry Andric       return "f11";
2540b57cec5SDimitry Andric     case dwarf_f12_mips:
2550b57cec5SDimitry Andric       return "f12";
2560b57cec5SDimitry Andric     case dwarf_f13_mips:
2570b57cec5SDimitry Andric       return "f13";
2580b57cec5SDimitry Andric     case dwarf_f14_mips:
2590b57cec5SDimitry Andric       return "f14";
2600b57cec5SDimitry Andric     case dwarf_f15_mips:
2610b57cec5SDimitry Andric       return "f15";
2620b57cec5SDimitry Andric     case dwarf_f16_mips:
2630b57cec5SDimitry Andric       return "f16";
2640b57cec5SDimitry Andric     case dwarf_f17_mips:
2650b57cec5SDimitry Andric       return "f17";
2660b57cec5SDimitry Andric     case dwarf_f18_mips:
2670b57cec5SDimitry Andric       return "f18";
2680b57cec5SDimitry Andric     case dwarf_f19_mips:
2690b57cec5SDimitry Andric       return "f19";
2700b57cec5SDimitry Andric     case dwarf_f20_mips:
2710b57cec5SDimitry Andric       return "f20";
2720b57cec5SDimitry Andric     case dwarf_f21_mips:
2730b57cec5SDimitry Andric       return "f21";
2740b57cec5SDimitry Andric     case dwarf_f22_mips:
2750b57cec5SDimitry Andric       return "f22";
2760b57cec5SDimitry Andric     case dwarf_f23_mips:
2770b57cec5SDimitry Andric       return "f23";
2780b57cec5SDimitry Andric     case dwarf_f24_mips:
2790b57cec5SDimitry Andric       return "f24";
2800b57cec5SDimitry Andric     case dwarf_f25_mips:
2810b57cec5SDimitry Andric       return "f25";
2820b57cec5SDimitry Andric     case dwarf_f26_mips:
2830b57cec5SDimitry Andric       return "f26";
2840b57cec5SDimitry Andric     case dwarf_f27_mips:
2850b57cec5SDimitry Andric       return "f27";
2860b57cec5SDimitry Andric     case dwarf_f28_mips:
2870b57cec5SDimitry Andric       return "f28";
2880b57cec5SDimitry Andric     case dwarf_f29_mips:
2890b57cec5SDimitry Andric       return "f29";
2900b57cec5SDimitry Andric     case dwarf_f30_mips:
2910b57cec5SDimitry Andric       return "f30";
2920b57cec5SDimitry Andric     case dwarf_f31_mips:
2930b57cec5SDimitry Andric       return "f31";
2940b57cec5SDimitry Andric     case dwarf_w0_mips:
2950b57cec5SDimitry Andric       return "w0";
2960b57cec5SDimitry Andric     case dwarf_w1_mips:
2970b57cec5SDimitry Andric       return "w1";
2980b57cec5SDimitry Andric     case dwarf_w2_mips:
2990b57cec5SDimitry Andric       return "w2";
3000b57cec5SDimitry Andric     case dwarf_w3_mips:
3010b57cec5SDimitry Andric       return "w3";
3020b57cec5SDimitry Andric     case dwarf_w4_mips:
3030b57cec5SDimitry Andric       return "w4";
3040b57cec5SDimitry Andric     case dwarf_w5_mips:
3050b57cec5SDimitry Andric       return "w5";
3060b57cec5SDimitry Andric     case dwarf_w6_mips:
3070b57cec5SDimitry Andric       return "w6";
3080b57cec5SDimitry Andric     case dwarf_w7_mips:
3090b57cec5SDimitry Andric       return "w7";
3100b57cec5SDimitry Andric     case dwarf_w8_mips:
3110b57cec5SDimitry Andric       return "w8";
3120b57cec5SDimitry Andric     case dwarf_w9_mips:
3130b57cec5SDimitry Andric       return "w9";
3140b57cec5SDimitry Andric     case dwarf_w10_mips:
3150b57cec5SDimitry Andric       return "w10";
3160b57cec5SDimitry Andric     case dwarf_w11_mips:
3170b57cec5SDimitry Andric       return "w11";
3180b57cec5SDimitry Andric     case dwarf_w12_mips:
3190b57cec5SDimitry Andric       return "w12";
3200b57cec5SDimitry Andric     case dwarf_w13_mips:
3210b57cec5SDimitry Andric       return "w13";
3220b57cec5SDimitry Andric     case dwarf_w14_mips:
3230b57cec5SDimitry Andric       return "w14";
3240b57cec5SDimitry Andric     case dwarf_w15_mips:
3250b57cec5SDimitry Andric       return "w15";
3260b57cec5SDimitry Andric     case dwarf_w16_mips:
3270b57cec5SDimitry Andric       return "w16";
3280b57cec5SDimitry Andric     case dwarf_w17_mips:
3290b57cec5SDimitry Andric       return "w17";
3300b57cec5SDimitry Andric     case dwarf_w18_mips:
3310b57cec5SDimitry Andric       return "w18";
3320b57cec5SDimitry Andric     case dwarf_w19_mips:
3330b57cec5SDimitry Andric       return "w19";
3340b57cec5SDimitry Andric     case dwarf_w20_mips:
3350b57cec5SDimitry Andric       return "w20";
3360b57cec5SDimitry Andric     case dwarf_w21_mips:
3370b57cec5SDimitry Andric       return "w21";
3380b57cec5SDimitry Andric     case dwarf_w22_mips:
3390b57cec5SDimitry Andric       return "w22";
3400b57cec5SDimitry Andric     case dwarf_w23_mips:
3410b57cec5SDimitry Andric       return "w23";
3420b57cec5SDimitry Andric     case dwarf_w24_mips:
3430b57cec5SDimitry Andric       return "w24";
3440b57cec5SDimitry Andric     case dwarf_w25_mips:
3450b57cec5SDimitry Andric       return "w25";
3460b57cec5SDimitry Andric     case dwarf_w26_mips:
3470b57cec5SDimitry Andric       return "w26";
3480b57cec5SDimitry Andric     case dwarf_w27_mips:
3490b57cec5SDimitry Andric       return "w27";
3500b57cec5SDimitry Andric     case dwarf_w28_mips:
3510b57cec5SDimitry Andric       return "w28";
3520b57cec5SDimitry Andric     case dwarf_w29_mips:
3530b57cec5SDimitry Andric       return "w29";
3540b57cec5SDimitry Andric     case dwarf_w30_mips:
3550b57cec5SDimitry Andric       return "w30";
3560b57cec5SDimitry Andric     case dwarf_w31_mips:
3570b57cec5SDimitry Andric       return "w31";
3580b57cec5SDimitry Andric     case dwarf_mir_mips:
3590b57cec5SDimitry Andric       return "mir";
3600b57cec5SDimitry Andric     case dwarf_mcsr_mips:
3610b57cec5SDimitry Andric       return "mcsr";
3620b57cec5SDimitry Andric     case dwarf_config5_mips:
3630b57cec5SDimitry Andric       return "config5";
3640b57cec5SDimitry Andric     default:
3650b57cec5SDimitry Andric       break;
3660b57cec5SDimitry Andric     }
3670b57cec5SDimitry Andric     return nullptr;
3680b57cec5SDimitry Andric   }
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric   switch (reg_num) {
3710b57cec5SDimitry Andric   case dwarf_zero_mips:
3720b57cec5SDimitry Andric     return "r0";
3730b57cec5SDimitry Andric   case dwarf_r1_mips:
3740b57cec5SDimitry Andric     return "r1";
3750b57cec5SDimitry Andric   case dwarf_r2_mips:
3760b57cec5SDimitry Andric     return "r2";
3770b57cec5SDimitry Andric   case dwarf_r3_mips:
3780b57cec5SDimitry Andric     return "r3";
3790b57cec5SDimitry Andric   case dwarf_r4_mips:
3800b57cec5SDimitry Andric     return "r4";
3810b57cec5SDimitry Andric   case dwarf_r5_mips:
3820b57cec5SDimitry Andric     return "r5";
3830b57cec5SDimitry Andric   case dwarf_r6_mips:
3840b57cec5SDimitry Andric     return "r6";
3850b57cec5SDimitry Andric   case dwarf_r7_mips:
3860b57cec5SDimitry Andric     return "r7";
3870b57cec5SDimitry Andric   case dwarf_r8_mips:
3880b57cec5SDimitry Andric     return "r8";
3890b57cec5SDimitry Andric   case dwarf_r9_mips:
3900b57cec5SDimitry Andric     return "r9";
3910b57cec5SDimitry Andric   case dwarf_r10_mips:
3920b57cec5SDimitry Andric     return "r10";
3930b57cec5SDimitry Andric   case dwarf_r11_mips:
3940b57cec5SDimitry Andric     return "r11";
3950b57cec5SDimitry Andric   case dwarf_r12_mips:
3960b57cec5SDimitry Andric     return "r12";
3970b57cec5SDimitry Andric   case dwarf_r13_mips:
3980b57cec5SDimitry Andric     return "r13";
3990b57cec5SDimitry Andric   case dwarf_r14_mips:
4000b57cec5SDimitry Andric     return "r14";
4010b57cec5SDimitry Andric   case dwarf_r15_mips:
4020b57cec5SDimitry Andric     return "r15";
4030b57cec5SDimitry Andric   case dwarf_r16_mips:
4040b57cec5SDimitry Andric     return "r16";
4050b57cec5SDimitry Andric   case dwarf_r17_mips:
4060b57cec5SDimitry Andric     return "r17";
4070b57cec5SDimitry Andric   case dwarf_r18_mips:
4080b57cec5SDimitry Andric     return "r18";
4090b57cec5SDimitry Andric   case dwarf_r19_mips:
4100b57cec5SDimitry Andric     return "r19";
4110b57cec5SDimitry Andric   case dwarf_r20_mips:
4120b57cec5SDimitry Andric     return "r20";
4130b57cec5SDimitry Andric   case dwarf_r21_mips:
4140b57cec5SDimitry Andric     return "r21";
4150b57cec5SDimitry Andric   case dwarf_r22_mips:
4160b57cec5SDimitry Andric     return "r22";
4170b57cec5SDimitry Andric   case dwarf_r23_mips:
4180b57cec5SDimitry Andric     return "r23";
4190b57cec5SDimitry Andric   case dwarf_r24_mips:
4200b57cec5SDimitry Andric     return "r24";
4210b57cec5SDimitry Andric   case dwarf_r25_mips:
4220b57cec5SDimitry Andric     return "r25";
4230b57cec5SDimitry Andric   case dwarf_r26_mips:
4240b57cec5SDimitry Andric     return "r26";
4250b57cec5SDimitry Andric   case dwarf_r27_mips:
4260b57cec5SDimitry Andric     return "r27";
4270b57cec5SDimitry Andric   case dwarf_gp_mips:
4280b57cec5SDimitry Andric     return "gp";
4290b57cec5SDimitry Andric   case dwarf_sp_mips:
4300b57cec5SDimitry Andric     return "sp";
4310b57cec5SDimitry Andric   case dwarf_r30_mips:
4320b57cec5SDimitry Andric     return "fp";
4330b57cec5SDimitry Andric   case dwarf_ra_mips:
4340b57cec5SDimitry Andric     return "ra";
4350b57cec5SDimitry Andric   case dwarf_sr_mips:
4360b57cec5SDimitry Andric     return "sr";
4370b57cec5SDimitry Andric   case dwarf_lo_mips:
4380b57cec5SDimitry Andric     return "lo";
4390b57cec5SDimitry Andric   case dwarf_hi_mips:
4400b57cec5SDimitry Andric     return "hi";
4410b57cec5SDimitry Andric   case dwarf_bad_mips:
4420b57cec5SDimitry Andric     return "bad";
4430b57cec5SDimitry Andric   case dwarf_cause_mips:
4440b57cec5SDimitry Andric     return "cause";
4450b57cec5SDimitry Andric   case dwarf_pc_mips:
4460b57cec5SDimitry Andric     return "pc";
4470b57cec5SDimitry Andric   case dwarf_f0_mips:
4480b57cec5SDimitry Andric     return "f0";
4490b57cec5SDimitry Andric   case dwarf_f1_mips:
4500b57cec5SDimitry Andric     return "f1";
4510b57cec5SDimitry Andric   case dwarf_f2_mips:
4520b57cec5SDimitry Andric     return "f2";
4530b57cec5SDimitry Andric   case dwarf_f3_mips:
4540b57cec5SDimitry Andric     return "f3";
4550b57cec5SDimitry Andric   case dwarf_f4_mips:
4560b57cec5SDimitry Andric     return "f4";
4570b57cec5SDimitry Andric   case dwarf_f5_mips:
4580b57cec5SDimitry Andric     return "f5";
4590b57cec5SDimitry Andric   case dwarf_f6_mips:
4600b57cec5SDimitry Andric     return "f6";
4610b57cec5SDimitry Andric   case dwarf_f7_mips:
4620b57cec5SDimitry Andric     return "f7";
4630b57cec5SDimitry Andric   case dwarf_f8_mips:
4640b57cec5SDimitry Andric     return "f8";
4650b57cec5SDimitry Andric   case dwarf_f9_mips:
4660b57cec5SDimitry Andric     return "f9";
4670b57cec5SDimitry Andric   case dwarf_f10_mips:
4680b57cec5SDimitry Andric     return "f10";
4690b57cec5SDimitry Andric   case dwarf_f11_mips:
4700b57cec5SDimitry Andric     return "f11";
4710b57cec5SDimitry Andric   case dwarf_f12_mips:
4720b57cec5SDimitry Andric     return "f12";
4730b57cec5SDimitry Andric   case dwarf_f13_mips:
4740b57cec5SDimitry Andric     return "f13";
4750b57cec5SDimitry Andric   case dwarf_f14_mips:
4760b57cec5SDimitry Andric     return "f14";
4770b57cec5SDimitry Andric   case dwarf_f15_mips:
4780b57cec5SDimitry Andric     return "f15";
4790b57cec5SDimitry Andric   case dwarf_f16_mips:
4800b57cec5SDimitry Andric     return "f16";
4810b57cec5SDimitry Andric   case dwarf_f17_mips:
4820b57cec5SDimitry Andric     return "f17";
4830b57cec5SDimitry Andric   case dwarf_f18_mips:
4840b57cec5SDimitry Andric     return "f18";
4850b57cec5SDimitry Andric   case dwarf_f19_mips:
4860b57cec5SDimitry Andric     return "f19";
4870b57cec5SDimitry Andric   case dwarf_f20_mips:
4880b57cec5SDimitry Andric     return "f20";
4890b57cec5SDimitry Andric   case dwarf_f21_mips:
4900b57cec5SDimitry Andric     return "f21";
4910b57cec5SDimitry Andric   case dwarf_f22_mips:
4920b57cec5SDimitry Andric     return "f22";
4930b57cec5SDimitry Andric   case dwarf_f23_mips:
4940b57cec5SDimitry Andric     return "f23";
4950b57cec5SDimitry Andric   case dwarf_f24_mips:
4960b57cec5SDimitry Andric     return "f24";
4970b57cec5SDimitry Andric   case dwarf_f25_mips:
4980b57cec5SDimitry Andric     return "f25";
4990b57cec5SDimitry Andric   case dwarf_f26_mips:
5000b57cec5SDimitry Andric     return "f26";
5010b57cec5SDimitry Andric   case dwarf_f27_mips:
5020b57cec5SDimitry Andric     return "f27";
5030b57cec5SDimitry Andric   case dwarf_f28_mips:
5040b57cec5SDimitry Andric     return "f28";
5050b57cec5SDimitry Andric   case dwarf_f29_mips:
5060b57cec5SDimitry Andric     return "f29";
5070b57cec5SDimitry Andric   case dwarf_f30_mips:
5080b57cec5SDimitry Andric     return "f30";
5090b57cec5SDimitry Andric   case dwarf_f31_mips:
5100b57cec5SDimitry Andric     return "f31";
5110b57cec5SDimitry Andric   case dwarf_fcsr_mips:
5120b57cec5SDimitry Andric     return "fcsr";
5130b57cec5SDimitry Andric   case dwarf_fir_mips:
5140b57cec5SDimitry Andric     return "fir";
5150b57cec5SDimitry Andric   case dwarf_w0_mips:
5160b57cec5SDimitry Andric     return "w0";
5170b57cec5SDimitry Andric   case dwarf_w1_mips:
5180b57cec5SDimitry Andric     return "w1";
5190b57cec5SDimitry Andric   case dwarf_w2_mips:
5200b57cec5SDimitry Andric     return "w2";
5210b57cec5SDimitry Andric   case dwarf_w3_mips:
5220b57cec5SDimitry Andric     return "w3";
5230b57cec5SDimitry Andric   case dwarf_w4_mips:
5240b57cec5SDimitry Andric     return "w4";
5250b57cec5SDimitry Andric   case dwarf_w5_mips:
5260b57cec5SDimitry Andric     return "w5";
5270b57cec5SDimitry Andric   case dwarf_w6_mips:
5280b57cec5SDimitry Andric     return "w6";
5290b57cec5SDimitry Andric   case dwarf_w7_mips:
5300b57cec5SDimitry Andric     return "w7";
5310b57cec5SDimitry Andric   case dwarf_w8_mips:
5320b57cec5SDimitry Andric     return "w8";
5330b57cec5SDimitry Andric   case dwarf_w9_mips:
5340b57cec5SDimitry Andric     return "w9";
5350b57cec5SDimitry Andric   case dwarf_w10_mips:
5360b57cec5SDimitry Andric     return "w10";
5370b57cec5SDimitry Andric   case dwarf_w11_mips:
5380b57cec5SDimitry Andric     return "w11";
5390b57cec5SDimitry Andric   case dwarf_w12_mips:
5400b57cec5SDimitry Andric     return "w12";
5410b57cec5SDimitry Andric   case dwarf_w13_mips:
5420b57cec5SDimitry Andric     return "w13";
5430b57cec5SDimitry Andric   case dwarf_w14_mips:
5440b57cec5SDimitry Andric     return "w14";
5450b57cec5SDimitry Andric   case dwarf_w15_mips:
5460b57cec5SDimitry Andric     return "w15";
5470b57cec5SDimitry Andric   case dwarf_w16_mips:
5480b57cec5SDimitry Andric     return "w16";
5490b57cec5SDimitry Andric   case dwarf_w17_mips:
5500b57cec5SDimitry Andric     return "w17";
5510b57cec5SDimitry Andric   case dwarf_w18_mips:
5520b57cec5SDimitry Andric     return "w18";
5530b57cec5SDimitry Andric   case dwarf_w19_mips:
5540b57cec5SDimitry Andric     return "w19";
5550b57cec5SDimitry Andric   case dwarf_w20_mips:
5560b57cec5SDimitry Andric     return "w20";
5570b57cec5SDimitry Andric   case dwarf_w21_mips:
5580b57cec5SDimitry Andric     return "w21";
5590b57cec5SDimitry Andric   case dwarf_w22_mips:
5600b57cec5SDimitry Andric     return "w22";
5610b57cec5SDimitry Andric   case dwarf_w23_mips:
5620b57cec5SDimitry Andric     return "w23";
5630b57cec5SDimitry Andric   case dwarf_w24_mips:
5640b57cec5SDimitry Andric     return "w24";
5650b57cec5SDimitry Andric   case dwarf_w25_mips:
5660b57cec5SDimitry Andric     return "w25";
5670b57cec5SDimitry Andric   case dwarf_w26_mips:
5680b57cec5SDimitry Andric     return "w26";
5690b57cec5SDimitry Andric   case dwarf_w27_mips:
5700b57cec5SDimitry Andric     return "w27";
5710b57cec5SDimitry Andric   case dwarf_w28_mips:
5720b57cec5SDimitry Andric     return "w28";
5730b57cec5SDimitry Andric   case dwarf_w29_mips:
5740b57cec5SDimitry Andric     return "w29";
5750b57cec5SDimitry Andric   case dwarf_w30_mips:
5760b57cec5SDimitry Andric     return "w30";
5770b57cec5SDimitry Andric   case dwarf_w31_mips:
5780b57cec5SDimitry Andric     return "w31";
5790b57cec5SDimitry Andric   case dwarf_mcsr_mips:
5800b57cec5SDimitry Andric     return "mcsr";
5810b57cec5SDimitry Andric   case dwarf_mir_mips:
5820b57cec5SDimitry Andric     return "mir";
5830b57cec5SDimitry Andric   case dwarf_config5_mips:
5840b57cec5SDimitry Andric     return "config5";
5850b57cec5SDimitry Andric   }
5860b57cec5SDimitry Andric   return nullptr;
5870b57cec5SDimitry Andric }
5880b57cec5SDimitry Andric 
589bdd1243dSDimitry Andric std::optional<RegisterInfo>
GetRegisterInfo(RegisterKind reg_kind,uint32_t reg_num)590bdd1243dSDimitry Andric EmulateInstructionMIPS::GetRegisterInfo(RegisterKind reg_kind,
591bdd1243dSDimitry Andric                                         uint32_t reg_num) {
5920b57cec5SDimitry Andric   if (reg_kind == eRegisterKindGeneric) {
5930b57cec5SDimitry Andric     switch (reg_num) {
5940b57cec5SDimitry Andric     case LLDB_REGNUM_GENERIC_PC:
5950b57cec5SDimitry Andric       reg_kind = eRegisterKindDWARF;
5960b57cec5SDimitry Andric       reg_num = dwarf_pc_mips;
5970b57cec5SDimitry Andric       break;
5980b57cec5SDimitry Andric     case LLDB_REGNUM_GENERIC_SP:
5990b57cec5SDimitry Andric       reg_kind = eRegisterKindDWARF;
6000b57cec5SDimitry Andric       reg_num = dwarf_sp_mips;
6010b57cec5SDimitry Andric       break;
6020b57cec5SDimitry Andric     case LLDB_REGNUM_GENERIC_FP:
6030b57cec5SDimitry Andric       reg_kind = eRegisterKindDWARF;
6040b57cec5SDimitry Andric       reg_num = dwarf_r30_mips;
6050b57cec5SDimitry Andric       break;
6060b57cec5SDimitry Andric     case LLDB_REGNUM_GENERIC_RA:
6070b57cec5SDimitry Andric       reg_kind = eRegisterKindDWARF;
6080b57cec5SDimitry Andric       reg_num = dwarf_ra_mips;
6090b57cec5SDimitry Andric       break;
6100b57cec5SDimitry Andric     case LLDB_REGNUM_GENERIC_FLAGS:
6110b57cec5SDimitry Andric       reg_kind = eRegisterKindDWARF;
6120b57cec5SDimitry Andric       reg_num = dwarf_sr_mips;
6130b57cec5SDimitry Andric       break;
6140b57cec5SDimitry Andric     default:
615bdd1243dSDimitry Andric       return {};
6160b57cec5SDimitry Andric     }
6170b57cec5SDimitry Andric   }
6180b57cec5SDimitry Andric 
6190b57cec5SDimitry Andric   if (reg_kind == eRegisterKindDWARF) {
620bdd1243dSDimitry Andric     RegisterInfo reg_info;
6210b57cec5SDimitry Andric     ::memset(&reg_info, 0, sizeof(RegisterInfo));
6220b57cec5SDimitry Andric     ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
6230b57cec5SDimitry Andric 
6240b57cec5SDimitry Andric     if (reg_num == dwarf_sr_mips || reg_num == dwarf_fcsr_mips ||
6250b57cec5SDimitry Andric         reg_num == dwarf_fir_mips || reg_num == dwarf_mcsr_mips ||
6260b57cec5SDimitry Andric         reg_num == dwarf_mir_mips || reg_num == dwarf_config5_mips) {
6270b57cec5SDimitry Andric       reg_info.byte_size = 4;
6280b57cec5SDimitry Andric       reg_info.format = eFormatHex;
6290b57cec5SDimitry Andric       reg_info.encoding = eEncodingUint;
6300b57cec5SDimitry Andric     } else if ((int)reg_num >= dwarf_zero_mips &&
6310b57cec5SDimitry Andric                (int)reg_num <= dwarf_f31_mips) {
6320b57cec5SDimitry Andric       reg_info.byte_size = 4;
6330b57cec5SDimitry Andric       reg_info.format = eFormatHex;
6340b57cec5SDimitry Andric       reg_info.encoding = eEncodingUint;
6350b57cec5SDimitry Andric     } else if ((int)reg_num >= dwarf_w0_mips &&
6360b57cec5SDimitry Andric                (int)reg_num <= dwarf_w31_mips) {
6370b57cec5SDimitry Andric       reg_info.byte_size = 16;
6380b57cec5SDimitry Andric       reg_info.format = eFormatVectorOfUInt8;
6390b57cec5SDimitry Andric       reg_info.encoding = eEncodingVector;
6400b57cec5SDimitry Andric     } else {
641bdd1243dSDimitry Andric       return {};
6420b57cec5SDimitry Andric     }
6430b57cec5SDimitry Andric 
6440b57cec5SDimitry Andric     reg_info.name = GetRegisterName(reg_num, false);
6450b57cec5SDimitry Andric     reg_info.alt_name = GetRegisterName(reg_num, true);
6460b57cec5SDimitry Andric     reg_info.kinds[eRegisterKindDWARF] = reg_num;
6470b57cec5SDimitry Andric 
6480b57cec5SDimitry Andric     switch (reg_num) {
6490b57cec5SDimitry Andric     case dwarf_r30_mips:
6500b57cec5SDimitry Andric       reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
6510b57cec5SDimitry Andric       break;
6520b57cec5SDimitry Andric     case dwarf_ra_mips:
6530b57cec5SDimitry Andric       reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
6540b57cec5SDimitry Andric       break;
6550b57cec5SDimitry Andric     case dwarf_sp_mips:
6560b57cec5SDimitry Andric       reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
6570b57cec5SDimitry Andric       break;
6580b57cec5SDimitry Andric     case dwarf_pc_mips:
6590b57cec5SDimitry Andric       reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
6600b57cec5SDimitry Andric       break;
6610b57cec5SDimitry Andric     case dwarf_sr_mips:
6620b57cec5SDimitry Andric       reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
6630b57cec5SDimitry Andric       break;
6640b57cec5SDimitry Andric     default:
6650b57cec5SDimitry Andric       break;
6660b57cec5SDimitry Andric     }
667bdd1243dSDimitry Andric     return reg_info;
6680b57cec5SDimitry Andric   }
669bdd1243dSDimitry Andric   return {};
6700b57cec5SDimitry Andric }
6710b57cec5SDimitry Andric 
6720b57cec5SDimitry Andric EmulateInstructionMIPS::MipsOpcode *
GetOpcodeForInstruction(llvm::StringRef name)67381ad6265SDimitry Andric EmulateInstructionMIPS::GetOpcodeForInstruction(llvm::StringRef name) {
6740b57cec5SDimitry Andric   static EmulateInstructionMIPS::MipsOpcode g_opcodes[] = {
6750b57cec5SDimitry Andric       // Prologue/Epilogue instructions
6760b57cec5SDimitry Andric       {"ADDiu", &EmulateInstructionMIPS::Emulate_ADDiu,
6770b57cec5SDimitry Andric        "ADDIU rt, rs, immediate"},
6780b57cec5SDimitry Andric       {"SW", &EmulateInstructionMIPS::Emulate_SW, "SW rt, offset(rs)"},
6790b57cec5SDimitry Andric       {"LW", &EmulateInstructionMIPS::Emulate_LW, "LW rt, offset(base)"},
6800b57cec5SDimitry Andric       {"SUBU", &EmulateInstructionMIPS::Emulate_SUBU_ADDU, "SUBU rd, rs, rt"},
6810b57cec5SDimitry Andric       {"ADDU", &EmulateInstructionMIPS::Emulate_SUBU_ADDU, "ADDU rd, rs, rt"},
6820b57cec5SDimitry Andric       {"LUI", &EmulateInstructionMIPS::Emulate_LUI, "LUI rt, immediate"},
6830b57cec5SDimitry Andric 
6840b57cec5SDimitry Andric       // MicroMIPS Prologue/Epilogue instructions
6850b57cec5SDimitry Andric       {"ADDIUSP_MM", &EmulateInstructionMIPS::Emulate_ADDIUSP,
6860b57cec5SDimitry Andric        "ADDIU immediate"},
6870b57cec5SDimitry Andric       {"ADDIUS5_MM", &EmulateInstructionMIPS::Emulate_ADDIUS5,
6880b57cec5SDimitry Andric        "ADDIUS5 rd,immediate"},
6890b57cec5SDimitry Andric       {"SWSP_MM", &EmulateInstructionMIPS::Emulate_SWSP, "SWSP rt,offset(sp)"},
6900b57cec5SDimitry Andric       {"SWM16_MM", &EmulateInstructionMIPS::Emulate_SWM16_32,
6910b57cec5SDimitry Andric        "SWM16 reglist,offset(sp)"},
6920b57cec5SDimitry Andric       {"SWM32_MM", &EmulateInstructionMIPS::Emulate_SWM16_32,
6930b57cec5SDimitry Andric        "SWM32 reglist,offset(base)"},
6940b57cec5SDimitry Andric       {"SWP_MM", &EmulateInstructionMIPS::Emulate_SWM16_32,
6950b57cec5SDimitry Andric        "SWP rs1,offset(base)"},
6960b57cec5SDimitry Andric       {"LWSP_MM", &EmulateInstructionMIPS::Emulate_LWSP, "LWSP rt,offset(sp)"},
6970b57cec5SDimitry Andric       {"LWM16_MM", &EmulateInstructionMIPS::Emulate_LWM16_32,
6980b57cec5SDimitry Andric        "LWM16 reglist,offset(sp)"},
6990b57cec5SDimitry Andric       {"LWM32_MM", &EmulateInstructionMIPS::Emulate_LWM16_32,
7000b57cec5SDimitry Andric        "LWM32 reglist,offset(base)"},
7010b57cec5SDimitry Andric       {"LWP_MM", &EmulateInstructionMIPS::Emulate_LWM16_32,
7020b57cec5SDimitry Andric        "LWP rd,offset(base)"},
7030b57cec5SDimitry Andric       {"JRADDIUSP", &EmulateInstructionMIPS::Emulate_JRADDIUSP,
7040b57cec5SDimitry Andric        "JRADDIUSP immediate"},
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric       // Load/Store  instructions
7070b57cec5SDimitry Andric       /* Following list of emulated instructions are required by implementation
7080b57cec5SDimitry Andric          of hardware watchpoint
7090b57cec5SDimitry Andric          for MIPS in lldb. As we just need the address accessed by instructions,
7100b57cec5SDimitry Andric          we have generalised
7110b57cec5SDimitry Andric          all these instructions in 2 functions depending on their addressing
7120b57cec5SDimitry Andric          modes */
7130b57cec5SDimitry Andric 
7140b57cec5SDimitry Andric       {"LB", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7150b57cec5SDimitry Andric        "LB    rt, offset(base)"},
7160b57cec5SDimitry Andric       {"LBE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7170b57cec5SDimitry Andric        "LBE   rt, offset(base)"},
7180b57cec5SDimitry Andric       {"LBU", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7190b57cec5SDimitry Andric        "LBU   rt, offset(base)"},
7200b57cec5SDimitry Andric       {"LBUE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7210b57cec5SDimitry Andric        "LBUE  rt, offset(base)"},
7220b57cec5SDimitry Andric       {"LDC1", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7230b57cec5SDimitry Andric        "LDC1  ft, offset(base)"},
7240b57cec5SDimitry Andric       {"LD", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7250b57cec5SDimitry Andric        "LD    rt, offset(base)"},
7260b57cec5SDimitry Andric       {"LDL", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7270b57cec5SDimitry Andric        "LDL   rt, offset(base)"},
7280b57cec5SDimitry Andric       {"LDR", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7290b57cec5SDimitry Andric        "LDR   rt, offset(base)"},
7300b57cec5SDimitry Andric       {"LLD", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7310b57cec5SDimitry Andric        "LLD   rt, offset(base)"},
7320b57cec5SDimitry Andric       {"LDC2", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7330b57cec5SDimitry Andric        "LDC2  rt, offset(base)"},
7340b57cec5SDimitry Andric       {"LDXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,
7350b57cec5SDimitry Andric        "LDXC1 fd, index (base)"},
7360b57cec5SDimitry Andric       {"LH", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7370b57cec5SDimitry Andric        "LH    rt, offset(base)"},
7380b57cec5SDimitry Andric       {"LHE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7390b57cec5SDimitry Andric        "LHE   rt, offset(base)"},
7400b57cec5SDimitry Andric       {"LHU", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7410b57cec5SDimitry Andric        "LHU   rt, offset(base)"},
7420b57cec5SDimitry Andric       {"LHUE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7430b57cec5SDimitry Andric        "LHUE  rt, offset(base)"},
7440b57cec5SDimitry Andric       {"LL", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7450b57cec5SDimitry Andric        "LL    rt, offset(base)"},
7460b57cec5SDimitry Andric       {"LLE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7470b57cec5SDimitry Andric        "LLE   rt, offset(base)"},
7480b57cec5SDimitry Andric       {"LUXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,
7490b57cec5SDimitry Andric        "LUXC1 fd, index (base)"},
7500b57cec5SDimitry Andric       {"LW", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7510b57cec5SDimitry Andric        "LW    rt, offset(base)"},
7520b57cec5SDimitry Andric       {"LWC1", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7530b57cec5SDimitry Andric        "LWC1  ft, offset(base)"},
7540b57cec5SDimitry Andric       {"LWC2", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7550b57cec5SDimitry Andric        "LWC2  rt, offset(base)"},
7560b57cec5SDimitry Andric       {"LWE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7570b57cec5SDimitry Andric        "LWE   rt, offset(base)"},
7580b57cec5SDimitry Andric       {"LWL", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7590b57cec5SDimitry Andric        "LWL   rt, offset(base)"},
7600b57cec5SDimitry Andric       {"LWLE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7610b57cec5SDimitry Andric        "LWLE  rt, offset(base)"},
7620b57cec5SDimitry Andric       {"LWR", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7630b57cec5SDimitry Andric        "LWR   rt, offset(base)"},
7640b57cec5SDimitry Andric       {"LWRE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7650b57cec5SDimitry Andric        "LWRE  rt, offset(base)"},
7660b57cec5SDimitry Andric       {"LWXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,
7670b57cec5SDimitry Andric        "LWXC1 fd, index (base)"},
7680b57cec5SDimitry Andric       {"LLX", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7690b57cec5SDimitry Andric        "LLX   rt, offset(base)"},
7700b57cec5SDimitry Andric       {"LLXE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7710b57cec5SDimitry Andric        "LLXE  rt, offset(base)"},
7720b57cec5SDimitry Andric       {"LLDX", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7730b57cec5SDimitry Andric        "LLDX  rt, offset(base)"},
7740b57cec5SDimitry Andric 
7750b57cec5SDimitry Andric       {"SB", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7760b57cec5SDimitry Andric        "SB    rt, offset(base)"},
7770b57cec5SDimitry Andric       {"SBE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7780b57cec5SDimitry Andric        "SBE   rt, offset(base)"},
7790b57cec5SDimitry Andric       {"SC", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7800b57cec5SDimitry Andric        "SC    rt, offset(base)"},
7810b57cec5SDimitry Andric       {"SCE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7820b57cec5SDimitry Andric        "SCE   rt, offset(base)"},
7830b57cec5SDimitry Andric       {"SCD", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7840b57cec5SDimitry Andric        "SCD   rt, offset(base)"},
7850b57cec5SDimitry Andric       {"SD", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7860b57cec5SDimitry Andric        "SD    rt, offset(base)"},
7870b57cec5SDimitry Andric       {"SDL", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7880b57cec5SDimitry Andric        "SDL   rt, offset(base)"},
7890b57cec5SDimitry Andric       {"SDR", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7900b57cec5SDimitry Andric        "SDR   rt, offset(base)"},
7910b57cec5SDimitry Andric       {"SDC1", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7920b57cec5SDimitry Andric        "SDC1  ft, offset(base)"},
7930b57cec5SDimitry Andric       {"SDC2", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7940b57cec5SDimitry Andric        "SDC2  rt, offset(base)"},
7950b57cec5SDimitry Andric       {"SDXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,
7960b57cec5SDimitry Andric        "SDXC1 fs, index(base)"},
7970b57cec5SDimitry Andric       {"SH", &EmulateInstructionMIPS::Emulate_LDST_Imm,
7980b57cec5SDimitry Andric        "SH    rt, offset(base)"},
7990b57cec5SDimitry Andric       {"SHE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
8000b57cec5SDimitry Andric        "SHE   rt, offset(base)"},
8010b57cec5SDimitry Andric       {"SUXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,
8020b57cec5SDimitry Andric        "SUXC1 fs, index (base)"},
8030b57cec5SDimitry Andric       {"SWC1", &EmulateInstructionMIPS::Emulate_LDST_Imm,
8040b57cec5SDimitry Andric        "SWC1  ft, offset(base)"},
8050b57cec5SDimitry Andric       {"SWC2", &EmulateInstructionMIPS::Emulate_LDST_Imm,
8060b57cec5SDimitry Andric        "SWC2  rt, offset(base)"},
8070b57cec5SDimitry Andric       {"SWE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
8080b57cec5SDimitry Andric        "SWE   rt, offset(base)"},
8090b57cec5SDimitry Andric       {"SWL", &EmulateInstructionMIPS::Emulate_LDST_Imm,
8100b57cec5SDimitry Andric        "SWL   rt, offset(base)"},
8110b57cec5SDimitry Andric       {"SWLE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
8120b57cec5SDimitry Andric        "SWLE  rt, offset(base)"},
8130b57cec5SDimitry Andric       {"SWR", &EmulateInstructionMIPS::Emulate_LDST_Imm,
8140b57cec5SDimitry Andric        "SWR   rt, offset(base)"},
8150b57cec5SDimitry Andric       {"SWRE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
8160b57cec5SDimitry Andric        "SWRE  rt, offset(base)"},
8170b57cec5SDimitry Andric       {"SWXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,
8180b57cec5SDimitry Andric        "SWXC1 fs, index (base)"},
8190b57cec5SDimitry Andric       {"SCX", &EmulateInstructionMIPS::Emulate_LDST_Imm,
8200b57cec5SDimitry Andric        "SCX   rt, offset(base)"},
8210b57cec5SDimitry Andric       {"SCXE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
8220b57cec5SDimitry Andric        "SCXE  rt, offset(base)"},
8230b57cec5SDimitry Andric       {"SCDX", &EmulateInstructionMIPS::Emulate_LDST_Imm,
8240b57cec5SDimitry Andric        "SCDX  rt, offset(base)"},
8250b57cec5SDimitry Andric 
8260b57cec5SDimitry Andric       // MicroMIPS Load/Store instructions
8270b57cec5SDimitry Andric       {"LBU16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
8280b57cec5SDimitry Andric        "LBU16 rt, decoded_offset(base)"},
8290b57cec5SDimitry Andric       {"LHU16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
8300b57cec5SDimitry Andric        "LHU16 rt, left_shifted_offset(base)"},
8310b57cec5SDimitry Andric       {"LW16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
8320b57cec5SDimitry Andric        "LW16  rt, left_shifted_offset(base)"},
8330b57cec5SDimitry Andric       {"LWGP_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
8340b57cec5SDimitry Andric        "LWGP  rt, left_shifted_offset(gp)"},
8350b57cec5SDimitry Andric       {"SH16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
8360b57cec5SDimitry Andric        "SH16  rt, left_shifted_offset(base)"},
8370b57cec5SDimitry Andric       {"SW16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
8380b57cec5SDimitry Andric        "SW16  rt, left_shifted_offset(base)"},
8390b57cec5SDimitry Andric       {"SW_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
8400b57cec5SDimitry Andric        "SWSP  rt, left_shifted_offset(base)"},
8410b57cec5SDimitry Andric       {"SB16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
8420b57cec5SDimitry Andric        "SB16  rt, offset(base)"},
8430b57cec5SDimitry Andric 
8440b57cec5SDimitry Andric       // Branch instructions
8450b57cec5SDimitry Andric       {"BEQ", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BEQ rs,rt,offset"},
8460b57cec5SDimitry Andric       {"BNE", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BNE rs,rt,offset"},
8470b57cec5SDimitry Andric       {"BEQL", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BEQL rs,rt,offset"},
8480b57cec5SDimitry Andric       {"BNEL", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BNEL rs,rt,offset"},
8490b57cec5SDimitry Andric       {"BGEZALL", &EmulateInstructionMIPS::Emulate_Bcond_Link,
8500b57cec5SDimitry Andric        "BGEZALL rt,offset"},
8510b57cec5SDimitry Andric       {"BAL", &EmulateInstructionMIPS::Emulate_BAL, "BAL offset"},
8520b57cec5SDimitry Andric       {"BGEZAL", &EmulateInstructionMIPS::Emulate_Bcond_Link,
8530b57cec5SDimitry Andric        "BGEZAL rs,offset"},
8540b57cec5SDimitry Andric       {"BALC", &EmulateInstructionMIPS::Emulate_BALC, "BALC offset"},
8550b57cec5SDimitry Andric       {"BC", &EmulateInstructionMIPS::Emulate_BC, "BC offset"},
8560b57cec5SDimitry Andric       {"BGEZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGEZ rs,offset"},
8570b57cec5SDimitry Andric       {"BLEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,
8580b57cec5SDimitry Andric        "BLEZALC rs,offset"},
8590b57cec5SDimitry Andric       {"BGEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,
8600b57cec5SDimitry Andric        "BGEZALC rs,offset"},
8610b57cec5SDimitry Andric       {"BLTZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,
8620b57cec5SDimitry Andric        "BLTZALC rs,offset"},
8630b57cec5SDimitry Andric       {"BGTZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,
8640b57cec5SDimitry Andric        "BGTZALC rs,offset"},
8650b57cec5SDimitry Andric       {"BEQZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,
8660b57cec5SDimitry Andric        "BEQZALC rs,offset"},
8670b57cec5SDimitry Andric       {"BNEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,
8680b57cec5SDimitry Andric        "BNEZALC rs,offset"},
8690b57cec5SDimitry Andric       {"BEQC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
8700b57cec5SDimitry Andric        "BEQC rs,rt,offset"},
8710b57cec5SDimitry Andric       {"BNEC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
8720b57cec5SDimitry Andric        "BNEC rs,rt,offset"},
8730b57cec5SDimitry Andric       {"BLTC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
8740b57cec5SDimitry Andric        "BLTC rs,rt,offset"},
8750b57cec5SDimitry Andric       {"BGEC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
8760b57cec5SDimitry Andric        "BGEC rs,rt,offset"},
8770b57cec5SDimitry Andric       {"BLTUC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
8780b57cec5SDimitry Andric        "BLTUC rs,rt,offset"},
8790b57cec5SDimitry Andric       {"BGEUC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
8800b57cec5SDimitry Andric        "BGEUC rs,rt,offset"},
8810b57cec5SDimitry Andric       {"BLTZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BLTZC rt,offset"},
8820b57cec5SDimitry Andric       {"BLEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BLEZC rt,offset"},
8830b57cec5SDimitry Andric       {"BGEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BGEZC rt,offset"},
8840b57cec5SDimitry Andric       {"BGTZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BGTZC rt,offset"},
8850b57cec5SDimitry Andric       {"BEQZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BEQZC rt,offset"},
8860b57cec5SDimitry Andric       {"BNEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BNEZC rt,offset"},
8870b57cec5SDimitry Andric       {"BGEZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGEZL rt,offset"},
8880b57cec5SDimitry Andric       {"BGTZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGTZ rt,offset"},
8890b57cec5SDimitry Andric       {"BGTZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGTZL rt,offset"},
8900b57cec5SDimitry Andric       {"BLEZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLEZ rt,offset"},
8910b57cec5SDimitry Andric       {"BLEZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLEZL rt,offset"},
8920b57cec5SDimitry Andric       {"BLTZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLTZ rt,offset"},
8930b57cec5SDimitry Andric       {"BLTZAL", &EmulateInstructionMIPS::Emulate_Bcond_Link,
8940b57cec5SDimitry Andric        "BLTZAL rt,offset"},
8950b57cec5SDimitry Andric       {"BLTZALL", &EmulateInstructionMIPS::Emulate_Bcond_Link,
8960b57cec5SDimitry Andric        "BLTZALL rt,offset"},
8970b57cec5SDimitry Andric       {"BLTZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLTZL rt,offset"},
8980b57cec5SDimitry Andric       {"BOVC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
8990b57cec5SDimitry Andric        "BOVC rs,rt,offset"},
9000b57cec5SDimitry Andric       {"BNVC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
9010b57cec5SDimitry Andric        "BNVC rs,rt,offset"},
9020b57cec5SDimitry Andric       {"J", &EmulateInstructionMIPS::Emulate_J, "J target"},
9030b57cec5SDimitry Andric       {"JAL", &EmulateInstructionMIPS::Emulate_JAL, "JAL target"},
9040b57cec5SDimitry Andric       {"JALX", &EmulateInstructionMIPS::Emulate_JAL, "JALX target"},
9050b57cec5SDimitry Andric       {"JALR", &EmulateInstructionMIPS::Emulate_JALR, "JALR target"},
9060b57cec5SDimitry Andric       {"JALR_HB", &EmulateInstructionMIPS::Emulate_JALR, "JALR.HB target"},
9070b57cec5SDimitry Andric       {"JIALC", &EmulateInstructionMIPS::Emulate_JIALC, "JIALC rt,offset"},
9080b57cec5SDimitry Andric       {"JIC", &EmulateInstructionMIPS::Emulate_JIC, "JIC rt,offset"},
9090b57cec5SDimitry Andric       {"JR", &EmulateInstructionMIPS::Emulate_JR, "JR target"},
9100b57cec5SDimitry Andric       {"JR_HB", &EmulateInstructionMIPS::Emulate_JR, "JR.HB target"},
9110b57cec5SDimitry Andric       {"BC1F", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1F cc, offset"},
9120b57cec5SDimitry Andric       {"BC1T", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1T cc, offset"},
9130b57cec5SDimitry Andric       {"BC1FL", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1FL cc, offset"},
9140b57cec5SDimitry Andric       {"BC1TL", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1TL cc, offset"},
9150b57cec5SDimitry Andric       {"BC1EQZ", &EmulateInstructionMIPS::Emulate_BC1EQZ, "BC1EQZ ft, offset"},
9160b57cec5SDimitry Andric       {"BC1NEZ", &EmulateInstructionMIPS::Emulate_BC1NEZ, "BC1NEZ ft, offset"},
9170b57cec5SDimitry Andric       {"BC1ANY2F", &EmulateInstructionMIPS::Emulate_3D_branch,
9180b57cec5SDimitry Andric        "BC1ANY2F cc, offset"},
9190b57cec5SDimitry Andric       {"BC1ANY2T", &EmulateInstructionMIPS::Emulate_3D_branch,
9200b57cec5SDimitry Andric        "BC1ANY2T cc, offset"},
9210b57cec5SDimitry Andric       {"BC1ANY4F", &EmulateInstructionMIPS::Emulate_3D_branch,
9220b57cec5SDimitry Andric        "BC1ANY4F cc, offset"},
9230b57cec5SDimitry Andric       {"BC1ANY4T", &EmulateInstructionMIPS::Emulate_3D_branch,
9240b57cec5SDimitry Andric        "BC1ANY4T cc, offset"},
9250b57cec5SDimitry Andric       {"BNZ_B", &EmulateInstructionMIPS::Emulate_BNZB, "BNZ.b wt,s16"},
9260b57cec5SDimitry Andric       {"BNZ_H", &EmulateInstructionMIPS::Emulate_BNZH, "BNZ.h wt,s16"},
9270b57cec5SDimitry Andric       {"BNZ_W", &EmulateInstructionMIPS::Emulate_BNZW, "BNZ.w wt,s16"},
9280b57cec5SDimitry Andric       {"BNZ_D", &EmulateInstructionMIPS::Emulate_BNZD, "BNZ.d wt,s16"},
9290b57cec5SDimitry Andric       {"BZ_B", &EmulateInstructionMIPS::Emulate_BZB, "BZ.b wt,s16"},
9300b57cec5SDimitry Andric       {"BZ_H", &EmulateInstructionMIPS::Emulate_BZH, "BZ.h wt,s16"},
9310b57cec5SDimitry Andric       {"BZ_W", &EmulateInstructionMIPS::Emulate_BZW, "BZ.w wt,s16"},
9320b57cec5SDimitry Andric       {"BZ_D", &EmulateInstructionMIPS::Emulate_BZD, "BZ.d wt,s16"},
9330b57cec5SDimitry Andric       {"BNZ_V", &EmulateInstructionMIPS::Emulate_BNZV, "BNZ.V wt,s16"},
9340b57cec5SDimitry Andric       {"BZ_V", &EmulateInstructionMIPS::Emulate_BZV, "BZ.V wt,s16"},
9350b57cec5SDimitry Andric 
9360b57cec5SDimitry Andric       // MicroMIPS Branch instructions
9370b57cec5SDimitry Andric       {"B16_MM", &EmulateInstructionMIPS::Emulate_B16_MM, "B16 offset"},
9380b57cec5SDimitry Andric       {"BEQZ16_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,
9390b57cec5SDimitry Andric        "BEQZ16 rs, offset"},
9400b57cec5SDimitry Andric       {"BNEZ16_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,
9410b57cec5SDimitry Andric        "BNEZ16 rs, offset"},
9420b57cec5SDimitry Andric       {"BEQZC_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,
9430b57cec5SDimitry Andric        "BEQZC rs, offset"},
9440b57cec5SDimitry Andric       {"BNEZC_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,
9450b57cec5SDimitry Andric        "BNEZC rs, offset"},
9460b57cec5SDimitry Andric       {"BGEZALS_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,
9470b57cec5SDimitry Andric        "BGEZALS rs, offset"},
9480b57cec5SDimitry Andric       {"BLTZALS_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,
9490b57cec5SDimitry Andric        "BLTZALS rs, offset"},
9500b57cec5SDimitry Andric       {"JALR16_MM", &EmulateInstructionMIPS::Emulate_JALRx16_MM, "JALR16 rs"},
9510b57cec5SDimitry Andric       {"JALRS16_MM", &EmulateInstructionMIPS::Emulate_JALRx16_MM, "JALRS16 rs"},
9520b57cec5SDimitry Andric       {"JR16_MM", &EmulateInstructionMIPS::Emulate_JR, "JR16 rs rs"},
9530b57cec5SDimitry Andric       {"JRC16_MM", &EmulateInstructionMIPS::Emulate_JR, "JRC16 rs rs"},
9540b57cec5SDimitry Andric       {"JALS_MM", &EmulateInstructionMIPS::Emulate_JALx, "JALS target"},
9550b57cec5SDimitry Andric       {"JALX_MM", &EmulateInstructionMIPS::Emulate_JALx, "JALX target"},
9560b57cec5SDimitry Andric       {"JALRS_MM", &EmulateInstructionMIPS::Emulate_JALRS, "JALRS rt, rs"},
9570b57cec5SDimitry Andric   };
9580b57cec5SDimitry Andric 
95981ad6265SDimitry Andric   for (MipsOpcode &opcode : g_opcodes) {
96081ad6265SDimitry Andric     if (name.equals_insensitive(opcode.op_name))
96181ad6265SDimitry Andric       return &opcode;
9620b57cec5SDimitry Andric   }
9630b57cec5SDimitry Andric   return nullptr;
9640b57cec5SDimitry Andric }
9650b57cec5SDimitry Andric 
9660b57cec5SDimitry Andric uint32_t
GetSizeOfInstruction(lldb_private::DataExtractor & data,uint64_t inst_addr)9670b57cec5SDimitry Andric EmulateInstructionMIPS::GetSizeOfInstruction(lldb_private::DataExtractor &data,
9680b57cec5SDimitry Andric                                              uint64_t inst_addr) {
9690b57cec5SDimitry Andric   uint64_t next_inst_size = 0;
9700b57cec5SDimitry Andric   llvm::MCInst mc_insn;
9710b57cec5SDimitry Andric   llvm::MCDisassembler::DecodeStatus decode_status;
9720b57cec5SDimitry Andric   llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());
9730b57cec5SDimitry Andric 
9740b57cec5SDimitry Andric   if (m_use_alt_disaasm)
975480093f4SDimitry Andric     decode_status = m_alt_disasm->getInstruction(
976480093f4SDimitry Andric         mc_insn, next_inst_size, raw_insn, inst_addr, llvm::nulls());
9770b57cec5SDimitry Andric   else
978480093f4SDimitry Andric     decode_status = m_disasm->getInstruction(mc_insn, next_inst_size, raw_insn,
979480093f4SDimitry Andric                                              inst_addr, llvm::nulls());
9800b57cec5SDimitry Andric 
9810b57cec5SDimitry Andric   if (decode_status != llvm::MCDisassembler::Success)
9820b57cec5SDimitry Andric     return false;
9830b57cec5SDimitry Andric 
9840b57cec5SDimitry Andric   return m_insn_info->get(mc_insn.getOpcode()).getSize();
9850b57cec5SDimitry Andric }
9860b57cec5SDimitry Andric 
SetInstruction(const Opcode & insn_opcode,const Address & inst_addr,Target * target)9870b57cec5SDimitry Andric bool EmulateInstructionMIPS::SetInstruction(const Opcode &insn_opcode,
9880b57cec5SDimitry Andric                                             const Address &inst_addr,
9890b57cec5SDimitry Andric                                             Target *target) {
9900b57cec5SDimitry Andric   m_use_alt_disaasm = false;
9910b57cec5SDimitry Andric 
9920b57cec5SDimitry Andric   if (EmulateInstruction::SetInstruction(insn_opcode, inst_addr, target)) {
9930b57cec5SDimitry Andric     if (inst_addr.GetAddressClass() == AddressClass::eCodeAlternateISA) {
9940b57cec5SDimitry Andric       Status error;
9950b57cec5SDimitry Andric       lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
9960b57cec5SDimitry Andric 
9970b57cec5SDimitry Andric       /*
9980b57cec5SDimitry Andric        * The address belongs to microMIPS function. To find the size of
9990b57cec5SDimitry Andric        * next instruction use microMIPS disassembler.
10000b57cec5SDimitry Andric       */
10010b57cec5SDimitry Andric       m_use_alt_disaasm = true;
10020b57cec5SDimitry Andric 
10030b57cec5SDimitry Andric       uint32_t current_inst_size = insn_opcode.GetByteSize();
10040b57cec5SDimitry Andric       uint8_t buf[sizeof(uint32_t)];
10050b57cec5SDimitry Andric       uint64_t next_inst_addr = (m_addr & (~1ull)) + current_inst_size;
10060b57cec5SDimitry Andric       Address next_addr(next_inst_addr);
10070b57cec5SDimitry Andric 
10080b57cec5SDimitry Andric       const size_t bytes_read =
10090b57cec5SDimitry Andric           target->ReadMemory(next_addr, /* Address of next instruction */
1010fe6060f1SDimitry Andric                              buf, sizeof(uint32_t), error,
1011fe6060f1SDimitry Andric                              false,  /* force_live_memory */
1012fe6060f1SDimitry Andric                              &load_addr);
10130b57cec5SDimitry Andric 
10140b57cec5SDimitry Andric       if (bytes_read == 0)
10150b57cec5SDimitry Andric         return true;
10160b57cec5SDimitry Andric 
10170b57cec5SDimitry Andric       DataExtractor data(buf, sizeof(uint32_t), GetByteOrder(),
10180b57cec5SDimitry Andric                          GetAddressByteSize());
10190b57cec5SDimitry Andric       m_next_inst_size = GetSizeOfInstruction(data, next_inst_addr);
10200b57cec5SDimitry Andric       return true;
10210b57cec5SDimitry Andric     } else {
10220b57cec5SDimitry Andric       /*
10230b57cec5SDimitry Andric        * If the address class is not AddressClass::eCodeAlternateISA then
10240b57cec5SDimitry Andric        * the function is not microMIPS. In this case instruction size is
10250b57cec5SDimitry Andric        * always 4 bytes.
10260b57cec5SDimitry Andric       */
10270b57cec5SDimitry Andric       m_next_inst_size = 4;
10280b57cec5SDimitry Andric       return true;
10290b57cec5SDimitry Andric     }
10300b57cec5SDimitry Andric   }
10310b57cec5SDimitry Andric   return false;
10320b57cec5SDimitry Andric }
10330b57cec5SDimitry Andric 
ReadInstruction()10340b57cec5SDimitry Andric bool EmulateInstructionMIPS::ReadInstruction() {
10350b57cec5SDimitry Andric   bool success = false;
10360b57cec5SDimitry Andric   m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
10370b57cec5SDimitry Andric                                 LLDB_INVALID_ADDRESS, &success);
10380b57cec5SDimitry Andric   if (success) {
10390b57cec5SDimitry Andric     Context read_inst_context;
10400b57cec5SDimitry Andric     read_inst_context.type = eContextReadOpcode;
10410b57cec5SDimitry Andric     read_inst_context.SetNoArgs();
10420b57cec5SDimitry Andric     m_opcode.SetOpcode32(
10430b57cec5SDimitry Andric         ReadMemoryUnsigned(read_inst_context, m_addr, 4, 0, &success),
10440b57cec5SDimitry Andric         GetByteOrder());
10450b57cec5SDimitry Andric   }
10460b57cec5SDimitry Andric   if (!success)
10470b57cec5SDimitry Andric     m_addr = LLDB_INVALID_ADDRESS;
10480b57cec5SDimitry Andric   return success;
10490b57cec5SDimitry Andric }
10500b57cec5SDimitry Andric 
EvaluateInstruction(uint32_t evaluate_options)10510b57cec5SDimitry Andric bool EmulateInstructionMIPS::EvaluateInstruction(uint32_t evaluate_options) {
10520b57cec5SDimitry Andric   bool success = false;
10530b57cec5SDimitry Andric   llvm::MCInst mc_insn;
10540b57cec5SDimitry Andric   uint64_t insn_size;
10550b57cec5SDimitry Andric   DataExtractor data;
10560b57cec5SDimitry Andric 
10570b57cec5SDimitry Andric   /* Keep the complexity of the decode logic with the llvm::MCDisassembler
10580b57cec5SDimitry Andric    * class. */
10590b57cec5SDimitry Andric   if (m_opcode.GetData(data)) {
10600b57cec5SDimitry Andric     llvm::MCDisassembler::DecodeStatus decode_status;
10610b57cec5SDimitry Andric     llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());
10620b57cec5SDimitry Andric     if (m_use_alt_disaasm)
1063480093f4SDimitry Andric       decode_status = m_alt_disasm->getInstruction(mc_insn, insn_size, raw_insn,
1064480093f4SDimitry Andric                                                    m_addr, llvm::nulls());
10650b57cec5SDimitry Andric     else
1066480093f4SDimitry Andric       decode_status = m_disasm->getInstruction(mc_insn, insn_size, raw_insn,
1067480093f4SDimitry Andric                                                m_addr, llvm::nulls());
10680b57cec5SDimitry Andric 
10690b57cec5SDimitry Andric     if (decode_status != llvm::MCDisassembler::Success)
10700b57cec5SDimitry Andric       return false;
10710b57cec5SDimitry Andric   }
10720b57cec5SDimitry Andric 
10730b57cec5SDimitry Andric   /*
10740b57cec5SDimitry Andric    * mc_insn.getOpcode() returns decoded opcode. However to make use
10750b57cec5SDimitry Andric    * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc".
10760b57cec5SDimitry Andric   */
10770b57cec5SDimitry Andric   const char *op_name = m_insn_info->getName(mc_insn.getOpcode()).data();
10780b57cec5SDimitry Andric 
10790b57cec5SDimitry Andric   if (op_name == nullptr)
10800b57cec5SDimitry Andric     return false;
10810b57cec5SDimitry Andric 
10820b57cec5SDimitry Andric   /*
10830b57cec5SDimitry Andric    * Decoding has been done already. Just get the call-back function
10840b57cec5SDimitry Andric    * and emulate the instruction.
10850b57cec5SDimitry Andric   */
10860b57cec5SDimitry Andric   MipsOpcode *opcode_data = GetOpcodeForInstruction(op_name);
10870b57cec5SDimitry Andric 
10880b57cec5SDimitry Andric   if (opcode_data == nullptr)
10890b57cec5SDimitry Andric     return false;
10900b57cec5SDimitry Andric 
10910b57cec5SDimitry Andric   uint64_t old_pc = 0, new_pc = 0;
10920b57cec5SDimitry Andric   const bool auto_advance_pc =
10930b57cec5SDimitry Andric       evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
10940b57cec5SDimitry Andric 
10950b57cec5SDimitry Andric   if (auto_advance_pc) {
10960b57cec5SDimitry Andric     old_pc =
10970b57cec5SDimitry Andric         ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
10980b57cec5SDimitry Andric     if (!success)
10990b57cec5SDimitry Andric       return false;
11000b57cec5SDimitry Andric   }
11010b57cec5SDimitry Andric 
11020b57cec5SDimitry Andric   /* emulate instruction */
11030b57cec5SDimitry Andric   success = (this->*opcode_data->callback)(mc_insn);
11040b57cec5SDimitry Andric   if (!success)
11050b57cec5SDimitry Andric     return false;
11060b57cec5SDimitry Andric 
11070b57cec5SDimitry Andric   if (auto_advance_pc) {
11080b57cec5SDimitry Andric     new_pc =
11090b57cec5SDimitry Andric         ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
11100b57cec5SDimitry Andric     if (!success)
11110b57cec5SDimitry Andric       return false;
11120b57cec5SDimitry Andric 
11130b57cec5SDimitry Andric     /* If we haven't changed the PC, change it here */
11140b57cec5SDimitry Andric     if (old_pc == new_pc) {
11150b57cec5SDimitry Andric       new_pc += 4;
11160b57cec5SDimitry Andric       Context context;
11170b57cec5SDimitry Andric       if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
11180b57cec5SDimitry Andric                                  new_pc))
11190b57cec5SDimitry Andric         return false;
11200b57cec5SDimitry Andric     }
11210b57cec5SDimitry Andric   }
11220b57cec5SDimitry Andric 
11230b57cec5SDimitry Andric   return true;
11240b57cec5SDimitry Andric }
11250b57cec5SDimitry Andric 
CreateFunctionEntryUnwind(UnwindPlan & unwind_plan)11260b57cec5SDimitry Andric bool EmulateInstructionMIPS::CreateFunctionEntryUnwind(
11270b57cec5SDimitry Andric     UnwindPlan &unwind_plan) {
11280b57cec5SDimitry Andric   unwind_plan.Clear();
11290b57cec5SDimitry Andric   unwind_plan.SetRegisterKind(eRegisterKindDWARF);
11300b57cec5SDimitry Andric 
11310b57cec5SDimitry Andric   UnwindPlan::RowSP row(new UnwindPlan::Row);
11320b57cec5SDimitry Andric   const bool can_replace = false;
11330b57cec5SDimitry Andric 
11340b57cec5SDimitry Andric   // Our previous Call Frame Address is the stack pointer
11350b57cec5SDimitry Andric   row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips, 0);
11360b57cec5SDimitry Andric 
11370b57cec5SDimitry Andric   // Our previous PC is in the RA
11380b57cec5SDimitry Andric   row->SetRegisterLocationToRegister(dwarf_pc_mips, dwarf_ra_mips, can_replace);
11390b57cec5SDimitry Andric 
11400b57cec5SDimitry Andric   unwind_plan.AppendRow(row);
11410b57cec5SDimitry Andric 
11420b57cec5SDimitry Andric   // All other registers are the same.
11430b57cec5SDimitry Andric   unwind_plan.SetSourceName("EmulateInstructionMIPS");
11440b57cec5SDimitry Andric   unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
11450b57cec5SDimitry Andric   unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
11469dba64beSDimitry Andric   unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
11470b57cec5SDimitry Andric   unwind_plan.SetReturnAddressRegister(dwarf_ra_mips);
11480b57cec5SDimitry Andric 
11490b57cec5SDimitry Andric   return true;
11500b57cec5SDimitry Andric }
11510b57cec5SDimitry Andric 
nonvolatile_reg_p(uint32_t regnum)11520b57cec5SDimitry Andric bool EmulateInstructionMIPS::nonvolatile_reg_p(uint32_t regnum) {
11530b57cec5SDimitry Andric   switch (regnum) {
11540b57cec5SDimitry Andric   case dwarf_r16_mips:
11550b57cec5SDimitry Andric   case dwarf_r17_mips:
11560b57cec5SDimitry Andric   case dwarf_r18_mips:
11570b57cec5SDimitry Andric   case dwarf_r19_mips:
11580b57cec5SDimitry Andric   case dwarf_r20_mips:
11590b57cec5SDimitry Andric   case dwarf_r21_mips:
11600b57cec5SDimitry Andric   case dwarf_r22_mips:
11610b57cec5SDimitry Andric   case dwarf_r23_mips:
11620b57cec5SDimitry Andric   case dwarf_gp_mips:
11630b57cec5SDimitry Andric   case dwarf_sp_mips:
11640b57cec5SDimitry Andric   case dwarf_r30_mips:
11650b57cec5SDimitry Andric   case dwarf_ra_mips:
11660b57cec5SDimitry Andric     return true;
11670b57cec5SDimitry Andric   default:
11680b57cec5SDimitry Andric     return false;
11690b57cec5SDimitry Andric   }
11700b57cec5SDimitry Andric   return false;
11710b57cec5SDimitry Andric }
11720b57cec5SDimitry Andric 
Emulate_ADDiu(llvm::MCInst & insn)11730b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_ADDiu(llvm::MCInst &insn) {
11740b57cec5SDimitry Andric   // ADDIU rt, rs, immediate
11750b57cec5SDimitry Andric   // GPR[rt] <- GPR[rs] + sign_extend(immediate)
11760b57cec5SDimitry Andric 
11770b57cec5SDimitry Andric   uint8_t dst, src;
11780b57cec5SDimitry Andric   bool success = false;
11790b57cec5SDimitry Andric   const uint32_t imm16 = insn.getOperand(2).getImm();
11800b57cec5SDimitry Andric   int64_t imm = SignedBits(imm16, 15, 0);
11810b57cec5SDimitry Andric 
11820b57cec5SDimitry Andric   dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
11830b57cec5SDimitry Andric   src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
11840b57cec5SDimitry Andric 
11850b57cec5SDimitry Andric   // If immediate value is greater then 2^16 - 1 then clang generate LUI,
11860b57cec5SDimitry Andric   // ADDIU, SUBU instructions in prolog. Example lui    $1, 0x2 addiu $1, $1,
11870b57cec5SDimitry Andric   // -0x5920 subu  $sp, $sp, $1 In this case, ADDIU dst and src will be same
11880b57cec5SDimitry Andric   // and not equal to sp
11890b57cec5SDimitry Andric   if (dst == src) {
11900b57cec5SDimitry Andric     Context context;
11910b57cec5SDimitry Andric 
11920b57cec5SDimitry Andric     /* read <src> register */
11930b57cec5SDimitry Andric     const int64_t src_opd_val = ReadRegisterUnsigned(
11940b57cec5SDimitry Andric         eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success);
11950b57cec5SDimitry Andric     if (!success)
11960b57cec5SDimitry Andric       return false;
11970b57cec5SDimitry Andric 
11980b57cec5SDimitry Andric     /* Check if this is daddiu sp, sp, imm16 */
11990b57cec5SDimitry Andric     if (dst == dwarf_sp_mips) {
12000b57cec5SDimitry Andric       uint64_t result = src_opd_val + imm;
1201bdd1243dSDimitry Andric       std::optional<RegisterInfo> reg_info_sp =
1202bdd1243dSDimitry Andric           GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);
1203bdd1243dSDimitry Andric       if (reg_info_sp)
1204bdd1243dSDimitry Andric         context.SetRegisterPlusOffset(*reg_info_sp, imm);
12050b57cec5SDimitry Andric 
12060b57cec5SDimitry Andric       /* We are allocating bytes on stack */
12070b57cec5SDimitry Andric       context.type = eContextAdjustStackPointer;
12080b57cec5SDimitry Andric 
12090b57cec5SDimitry Andric       WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);
12100b57cec5SDimitry Andric       return true;
12110b57cec5SDimitry Andric     }
12120b57cec5SDimitry Andric 
12130b57cec5SDimitry Andric     imm += src_opd_val;
12140b57cec5SDimitry Andric     context.SetImmediateSigned(imm);
12150b57cec5SDimitry Andric     context.type = eContextImmediate;
12160b57cec5SDimitry Andric 
12170b57cec5SDimitry Andric     if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
12180b57cec5SDimitry Andric                                dwarf_zero_mips + dst, imm))
12190b57cec5SDimitry Andric       return false;
12200b57cec5SDimitry Andric   }
12210b57cec5SDimitry Andric 
12220b57cec5SDimitry Andric   return true;
12230b57cec5SDimitry Andric }
12240b57cec5SDimitry Andric 
Emulate_SW(llvm::MCInst & insn)12250b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_SW(llvm::MCInst &insn) {
12260b57cec5SDimitry Andric   bool success = false;
12270b57cec5SDimitry Andric   uint32_t imm16 = insn.getOperand(2).getImm();
12280b57cec5SDimitry Andric   uint32_t imm = SignedBits(imm16, 15, 0);
12290b57cec5SDimitry Andric   uint32_t src, base;
12300b57cec5SDimitry Andric   int32_t address;
12310b57cec5SDimitry Andric   Context bad_vaddr_context;
12320b57cec5SDimitry Andric 
12330b57cec5SDimitry Andric   src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
12340b57cec5SDimitry Andric   base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
12350b57cec5SDimitry Andric 
1236bdd1243dSDimitry Andric   std::optional<RegisterInfo> reg_info_base =
1237bdd1243dSDimitry Andric       GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base);
1238bdd1243dSDimitry Andric   if (!reg_info_base)
12390b57cec5SDimitry Andric     return false;
12400b57cec5SDimitry Andric 
12410b57cec5SDimitry Andric   /* read base register */
12420b57cec5SDimitry Andric   address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
12430b57cec5SDimitry Andric                                           dwarf_zero_mips + base, 0, &success);
12440b57cec5SDimitry Andric   if (!success)
12450b57cec5SDimitry Andric     return false;
12460b57cec5SDimitry Andric 
12470b57cec5SDimitry Andric   /* destination address */
12480b57cec5SDimitry Andric   address = address + imm;
12490b57cec5SDimitry Andric 
12500b57cec5SDimitry Andric   /* Set the bad_vaddr register with base address used in the instruction */
12510b57cec5SDimitry Andric   bad_vaddr_context.type = eContextInvalid;
12520b57cec5SDimitry Andric   WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
12530b57cec5SDimitry Andric                         address);
12540b57cec5SDimitry Andric 
12550b57cec5SDimitry Andric   /* We look for sp based non-volatile register stores */
12560b57cec5SDimitry Andric   if (nonvolatile_reg_p(src)) {
1257bdd1243dSDimitry Andric     std::optional<RegisterInfo> reg_info_src =
1258bdd1243dSDimitry Andric         GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src);
1259bdd1243dSDimitry Andric     if (!reg_info_src)
12600b57cec5SDimitry Andric       return false;
12610b57cec5SDimitry Andric 
12620b57cec5SDimitry Andric     Context context;
12630b57cec5SDimitry Andric     context.type = eContextPushRegisterOnStack;
1264bdd1243dSDimitry Andric     context.SetRegisterToRegisterPlusOffset(*reg_info_src, *reg_info_base, 0);
12650b57cec5SDimitry Andric 
1266*06c3fb27SDimitry Andric     RegisterValue::BytesContainer buffer(reg_info_src->byte_size);
12670b57cec5SDimitry Andric     Status error;
12680b57cec5SDimitry Andric 
1269bdd1243dSDimitry Andric     std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);
1270bdd1243dSDimitry Andric     if (!data_src)
12710b57cec5SDimitry Andric       return false;
12720b57cec5SDimitry Andric 
1273*06c3fb27SDimitry Andric     if (data_src->GetAsMemoryData(*reg_info_src, buffer.data(),
1274bdd1243dSDimitry Andric                                   reg_info_src->byte_size, eByteOrderLittle,
1275bdd1243dSDimitry Andric                                   error) == 0)
12760b57cec5SDimitry Andric       return false;
12770b57cec5SDimitry Andric 
1278*06c3fb27SDimitry Andric     if (!WriteMemory(context, address, buffer.data(), reg_info_src->byte_size))
12790b57cec5SDimitry Andric       return false;
12800b57cec5SDimitry Andric 
12810b57cec5SDimitry Andric     return true;
12820b57cec5SDimitry Andric   }
12830b57cec5SDimitry Andric 
12840b57cec5SDimitry Andric   return false;
12850b57cec5SDimitry Andric }
12860b57cec5SDimitry Andric 
Emulate_LW(llvm::MCInst & insn)12870b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_LW(llvm::MCInst &insn) {
12880b57cec5SDimitry Andric   bool success = false;
12890b57cec5SDimitry Andric   uint32_t src, base;
12900b57cec5SDimitry Andric   int32_t imm, address;
12910b57cec5SDimitry Andric   Context bad_vaddr_context;
12920b57cec5SDimitry Andric 
12930b57cec5SDimitry Andric   src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
12940b57cec5SDimitry Andric   base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
12950b57cec5SDimitry Andric   imm = insn.getOperand(2).getImm();
12960b57cec5SDimitry Andric 
1297bdd1243dSDimitry Andric   if (GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))
12980b57cec5SDimitry Andric     return false;
12990b57cec5SDimitry Andric 
13000b57cec5SDimitry Andric   /* read base register */
13010b57cec5SDimitry Andric   address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
13020b57cec5SDimitry Andric                                           dwarf_zero_mips + base, 0, &success);
13030b57cec5SDimitry Andric   if (!success)
13040b57cec5SDimitry Andric     return false;
13050b57cec5SDimitry Andric 
13060b57cec5SDimitry Andric   /* destination address */
13070b57cec5SDimitry Andric   address = address + imm;
13080b57cec5SDimitry Andric 
13090b57cec5SDimitry Andric   /* Set the bad_vaddr register with base address used in the instruction */
13100b57cec5SDimitry Andric   bad_vaddr_context.type = eContextInvalid;
13110b57cec5SDimitry Andric   WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
13120b57cec5SDimitry Andric                         address);
13130b57cec5SDimitry Andric 
13140b57cec5SDimitry Andric   if (nonvolatile_reg_p(src)) {
13150b57cec5SDimitry Andric     RegisterValue data_src;
1316bdd1243dSDimitry Andric     std::optional<RegisterInfo> reg_info_src =
1317bdd1243dSDimitry Andric         GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src);
1318bdd1243dSDimitry Andric     if (!reg_info_src)
13190b57cec5SDimitry Andric       return false;
13200b57cec5SDimitry Andric 
13210b57cec5SDimitry Andric     Context context;
13220b57cec5SDimitry Andric     context.type = eContextPopRegisterOffStack;
13230b57cec5SDimitry Andric     context.SetAddress(address);
13240b57cec5SDimitry Andric 
1325bdd1243dSDimitry Andric     return WriteRegister(context, *reg_info_src, data_src);
13260b57cec5SDimitry Andric   }
13270b57cec5SDimitry Andric 
13280b57cec5SDimitry Andric   return false;
13290b57cec5SDimitry Andric }
13300b57cec5SDimitry Andric 
Emulate_SUBU_ADDU(llvm::MCInst & insn)13310b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_SUBU_ADDU(llvm::MCInst &insn) {
13320b57cec5SDimitry Andric   // SUBU sp, <src>, <rt>
13330b57cec5SDimitry Andric   // ADDU sp, <src>, <rt>
13340b57cec5SDimitry Andric   // ADDU dst, sp, <rt>
13350b57cec5SDimitry Andric 
13360b57cec5SDimitry Andric   bool success = false;
13370b57cec5SDimitry Andric   uint64_t result;
13380b57cec5SDimitry Andric   uint8_t src, dst, rt;
133981ad6265SDimitry Andric   llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
13400b57cec5SDimitry Andric 
13410b57cec5SDimitry Andric   dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
13420b57cec5SDimitry Andric   src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
13430b57cec5SDimitry Andric 
13440b57cec5SDimitry Andric   /* Check if sp is destination register */
13450b57cec5SDimitry Andric   if (dst == dwarf_sp_mips) {
13460b57cec5SDimitry Andric     rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
13470b57cec5SDimitry Andric 
13480b57cec5SDimitry Andric     /* read <src> register */
13490b57cec5SDimitry Andric     uint64_t src_opd_val = ReadRegisterUnsigned(
13500b57cec5SDimitry Andric         eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success);
13510b57cec5SDimitry Andric     if (!success)
13520b57cec5SDimitry Andric       return false;
13530b57cec5SDimitry Andric 
13540b57cec5SDimitry Andric     /* read <rt > register */
13550b57cec5SDimitry Andric     uint64_t rt_opd_val = ReadRegisterUnsigned(
13560b57cec5SDimitry Andric         eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
13570b57cec5SDimitry Andric     if (!success)
13580b57cec5SDimitry Andric       return false;
13590b57cec5SDimitry Andric 
136081ad6265SDimitry Andric     if (op_name.equals_insensitive("SUBU"))
13610b57cec5SDimitry Andric       result = src_opd_val - rt_opd_val;
13620b57cec5SDimitry Andric     else
13630b57cec5SDimitry Andric       result = src_opd_val + rt_opd_val;
13640b57cec5SDimitry Andric 
13650b57cec5SDimitry Andric     Context context;
1366bdd1243dSDimitry Andric     std::optional<RegisterInfo> reg_info_sp =
1367bdd1243dSDimitry Andric         GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);
1368bdd1243dSDimitry Andric     if (reg_info_sp)
1369bdd1243dSDimitry Andric       context.SetRegisterPlusOffset(*reg_info_sp, rt_opd_val);
13700b57cec5SDimitry Andric 
13710b57cec5SDimitry Andric     /* We are allocating bytes on stack */
13720b57cec5SDimitry Andric     context.type = eContextAdjustStackPointer;
13730b57cec5SDimitry Andric 
13740b57cec5SDimitry Andric     WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);
13750b57cec5SDimitry Andric 
13760b57cec5SDimitry Andric     return true;
13770b57cec5SDimitry Andric   } else if (src == dwarf_sp_mips) {
13780b57cec5SDimitry Andric     rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
13790b57cec5SDimitry Andric 
13800b57cec5SDimitry Andric     /* read <src> register */
13810b57cec5SDimitry Andric     uint64_t src_opd_val = ReadRegisterUnsigned(
13820b57cec5SDimitry Andric         eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success);
13830b57cec5SDimitry Andric     if (!success)
13840b57cec5SDimitry Andric       return false;
13850b57cec5SDimitry Andric 
13860b57cec5SDimitry Andric     /* read <rt> register */
13870b57cec5SDimitry Andric     uint64_t rt_opd_val = ReadRegisterUnsigned(
13880b57cec5SDimitry Andric         eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
13890b57cec5SDimitry Andric     if (!success)
13900b57cec5SDimitry Andric       return false;
13910b57cec5SDimitry Andric 
13920b57cec5SDimitry Andric     Context context;
13930b57cec5SDimitry Andric 
139481ad6265SDimitry Andric     if (op_name.equals_insensitive("SUBU"))
13950b57cec5SDimitry Andric       result = src_opd_val - rt_opd_val;
13960b57cec5SDimitry Andric     else
13970b57cec5SDimitry Andric       result = src_opd_val + rt_opd_val;
13980b57cec5SDimitry Andric 
13990b57cec5SDimitry Andric     context.SetImmediateSigned(result);
14000b57cec5SDimitry Andric     context.type = eContextImmediate;
14010b57cec5SDimitry Andric 
14020b57cec5SDimitry Andric     if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
14030b57cec5SDimitry Andric                                dwarf_zero_mips + dst, result))
14040b57cec5SDimitry Andric       return false;
14050b57cec5SDimitry Andric   }
14060b57cec5SDimitry Andric 
14070b57cec5SDimitry Andric   return true;
14080b57cec5SDimitry Andric }
14090b57cec5SDimitry Andric 
Emulate_LUI(llvm::MCInst & insn)14100b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_LUI(llvm::MCInst &insn) {
14110b57cec5SDimitry Andric   // LUI rt, immediate
14120b57cec5SDimitry Andric   // GPR[rt] <- sign_extend(immediate << 16)
14130b57cec5SDimitry Andric 
14140b57cec5SDimitry Andric   const uint32_t imm32 = insn.getOperand(1).getImm() << 16;
14150b57cec5SDimitry Andric   int64_t imm = SignedBits(imm32, 31, 0);
14160b57cec5SDimitry Andric   uint8_t rt;
14170b57cec5SDimitry Andric   Context context;
14180b57cec5SDimitry Andric 
14190b57cec5SDimitry Andric   rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
14200b57cec5SDimitry Andric   context.SetImmediateSigned(imm);
14210b57cec5SDimitry Andric   context.type = eContextImmediate;
14220b57cec5SDimitry Andric 
14230b57cec5SDimitry Andric   return WriteRegisterUnsigned(context, eRegisterKindDWARF,
14240b57cec5SDimitry Andric                                dwarf_zero_mips + rt, imm);
14250b57cec5SDimitry Andric }
14260b57cec5SDimitry Andric 
Emulate_ADDIUSP(llvm::MCInst & insn)14270b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_ADDIUSP(llvm::MCInst &insn) {
14280b57cec5SDimitry Andric   bool success = false;
14290b57cec5SDimitry Andric   const uint32_t imm9 = insn.getOperand(0).getImm();
14300b57cec5SDimitry Andric   uint64_t result;
14310b57cec5SDimitry Andric 
14320b57cec5SDimitry Andric   // This instruction operates implicitly on stack pointer, so read <sp>
14330b57cec5SDimitry Andric   // register.
14340b57cec5SDimitry Andric   uint64_t src_opd_val =
14350b57cec5SDimitry Andric       ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_sp_mips, 0, &success);
14360b57cec5SDimitry Andric   if (!success)
14370b57cec5SDimitry Andric     return false;
14380b57cec5SDimitry Andric 
14390b57cec5SDimitry Andric   result = src_opd_val + imm9;
14400b57cec5SDimitry Andric 
14410b57cec5SDimitry Andric   Context context;
1442bdd1243dSDimitry Andric   std::optional<RegisterInfo> reg_info_sp =
1443bdd1243dSDimitry Andric       GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);
1444bdd1243dSDimitry Andric   if (reg_info_sp)
1445bdd1243dSDimitry Andric     context.SetRegisterPlusOffset(*reg_info_sp, imm9);
14460b57cec5SDimitry Andric 
14470b57cec5SDimitry Andric   // We are adjusting the stack.
14480b57cec5SDimitry Andric   context.type = eContextAdjustStackPointer;
14490b57cec5SDimitry Andric 
14500b57cec5SDimitry Andric   WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);
14510b57cec5SDimitry Andric   return true;
14520b57cec5SDimitry Andric }
14530b57cec5SDimitry Andric 
Emulate_ADDIUS5(llvm::MCInst & insn)14540b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_ADDIUS5(llvm::MCInst &insn) {
14550b57cec5SDimitry Andric   bool success = false;
14560b57cec5SDimitry Andric   uint32_t base;
14570b57cec5SDimitry Andric   const uint32_t imm4 = insn.getOperand(2).getImm();
14580b57cec5SDimitry Andric   uint64_t result;
14590b57cec5SDimitry Andric 
14600b57cec5SDimitry Andric   // The source and destination register is same for this instruction.
14610b57cec5SDimitry Andric   base = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
14620b57cec5SDimitry Andric 
14630b57cec5SDimitry Andric   // We are looking for stack adjustment only
14640b57cec5SDimitry Andric   if (base == dwarf_sp_mips) {
14650b57cec5SDimitry Andric     // Read stack pointer register
14660b57cec5SDimitry Andric     uint64_t src_opd_val = ReadRegisterUnsigned(
14670b57cec5SDimitry Andric         eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
14680b57cec5SDimitry Andric     if (!success)
14690b57cec5SDimitry Andric       return false;
14700b57cec5SDimitry Andric 
14710b57cec5SDimitry Andric     result = src_opd_val + imm4;
14720b57cec5SDimitry Andric 
14730b57cec5SDimitry Andric     Context context;
1474bdd1243dSDimitry Andric     std::optional<RegisterInfo> reg_info_sp =
1475bdd1243dSDimitry Andric         GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);
1476bdd1243dSDimitry Andric     if (reg_info_sp)
1477bdd1243dSDimitry Andric       context.SetRegisterPlusOffset(*reg_info_sp, imm4);
14780b57cec5SDimitry Andric 
14790b57cec5SDimitry Andric     // We are adjusting the stack.
14800b57cec5SDimitry Andric     context.type = eContextAdjustStackPointer;
14810b57cec5SDimitry Andric 
14820b57cec5SDimitry Andric     WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);
14830b57cec5SDimitry Andric   }
14840b57cec5SDimitry Andric 
14850b57cec5SDimitry Andric   return true;
14860b57cec5SDimitry Andric }
14870b57cec5SDimitry Andric 
Emulate_SWSP(llvm::MCInst & insn)14880b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_SWSP(llvm::MCInst &insn) {
14890b57cec5SDimitry Andric   bool success = false;
14900b57cec5SDimitry Andric   uint32_t imm5 = insn.getOperand(2).getImm();
14910b57cec5SDimitry Andric   uint32_t src, base;
14920b57cec5SDimitry Andric   Context bad_vaddr_context;
14930b57cec5SDimitry Andric   uint32_t address;
14940b57cec5SDimitry Andric 
14950b57cec5SDimitry Andric   src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
14960b57cec5SDimitry Andric   base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
14970b57cec5SDimitry Andric 
1498bdd1243dSDimitry Andric   std::optional<RegisterInfo> reg_info_base =
1499bdd1243dSDimitry Andric       GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base);
1500bdd1243dSDimitry Andric   if (!reg_info_base)
15010b57cec5SDimitry Andric     return false;
15020b57cec5SDimitry Andric 
15030b57cec5SDimitry Andric   // read base register
15040b57cec5SDimitry Andric   address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0,
15050b57cec5SDimitry Andric                                  &success);
15060b57cec5SDimitry Andric   if (!success)
15070b57cec5SDimitry Andric     return false;
15080b57cec5SDimitry Andric 
15090b57cec5SDimitry Andric   // destination address
15100b57cec5SDimitry Andric   address = address + imm5;
15110b57cec5SDimitry Andric 
15120b57cec5SDimitry Andric   // We use bad_vaddr_context to store base address which is used by H/W
15130b57cec5SDimitry Andric   // watchpoint Set the bad_vaddr register with base address used in the
15140b57cec5SDimitry Andric   // instruction
15150b57cec5SDimitry Andric   bad_vaddr_context.type = eContextInvalid;
15160b57cec5SDimitry Andric   WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
15170b57cec5SDimitry Andric                         address);
15180b57cec5SDimitry Andric 
15190b57cec5SDimitry Andric   // We look for sp based non-volatile register stores.
15200b57cec5SDimitry Andric   if (base == dwarf_sp_mips && nonvolatile_reg_p(src)) {
15210b57cec5SDimitry Andric     RegisterInfo reg_info_src = {};
15220b57cec5SDimitry Andric     Context context;
15230b57cec5SDimitry Andric     context.type = eContextPushRegisterOnStack;
1524bdd1243dSDimitry Andric     context.SetRegisterToRegisterPlusOffset(reg_info_src, *reg_info_base, 0);
15250b57cec5SDimitry Andric 
1526*06c3fb27SDimitry Andric     RegisterValue::BytesContainer buffer(reg_info_src.byte_size);
15270b57cec5SDimitry Andric     Status error;
15280b57cec5SDimitry Andric 
1529bdd1243dSDimitry Andric     std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);
1530bdd1243dSDimitry Andric     if (!data_src)
15310b57cec5SDimitry Andric       return false;
15320b57cec5SDimitry Andric 
1533*06c3fb27SDimitry Andric     if (data_src->GetAsMemoryData(reg_info_src, buffer.data(),
1534*06c3fb27SDimitry Andric                                   reg_info_src.byte_size, eByteOrderLittle,
1535*06c3fb27SDimitry Andric                                   error) == 0)
15360b57cec5SDimitry Andric       return false;
15370b57cec5SDimitry Andric 
1538*06c3fb27SDimitry Andric     if (!WriteMemory(context, address, buffer.data(), reg_info_src.byte_size))
15390b57cec5SDimitry Andric       return false;
15400b57cec5SDimitry Andric 
15410b57cec5SDimitry Andric     return true;
15420b57cec5SDimitry Andric   }
15430b57cec5SDimitry Andric 
15440b57cec5SDimitry Andric   return false;
15450b57cec5SDimitry Andric }
15460b57cec5SDimitry Andric 
15470b57cec5SDimitry Andric /* Emulate SWM16,SWM32 and SWP instruction.
15480b57cec5SDimitry Andric 
15490b57cec5SDimitry Andric    SWM16 always has stack pointer as a base register (but it is still available
15500b57cec5SDimitry Andric    in MCInst as an operand).
15510b57cec5SDimitry Andric    SWM32 and SWP can have base register other than stack pointer.
15520b57cec5SDimitry Andric */
Emulate_SWM16_32(llvm::MCInst & insn)15530b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_SWM16_32(llvm::MCInst &insn) {
15540b57cec5SDimitry Andric   bool success = false;
15550b57cec5SDimitry Andric   uint32_t src, base;
15560b57cec5SDimitry Andric   uint32_t num_operands = insn.getNumOperands(); // No of operands vary based on
15570b57cec5SDimitry Andric                                                  // no of regs to store.
15580b57cec5SDimitry Andric 
15590b57cec5SDimitry Andric   // Base register is second last operand of the instruction.
15600b57cec5SDimitry Andric   base =
15610b57cec5SDimitry Andric       m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
15620b57cec5SDimitry Andric 
15630b57cec5SDimitry Andric   // We are looking for sp based stores so if base is not a stack pointer then
15640b57cec5SDimitry Andric   // don't proceed.
15650b57cec5SDimitry Andric   if (base != dwarf_sp_mips)
15660b57cec5SDimitry Andric     return false;
15670b57cec5SDimitry Andric 
15680b57cec5SDimitry Andric   // offset is always the last operand.
15690b57cec5SDimitry Andric   uint32_t offset = insn.getOperand(num_operands - 1).getImm();
15700b57cec5SDimitry Andric 
1571bdd1243dSDimitry Andric   std::optional<RegisterInfo> reg_info_base =
1572bdd1243dSDimitry Andric       GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base);
1573bdd1243dSDimitry Andric   if (!reg_info_base)
15740b57cec5SDimitry Andric     return false;
15750b57cec5SDimitry Andric 
15760b57cec5SDimitry Andric   // read SP
15770b57cec5SDimitry Andric   uint32_t base_address = ReadRegisterUnsigned(
15780b57cec5SDimitry Andric       eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
15790b57cec5SDimitry Andric   if (!success)
15800b57cec5SDimitry Andric     return false;
15810b57cec5SDimitry Andric 
15820b57cec5SDimitry Andric   // Resulting base addrss
15830b57cec5SDimitry Andric   base_address = base_address + offset;
15840b57cec5SDimitry Andric 
15850b57cec5SDimitry Andric   // Total no of registers to be stored are num_operands-2.
15860b57cec5SDimitry Andric   for (uint32_t i = 0; i < num_operands - 2; i++) {
15870b57cec5SDimitry Andric     // Get the register number to be stored.
15880b57cec5SDimitry Andric     src = m_reg_info->getEncodingValue(insn.getOperand(i).getReg());
15890b57cec5SDimitry Andric 
15900b57cec5SDimitry Andric     /*
15910b57cec5SDimitry Andric         Record only non-volatile stores.
15920b57cec5SDimitry Andric         This check is required for SWP instruction because source operand could
15930b57cec5SDimitry Andric        be any register.
15940b57cec5SDimitry Andric         SWM16 and SWM32 instruction always has saved registers as source
15950b57cec5SDimitry Andric        operands.
15960b57cec5SDimitry Andric     */
15970b57cec5SDimitry Andric     if (!nonvolatile_reg_p(src))
15980b57cec5SDimitry Andric       return false;
15990b57cec5SDimitry Andric 
1600bdd1243dSDimitry Andric     std::optional<RegisterInfo> reg_info_src =
1601bdd1243dSDimitry Andric         GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src);
1602bdd1243dSDimitry Andric     if (!reg_info_src)
16030b57cec5SDimitry Andric       return false;
16040b57cec5SDimitry Andric 
16050b57cec5SDimitry Andric     Context context;
16060b57cec5SDimitry Andric     context.type = eContextPushRegisterOnStack;
1607bdd1243dSDimitry Andric     context.SetRegisterToRegisterPlusOffset(*reg_info_src, *reg_info_base, 0);
16080b57cec5SDimitry Andric 
1609*06c3fb27SDimitry Andric     RegisterValue::BytesContainer buffer(reg_info_src->byte_size);
16100b57cec5SDimitry Andric     Status error;
16110b57cec5SDimitry Andric 
1612bdd1243dSDimitry Andric     std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);
1613bdd1243dSDimitry Andric     if (!data_src)
16140b57cec5SDimitry Andric       return false;
16150b57cec5SDimitry Andric 
1616*06c3fb27SDimitry Andric     if (data_src->GetAsMemoryData(*reg_info_src, buffer.data(),
1617bdd1243dSDimitry Andric                                   reg_info_src->byte_size, eByteOrderLittle,
1618bdd1243dSDimitry Andric                                   error) == 0)
16190b57cec5SDimitry Andric       return false;
16200b57cec5SDimitry Andric 
1621*06c3fb27SDimitry Andric     if (!WriteMemory(context, base_address, buffer.data(),
1622*06c3fb27SDimitry Andric                      reg_info_src->byte_size))
16230b57cec5SDimitry Andric       return false;
16240b57cec5SDimitry Andric 
16250b57cec5SDimitry Andric     // Stack address for next register
1626bdd1243dSDimitry Andric     base_address = base_address + reg_info_src->byte_size;
16270b57cec5SDimitry Andric   }
16280b57cec5SDimitry Andric   return true;
16290b57cec5SDimitry Andric }
16300b57cec5SDimitry Andric 
Emulate_LWSP(llvm::MCInst & insn)16310b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_LWSP(llvm::MCInst &insn) {
16320b57cec5SDimitry Andric   bool success = false;
16330b57cec5SDimitry Andric   uint32_t src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
16340b57cec5SDimitry Andric   uint32_t base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
16350b57cec5SDimitry Andric   uint32_t imm5 = insn.getOperand(2).getImm();
16360b57cec5SDimitry Andric   Context bad_vaddr_context;
16370b57cec5SDimitry Andric 
1638bdd1243dSDimitry Andric   if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))
16390b57cec5SDimitry Andric     return false;
16400b57cec5SDimitry Andric 
16410b57cec5SDimitry Andric   // read base register
16420b57cec5SDimitry Andric   uint32_t base_address = ReadRegisterUnsigned(
16430b57cec5SDimitry Andric       eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
16440b57cec5SDimitry Andric   if (!success)
16450b57cec5SDimitry Andric     return false;
16460b57cec5SDimitry Andric 
16470b57cec5SDimitry Andric   base_address = base_address + imm5;
16480b57cec5SDimitry Andric 
16490b57cec5SDimitry Andric   // We use bad_vaddr_context to store base address which is used by H/W
16500b57cec5SDimitry Andric   // watchpoint Set the bad_vaddr register with base address used in the
16510b57cec5SDimitry Andric   // instruction
16520b57cec5SDimitry Andric   bad_vaddr_context.type = eContextInvalid;
16530b57cec5SDimitry Andric   WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
16540b57cec5SDimitry Andric                         base_address);
16550b57cec5SDimitry Andric 
16560b57cec5SDimitry Andric   if (base == dwarf_sp_mips && nonvolatile_reg_p(src)) {
16570b57cec5SDimitry Andric     RegisterValue data_src;
1658bdd1243dSDimitry Andric     std::optional<RegisterInfo> reg_info_src =
1659bdd1243dSDimitry Andric         GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src);
1660bdd1243dSDimitry Andric     if (!reg_info_src)
16610b57cec5SDimitry Andric       return false;
16620b57cec5SDimitry Andric 
16630b57cec5SDimitry Andric     Context context;
16640b57cec5SDimitry Andric     context.type = eContextPopRegisterOffStack;
16650b57cec5SDimitry Andric     context.SetAddress(base_address);
16660b57cec5SDimitry Andric 
1667bdd1243dSDimitry Andric     return WriteRegister(context, *reg_info_src, data_src);
16680b57cec5SDimitry Andric   }
16690b57cec5SDimitry Andric 
16700b57cec5SDimitry Andric   return false;
16710b57cec5SDimitry Andric }
16720b57cec5SDimitry Andric 
16730b57cec5SDimitry Andric /* Emulate LWM16, LWM32 and LWP instructions.
16740b57cec5SDimitry Andric 
16750b57cec5SDimitry Andric    LWM16 always has stack pointer as a base register (but it is still available
16760b57cec5SDimitry Andric    in MCInst as an operand).
16770b57cec5SDimitry Andric    LWM32 and LWP can have base register other than stack pointer.
16780b57cec5SDimitry Andric */
Emulate_LWM16_32(llvm::MCInst & insn)16790b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_LWM16_32(llvm::MCInst &insn) {
16800b57cec5SDimitry Andric   bool success = false;
16810b57cec5SDimitry Andric   uint32_t dst, base;
16820b57cec5SDimitry Andric   uint32_t num_operands = insn.getNumOperands(); // No of operands vary based on
16830b57cec5SDimitry Andric                                                  // no of regs to store.
16840b57cec5SDimitry Andric   uint32_t imm = insn.getOperand(num_operands - 1)
16850b57cec5SDimitry Andric                      .getImm(); // imm is the last operand in the instruction.
16860b57cec5SDimitry Andric 
16870b57cec5SDimitry Andric   // Base register is second last operand of the instruction.
16880b57cec5SDimitry Andric   base =
16890b57cec5SDimitry Andric       m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
16900b57cec5SDimitry Andric 
16910b57cec5SDimitry Andric   // We are looking for sp based loads so if base is not a stack pointer then
16920b57cec5SDimitry Andric   // don't proceed.
16930b57cec5SDimitry Andric   if (base != dwarf_sp_mips)
16940b57cec5SDimitry Andric     return false;
16950b57cec5SDimitry Andric 
16960b57cec5SDimitry Andric   uint32_t base_address = ReadRegisterUnsigned(
16970b57cec5SDimitry Andric       eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
16980b57cec5SDimitry Andric   if (!success)
16990b57cec5SDimitry Andric     return false;
17000b57cec5SDimitry Andric 
17010b57cec5SDimitry Andric   base_address = base_address + imm;
17020b57cec5SDimitry Andric 
17030b57cec5SDimitry Andric   RegisterValue data_dst;
17040b57cec5SDimitry Andric 
17050b57cec5SDimitry Andric   // Total no of registers to be re-stored are num_operands-2.
17060b57cec5SDimitry Andric   for (uint32_t i = 0; i < num_operands - 2; i++) {
17070b57cec5SDimitry Andric     // Get the register number to be re-stored.
17080b57cec5SDimitry Andric     dst = m_reg_info->getEncodingValue(insn.getOperand(i).getReg());
17090b57cec5SDimitry Andric 
17100b57cec5SDimitry Andric     /*
17110b57cec5SDimitry Andric         Record only non-volatile loads.
17120b57cec5SDimitry Andric         This check is required for LWP instruction because destination operand
17130b57cec5SDimitry Andric        could be any register.
17140b57cec5SDimitry Andric         LWM16 and LWM32 instruction always has saved registers as destination
17150b57cec5SDimitry Andric        operands.
17160b57cec5SDimitry Andric     */
17170b57cec5SDimitry Andric     if (!nonvolatile_reg_p(dst))
17180b57cec5SDimitry Andric       return false;
17190b57cec5SDimitry Andric 
1720bdd1243dSDimitry Andric     std::optional<RegisterInfo> reg_info_dst =
1721bdd1243dSDimitry Andric         GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + dst);
1722bdd1243dSDimitry Andric     if (!reg_info_dst)
17230b57cec5SDimitry Andric       return false;
17240b57cec5SDimitry Andric 
17250b57cec5SDimitry Andric     Context context;
17260b57cec5SDimitry Andric     context.type = eContextPopRegisterOffStack;
17270b57cec5SDimitry Andric     context.SetAddress(base_address + (i * 4));
17280b57cec5SDimitry Andric 
1729bdd1243dSDimitry Andric     if (!WriteRegister(context, *reg_info_dst, data_dst))
17300b57cec5SDimitry Andric       return false;
17310b57cec5SDimitry Andric   }
17320b57cec5SDimitry Andric 
17330b57cec5SDimitry Andric   return true;
17340b57cec5SDimitry Andric }
17350b57cec5SDimitry Andric 
Emulate_JRADDIUSP(llvm::MCInst & insn)17360b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_JRADDIUSP(llvm::MCInst &insn) {
17370b57cec5SDimitry Andric   bool success = false;
17380b57cec5SDimitry Andric   int32_t imm5 = insn.getOperand(0).getImm();
17390b57cec5SDimitry Andric 
17400b57cec5SDimitry Andric   /* JRADDIUSP immediate
17410b57cec5SDimitry Andric   *       PC <- RA
17420b57cec5SDimitry Andric   *       SP <- SP + zero_extend(Immediate << 2)
17430b57cec5SDimitry Andric   */
17440b57cec5SDimitry Andric 
17450b57cec5SDimitry Andric   // This instruction operates implicitly on stack pointer, so read <sp>
17460b57cec5SDimitry Andric   // register.
17470b57cec5SDimitry Andric   int32_t src_opd_val =
17480b57cec5SDimitry Andric       ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_sp_mips, 0, &success);
17490b57cec5SDimitry Andric   if (!success)
17500b57cec5SDimitry Andric     return false;
17510b57cec5SDimitry Andric 
17520b57cec5SDimitry Andric   int32_t ra_val =
17530b57cec5SDimitry Andric       ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_ra_mips, 0, &success);
17540b57cec5SDimitry Andric   if (!success)
17550b57cec5SDimitry Andric     return false;
17560b57cec5SDimitry Andric 
17570b57cec5SDimitry Andric   int32_t result = src_opd_val + imm5;
17580b57cec5SDimitry Andric 
17590b57cec5SDimitry Andric   Context context;
17600b57cec5SDimitry Andric 
17610b57cec5SDimitry Andric   // Update the PC
17620b57cec5SDimitry Andric   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
17630b57cec5SDimitry Andric                              ra_val))
17640b57cec5SDimitry Andric     return false;
17650b57cec5SDimitry Andric 
1766bdd1243dSDimitry Andric   std::optional<RegisterInfo> reg_info_sp =
1767bdd1243dSDimitry Andric       GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);
1768bdd1243dSDimitry Andric   if (reg_info_sp)
1769bdd1243dSDimitry Andric     context.SetRegisterPlusOffset(*reg_info_sp, imm5);
17700b57cec5SDimitry Andric 
17710b57cec5SDimitry Andric   // We are adjusting stack
17720b57cec5SDimitry Andric   context.type = eContextAdjustStackPointer;
17730b57cec5SDimitry Andric 
17740b57cec5SDimitry Andric   // update SP
17750b57cec5SDimitry Andric   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips,
17760b57cec5SDimitry Andric                                result);
17770b57cec5SDimitry Andric }
17780b57cec5SDimitry Andric 
IsAdd64bitOverflow(int32_t a,int32_t b)17790b57cec5SDimitry Andric static int IsAdd64bitOverflow(int32_t a, int32_t b) {
17800b57cec5SDimitry Andric   int32_t r = (uint32_t)a + (uint32_t)b;
17810b57cec5SDimitry Andric   return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
17820b57cec5SDimitry Andric }
17830b57cec5SDimitry Andric 
17840b57cec5SDimitry Andric /*
17850b57cec5SDimitry Andric     Emulate below MIPS branch instructions.
17860b57cec5SDimitry Andric     BEQ, BNE : Branch on condition
17870b57cec5SDimitry Andric     BEQL, BNEL : Branch likely
17880b57cec5SDimitry Andric */
Emulate_BXX_3ops(llvm::MCInst & insn)17890b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_BXX_3ops(llvm::MCInst &insn) {
17900b57cec5SDimitry Andric   bool success = false;
17910b57cec5SDimitry Andric   uint32_t rs, rt;
17920b57cec5SDimitry Andric   int32_t offset, pc, target = 0, rs_val, rt_val;
179381ad6265SDimitry Andric   llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
17940b57cec5SDimitry Andric 
17950b57cec5SDimitry Andric   rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
17960b57cec5SDimitry Andric   rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
17970b57cec5SDimitry Andric   offset = insn.getOperand(2).getImm();
17980b57cec5SDimitry Andric 
17990b57cec5SDimitry Andric   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
18000b57cec5SDimitry Andric   if (!success)
18010b57cec5SDimitry Andric     return false;
18020b57cec5SDimitry Andric 
18030b57cec5SDimitry Andric   rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
18040b57cec5SDimitry Andric                                          dwarf_zero_mips + rs, 0, &success);
18050b57cec5SDimitry Andric   if (!success)
18060b57cec5SDimitry Andric     return false;
18070b57cec5SDimitry Andric 
18080b57cec5SDimitry Andric   rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
18090b57cec5SDimitry Andric                                          dwarf_zero_mips + rt, 0, &success);
18100b57cec5SDimitry Andric   if (!success)
18110b57cec5SDimitry Andric     return false;
18120b57cec5SDimitry Andric 
181381ad6265SDimitry Andric   if (op_name.equals_insensitive("BEQ") || op_name.equals_insensitive("BEQL")) {
18140b57cec5SDimitry Andric     if (rs_val == rt_val)
18150b57cec5SDimitry Andric       target = pc + offset;
18160b57cec5SDimitry Andric     else
18170b57cec5SDimitry Andric       target = pc + 8;
181881ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BNE") ||
181981ad6265SDimitry Andric              op_name.equals_insensitive("BNEL")) {
18200b57cec5SDimitry Andric     if (rs_val != rt_val)
18210b57cec5SDimitry Andric       target = pc + offset;
18220b57cec5SDimitry Andric     else
18230b57cec5SDimitry Andric       target = pc + 8;
18240b57cec5SDimitry Andric   }
18250b57cec5SDimitry Andric 
18260b57cec5SDimitry Andric   Context context;
18270b57cec5SDimitry Andric   context.type = eContextRelativeBranchImmediate;
18280b57cec5SDimitry Andric   context.SetImmediate(offset);
18290b57cec5SDimitry Andric 
18300b57cec5SDimitry Andric   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
18310b57cec5SDimitry Andric                                target);
18320b57cec5SDimitry Andric }
18330b57cec5SDimitry Andric 
18340b57cec5SDimitry Andric /*
18350b57cec5SDimitry Andric     Emulate below MIPS branch instructions.
18360b57cec5SDimitry Andric     BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch
18370b57cec5SDimitry Andric    instructions with no delay slot
18380b57cec5SDimitry Andric */
Emulate_BXX_3ops_C(llvm::MCInst & insn)18390b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_BXX_3ops_C(llvm::MCInst &insn) {
18400b57cec5SDimitry Andric   bool success = false;
18410b57cec5SDimitry Andric   uint32_t rs, rt;
18420b57cec5SDimitry Andric   int32_t offset, pc, target = 0, rs_val, rt_val;
184381ad6265SDimitry Andric   llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
18440b57cec5SDimitry Andric   uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
18450b57cec5SDimitry Andric 
18460b57cec5SDimitry Andric   rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
18470b57cec5SDimitry Andric   rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
18480b57cec5SDimitry Andric   offset = insn.getOperand(2).getImm();
18490b57cec5SDimitry Andric 
18500b57cec5SDimitry Andric   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
18510b57cec5SDimitry Andric   if (!success)
18520b57cec5SDimitry Andric     return false;
18530b57cec5SDimitry Andric 
18540b57cec5SDimitry Andric   rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
18550b57cec5SDimitry Andric                                          dwarf_zero_mips + rs, 0, &success);
18560b57cec5SDimitry Andric   if (!success)
18570b57cec5SDimitry Andric     return false;
18580b57cec5SDimitry Andric 
18590b57cec5SDimitry Andric   rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
18600b57cec5SDimitry Andric                                          dwarf_zero_mips + rt, 0, &success);
18610b57cec5SDimitry Andric   if (!success)
18620b57cec5SDimitry Andric     return false;
18630b57cec5SDimitry Andric 
186481ad6265SDimitry Andric   if (op_name.equals_insensitive("BEQC")) {
18650b57cec5SDimitry Andric     if (rs_val == rt_val)
18660b57cec5SDimitry Andric       target = pc + offset;
18670b57cec5SDimitry Andric     else
18680b57cec5SDimitry Andric       target = pc + 4;
186981ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BNEC")) {
18700b57cec5SDimitry Andric     if (rs_val != rt_val)
18710b57cec5SDimitry Andric       target = pc + offset;
18720b57cec5SDimitry Andric     else
18730b57cec5SDimitry Andric       target = pc + 4;
187481ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BLTC")) {
18750b57cec5SDimitry Andric     if (rs_val < rt_val)
18760b57cec5SDimitry Andric       target = pc + offset;
18770b57cec5SDimitry Andric     else
18780b57cec5SDimitry Andric       target = pc + 4;
187981ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BGEC")) {
18800b57cec5SDimitry Andric     if (rs_val >= rt_val)
18810b57cec5SDimitry Andric       target = pc + offset;
18820b57cec5SDimitry Andric     else
18830b57cec5SDimitry Andric       target = pc + 4;
188481ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BLTUC")) {
18850b57cec5SDimitry Andric     if (rs_val < rt_val)
18860b57cec5SDimitry Andric       target = pc + offset;
18870b57cec5SDimitry Andric     else
18880b57cec5SDimitry Andric       target = pc + 4;
188981ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BGEUC")) {
18900b57cec5SDimitry Andric     if ((uint32_t)rs_val >= (uint32_t)rt_val)
18910b57cec5SDimitry Andric       target = pc + offset;
18920b57cec5SDimitry Andric     else
18930b57cec5SDimitry Andric       target = pc + 4;
189481ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BOVC")) {
18950b57cec5SDimitry Andric     if (IsAdd64bitOverflow(rs_val, rt_val))
18960b57cec5SDimitry Andric       target = pc + offset;
18970b57cec5SDimitry Andric     else
18980b57cec5SDimitry Andric       target = pc + 4;
189981ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BNVC")) {
19000b57cec5SDimitry Andric     if (!IsAdd64bitOverflow(rs_val, rt_val))
19010b57cec5SDimitry Andric       target = pc + offset;
19020b57cec5SDimitry Andric     else
19030b57cec5SDimitry Andric       target = pc + 4;
19040b57cec5SDimitry Andric   }
19050b57cec5SDimitry Andric 
19060b57cec5SDimitry Andric   Context context;
19070b57cec5SDimitry Andric   context.type = eContextRelativeBranchImmediate;
19080b57cec5SDimitry Andric   context.SetImmediate(current_inst_size + offset);
19090b57cec5SDimitry Andric 
19100b57cec5SDimitry Andric   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
19110b57cec5SDimitry Andric                                target);
19120b57cec5SDimitry Andric }
19130b57cec5SDimitry Andric 
19140b57cec5SDimitry Andric /*
19150b57cec5SDimitry Andric     Emulate below MIPS conditional branch and link instructions.
19160b57cec5SDimitry Andric     BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches
19170b57cec5SDimitry Andric */
Emulate_Bcond_Link_C(llvm::MCInst & insn)19180b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_Bcond_Link_C(llvm::MCInst &insn) {
19190b57cec5SDimitry Andric   bool success = false;
19200b57cec5SDimitry Andric   uint32_t rs;
19210b57cec5SDimitry Andric   int32_t offset, pc, target = 0;
19220b57cec5SDimitry Andric   int32_t rs_val;
192381ad6265SDimitry Andric   llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
19240b57cec5SDimitry Andric 
19250b57cec5SDimitry Andric   rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
19260b57cec5SDimitry Andric   offset = insn.getOperand(1).getImm();
19270b57cec5SDimitry Andric 
19280b57cec5SDimitry Andric   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
19290b57cec5SDimitry Andric   if (!success)
19300b57cec5SDimitry Andric     return false;
19310b57cec5SDimitry Andric 
19320b57cec5SDimitry Andric   rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
19330b57cec5SDimitry Andric                                          dwarf_zero_mips + rs, 0, &success);
19340b57cec5SDimitry Andric   if (!success)
19350b57cec5SDimitry Andric     return false;
19360b57cec5SDimitry Andric 
193781ad6265SDimitry Andric   if (op_name.equals_insensitive("BLEZALC")) {
19380b57cec5SDimitry Andric     if (rs_val <= 0)
19390b57cec5SDimitry Andric       target = pc + offset;
19400b57cec5SDimitry Andric     else
19410b57cec5SDimitry Andric       target = pc + 4;
194281ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BGEZALC")) {
19430b57cec5SDimitry Andric     if (rs_val >= 0)
19440b57cec5SDimitry Andric       target = pc + offset;
19450b57cec5SDimitry Andric     else
19460b57cec5SDimitry Andric       target = pc + 4;
194781ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BLTZALC")) {
19480b57cec5SDimitry Andric     if (rs_val < 0)
19490b57cec5SDimitry Andric       target = pc + offset;
19500b57cec5SDimitry Andric     else
19510b57cec5SDimitry Andric       target = pc + 4;
195281ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BGTZALC")) {
19530b57cec5SDimitry Andric     if (rs_val > 0)
19540b57cec5SDimitry Andric       target = pc + offset;
19550b57cec5SDimitry Andric     else
19560b57cec5SDimitry Andric       target = pc + 4;
195781ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BEQZALC")) {
19580b57cec5SDimitry Andric     if (rs_val == 0)
19590b57cec5SDimitry Andric       target = pc + offset;
19600b57cec5SDimitry Andric     else
19610b57cec5SDimitry Andric       target = pc + 4;
196281ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BNEZALC")) {
19630b57cec5SDimitry Andric     if (rs_val != 0)
19640b57cec5SDimitry Andric       target = pc + offset;
19650b57cec5SDimitry Andric     else
19660b57cec5SDimitry Andric       target = pc + 4;
19670b57cec5SDimitry Andric   }
19680b57cec5SDimitry Andric 
19690b57cec5SDimitry Andric   Context context;
19700b57cec5SDimitry Andric 
19710b57cec5SDimitry Andric   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
19720b57cec5SDimitry Andric                              target))
19730b57cec5SDimitry Andric     return false;
19740b57cec5SDimitry Andric 
19750b57cec5SDimitry Andric   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
19760b57cec5SDimitry Andric                              pc + 4))
19770b57cec5SDimitry Andric     return false;
19780b57cec5SDimitry Andric 
19790b57cec5SDimitry Andric   return true;
19800b57cec5SDimitry Andric }
19810b57cec5SDimitry Andric 
19820b57cec5SDimitry Andric /*
19830b57cec5SDimitry Andric     Emulate below MIPS Non-Compact conditional branch and link instructions.
19840b57cec5SDimitry Andric     BLTZAL, BGEZAL      :
19850b57cec5SDimitry Andric     BLTZALL, BGEZALL    : Branch likely
19860b57cec5SDimitry Andric */
Emulate_Bcond_Link(llvm::MCInst & insn)19870b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_Bcond_Link(llvm::MCInst &insn) {
19880b57cec5SDimitry Andric   bool success = false;
19890b57cec5SDimitry Andric   uint32_t rs;
19900b57cec5SDimitry Andric   int32_t offset, pc, target = 0;
19910b57cec5SDimitry Andric   int32_t rs_val;
199281ad6265SDimitry Andric   llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
19930b57cec5SDimitry Andric 
19940b57cec5SDimitry Andric   rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
19950b57cec5SDimitry Andric   offset = insn.getOperand(1).getImm();
19960b57cec5SDimitry Andric 
19970b57cec5SDimitry Andric   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
19980b57cec5SDimitry Andric   if (!success)
19990b57cec5SDimitry Andric     return false;
20000b57cec5SDimitry Andric 
20010b57cec5SDimitry Andric   rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
20020b57cec5SDimitry Andric                                          dwarf_zero_mips + rs, 0, &success);
20030b57cec5SDimitry Andric   if (!success)
20040b57cec5SDimitry Andric     return false;
20050b57cec5SDimitry Andric 
200681ad6265SDimitry Andric   if (op_name.equals_insensitive("BLTZAL") ||
200781ad6265SDimitry Andric       op_name.equals_insensitive("BLTZALL")) {
20080b57cec5SDimitry Andric     if ((int32_t)rs_val < 0)
20090b57cec5SDimitry Andric       target = pc + offset;
20100b57cec5SDimitry Andric     else
20110b57cec5SDimitry Andric       target = pc + 8;
201281ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BGEZAL") ||
201381ad6265SDimitry Andric              op_name.equals_insensitive("BGEZALL")) {
20140b57cec5SDimitry Andric     if ((int32_t)rs_val >= 0)
20150b57cec5SDimitry Andric       target = pc + offset;
20160b57cec5SDimitry Andric     else
20170b57cec5SDimitry Andric       target = pc + 8;
20180b57cec5SDimitry Andric   }
20190b57cec5SDimitry Andric 
20200b57cec5SDimitry Andric   Context context;
20210b57cec5SDimitry Andric 
20220b57cec5SDimitry Andric   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
20230b57cec5SDimitry Andric                              target))
20240b57cec5SDimitry Andric     return false;
20250b57cec5SDimitry Andric 
20260b57cec5SDimitry Andric   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
20270b57cec5SDimitry Andric                              pc + 8))
20280b57cec5SDimitry Andric     return false;
20290b57cec5SDimitry Andric 
20300b57cec5SDimitry Andric   return true;
20310b57cec5SDimitry Andric }
20320b57cec5SDimitry Andric 
20330b57cec5SDimitry Andric /*
20340b57cec5SDimitry Andric     Emulate below MIPS branch instructions.
20350b57cec5SDimitry Andric     BLTZL, BGEZL, BGTZL, BLEZL : Branch likely
20360b57cec5SDimitry Andric     BLTZ, BGEZ, BGTZ, BLEZ     : Non-compact branches
20370b57cec5SDimitry Andric */
Emulate_BXX_2ops(llvm::MCInst & insn)20380b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_BXX_2ops(llvm::MCInst &insn) {
20390b57cec5SDimitry Andric   bool success = false;
20400b57cec5SDimitry Andric   uint32_t rs;
20410b57cec5SDimitry Andric   int32_t offset, pc, target = 0;
20420b57cec5SDimitry Andric   int32_t rs_val;
204381ad6265SDimitry Andric   llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
20440b57cec5SDimitry Andric 
20450b57cec5SDimitry Andric   rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
20460b57cec5SDimitry Andric   offset = insn.getOperand(1).getImm();
20470b57cec5SDimitry Andric 
20480b57cec5SDimitry Andric   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
20490b57cec5SDimitry Andric   if (!success)
20500b57cec5SDimitry Andric     return false;
20510b57cec5SDimitry Andric 
20520b57cec5SDimitry Andric   rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
20530b57cec5SDimitry Andric                                          dwarf_zero_mips + rs, 0, &success);
20540b57cec5SDimitry Andric   if (!success)
20550b57cec5SDimitry Andric     return false;
20560b57cec5SDimitry Andric 
205781ad6265SDimitry Andric   if (op_name.equals_insensitive("BLTZL") ||
205881ad6265SDimitry Andric       op_name.equals_insensitive("BLTZ")) {
20590b57cec5SDimitry Andric     if (rs_val < 0)
20600b57cec5SDimitry Andric       target = pc + offset;
20610b57cec5SDimitry Andric     else
20620b57cec5SDimitry Andric       target = pc + 8;
206381ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BGEZL") ||
206481ad6265SDimitry Andric              op_name.equals_insensitive("BGEZ")) {
20650b57cec5SDimitry Andric     if (rs_val >= 0)
20660b57cec5SDimitry Andric       target = pc + offset;
20670b57cec5SDimitry Andric     else
20680b57cec5SDimitry Andric       target = pc + 8;
206981ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BGTZL") ||
207081ad6265SDimitry Andric              op_name.equals_insensitive("BGTZ")) {
20710b57cec5SDimitry Andric     if (rs_val > 0)
20720b57cec5SDimitry Andric       target = pc + offset;
20730b57cec5SDimitry Andric     else
20740b57cec5SDimitry Andric       target = pc + 8;
207581ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BLEZL") ||
207681ad6265SDimitry Andric              op_name.equals_insensitive("BLEZ")) {
20770b57cec5SDimitry Andric     if (rs_val <= 0)
20780b57cec5SDimitry Andric       target = pc + offset;
20790b57cec5SDimitry Andric     else
20800b57cec5SDimitry Andric       target = pc + 8;
20810b57cec5SDimitry Andric   }
20820b57cec5SDimitry Andric 
20830b57cec5SDimitry Andric   Context context;
20840b57cec5SDimitry Andric   context.type = eContextRelativeBranchImmediate;
20850b57cec5SDimitry Andric   context.SetImmediate(offset);
20860b57cec5SDimitry Andric 
20870b57cec5SDimitry Andric   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
20880b57cec5SDimitry Andric                                target);
20890b57cec5SDimitry Andric }
20900b57cec5SDimitry Andric 
20910b57cec5SDimitry Andric /*
20920b57cec5SDimitry Andric     Emulate below MIPS branch instructions.
20930b57cec5SDimitry Andric     BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches
20940b57cec5SDimitry Andric */
Emulate_BXX_2ops_C(llvm::MCInst & insn)20950b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_BXX_2ops_C(llvm::MCInst &insn) {
20960b57cec5SDimitry Andric   bool success = false;
20970b57cec5SDimitry Andric   uint32_t rs;
20980b57cec5SDimitry Andric   int32_t offset, pc, target = 0;
20990b57cec5SDimitry Andric   int32_t rs_val;
210081ad6265SDimitry Andric   llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
21010b57cec5SDimitry Andric   uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
21020b57cec5SDimitry Andric 
21030b57cec5SDimitry Andric   rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
21040b57cec5SDimitry Andric   offset = insn.getOperand(1).getImm();
21050b57cec5SDimitry Andric 
21060b57cec5SDimitry Andric   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
21070b57cec5SDimitry Andric   if (!success)
21080b57cec5SDimitry Andric     return false;
21090b57cec5SDimitry Andric 
21100b57cec5SDimitry Andric   rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
21110b57cec5SDimitry Andric                                          dwarf_zero_mips + rs, 0, &success);
21120b57cec5SDimitry Andric   if (!success)
21130b57cec5SDimitry Andric     return false;
21140b57cec5SDimitry Andric 
211581ad6265SDimitry Andric   if (op_name.equals_insensitive("BLTZC")) {
21160b57cec5SDimitry Andric     if (rs_val < 0)
21170b57cec5SDimitry Andric       target = pc + offset;
21180b57cec5SDimitry Andric     else
21190b57cec5SDimitry Andric       target = pc + 4;
212081ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BLEZC")) {
21210b57cec5SDimitry Andric     if (rs_val <= 0)
21220b57cec5SDimitry Andric       target = pc + offset;
21230b57cec5SDimitry Andric     else
21240b57cec5SDimitry Andric       target = pc + 4;
212581ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BGEZC")) {
21260b57cec5SDimitry Andric     if (rs_val >= 0)
21270b57cec5SDimitry Andric       target = pc + offset;
21280b57cec5SDimitry Andric     else
21290b57cec5SDimitry Andric       target = pc + 4;
213081ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BGTZC")) {
21310b57cec5SDimitry Andric     if (rs_val > 0)
21320b57cec5SDimitry Andric       target = pc + offset;
21330b57cec5SDimitry Andric     else
21340b57cec5SDimitry Andric       target = pc + 4;
213581ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BEQZC")) {
21360b57cec5SDimitry Andric     if (rs_val == 0)
21370b57cec5SDimitry Andric       target = pc + offset;
21380b57cec5SDimitry Andric     else
21390b57cec5SDimitry Andric       target = pc + 4;
214081ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BNEZC")) {
21410b57cec5SDimitry Andric     if (rs_val != 0)
21420b57cec5SDimitry Andric       target = pc + offset;
21430b57cec5SDimitry Andric     else
21440b57cec5SDimitry Andric       target = pc + 4;
21450b57cec5SDimitry Andric   }
21460b57cec5SDimitry Andric 
21470b57cec5SDimitry Andric   Context context;
21480b57cec5SDimitry Andric   context.type = eContextRelativeBranchImmediate;
21490b57cec5SDimitry Andric   context.SetImmediate(current_inst_size + offset);
21500b57cec5SDimitry Andric 
21510b57cec5SDimitry Andric   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
21520b57cec5SDimitry Andric                                target);
21530b57cec5SDimitry Andric }
21540b57cec5SDimitry Andric 
Emulate_B16_MM(llvm::MCInst & insn)21550b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_B16_MM(llvm::MCInst &insn) {
21560b57cec5SDimitry Andric   bool success = false;
21570b57cec5SDimitry Andric   int32_t offset, pc, target;
21580b57cec5SDimitry Andric   uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
21590b57cec5SDimitry Andric 
21600b57cec5SDimitry Andric   offset = insn.getOperand(0).getImm();
21610b57cec5SDimitry Andric 
21620b57cec5SDimitry Andric   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
21630b57cec5SDimitry Andric   if (!success)
21640b57cec5SDimitry Andric     return false;
21650b57cec5SDimitry Andric 
21660b57cec5SDimitry Andric   // unconditional branch
21670b57cec5SDimitry Andric   target = pc + offset;
21680b57cec5SDimitry Andric 
21690b57cec5SDimitry Andric   Context context;
21700b57cec5SDimitry Andric   context.type = eContextRelativeBranchImmediate;
21710b57cec5SDimitry Andric   context.SetImmediate(current_inst_size + offset);
21720b57cec5SDimitry Andric 
21730b57cec5SDimitry Andric   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
21740b57cec5SDimitry Andric                                target);
21750b57cec5SDimitry Andric }
21760b57cec5SDimitry Andric 
21770b57cec5SDimitry Andric /*
21780b57cec5SDimitry Andric    BEQZC, BNEZC are 32 bit compact instructions without a delay slot.
21790b57cec5SDimitry Andric    BEQZ16, BNEZ16 are 16 bit instructions with delay slot.
21800b57cec5SDimitry Andric    BGEZALS, BLTZALS are 16 bit instructions with short (2-byte) delay slot.
21810b57cec5SDimitry Andric */
Emulate_Branch_MM(llvm::MCInst & insn)21820b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_Branch_MM(llvm::MCInst &insn) {
21830b57cec5SDimitry Andric   bool success = false;
21840b57cec5SDimitry Andric   int32_t target = 0;
21850b57cec5SDimitry Andric   uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
218681ad6265SDimitry Andric   llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
21870b57cec5SDimitry Andric   bool update_ra = false;
21880b57cec5SDimitry Andric   uint32_t ra_offset = 0;
21890b57cec5SDimitry Andric 
21900b57cec5SDimitry Andric   /*
21910b57cec5SDimitry Andric    * BEQZ16 rs, offset
21920b57cec5SDimitry Andric    *      condition <- (GPR[rs] = 0)
21930b57cec5SDimitry Andric    *      if condition then
21940b57cec5SDimitry Andric    *          PC = PC + sign_ext (offset || 0)
21950b57cec5SDimitry Andric    *
21960b57cec5SDimitry Andric    * BNEZ16 rs, offset
21970b57cec5SDimitry Andric    *      condition <- (GPR[rs] != 0)
21980b57cec5SDimitry Andric    *      if condition then
21990b57cec5SDimitry Andric    *          PC = PC + sign_ext (offset || 0)
22000b57cec5SDimitry Andric    *
22010b57cec5SDimitry Andric    * BEQZC rs, offset     (compact instruction: No delay slot)
22020b57cec5SDimitry Andric    *      condition <- (GPR[rs] == 0)
22030b57cec5SDimitry Andric    *      if condition then
22040b57cec5SDimitry Andric    *         PC = PC + 4 + sign_ext (offset || 0)
22050b57cec5SDimitry Andric   */
22060b57cec5SDimitry Andric 
22070b57cec5SDimitry Andric   uint32_t rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
22080b57cec5SDimitry Andric   int32_t offset = insn.getOperand(1).getImm();
22090b57cec5SDimitry Andric 
22100b57cec5SDimitry Andric   int32_t pc =
22110b57cec5SDimitry Andric       ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
22120b57cec5SDimitry Andric   if (!success)
22130b57cec5SDimitry Andric     return false;
22140b57cec5SDimitry Andric 
22150b57cec5SDimitry Andric   int32_t rs_val = (int32_t)ReadRegisterUnsigned(
22160b57cec5SDimitry Andric       eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
22170b57cec5SDimitry Andric   if (!success)
22180b57cec5SDimitry Andric     return false;
22190b57cec5SDimitry Andric 
222081ad6265SDimitry Andric   if (op_name.equals_insensitive("BEQZ16_MM")) {
22210b57cec5SDimitry Andric     if (rs_val == 0)
22220b57cec5SDimitry Andric       target = pc + offset;
22230b57cec5SDimitry Andric     else
22240b57cec5SDimitry Andric       target = pc + current_inst_size +
22250b57cec5SDimitry Andric                m_next_inst_size; // Skip delay slot instruction.
222681ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BNEZ16_MM")) {
22270b57cec5SDimitry Andric     if (rs_val != 0)
22280b57cec5SDimitry Andric       target = pc + offset;
22290b57cec5SDimitry Andric     else
22300b57cec5SDimitry Andric       target = pc + current_inst_size +
22310b57cec5SDimitry Andric                m_next_inst_size; // Skip delay slot instruction.
223281ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BEQZC_MM")) {
22330b57cec5SDimitry Andric     if (rs_val == 0)
22340b57cec5SDimitry Andric       target = pc + 4 + offset;
22350b57cec5SDimitry Andric     else
22360b57cec5SDimitry Andric       target =
22370b57cec5SDimitry Andric           pc +
22380b57cec5SDimitry Andric           4; // 32 bit instruction and does not have delay slot instruction.
223981ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BNEZC_MM")) {
22400b57cec5SDimitry Andric     if (rs_val != 0)
22410b57cec5SDimitry Andric       target = pc + 4 + offset;
22420b57cec5SDimitry Andric     else
22430b57cec5SDimitry Andric       target =
22440b57cec5SDimitry Andric           pc +
22450b57cec5SDimitry Andric           4; // 32 bit instruction and does not have delay slot instruction.
224681ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BGEZALS_MM")) {
22470b57cec5SDimitry Andric     if (rs_val >= 0)
22480b57cec5SDimitry Andric       target = pc + offset;
22490b57cec5SDimitry Andric     else
22500b57cec5SDimitry Andric       target = pc + 6; // 32 bit instruction with short (2-byte) delay slot
22510b57cec5SDimitry Andric 
22520b57cec5SDimitry Andric     update_ra = true;
22530b57cec5SDimitry Andric     ra_offset = 6;
225481ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BLTZALS_MM")) {
22550b57cec5SDimitry Andric     if (rs_val >= 0)
22560b57cec5SDimitry Andric       target = pc + offset;
22570b57cec5SDimitry Andric     else
22580b57cec5SDimitry Andric       target = pc + 6; // 32 bit instruction with short (2-byte) delay slot
22590b57cec5SDimitry Andric 
22600b57cec5SDimitry Andric     update_ra = true;
22610b57cec5SDimitry Andric     ra_offset = 6;
22620b57cec5SDimitry Andric   }
22630b57cec5SDimitry Andric 
22640b57cec5SDimitry Andric   Context context;
22650b57cec5SDimitry Andric   context.type = eContextRelativeBranchImmediate;
22660b57cec5SDimitry Andric   context.SetImmediate(current_inst_size + offset);
22670b57cec5SDimitry Andric 
22680b57cec5SDimitry Andric   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
22690b57cec5SDimitry Andric                              target))
22700b57cec5SDimitry Andric     return false;
22710b57cec5SDimitry Andric 
22720b57cec5SDimitry Andric   if (update_ra) {
22730b57cec5SDimitry Andric     if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
22740b57cec5SDimitry Andric                                pc + ra_offset))
22750b57cec5SDimitry Andric       return false;
22760b57cec5SDimitry Andric   }
22770b57cec5SDimitry Andric   return true;
22780b57cec5SDimitry Andric }
22790b57cec5SDimitry Andric 
22800b57cec5SDimitry Andric /* Emulate micromips jump instructions.
22810b57cec5SDimitry Andric    JALR16,JALRS16
22820b57cec5SDimitry Andric */
Emulate_JALRx16_MM(llvm::MCInst & insn)22830b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_JALRx16_MM(llvm::MCInst &insn) {
22840b57cec5SDimitry Andric   bool success = false;
22850b57cec5SDimitry Andric   uint32_t ra_offset = 0;
228681ad6265SDimitry Andric   llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
22870b57cec5SDimitry Andric 
22880b57cec5SDimitry Andric   uint32_t rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
22890b57cec5SDimitry Andric 
22900b57cec5SDimitry Andric   uint32_t pc =
22910b57cec5SDimitry Andric       ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
22920b57cec5SDimitry Andric   if (!success)
22930b57cec5SDimitry Andric     return false;
22940b57cec5SDimitry Andric 
22950b57cec5SDimitry Andric   uint32_t rs_val = ReadRegisterUnsigned(eRegisterKindDWARF,
22960b57cec5SDimitry Andric                                          dwarf_zero_mips + rs, 0, &success);
22970b57cec5SDimitry Andric   if (!success)
22980b57cec5SDimitry Andric     return false;
22990b57cec5SDimitry Andric 
230081ad6265SDimitry Andric   if (op_name.equals_insensitive("JALR16_MM"))
23010b57cec5SDimitry Andric     ra_offset = 6; // 2-byte instruction with 4-byte delay slot.
230281ad6265SDimitry Andric   else if (op_name.equals_insensitive("JALRS16_MM"))
23030b57cec5SDimitry Andric     ra_offset = 4; // 2-byte instruction with 2-byte delay slot.
23040b57cec5SDimitry Andric 
23050b57cec5SDimitry Andric   Context context;
23060b57cec5SDimitry Andric 
23070b57cec5SDimitry Andric   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
23080b57cec5SDimitry Andric                              rs_val))
23090b57cec5SDimitry Andric     return false;
23100b57cec5SDimitry Andric 
23110b57cec5SDimitry Andric   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
23120b57cec5SDimitry Andric                              pc + ra_offset))
23130b57cec5SDimitry Andric     return false;
23140b57cec5SDimitry Andric 
23150b57cec5SDimitry Andric   return true;
23160b57cec5SDimitry Andric }
23170b57cec5SDimitry Andric 
23180b57cec5SDimitry Andric /* Emulate JALS and JALX instructions.
23190b57cec5SDimitry Andric     JALS 32 bit instruction with short (2-byte) delay slot.
23200b57cec5SDimitry Andric     JALX 32 bit instruction with 4-byte delay slot.
23210b57cec5SDimitry Andric */
Emulate_JALx(llvm::MCInst & insn)23220b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_JALx(llvm::MCInst &insn) {
23230b57cec5SDimitry Andric   bool success = false;
23240b57cec5SDimitry Andric   uint32_t offset = 0, target = 0, pc = 0, ra_offset = 0;
232581ad6265SDimitry Andric   llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
23260b57cec5SDimitry Andric 
23270b57cec5SDimitry Andric   /*
23280b57cec5SDimitry Andric    * JALS target
23290b57cec5SDimitry Andric    *      RA = PC + 6
23300b57cec5SDimitry Andric    *      offset = sign_ext (offset << 1)
23310b57cec5SDimitry Andric    *      PC = PC[31-27] | offset
23320b57cec5SDimitry Andric    * JALX target
23330b57cec5SDimitry Andric    *      RA = PC + 8
23340b57cec5SDimitry Andric    *      offset = sign_ext (offset << 2)
23350b57cec5SDimitry Andric    *      PC = PC[31-28] | offset
23360b57cec5SDimitry Andric   */
23370b57cec5SDimitry Andric   offset = insn.getOperand(0).getImm();
23380b57cec5SDimitry Andric 
23390b57cec5SDimitry Andric   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
23400b57cec5SDimitry Andric   if (!success)
23410b57cec5SDimitry Andric     return false;
23420b57cec5SDimitry Andric 
23430b57cec5SDimitry Andric   // These are PC-region branches and not PC-relative.
234481ad6265SDimitry Andric   if (op_name.equals_insensitive("JALS_MM")) {
23450b57cec5SDimitry Andric     // target address is in the “current” 128 MB-aligned region
23460b57cec5SDimitry Andric     target = (pc & 0xF8000000UL) | offset;
23470b57cec5SDimitry Andric     ra_offset = 6;
234881ad6265SDimitry Andric   } else if (op_name.equals_insensitive("JALX_MM")) {
23490b57cec5SDimitry Andric     // target address is in the “current” 256 MB-aligned region
23500b57cec5SDimitry Andric     target = (pc & 0xF0000000UL) | offset;
23510b57cec5SDimitry Andric     ra_offset = 8;
23520b57cec5SDimitry Andric   }
23530b57cec5SDimitry Andric 
23540b57cec5SDimitry Andric   Context context;
23550b57cec5SDimitry Andric 
23560b57cec5SDimitry Andric   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
23570b57cec5SDimitry Andric                              target))
23580b57cec5SDimitry Andric     return false;
23590b57cec5SDimitry Andric 
23600b57cec5SDimitry Andric   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
23610b57cec5SDimitry Andric                              pc + ra_offset))
23620b57cec5SDimitry Andric     return false;
23630b57cec5SDimitry Andric 
23640b57cec5SDimitry Andric   return true;
23650b57cec5SDimitry Andric }
23660b57cec5SDimitry Andric 
Emulate_JALRS(llvm::MCInst & insn)23670b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_JALRS(llvm::MCInst &insn) {
23680b57cec5SDimitry Andric   bool success = false;
23690b57cec5SDimitry Andric   uint32_t rs = 0, rt = 0;
23700b57cec5SDimitry Andric   int32_t pc = 0, rs_val = 0;
23710b57cec5SDimitry Andric 
23720b57cec5SDimitry Andric   /*
23730b57cec5SDimitry Andric       JALRS rt, rs
23740b57cec5SDimitry Andric           GPR[rt] <- PC + 6
23750b57cec5SDimitry Andric           PC <- GPR[rs]
23760b57cec5SDimitry Andric   */
23770b57cec5SDimitry Andric 
23780b57cec5SDimitry Andric   rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
23790b57cec5SDimitry Andric   rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
23800b57cec5SDimitry Andric 
23810b57cec5SDimitry Andric   rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
23820b57cec5SDimitry Andric                                          dwarf_zero_mips + rs, 0, &success);
23830b57cec5SDimitry Andric   if (!success)
23840b57cec5SDimitry Andric     return false;
23850b57cec5SDimitry Andric 
23860b57cec5SDimitry Andric   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
23870b57cec5SDimitry Andric   if (!success)
23880b57cec5SDimitry Andric     return false;
23890b57cec5SDimitry Andric 
23900b57cec5SDimitry Andric   Context context;
23910b57cec5SDimitry Andric 
23920b57cec5SDimitry Andric   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
23930b57cec5SDimitry Andric                              rs_val))
23940b57cec5SDimitry Andric     return false;
23950b57cec5SDimitry Andric 
23960b57cec5SDimitry Andric   // This is 4-byte instruction with 2-byte delay slot.
23970b57cec5SDimitry Andric   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_zero_mips + rt,
23980b57cec5SDimitry Andric                              pc + 6))
23990b57cec5SDimitry Andric     return false;
24000b57cec5SDimitry Andric 
24010b57cec5SDimitry Andric   return true;
24020b57cec5SDimitry Andric }
24030b57cec5SDimitry Andric 
Emulate_BAL(llvm::MCInst & insn)24040b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_BAL(llvm::MCInst &insn) {
24050b57cec5SDimitry Andric   bool success = false;
24060b57cec5SDimitry Andric   int32_t offset, pc, target;
24070b57cec5SDimitry Andric 
24080b57cec5SDimitry Andric   /*
24090b57cec5SDimitry Andric    * BAL offset
24100b57cec5SDimitry Andric    *      offset = sign_ext (offset << 2)
24110b57cec5SDimitry Andric    *      RA = PC + 8
24120b57cec5SDimitry Andric    *      PC = PC + offset
24130b57cec5SDimitry Andric   */
24140b57cec5SDimitry Andric   offset = insn.getOperand(0).getImm();
24150b57cec5SDimitry Andric 
24160b57cec5SDimitry Andric   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
24170b57cec5SDimitry Andric   if (!success)
24180b57cec5SDimitry Andric     return false;
24190b57cec5SDimitry Andric 
24200b57cec5SDimitry Andric   target = pc + offset;
24210b57cec5SDimitry Andric 
24220b57cec5SDimitry Andric   Context context;
24230b57cec5SDimitry Andric 
24240b57cec5SDimitry Andric   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
24250b57cec5SDimitry Andric                              target))
24260b57cec5SDimitry Andric     return false;
24270b57cec5SDimitry Andric 
24280b57cec5SDimitry Andric   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
24290b57cec5SDimitry Andric                              pc + 8))
24300b57cec5SDimitry Andric     return false;
24310b57cec5SDimitry Andric 
24320b57cec5SDimitry Andric   return true;
24330b57cec5SDimitry Andric }
24340b57cec5SDimitry Andric 
Emulate_BALC(llvm::MCInst & insn)24350b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_BALC(llvm::MCInst &insn) {
24360b57cec5SDimitry Andric   bool success = false;
24370b57cec5SDimitry Andric   int32_t offset, pc, target;
24380b57cec5SDimitry Andric 
24390b57cec5SDimitry Andric   /*
24400b57cec5SDimitry Andric    * BALC offset
24410b57cec5SDimitry Andric    *      offset = sign_ext (offset << 2)
24420b57cec5SDimitry Andric    *      RA = PC + 4
24430b57cec5SDimitry Andric    *      PC = PC + 4 + offset
24440b57cec5SDimitry Andric   */
24450b57cec5SDimitry Andric   offset = insn.getOperand(0).getImm();
24460b57cec5SDimitry Andric 
24470b57cec5SDimitry Andric   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
24480b57cec5SDimitry Andric   if (!success)
24490b57cec5SDimitry Andric     return false;
24500b57cec5SDimitry Andric 
24510b57cec5SDimitry Andric   target = pc + offset;
24520b57cec5SDimitry Andric 
24530b57cec5SDimitry Andric   Context context;
24540b57cec5SDimitry Andric 
24550b57cec5SDimitry Andric   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
24560b57cec5SDimitry Andric                              target))
24570b57cec5SDimitry Andric     return false;
24580b57cec5SDimitry Andric 
24590b57cec5SDimitry Andric   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
24600b57cec5SDimitry Andric                              pc + 4))
24610b57cec5SDimitry Andric     return false;
24620b57cec5SDimitry Andric 
24630b57cec5SDimitry Andric   return true;
24640b57cec5SDimitry Andric }
24650b57cec5SDimitry Andric 
Emulate_BC(llvm::MCInst & insn)24660b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_BC(llvm::MCInst &insn) {
24670b57cec5SDimitry Andric   bool success = false;
24680b57cec5SDimitry Andric   int32_t offset, pc, target;
24690b57cec5SDimitry Andric 
24700b57cec5SDimitry Andric   /*
24710b57cec5SDimitry Andric    * BC offset
24720b57cec5SDimitry Andric    *      offset = sign_ext (offset << 2)
24730b57cec5SDimitry Andric    *      PC = PC + 4 + offset
24740b57cec5SDimitry Andric   */
24750b57cec5SDimitry Andric   offset = insn.getOperand(0).getImm();
24760b57cec5SDimitry Andric 
24770b57cec5SDimitry Andric   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
24780b57cec5SDimitry Andric   if (!success)
24790b57cec5SDimitry Andric     return false;
24800b57cec5SDimitry Andric 
24810b57cec5SDimitry Andric   target = pc + offset;
24820b57cec5SDimitry Andric 
24830b57cec5SDimitry Andric   Context context;
24840b57cec5SDimitry Andric 
24850b57cec5SDimitry Andric   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
24860b57cec5SDimitry Andric                                target);
24870b57cec5SDimitry Andric }
24880b57cec5SDimitry Andric 
Emulate_J(llvm::MCInst & insn)24890b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_J(llvm::MCInst &insn) {
24900b57cec5SDimitry Andric   bool success = false;
24910b57cec5SDimitry Andric   uint32_t offset, pc;
24920b57cec5SDimitry Andric 
24930b57cec5SDimitry Andric   /*
24940b57cec5SDimitry Andric    * J offset
24950b57cec5SDimitry Andric    *      offset = sign_ext (offset << 2)
24960b57cec5SDimitry Andric    *      PC = PC[63-28] | offset
24970b57cec5SDimitry Andric   */
24980b57cec5SDimitry Andric   offset = insn.getOperand(0).getImm();
24990b57cec5SDimitry Andric 
25000b57cec5SDimitry Andric   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
25010b57cec5SDimitry Andric   if (!success)
25020b57cec5SDimitry Andric     return false;
25030b57cec5SDimitry Andric 
25040b57cec5SDimitry Andric   /* This is a PC-region branch and not PC-relative */
25050b57cec5SDimitry Andric   pc = (pc & 0xF0000000UL) | offset;
25060b57cec5SDimitry Andric 
25070b57cec5SDimitry Andric   Context context;
25080b57cec5SDimitry Andric 
25090b57cec5SDimitry Andric   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, pc);
25100b57cec5SDimitry Andric }
25110b57cec5SDimitry Andric 
Emulate_JAL(llvm::MCInst & insn)25120b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_JAL(llvm::MCInst &insn) {
25130b57cec5SDimitry Andric   bool success = false;
25140b57cec5SDimitry Andric   uint32_t offset, target, pc;
25150b57cec5SDimitry Andric 
25160b57cec5SDimitry Andric   /*
25170b57cec5SDimitry Andric    * JAL offset
25180b57cec5SDimitry Andric    *      offset = sign_ext (offset << 2)
25190b57cec5SDimitry Andric    *      PC = PC[63-28] | offset
25200b57cec5SDimitry Andric   */
25210b57cec5SDimitry Andric   offset = insn.getOperand(0).getImm();
25220b57cec5SDimitry Andric 
25230b57cec5SDimitry Andric   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
25240b57cec5SDimitry Andric   if (!success)
25250b57cec5SDimitry Andric     return false;
25260b57cec5SDimitry Andric 
25270b57cec5SDimitry Andric   /* This is a PC-region branch and not PC-relative */
25280b57cec5SDimitry Andric   target = (pc & 0xF0000000UL) | offset;
25290b57cec5SDimitry Andric 
25300b57cec5SDimitry Andric   Context context;
25310b57cec5SDimitry Andric 
25320b57cec5SDimitry Andric   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
25330b57cec5SDimitry Andric                              target))
25340b57cec5SDimitry Andric     return false;
25350b57cec5SDimitry Andric 
25360b57cec5SDimitry Andric   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
25370b57cec5SDimitry Andric                              pc + 8))
25380b57cec5SDimitry Andric     return false;
25390b57cec5SDimitry Andric 
25400b57cec5SDimitry Andric   return true;
25410b57cec5SDimitry Andric }
25420b57cec5SDimitry Andric 
Emulate_JALR(llvm::MCInst & insn)25430b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_JALR(llvm::MCInst &insn) {
25440b57cec5SDimitry Andric   bool success = false;
25450b57cec5SDimitry Andric   uint32_t rs, rt;
25460b57cec5SDimitry Andric   uint32_t pc, rs_val;
25470b57cec5SDimitry Andric 
25480b57cec5SDimitry Andric   /*
25490b57cec5SDimitry Andric    * JALR rt, rs
25500b57cec5SDimitry Andric    *      GPR[rt] = PC + 8
25510b57cec5SDimitry Andric    *      PC = GPR[rs]
25520b57cec5SDimitry Andric   */
25530b57cec5SDimitry Andric   rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
25540b57cec5SDimitry Andric   rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
25550b57cec5SDimitry Andric 
25560b57cec5SDimitry Andric   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
25570b57cec5SDimitry Andric   if (!success)
25580b57cec5SDimitry Andric     return false;
25590b57cec5SDimitry Andric 
25600b57cec5SDimitry Andric   rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + rs, 0,
25610b57cec5SDimitry Andric                                 &success);
25620b57cec5SDimitry Andric   if (!success)
25630b57cec5SDimitry Andric     return false;
25640b57cec5SDimitry Andric 
25650b57cec5SDimitry Andric   Context context;
25660b57cec5SDimitry Andric 
25670b57cec5SDimitry Andric   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
25680b57cec5SDimitry Andric                              rs_val))
25690b57cec5SDimitry Andric     return false;
25700b57cec5SDimitry Andric 
25710b57cec5SDimitry Andric   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_zero_mips + rt,
25720b57cec5SDimitry Andric                              pc + 8))
25730b57cec5SDimitry Andric     return false;
25740b57cec5SDimitry Andric 
25750b57cec5SDimitry Andric   return true;
25760b57cec5SDimitry Andric }
25770b57cec5SDimitry Andric 
Emulate_JIALC(llvm::MCInst & insn)25780b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_JIALC(llvm::MCInst &insn) {
25790b57cec5SDimitry Andric   bool success = false;
25800b57cec5SDimitry Andric   uint32_t rt;
25810b57cec5SDimitry Andric   int32_t target, offset, pc, rt_val;
25820b57cec5SDimitry Andric 
25830b57cec5SDimitry Andric   /*
25840b57cec5SDimitry Andric    * JIALC rt, offset
25850b57cec5SDimitry Andric    *      offset = sign_ext (offset)
25860b57cec5SDimitry Andric    *      PC = GPR[rt] + offset
25870b57cec5SDimitry Andric    *      RA = PC + 4
25880b57cec5SDimitry Andric   */
25890b57cec5SDimitry Andric   rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
25900b57cec5SDimitry Andric   offset = insn.getOperand(1).getImm();
25910b57cec5SDimitry Andric 
25920b57cec5SDimitry Andric   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
25930b57cec5SDimitry Andric   if (!success)
25940b57cec5SDimitry Andric     return false;
25950b57cec5SDimitry Andric 
25960b57cec5SDimitry Andric   rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
25970b57cec5SDimitry Andric                                          dwarf_zero_mips + rt, 0, &success);
25980b57cec5SDimitry Andric   if (!success)
25990b57cec5SDimitry Andric     return false;
26000b57cec5SDimitry Andric 
26010b57cec5SDimitry Andric   target = rt_val + offset;
26020b57cec5SDimitry Andric 
26030b57cec5SDimitry Andric   Context context;
26040b57cec5SDimitry Andric 
26050b57cec5SDimitry Andric   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
26060b57cec5SDimitry Andric                              target))
26070b57cec5SDimitry Andric     return false;
26080b57cec5SDimitry Andric 
26090b57cec5SDimitry Andric   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
26100b57cec5SDimitry Andric                              pc + 4))
26110b57cec5SDimitry Andric     return false;
26120b57cec5SDimitry Andric 
26130b57cec5SDimitry Andric   return true;
26140b57cec5SDimitry Andric }
26150b57cec5SDimitry Andric 
Emulate_JIC(llvm::MCInst & insn)26160b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_JIC(llvm::MCInst &insn) {
26170b57cec5SDimitry Andric   bool success = false;
26180b57cec5SDimitry Andric   uint32_t rt;
26190b57cec5SDimitry Andric   int32_t target, offset, rt_val;
26200b57cec5SDimitry Andric 
26210b57cec5SDimitry Andric   /*
26220b57cec5SDimitry Andric    * JIC rt, offset
26230b57cec5SDimitry Andric    *      offset = sign_ext (offset)
26240b57cec5SDimitry Andric    *      PC = GPR[rt] + offset
26250b57cec5SDimitry Andric   */
26260b57cec5SDimitry Andric   rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
26270b57cec5SDimitry Andric   offset = insn.getOperand(1).getImm();
26280b57cec5SDimitry Andric 
26290b57cec5SDimitry Andric   rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
26300b57cec5SDimitry Andric                                          dwarf_zero_mips + rt, 0, &success);
26310b57cec5SDimitry Andric   if (!success)
26320b57cec5SDimitry Andric     return false;
26330b57cec5SDimitry Andric 
26340b57cec5SDimitry Andric   target = rt_val + offset;
26350b57cec5SDimitry Andric 
26360b57cec5SDimitry Andric   Context context;
26370b57cec5SDimitry Andric 
26380b57cec5SDimitry Andric   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
26390b57cec5SDimitry Andric                                target);
26400b57cec5SDimitry Andric }
26410b57cec5SDimitry Andric 
Emulate_JR(llvm::MCInst & insn)26420b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_JR(llvm::MCInst &insn) {
26430b57cec5SDimitry Andric   bool success = false;
26440b57cec5SDimitry Andric   uint32_t rs;
26450b57cec5SDimitry Andric   uint32_t rs_val;
26460b57cec5SDimitry Andric 
26470b57cec5SDimitry Andric   /*
26480b57cec5SDimitry Andric    * JR rs
26490b57cec5SDimitry Andric    *      PC = GPR[rs]
26500b57cec5SDimitry Andric   */
26510b57cec5SDimitry Andric   rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
26520b57cec5SDimitry Andric 
26530b57cec5SDimitry Andric   rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + rs, 0,
26540b57cec5SDimitry Andric                                 &success);
26550b57cec5SDimitry Andric   if (!success)
26560b57cec5SDimitry Andric     return false;
26570b57cec5SDimitry Andric 
26580b57cec5SDimitry Andric   Context context;
26590b57cec5SDimitry Andric 
26600b57cec5SDimitry Andric   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
26610b57cec5SDimitry Andric                                rs_val);
26620b57cec5SDimitry Andric }
26630b57cec5SDimitry Andric 
26640b57cec5SDimitry Andric /*
26650b57cec5SDimitry Andric     Emulate Branch on FP True/False
26660b57cec5SDimitry Andric     BC1F, BC1FL :   Branch on FP False (L stands for branch likely)
26670b57cec5SDimitry Andric     BC1T, BC1TL :   Branch on FP True  (L stands for branch likely)
26680b57cec5SDimitry Andric */
Emulate_FP_branch(llvm::MCInst & insn)26690b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_FP_branch(llvm::MCInst &insn) {
26700b57cec5SDimitry Andric   bool success = false;
26710b57cec5SDimitry Andric   uint32_t cc, fcsr;
26720b57cec5SDimitry Andric   int32_t pc, offset, target = 0;
267381ad6265SDimitry Andric   llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
26740b57cec5SDimitry Andric 
26750b57cec5SDimitry Andric   cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
26760b57cec5SDimitry Andric   offset = insn.getOperand(1).getImm();
26770b57cec5SDimitry Andric 
26780b57cec5SDimitry Andric   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
26790b57cec5SDimitry Andric   if (!success)
26800b57cec5SDimitry Andric     return false;
26810b57cec5SDimitry Andric 
26820b57cec5SDimitry Andric   fcsr = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);
26830b57cec5SDimitry Andric   if (!success)
26840b57cec5SDimitry Andric     return false;
26850b57cec5SDimitry Andric 
26860b57cec5SDimitry Andric   /* fcsr[23], fcsr[25-31] are vaild condition bits */
26870b57cec5SDimitry Andric   fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
26880b57cec5SDimitry Andric 
268981ad6265SDimitry Andric   if (op_name.equals_insensitive("BC1F") ||
269081ad6265SDimitry Andric       op_name.equals_insensitive("BC1FL")) {
26910b57cec5SDimitry Andric     if ((fcsr & (1 << cc)) == 0)
26920b57cec5SDimitry Andric       target = pc + offset;
26930b57cec5SDimitry Andric     else
26940b57cec5SDimitry Andric       target = pc + 8;
269581ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BC1T") ||
269681ad6265SDimitry Andric              op_name.equals_insensitive("BC1TL")) {
26970b57cec5SDimitry Andric     if ((fcsr & (1 << cc)) != 0)
26980b57cec5SDimitry Andric       target = pc + offset;
26990b57cec5SDimitry Andric     else
27000b57cec5SDimitry Andric       target = pc + 8;
27010b57cec5SDimitry Andric   }
27020b57cec5SDimitry Andric   Context context;
27030b57cec5SDimitry Andric 
27040b57cec5SDimitry Andric   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
27050b57cec5SDimitry Andric                                target);
27060b57cec5SDimitry Andric }
27070b57cec5SDimitry Andric 
Emulate_BC1EQZ(llvm::MCInst & insn)27080b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_BC1EQZ(llvm::MCInst &insn) {
27090b57cec5SDimitry Andric   bool success = false;
27100b57cec5SDimitry Andric   uint32_t ft;
27110b57cec5SDimitry Andric   uint32_t ft_val;
27120b57cec5SDimitry Andric   int32_t target, pc, offset;
27130b57cec5SDimitry Andric 
27140b57cec5SDimitry Andric   /*
27150b57cec5SDimitry Andric    * BC1EQZ ft, offset
27160b57cec5SDimitry Andric    *  condition <- (FPR[ft].bit0 == 0)
27170b57cec5SDimitry Andric    *      if condition then
27180b57cec5SDimitry Andric    *          offset = sign_ext (offset)
27190b57cec5SDimitry Andric    *          PC = PC + 4 + offset
27200b57cec5SDimitry Andric   */
27210b57cec5SDimitry Andric   ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
27220b57cec5SDimitry Andric   offset = insn.getOperand(1).getImm();
27230b57cec5SDimitry Andric 
27240b57cec5SDimitry Andric   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
27250b57cec5SDimitry Andric   if (!success)
27260b57cec5SDimitry Andric     return false;
27270b57cec5SDimitry Andric 
27280b57cec5SDimitry Andric   ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + ft, 0,
27290b57cec5SDimitry Andric                                 &success);
27300b57cec5SDimitry Andric   if (!success)
27310b57cec5SDimitry Andric     return false;
27320b57cec5SDimitry Andric 
27330b57cec5SDimitry Andric   if ((ft_val & 1) == 0)
27340b57cec5SDimitry Andric     target = pc + 4 + offset;
27350b57cec5SDimitry Andric   else
27360b57cec5SDimitry Andric     target = pc + 8;
27370b57cec5SDimitry Andric 
27380b57cec5SDimitry Andric   Context context;
27390b57cec5SDimitry Andric 
27400b57cec5SDimitry Andric   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
27410b57cec5SDimitry Andric                                target);
27420b57cec5SDimitry Andric }
27430b57cec5SDimitry Andric 
Emulate_BC1NEZ(llvm::MCInst & insn)27440b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_BC1NEZ(llvm::MCInst &insn) {
27450b57cec5SDimitry Andric   bool success = false;
27460b57cec5SDimitry Andric   uint32_t ft;
27470b57cec5SDimitry Andric   uint32_t ft_val;
27480b57cec5SDimitry Andric   int32_t target, pc, offset;
27490b57cec5SDimitry Andric 
27500b57cec5SDimitry Andric   /*
27510b57cec5SDimitry Andric    * BC1NEZ ft, offset
27520b57cec5SDimitry Andric    *  condition <- (FPR[ft].bit0 != 0)
27530b57cec5SDimitry Andric    *      if condition then
27540b57cec5SDimitry Andric    *          offset = sign_ext (offset)
27550b57cec5SDimitry Andric    *          PC = PC + 4 + offset
27560b57cec5SDimitry Andric   */
27570b57cec5SDimitry Andric   ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
27580b57cec5SDimitry Andric   offset = insn.getOperand(1).getImm();
27590b57cec5SDimitry Andric 
27600b57cec5SDimitry Andric   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
27610b57cec5SDimitry Andric   if (!success)
27620b57cec5SDimitry Andric     return false;
27630b57cec5SDimitry Andric 
27640b57cec5SDimitry Andric   ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + ft, 0,
27650b57cec5SDimitry Andric                                 &success);
27660b57cec5SDimitry Andric   if (!success)
27670b57cec5SDimitry Andric     return false;
27680b57cec5SDimitry Andric 
27690b57cec5SDimitry Andric   if ((ft_val & 1) != 0)
27700b57cec5SDimitry Andric     target = pc + 4 + offset;
27710b57cec5SDimitry Andric   else
27720b57cec5SDimitry Andric     target = pc + 8;
27730b57cec5SDimitry Andric 
27740b57cec5SDimitry Andric   Context context;
27750b57cec5SDimitry Andric 
27760b57cec5SDimitry Andric   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
27770b57cec5SDimitry Andric                                target);
27780b57cec5SDimitry Andric }
27790b57cec5SDimitry Andric 
27800b57cec5SDimitry Andric /*
27810b57cec5SDimitry Andric     Emulate MIPS-3D Branch instructions
27820b57cec5SDimitry Andric     BC1ANY2F, BC1ANY2T  : Branch on Any of Two Floating Point Condition Codes
27830b57cec5SDimitry Andric    False/True
27840b57cec5SDimitry Andric     BC1ANY4F, BC1ANY4T  : Branch on Any of Four Floating Point Condition Codes
27850b57cec5SDimitry Andric    False/True
27860b57cec5SDimitry Andric */
Emulate_3D_branch(llvm::MCInst & insn)27870b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_3D_branch(llvm::MCInst &insn) {
27880b57cec5SDimitry Andric   bool success = false;
27890b57cec5SDimitry Andric   uint32_t cc, fcsr;
27900b57cec5SDimitry Andric   int32_t pc, offset, target = 0;
279181ad6265SDimitry Andric   llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
27920b57cec5SDimitry Andric 
27930b57cec5SDimitry Andric   cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
27940b57cec5SDimitry Andric   offset = insn.getOperand(1).getImm();
27950b57cec5SDimitry Andric 
27960b57cec5SDimitry Andric   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
27970b57cec5SDimitry Andric   if (!success)
27980b57cec5SDimitry Andric     return false;
27990b57cec5SDimitry Andric 
28000b57cec5SDimitry Andric   fcsr = (uint32_t)ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips, 0,
28010b57cec5SDimitry Andric                                         &success);
28020b57cec5SDimitry Andric   if (!success)
28030b57cec5SDimitry Andric     return false;
28040b57cec5SDimitry Andric 
28050b57cec5SDimitry Andric   /* fcsr[23], fcsr[25-31] are vaild condition bits */
28060b57cec5SDimitry Andric   fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
28070b57cec5SDimitry Andric 
280881ad6265SDimitry Andric   if (op_name.equals_insensitive("BC1ANY2F")) {
28090b57cec5SDimitry Andric     /* if any one bit is 0 */
28100b57cec5SDimitry Andric     if (((fcsr >> cc) & 3) != 3)
28110b57cec5SDimitry Andric       target = pc + offset;
28120b57cec5SDimitry Andric     else
28130b57cec5SDimitry Andric       target = pc + 8;
281481ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BC1ANY2T")) {
28150b57cec5SDimitry Andric     /* if any one bit is 1 */
28160b57cec5SDimitry Andric     if (((fcsr >> cc) & 3) != 0)
28170b57cec5SDimitry Andric       target = pc + offset;
28180b57cec5SDimitry Andric     else
28190b57cec5SDimitry Andric       target = pc + 8;
282081ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BC1ANY4F")) {
28210b57cec5SDimitry Andric     /* if any one bit is 0 */
28220b57cec5SDimitry Andric     if (((fcsr >> cc) & 0xf) != 0xf)
28230b57cec5SDimitry Andric       target = pc + offset;
28240b57cec5SDimitry Andric     else
28250b57cec5SDimitry Andric       target = pc + 8;
282681ad6265SDimitry Andric   } else if (op_name.equals_insensitive("BC1ANY4T")) {
28270b57cec5SDimitry Andric     /* if any one bit is 1 */
28280b57cec5SDimitry Andric     if (((fcsr >> cc) & 0xf) != 0)
28290b57cec5SDimitry Andric       target = pc + offset;
28300b57cec5SDimitry Andric     else
28310b57cec5SDimitry Andric       target = pc + 8;
28320b57cec5SDimitry Andric   }
28330b57cec5SDimitry Andric   Context context;
28340b57cec5SDimitry Andric 
28350b57cec5SDimitry Andric   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
28360b57cec5SDimitry Andric                                target);
28370b57cec5SDimitry Andric }
28380b57cec5SDimitry Andric 
Emulate_BNZB(llvm::MCInst & insn)28390b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_BNZB(llvm::MCInst &insn) {
28400b57cec5SDimitry Andric   return Emulate_MSA_Branch_DF(insn, 1, true);
28410b57cec5SDimitry Andric }
28420b57cec5SDimitry Andric 
Emulate_BNZH(llvm::MCInst & insn)28430b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_BNZH(llvm::MCInst &insn) {
28440b57cec5SDimitry Andric   return Emulate_MSA_Branch_DF(insn, 2, true);
28450b57cec5SDimitry Andric }
28460b57cec5SDimitry Andric 
Emulate_BNZW(llvm::MCInst & insn)28470b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_BNZW(llvm::MCInst &insn) {
28480b57cec5SDimitry Andric   return Emulate_MSA_Branch_DF(insn, 4, true);
28490b57cec5SDimitry Andric }
28500b57cec5SDimitry Andric 
Emulate_BNZD(llvm::MCInst & insn)28510b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_BNZD(llvm::MCInst &insn) {
28520b57cec5SDimitry Andric   return Emulate_MSA_Branch_DF(insn, 8, true);
28530b57cec5SDimitry Andric }
28540b57cec5SDimitry Andric 
Emulate_BZB(llvm::MCInst & insn)28550b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_BZB(llvm::MCInst &insn) {
28560b57cec5SDimitry Andric   return Emulate_MSA_Branch_DF(insn, 1, false);
28570b57cec5SDimitry Andric }
28580b57cec5SDimitry Andric 
Emulate_BZH(llvm::MCInst & insn)28590b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_BZH(llvm::MCInst &insn) {
28600b57cec5SDimitry Andric   return Emulate_MSA_Branch_DF(insn, 2, false);
28610b57cec5SDimitry Andric }
28620b57cec5SDimitry Andric 
Emulate_BZW(llvm::MCInst & insn)28630b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_BZW(llvm::MCInst &insn) {
28640b57cec5SDimitry Andric   return Emulate_MSA_Branch_DF(insn, 4, false);
28650b57cec5SDimitry Andric }
28660b57cec5SDimitry Andric 
Emulate_BZD(llvm::MCInst & insn)28670b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_BZD(llvm::MCInst &insn) {
28680b57cec5SDimitry Andric   return Emulate_MSA_Branch_DF(insn, 8, false);
28690b57cec5SDimitry Andric }
28700b57cec5SDimitry Andric 
Emulate_MSA_Branch_DF(llvm::MCInst & insn,int element_byte_size,bool bnz)28710b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_MSA_Branch_DF(llvm::MCInst &insn,
28720b57cec5SDimitry Andric                                                    int element_byte_size,
28730b57cec5SDimitry Andric                                                    bool bnz) {
28740b57cec5SDimitry Andric   bool success = false, branch_hit = true;
28750b57cec5SDimitry Andric   int32_t target = 0;
28760b57cec5SDimitry Andric   RegisterValue reg_value;
28770b57cec5SDimitry Andric   const uint8_t *ptr = nullptr;
28780b57cec5SDimitry Andric 
28790b57cec5SDimitry Andric   uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
28800b57cec5SDimitry Andric   int32_t offset = insn.getOperand(1).getImm();
28810b57cec5SDimitry Andric 
28820b57cec5SDimitry Andric   int32_t pc =
28830b57cec5SDimitry Andric       ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
28840b57cec5SDimitry Andric   if (!success)
28850b57cec5SDimitry Andric     return false;
28860b57cec5SDimitry Andric 
28870b57cec5SDimitry Andric   if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value))
28880b57cec5SDimitry Andric     ptr = (const uint8_t *)reg_value.GetBytes();
28890b57cec5SDimitry Andric   else
28900b57cec5SDimitry Andric     return false;
28910b57cec5SDimitry Andric 
28920b57cec5SDimitry Andric   for (int i = 0; i < 16 / element_byte_size; i++) {
28930b57cec5SDimitry Andric     switch (element_byte_size) {
28940b57cec5SDimitry Andric     case 1:
28950b57cec5SDimitry Andric       if ((*ptr == 0 && bnz) || (*ptr != 0 && !bnz))
28960b57cec5SDimitry Andric         branch_hit = false;
28970b57cec5SDimitry Andric       break;
28980b57cec5SDimitry Andric     case 2:
28990b57cec5SDimitry Andric       if ((*(const uint16_t *)ptr == 0 && bnz) ||
29000b57cec5SDimitry Andric           (*(const uint16_t *)ptr != 0 && !bnz))
29010b57cec5SDimitry Andric         branch_hit = false;
29020b57cec5SDimitry Andric       break;
29030b57cec5SDimitry Andric     case 4:
29040b57cec5SDimitry Andric       if ((*(const uint32_t *)ptr == 0 && bnz) ||
29050b57cec5SDimitry Andric           (*(const uint32_t *)ptr != 0 && !bnz))
29060b57cec5SDimitry Andric         branch_hit = false;
29070b57cec5SDimitry Andric       break;
29080b57cec5SDimitry Andric     case 8:
29090b57cec5SDimitry Andric       if ((*(const uint64_t *)ptr == 0 && bnz) ||
29100b57cec5SDimitry Andric           (*(const uint64_t *)ptr != 0 && !bnz))
29110b57cec5SDimitry Andric         branch_hit = false;
29120b57cec5SDimitry Andric       break;
29130b57cec5SDimitry Andric     }
29140b57cec5SDimitry Andric     if (!branch_hit)
29150b57cec5SDimitry Andric       break;
29160b57cec5SDimitry Andric     ptr = ptr + element_byte_size;
29170b57cec5SDimitry Andric   }
29180b57cec5SDimitry Andric 
29190b57cec5SDimitry Andric   if (branch_hit)
29200b57cec5SDimitry Andric     target = pc + offset;
29210b57cec5SDimitry Andric   else
29220b57cec5SDimitry Andric     target = pc + 8;
29230b57cec5SDimitry Andric 
29240b57cec5SDimitry Andric   Context context;
29250b57cec5SDimitry Andric   context.type = eContextRelativeBranchImmediate;
29260b57cec5SDimitry Andric 
29270b57cec5SDimitry Andric   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
29280b57cec5SDimitry Andric                                target);
29290b57cec5SDimitry Andric }
29300b57cec5SDimitry Andric 
Emulate_BNZV(llvm::MCInst & insn)29310b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_BNZV(llvm::MCInst &insn) {
29320b57cec5SDimitry Andric   return Emulate_MSA_Branch_V(insn, true);
29330b57cec5SDimitry Andric }
29340b57cec5SDimitry Andric 
Emulate_BZV(llvm::MCInst & insn)29350b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_BZV(llvm::MCInst &insn) {
29360b57cec5SDimitry Andric   return Emulate_MSA_Branch_V(insn, false);
29370b57cec5SDimitry Andric }
29380b57cec5SDimitry Andric 
Emulate_MSA_Branch_V(llvm::MCInst & insn,bool bnz)29390b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_MSA_Branch_V(llvm::MCInst &insn,
29400b57cec5SDimitry Andric                                                   bool bnz) {
29410b57cec5SDimitry Andric   bool success = false;
29420b57cec5SDimitry Andric   int32_t target = 0;
2943349cc55cSDimitry Andric   llvm::APInt wr_val = llvm::APInt::getZero(128);
29440b57cec5SDimitry Andric   llvm::APInt fail_value = llvm::APInt::getMaxValue(128);
2945349cc55cSDimitry Andric   llvm::APInt zero_value = llvm::APInt::getZero(128);
29460b57cec5SDimitry Andric   RegisterValue reg_value;
29470b57cec5SDimitry Andric 
29480b57cec5SDimitry Andric   uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
29490b57cec5SDimitry Andric   int32_t offset = insn.getOperand(1).getImm();
29500b57cec5SDimitry Andric 
29510b57cec5SDimitry Andric   int32_t pc =
29520b57cec5SDimitry Andric       ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
29530b57cec5SDimitry Andric   if (!success)
29540b57cec5SDimitry Andric     return false;
29550b57cec5SDimitry Andric 
29560b57cec5SDimitry Andric   if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value))
29570b57cec5SDimitry Andric     wr_val = reg_value.GetAsUInt128(fail_value);
29580b57cec5SDimitry Andric   else
29590b57cec5SDimitry Andric     return false;
29600b57cec5SDimitry Andric 
29610b57cec5SDimitry Andric   if ((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) ||
29620b57cec5SDimitry Andric       (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz))
29630b57cec5SDimitry Andric     target = pc + offset;
29640b57cec5SDimitry Andric   else
29650b57cec5SDimitry Andric     target = pc + 8;
29660b57cec5SDimitry Andric 
29670b57cec5SDimitry Andric   Context context;
29680b57cec5SDimitry Andric   context.type = eContextRelativeBranchImmediate;
29690b57cec5SDimitry Andric 
29700b57cec5SDimitry Andric   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
29710b57cec5SDimitry Andric                                target);
29720b57cec5SDimitry Andric }
29730b57cec5SDimitry Andric 
Emulate_LDST_Imm(llvm::MCInst & insn)29740b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_LDST_Imm(llvm::MCInst &insn) {
29750b57cec5SDimitry Andric   bool success = false;
29760b57cec5SDimitry Andric   uint32_t base;
29770b57cec5SDimitry Andric   int32_t imm, address;
29780b57cec5SDimitry Andric   Context bad_vaddr_context;
29790b57cec5SDimitry Andric 
29800b57cec5SDimitry Andric   uint32_t num_operands = insn.getNumOperands();
29810b57cec5SDimitry Andric   base =
29820b57cec5SDimitry Andric       m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
29830b57cec5SDimitry Andric   imm = insn.getOperand(num_operands - 1).getImm();
29840b57cec5SDimitry Andric 
2985bdd1243dSDimitry Andric   if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))
29860b57cec5SDimitry Andric     return false;
29870b57cec5SDimitry Andric 
29880b57cec5SDimitry Andric   /* read base register */
29890b57cec5SDimitry Andric   address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
29900b57cec5SDimitry Andric                                           dwarf_zero_mips + base, 0, &success);
29910b57cec5SDimitry Andric   if (!success)
29920b57cec5SDimitry Andric     return false;
29930b57cec5SDimitry Andric 
29940b57cec5SDimitry Andric   /* destination address */
29950b57cec5SDimitry Andric   address = address + imm;
29960b57cec5SDimitry Andric 
29970b57cec5SDimitry Andric   /* Set the bad_vaddr register with base address used in the instruction */
29980b57cec5SDimitry Andric   bad_vaddr_context.type = eContextInvalid;
29990b57cec5SDimitry Andric   WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
30000b57cec5SDimitry Andric                         address);
30010b57cec5SDimitry Andric 
30020b57cec5SDimitry Andric   return true;
30030b57cec5SDimitry Andric }
30040b57cec5SDimitry Andric 
Emulate_LDST_Reg(llvm::MCInst & insn)30050b57cec5SDimitry Andric bool EmulateInstructionMIPS::Emulate_LDST_Reg(llvm::MCInst &insn) {
30060b57cec5SDimitry Andric   bool success = false;
30070b57cec5SDimitry Andric   uint32_t base, index;
30080b57cec5SDimitry Andric   int32_t address, index_address;
30090b57cec5SDimitry Andric   Context bad_vaddr_context;
30100b57cec5SDimitry Andric 
30110b57cec5SDimitry Andric   uint32_t num_operands = insn.getNumOperands();
30120b57cec5SDimitry Andric   base =
30130b57cec5SDimitry Andric       m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
30140b57cec5SDimitry Andric   index =
30150b57cec5SDimitry Andric       m_reg_info->getEncodingValue(insn.getOperand(num_operands - 1).getReg());
30160b57cec5SDimitry Andric 
3017bdd1243dSDimitry Andric   if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))
30180b57cec5SDimitry Andric     return false;
30190b57cec5SDimitry Andric 
3020bdd1243dSDimitry Andric   if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + index))
30210b57cec5SDimitry Andric     return false;
30220b57cec5SDimitry Andric 
30230b57cec5SDimitry Andric   /* read base register */
30240b57cec5SDimitry Andric   address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
30250b57cec5SDimitry Andric                                           dwarf_zero_mips + base, 0, &success);
30260b57cec5SDimitry Andric   if (!success)
30270b57cec5SDimitry Andric     return false;
30280b57cec5SDimitry Andric 
30290b57cec5SDimitry Andric   /* read index register */
30300b57cec5SDimitry Andric   index_address = (int32_t)ReadRegisterUnsigned(
30310b57cec5SDimitry Andric       eRegisterKindDWARF, dwarf_zero_mips + index, 0, &success);
30320b57cec5SDimitry Andric   if (!success)
30330b57cec5SDimitry Andric     return false;
30340b57cec5SDimitry Andric 
30350b57cec5SDimitry Andric   /* destination address */
30360b57cec5SDimitry Andric   address = address + index_address;
30370b57cec5SDimitry Andric 
30380b57cec5SDimitry Andric   /* Set the bad_vaddr register with base address used in the instruction */
30390b57cec5SDimitry Andric   bad_vaddr_context.type = eContextInvalid;
30400b57cec5SDimitry Andric   WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
30410b57cec5SDimitry Andric                         address);
30420b57cec5SDimitry Andric 
30430b57cec5SDimitry Andric   return true;
30440b57cec5SDimitry Andric }
3045