1 //===-- EmulateInstructionMIPS64.cpp -----------------------------*- C++-*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "EmulateInstructionMIPS64.h"
13 #include "lldb/Core/Address.h"
14 #include "lldb/Core/Opcode.h"
15 #include "lldb/Core/PluginManager.h"
16 #include "lldb/Host/PosixApi.h"
17 #include "lldb/Symbol/UnwindPlan.h"
18 #include "lldb/Utility/ArchSpec.h"
19 #include "lldb/Utility/ConstString.h"
20 #include "lldb/Utility/DataExtractor.h"
21 #include "lldb/Utility/RegisterValue.h"
22 #include "lldb/Utility/Stream.h"
23 #include "llvm-c/Disassembler.h"
24 #include "llvm/MC/MCAsmInfo.h"
25 #include "llvm/MC/MCContext.h"
26 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
27 #include "llvm/MC/MCInst.h"
28 #include "llvm/MC/MCInstrInfo.h"
29 #include "llvm/MC/MCRegisterInfo.h"
30 #include "llvm/MC/MCSubtargetInfo.h"
31 #include "llvm/Support/TargetRegistry.h"
32 #include "llvm/Support/TargetSelect.h"
34 #include "llvm/ADT/STLExtras.h"
36 #include "Plugins/Process/Utility/InstructionUtils.h"
37 #include "Plugins/Process/Utility/RegisterContext_mips.h"
40 using namespace lldb_private;
42 #define UInt(x) ((uint64_t)x)
43 #define integer int64_t
46 // EmulateInstructionMIPS64 implementation
51 void LLVMInitializeMipsTargetInfo();
52 void LLVMInitializeMipsTarget();
53 void LLVMInitializeMipsAsmPrinter();
54 void LLVMInitializeMipsTargetMC();
55 void LLVMInitializeMipsDisassembler();
59 EmulateInstructionMIPS64::EmulateInstructionMIPS64(
60 const lldb_private::ArchSpec &arch)
61 : EmulateInstruction(arch) {
62 /* Create instance of llvm::MCDisassembler */
64 llvm::Triple triple = arch.GetTriple();
65 const llvm::Target *target =
66 llvm::TargetRegistry::lookupTarget(triple.getTriple(), Status);
69 * If we fail to get the target then we haven't registered it. The
70 * SystemInitializerCommon
71 * does not initialize targets, MCs and disassemblers. However we need the
73 * to decode the instructions so that the decoding complexity stays with LLVM.
74 * Initialize the MIPS targets and disassemblers.
78 LLVMInitializeMipsTargetInfo();
79 LLVMInitializeMipsTarget();
80 LLVMInitializeMipsAsmPrinter();
81 LLVMInitializeMipsTargetMC();
82 LLVMInitializeMipsDisassembler();
83 target = llvm::TargetRegistry::lookupTarget(triple.getTriple(), Status);
91 switch (arch.GetCore()) {
92 case ArchSpec::eCore_mips32:
93 case ArchSpec::eCore_mips32el:
96 case ArchSpec::eCore_mips32r2:
97 case ArchSpec::eCore_mips32r2el:
100 case ArchSpec::eCore_mips32r3:
101 case ArchSpec::eCore_mips32r3el:
104 case ArchSpec::eCore_mips32r5:
105 case ArchSpec::eCore_mips32r5el:
108 case ArchSpec::eCore_mips32r6:
109 case ArchSpec::eCore_mips32r6el:
112 case ArchSpec::eCore_mips64:
113 case ArchSpec::eCore_mips64el:
116 case ArchSpec::eCore_mips64r2:
117 case ArchSpec::eCore_mips64r2el:
120 case ArchSpec::eCore_mips64r3:
121 case ArchSpec::eCore_mips64r3el:
124 case ArchSpec::eCore_mips64r5:
125 case ArchSpec::eCore_mips64r5el:
128 case ArchSpec::eCore_mips64r6:
129 case ArchSpec::eCore_mips64r6el:
137 std::string features = "";
138 uint32_t arch_flags = arch.GetFlags();
139 if (arch_flags & ArchSpec::eMIPSAse_msa)
141 if (arch_flags & ArchSpec::eMIPSAse_dsp)
143 if (arch_flags & ArchSpec::eMIPSAse_dspr2)
144 features += "+dspr2,";
145 if (arch_flags & ArchSpec::eMIPSAse_mips16)
146 features += "+mips16,";
147 if (arch_flags & ArchSpec::eMIPSAse_micromips)
148 features += "+micromips,";
150 m_reg_info.reset(target->createMCRegInfo(triple.getTriple()));
151 assert(m_reg_info.get());
153 m_insn_info.reset(target->createMCInstrInfo());
154 assert(m_insn_info.get());
156 m_asm_info.reset(target->createMCAsmInfo(*m_reg_info, triple.getTriple()));
157 m_subtype_info.reset(
158 target->createMCSubtargetInfo(triple.getTriple(), cpu, features));
159 assert(m_asm_info.get() && m_subtype_info.get());
162 new llvm::MCContext(m_asm_info.get(), m_reg_info.get(), nullptr));
163 assert(m_context.get());
165 m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context));
166 assert(m_disasm.get());
169 void EmulateInstructionMIPS64::Initialize() {
170 PluginManager::RegisterPlugin(GetPluginNameStatic(),
171 GetPluginDescriptionStatic(), CreateInstance);
174 void EmulateInstructionMIPS64::Terminate() {
175 PluginManager::UnregisterPlugin(CreateInstance);
178 ConstString EmulateInstructionMIPS64::GetPluginNameStatic() {
179 ConstString g_plugin_name("lldb.emulate-instruction.mips64");
180 return g_plugin_name;
183 lldb_private::ConstString EmulateInstructionMIPS64::GetPluginName() {
184 static ConstString g_plugin_name("EmulateInstructionMIPS64");
185 return g_plugin_name;
188 const char *EmulateInstructionMIPS64::GetPluginDescriptionStatic() {
189 return "Emulate instructions for the MIPS64 architecture.";
193 EmulateInstructionMIPS64::CreateInstance(const ArchSpec &arch,
194 InstructionType inst_type) {
195 if (EmulateInstructionMIPS64::SupportsEmulatingInstructionsOfTypeStatic(
197 if (arch.GetTriple().getArch() == llvm::Triple::mips64 ||
198 arch.GetTriple().getArch() == llvm::Triple::mips64el) {
199 return new EmulateInstructionMIPS64(arch);
206 bool EmulateInstructionMIPS64::SetTargetTriple(const ArchSpec &arch) {
207 return arch.GetTriple().getArch() == llvm::Triple::mips64 ||
208 arch.GetTriple().getArch() == llvm::Triple::mips64el;
211 const char *EmulateInstructionMIPS64::GetRegisterName(unsigned reg_num,
212 bool alternate_name) {
213 if (alternate_name) {
215 case dwarf_sp_mips64:
217 case dwarf_r30_mips64:
219 case dwarf_ra_mips64:
221 case dwarf_f0_mips64:
223 case dwarf_f1_mips64:
225 case dwarf_f2_mips64:
227 case dwarf_f3_mips64:
229 case dwarf_f4_mips64:
231 case dwarf_f5_mips64:
233 case dwarf_f6_mips64:
235 case dwarf_f7_mips64:
237 case dwarf_f8_mips64:
239 case dwarf_f9_mips64:
241 case dwarf_f10_mips64:
243 case dwarf_f11_mips64:
245 case dwarf_f12_mips64:
247 case dwarf_f13_mips64:
249 case dwarf_f14_mips64:
251 case dwarf_f15_mips64:
253 case dwarf_f16_mips64:
255 case dwarf_f17_mips64:
257 case dwarf_f18_mips64:
259 case dwarf_f19_mips64:
261 case dwarf_f20_mips64:
263 case dwarf_f21_mips64:
265 case dwarf_f22_mips64:
267 case dwarf_f23_mips64:
269 case dwarf_f24_mips64:
271 case dwarf_f25_mips64:
273 case dwarf_f26_mips64:
275 case dwarf_f27_mips64:
277 case dwarf_f28_mips64:
279 case dwarf_f29_mips64:
281 case dwarf_f30_mips64:
283 case dwarf_f31_mips64:
285 case dwarf_w0_mips64:
287 case dwarf_w1_mips64:
289 case dwarf_w2_mips64:
291 case dwarf_w3_mips64:
293 case dwarf_w4_mips64:
295 case dwarf_w5_mips64:
297 case dwarf_w6_mips64:
299 case dwarf_w7_mips64:
301 case dwarf_w8_mips64:
303 case dwarf_w9_mips64:
305 case dwarf_w10_mips64:
307 case dwarf_w11_mips64:
309 case dwarf_w12_mips64:
311 case dwarf_w13_mips64:
313 case dwarf_w14_mips64:
315 case dwarf_w15_mips64:
317 case dwarf_w16_mips64:
319 case dwarf_w17_mips64:
321 case dwarf_w18_mips64:
323 case dwarf_w19_mips64:
325 case dwarf_w20_mips64:
327 case dwarf_w21_mips64:
329 case dwarf_w22_mips64:
331 case dwarf_w23_mips64:
333 case dwarf_w24_mips64:
335 case dwarf_w25_mips64:
337 case dwarf_w26_mips64:
339 case dwarf_w27_mips64:
341 case dwarf_w28_mips64:
343 case dwarf_w29_mips64:
345 case dwarf_w30_mips64:
347 case dwarf_w31_mips64:
349 case dwarf_mir_mips64:
351 case dwarf_mcsr_mips64:
353 case dwarf_config5_mips64:
362 case dwarf_zero_mips64:
364 case dwarf_r1_mips64:
366 case dwarf_r2_mips64:
368 case dwarf_r3_mips64:
370 case dwarf_r4_mips64:
372 case dwarf_r5_mips64:
374 case dwarf_r6_mips64:
376 case dwarf_r7_mips64:
378 case dwarf_r8_mips64:
380 case dwarf_r9_mips64:
382 case dwarf_r10_mips64:
384 case dwarf_r11_mips64:
386 case dwarf_r12_mips64:
388 case dwarf_r13_mips64:
390 case dwarf_r14_mips64:
392 case dwarf_r15_mips64:
394 case dwarf_r16_mips64:
396 case dwarf_r17_mips64:
398 case dwarf_r18_mips64:
400 case dwarf_r19_mips64:
402 case dwarf_r20_mips64:
404 case dwarf_r21_mips64:
406 case dwarf_r22_mips64:
408 case dwarf_r23_mips64:
410 case dwarf_r24_mips64:
412 case dwarf_r25_mips64:
414 case dwarf_r26_mips64:
416 case dwarf_r27_mips64:
418 case dwarf_gp_mips64:
420 case dwarf_sp_mips64:
422 case dwarf_r30_mips64:
424 case dwarf_ra_mips64:
426 case dwarf_sr_mips64:
428 case dwarf_lo_mips64:
430 case dwarf_hi_mips64:
432 case dwarf_bad_mips64:
434 case dwarf_cause_mips64:
436 case dwarf_pc_mips64:
438 case dwarf_f0_mips64:
440 case dwarf_f1_mips64:
442 case dwarf_f2_mips64:
444 case dwarf_f3_mips64:
446 case dwarf_f4_mips64:
448 case dwarf_f5_mips64:
450 case dwarf_f6_mips64:
452 case dwarf_f7_mips64:
454 case dwarf_f8_mips64:
456 case dwarf_f9_mips64:
458 case dwarf_f10_mips64:
460 case dwarf_f11_mips64:
462 case dwarf_f12_mips64:
464 case dwarf_f13_mips64:
466 case dwarf_f14_mips64:
468 case dwarf_f15_mips64:
470 case dwarf_f16_mips64:
472 case dwarf_f17_mips64:
474 case dwarf_f18_mips64:
476 case dwarf_f19_mips64:
478 case dwarf_f20_mips64:
480 case dwarf_f21_mips64:
482 case dwarf_f22_mips64:
484 case dwarf_f23_mips64:
486 case dwarf_f24_mips64:
488 case dwarf_f25_mips64:
490 case dwarf_f26_mips64:
492 case dwarf_f27_mips64:
494 case dwarf_f28_mips64:
496 case dwarf_f29_mips64:
498 case dwarf_f30_mips64:
500 case dwarf_f31_mips64:
502 case dwarf_fcsr_mips64:
504 case dwarf_fir_mips64:
506 case dwarf_w0_mips64:
508 case dwarf_w1_mips64:
510 case dwarf_w2_mips64:
512 case dwarf_w3_mips64:
514 case dwarf_w4_mips64:
516 case dwarf_w5_mips64:
518 case dwarf_w6_mips64:
520 case dwarf_w7_mips64:
522 case dwarf_w8_mips64:
524 case dwarf_w9_mips64:
526 case dwarf_w10_mips64:
528 case dwarf_w11_mips64:
530 case dwarf_w12_mips64:
532 case dwarf_w13_mips64:
534 case dwarf_w14_mips64:
536 case dwarf_w15_mips64:
538 case dwarf_w16_mips64:
540 case dwarf_w17_mips64:
542 case dwarf_w18_mips64:
544 case dwarf_w19_mips64:
546 case dwarf_w20_mips64:
548 case dwarf_w21_mips64:
550 case dwarf_w22_mips64:
552 case dwarf_w23_mips64:
554 case dwarf_w24_mips64:
556 case dwarf_w25_mips64:
558 case dwarf_w26_mips64:
560 case dwarf_w27_mips64:
562 case dwarf_w28_mips64:
564 case dwarf_w29_mips64:
566 case dwarf_w30_mips64:
568 case dwarf_w31_mips64:
570 case dwarf_mcsr_mips64:
572 case dwarf_mir_mips64:
574 case dwarf_config5_mips64:
580 bool EmulateInstructionMIPS64::GetRegisterInfo(RegisterKind reg_kind,
582 RegisterInfo ®_info) {
583 if (reg_kind == eRegisterKindGeneric) {
585 case LLDB_REGNUM_GENERIC_PC:
586 reg_kind = eRegisterKindDWARF;
587 reg_num = dwarf_pc_mips64;
589 case LLDB_REGNUM_GENERIC_SP:
590 reg_kind = eRegisterKindDWARF;
591 reg_num = dwarf_sp_mips64;
593 case LLDB_REGNUM_GENERIC_FP:
594 reg_kind = eRegisterKindDWARF;
595 reg_num = dwarf_r30_mips64;
597 case LLDB_REGNUM_GENERIC_RA:
598 reg_kind = eRegisterKindDWARF;
599 reg_num = dwarf_ra_mips64;
601 case LLDB_REGNUM_GENERIC_FLAGS:
602 reg_kind = eRegisterKindDWARF;
603 reg_num = dwarf_sr_mips64;
610 if (reg_kind == eRegisterKindDWARF) {
611 ::memset(®_info, 0, sizeof(RegisterInfo));
612 ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
614 if (reg_num == dwarf_sr_mips64 || reg_num == dwarf_fcsr_mips64 ||
615 reg_num == dwarf_fir_mips64 || reg_num == dwarf_mcsr_mips64 ||
616 reg_num == dwarf_mir_mips64 || reg_num == dwarf_config5_mips64) {
617 reg_info.byte_size = 4;
618 reg_info.format = eFormatHex;
619 reg_info.encoding = eEncodingUint;
620 } else if ((int)reg_num >= dwarf_zero_mips64 &&
621 (int)reg_num <= dwarf_f31_mips64) {
622 reg_info.byte_size = 8;
623 reg_info.format = eFormatHex;
624 reg_info.encoding = eEncodingUint;
625 } else if ((int)reg_num >= dwarf_w0_mips64 &&
626 (int)reg_num <= dwarf_w31_mips64) {
627 reg_info.byte_size = 16;
628 reg_info.format = eFormatVectorOfUInt8;
629 reg_info.encoding = eEncodingVector;
634 reg_info.name = GetRegisterName(reg_num, false);
635 reg_info.alt_name = GetRegisterName(reg_num, true);
636 reg_info.kinds[eRegisterKindDWARF] = reg_num;
639 case dwarf_r30_mips64:
640 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
642 case dwarf_ra_mips64:
643 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
645 case dwarf_sp_mips64:
646 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
648 case dwarf_pc_mips64:
649 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
651 case dwarf_sr_mips64:
652 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
662 EmulateInstructionMIPS64::MipsOpcode *
663 EmulateInstructionMIPS64::GetOpcodeForInstruction(const char *op_name) {
664 static EmulateInstructionMIPS64::MipsOpcode g_opcodes[] = {
665 // Prologue/Epilogue instructions
666 {"DADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu,
667 "DADDIU rt, rs, immediate"},
668 {"ADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu,
669 "ADDIU rt, rs, immediate"},
670 {"SD", &EmulateInstructionMIPS64::Emulate_SD, "SD rt, offset(rs)"},
671 {"LD", &EmulateInstructionMIPS64::Emulate_LD, "LD rt, offset(base)"},
672 {"DSUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
674 {"SUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
676 {"DADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
678 {"ADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
680 {"LUI", &EmulateInstructionMIPS64::Emulate_LUI, "LUI rt, immediate"},
682 // Load/Store instructions
683 /* Following list of emulated instructions are required by implementation
684 of hardware watchpoint
685 for MIPS in lldb. As we just need the address accessed by instructions,
687 all these instructions in 2 functions depending on their addressing
690 {"LB", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
691 "LB rt, offset(base)"},
692 {"LBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
693 "LBE rt, offset(base)"},
694 {"LBU", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
695 "LBU rt, offset(base)"},
696 {"LBUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
697 "LBUE rt, offset(base)"},
698 {"LDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
699 "LDC1 ft, offset(base)"},
700 {"LDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
701 "LDL rt, offset(base)"},
702 {"LDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
703 "LDR rt, offset(base)"},
704 {"LLD", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
705 "LLD rt, offset(base)"},
706 {"LDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
707 "LDC2 rt, offset(base)"},
708 {"LDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
709 "LDXC1 fd, index (base)"},
710 {"LH", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
711 "LH rt, offset(base)"},
712 {"LHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
713 "LHE rt, offset(base)"},
714 {"LHU", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
715 "LHU rt, offset(base)"},
716 {"LHUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
717 "LHUE rt, offset(base)"},
718 {"LL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
719 "LL rt, offset(base)"},
720 {"LLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
721 "LLE rt, offset(base)"},
722 {"LUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
723 "LUXC1 fd, index (base)"},
724 {"LW", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
725 "LW rt, offset(rs)"},
726 {"LWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
727 "LWC1 ft, offset(base)"},
728 {"LWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
729 "LWC2 rt, offset(base)"},
730 {"LWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
731 "LWE rt, offset(base)"},
732 {"LWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
733 "LWL rt, offset(base)"},
734 {"LWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
735 "LWLE rt, offset(base)"},
736 {"LWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
737 "LWR rt, offset(base)"},
738 {"LWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
739 "LWRE rt, offset(base)"},
740 {"LWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
741 "LWXC1 fd, index (base)"},
743 {"SB", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
744 "SB rt, offset(base)"},
745 {"SBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
746 "SBE rt, offset(base)"},
747 {"SC", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
748 "SC rt, offset(base)"},
749 {"SCE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
750 "SCE rt, offset(base)"},
751 {"SCD", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
752 "SCD rt, offset(base)"},
753 {"SDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
754 "SDL rt, offset(base)"},
755 {"SDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
756 "SDR rt, offset(base)"},
757 {"SDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
758 "SDC1 ft, offset(base)"},
759 {"SDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
760 "SDC2 rt, offset(base)"},
761 {"SDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
762 "SDXC1 fs, index (base)"},
763 {"SH", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
764 "SH rt, offset(base)"},
765 {"SHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
766 "SHE rt, offset(base)"},
767 {"SUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
768 "SUXC1 fs, index (base)"},
769 {"SW", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
770 "SW rt, offset(rs)"},
771 {"SWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
772 "SWC1 ft, offset(base)"},
773 {"SWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
774 "SWC2 rt, offset(base)"},
775 {"SWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
776 "SWE rt, offset(base)"},
777 {"SWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
778 "SWL rt, offset(base)"},
779 {"SWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
780 "SWLE rt, offset(base)"},
781 {"SWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
782 "SWR rt, offset(base)"},
783 {"SWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
784 "SWRE rt, offset(base)"},
785 {"SWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
786 "SWXC1 fs, index (base)"},
788 // Branch instructions
789 {"BEQ", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"},
790 {"BEQ64", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"},
791 {"BNE", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"},
792 {"BNE64", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"},
793 {"BEQL", &EmulateInstructionMIPS64::Emulate_BXX_3ops,
794 "BEQL rs,rt,offset"},
795 {"BNEL", &EmulateInstructionMIPS64::Emulate_BXX_3ops,
796 "BNEL rs,rt,offset"},
797 {"BGEZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
798 "BGEZALL rt,offset"},
799 {"BAL", &EmulateInstructionMIPS64::Emulate_BAL, "BAL offset"},
800 {"BGEZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
802 {"BALC", &EmulateInstructionMIPS64::Emulate_BALC, "BALC offset"},
803 {"BC", &EmulateInstructionMIPS64::Emulate_BC, "BC offset"},
804 {"BGEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"},
805 {"BGEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"},
806 {"BLEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
807 "BLEZALC rs,offset"},
808 {"BGEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
809 "BGEZALC rs,offset"},
810 {"BLTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
811 "BLTZALC rs,offset"},
812 {"BGTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
813 "BGTZALC rs,offset"},
814 {"BEQZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
815 "BEQZALC rs,offset"},
816 {"BNEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
817 "BNEZALC rs,offset"},
818 {"BEQC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
819 "BEQC rs,rt,offset"},
820 {"BEQC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
821 "BEQC rs,rt,offset"},
822 {"BNEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
823 "BNEC rs,rt,offset"},
824 {"BNEC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
825 "BNEC rs,rt,offset"},
826 {"BLTC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
827 "BLTC rs,rt,offset"},
828 {"BLTC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
829 "BLTC rs,rt,offset"},
830 {"BGEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
831 "BGEC rs,rt,offset"},
832 {"BGEC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
833 "BGEC rs,rt,offset"},
834 {"BLTUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
835 "BLTUC rs,rt,offset"},
836 {"BLTUC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
837 "BLTUC rs,rt,offset"},
838 {"BGEUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
839 "BGEUC rs,rt,offset"},
840 {"BGEUC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
841 "BGEUC rs,rt,offset"},
842 {"BLTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
844 {"BLTZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
846 {"BLEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
848 {"BLEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
850 {"BGEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
852 {"BGEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
854 {"BGTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
856 {"BGTZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
858 {"BEQZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
860 {"BEQZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
862 {"BNEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
864 {"BNEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
866 {"BGEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZL rt,offset"},
867 {"BGTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"},
868 {"BGTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"},
869 {"BGTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZL rt,offset"},
870 {"BLEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"},
871 {"BLEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"},
872 {"BLEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZL rt,offset"},
873 {"BLTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"},
874 {"BLTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"},
875 {"BLTZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
877 {"BLTZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
878 "BLTZALL rt,offset"},
879 {"BLTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZL rt,offset"},
880 {"BOVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
881 "BOVC rs,rt,offset"},
882 {"BNVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
883 "BNVC rs,rt,offset"},
884 {"J", &EmulateInstructionMIPS64::Emulate_J, "J target"},
885 {"JAL", &EmulateInstructionMIPS64::Emulate_JAL, "JAL target"},
886 {"JALX", &EmulateInstructionMIPS64::Emulate_JAL, "JALX target"},
887 {"JALR", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target"},
888 {"JALR64", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target"},
889 {"JALR_HB", &EmulateInstructionMIPS64::Emulate_JALR, "JALR.HB target"},
890 {"JIALC", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"},
891 {"JIALC64", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"},
892 {"JIC", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"},
893 {"JIC64", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"},
894 {"JR", &EmulateInstructionMIPS64::Emulate_JR, "JR target"},
895 {"JR64", &EmulateInstructionMIPS64::Emulate_JR, "JR target"},
896 {"JR_HB", &EmulateInstructionMIPS64::Emulate_JR, "JR.HB target"},
897 {"BC1F", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1F cc, offset"},
898 {"BC1T", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1T cc, offset"},
899 {"BC1FL", &EmulateInstructionMIPS64::Emulate_FP_branch,
901 {"BC1TL", &EmulateInstructionMIPS64::Emulate_FP_branch,
903 {"BC1EQZ", &EmulateInstructionMIPS64::Emulate_BC1EQZ,
904 "BC1EQZ ft, offset"},
905 {"BC1NEZ", &EmulateInstructionMIPS64::Emulate_BC1NEZ,
906 "BC1NEZ ft, offset"},
907 {"BC1ANY2F", &EmulateInstructionMIPS64::Emulate_3D_branch,
908 "BC1ANY2F cc, offset"},
909 {"BC1ANY2T", &EmulateInstructionMIPS64::Emulate_3D_branch,
910 "BC1ANY2T cc, offset"},
911 {"BC1ANY4F", &EmulateInstructionMIPS64::Emulate_3D_branch,
912 "BC1ANY4F cc, offset"},
913 {"BC1ANY4T", &EmulateInstructionMIPS64::Emulate_3D_branch,
914 "BC1ANY4T cc, offset"},
915 {"BNZ_B", &EmulateInstructionMIPS64::Emulate_BNZB, "BNZ.b wt,s16"},
916 {"BNZ_H", &EmulateInstructionMIPS64::Emulate_BNZH, "BNZ.h wt,s16"},
917 {"BNZ_W", &EmulateInstructionMIPS64::Emulate_BNZW, "BNZ.w wt,s16"},
918 {"BNZ_D", &EmulateInstructionMIPS64::Emulate_BNZD, "BNZ.d wt,s16"},
919 {"BZ_B", &EmulateInstructionMIPS64::Emulate_BZB, "BZ.b wt,s16"},
920 {"BZ_H", &EmulateInstructionMIPS64::Emulate_BZH, "BZ.h wt,s16"},
921 {"BZ_W", &EmulateInstructionMIPS64::Emulate_BZW, "BZ.w wt,s16"},
922 {"BZ_D", &EmulateInstructionMIPS64::Emulate_BZD, "BZ.d wt,s16"},
923 {"BNZ_V", &EmulateInstructionMIPS64::Emulate_BNZV, "BNZ.V wt,s16"},
924 {"BZ_V", &EmulateInstructionMIPS64::Emulate_BZV, "BZ.V wt,s16"},
927 static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes);
929 for (size_t i = 0; i < k_num_mips_opcodes; ++i) {
930 if (!strcasecmp(g_opcodes[i].op_name, op_name))
931 return &g_opcodes[i];
937 bool EmulateInstructionMIPS64::ReadInstruction() {
938 bool success = false;
939 m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
940 LLDB_INVALID_ADDRESS, &success);
942 Context read_inst_context;
943 read_inst_context.type = eContextReadOpcode;
944 read_inst_context.SetNoArgs();
945 m_opcode.SetOpcode32(
946 ReadMemoryUnsigned(read_inst_context, m_addr, 4, 0, &success),
950 m_addr = LLDB_INVALID_ADDRESS;
954 bool EmulateInstructionMIPS64::EvaluateInstruction(uint32_t evaluate_options) {
955 bool success = false;
956 llvm::MCInst mc_insn;
960 /* Keep the complexity of the decode logic with the llvm::MCDisassembler
962 if (m_opcode.GetData(data)) {
963 llvm::MCDisassembler::DecodeStatus decode_status;
964 llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());
965 decode_status = m_disasm->getInstruction(
966 mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls());
967 if (decode_status != llvm::MCDisassembler::Success)
972 * mc_insn.getOpcode() returns decoded opcode. However to make use
973 * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc".
975 const char *op_name = m_insn_info->getName(mc_insn.getOpcode()).data();
977 if (op_name == nullptr)
981 * Decoding has been done already. Just get the call-back function
982 * and emulate the instruction.
984 MipsOpcode *opcode_data = GetOpcodeForInstruction(op_name);
986 if (opcode_data == nullptr)
989 uint64_t old_pc = 0, new_pc = 0;
990 const bool auto_advance_pc =
991 evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
993 if (auto_advance_pc) {
995 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1000 /* emulate instruction */
1001 success = (this->*opcode_data->callback)(mc_insn);
1005 if (auto_advance_pc) {
1007 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1011 /* If we haven't changed the PC, change it here */
1012 if (old_pc == new_pc) {
1015 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1024 bool EmulateInstructionMIPS64::CreateFunctionEntryUnwind(
1025 UnwindPlan &unwind_plan) {
1026 unwind_plan.Clear();
1027 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
1029 UnwindPlan::RowSP row(new UnwindPlan::Row);
1030 const bool can_replace = false;
1032 // Our previous Call Frame Address is the stack pointer
1033 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips64, 0);
1035 // Our previous PC is in the RA
1036 row->SetRegisterLocationToRegister(dwarf_pc_mips64, dwarf_ra_mips64,
1039 unwind_plan.AppendRow(row);
1041 // All other registers are the same.
1042 unwind_plan.SetSourceName("EmulateInstructionMIPS64");
1043 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1044 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
1045 unwind_plan.SetReturnAddressRegister(dwarf_ra_mips64);
1050 bool EmulateInstructionMIPS64::nonvolatile_reg_p(uint64_t regnum) {
1052 case dwarf_r16_mips64:
1053 case dwarf_r17_mips64:
1054 case dwarf_r18_mips64:
1055 case dwarf_r19_mips64:
1056 case dwarf_r20_mips64:
1057 case dwarf_r21_mips64:
1058 case dwarf_r22_mips64:
1059 case dwarf_r23_mips64:
1060 case dwarf_gp_mips64:
1061 case dwarf_sp_mips64:
1062 case dwarf_r30_mips64:
1063 case dwarf_ra_mips64:
1071 bool EmulateInstructionMIPS64::Emulate_DADDiu(llvm::MCInst &insn) {
1072 // DADDIU rt, rs, immediate
1073 // GPR[rt] <- GPR[rs] + sign_extend(immediate)
1076 bool success = false;
1077 const uint32_t imm16 = insn.getOperand(2).getImm();
1078 int64_t imm = SignedBits(imm16, 15, 0);
1080 dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1081 src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1083 // If immediate is greater than 2^16 - 1 then clang generate LUI,
1084 // (D)ADDIU,(D)SUBU instructions in prolog. Example lui $1, 0x2 daddiu $1,
1085 // $1, -0x5920 dsubu $sp, $sp, $1 In this case, (D)ADDIU dst and src will be
1086 // same and not equal to sp
1090 /* read <src> register */
1091 const uint64_t src_opd_val = ReadRegisterUnsigned(
1092 eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
1096 /* Check if this is daddiu sp, sp, imm16 */
1097 if (dst == dwarf_sp_mips64) {
1099 * From the MIPS IV spec:
1101 * The term “unsigned” in the instruction name is a misnomer; this
1102 * operation is 64-bit modulo arithmetic that does not trap on overflow.
1103 * It is appropriate for arithmetic which is not signed, such as address
1104 * arithmetic, or integer arithmetic environments that ignore overflow,
1105 * such as “C” language arithmetic.
1107 * Assume 2's complement and rely on unsigned overflow here.
1109 uint64_t result = src_opd_val + imm;
1110 RegisterInfo reg_info_sp;
1112 if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp))
1113 context.SetRegisterPlusOffset(reg_info_sp, imm);
1115 /* We are allocating bytes on stack */
1116 context.type = eContextAdjustStackPointer;
1118 WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips64,
1124 context.SetImmediateSigned(imm);
1125 context.type = eContextImmediate;
1127 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1128 dwarf_zero_mips64 + dst, imm))
1135 bool EmulateInstructionMIPS64::Emulate_SD(llvm::MCInst &insn) {
1137 RegisterInfo reg_info_base;
1138 RegisterInfo reg_info_src;
1139 bool success = false;
1140 uint32_t imm16 = insn.getOperand(2).getImm();
1141 uint64_t imm = SignedBits(imm16, 15, 0);
1143 Context bad_vaddr_context;
1145 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1146 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1148 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base,
1150 !GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src,
1155 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + base,
1160 /* destination address */
1161 address = address + imm;
1163 /* We look for sp based non-volatile register stores */
1164 if (nonvolatile_reg_p(src)) {
1166 RegisterValue data_src;
1167 context.type = eContextPushRegisterOnStack;
1168 context.SetRegisterToRegisterPlusOffset(reg_info_src, reg_info_base, 0);
1170 uint8_t buffer[RegisterValue::kMaxRegisterByteSize];
1173 if (!ReadRegister(®_info_base, data_src))
1176 if (data_src.GetAsMemoryData(®_info_src, buffer, reg_info_src.byte_size,
1177 eByteOrderLittle, error) == 0)
1180 if (!WriteMemory(context, address, buffer, reg_info_src.byte_size))
1184 /* Set the bad_vaddr register with base address used in the instruction */
1185 bad_vaddr_context.type = eContextInvalid;
1186 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64,
1192 bool EmulateInstructionMIPS64::Emulate_LD(llvm::MCInst &insn) {
1193 bool success = false;
1195 int64_t imm, address;
1196 Context bad_vaddr_context;
1198 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1199 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1200 imm = insn.getOperand(2).getImm();
1202 RegisterInfo reg_info_base;
1203 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base,
1207 /* read base register */
1208 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + base,
1213 /* destination address */
1214 address = address + imm;
1216 /* Set the bad_vaddr register with base address used in the instruction */
1217 bad_vaddr_context.type = eContextInvalid;
1218 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64,
1221 if (nonvolatile_reg_p(src)) {
1222 RegisterValue data_src;
1223 RegisterInfo reg_info_src;
1225 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src,
1230 context.type = eContextRegisterLoad;
1232 return WriteRegister(context, ®_info_src, data_src);
1238 bool EmulateInstructionMIPS64::Emulate_LUI(llvm::MCInst &insn) {
1239 // LUI rt, immediate
1240 // GPR[rt] <- sign_extend(immediate << 16)
1242 const uint32_t imm32 = insn.getOperand(1).getImm() << 16;
1243 int64_t imm = SignedBits(imm32, 31, 0);
1247 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1248 context.SetImmediateSigned(imm);
1249 context.type = eContextImmediate;
1251 return WriteRegisterUnsigned(context, eRegisterKindDWARF,
1252 dwarf_zero_mips64 + rt, imm);
1255 bool EmulateInstructionMIPS64::Emulate_DSUBU_DADDU(llvm::MCInst &insn) {
1256 // DSUBU sp, <src>, <rt>
1257 // DADDU sp, <src>, <rt>
1258 // DADDU dst, sp, <rt>
1260 bool success = false;
1262 uint8_t src, dst, rt;
1263 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1265 dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1266 src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1268 /* Check if sp is destination register */
1269 if (dst == dwarf_sp_mips64) {
1270 rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1272 /* read <src> register */
1273 uint64_t src_opd_val = ReadRegisterUnsigned(
1274 eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
1278 /* read <rt > register */
1279 uint64_t rt_opd_val = ReadRegisterUnsigned(
1280 eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
1284 if (!strcasecmp(op_name, "DSUBU") || !strcasecmp(op_name, "SUBU"))
1285 result = src_opd_val - rt_opd_val;
1287 result = src_opd_val + rt_opd_val;
1290 RegisterInfo reg_info_sp;
1291 if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp))
1292 context.SetRegisterPlusOffset(reg_info_sp, rt_opd_val);
1294 /* We are allocating bytes on stack */
1295 context.type = eContextAdjustStackPointer;
1297 WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips64, result);
1300 } else if (src == dwarf_sp_mips64) {
1301 rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1303 /* read <src> register */
1304 uint64_t src_opd_val = ReadRegisterUnsigned(
1305 eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
1309 /* read <rt> register */
1310 uint64_t rt_opd_val = ReadRegisterUnsigned(
1311 eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
1317 if (!strcasecmp(op_name, "DSUBU") || !strcasecmp(op_name, "SUBU"))
1318 result = src_opd_val - rt_opd_val;
1320 result = src_opd_val + rt_opd_val;
1322 context.SetImmediateSigned(result);
1323 context.type = eContextImmediate;
1325 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1326 dwarf_zero_mips64 + dst, result))
1334 Emulate below MIPS branch instructions.
1335 BEQ, BNE : Branch on condition
1336 BEQL, BNEL : Branch likely
1338 bool EmulateInstructionMIPS64::Emulate_BXX_3ops(llvm::MCInst &insn) {
1339 bool success = false;
1341 int64_t offset, pc, rs_val, rt_val, target = 0;
1342 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1344 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1345 rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1346 offset = insn.getOperand(2).getImm();
1348 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1352 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1353 dwarf_zero_mips64 + rs, 0, &success);
1357 rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1358 dwarf_zero_mips64 + rt, 0, &success);
1362 if (!strcasecmp(op_name, "BEQ") || !strcasecmp(op_name, "BEQL")
1363 || !strcasecmp(op_name, "BEQ64") ) {
1364 if (rs_val == rt_val)
1365 target = pc + offset;
1368 } else if (!strcasecmp(op_name, "BNE") || !strcasecmp(op_name, "BNEL")
1369 || !strcasecmp(op_name, "BNE64")) {
1370 if (rs_val != rt_val)
1371 target = pc + offset;
1377 context.type = eContextRelativeBranchImmediate;
1378 context.SetImmediate(offset);
1380 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1385 Emulate below MIPS Non-Compact conditional branch and link instructions.
1387 BLTZALL, BGEZALL : Branch likely
1389 bool EmulateInstructionMIPS64::Emulate_Bcond_Link(llvm::MCInst &insn) {
1390 bool success = false;
1392 int64_t offset, pc, target = 0;
1394 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1396 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1397 offset = insn.getOperand(1).getImm();
1399 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1403 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1404 dwarf_zero_mips64 + rs, 0, &success);
1408 if (!strcasecmp(op_name, "BLTZAL") || !strcasecmp(op_name, "BLTZALL")) {
1410 target = pc + offset;
1413 } else if (!strcasecmp(op_name, "BGEZAL") ||
1414 !strcasecmp(op_name, "BGEZALL")) {
1416 target = pc + offset;
1423 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1427 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1434 bool EmulateInstructionMIPS64::Emulate_BAL(llvm::MCInst &insn) {
1435 bool success = false;
1436 int64_t offset, pc, target;
1440 * offset = sign_ext (offset << 2)
1444 offset = insn.getOperand(0).getImm();
1446 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1450 target = pc + offset;
1454 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1458 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1465 bool EmulateInstructionMIPS64::Emulate_BALC(llvm::MCInst &insn) {
1466 bool success = false;
1467 int64_t offset, pc, target;
1471 * offset = sign_ext (offset << 2)
1473 * PC = PC + 4 + offset
1475 offset = insn.getOperand(0).getImm();
1477 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1481 target = pc + offset;
1485 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1489 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1497 Emulate below MIPS conditional branch and link instructions.
1498 BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches
1500 bool EmulateInstructionMIPS64::Emulate_Bcond_Link_C(llvm::MCInst &insn) {
1501 bool success = false;
1503 int64_t offset, pc, rs_val, target = 0;
1504 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1506 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1507 offset = insn.getOperand(1).getImm();
1509 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1513 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1514 dwarf_zero_mips64 + rs, 0, &success);
1518 if (!strcasecmp(op_name, "BLEZALC")) {
1520 target = pc + offset;
1523 } else if (!strcasecmp(op_name, "BGEZALC")) {
1525 target = pc + offset;
1528 } else if (!strcasecmp(op_name, "BLTZALC")) {
1530 target = pc + offset;
1533 } else if (!strcasecmp(op_name, "BGTZALC")) {
1535 target = pc + offset;
1538 } else if (!strcasecmp(op_name, "BEQZALC")) {
1540 target = pc + offset;
1543 } else if (!strcasecmp(op_name, "BNEZALC")) {
1545 target = pc + offset;
1552 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1556 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1564 Emulate below MIPS branch instructions.
1565 BLTZL, BGEZL, BGTZL, BLEZL : Branch likely
1566 BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches
1568 bool EmulateInstructionMIPS64::Emulate_BXX_2ops(llvm::MCInst &insn) {
1569 bool success = false;
1571 int64_t offset, pc, rs_val, target = 0;
1572 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1574 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1575 offset = insn.getOperand(1).getImm();
1577 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1581 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1582 dwarf_zero_mips64 + rs, 0, &success);
1586 if (!strcasecmp(op_name, "BLTZL") || !strcasecmp(op_name, "BLTZ")
1587 || !strcasecmp(op_name, "BLTZ64")) {
1589 target = pc + offset;
1592 } else if (!strcasecmp(op_name, "BGEZL") || !strcasecmp(op_name, "BGEZ")
1593 || !strcasecmp(op_name, "BGEZ64")) {
1595 target = pc + offset;
1598 } else if (!strcasecmp(op_name, "BGTZL") || !strcasecmp(op_name, "BGTZ")
1599 || !strcasecmp(op_name, "BGTZ64")) {
1601 target = pc + offset;
1604 } else if (!strcasecmp(op_name, "BLEZL") || !strcasecmp(op_name, "BLEZ")
1605 || !strcasecmp(op_name, "BLEZ64")) {
1607 target = pc + offset;
1613 context.type = eContextRelativeBranchImmediate;
1614 context.SetImmediate(offset);
1616 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1620 bool EmulateInstructionMIPS64::Emulate_BC(llvm::MCInst &insn) {
1621 bool success = false;
1622 int64_t offset, pc, target;
1626 * offset = sign_ext (offset << 2)
1627 * PC = PC + 4 + offset
1629 offset = insn.getOperand(0).getImm();
1631 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1635 target = pc + offset;
1639 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1643 static int IsAdd64bitOverflow(int64_t a, int64_t b) {
1644 int64_t r = (uint64_t)a + (uint64_t)b;
1645 return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
1649 Emulate below MIPS branch instructions.
1650 BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch
1651 instructions with no delay slot
1653 bool EmulateInstructionMIPS64::Emulate_BXX_3ops_C(llvm::MCInst &insn) {
1654 bool success = false;
1656 int64_t offset, pc, rs_val, rt_val, target = 0;
1657 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1658 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
1660 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1661 rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1662 offset = insn.getOperand(2).getImm();
1664 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1668 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1669 dwarf_zero_mips64 + rs, 0, &success);
1673 rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1674 dwarf_zero_mips64 + rt, 0, &success);
1678 if (!strcasecmp(op_name, "BEQC") || !strcasecmp(op_name, "BEQC64")) {
1679 if (rs_val == rt_val)
1680 target = pc + offset;
1683 } else if (!strcasecmp(op_name, "BNEC") || !strcasecmp(op_name, "BNEC64")) {
1684 if (rs_val != rt_val)
1685 target = pc + offset;
1688 } else if (!strcasecmp(op_name, "BLTC") || !strcasecmp(op_name, "BLTC64")) {
1689 if (rs_val < rt_val)
1690 target = pc + offset;
1693 } else if (!strcasecmp(op_name, "BGEC64") || !strcasecmp(op_name, "BGEC")) {
1694 if (rs_val >= rt_val)
1695 target = pc + offset;
1698 } else if (!strcasecmp(op_name, "BLTUC") || !strcasecmp(op_name, "BLTUC64")) {
1699 if (rs_val < rt_val)
1700 target = pc + offset;
1703 } else if (!strcasecmp(op_name, "BGEUC") || !strcasecmp(op_name, "BGEUC64")) {
1704 if ((uint32_t)rs_val >= (uint32_t)rt_val)
1705 target = pc + offset;
1708 } else if (!strcasecmp(op_name, "BOVC")) {
1709 if (IsAdd64bitOverflow(rs_val, rt_val))
1710 target = pc + offset;
1713 } else if (!strcasecmp(op_name, "BNVC")) {
1714 if (!IsAdd64bitOverflow(rs_val, rt_val))
1715 target = pc + offset;
1721 context.type = eContextRelativeBranchImmediate;
1722 context.SetImmediate(current_inst_size + offset);
1724 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1729 Emulate below MIPS branch instructions.
1730 BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches
1732 bool EmulateInstructionMIPS64::Emulate_BXX_2ops_C(llvm::MCInst &insn) {
1733 bool success = false;
1735 int64_t offset, pc, target = 0;
1737 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1738 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
1740 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1741 offset = insn.getOperand(1).getImm();
1743 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1747 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1748 dwarf_zero_mips64 + rs, 0, &success);
1752 if (!strcasecmp(op_name, "BLTZC") || !strcasecmp(op_name, "BLTZC64")) {
1754 target = pc + offset;
1757 } else if (!strcasecmp(op_name, "BLEZC") || !strcasecmp(op_name, "BLEZC64")) {
1759 target = pc + offset;
1762 } else if (!strcasecmp(op_name, "BGEZC") || !strcasecmp(op_name, "BGEZC64")) {
1764 target = pc + offset;
1767 } else if (!strcasecmp(op_name, "BGTZC") || !strcasecmp(op_name, "BGTZC64")) {
1769 target = pc + offset;
1772 } else if (!strcasecmp(op_name, "BEQZC") || !strcasecmp(op_name, "BEQZC64")) {
1774 target = pc + offset;
1777 } else if (!strcasecmp(op_name, "BNEZC") || !strcasecmp(op_name, "BNEZC64")) {
1779 target = pc + offset;
1785 context.type = eContextRelativeBranchImmediate;
1786 context.SetImmediate(current_inst_size + offset);
1788 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1792 bool EmulateInstructionMIPS64::Emulate_J(llvm::MCInst &insn) {
1793 bool success = false;
1794 uint64_t offset, pc;
1798 * offset = sign_ext (offset << 2)
1799 * PC = PC[63-28] | offset
1801 offset = insn.getOperand(0).getImm();
1803 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1807 /* This is a PC-region branch and not PC-relative */
1808 pc = (pc & 0xFFFFFFFFF0000000ULL) | offset;
1812 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1816 bool EmulateInstructionMIPS64::Emulate_JAL(llvm::MCInst &insn) {
1817 bool success = false;
1818 uint64_t offset, target, pc;
1822 * offset = sign_ext (offset << 2)
1823 * PC = PC[63-28] | offset
1825 offset = insn.getOperand(0).getImm();
1827 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1831 /* This is a PC-region branch and not PC-relative */
1832 target = (pc & 0xFFFFFFFFF0000000ULL) | offset;
1836 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1840 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1847 bool EmulateInstructionMIPS64::Emulate_JALR(llvm::MCInst &insn) {
1848 bool success = false;
1850 uint64_t pc, rs_val;
1857 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1858 rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1860 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1864 rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0,
1871 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1875 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1876 dwarf_zero_mips64 + rt, pc + 8))
1882 bool EmulateInstructionMIPS64::Emulate_JIALC(llvm::MCInst &insn) {
1883 bool success = false;
1885 int64_t target, offset, pc, rt_val;
1889 * offset = sign_ext (offset)
1890 * PC = GPR[rt] + offset
1893 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1894 offset = insn.getOperand(1).getImm();
1896 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1900 rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1901 dwarf_zero_mips64 + rt, 0, &success);
1905 target = rt_val + offset;
1909 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1913 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1920 bool EmulateInstructionMIPS64::Emulate_JIC(llvm::MCInst &insn) {
1921 bool success = false;
1923 int64_t target, offset, rt_val;
1927 * offset = sign_ext (offset)
1928 * PC = GPR[rt] + offset
1930 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1931 offset = insn.getOperand(1).getImm();
1933 rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1934 dwarf_zero_mips64 + rt, 0, &success);
1938 target = rt_val + offset;
1942 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1946 bool EmulateInstructionMIPS64::Emulate_JR(llvm::MCInst &insn) {
1947 bool success = false;
1955 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1957 rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0,
1964 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1969 Emulate Branch on FP True/False
1970 BC1F, BC1FL : Branch on FP False (L stands for branch likely)
1971 BC1T, BC1TL : Branch on FP True (L stands for branch likely)
1973 bool EmulateInstructionMIPS64::Emulate_FP_branch(llvm::MCInst &insn) {
1974 bool success = false;
1976 int64_t pc, offset, target = 0;
1977 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1981 * condition <- (FPConditionCode(cc) == 0)
1983 * offset = sign_ext (offset)
1986 cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1987 offset = insn.getOperand(1).getImm();
1989 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1994 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
1998 /* fcsr[23], fcsr[25-31] are vaild condition bits */
1999 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2001 if (!strcasecmp(op_name, "BC1F") || !strcasecmp(op_name, "BC1FL")) {
2002 if ((fcsr & (1 << cc)) == 0)
2003 target = pc + offset;
2006 } else if (!strcasecmp(op_name, "BC1T") || !strcasecmp(op_name, "BC1TL")) {
2007 if ((fcsr & (1 << cc)) != 0)
2008 target = pc + offset;
2015 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2019 bool EmulateInstructionMIPS64::Emulate_BC1EQZ(llvm::MCInst &insn) {
2020 bool success = false;
2023 int64_t target, pc, offset;
2027 * condition <- (FPR[ft].bit0 == 0)
2029 * offset = sign_ext (offset)
2030 * PC = PC + 4 + offset
2032 ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2033 offset = insn.getOperand(1).getImm();
2035 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2039 ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0,
2044 if ((ft_val & 1) == 0)
2045 target = pc + 4 + offset;
2051 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2055 bool EmulateInstructionMIPS64::Emulate_BC1NEZ(llvm::MCInst &insn) {
2056 bool success = false;
2059 int64_t target, pc, offset;
2063 * condition <- (FPR[ft].bit0 != 0)
2065 * offset = sign_ext (offset)
2066 * PC = PC + 4 + offset
2068 ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2069 offset = insn.getOperand(1).getImm();
2071 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2075 ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0,
2080 if ((ft_val & 1) != 0)
2081 target = pc + 4 + offset;
2087 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2092 Emulate MIPS-3D Branch instructions
2093 BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes
2095 BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes
2098 bool EmulateInstructionMIPS64::Emulate_3D_branch(llvm::MCInst &insn) {
2099 bool success = false;
2101 int64_t pc, offset, target = 0;
2102 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
2104 cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2105 offset = insn.getOperand(1).getImm();
2107 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2111 fcsr = (uint32_t)ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips64,
2116 /* fcsr[23], fcsr[25-31] are vaild condition bits */
2117 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2119 if (!strcasecmp(op_name, "BC1ANY2F")) {
2120 /* if any one bit is 0 */
2121 if (((fcsr >> cc) & 3) != 3)
2122 target = pc + offset;
2125 } else if (!strcasecmp(op_name, "BC1ANY2T")) {
2126 /* if any one bit is 1 */
2127 if (((fcsr >> cc) & 3) != 0)
2128 target = pc + offset;
2131 } else if (!strcasecmp(op_name, "BC1ANY4F")) {
2132 /* if any one bit is 0 */
2133 if (((fcsr >> cc) & 0xf) != 0xf)
2134 target = pc + offset;
2137 } else if (!strcasecmp(op_name, "BC1ANY4T")) {
2138 /* if any one bit is 1 */
2139 if (((fcsr >> cc) & 0xf) != 0)
2140 target = pc + offset;
2147 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2151 bool EmulateInstructionMIPS64::Emulate_BNZB(llvm::MCInst &insn) {
2152 return Emulate_MSA_Branch_DF(insn, 1, true);
2155 bool EmulateInstructionMIPS64::Emulate_BNZH(llvm::MCInst &insn) {
2156 return Emulate_MSA_Branch_DF(insn, 2, true);
2159 bool EmulateInstructionMIPS64::Emulate_BNZW(llvm::MCInst &insn) {
2160 return Emulate_MSA_Branch_DF(insn, 4, true);
2163 bool EmulateInstructionMIPS64::Emulate_BNZD(llvm::MCInst &insn) {
2164 return Emulate_MSA_Branch_DF(insn, 8, true);
2167 bool EmulateInstructionMIPS64::Emulate_BZB(llvm::MCInst &insn) {
2168 return Emulate_MSA_Branch_DF(insn, 1, false);
2171 bool EmulateInstructionMIPS64::Emulate_BZH(llvm::MCInst &insn) {
2172 return Emulate_MSA_Branch_DF(insn, 2, false);
2175 bool EmulateInstructionMIPS64::Emulate_BZW(llvm::MCInst &insn) {
2176 return Emulate_MSA_Branch_DF(insn, 4, false);
2179 bool EmulateInstructionMIPS64::Emulate_BZD(llvm::MCInst &insn) {
2180 return Emulate_MSA_Branch_DF(insn, 8, false);
2183 bool EmulateInstructionMIPS64::Emulate_MSA_Branch_DF(llvm::MCInst &insn,
2184 int element_byte_size,
2186 bool success = false, branch_hit = true;
2188 RegisterValue reg_value;
2189 const uint8_t *ptr = nullptr;
2191 uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2192 int64_t offset = insn.getOperand(1).getImm();
2195 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2199 if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value))
2200 ptr = (const uint8_t *)reg_value.GetBytes();
2204 for (int i = 0; i < 16 / element_byte_size; i++) {
2205 switch (element_byte_size) {
2207 if ((*ptr == 0 && bnz) || (*ptr != 0 && !bnz))
2211 if ((*(const uint16_t *)ptr == 0 && bnz) ||
2212 (*(const uint16_t *)ptr != 0 && !bnz))
2216 if ((*(const uint32_t *)ptr == 0 && bnz) ||
2217 (*(const uint32_t *)ptr != 0 && !bnz))
2221 if ((*(const uint64_t *)ptr == 0 && bnz) ||
2222 (*(const uint64_t *)ptr != 0 && !bnz))
2228 ptr = ptr + element_byte_size;
2232 target = pc + offset;
2237 context.type = eContextRelativeBranchImmediate;
2239 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2243 bool EmulateInstructionMIPS64::Emulate_BNZV(llvm::MCInst &insn) {
2244 return Emulate_MSA_Branch_V(insn, true);
2247 bool EmulateInstructionMIPS64::Emulate_BZV(llvm::MCInst &insn) {
2248 return Emulate_MSA_Branch_V(insn, false);
2251 bool EmulateInstructionMIPS64::Emulate_MSA_Branch_V(llvm::MCInst &insn,
2253 bool success = false;
2255 llvm::APInt wr_val = llvm::APInt::getNullValue(128);
2256 llvm::APInt fail_value = llvm::APInt::getMaxValue(128);
2257 llvm::APInt zero_value = llvm::APInt::getNullValue(128);
2258 RegisterValue reg_value;
2260 uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2261 int64_t offset = insn.getOperand(1).getImm();
2264 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2268 if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value))
2269 wr_val = reg_value.GetAsUInt128(fail_value);
2273 if ((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) ||
2274 (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz))
2275 target = pc + offset;
2280 context.type = eContextRelativeBranchImmediate;
2282 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2286 bool EmulateInstructionMIPS64::Emulate_LDST_Imm(llvm::MCInst &insn) {
2287 bool success = false;
2289 int64_t imm, address;
2290 Context bad_vaddr_context;
2292 uint32_t num_operands = insn.getNumOperands();
2294 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
2295 imm = insn.getOperand(num_operands - 1).getImm();
2297 RegisterInfo reg_info_base;
2298 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base,
2302 /* read base register */
2303 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0,
2308 /* destination address */
2309 address = address + imm;
2311 /* Set the bad_vaddr register with base address used in the instruction */
2312 bad_vaddr_context.type = eContextInvalid;
2313 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
2319 bool EmulateInstructionMIPS64::Emulate_LDST_Reg(llvm::MCInst &insn) {
2320 bool success = false;
2321 uint32_t base, index;
2322 int64_t address, index_address;
2323 Context bad_vaddr_context;
2325 uint32_t num_operands = insn.getNumOperands();
2327 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
2329 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 1).getReg());
2331 RegisterInfo reg_info_base, reg_info_index;
2332 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base,
2336 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + index,
2340 /* read base register */
2341 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0,
2346 /* read index register */
2347 index_address = ReadRegisterUnsigned(eRegisterKindDWARF,
2348 dwarf_zero_mips + index, 0, &success);
2352 /* destination address */
2353 address = address + index_address;
2355 /* Set the bad_vaddr register with base address used in the instruction */
2356 bad_vaddr_context.type = eContextInvalid;
2357 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,