1 //===-- EmulateInstructionMIPS64.cpp --------------------------------------===//
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"
14 #include "lldb/Core/Address.h"
15 #include "lldb/Core/Opcode.h"
16 #include "lldb/Core/PluginManager.h"
17 #include "lldb/Host/PosixApi.h"
18 #include "lldb/Symbol/UnwindPlan.h"
19 #include "lldb/Utility/ArchSpec.h"
20 #include "lldb/Utility/ConstString.h"
21 #include "lldb/Utility/DataExtractor.h"
22 #include "lldb/Utility/RegisterValue.h"
23 #include "lldb/Utility/Stream.h"
24 #include "llvm-c/Disassembler.h"
25 #include "llvm/MC/MCAsmInfo.h"
26 #include "llvm/MC/MCContext.h"
27 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
28 #include "llvm/MC/MCInst.h"
29 #include "llvm/MC/MCInstrInfo.h"
30 #include "llvm/MC/MCRegisterInfo.h"
31 #include "llvm/MC/MCSubtargetInfo.h"
32 #include "llvm/MC/MCTargetOptions.h"
33 #include "llvm/MC/TargetRegistry.h"
34 #include "llvm/Support/TargetSelect.h"
36 #include "llvm/ADT/STLExtras.h"
38 #include "Plugins/Process/Utility/InstructionUtils.h"
39 #include "Plugins/Process/Utility/RegisterContext_mips.h"
42 using namespace lldb_private
;
44 LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionMIPS64
, InstructionMIPS64
)
46 #define UInt(x) ((uint64_t)x)
47 #define integer int64_t
50 // EmulateInstructionMIPS64 implementation
55 void LLVMInitializeMipsTargetInfo();
56 void LLVMInitializeMipsTarget();
57 void LLVMInitializeMipsAsmPrinter();
58 void LLVMInitializeMipsTargetMC();
59 void LLVMInitializeMipsDisassembler();
63 EmulateInstructionMIPS64::EmulateInstructionMIPS64(
64 const lldb_private::ArchSpec
&arch
)
65 : EmulateInstruction(arch
) {
66 /* Create instance of llvm::MCDisassembler */
68 llvm::Triple triple
= arch
.GetTriple();
69 const llvm::Target
*target
=
70 llvm::TargetRegistry::lookupTarget(triple
.getTriple(), Status
);
73 * If we fail to get the target then we haven't registered it. The
74 * SystemInitializerCommon
75 * does not initialize targets, MCs and disassemblers. However we need the
77 * to decode the instructions so that the decoding complexity stays with LLVM.
78 * Initialize the MIPS targets and disassemblers.
82 LLVMInitializeMipsTargetInfo();
83 LLVMInitializeMipsTarget();
84 LLVMInitializeMipsAsmPrinter();
85 LLVMInitializeMipsTargetMC();
86 LLVMInitializeMipsDisassembler();
87 target
= llvm::TargetRegistry::lookupTarget(triple
.getTriple(), Status
);
95 switch (arch
.GetCore()) {
96 case ArchSpec::eCore_mips32
:
97 case ArchSpec::eCore_mips32el
:
100 case ArchSpec::eCore_mips32r2
:
101 case ArchSpec::eCore_mips32r2el
:
104 case ArchSpec::eCore_mips32r3
:
105 case ArchSpec::eCore_mips32r3el
:
108 case ArchSpec::eCore_mips32r5
:
109 case ArchSpec::eCore_mips32r5el
:
112 case ArchSpec::eCore_mips32r6
:
113 case ArchSpec::eCore_mips32r6el
:
116 case ArchSpec::eCore_mips64
:
117 case ArchSpec::eCore_mips64el
:
120 case ArchSpec::eCore_mips64r2
:
121 case ArchSpec::eCore_mips64r2el
:
124 case ArchSpec::eCore_mips64r3
:
125 case ArchSpec::eCore_mips64r3el
:
128 case ArchSpec::eCore_mips64r5
:
129 case ArchSpec::eCore_mips64r5el
:
132 case ArchSpec::eCore_mips64r6
:
133 case ArchSpec::eCore_mips64r6el
:
141 std::string features
;
142 uint32_t arch_flags
= arch
.GetFlags();
143 if (arch_flags
& ArchSpec::eMIPSAse_msa
)
145 if (arch_flags
& ArchSpec::eMIPSAse_dsp
)
147 if (arch_flags
& ArchSpec::eMIPSAse_dspr2
)
148 features
+= "+dspr2,";
149 if (arch_flags
& ArchSpec::eMIPSAse_mips16
)
150 features
+= "+mips16,";
151 if (arch_flags
& ArchSpec::eMIPSAse_micromips
)
152 features
+= "+micromips,";
154 m_reg_info
.reset(target
->createMCRegInfo(triple
.getTriple()));
155 assert(m_reg_info
.get());
157 m_insn_info
.reset(target
->createMCInstrInfo());
158 assert(m_insn_info
.get());
160 llvm::MCTargetOptions MCOptions
;
162 target
->createMCAsmInfo(*m_reg_info
, triple
.getTriple(), MCOptions
));
163 m_subtype_info
.reset(
164 target
->createMCSubtargetInfo(triple
.getTriple(), cpu
, features
));
165 assert(m_asm_info
.get() && m_subtype_info
.get());
167 m_context
= std::make_unique
<llvm::MCContext
>(
168 triple
, m_asm_info
.get(), m_reg_info
.get(), m_subtype_info
.get());
169 assert(m_context
.get());
171 m_disasm
.reset(target
->createMCDisassembler(*m_subtype_info
, *m_context
));
172 assert(m_disasm
.get());
175 void EmulateInstructionMIPS64::Initialize() {
176 PluginManager::RegisterPlugin(GetPluginNameStatic(),
177 GetPluginDescriptionStatic(), CreateInstance
);
180 void EmulateInstructionMIPS64::Terminate() {
181 PluginManager::UnregisterPlugin(CreateInstance
);
184 llvm::StringRef
EmulateInstructionMIPS64::GetPluginDescriptionStatic() {
185 return "Emulate instructions for the MIPS64 architecture.";
189 EmulateInstructionMIPS64::CreateInstance(const ArchSpec
&arch
,
190 InstructionType inst_type
) {
191 if (EmulateInstructionMIPS64::SupportsEmulatingInstructionsOfTypeStatic(
193 if (arch
.GetTriple().getArch() == llvm::Triple::mips64
||
194 arch
.GetTriple().getArch() == llvm::Triple::mips64el
) {
195 return new EmulateInstructionMIPS64(arch
);
202 bool EmulateInstructionMIPS64::SetTargetTriple(const ArchSpec
&arch
) {
203 return arch
.GetTriple().getArch() == llvm::Triple::mips64
||
204 arch
.GetTriple().getArch() == llvm::Triple::mips64el
;
207 const char *EmulateInstructionMIPS64::GetRegisterName(unsigned reg_num
,
208 bool alternate_name
) {
209 if (alternate_name
) {
211 case dwarf_sp_mips64
:
213 case dwarf_r30_mips64
:
215 case dwarf_ra_mips64
:
217 case dwarf_f0_mips64
:
219 case dwarf_f1_mips64
:
221 case dwarf_f2_mips64
:
223 case dwarf_f3_mips64
:
225 case dwarf_f4_mips64
:
227 case dwarf_f5_mips64
:
229 case dwarf_f6_mips64
:
231 case dwarf_f7_mips64
:
233 case dwarf_f8_mips64
:
235 case dwarf_f9_mips64
:
237 case dwarf_f10_mips64
:
239 case dwarf_f11_mips64
:
241 case dwarf_f12_mips64
:
243 case dwarf_f13_mips64
:
245 case dwarf_f14_mips64
:
247 case dwarf_f15_mips64
:
249 case dwarf_f16_mips64
:
251 case dwarf_f17_mips64
:
253 case dwarf_f18_mips64
:
255 case dwarf_f19_mips64
:
257 case dwarf_f20_mips64
:
259 case dwarf_f21_mips64
:
261 case dwarf_f22_mips64
:
263 case dwarf_f23_mips64
:
265 case dwarf_f24_mips64
:
267 case dwarf_f25_mips64
:
269 case dwarf_f26_mips64
:
271 case dwarf_f27_mips64
:
273 case dwarf_f28_mips64
:
275 case dwarf_f29_mips64
:
277 case dwarf_f30_mips64
:
279 case dwarf_f31_mips64
:
281 case dwarf_w0_mips64
:
283 case dwarf_w1_mips64
:
285 case dwarf_w2_mips64
:
287 case dwarf_w3_mips64
:
289 case dwarf_w4_mips64
:
291 case dwarf_w5_mips64
:
293 case dwarf_w6_mips64
:
295 case dwarf_w7_mips64
:
297 case dwarf_w8_mips64
:
299 case dwarf_w9_mips64
:
301 case dwarf_w10_mips64
:
303 case dwarf_w11_mips64
:
305 case dwarf_w12_mips64
:
307 case dwarf_w13_mips64
:
309 case dwarf_w14_mips64
:
311 case dwarf_w15_mips64
:
313 case dwarf_w16_mips64
:
315 case dwarf_w17_mips64
:
317 case dwarf_w18_mips64
:
319 case dwarf_w19_mips64
:
321 case dwarf_w20_mips64
:
323 case dwarf_w21_mips64
:
325 case dwarf_w22_mips64
:
327 case dwarf_w23_mips64
:
329 case dwarf_w24_mips64
:
331 case dwarf_w25_mips64
:
333 case dwarf_w26_mips64
:
335 case dwarf_w27_mips64
:
337 case dwarf_w28_mips64
:
339 case dwarf_w29_mips64
:
341 case dwarf_w30_mips64
:
343 case dwarf_w31_mips64
:
345 case dwarf_mir_mips64
:
347 case dwarf_mcsr_mips64
:
349 case dwarf_config5_mips64
:
358 case dwarf_zero_mips64
:
360 case dwarf_r1_mips64
:
362 case dwarf_r2_mips64
:
364 case dwarf_r3_mips64
:
366 case dwarf_r4_mips64
:
368 case dwarf_r5_mips64
:
370 case dwarf_r6_mips64
:
372 case dwarf_r7_mips64
:
374 case dwarf_r8_mips64
:
376 case dwarf_r9_mips64
:
378 case dwarf_r10_mips64
:
380 case dwarf_r11_mips64
:
382 case dwarf_r12_mips64
:
384 case dwarf_r13_mips64
:
386 case dwarf_r14_mips64
:
388 case dwarf_r15_mips64
:
390 case dwarf_r16_mips64
:
392 case dwarf_r17_mips64
:
394 case dwarf_r18_mips64
:
396 case dwarf_r19_mips64
:
398 case dwarf_r20_mips64
:
400 case dwarf_r21_mips64
:
402 case dwarf_r22_mips64
:
404 case dwarf_r23_mips64
:
406 case dwarf_r24_mips64
:
408 case dwarf_r25_mips64
:
410 case dwarf_r26_mips64
:
412 case dwarf_r27_mips64
:
414 case dwarf_gp_mips64
:
416 case dwarf_sp_mips64
:
418 case dwarf_r30_mips64
:
420 case dwarf_ra_mips64
:
422 case dwarf_sr_mips64
:
424 case dwarf_lo_mips64
:
426 case dwarf_hi_mips64
:
428 case dwarf_bad_mips64
:
430 case dwarf_cause_mips64
:
432 case dwarf_pc_mips64
:
434 case dwarf_f0_mips64
:
436 case dwarf_f1_mips64
:
438 case dwarf_f2_mips64
:
440 case dwarf_f3_mips64
:
442 case dwarf_f4_mips64
:
444 case dwarf_f5_mips64
:
446 case dwarf_f6_mips64
:
448 case dwarf_f7_mips64
:
450 case dwarf_f8_mips64
:
452 case dwarf_f9_mips64
:
454 case dwarf_f10_mips64
:
456 case dwarf_f11_mips64
:
458 case dwarf_f12_mips64
:
460 case dwarf_f13_mips64
:
462 case dwarf_f14_mips64
:
464 case dwarf_f15_mips64
:
466 case dwarf_f16_mips64
:
468 case dwarf_f17_mips64
:
470 case dwarf_f18_mips64
:
472 case dwarf_f19_mips64
:
474 case dwarf_f20_mips64
:
476 case dwarf_f21_mips64
:
478 case dwarf_f22_mips64
:
480 case dwarf_f23_mips64
:
482 case dwarf_f24_mips64
:
484 case dwarf_f25_mips64
:
486 case dwarf_f26_mips64
:
488 case dwarf_f27_mips64
:
490 case dwarf_f28_mips64
:
492 case dwarf_f29_mips64
:
494 case dwarf_f30_mips64
:
496 case dwarf_f31_mips64
:
498 case dwarf_fcsr_mips64
:
500 case dwarf_fir_mips64
:
502 case dwarf_w0_mips64
:
504 case dwarf_w1_mips64
:
506 case dwarf_w2_mips64
:
508 case dwarf_w3_mips64
:
510 case dwarf_w4_mips64
:
512 case dwarf_w5_mips64
:
514 case dwarf_w6_mips64
:
516 case dwarf_w7_mips64
:
518 case dwarf_w8_mips64
:
520 case dwarf_w9_mips64
:
522 case dwarf_w10_mips64
:
524 case dwarf_w11_mips64
:
526 case dwarf_w12_mips64
:
528 case dwarf_w13_mips64
:
530 case dwarf_w14_mips64
:
532 case dwarf_w15_mips64
:
534 case dwarf_w16_mips64
:
536 case dwarf_w17_mips64
:
538 case dwarf_w18_mips64
:
540 case dwarf_w19_mips64
:
542 case dwarf_w20_mips64
:
544 case dwarf_w21_mips64
:
546 case dwarf_w22_mips64
:
548 case dwarf_w23_mips64
:
550 case dwarf_w24_mips64
:
552 case dwarf_w25_mips64
:
554 case dwarf_w26_mips64
:
556 case dwarf_w27_mips64
:
558 case dwarf_w28_mips64
:
560 case dwarf_w29_mips64
:
562 case dwarf_w30_mips64
:
564 case dwarf_w31_mips64
:
566 case dwarf_mcsr_mips64
:
568 case dwarf_mir_mips64
:
570 case dwarf_config5_mips64
:
576 std::optional
<RegisterInfo
>
577 EmulateInstructionMIPS64::GetRegisterInfo(RegisterKind reg_kind
,
579 if (reg_kind
== eRegisterKindGeneric
) {
581 case LLDB_REGNUM_GENERIC_PC
:
582 reg_kind
= eRegisterKindDWARF
;
583 reg_num
= dwarf_pc_mips64
;
585 case LLDB_REGNUM_GENERIC_SP
:
586 reg_kind
= eRegisterKindDWARF
;
587 reg_num
= dwarf_sp_mips64
;
589 case LLDB_REGNUM_GENERIC_FP
:
590 reg_kind
= eRegisterKindDWARF
;
591 reg_num
= dwarf_r30_mips64
;
593 case LLDB_REGNUM_GENERIC_RA
:
594 reg_kind
= eRegisterKindDWARF
;
595 reg_num
= dwarf_ra_mips64
;
597 case LLDB_REGNUM_GENERIC_FLAGS
:
598 reg_kind
= eRegisterKindDWARF
;
599 reg_num
= dwarf_sr_mips64
;
606 if (reg_kind
== eRegisterKindDWARF
) {
607 RegisterInfo reg_info
;
608 ::memset(®_info
, 0, sizeof(RegisterInfo
));
609 ::memset(reg_info
.kinds
, LLDB_INVALID_REGNUM
, sizeof(reg_info
.kinds
));
611 if (reg_num
== dwarf_sr_mips64
|| reg_num
== dwarf_fcsr_mips64
||
612 reg_num
== dwarf_fir_mips64
|| reg_num
== dwarf_mcsr_mips64
||
613 reg_num
== dwarf_mir_mips64
|| reg_num
== dwarf_config5_mips64
) {
614 reg_info
.byte_size
= 4;
615 reg_info
.format
= eFormatHex
;
616 reg_info
.encoding
= eEncodingUint
;
617 } else if ((int)reg_num
>= dwarf_zero_mips64
&&
618 (int)reg_num
<= dwarf_f31_mips64
) {
619 reg_info
.byte_size
= 8;
620 reg_info
.format
= eFormatHex
;
621 reg_info
.encoding
= eEncodingUint
;
622 } else if ((int)reg_num
>= dwarf_w0_mips64
&&
623 (int)reg_num
<= dwarf_w31_mips64
) {
624 reg_info
.byte_size
= 16;
625 reg_info
.format
= eFormatVectorOfUInt8
;
626 reg_info
.encoding
= eEncodingVector
;
631 reg_info
.name
= GetRegisterName(reg_num
, false);
632 reg_info
.alt_name
= GetRegisterName(reg_num
, true);
633 reg_info
.kinds
[eRegisterKindDWARF
] = reg_num
;
636 case dwarf_r30_mips64
:
637 reg_info
.kinds
[eRegisterKindGeneric
] = LLDB_REGNUM_GENERIC_FP
;
639 case dwarf_ra_mips64
:
640 reg_info
.kinds
[eRegisterKindGeneric
] = LLDB_REGNUM_GENERIC_RA
;
642 case dwarf_sp_mips64
:
643 reg_info
.kinds
[eRegisterKindGeneric
] = LLDB_REGNUM_GENERIC_SP
;
645 case dwarf_pc_mips64
:
646 reg_info
.kinds
[eRegisterKindGeneric
] = LLDB_REGNUM_GENERIC_PC
;
648 case dwarf_sr_mips64
:
649 reg_info
.kinds
[eRegisterKindGeneric
] = LLDB_REGNUM_GENERIC_FLAGS
;
659 EmulateInstructionMIPS64::MipsOpcode
*
660 EmulateInstructionMIPS64::GetOpcodeForInstruction(llvm::StringRef op_name
) {
661 static EmulateInstructionMIPS64::MipsOpcode g_opcodes
[] = {
662 // Prologue/Epilogue instructions
663 {"DADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu
,
664 "DADDIU rt, rs, immediate"},
665 {"ADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu
,
666 "ADDIU rt, rs, immediate"},
667 {"SD", &EmulateInstructionMIPS64::Emulate_SD
, "SD rt, offset(rs)"},
668 {"LD", &EmulateInstructionMIPS64::Emulate_LD
, "LD rt, offset(base)"},
669 {"DSUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU
,
671 {"SUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU
,
673 {"DADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU
,
675 {"ADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU
,
677 {"LUI", &EmulateInstructionMIPS64::Emulate_LUI
, "LUI rt, immediate"},
679 // Load/Store instructions
680 /* Following list of emulated instructions are required by implementation
681 of hardware watchpoint
682 for MIPS in lldb. As we just need the address accessed by instructions,
684 all these instructions in 2 functions depending on their addressing
687 {"LB", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
688 "LB rt, offset(base)"},
689 {"LBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
690 "LBE rt, offset(base)"},
691 {"LBU", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
692 "LBU rt, offset(base)"},
693 {"LBUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
694 "LBUE rt, offset(base)"},
695 {"LDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
696 "LDC1 ft, offset(base)"},
697 {"LDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
698 "LDL rt, offset(base)"},
699 {"LDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
700 "LDR rt, offset(base)"},
701 {"LLD", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
702 "LLD rt, offset(base)"},
703 {"LDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
704 "LDC2 rt, offset(base)"},
705 {"LDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg
,
706 "LDXC1 fd, index (base)"},
707 {"LH", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
708 "LH rt, offset(base)"},
709 {"LHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
710 "LHE rt, offset(base)"},
711 {"LHU", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
712 "LHU rt, offset(base)"},
713 {"LHUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
714 "LHUE rt, offset(base)"},
715 {"LL", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
716 "LL rt, offset(base)"},
717 {"LLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
718 "LLE rt, offset(base)"},
719 {"LUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg
,
720 "LUXC1 fd, index (base)"},
721 {"LW", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
722 "LW rt, offset(rs)"},
723 {"LWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
724 "LWC1 ft, offset(base)"},
725 {"LWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
726 "LWC2 rt, offset(base)"},
727 {"LWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
728 "LWE rt, offset(base)"},
729 {"LWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
730 "LWL rt, offset(base)"},
731 {"LWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
732 "LWLE rt, offset(base)"},
733 {"LWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
734 "LWR rt, offset(base)"},
735 {"LWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
736 "LWRE rt, offset(base)"},
737 {"LWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg
,
738 "LWXC1 fd, index (base)"},
740 {"SB", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
741 "SB rt, offset(base)"},
742 {"SBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
743 "SBE rt, offset(base)"},
744 {"SC", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
745 "SC rt, offset(base)"},
746 {"SCE", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
747 "SCE rt, offset(base)"},
748 {"SCD", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
749 "SCD rt, offset(base)"},
750 {"SDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
751 "SDL rt, offset(base)"},
752 {"SDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
753 "SDR rt, offset(base)"},
754 {"SDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
755 "SDC1 ft, offset(base)"},
756 {"SDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
757 "SDC2 rt, offset(base)"},
758 {"SDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg
,
759 "SDXC1 fs, index (base)"},
760 {"SH", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
761 "SH rt, offset(base)"},
762 {"SHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
763 "SHE rt, offset(base)"},
764 {"SUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg
,
765 "SUXC1 fs, index (base)"},
766 {"SW", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
767 "SW rt, offset(rs)"},
768 {"SWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
769 "SWC1 ft, offset(base)"},
770 {"SWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
771 "SWC2 rt, offset(base)"},
772 {"SWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
773 "SWE rt, offset(base)"},
774 {"SWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
775 "SWL rt, offset(base)"},
776 {"SWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
777 "SWLE rt, offset(base)"},
778 {"SWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
779 "SWR rt, offset(base)"},
780 {"SWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm
,
781 "SWRE rt, offset(base)"},
782 {"SWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg
,
783 "SWXC1 fs, index (base)"},
785 // Branch instructions
786 {"BEQ", &EmulateInstructionMIPS64::Emulate_BXX_3ops
, "BEQ rs,rt,offset"},
787 {"BEQ64", &EmulateInstructionMIPS64::Emulate_BXX_3ops
, "BEQ rs,rt,offset"},
788 {"BNE", &EmulateInstructionMIPS64::Emulate_BXX_3ops
, "BNE rs,rt,offset"},
789 {"BNE64", &EmulateInstructionMIPS64::Emulate_BXX_3ops
, "BNE rs,rt,offset"},
790 {"BEQL", &EmulateInstructionMIPS64::Emulate_BXX_3ops
,
791 "BEQL rs,rt,offset"},
792 {"BNEL", &EmulateInstructionMIPS64::Emulate_BXX_3ops
,
793 "BNEL rs,rt,offset"},
794 {"BGEZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link
,
795 "BGEZALL rt,offset"},
796 {"BAL", &EmulateInstructionMIPS64::Emulate_BAL
, "BAL offset"},
797 {"BGEZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link
,
799 {"BALC", &EmulateInstructionMIPS64::Emulate_BALC
, "BALC offset"},
800 {"BC", &EmulateInstructionMIPS64::Emulate_BC
, "BC offset"},
801 {"BGEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops
, "BGEZ rs,offset"},
802 {"BGEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops
, "BGEZ rs,offset"},
803 {"BLEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C
,
804 "BLEZALC rs,offset"},
805 {"BGEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C
,
806 "BGEZALC rs,offset"},
807 {"BLTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C
,
808 "BLTZALC rs,offset"},
809 {"BGTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C
,
810 "BGTZALC rs,offset"},
811 {"BEQZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C
,
812 "BEQZALC rs,offset"},
813 {"BNEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C
,
814 "BNEZALC rs,offset"},
815 {"BEQC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C
,
816 "BEQC rs,rt,offset"},
817 {"BEQC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C
,
818 "BEQC rs,rt,offset"},
819 {"BNEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C
,
820 "BNEC rs,rt,offset"},
821 {"BNEC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C
,
822 "BNEC rs,rt,offset"},
823 {"BLTC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C
,
824 "BLTC rs,rt,offset"},
825 {"BLTC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C
,
826 "BLTC rs,rt,offset"},
827 {"BGEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C
,
828 "BGEC rs,rt,offset"},
829 {"BGEC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C
,
830 "BGEC rs,rt,offset"},
831 {"BLTUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C
,
832 "BLTUC rs,rt,offset"},
833 {"BLTUC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C
,
834 "BLTUC rs,rt,offset"},
835 {"BGEUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C
,
836 "BGEUC rs,rt,offset"},
837 {"BGEUC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C
,
838 "BGEUC rs,rt,offset"},
839 {"BLTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C
,
841 {"BLTZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C
,
843 {"BLEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C
,
845 {"BLEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C
,
847 {"BGEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C
,
849 {"BGEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C
,
851 {"BGTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C
,
853 {"BGTZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C
,
855 {"BEQZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C
,
857 {"BEQZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C
,
859 {"BNEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C
,
861 {"BNEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C
,
863 {"BGEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops
, "BGEZL rt,offset"},
864 {"BGTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops
, "BGTZ rt,offset"},
865 {"BGTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops
, "BGTZ rt,offset"},
866 {"BGTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops
, "BGTZL rt,offset"},
867 {"BLEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops
, "BLEZ rt,offset"},
868 {"BLEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops
, "BLEZ rt,offset"},
869 {"BLEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops
, "BLEZL rt,offset"},
870 {"BLTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops
, "BLTZ rt,offset"},
871 {"BLTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops
, "BLTZ rt,offset"},
872 {"BLTZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link
,
874 {"BLTZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link
,
875 "BLTZALL rt,offset"},
876 {"BLTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops
, "BLTZL rt,offset"},
877 {"BOVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C
,
878 "BOVC rs,rt,offset"},
879 {"BNVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C
,
880 "BNVC rs,rt,offset"},
881 {"J", &EmulateInstructionMIPS64::Emulate_J
, "J target"},
882 {"JAL", &EmulateInstructionMIPS64::Emulate_JAL
, "JAL target"},
883 {"JALX", &EmulateInstructionMIPS64::Emulate_JAL
, "JALX target"},
884 {"JALR", &EmulateInstructionMIPS64::Emulate_JALR
, "JALR target"},
885 {"JALR64", &EmulateInstructionMIPS64::Emulate_JALR
, "JALR target"},
886 {"JALR_HB", &EmulateInstructionMIPS64::Emulate_JALR
, "JALR.HB target"},
887 {"JIALC", &EmulateInstructionMIPS64::Emulate_JIALC
, "JIALC rt,offset"},
888 {"JIALC64", &EmulateInstructionMIPS64::Emulate_JIALC
, "JIALC rt,offset"},
889 {"JIC", &EmulateInstructionMIPS64::Emulate_JIC
, "JIC rt,offset"},
890 {"JIC64", &EmulateInstructionMIPS64::Emulate_JIC
, "JIC rt,offset"},
891 {"JR", &EmulateInstructionMIPS64::Emulate_JR
, "JR target"},
892 {"JR64", &EmulateInstructionMIPS64::Emulate_JR
, "JR target"},
893 {"JR_HB", &EmulateInstructionMIPS64::Emulate_JR
, "JR.HB target"},
894 {"BC1F", &EmulateInstructionMIPS64::Emulate_FP_branch
, "BC1F cc, offset"},
895 {"BC1T", &EmulateInstructionMIPS64::Emulate_FP_branch
, "BC1T cc, offset"},
896 {"BC1FL", &EmulateInstructionMIPS64::Emulate_FP_branch
,
898 {"BC1TL", &EmulateInstructionMIPS64::Emulate_FP_branch
,
900 {"BC1EQZ", &EmulateInstructionMIPS64::Emulate_BC1EQZ
,
901 "BC1EQZ ft, offset"},
902 {"BC1NEZ", &EmulateInstructionMIPS64::Emulate_BC1NEZ
,
903 "BC1NEZ ft, offset"},
904 {"BC1ANY2F", &EmulateInstructionMIPS64::Emulate_3D_branch
,
905 "BC1ANY2F cc, offset"},
906 {"BC1ANY2T", &EmulateInstructionMIPS64::Emulate_3D_branch
,
907 "BC1ANY2T cc, offset"},
908 {"BC1ANY4F", &EmulateInstructionMIPS64::Emulate_3D_branch
,
909 "BC1ANY4F cc, offset"},
910 {"BC1ANY4T", &EmulateInstructionMIPS64::Emulate_3D_branch
,
911 "BC1ANY4T cc, offset"},
912 {"BNZ_B", &EmulateInstructionMIPS64::Emulate_BNZB
, "BNZ.b wt,s16"},
913 {"BNZ_H", &EmulateInstructionMIPS64::Emulate_BNZH
, "BNZ.h wt,s16"},
914 {"BNZ_W", &EmulateInstructionMIPS64::Emulate_BNZW
, "BNZ.w wt,s16"},
915 {"BNZ_D", &EmulateInstructionMIPS64::Emulate_BNZD
, "BNZ.d wt,s16"},
916 {"BZ_B", &EmulateInstructionMIPS64::Emulate_BZB
, "BZ.b wt,s16"},
917 {"BZ_H", &EmulateInstructionMIPS64::Emulate_BZH
, "BZ.h wt,s16"},
918 {"BZ_W", &EmulateInstructionMIPS64::Emulate_BZW
, "BZ.w wt,s16"},
919 {"BZ_D", &EmulateInstructionMIPS64::Emulate_BZD
, "BZ.d wt,s16"},
920 {"BNZ_V", &EmulateInstructionMIPS64::Emulate_BNZV
, "BNZ.V wt,s16"},
921 {"BZ_V", &EmulateInstructionMIPS64::Emulate_BZV
, "BZ.V wt,s16"},
924 for (MipsOpcode
&opcode
: g_opcodes
) {
925 if (op_name
.equals_insensitive(opcode
.op_name
))
931 bool EmulateInstructionMIPS64::ReadInstruction() {
932 bool success
= false;
933 m_addr
= ReadRegisterUnsigned(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_PC
,
934 LLDB_INVALID_ADDRESS
, &success
);
936 Context read_inst_context
;
937 read_inst_context
.type
= eContextReadOpcode
;
938 read_inst_context
.SetNoArgs();
939 m_opcode
.SetOpcode32(
940 ReadMemoryUnsigned(read_inst_context
, m_addr
, 4, 0, &success
),
944 m_addr
= LLDB_INVALID_ADDRESS
;
948 bool EmulateInstructionMIPS64::EvaluateInstruction(uint32_t evaluate_options
) {
949 bool success
= false;
950 llvm::MCInst mc_insn
;
954 /* Keep the complexity of the decode logic with the llvm::MCDisassembler
956 if (m_opcode
.GetData(data
)) {
957 llvm::MCDisassembler::DecodeStatus decode_status
;
958 llvm::ArrayRef
<uint8_t> raw_insn(data
.GetDataStart(), data
.GetByteSize());
959 decode_status
= m_disasm
->getInstruction(mc_insn
, insn_size
, raw_insn
,
960 m_addr
, llvm::nulls());
961 if (decode_status
!= llvm::MCDisassembler::Success
)
966 * mc_insn.getOpcode() returns decoded opcode. However to make use
967 * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc".
969 llvm::StringRef op_name
= m_insn_info
->getName(mc_insn
.getOpcode());
972 * Decoding has been done already. Just get the call-back function
973 * and emulate the instruction.
975 MipsOpcode
*opcode_data
= GetOpcodeForInstruction(op_name
);
977 if (opcode_data
== nullptr)
980 uint64_t old_pc
= 0, new_pc
= 0;
981 const bool auto_advance_pc
=
982 evaluate_options
& eEmulateInstructionOptionAutoAdvancePC
;
984 if (auto_advance_pc
) {
986 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc_mips64
, 0, &success
);
991 /* emulate instruction */
992 success
= (this->*opcode_data
->callback
)(mc_insn
);
996 if (auto_advance_pc
) {
998 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc_mips64
, 0, &success
);
1002 /* If we haven't changed the PC, change it here */
1003 if (old_pc
== new_pc
) {
1006 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc_mips64
,
1015 bool EmulateInstructionMIPS64::CreateFunctionEntryUnwind(
1016 UnwindPlan
&unwind_plan
) {
1017 unwind_plan
.Clear();
1018 unwind_plan
.SetRegisterKind(eRegisterKindDWARF
);
1020 UnwindPlan::RowSP
row(new UnwindPlan::Row
);
1021 const bool can_replace
= false;
1023 // Our previous Call Frame Address is the stack pointer
1024 row
->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips64
, 0);
1026 // Our previous PC is in the RA
1027 row
->SetRegisterLocationToRegister(dwarf_pc_mips64
, dwarf_ra_mips64
,
1030 unwind_plan
.AppendRow(row
);
1032 // All other registers are the same.
1033 unwind_plan
.SetSourceName("EmulateInstructionMIPS64");
1034 unwind_plan
.SetSourcedFromCompiler(eLazyBoolNo
);
1035 unwind_plan
.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes
);
1036 unwind_plan
.SetUnwindPlanForSignalTrap(eLazyBoolNo
);
1037 unwind_plan
.SetReturnAddressRegister(dwarf_ra_mips64
);
1042 bool EmulateInstructionMIPS64::nonvolatile_reg_p(uint64_t regnum
) {
1044 case dwarf_r16_mips64
:
1045 case dwarf_r17_mips64
:
1046 case dwarf_r18_mips64
:
1047 case dwarf_r19_mips64
:
1048 case dwarf_r20_mips64
:
1049 case dwarf_r21_mips64
:
1050 case dwarf_r22_mips64
:
1051 case dwarf_r23_mips64
:
1052 case dwarf_gp_mips64
:
1053 case dwarf_sp_mips64
:
1054 case dwarf_r30_mips64
:
1055 case dwarf_ra_mips64
:
1063 bool EmulateInstructionMIPS64::Emulate_DADDiu(llvm::MCInst
&insn
) {
1064 // DADDIU rt, rs, immediate
1065 // GPR[rt] <- GPR[rs] + sign_extend(immediate)
1068 bool success
= false;
1069 const uint32_t imm16
= insn
.getOperand(2).getImm();
1070 int64_t imm
= SignedBits(imm16
, 15, 0);
1072 dst
= m_reg_info
->getEncodingValue(insn
.getOperand(0).getReg());
1073 src
= m_reg_info
->getEncodingValue(insn
.getOperand(1).getReg());
1075 // If immediate is greater than 2^16 - 1 then clang generate LUI,
1076 // (D)ADDIU,(D)SUBU instructions in prolog. Example lui $1, 0x2 daddiu $1,
1077 // $1, -0x5920 dsubu $sp, $sp, $1 In this case, (D)ADDIU dst and src will be
1078 // same and not equal to sp
1082 /* read <src> register */
1083 const uint64_t src_opd_val
= ReadRegisterUnsigned(
1084 eRegisterKindDWARF
, dwarf_zero_mips64
+ src
, 0, &success
);
1088 /* Check if this is daddiu sp, sp, imm16 */
1089 if (dst
== dwarf_sp_mips64
) {
1091 * From the MIPS IV spec:
1093 * The term “unsigned” in the instruction name is a misnomer; this
1094 * operation is 64-bit modulo arithmetic that does not trap on overflow.
1095 * It is appropriate for arithmetic which is not signed, such as address
1096 * arithmetic, or integer arithmetic environments that ignore overflow,
1097 * such as “C” language arithmetic.
1099 * Assume 2's complement and rely on unsigned overflow here.
1101 uint64_t result
= src_opd_val
+ imm
;
1102 std::optional
<RegisterInfo
> reg_info_sp
=
1103 GetRegisterInfo(eRegisterKindDWARF
, dwarf_sp_mips64
);
1105 context
.SetRegisterPlusOffset(*reg_info_sp
, imm
);
1107 /* We are allocating bytes on stack */
1108 context
.type
= eContextAdjustStackPointer
;
1110 WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_sp_mips64
,
1116 context
.SetImmediateSigned(imm
);
1117 context
.type
= eContextImmediate
;
1119 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
,
1120 dwarf_zero_mips64
+ dst
, imm
))
1127 bool EmulateInstructionMIPS64::Emulate_SD(llvm::MCInst
&insn
) {
1129 bool success
= false;
1130 uint32_t imm16
= insn
.getOperand(2).getImm();
1131 uint64_t imm
= SignedBits(imm16
, 15, 0);
1133 Context bad_vaddr_context
;
1135 src
= m_reg_info
->getEncodingValue(insn
.getOperand(0).getReg());
1136 base
= m_reg_info
->getEncodingValue(insn
.getOperand(1).getReg());
1138 std::optional
<RegisterInfo
> reg_info_base
=
1139 GetRegisterInfo(eRegisterKindDWARF
, dwarf_zero_mips64
+ base
);
1140 std::optional
<RegisterInfo
> reg_info_src
=
1141 GetRegisterInfo(eRegisterKindDWARF
, dwarf_zero_mips64
+ src
);
1142 if (!reg_info_base
|| !reg_info_src
)
1146 address
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_zero_mips64
+ base
,
1151 /* destination address */
1152 address
= address
+ imm
;
1154 /* We look for sp based non-volatile register stores */
1155 if (nonvolatile_reg_p(src
)) {
1157 context
.type
= eContextPushRegisterOnStack
;
1158 context
.SetRegisterToRegisterPlusOffset(*reg_info_src
, *reg_info_base
, 0);
1160 std::optional
<RegisterValue
> data_src
= ReadRegister(*reg_info_base
);
1165 RegisterValue::BytesContainer
buffer(reg_info_src
->byte_size
);
1166 if (data_src
->GetAsMemoryData(*reg_info_src
, buffer
.data(),
1167 reg_info_src
->byte_size
, eByteOrderLittle
,
1171 if (!WriteMemory(context
, address
, buffer
.data(), reg_info_src
->byte_size
))
1175 /* Set the bad_vaddr register with base address used in the instruction */
1176 bad_vaddr_context
.type
= eContextInvalid
;
1177 WriteRegisterUnsigned(bad_vaddr_context
, eRegisterKindDWARF
, dwarf_bad_mips64
,
1183 bool EmulateInstructionMIPS64::Emulate_LD(llvm::MCInst
&insn
) {
1184 bool success
= false;
1186 int64_t imm
, address
;
1187 Context bad_vaddr_context
;
1189 src
= m_reg_info
->getEncodingValue(insn
.getOperand(0).getReg());
1190 base
= m_reg_info
->getEncodingValue(insn
.getOperand(1).getReg());
1191 imm
= insn
.getOperand(2).getImm();
1193 if (!GetRegisterInfo(eRegisterKindDWARF
, dwarf_zero_mips64
+ base
))
1196 /* read base register */
1197 address
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_zero_mips64
+ base
,
1202 /* destination address */
1203 address
= address
+ imm
;
1205 /* Set the bad_vaddr register with base address used in the instruction */
1206 bad_vaddr_context
.type
= eContextInvalid
;
1207 WriteRegisterUnsigned(bad_vaddr_context
, eRegisterKindDWARF
, dwarf_bad_mips64
,
1210 if (nonvolatile_reg_p(src
)) {
1211 RegisterValue data_src
;
1212 std::optional
<RegisterInfo
> reg_info_src
=
1213 GetRegisterInfo(eRegisterKindDWARF
, dwarf_zero_mips64
+ src
);
1218 context
.type
= eContextRegisterLoad
;
1220 return WriteRegister(context
, *reg_info_src
, data_src
);
1226 bool EmulateInstructionMIPS64::Emulate_LUI(llvm::MCInst
&insn
) {
1227 // LUI rt, immediate
1228 // GPR[rt] <- sign_extend(immediate << 16)
1230 const uint32_t imm32
= insn
.getOperand(1).getImm() << 16;
1231 int64_t imm
= SignedBits(imm32
, 31, 0);
1235 rt
= m_reg_info
->getEncodingValue(insn
.getOperand(0).getReg());
1236 context
.SetImmediateSigned(imm
);
1237 context
.type
= eContextImmediate
;
1239 return WriteRegisterUnsigned(context
, eRegisterKindDWARF
,
1240 dwarf_zero_mips64
+ rt
, imm
);
1243 bool EmulateInstructionMIPS64::Emulate_DSUBU_DADDU(llvm::MCInst
&insn
) {
1244 // DSUBU sp, <src>, <rt>
1245 // DADDU sp, <src>, <rt>
1246 // DADDU dst, sp, <rt>
1248 bool success
= false;
1250 uint8_t src
, dst
, rt
;
1251 llvm::StringRef op_name
= m_insn_info
->getName(insn
.getOpcode());
1253 dst
= m_reg_info
->getEncodingValue(insn
.getOperand(0).getReg());
1254 src
= m_reg_info
->getEncodingValue(insn
.getOperand(1).getReg());
1256 /* Check if sp is destination register */
1257 if (dst
== dwarf_sp_mips64
) {
1258 rt
= m_reg_info
->getEncodingValue(insn
.getOperand(2).getReg());
1260 /* read <src> register */
1261 uint64_t src_opd_val
= ReadRegisterUnsigned(
1262 eRegisterKindDWARF
, dwarf_zero_mips64
+ src
, 0, &success
);
1266 /* read <rt > register */
1267 uint64_t rt_opd_val
= ReadRegisterUnsigned(
1268 eRegisterKindDWARF
, dwarf_zero_mips64
+ rt
, 0, &success
);
1272 if (op_name
.equals_insensitive("DSUBU") ||
1273 op_name
.equals_insensitive("SUBU"))
1274 result
= src_opd_val
- rt_opd_val
;
1276 result
= src_opd_val
+ rt_opd_val
;
1279 std::optional
<RegisterInfo
> reg_info_sp
=
1280 GetRegisterInfo(eRegisterKindDWARF
, dwarf_sp_mips64
);
1282 context
.SetRegisterPlusOffset(*reg_info_sp
, rt_opd_val
);
1284 /* We are allocating bytes on stack */
1285 context
.type
= eContextAdjustStackPointer
;
1287 WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_sp_mips64
, result
);
1290 } else if (src
== dwarf_sp_mips64
) {
1291 rt
= m_reg_info
->getEncodingValue(insn
.getOperand(2).getReg());
1293 /* read <src> register */
1294 uint64_t src_opd_val
= ReadRegisterUnsigned(
1295 eRegisterKindDWARF
, dwarf_zero_mips64
+ src
, 0, &success
);
1299 /* read <rt> register */
1300 uint64_t rt_opd_val
= ReadRegisterUnsigned(
1301 eRegisterKindDWARF
, dwarf_zero_mips64
+ rt
, 0, &success
);
1307 if (op_name
.equals_insensitive("DSUBU") ||
1308 op_name
.equals_insensitive("SUBU"))
1309 result
= src_opd_val
- rt_opd_val
;
1311 result
= src_opd_val
+ rt_opd_val
;
1313 context
.SetImmediateSigned(result
);
1314 context
.type
= eContextImmediate
;
1316 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
,
1317 dwarf_zero_mips64
+ dst
, result
))
1325 Emulate below MIPS branch instructions.
1326 BEQ, BNE : Branch on condition
1327 BEQL, BNEL : Branch likely
1329 bool EmulateInstructionMIPS64::Emulate_BXX_3ops(llvm::MCInst
&insn
) {
1330 bool success
= false;
1332 int64_t offset
, pc
, rs_val
, rt_val
, target
= 0;
1333 llvm::StringRef op_name
= m_insn_info
->getName(insn
.getOpcode());
1335 rs
= m_reg_info
->getEncodingValue(insn
.getOperand(0).getReg());
1336 rt
= m_reg_info
->getEncodingValue(insn
.getOperand(1).getReg());
1337 offset
= insn
.getOperand(2).getImm();
1339 pc
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc_mips64
, 0, &success
);
1343 rs_val
= (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF
,
1344 dwarf_zero_mips64
+ rs
, 0, &success
);
1348 rt_val
= (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF
,
1349 dwarf_zero_mips64
+ rt
, 0, &success
);
1353 if (op_name
.equals_insensitive("BEQ") || op_name
.equals_insensitive("BEQL") ||
1354 op_name
.equals_insensitive("BEQ64")) {
1355 if (rs_val
== rt_val
)
1356 target
= pc
+ offset
;
1359 } else if (op_name
.equals_insensitive("BNE") ||
1360 op_name
.equals_insensitive("BNEL") ||
1361 op_name
.equals_insensitive("BNE64")) {
1362 if (rs_val
!= rt_val
)
1363 target
= pc
+ offset
;
1369 context
.type
= eContextRelativeBranchImmediate
;
1370 context
.SetImmediate(offset
);
1372 return WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc_mips64
,
1377 Emulate below MIPS Non-Compact conditional branch and link instructions.
1379 BLTZALL, BGEZALL : Branch likely
1381 bool EmulateInstructionMIPS64::Emulate_Bcond_Link(llvm::MCInst
&insn
) {
1382 bool success
= false;
1384 int64_t offset
, pc
, target
= 0;
1386 llvm::StringRef op_name
= m_insn_info
->getName(insn
.getOpcode());
1388 rs
= m_reg_info
->getEncodingValue(insn
.getOperand(0).getReg());
1389 offset
= insn
.getOperand(1).getImm();
1391 pc
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc_mips64
, 0, &success
);
1395 rs_val
= (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF
,
1396 dwarf_zero_mips64
+ rs
, 0, &success
);
1400 if (op_name
.equals_insensitive("BLTZAL") ||
1401 op_name
.equals_insensitive("BLTZALL")) {
1403 target
= pc
+ offset
;
1406 } else if (op_name
.equals_insensitive("BGEZAL") ||
1407 op_name
.equals_insensitive("BGEZALL")) {
1409 target
= pc
+ offset
;
1416 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc_mips64
,
1420 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_ra_mips64
,
1427 bool EmulateInstructionMIPS64::Emulate_BAL(llvm::MCInst
&insn
) {
1428 bool success
= false;
1429 int64_t offset
, pc
, target
;
1433 * offset = sign_ext (offset << 2)
1437 offset
= insn
.getOperand(0).getImm();
1439 pc
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc_mips64
, 0, &success
);
1443 target
= pc
+ offset
;
1447 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc_mips64
,
1451 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_ra_mips64
,
1458 bool EmulateInstructionMIPS64::Emulate_BALC(llvm::MCInst
&insn
) {
1459 bool success
= false;
1460 int64_t offset
, pc
, target
;
1464 * offset = sign_ext (offset << 2)
1466 * PC = PC + 4 + offset
1468 offset
= insn
.getOperand(0).getImm();
1470 pc
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc_mips64
, 0, &success
);
1474 target
= pc
+ offset
;
1478 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc_mips64
,
1482 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_ra_mips64
,
1490 Emulate below MIPS conditional branch and link instructions.
1491 BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches
1493 bool EmulateInstructionMIPS64::Emulate_Bcond_Link_C(llvm::MCInst
&insn
) {
1494 bool success
= false;
1496 int64_t offset
, pc
, rs_val
, target
= 0;
1497 llvm::StringRef op_name
= m_insn_info
->getName(insn
.getOpcode());
1499 rs
= m_reg_info
->getEncodingValue(insn
.getOperand(0).getReg());
1500 offset
= insn
.getOperand(1).getImm();
1502 pc
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc_mips64
, 0, &success
);
1506 rs_val
= (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF
,
1507 dwarf_zero_mips64
+ rs
, 0, &success
);
1511 if (op_name
.equals_insensitive("BLEZALC")) {
1513 target
= pc
+ offset
;
1516 } else if (op_name
.equals_insensitive("BGEZALC")) {
1518 target
= pc
+ offset
;
1521 } else if (op_name
.equals_insensitive("BLTZALC")) {
1523 target
= pc
+ offset
;
1526 } else if (op_name
.equals_insensitive("BGTZALC")) {
1528 target
= pc
+ offset
;
1531 } else if (op_name
.equals_insensitive("BEQZALC")) {
1533 target
= pc
+ offset
;
1536 } else if (op_name
.equals_insensitive("BNEZALC")) {
1538 target
= pc
+ offset
;
1545 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc_mips64
,
1549 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_ra_mips64
,
1557 Emulate below MIPS branch instructions.
1558 BLTZL, BGEZL, BGTZL, BLEZL : Branch likely
1559 BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches
1561 bool EmulateInstructionMIPS64::Emulate_BXX_2ops(llvm::MCInst
&insn
) {
1562 bool success
= false;
1564 int64_t offset
, pc
, rs_val
, target
= 0;
1565 llvm::StringRef op_name
= m_insn_info
->getName(insn
.getOpcode());
1567 rs
= m_reg_info
->getEncodingValue(insn
.getOperand(0).getReg());
1568 offset
= insn
.getOperand(1).getImm();
1570 pc
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc_mips64
, 0, &success
);
1574 rs_val
= (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF
,
1575 dwarf_zero_mips64
+ rs
, 0, &success
);
1579 if (op_name
.equals_insensitive("BLTZL") ||
1580 op_name
.equals_insensitive("BLTZ") ||
1581 op_name
.equals_insensitive("BLTZ64")) {
1583 target
= pc
+ offset
;
1586 } else if (op_name
.equals_insensitive("BGEZL") ||
1587 op_name
.equals_insensitive("BGEZ") ||
1588 op_name
.equals_insensitive("BGEZ64")) {
1590 target
= pc
+ offset
;
1593 } else if (op_name
.equals_insensitive("BGTZL") ||
1594 op_name
.equals_insensitive("BGTZ") ||
1595 op_name
.equals_insensitive("BGTZ64")) {
1597 target
= pc
+ offset
;
1600 } else if (op_name
.equals_insensitive("BLEZL") ||
1601 op_name
.equals_insensitive("BLEZ") ||
1602 op_name
.equals_insensitive("BLEZ64")) {
1604 target
= pc
+ offset
;
1610 context
.type
= eContextRelativeBranchImmediate
;
1611 context
.SetImmediate(offset
);
1613 return WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc_mips64
,
1617 bool EmulateInstructionMIPS64::Emulate_BC(llvm::MCInst
&insn
) {
1618 bool success
= false;
1619 int64_t offset
, pc
, target
;
1623 * offset = sign_ext (offset << 2)
1624 * PC = PC + 4 + offset
1626 offset
= insn
.getOperand(0).getImm();
1628 pc
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc_mips64
, 0, &success
);
1632 target
= pc
+ offset
;
1636 return WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc_mips64
,
1640 static int IsAdd64bitOverflow(int64_t a
, int64_t b
) {
1641 int64_t r
= (uint64_t)a
+ (uint64_t)b
;
1642 return (a
< 0 && b
< 0 && r
>= 0) || (a
>= 0 && b
>= 0 && r
< 0);
1646 Emulate below MIPS branch instructions.
1647 BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch
1648 instructions with no delay slot
1650 bool EmulateInstructionMIPS64::Emulate_BXX_3ops_C(llvm::MCInst
&insn
) {
1651 bool success
= false;
1653 int64_t offset
, pc
, rs_val
, rt_val
, target
= 0;
1654 llvm::StringRef op_name
= m_insn_info
->getName(insn
.getOpcode());
1655 uint32_t current_inst_size
= m_insn_info
->get(insn
.getOpcode()).getSize();
1657 rs
= m_reg_info
->getEncodingValue(insn
.getOperand(0).getReg());
1658 rt
= m_reg_info
->getEncodingValue(insn
.getOperand(1).getReg());
1659 offset
= insn
.getOperand(2).getImm();
1661 pc
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc_mips64
, 0, &success
);
1665 rs_val
= (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF
,
1666 dwarf_zero_mips64
+ rs
, 0, &success
);
1670 rt_val
= (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF
,
1671 dwarf_zero_mips64
+ rt
, 0, &success
);
1675 if (op_name
.equals_insensitive("BEQC") ||
1676 op_name
.equals_insensitive("BEQC64")) {
1677 if (rs_val
== rt_val
)
1678 target
= pc
+ offset
;
1681 } else if (op_name
.equals_insensitive("BNEC") ||
1682 op_name
.equals_insensitive("BNEC64")) {
1683 if (rs_val
!= rt_val
)
1684 target
= pc
+ offset
;
1687 } else if (op_name
.equals_insensitive("BLTC") ||
1688 op_name
.equals_insensitive("BLTC64")) {
1689 if (rs_val
< rt_val
)
1690 target
= pc
+ offset
;
1693 } else if (op_name
.equals_insensitive("BGEC64") ||
1694 op_name
.equals_insensitive("BGEC")) {
1695 if (rs_val
>= rt_val
)
1696 target
= pc
+ offset
;
1699 } else if (op_name
.equals_insensitive("BLTUC") ||
1700 op_name
.equals_insensitive("BLTUC64")) {
1701 if (rs_val
< rt_val
)
1702 target
= pc
+ offset
;
1705 } else if (op_name
.equals_insensitive("BGEUC") ||
1706 op_name
.equals_insensitive("BGEUC64")) {
1707 if ((uint32_t)rs_val
>= (uint32_t)rt_val
)
1708 target
= pc
+ offset
;
1711 } else if (op_name
.equals_insensitive("BOVC")) {
1712 if (IsAdd64bitOverflow(rs_val
, rt_val
))
1713 target
= pc
+ offset
;
1716 } else if (op_name
.equals_insensitive("BNVC")) {
1717 if (!IsAdd64bitOverflow(rs_val
, rt_val
))
1718 target
= pc
+ offset
;
1724 context
.type
= eContextRelativeBranchImmediate
;
1725 context
.SetImmediate(current_inst_size
+ offset
);
1727 return WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc_mips64
,
1732 Emulate below MIPS branch instructions.
1733 BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches
1735 bool EmulateInstructionMIPS64::Emulate_BXX_2ops_C(llvm::MCInst
&insn
) {
1736 bool success
= false;
1738 int64_t offset
, pc
, target
= 0;
1740 llvm::StringRef op_name
= m_insn_info
->getName(insn
.getOpcode());
1741 uint32_t current_inst_size
= m_insn_info
->get(insn
.getOpcode()).getSize();
1743 rs
= m_reg_info
->getEncodingValue(insn
.getOperand(0).getReg());
1744 offset
= insn
.getOperand(1).getImm();
1746 pc
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc_mips64
, 0, &success
);
1750 rs_val
= (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF
,
1751 dwarf_zero_mips64
+ rs
, 0, &success
);
1755 if (op_name
.equals_insensitive("BLTZC") ||
1756 op_name
.equals_insensitive("BLTZC64")) {
1758 target
= pc
+ offset
;
1761 } else if (op_name
.equals_insensitive("BLEZC") ||
1762 op_name
.equals_insensitive("BLEZC64")) {
1764 target
= pc
+ offset
;
1767 } else if (op_name
.equals_insensitive("BGEZC") ||
1768 op_name
.equals_insensitive("BGEZC64")) {
1770 target
= pc
+ offset
;
1773 } else if (op_name
.equals_insensitive("BGTZC") ||
1774 op_name
.equals_insensitive("BGTZC64")) {
1776 target
= pc
+ offset
;
1779 } else if (op_name
.equals_insensitive("BEQZC") ||
1780 op_name
.equals_insensitive("BEQZC64")) {
1782 target
= pc
+ offset
;
1785 } else if (op_name
.equals_insensitive("BNEZC") ||
1786 op_name
.equals_insensitive("BNEZC64")) {
1788 target
= pc
+ offset
;
1794 context
.type
= eContextRelativeBranchImmediate
;
1795 context
.SetImmediate(current_inst_size
+ offset
);
1797 return WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc_mips64
,
1801 bool EmulateInstructionMIPS64::Emulate_J(llvm::MCInst
&insn
) {
1802 bool success
= false;
1803 uint64_t offset
, pc
;
1807 * offset = sign_ext (offset << 2)
1808 * PC = PC[63-28] | offset
1810 offset
= insn
.getOperand(0).getImm();
1812 pc
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc_mips64
, 0, &success
);
1816 /* This is a PC-region branch and not PC-relative */
1817 pc
= (pc
& 0xFFFFFFFFF0000000ULL
) | offset
;
1821 return WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc_mips64
,
1825 bool EmulateInstructionMIPS64::Emulate_JAL(llvm::MCInst
&insn
) {
1826 bool success
= false;
1827 uint64_t offset
, target
, pc
;
1831 * offset = sign_ext (offset << 2)
1832 * PC = PC[63-28] | offset
1834 offset
= insn
.getOperand(0).getImm();
1836 pc
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc_mips64
, 0, &success
);
1840 /* This is a PC-region branch and not PC-relative */
1841 target
= (pc
& 0xFFFFFFFFF0000000ULL
) | offset
;
1845 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc_mips64
,
1849 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_ra_mips64
,
1856 bool EmulateInstructionMIPS64::Emulate_JALR(llvm::MCInst
&insn
) {
1857 bool success
= false;
1859 uint64_t pc
, rs_val
;
1866 rt
= m_reg_info
->getEncodingValue(insn
.getOperand(0).getReg());
1867 rs
= m_reg_info
->getEncodingValue(insn
.getOperand(1).getReg());
1869 pc
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc_mips64
, 0, &success
);
1873 rs_val
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_zero_mips64
+ rs
, 0,
1880 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc_mips64
,
1884 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
,
1885 dwarf_zero_mips64
+ rt
, pc
+ 8))
1891 bool EmulateInstructionMIPS64::Emulate_JIALC(llvm::MCInst
&insn
) {
1892 bool success
= false;
1894 int64_t target
, offset
, pc
, rt_val
;
1898 * offset = sign_ext (offset)
1899 * PC = GPR[rt] + offset
1902 rt
= m_reg_info
->getEncodingValue(insn
.getOperand(0).getReg());
1903 offset
= insn
.getOperand(1).getImm();
1905 pc
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc_mips64
, 0, &success
);
1909 rt_val
= (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF
,
1910 dwarf_zero_mips64
+ rt
, 0, &success
);
1914 target
= rt_val
+ offset
;
1918 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc_mips64
,
1922 if (!WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_ra_mips64
,
1929 bool EmulateInstructionMIPS64::Emulate_JIC(llvm::MCInst
&insn
) {
1930 bool success
= false;
1932 int64_t target
, offset
, rt_val
;
1936 * offset = sign_ext (offset)
1937 * PC = GPR[rt] + offset
1939 rt
= m_reg_info
->getEncodingValue(insn
.getOperand(0).getReg());
1940 offset
= insn
.getOperand(1).getImm();
1942 rt_val
= (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF
,
1943 dwarf_zero_mips64
+ rt
, 0, &success
);
1947 target
= rt_val
+ offset
;
1951 return WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc_mips64
,
1955 bool EmulateInstructionMIPS64::Emulate_JR(llvm::MCInst
&insn
) {
1956 bool success
= false;
1964 rs
= m_reg_info
->getEncodingValue(insn
.getOperand(0).getReg());
1966 rs_val
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_zero_mips64
+ rs
, 0,
1973 return WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc_mips64
,
1978 Emulate Branch on FP True/False
1979 BC1F, BC1FL : Branch on FP False (L stands for branch likely)
1980 BC1T, BC1TL : Branch on FP True (L stands for branch likely)
1982 bool EmulateInstructionMIPS64::Emulate_FP_branch(llvm::MCInst
&insn
) {
1983 bool success
= false;
1985 int64_t pc
, offset
, target
= 0;
1986 llvm::StringRef op_name
= m_insn_info
->getName(insn
.getOpcode());
1990 * condition <- (FPConditionCode(cc) == 0)
1992 * offset = sign_ext (offset)
1995 cc
= m_reg_info
->getEncodingValue(insn
.getOperand(0).getReg());
1996 offset
= insn
.getOperand(1).getImm();
1998 pc
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc_mips64
, 0, &success
);
2003 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_fcsr_mips64
, 0, &success
);
2007 /* fcsr[23], fcsr[25-31] are vaild condition bits */
2008 fcsr
= ((fcsr
>> 24) & 0xfe) | ((fcsr
>> 23) & 0x01);
2010 if (op_name
.equals_insensitive("BC1F") ||
2011 op_name
.equals_insensitive("BC1FL")) {
2012 if ((fcsr
& (1 << cc
)) == 0)
2013 target
= pc
+ offset
;
2016 } else if (op_name
.equals_insensitive("BC1T") ||
2017 op_name
.equals_insensitive("BC1TL")) {
2018 if ((fcsr
& (1 << cc
)) != 0)
2019 target
= pc
+ offset
;
2026 return WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc_mips64
,
2030 bool EmulateInstructionMIPS64::Emulate_BC1EQZ(llvm::MCInst
&insn
) {
2031 bool success
= false;
2034 int64_t target
, pc
, offset
;
2038 * condition <- (FPR[ft].bit0 == 0)
2040 * offset = sign_ext (offset)
2041 * PC = PC + 4 + offset
2043 ft
= m_reg_info
->getEncodingValue(insn
.getOperand(0).getReg());
2044 offset
= insn
.getOperand(1).getImm();
2046 pc
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc_mips64
, 0, &success
);
2050 ft_val
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_zero_mips64
+ ft
, 0,
2055 if ((ft_val
& 1) == 0)
2056 target
= pc
+ 4 + offset
;
2062 return WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc_mips64
,
2066 bool EmulateInstructionMIPS64::Emulate_BC1NEZ(llvm::MCInst
&insn
) {
2067 bool success
= false;
2070 int64_t target
, pc
, offset
;
2074 * condition <- (FPR[ft].bit0 != 0)
2076 * offset = sign_ext (offset)
2077 * PC = PC + 4 + offset
2079 ft
= m_reg_info
->getEncodingValue(insn
.getOperand(0).getReg());
2080 offset
= insn
.getOperand(1).getImm();
2082 pc
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc_mips64
, 0, &success
);
2086 ft_val
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_zero_mips64
+ ft
, 0,
2091 if ((ft_val
& 1) != 0)
2092 target
= pc
+ 4 + offset
;
2098 return WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc_mips64
,
2103 Emulate MIPS-3D Branch instructions
2104 BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes
2106 BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes
2109 bool EmulateInstructionMIPS64::Emulate_3D_branch(llvm::MCInst
&insn
) {
2110 bool success
= false;
2112 int64_t pc
, offset
, target
= 0;
2113 llvm::StringRef op_name
= m_insn_info
->getName(insn
.getOpcode());
2115 cc
= m_reg_info
->getEncodingValue(insn
.getOperand(0).getReg());
2116 offset
= insn
.getOperand(1).getImm();
2118 pc
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc_mips64
, 0, &success
);
2122 fcsr
= (uint32_t)ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_fcsr_mips64
,
2127 /* fcsr[23], fcsr[25-31] are vaild condition bits */
2128 fcsr
= ((fcsr
>> 24) & 0xfe) | ((fcsr
>> 23) & 0x01);
2130 if (op_name
.equals_insensitive("BC1ANY2F")) {
2131 /* if any one bit is 0 */
2132 if (((fcsr
>> cc
) & 3) != 3)
2133 target
= pc
+ offset
;
2136 } else if (op_name
.equals_insensitive("BC1ANY2T")) {
2137 /* if any one bit is 1 */
2138 if (((fcsr
>> cc
) & 3) != 0)
2139 target
= pc
+ offset
;
2142 } else if (op_name
.equals_insensitive("BC1ANY4F")) {
2143 /* if any one bit is 0 */
2144 if (((fcsr
>> cc
) & 0xf) != 0xf)
2145 target
= pc
+ offset
;
2148 } else if (op_name
.equals_insensitive("BC1ANY4T")) {
2149 /* if any one bit is 1 */
2150 if (((fcsr
>> cc
) & 0xf) != 0)
2151 target
= pc
+ offset
;
2158 return WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc_mips64
,
2162 bool EmulateInstructionMIPS64::Emulate_BNZB(llvm::MCInst
&insn
) {
2163 return Emulate_MSA_Branch_DF(insn
, 1, true);
2166 bool EmulateInstructionMIPS64::Emulate_BNZH(llvm::MCInst
&insn
) {
2167 return Emulate_MSA_Branch_DF(insn
, 2, true);
2170 bool EmulateInstructionMIPS64::Emulate_BNZW(llvm::MCInst
&insn
) {
2171 return Emulate_MSA_Branch_DF(insn
, 4, true);
2174 bool EmulateInstructionMIPS64::Emulate_BNZD(llvm::MCInst
&insn
) {
2175 return Emulate_MSA_Branch_DF(insn
, 8, true);
2178 bool EmulateInstructionMIPS64::Emulate_BZB(llvm::MCInst
&insn
) {
2179 return Emulate_MSA_Branch_DF(insn
, 1, false);
2182 bool EmulateInstructionMIPS64::Emulate_BZH(llvm::MCInst
&insn
) {
2183 return Emulate_MSA_Branch_DF(insn
, 2, false);
2186 bool EmulateInstructionMIPS64::Emulate_BZW(llvm::MCInst
&insn
) {
2187 return Emulate_MSA_Branch_DF(insn
, 4, false);
2190 bool EmulateInstructionMIPS64::Emulate_BZD(llvm::MCInst
&insn
) {
2191 return Emulate_MSA_Branch_DF(insn
, 8, false);
2194 bool EmulateInstructionMIPS64::Emulate_MSA_Branch_DF(llvm::MCInst
&insn
,
2195 int element_byte_size
,
2197 bool success
= false, branch_hit
= true;
2199 RegisterValue reg_value
;
2200 const uint8_t *ptr
= nullptr;
2202 uint32_t wt
= m_reg_info
->getEncodingValue(insn
.getOperand(0).getReg());
2203 int64_t offset
= insn
.getOperand(1).getImm();
2206 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc_mips64
, 0, &success
);
2210 if (ReadRegister(eRegisterKindDWARF
, dwarf_w0_mips64
+ wt
, reg_value
))
2211 ptr
= (const uint8_t *)reg_value
.GetBytes();
2215 for (int i
= 0; i
< 16 / element_byte_size
; i
++) {
2216 switch (element_byte_size
) {
2218 if ((*ptr
== 0 && bnz
) || (*ptr
!= 0 && !bnz
))
2222 if ((*(const uint16_t *)ptr
== 0 && bnz
) ||
2223 (*(const uint16_t *)ptr
!= 0 && !bnz
))
2227 if ((*(const uint32_t *)ptr
== 0 && bnz
) ||
2228 (*(const uint32_t *)ptr
!= 0 && !bnz
))
2232 if ((*(const uint64_t *)ptr
== 0 && bnz
) ||
2233 (*(const uint64_t *)ptr
!= 0 && !bnz
))
2239 ptr
= ptr
+ element_byte_size
;
2243 target
= pc
+ offset
;
2248 context
.type
= eContextRelativeBranchImmediate
;
2250 return WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc_mips64
,
2254 bool EmulateInstructionMIPS64::Emulate_BNZV(llvm::MCInst
&insn
) {
2255 return Emulate_MSA_Branch_V(insn
, true);
2258 bool EmulateInstructionMIPS64::Emulate_BZV(llvm::MCInst
&insn
) {
2259 return Emulate_MSA_Branch_V(insn
, false);
2262 bool EmulateInstructionMIPS64::Emulate_MSA_Branch_V(llvm::MCInst
&insn
,
2264 bool success
= false;
2266 llvm::APInt wr_val
= llvm::APInt::getZero(128);
2267 llvm::APInt fail_value
= llvm::APInt::getMaxValue(128);
2268 llvm::APInt zero_value
= llvm::APInt::getZero(128);
2269 RegisterValue reg_value
;
2271 uint32_t wt
= m_reg_info
->getEncodingValue(insn
.getOperand(0).getReg());
2272 int64_t offset
= insn
.getOperand(1).getImm();
2275 ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_pc_mips64
, 0, &success
);
2279 if (ReadRegister(eRegisterKindDWARF
, dwarf_w0_mips64
+ wt
, reg_value
))
2280 wr_val
= reg_value
.GetAsUInt128(fail_value
);
2284 if ((llvm::APInt::isSameValue(zero_value
, wr_val
) && !bnz
) ||
2285 (!llvm::APInt::isSameValue(zero_value
, wr_val
) && bnz
))
2286 target
= pc
+ offset
;
2291 context
.type
= eContextRelativeBranchImmediate
;
2293 return WriteRegisterUnsigned(context
, eRegisterKindDWARF
, dwarf_pc_mips64
,
2297 bool EmulateInstructionMIPS64::Emulate_LDST_Imm(llvm::MCInst
&insn
) {
2298 bool success
= false;
2300 int64_t imm
, address
;
2301 Context bad_vaddr_context
;
2303 uint32_t num_operands
= insn
.getNumOperands();
2305 m_reg_info
->getEncodingValue(insn
.getOperand(num_operands
- 2).getReg());
2306 imm
= insn
.getOperand(num_operands
- 1).getImm();
2308 if (!GetRegisterInfo(eRegisterKindDWARF
, dwarf_zero_mips
+ base
))
2311 /* read base register */
2312 address
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_zero_mips
+ base
, 0,
2317 /* destination address */
2318 address
= address
+ imm
;
2320 /* Set the bad_vaddr register with base address used in the instruction */
2321 bad_vaddr_context
.type
= eContextInvalid
;
2322 WriteRegisterUnsigned(bad_vaddr_context
, eRegisterKindDWARF
, dwarf_bad_mips
,
2328 bool EmulateInstructionMIPS64::Emulate_LDST_Reg(llvm::MCInst
&insn
) {
2329 bool success
= false;
2330 uint32_t base
, index
;
2331 int64_t address
, index_address
;
2332 Context bad_vaddr_context
;
2334 uint32_t num_operands
= insn
.getNumOperands();
2336 m_reg_info
->getEncodingValue(insn
.getOperand(num_operands
- 2).getReg());
2338 m_reg_info
->getEncodingValue(insn
.getOperand(num_operands
- 1).getReg());
2340 if (!GetRegisterInfo(eRegisterKindDWARF
, dwarf_zero_mips
+ base
))
2343 if (!GetRegisterInfo(eRegisterKindDWARF
, dwarf_zero_mips
+ index
))
2346 /* read base register */
2347 address
= ReadRegisterUnsigned(eRegisterKindDWARF
, dwarf_zero_mips
+ base
, 0,
2352 /* read index register */
2353 index_address
= ReadRegisterUnsigned(eRegisterKindDWARF
,
2354 dwarf_zero_mips
+ index
, 0, &success
);
2358 /* destination address */
2359 address
= address
+ index_address
;
2361 /* Set the bad_vaddr register with base address used in the instruction */
2362 bad_vaddr_context
.type
= eContextInvalid
;
2363 WriteRegisterUnsigned(bad_vaddr_context
, eRegisterKindDWARF
, dwarf_bad_mips
,