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/MC/MCTargetOptions.h"
32 #include "llvm/Support/TargetRegistry.h"
33 #include "llvm/Support/TargetSelect.h"
35 #include "llvm/ADT/STLExtras.h"
37 #include "Plugins/Process/Utility/InstructionUtils.h"
38 #include "Plugins/Process/Utility/RegisterContext_mips.h"
41 using namespace lldb_private;
43 #define UInt(x) ((uint64_t)x)
44 #define integer int64_t
47 // EmulateInstructionMIPS64 implementation
52 void LLVMInitializeMipsTargetInfo();
53 void LLVMInitializeMipsTarget();
54 void LLVMInitializeMipsAsmPrinter();
55 void LLVMInitializeMipsTargetMC();
56 void LLVMInitializeMipsDisassembler();
60 EmulateInstructionMIPS64::EmulateInstructionMIPS64(
61 const lldb_private::ArchSpec &arch)
62 : EmulateInstruction(arch) {
63 /* Create instance of llvm::MCDisassembler */
65 llvm::Triple triple = arch.GetTriple();
66 const llvm::Target *target =
67 llvm::TargetRegistry::lookupTarget(triple.getTriple(), Status);
70 * If we fail to get the target then we haven't registered it. The
71 * SystemInitializerCommon
72 * does not initialize targets, MCs and disassemblers. However we need the
74 * to decode the instructions so that the decoding complexity stays with LLVM.
75 * Initialize the MIPS targets and disassemblers.
79 LLVMInitializeMipsTargetInfo();
80 LLVMInitializeMipsTarget();
81 LLVMInitializeMipsAsmPrinter();
82 LLVMInitializeMipsTargetMC();
83 LLVMInitializeMipsDisassembler();
84 target = llvm::TargetRegistry::lookupTarget(triple.getTriple(), Status);
92 switch (arch.GetCore()) {
93 case ArchSpec::eCore_mips32:
94 case ArchSpec::eCore_mips32el:
97 case ArchSpec::eCore_mips32r2:
98 case ArchSpec::eCore_mips32r2el:
101 case ArchSpec::eCore_mips32r3:
102 case ArchSpec::eCore_mips32r3el:
105 case ArchSpec::eCore_mips32r5:
106 case ArchSpec::eCore_mips32r5el:
109 case ArchSpec::eCore_mips32r6:
110 case ArchSpec::eCore_mips32r6el:
113 case ArchSpec::eCore_mips64:
114 case ArchSpec::eCore_mips64el:
117 case ArchSpec::eCore_mips64r2:
118 case ArchSpec::eCore_mips64r2el:
121 case ArchSpec::eCore_mips64r3:
122 case ArchSpec::eCore_mips64r3el:
125 case ArchSpec::eCore_mips64r5:
126 case ArchSpec::eCore_mips64r5el:
129 case ArchSpec::eCore_mips64r6:
130 case ArchSpec::eCore_mips64r6el:
138 std::string features = "";
139 uint32_t arch_flags = arch.GetFlags();
140 if (arch_flags & ArchSpec::eMIPSAse_msa)
142 if (arch_flags & ArchSpec::eMIPSAse_dsp)
144 if (arch_flags & ArchSpec::eMIPSAse_dspr2)
145 features += "+dspr2,";
146 if (arch_flags & ArchSpec::eMIPSAse_mips16)
147 features += "+mips16,";
148 if (arch_flags & ArchSpec::eMIPSAse_micromips)
149 features += "+micromips,";
151 m_reg_info.reset(target->createMCRegInfo(triple.getTriple()));
152 assert(m_reg_info.get());
154 m_insn_info.reset(target->createMCInstrInfo());
155 assert(m_insn_info.get());
157 llvm::MCTargetOptions MCOptions;
159 target->createMCAsmInfo(*m_reg_info, triple.getTriple(), MCOptions));
160 m_subtype_info.reset(
161 target->createMCSubtargetInfo(triple.getTriple(), cpu, features));
162 assert(m_asm_info.get() && m_subtype_info.get());
165 new llvm::MCContext(m_asm_info.get(), m_reg_info.get(), nullptr));
166 assert(m_context.get());
168 m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context));
169 assert(m_disasm.get());
172 void EmulateInstructionMIPS64::Initialize() {
173 PluginManager::RegisterPlugin(GetPluginNameStatic(),
174 GetPluginDescriptionStatic(), CreateInstance);
177 void EmulateInstructionMIPS64::Terminate() {
178 PluginManager::UnregisterPlugin(CreateInstance);
181 ConstString EmulateInstructionMIPS64::GetPluginNameStatic() {
182 ConstString g_plugin_name("lldb.emulate-instruction.mips64");
183 return g_plugin_name;
186 lldb_private::ConstString EmulateInstructionMIPS64::GetPluginName() {
187 static ConstString g_plugin_name("EmulateInstructionMIPS64");
188 return g_plugin_name;
191 const char *EmulateInstructionMIPS64::GetPluginDescriptionStatic() {
192 return "Emulate instructions for the MIPS64 architecture.";
196 EmulateInstructionMIPS64::CreateInstance(const ArchSpec &arch,
197 InstructionType inst_type) {
198 if (EmulateInstructionMIPS64::SupportsEmulatingInstructionsOfTypeStatic(
200 if (arch.GetTriple().getArch() == llvm::Triple::mips64 ||
201 arch.GetTriple().getArch() == llvm::Triple::mips64el) {
202 return new EmulateInstructionMIPS64(arch);
209 bool EmulateInstructionMIPS64::SetTargetTriple(const ArchSpec &arch) {
210 return arch.GetTriple().getArch() == llvm::Triple::mips64 ||
211 arch.GetTriple().getArch() == llvm::Triple::mips64el;
214 const char *EmulateInstructionMIPS64::GetRegisterName(unsigned reg_num,
215 bool alternate_name) {
216 if (alternate_name) {
218 case dwarf_sp_mips64:
220 case dwarf_r30_mips64:
222 case dwarf_ra_mips64:
224 case dwarf_f0_mips64:
226 case dwarf_f1_mips64:
228 case dwarf_f2_mips64:
230 case dwarf_f3_mips64:
232 case dwarf_f4_mips64:
234 case dwarf_f5_mips64:
236 case dwarf_f6_mips64:
238 case dwarf_f7_mips64:
240 case dwarf_f8_mips64:
242 case dwarf_f9_mips64:
244 case dwarf_f10_mips64:
246 case dwarf_f11_mips64:
248 case dwarf_f12_mips64:
250 case dwarf_f13_mips64:
252 case dwarf_f14_mips64:
254 case dwarf_f15_mips64:
256 case dwarf_f16_mips64:
258 case dwarf_f17_mips64:
260 case dwarf_f18_mips64:
262 case dwarf_f19_mips64:
264 case dwarf_f20_mips64:
266 case dwarf_f21_mips64:
268 case dwarf_f22_mips64:
270 case dwarf_f23_mips64:
272 case dwarf_f24_mips64:
274 case dwarf_f25_mips64:
276 case dwarf_f26_mips64:
278 case dwarf_f27_mips64:
280 case dwarf_f28_mips64:
282 case dwarf_f29_mips64:
284 case dwarf_f30_mips64:
286 case dwarf_f31_mips64:
288 case dwarf_w0_mips64:
290 case dwarf_w1_mips64:
292 case dwarf_w2_mips64:
294 case dwarf_w3_mips64:
296 case dwarf_w4_mips64:
298 case dwarf_w5_mips64:
300 case dwarf_w6_mips64:
302 case dwarf_w7_mips64:
304 case dwarf_w8_mips64:
306 case dwarf_w9_mips64:
308 case dwarf_w10_mips64:
310 case dwarf_w11_mips64:
312 case dwarf_w12_mips64:
314 case dwarf_w13_mips64:
316 case dwarf_w14_mips64:
318 case dwarf_w15_mips64:
320 case dwarf_w16_mips64:
322 case dwarf_w17_mips64:
324 case dwarf_w18_mips64:
326 case dwarf_w19_mips64:
328 case dwarf_w20_mips64:
330 case dwarf_w21_mips64:
332 case dwarf_w22_mips64:
334 case dwarf_w23_mips64:
336 case dwarf_w24_mips64:
338 case dwarf_w25_mips64:
340 case dwarf_w26_mips64:
342 case dwarf_w27_mips64:
344 case dwarf_w28_mips64:
346 case dwarf_w29_mips64:
348 case dwarf_w30_mips64:
350 case dwarf_w31_mips64:
352 case dwarf_mir_mips64:
354 case dwarf_mcsr_mips64:
356 case dwarf_config5_mips64:
365 case dwarf_zero_mips64:
367 case dwarf_r1_mips64:
369 case dwarf_r2_mips64:
371 case dwarf_r3_mips64:
373 case dwarf_r4_mips64:
375 case dwarf_r5_mips64:
377 case dwarf_r6_mips64:
379 case dwarf_r7_mips64:
381 case dwarf_r8_mips64:
383 case dwarf_r9_mips64:
385 case dwarf_r10_mips64:
387 case dwarf_r11_mips64:
389 case dwarf_r12_mips64:
391 case dwarf_r13_mips64:
393 case dwarf_r14_mips64:
395 case dwarf_r15_mips64:
397 case dwarf_r16_mips64:
399 case dwarf_r17_mips64:
401 case dwarf_r18_mips64:
403 case dwarf_r19_mips64:
405 case dwarf_r20_mips64:
407 case dwarf_r21_mips64:
409 case dwarf_r22_mips64:
411 case dwarf_r23_mips64:
413 case dwarf_r24_mips64:
415 case dwarf_r25_mips64:
417 case dwarf_r26_mips64:
419 case dwarf_r27_mips64:
421 case dwarf_gp_mips64:
423 case dwarf_sp_mips64:
425 case dwarf_r30_mips64:
427 case dwarf_ra_mips64:
429 case dwarf_sr_mips64:
431 case dwarf_lo_mips64:
433 case dwarf_hi_mips64:
435 case dwarf_bad_mips64:
437 case dwarf_cause_mips64:
439 case dwarf_pc_mips64:
441 case dwarf_f0_mips64:
443 case dwarf_f1_mips64:
445 case dwarf_f2_mips64:
447 case dwarf_f3_mips64:
449 case dwarf_f4_mips64:
451 case dwarf_f5_mips64:
453 case dwarf_f6_mips64:
455 case dwarf_f7_mips64:
457 case dwarf_f8_mips64:
459 case dwarf_f9_mips64:
461 case dwarf_f10_mips64:
463 case dwarf_f11_mips64:
465 case dwarf_f12_mips64:
467 case dwarf_f13_mips64:
469 case dwarf_f14_mips64:
471 case dwarf_f15_mips64:
473 case dwarf_f16_mips64:
475 case dwarf_f17_mips64:
477 case dwarf_f18_mips64:
479 case dwarf_f19_mips64:
481 case dwarf_f20_mips64:
483 case dwarf_f21_mips64:
485 case dwarf_f22_mips64:
487 case dwarf_f23_mips64:
489 case dwarf_f24_mips64:
491 case dwarf_f25_mips64:
493 case dwarf_f26_mips64:
495 case dwarf_f27_mips64:
497 case dwarf_f28_mips64:
499 case dwarf_f29_mips64:
501 case dwarf_f30_mips64:
503 case dwarf_f31_mips64:
505 case dwarf_fcsr_mips64:
507 case dwarf_fir_mips64:
509 case dwarf_w0_mips64:
511 case dwarf_w1_mips64:
513 case dwarf_w2_mips64:
515 case dwarf_w3_mips64:
517 case dwarf_w4_mips64:
519 case dwarf_w5_mips64:
521 case dwarf_w6_mips64:
523 case dwarf_w7_mips64:
525 case dwarf_w8_mips64:
527 case dwarf_w9_mips64:
529 case dwarf_w10_mips64:
531 case dwarf_w11_mips64:
533 case dwarf_w12_mips64:
535 case dwarf_w13_mips64:
537 case dwarf_w14_mips64:
539 case dwarf_w15_mips64:
541 case dwarf_w16_mips64:
543 case dwarf_w17_mips64:
545 case dwarf_w18_mips64:
547 case dwarf_w19_mips64:
549 case dwarf_w20_mips64:
551 case dwarf_w21_mips64:
553 case dwarf_w22_mips64:
555 case dwarf_w23_mips64:
557 case dwarf_w24_mips64:
559 case dwarf_w25_mips64:
561 case dwarf_w26_mips64:
563 case dwarf_w27_mips64:
565 case dwarf_w28_mips64:
567 case dwarf_w29_mips64:
569 case dwarf_w30_mips64:
571 case dwarf_w31_mips64:
573 case dwarf_mcsr_mips64:
575 case dwarf_mir_mips64:
577 case dwarf_config5_mips64:
583 bool EmulateInstructionMIPS64::GetRegisterInfo(RegisterKind reg_kind,
585 RegisterInfo ®_info) {
586 if (reg_kind == eRegisterKindGeneric) {
588 case LLDB_REGNUM_GENERIC_PC:
589 reg_kind = eRegisterKindDWARF;
590 reg_num = dwarf_pc_mips64;
592 case LLDB_REGNUM_GENERIC_SP:
593 reg_kind = eRegisterKindDWARF;
594 reg_num = dwarf_sp_mips64;
596 case LLDB_REGNUM_GENERIC_FP:
597 reg_kind = eRegisterKindDWARF;
598 reg_num = dwarf_r30_mips64;
600 case LLDB_REGNUM_GENERIC_RA:
601 reg_kind = eRegisterKindDWARF;
602 reg_num = dwarf_ra_mips64;
604 case LLDB_REGNUM_GENERIC_FLAGS:
605 reg_kind = eRegisterKindDWARF;
606 reg_num = dwarf_sr_mips64;
613 if (reg_kind == eRegisterKindDWARF) {
614 ::memset(®_info, 0, sizeof(RegisterInfo));
615 ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
617 if (reg_num == dwarf_sr_mips64 || reg_num == dwarf_fcsr_mips64 ||
618 reg_num == dwarf_fir_mips64 || reg_num == dwarf_mcsr_mips64 ||
619 reg_num == dwarf_mir_mips64 || reg_num == dwarf_config5_mips64) {
620 reg_info.byte_size = 4;
621 reg_info.format = eFormatHex;
622 reg_info.encoding = eEncodingUint;
623 } else if ((int)reg_num >= dwarf_zero_mips64 &&
624 (int)reg_num <= dwarf_f31_mips64) {
625 reg_info.byte_size = 8;
626 reg_info.format = eFormatHex;
627 reg_info.encoding = eEncodingUint;
628 } else if ((int)reg_num >= dwarf_w0_mips64 &&
629 (int)reg_num <= dwarf_w31_mips64) {
630 reg_info.byte_size = 16;
631 reg_info.format = eFormatVectorOfUInt8;
632 reg_info.encoding = eEncodingVector;
637 reg_info.name = GetRegisterName(reg_num, false);
638 reg_info.alt_name = GetRegisterName(reg_num, true);
639 reg_info.kinds[eRegisterKindDWARF] = reg_num;
642 case dwarf_r30_mips64:
643 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
645 case dwarf_ra_mips64:
646 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
648 case dwarf_sp_mips64:
649 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
651 case dwarf_pc_mips64:
652 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
654 case dwarf_sr_mips64:
655 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
665 EmulateInstructionMIPS64::MipsOpcode *
666 EmulateInstructionMIPS64::GetOpcodeForInstruction(const char *op_name) {
667 static EmulateInstructionMIPS64::MipsOpcode g_opcodes[] = {
668 // Prologue/Epilogue instructions
669 {"DADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu,
670 "DADDIU rt, rs, immediate"},
671 {"ADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu,
672 "ADDIU rt, rs, immediate"},
673 {"SD", &EmulateInstructionMIPS64::Emulate_SD, "SD rt, offset(rs)"},
674 {"LD", &EmulateInstructionMIPS64::Emulate_LD, "LD rt, offset(base)"},
675 {"DSUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
677 {"SUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
679 {"DADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
681 {"ADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
683 {"LUI", &EmulateInstructionMIPS64::Emulate_LUI, "LUI rt, immediate"},
685 // Load/Store instructions
686 /* Following list of emulated instructions are required by implementation
687 of hardware watchpoint
688 for MIPS in lldb. As we just need the address accessed by instructions,
690 all these instructions in 2 functions depending on their addressing
693 {"LB", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
694 "LB rt, offset(base)"},
695 {"LBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
696 "LBE rt, offset(base)"},
697 {"LBU", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
698 "LBU rt, offset(base)"},
699 {"LBUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
700 "LBUE rt, offset(base)"},
701 {"LDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
702 "LDC1 ft, offset(base)"},
703 {"LDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
704 "LDL rt, offset(base)"},
705 {"LDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
706 "LDR rt, offset(base)"},
707 {"LLD", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
708 "LLD rt, offset(base)"},
709 {"LDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
710 "LDC2 rt, offset(base)"},
711 {"LDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
712 "LDXC1 fd, index (base)"},
713 {"LH", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
714 "LH rt, offset(base)"},
715 {"LHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
716 "LHE rt, offset(base)"},
717 {"LHU", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
718 "LHU rt, offset(base)"},
719 {"LHUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
720 "LHUE rt, offset(base)"},
721 {"LL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
722 "LL rt, offset(base)"},
723 {"LLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
724 "LLE rt, offset(base)"},
725 {"LUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
726 "LUXC1 fd, index (base)"},
727 {"LW", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
728 "LW rt, offset(rs)"},
729 {"LWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
730 "LWC1 ft, offset(base)"},
731 {"LWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
732 "LWC2 rt, offset(base)"},
733 {"LWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
734 "LWE rt, offset(base)"},
735 {"LWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
736 "LWL rt, offset(base)"},
737 {"LWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
738 "LWLE rt, offset(base)"},
739 {"LWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
740 "LWR rt, offset(base)"},
741 {"LWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
742 "LWRE rt, offset(base)"},
743 {"LWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
744 "LWXC1 fd, index (base)"},
746 {"SB", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
747 "SB rt, offset(base)"},
748 {"SBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
749 "SBE rt, offset(base)"},
750 {"SC", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
751 "SC rt, offset(base)"},
752 {"SCE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
753 "SCE rt, offset(base)"},
754 {"SCD", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
755 "SCD rt, offset(base)"},
756 {"SDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
757 "SDL rt, offset(base)"},
758 {"SDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
759 "SDR rt, offset(base)"},
760 {"SDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
761 "SDC1 ft, offset(base)"},
762 {"SDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
763 "SDC2 rt, offset(base)"},
764 {"SDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
765 "SDXC1 fs, index (base)"},
766 {"SH", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
767 "SH rt, offset(base)"},
768 {"SHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
769 "SHE rt, offset(base)"},
770 {"SUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
771 "SUXC1 fs, index (base)"},
772 {"SW", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
773 "SW rt, offset(rs)"},
774 {"SWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
775 "SWC1 ft, offset(base)"},
776 {"SWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
777 "SWC2 rt, offset(base)"},
778 {"SWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
779 "SWE rt, offset(base)"},
780 {"SWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
781 "SWL rt, offset(base)"},
782 {"SWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
783 "SWLE rt, offset(base)"},
784 {"SWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
785 "SWR rt, offset(base)"},
786 {"SWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
787 "SWRE rt, offset(base)"},
788 {"SWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
789 "SWXC1 fs, index (base)"},
791 // Branch instructions
792 {"BEQ", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"},
793 {"BEQ64", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"},
794 {"BNE", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"},
795 {"BNE64", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"},
796 {"BEQL", &EmulateInstructionMIPS64::Emulate_BXX_3ops,
797 "BEQL rs,rt,offset"},
798 {"BNEL", &EmulateInstructionMIPS64::Emulate_BXX_3ops,
799 "BNEL rs,rt,offset"},
800 {"BGEZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
801 "BGEZALL rt,offset"},
802 {"BAL", &EmulateInstructionMIPS64::Emulate_BAL, "BAL offset"},
803 {"BGEZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
805 {"BALC", &EmulateInstructionMIPS64::Emulate_BALC, "BALC offset"},
806 {"BC", &EmulateInstructionMIPS64::Emulate_BC, "BC offset"},
807 {"BGEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"},
808 {"BGEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"},
809 {"BLEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
810 "BLEZALC rs,offset"},
811 {"BGEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
812 "BGEZALC rs,offset"},
813 {"BLTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
814 "BLTZALC rs,offset"},
815 {"BGTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
816 "BGTZALC rs,offset"},
817 {"BEQZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
818 "BEQZALC rs,offset"},
819 {"BNEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
820 "BNEZALC rs,offset"},
821 {"BEQC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
822 "BEQC rs,rt,offset"},
823 {"BEQC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
824 "BEQC rs,rt,offset"},
825 {"BNEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
826 "BNEC rs,rt,offset"},
827 {"BNEC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
828 "BNEC rs,rt,offset"},
829 {"BLTC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
830 "BLTC rs,rt,offset"},
831 {"BLTC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
832 "BLTC rs,rt,offset"},
833 {"BGEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
834 "BGEC rs,rt,offset"},
835 {"BGEC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
836 "BGEC rs,rt,offset"},
837 {"BLTUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
838 "BLTUC rs,rt,offset"},
839 {"BLTUC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
840 "BLTUC rs,rt,offset"},
841 {"BGEUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
842 "BGEUC rs,rt,offset"},
843 {"BGEUC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
844 "BGEUC rs,rt,offset"},
845 {"BLTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
847 {"BLTZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
849 {"BLEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
851 {"BLEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
853 {"BGEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
855 {"BGEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
857 {"BGTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
859 {"BGTZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
861 {"BEQZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
863 {"BEQZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
865 {"BNEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
867 {"BNEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
869 {"BGEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZL rt,offset"},
870 {"BGTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"},
871 {"BGTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"},
872 {"BGTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZL rt,offset"},
873 {"BLEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"},
874 {"BLEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"},
875 {"BLEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZL rt,offset"},
876 {"BLTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"},
877 {"BLTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"},
878 {"BLTZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
880 {"BLTZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
881 "BLTZALL rt,offset"},
882 {"BLTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZL rt,offset"},
883 {"BOVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
884 "BOVC rs,rt,offset"},
885 {"BNVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
886 "BNVC rs,rt,offset"},
887 {"J", &EmulateInstructionMIPS64::Emulate_J, "J target"},
888 {"JAL", &EmulateInstructionMIPS64::Emulate_JAL, "JAL target"},
889 {"JALX", &EmulateInstructionMIPS64::Emulate_JAL, "JALX target"},
890 {"JALR", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target"},
891 {"JALR64", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target"},
892 {"JALR_HB", &EmulateInstructionMIPS64::Emulate_JALR, "JALR.HB target"},
893 {"JIALC", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"},
894 {"JIALC64", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"},
895 {"JIC", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"},
896 {"JIC64", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"},
897 {"JR", &EmulateInstructionMIPS64::Emulate_JR, "JR target"},
898 {"JR64", &EmulateInstructionMIPS64::Emulate_JR, "JR target"},
899 {"JR_HB", &EmulateInstructionMIPS64::Emulate_JR, "JR.HB target"},
900 {"BC1F", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1F cc, offset"},
901 {"BC1T", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1T cc, offset"},
902 {"BC1FL", &EmulateInstructionMIPS64::Emulate_FP_branch,
904 {"BC1TL", &EmulateInstructionMIPS64::Emulate_FP_branch,
906 {"BC1EQZ", &EmulateInstructionMIPS64::Emulate_BC1EQZ,
907 "BC1EQZ ft, offset"},
908 {"BC1NEZ", &EmulateInstructionMIPS64::Emulate_BC1NEZ,
909 "BC1NEZ ft, offset"},
910 {"BC1ANY2F", &EmulateInstructionMIPS64::Emulate_3D_branch,
911 "BC1ANY2F cc, offset"},
912 {"BC1ANY2T", &EmulateInstructionMIPS64::Emulate_3D_branch,
913 "BC1ANY2T cc, offset"},
914 {"BC1ANY4F", &EmulateInstructionMIPS64::Emulate_3D_branch,
915 "BC1ANY4F cc, offset"},
916 {"BC1ANY4T", &EmulateInstructionMIPS64::Emulate_3D_branch,
917 "BC1ANY4T cc, offset"},
918 {"BNZ_B", &EmulateInstructionMIPS64::Emulate_BNZB, "BNZ.b wt,s16"},
919 {"BNZ_H", &EmulateInstructionMIPS64::Emulate_BNZH, "BNZ.h wt,s16"},
920 {"BNZ_W", &EmulateInstructionMIPS64::Emulate_BNZW, "BNZ.w wt,s16"},
921 {"BNZ_D", &EmulateInstructionMIPS64::Emulate_BNZD, "BNZ.d wt,s16"},
922 {"BZ_B", &EmulateInstructionMIPS64::Emulate_BZB, "BZ.b wt,s16"},
923 {"BZ_H", &EmulateInstructionMIPS64::Emulate_BZH, "BZ.h wt,s16"},
924 {"BZ_W", &EmulateInstructionMIPS64::Emulate_BZW, "BZ.w wt,s16"},
925 {"BZ_D", &EmulateInstructionMIPS64::Emulate_BZD, "BZ.d wt,s16"},
926 {"BNZ_V", &EmulateInstructionMIPS64::Emulate_BNZV, "BNZ.V wt,s16"},
927 {"BZ_V", &EmulateInstructionMIPS64::Emulate_BZV, "BZ.V wt,s16"},
930 static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes);
932 for (size_t i = 0; i < k_num_mips_opcodes; ++i) {
933 if (!strcasecmp(g_opcodes[i].op_name, op_name))
934 return &g_opcodes[i];
940 bool EmulateInstructionMIPS64::ReadInstruction() {
941 bool success = false;
942 m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
943 LLDB_INVALID_ADDRESS, &success);
945 Context read_inst_context;
946 read_inst_context.type = eContextReadOpcode;
947 read_inst_context.SetNoArgs();
948 m_opcode.SetOpcode32(
949 ReadMemoryUnsigned(read_inst_context, m_addr, 4, 0, &success),
953 m_addr = LLDB_INVALID_ADDRESS;
957 bool EmulateInstructionMIPS64::EvaluateInstruction(uint32_t evaluate_options) {
958 bool success = false;
959 llvm::MCInst mc_insn;
963 /* Keep the complexity of the decode logic with the llvm::MCDisassembler
965 if (m_opcode.GetData(data)) {
966 llvm::MCDisassembler::DecodeStatus decode_status;
967 llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());
968 decode_status = m_disasm->getInstruction(mc_insn, insn_size, raw_insn,
969 m_addr, llvm::nulls());
970 if (decode_status != llvm::MCDisassembler::Success)
975 * mc_insn.getOpcode() returns decoded opcode. However to make use
976 * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc".
978 const char *op_name = m_insn_info->getName(mc_insn.getOpcode()).data();
980 if (op_name == nullptr)
984 * Decoding has been done already. Just get the call-back function
985 * and emulate the instruction.
987 MipsOpcode *opcode_data = GetOpcodeForInstruction(op_name);
989 if (opcode_data == nullptr)
992 uint64_t old_pc = 0, new_pc = 0;
993 const bool auto_advance_pc =
994 evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
996 if (auto_advance_pc) {
998 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1003 /* emulate instruction */
1004 success = (this->*opcode_data->callback)(mc_insn);
1008 if (auto_advance_pc) {
1010 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1014 /* If we haven't changed the PC, change it here */
1015 if (old_pc == new_pc) {
1018 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1027 bool EmulateInstructionMIPS64::CreateFunctionEntryUnwind(
1028 UnwindPlan &unwind_plan) {
1029 unwind_plan.Clear();
1030 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
1032 UnwindPlan::RowSP row(new UnwindPlan::Row);
1033 const bool can_replace = false;
1035 // Our previous Call Frame Address is the stack pointer
1036 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips64, 0);
1038 // Our previous PC is in the RA
1039 row->SetRegisterLocationToRegister(dwarf_pc_mips64, dwarf_ra_mips64,
1042 unwind_plan.AppendRow(row);
1044 // All other registers are the same.
1045 unwind_plan.SetSourceName("EmulateInstructionMIPS64");
1046 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1047 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
1048 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
1049 unwind_plan.SetReturnAddressRegister(dwarf_ra_mips64);
1054 bool EmulateInstructionMIPS64::nonvolatile_reg_p(uint64_t regnum) {
1056 case dwarf_r16_mips64:
1057 case dwarf_r17_mips64:
1058 case dwarf_r18_mips64:
1059 case dwarf_r19_mips64:
1060 case dwarf_r20_mips64:
1061 case dwarf_r21_mips64:
1062 case dwarf_r22_mips64:
1063 case dwarf_r23_mips64:
1064 case dwarf_gp_mips64:
1065 case dwarf_sp_mips64:
1066 case dwarf_r30_mips64:
1067 case dwarf_ra_mips64:
1075 bool EmulateInstructionMIPS64::Emulate_DADDiu(llvm::MCInst &insn) {
1076 // DADDIU rt, rs, immediate
1077 // GPR[rt] <- GPR[rs] + sign_extend(immediate)
1080 bool success = false;
1081 const uint32_t imm16 = insn.getOperand(2).getImm();
1082 int64_t imm = SignedBits(imm16, 15, 0);
1084 dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1085 src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1087 // If immediate is greater than 2^16 - 1 then clang generate LUI,
1088 // (D)ADDIU,(D)SUBU instructions in prolog. Example lui $1, 0x2 daddiu $1,
1089 // $1, -0x5920 dsubu $sp, $sp, $1 In this case, (D)ADDIU dst and src will be
1090 // same and not equal to sp
1094 /* read <src> register */
1095 const uint64_t src_opd_val = ReadRegisterUnsigned(
1096 eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
1100 /* Check if this is daddiu sp, sp, imm16 */
1101 if (dst == dwarf_sp_mips64) {
1103 * From the MIPS IV spec:
1105 * The term “unsigned” in the instruction name is a misnomer; this
1106 * operation is 64-bit modulo arithmetic that does not trap on overflow.
1107 * It is appropriate for arithmetic which is not signed, such as address
1108 * arithmetic, or integer arithmetic environments that ignore overflow,
1109 * such as “C” language arithmetic.
1111 * Assume 2's complement and rely on unsigned overflow here.
1113 uint64_t result = src_opd_val + imm;
1114 RegisterInfo reg_info_sp;
1116 if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp))
1117 context.SetRegisterPlusOffset(reg_info_sp, imm);
1119 /* We are allocating bytes on stack */
1120 context.type = eContextAdjustStackPointer;
1122 WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips64,
1128 context.SetImmediateSigned(imm);
1129 context.type = eContextImmediate;
1131 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1132 dwarf_zero_mips64 + dst, imm))
1139 bool EmulateInstructionMIPS64::Emulate_SD(llvm::MCInst &insn) {
1141 RegisterInfo reg_info_base;
1142 RegisterInfo reg_info_src;
1143 bool success = false;
1144 uint32_t imm16 = insn.getOperand(2).getImm();
1145 uint64_t imm = SignedBits(imm16, 15, 0);
1147 Context bad_vaddr_context;
1149 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1150 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1152 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base,
1154 !GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src,
1159 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + base,
1164 /* destination address */
1165 address = address + imm;
1167 /* We look for sp based non-volatile register stores */
1168 if (nonvolatile_reg_p(src)) {
1170 RegisterValue data_src;
1171 context.type = eContextPushRegisterOnStack;
1172 context.SetRegisterToRegisterPlusOffset(reg_info_src, reg_info_base, 0);
1174 uint8_t buffer[RegisterValue::kMaxRegisterByteSize];
1177 if (!ReadRegister(®_info_base, data_src))
1180 if (data_src.GetAsMemoryData(®_info_src, buffer, reg_info_src.byte_size,
1181 eByteOrderLittle, error) == 0)
1184 if (!WriteMemory(context, address, buffer, reg_info_src.byte_size))
1188 /* Set the bad_vaddr register with base address used in the instruction */
1189 bad_vaddr_context.type = eContextInvalid;
1190 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64,
1196 bool EmulateInstructionMIPS64::Emulate_LD(llvm::MCInst &insn) {
1197 bool success = false;
1199 int64_t imm, address;
1200 Context bad_vaddr_context;
1202 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1203 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1204 imm = insn.getOperand(2).getImm();
1206 RegisterInfo reg_info_base;
1207 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base,
1211 /* read base register */
1212 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + base,
1217 /* destination address */
1218 address = address + imm;
1220 /* Set the bad_vaddr register with base address used in the instruction */
1221 bad_vaddr_context.type = eContextInvalid;
1222 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64,
1225 if (nonvolatile_reg_p(src)) {
1226 RegisterValue data_src;
1227 RegisterInfo reg_info_src;
1229 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src,
1234 context.type = eContextRegisterLoad;
1236 return WriteRegister(context, ®_info_src, data_src);
1242 bool EmulateInstructionMIPS64::Emulate_LUI(llvm::MCInst &insn) {
1243 // LUI rt, immediate
1244 // GPR[rt] <- sign_extend(immediate << 16)
1246 const uint32_t imm32 = insn.getOperand(1).getImm() << 16;
1247 int64_t imm = SignedBits(imm32, 31, 0);
1251 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1252 context.SetImmediateSigned(imm);
1253 context.type = eContextImmediate;
1255 return WriteRegisterUnsigned(context, eRegisterKindDWARF,
1256 dwarf_zero_mips64 + rt, imm);
1259 bool EmulateInstructionMIPS64::Emulate_DSUBU_DADDU(llvm::MCInst &insn) {
1260 // DSUBU sp, <src>, <rt>
1261 // DADDU sp, <src>, <rt>
1262 // DADDU dst, sp, <rt>
1264 bool success = false;
1266 uint8_t src, dst, rt;
1267 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1269 dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1270 src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1272 /* Check if sp is destination register */
1273 if (dst == dwarf_sp_mips64) {
1274 rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1276 /* read <src> register */
1277 uint64_t src_opd_val = ReadRegisterUnsigned(
1278 eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
1282 /* read <rt > register */
1283 uint64_t rt_opd_val = ReadRegisterUnsigned(
1284 eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
1288 if (!strcasecmp(op_name, "DSUBU") || !strcasecmp(op_name, "SUBU"))
1289 result = src_opd_val - rt_opd_val;
1291 result = src_opd_val + rt_opd_val;
1294 RegisterInfo reg_info_sp;
1295 if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp))
1296 context.SetRegisterPlusOffset(reg_info_sp, rt_opd_val);
1298 /* We are allocating bytes on stack */
1299 context.type = eContextAdjustStackPointer;
1301 WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips64, result);
1304 } else if (src == dwarf_sp_mips64) {
1305 rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1307 /* read <src> register */
1308 uint64_t src_opd_val = ReadRegisterUnsigned(
1309 eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
1313 /* read <rt> register */
1314 uint64_t rt_opd_val = ReadRegisterUnsigned(
1315 eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
1321 if (!strcasecmp(op_name, "DSUBU") || !strcasecmp(op_name, "SUBU"))
1322 result = src_opd_val - rt_opd_val;
1324 result = src_opd_val + rt_opd_val;
1326 context.SetImmediateSigned(result);
1327 context.type = eContextImmediate;
1329 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1330 dwarf_zero_mips64 + dst, result))
1338 Emulate below MIPS branch instructions.
1339 BEQ, BNE : Branch on condition
1340 BEQL, BNEL : Branch likely
1342 bool EmulateInstructionMIPS64::Emulate_BXX_3ops(llvm::MCInst &insn) {
1343 bool success = false;
1345 int64_t offset, pc, rs_val, rt_val, target = 0;
1346 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1348 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1349 rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1350 offset = insn.getOperand(2).getImm();
1352 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1356 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1357 dwarf_zero_mips64 + rs, 0, &success);
1361 rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1362 dwarf_zero_mips64 + rt, 0, &success);
1366 if (!strcasecmp(op_name, "BEQ") || !strcasecmp(op_name, "BEQL")
1367 || !strcasecmp(op_name, "BEQ64") ) {
1368 if (rs_val == rt_val)
1369 target = pc + offset;
1372 } else if (!strcasecmp(op_name, "BNE") || !strcasecmp(op_name, "BNEL")
1373 || !strcasecmp(op_name, "BNE64")) {
1374 if (rs_val != rt_val)
1375 target = pc + offset;
1381 context.type = eContextRelativeBranchImmediate;
1382 context.SetImmediate(offset);
1384 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1389 Emulate below MIPS Non-Compact conditional branch and link instructions.
1391 BLTZALL, BGEZALL : Branch likely
1393 bool EmulateInstructionMIPS64::Emulate_Bcond_Link(llvm::MCInst &insn) {
1394 bool success = false;
1396 int64_t offset, pc, target = 0;
1398 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1400 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1401 offset = insn.getOperand(1).getImm();
1403 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1407 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1408 dwarf_zero_mips64 + rs, 0, &success);
1412 if (!strcasecmp(op_name, "BLTZAL") || !strcasecmp(op_name, "BLTZALL")) {
1414 target = pc + offset;
1417 } else if (!strcasecmp(op_name, "BGEZAL") ||
1418 !strcasecmp(op_name, "BGEZALL")) {
1420 target = pc + offset;
1427 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1431 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1438 bool EmulateInstructionMIPS64::Emulate_BAL(llvm::MCInst &insn) {
1439 bool success = false;
1440 int64_t offset, pc, target;
1444 * offset = sign_ext (offset << 2)
1448 offset = insn.getOperand(0).getImm();
1450 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1454 target = pc + offset;
1458 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1462 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1469 bool EmulateInstructionMIPS64::Emulate_BALC(llvm::MCInst &insn) {
1470 bool success = false;
1471 int64_t offset, pc, target;
1475 * offset = sign_ext (offset << 2)
1477 * PC = PC + 4 + offset
1479 offset = insn.getOperand(0).getImm();
1481 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1485 target = pc + offset;
1489 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1493 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1501 Emulate below MIPS conditional branch and link instructions.
1502 BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches
1504 bool EmulateInstructionMIPS64::Emulate_Bcond_Link_C(llvm::MCInst &insn) {
1505 bool success = false;
1507 int64_t offset, pc, rs_val, target = 0;
1508 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1510 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1511 offset = insn.getOperand(1).getImm();
1513 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1517 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1518 dwarf_zero_mips64 + rs, 0, &success);
1522 if (!strcasecmp(op_name, "BLEZALC")) {
1524 target = pc + offset;
1527 } else if (!strcasecmp(op_name, "BGEZALC")) {
1529 target = pc + offset;
1532 } else if (!strcasecmp(op_name, "BLTZALC")) {
1534 target = pc + offset;
1537 } else if (!strcasecmp(op_name, "BGTZALC")) {
1539 target = pc + offset;
1542 } else if (!strcasecmp(op_name, "BEQZALC")) {
1544 target = pc + offset;
1547 } else if (!strcasecmp(op_name, "BNEZALC")) {
1549 target = pc + offset;
1556 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1560 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1568 Emulate below MIPS branch instructions.
1569 BLTZL, BGEZL, BGTZL, BLEZL : Branch likely
1570 BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches
1572 bool EmulateInstructionMIPS64::Emulate_BXX_2ops(llvm::MCInst &insn) {
1573 bool success = false;
1575 int64_t offset, pc, rs_val, target = 0;
1576 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1578 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1579 offset = insn.getOperand(1).getImm();
1581 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1585 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1586 dwarf_zero_mips64 + rs, 0, &success);
1590 if (!strcasecmp(op_name, "BLTZL") || !strcasecmp(op_name, "BLTZ")
1591 || !strcasecmp(op_name, "BLTZ64")) {
1593 target = pc + offset;
1596 } else if (!strcasecmp(op_name, "BGEZL") || !strcasecmp(op_name, "BGEZ")
1597 || !strcasecmp(op_name, "BGEZ64")) {
1599 target = pc + offset;
1602 } else if (!strcasecmp(op_name, "BGTZL") || !strcasecmp(op_name, "BGTZ")
1603 || !strcasecmp(op_name, "BGTZ64")) {
1605 target = pc + offset;
1608 } else if (!strcasecmp(op_name, "BLEZL") || !strcasecmp(op_name, "BLEZ")
1609 || !strcasecmp(op_name, "BLEZ64")) {
1611 target = pc + offset;
1617 context.type = eContextRelativeBranchImmediate;
1618 context.SetImmediate(offset);
1620 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1624 bool EmulateInstructionMIPS64::Emulate_BC(llvm::MCInst &insn) {
1625 bool success = false;
1626 int64_t offset, pc, target;
1630 * offset = sign_ext (offset << 2)
1631 * PC = PC + 4 + offset
1633 offset = insn.getOperand(0).getImm();
1635 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1639 target = pc + offset;
1643 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1647 static int IsAdd64bitOverflow(int64_t a, int64_t b) {
1648 int64_t r = (uint64_t)a + (uint64_t)b;
1649 return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
1653 Emulate below MIPS branch instructions.
1654 BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch
1655 instructions with no delay slot
1657 bool EmulateInstructionMIPS64::Emulate_BXX_3ops_C(llvm::MCInst &insn) {
1658 bool success = false;
1660 int64_t offset, pc, rs_val, rt_val, target = 0;
1661 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1662 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
1664 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1665 rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1666 offset = insn.getOperand(2).getImm();
1668 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1672 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1673 dwarf_zero_mips64 + rs, 0, &success);
1677 rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1678 dwarf_zero_mips64 + rt, 0, &success);
1682 if (!strcasecmp(op_name, "BEQC") || !strcasecmp(op_name, "BEQC64")) {
1683 if (rs_val == rt_val)
1684 target = pc + offset;
1687 } else if (!strcasecmp(op_name, "BNEC") || !strcasecmp(op_name, "BNEC64")) {
1688 if (rs_val != rt_val)
1689 target = pc + offset;
1692 } else if (!strcasecmp(op_name, "BLTC") || !strcasecmp(op_name, "BLTC64")) {
1693 if (rs_val < rt_val)
1694 target = pc + offset;
1697 } else if (!strcasecmp(op_name, "BGEC64") || !strcasecmp(op_name, "BGEC")) {
1698 if (rs_val >= rt_val)
1699 target = pc + offset;
1702 } else if (!strcasecmp(op_name, "BLTUC") || !strcasecmp(op_name, "BLTUC64")) {
1703 if (rs_val < rt_val)
1704 target = pc + offset;
1707 } else if (!strcasecmp(op_name, "BGEUC") || !strcasecmp(op_name, "BGEUC64")) {
1708 if ((uint32_t)rs_val >= (uint32_t)rt_val)
1709 target = pc + offset;
1712 } else if (!strcasecmp(op_name, "BOVC")) {
1713 if (IsAdd64bitOverflow(rs_val, rt_val))
1714 target = pc + offset;
1717 } else if (!strcasecmp(op_name, "BNVC")) {
1718 if (!IsAdd64bitOverflow(rs_val, rt_val))
1719 target = pc + offset;
1725 context.type = eContextRelativeBranchImmediate;
1726 context.SetImmediate(current_inst_size + offset);
1728 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1733 Emulate below MIPS branch instructions.
1734 BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches
1736 bool EmulateInstructionMIPS64::Emulate_BXX_2ops_C(llvm::MCInst &insn) {
1737 bool success = false;
1739 int64_t offset, pc, target = 0;
1741 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1742 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
1744 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1745 offset = insn.getOperand(1).getImm();
1747 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1751 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1752 dwarf_zero_mips64 + rs, 0, &success);
1756 if (!strcasecmp(op_name, "BLTZC") || !strcasecmp(op_name, "BLTZC64")) {
1758 target = pc + offset;
1761 } else if (!strcasecmp(op_name, "BLEZC") || !strcasecmp(op_name, "BLEZC64")) {
1763 target = pc + offset;
1766 } else if (!strcasecmp(op_name, "BGEZC") || !strcasecmp(op_name, "BGEZC64")) {
1768 target = pc + offset;
1771 } else if (!strcasecmp(op_name, "BGTZC") || !strcasecmp(op_name, "BGTZC64")) {
1773 target = pc + offset;
1776 } else if (!strcasecmp(op_name, "BEQZC") || !strcasecmp(op_name, "BEQZC64")) {
1778 target = pc + offset;
1781 } else if (!strcasecmp(op_name, "BNEZC") || !strcasecmp(op_name, "BNEZC64")) {
1783 target = pc + offset;
1789 context.type = eContextRelativeBranchImmediate;
1790 context.SetImmediate(current_inst_size + offset);
1792 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1796 bool EmulateInstructionMIPS64::Emulate_J(llvm::MCInst &insn) {
1797 bool success = false;
1798 uint64_t offset, pc;
1802 * offset = sign_ext (offset << 2)
1803 * PC = PC[63-28] | offset
1805 offset = insn.getOperand(0).getImm();
1807 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1811 /* This is a PC-region branch and not PC-relative */
1812 pc = (pc & 0xFFFFFFFFF0000000ULL) | offset;
1816 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1820 bool EmulateInstructionMIPS64::Emulate_JAL(llvm::MCInst &insn) {
1821 bool success = false;
1822 uint64_t offset, target, pc;
1826 * offset = sign_ext (offset << 2)
1827 * PC = PC[63-28] | offset
1829 offset = insn.getOperand(0).getImm();
1831 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1835 /* This is a PC-region branch and not PC-relative */
1836 target = (pc & 0xFFFFFFFFF0000000ULL) | offset;
1840 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1844 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1851 bool EmulateInstructionMIPS64::Emulate_JALR(llvm::MCInst &insn) {
1852 bool success = false;
1854 uint64_t pc, rs_val;
1861 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1862 rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1864 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1868 rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0,
1875 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1879 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1880 dwarf_zero_mips64 + rt, pc + 8))
1886 bool EmulateInstructionMIPS64::Emulate_JIALC(llvm::MCInst &insn) {
1887 bool success = false;
1889 int64_t target, offset, pc, rt_val;
1893 * offset = sign_ext (offset)
1894 * PC = GPR[rt] + offset
1897 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1898 offset = insn.getOperand(1).getImm();
1900 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1904 rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1905 dwarf_zero_mips64 + rt, 0, &success);
1909 target = rt_val + offset;
1913 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1917 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1924 bool EmulateInstructionMIPS64::Emulate_JIC(llvm::MCInst &insn) {
1925 bool success = false;
1927 int64_t target, offset, rt_val;
1931 * offset = sign_ext (offset)
1932 * PC = GPR[rt] + offset
1934 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1935 offset = insn.getOperand(1).getImm();
1937 rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1938 dwarf_zero_mips64 + rt, 0, &success);
1942 target = rt_val + offset;
1946 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1950 bool EmulateInstructionMIPS64::Emulate_JR(llvm::MCInst &insn) {
1951 bool success = false;
1959 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1961 rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0,
1968 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1973 Emulate Branch on FP True/False
1974 BC1F, BC1FL : Branch on FP False (L stands for branch likely)
1975 BC1T, BC1TL : Branch on FP True (L stands for branch likely)
1977 bool EmulateInstructionMIPS64::Emulate_FP_branch(llvm::MCInst &insn) {
1978 bool success = false;
1980 int64_t pc, offset, target = 0;
1981 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1985 * condition <- (FPConditionCode(cc) == 0)
1987 * offset = sign_ext (offset)
1990 cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1991 offset = insn.getOperand(1).getImm();
1993 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1998 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
2002 /* fcsr[23], fcsr[25-31] are vaild condition bits */
2003 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2005 if (!strcasecmp(op_name, "BC1F") || !strcasecmp(op_name, "BC1FL")) {
2006 if ((fcsr & (1 << cc)) == 0)
2007 target = pc + offset;
2010 } else if (!strcasecmp(op_name, "BC1T") || !strcasecmp(op_name, "BC1TL")) {
2011 if ((fcsr & (1 << cc)) != 0)
2012 target = pc + offset;
2019 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2023 bool EmulateInstructionMIPS64::Emulate_BC1EQZ(llvm::MCInst &insn) {
2024 bool success = false;
2027 int64_t target, pc, offset;
2031 * condition <- (FPR[ft].bit0 == 0)
2033 * offset = sign_ext (offset)
2034 * PC = PC + 4 + offset
2036 ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2037 offset = insn.getOperand(1).getImm();
2039 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2043 ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0,
2048 if ((ft_val & 1) == 0)
2049 target = pc + 4 + offset;
2055 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2059 bool EmulateInstructionMIPS64::Emulate_BC1NEZ(llvm::MCInst &insn) {
2060 bool success = false;
2063 int64_t target, pc, offset;
2067 * condition <- (FPR[ft].bit0 != 0)
2069 * offset = sign_ext (offset)
2070 * PC = PC + 4 + offset
2072 ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2073 offset = insn.getOperand(1).getImm();
2075 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2079 ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0,
2084 if ((ft_val & 1) != 0)
2085 target = pc + 4 + offset;
2091 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2096 Emulate MIPS-3D Branch instructions
2097 BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes
2099 BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes
2102 bool EmulateInstructionMIPS64::Emulate_3D_branch(llvm::MCInst &insn) {
2103 bool success = false;
2105 int64_t pc, offset, target = 0;
2106 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
2108 cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2109 offset = insn.getOperand(1).getImm();
2111 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2115 fcsr = (uint32_t)ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips64,
2120 /* fcsr[23], fcsr[25-31] are vaild condition bits */
2121 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2123 if (!strcasecmp(op_name, "BC1ANY2F")) {
2124 /* if any one bit is 0 */
2125 if (((fcsr >> cc) & 3) != 3)
2126 target = pc + offset;
2129 } else if (!strcasecmp(op_name, "BC1ANY2T")) {
2130 /* if any one bit is 1 */
2131 if (((fcsr >> cc) & 3) != 0)
2132 target = pc + offset;
2135 } else if (!strcasecmp(op_name, "BC1ANY4F")) {
2136 /* if any one bit is 0 */
2137 if (((fcsr >> cc) & 0xf) != 0xf)
2138 target = pc + offset;
2141 } else if (!strcasecmp(op_name, "BC1ANY4T")) {
2142 /* if any one bit is 1 */
2143 if (((fcsr >> cc) & 0xf) != 0)
2144 target = pc + offset;
2151 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2155 bool EmulateInstructionMIPS64::Emulate_BNZB(llvm::MCInst &insn) {
2156 return Emulate_MSA_Branch_DF(insn, 1, true);
2159 bool EmulateInstructionMIPS64::Emulate_BNZH(llvm::MCInst &insn) {
2160 return Emulate_MSA_Branch_DF(insn, 2, true);
2163 bool EmulateInstructionMIPS64::Emulate_BNZW(llvm::MCInst &insn) {
2164 return Emulate_MSA_Branch_DF(insn, 4, true);
2167 bool EmulateInstructionMIPS64::Emulate_BNZD(llvm::MCInst &insn) {
2168 return Emulate_MSA_Branch_DF(insn, 8, true);
2171 bool EmulateInstructionMIPS64::Emulate_BZB(llvm::MCInst &insn) {
2172 return Emulate_MSA_Branch_DF(insn, 1, false);
2175 bool EmulateInstructionMIPS64::Emulate_BZH(llvm::MCInst &insn) {
2176 return Emulate_MSA_Branch_DF(insn, 2, false);
2179 bool EmulateInstructionMIPS64::Emulate_BZW(llvm::MCInst &insn) {
2180 return Emulate_MSA_Branch_DF(insn, 4, false);
2183 bool EmulateInstructionMIPS64::Emulate_BZD(llvm::MCInst &insn) {
2184 return Emulate_MSA_Branch_DF(insn, 8, false);
2187 bool EmulateInstructionMIPS64::Emulate_MSA_Branch_DF(llvm::MCInst &insn,
2188 int element_byte_size,
2190 bool success = false, branch_hit = true;
2192 RegisterValue reg_value;
2193 const uint8_t *ptr = nullptr;
2195 uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2196 int64_t offset = insn.getOperand(1).getImm();
2199 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2203 if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value))
2204 ptr = (const uint8_t *)reg_value.GetBytes();
2208 for (int i = 0; i < 16 / element_byte_size; i++) {
2209 switch (element_byte_size) {
2211 if ((*ptr == 0 && bnz) || (*ptr != 0 && !bnz))
2215 if ((*(const uint16_t *)ptr == 0 && bnz) ||
2216 (*(const uint16_t *)ptr != 0 && !bnz))
2220 if ((*(const uint32_t *)ptr == 0 && bnz) ||
2221 (*(const uint32_t *)ptr != 0 && !bnz))
2225 if ((*(const uint64_t *)ptr == 0 && bnz) ||
2226 (*(const uint64_t *)ptr != 0 && !bnz))
2232 ptr = ptr + element_byte_size;
2236 target = pc + offset;
2241 context.type = eContextRelativeBranchImmediate;
2243 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2247 bool EmulateInstructionMIPS64::Emulate_BNZV(llvm::MCInst &insn) {
2248 return Emulate_MSA_Branch_V(insn, true);
2251 bool EmulateInstructionMIPS64::Emulate_BZV(llvm::MCInst &insn) {
2252 return Emulate_MSA_Branch_V(insn, false);
2255 bool EmulateInstructionMIPS64::Emulate_MSA_Branch_V(llvm::MCInst &insn,
2257 bool success = false;
2259 llvm::APInt wr_val = llvm::APInt::getNullValue(128);
2260 llvm::APInt fail_value = llvm::APInt::getMaxValue(128);
2261 llvm::APInt zero_value = llvm::APInt::getNullValue(128);
2262 RegisterValue reg_value;
2264 uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2265 int64_t offset = insn.getOperand(1).getImm();
2268 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2272 if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value))
2273 wr_val = reg_value.GetAsUInt128(fail_value);
2277 if ((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) ||
2278 (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz))
2279 target = pc + offset;
2284 context.type = eContextRelativeBranchImmediate;
2286 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2290 bool EmulateInstructionMIPS64::Emulate_LDST_Imm(llvm::MCInst &insn) {
2291 bool success = false;
2293 int64_t imm, address;
2294 Context bad_vaddr_context;
2296 uint32_t num_operands = insn.getNumOperands();
2298 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
2299 imm = insn.getOperand(num_operands - 1).getImm();
2301 RegisterInfo reg_info_base;
2302 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base,
2306 /* read base register */
2307 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0,
2312 /* destination address */
2313 address = address + imm;
2315 /* Set the bad_vaddr register with base address used in the instruction */
2316 bad_vaddr_context.type = eContextInvalid;
2317 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
2323 bool EmulateInstructionMIPS64::Emulate_LDST_Reg(llvm::MCInst &insn) {
2324 bool success = false;
2325 uint32_t base, index;
2326 int64_t address, index_address;
2327 Context bad_vaddr_context;
2329 uint32_t num_operands = insn.getNumOperands();
2331 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
2333 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 1).getReg());
2335 RegisterInfo reg_info_base, reg_info_index;
2336 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base,
2340 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + index,
2344 /* read base register */
2345 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0,
2350 /* read index register */
2351 index_address = ReadRegisterUnsigned(eRegisterKindDWARF,
2352 dwarf_zero_mips + index, 0, &success);
2356 /* destination address */
2357 address = address + index_address;
2359 /* Set the bad_vaddr register with base address used in the instruction */
2360 bad_vaddr_context.type = eContextInvalid;
2361 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,