1 //===-- EmulateInstructionMIPS64.cpp --------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "EmulateInstructionMIPS64.h"
10 
11 #include <stdlib.h>
12 
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"
34 
35 #include "llvm/ADT/STLExtras.h"
36 
37 #include "Plugins/Process/Utility/InstructionUtils.h"
38 #include "Plugins/Process/Utility/RegisterContext_mips.h"
39 
40 using namespace lldb;
41 using namespace lldb_private;
42 
43 LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionMIPS64, InstructionMIPS64)
44 
45 #define UInt(x) ((uint64_t)x)
46 #define integer int64_t
47 
48 //
49 // EmulateInstructionMIPS64 implementation
50 //
51 
52 #ifdef __mips__
53 extern "C" {
54 void LLVMInitializeMipsTargetInfo();
55 void LLVMInitializeMipsTarget();
56 void LLVMInitializeMipsAsmPrinter();
57 void LLVMInitializeMipsTargetMC();
58 void LLVMInitializeMipsDisassembler();
59 }
60 #endif
61 
62 EmulateInstructionMIPS64::EmulateInstructionMIPS64(
63     const lldb_private::ArchSpec &arch)
64     : EmulateInstruction(arch) {
65   /* Create instance of llvm::MCDisassembler */
66   std::string Status;
67   llvm::Triple triple = arch.GetTriple();
68   const llvm::Target *target =
69       llvm::TargetRegistry::lookupTarget(triple.getTriple(), Status);
70 
71 /*
72  * If we fail to get the target then we haven't registered it. The
73  * SystemInitializerCommon
74  * does not initialize targets, MCs and disassemblers. However we need the
75  * MCDisassembler
76  * to decode the instructions so that the decoding complexity stays with LLVM.
77  * Initialize the MIPS targets and disassemblers.
78 */
79 #ifdef __mips__
80   if (!target) {
81     LLVMInitializeMipsTargetInfo();
82     LLVMInitializeMipsTarget();
83     LLVMInitializeMipsAsmPrinter();
84     LLVMInitializeMipsTargetMC();
85     LLVMInitializeMipsDisassembler();
86     target = llvm::TargetRegistry::lookupTarget(triple.getTriple(), Status);
87   }
88 #endif
89 
90   assert(target);
91 
92   llvm::StringRef cpu;
93 
94   switch (arch.GetCore()) {
95   case ArchSpec::eCore_mips32:
96   case ArchSpec::eCore_mips32el:
97     cpu = "mips32";
98     break;
99   case ArchSpec::eCore_mips32r2:
100   case ArchSpec::eCore_mips32r2el:
101     cpu = "mips32r2";
102     break;
103   case ArchSpec::eCore_mips32r3:
104   case ArchSpec::eCore_mips32r3el:
105     cpu = "mips32r3";
106     break;
107   case ArchSpec::eCore_mips32r5:
108   case ArchSpec::eCore_mips32r5el:
109     cpu = "mips32r5";
110     break;
111   case ArchSpec::eCore_mips32r6:
112   case ArchSpec::eCore_mips32r6el:
113     cpu = "mips32r6";
114     break;
115   case ArchSpec::eCore_mips64:
116   case ArchSpec::eCore_mips64el:
117     cpu = "mips64";
118     break;
119   case ArchSpec::eCore_mips64r2:
120   case ArchSpec::eCore_mips64r2el:
121     cpu = "mips64r2";
122     break;
123   case ArchSpec::eCore_mips64r3:
124   case ArchSpec::eCore_mips64r3el:
125     cpu = "mips64r3";
126     break;
127   case ArchSpec::eCore_mips64r5:
128   case ArchSpec::eCore_mips64r5el:
129     cpu = "mips64r5";
130     break;
131   case ArchSpec::eCore_mips64r6:
132   case ArchSpec::eCore_mips64r6el:
133     cpu = "mips64r6";
134     break;
135   default:
136     cpu = "generic";
137     break;
138   }
139 
140   std::string features = "";
141   uint32_t arch_flags = arch.GetFlags();
142   if (arch_flags & ArchSpec::eMIPSAse_msa)
143     features += "+msa,";
144   if (arch_flags & ArchSpec::eMIPSAse_dsp)
145     features += "+dsp,";
146   if (arch_flags & ArchSpec::eMIPSAse_dspr2)
147     features += "+dspr2,";
148   if (arch_flags & ArchSpec::eMIPSAse_mips16)
149     features += "+mips16,";
150   if (arch_flags & ArchSpec::eMIPSAse_micromips)
151     features += "+micromips,";
152 
153   m_reg_info.reset(target->createMCRegInfo(triple.getTriple()));
154   assert(m_reg_info.get());
155 
156   m_insn_info.reset(target->createMCInstrInfo());
157   assert(m_insn_info.get());
158 
159   llvm::MCTargetOptions MCOptions;
160   m_asm_info.reset(
161       target->createMCAsmInfo(*m_reg_info, triple.getTriple(), MCOptions));
162   m_subtype_info.reset(
163       target->createMCSubtargetInfo(triple.getTriple(), cpu, features));
164   assert(m_asm_info.get() && m_subtype_info.get());
165 
166   m_context = std::make_unique<llvm::MCContext>(
167       triple, m_asm_info.get(), m_reg_info.get(), /*MOFI=*/nullptr,
168       m_subtype_info.get());
169   assert(m_context.get());
170 
171   m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context));
172   assert(m_disasm.get());
173 }
174 
175 void EmulateInstructionMIPS64::Initialize() {
176   PluginManager::RegisterPlugin(GetPluginNameStatic(),
177                                 GetPluginDescriptionStatic(), CreateInstance);
178 }
179 
180 void EmulateInstructionMIPS64::Terminate() {
181   PluginManager::UnregisterPlugin(CreateInstance);
182 }
183 
184 ConstString EmulateInstructionMIPS64::GetPluginNameStatic() {
185   ConstString g_plugin_name("lldb.emulate-instruction.mips64");
186   return g_plugin_name;
187 }
188 
189 lldb_private::ConstString EmulateInstructionMIPS64::GetPluginName() {
190   static ConstString g_plugin_name("EmulateInstructionMIPS64");
191   return g_plugin_name;
192 }
193 
194 const char *EmulateInstructionMIPS64::GetPluginDescriptionStatic() {
195   return "Emulate instructions for the MIPS64 architecture.";
196 }
197 
198 EmulateInstruction *
199 EmulateInstructionMIPS64::CreateInstance(const ArchSpec &arch,
200                                          InstructionType inst_type) {
201   if (EmulateInstructionMIPS64::SupportsEmulatingInstructionsOfTypeStatic(
202           inst_type)) {
203     if (arch.GetTriple().getArch() == llvm::Triple::mips64 ||
204         arch.GetTriple().getArch() == llvm::Triple::mips64el) {
205       return new EmulateInstructionMIPS64(arch);
206     }
207   }
208 
209   return nullptr;
210 }
211 
212 bool EmulateInstructionMIPS64::SetTargetTriple(const ArchSpec &arch) {
213   return arch.GetTriple().getArch() == llvm::Triple::mips64 ||
214          arch.GetTriple().getArch() == llvm::Triple::mips64el;
215 }
216 
217 const char *EmulateInstructionMIPS64::GetRegisterName(unsigned reg_num,
218                                                       bool alternate_name) {
219   if (alternate_name) {
220     switch (reg_num) {
221     case dwarf_sp_mips64:
222       return "r29";
223     case dwarf_r30_mips64:
224       return "r30";
225     case dwarf_ra_mips64:
226       return "r31";
227     case dwarf_f0_mips64:
228       return "f0";
229     case dwarf_f1_mips64:
230       return "f1";
231     case dwarf_f2_mips64:
232       return "f2";
233     case dwarf_f3_mips64:
234       return "f3";
235     case dwarf_f4_mips64:
236       return "f4";
237     case dwarf_f5_mips64:
238       return "f5";
239     case dwarf_f6_mips64:
240       return "f6";
241     case dwarf_f7_mips64:
242       return "f7";
243     case dwarf_f8_mips64:
244       return "f8";
245     case dwarf_f9_mips64:
246       return "f9";
247     case dwarf_f10_mips64:
248       return "f10";
249     case dwarf_f11_mips64:
250       return "f11";
251     case dwarf_f12_mips64:
252       return "f12";
253     case dwarf_f13_mips64:
254       return "f13";
255     case dwarf_f14_mips64:
256       return "f14";
257     case dwarf_f15_mips64:
258       return "f15";
259     case dwarf_f16_mips64:
260       return "f16";
261     case dwarf_f17_mips64:
262       return "f17";
263     case dwarf_f18_mips64:
264       return "f18";
265     case dwarf_f19_mips64:
266       return "f19";
267     case dwarf_f20_mips64:
268       return "f20";
269     case dwarf_f21_mips64:
270       return "f21";
271     case dwarf_f22_mips64:
272       return "f22";
273     case dwarf_f23_mips64:
274       return "f23";
275     case dwarf_f24_mips64:
276       return "f24";
277     case dwarf_f25_mips64:
278       return "f25";
279     case dwarf_f26_mips64:
280       return "f26";
281     case dwarf_f27_mips64:
282       return "f27";
283     case dwarf_f28_mips64:
284       return "f28";
285     case dwarf_f29_mips64:
286       return "f29";
287     case dwarf_f30_mips64:
288       return "f30";
289     case dwarf_f31_mips64:
290       return "f31";
291     case dwarf_w0_mips64:
292       return "w0";
293     case dwarf_w1_mips64:
294       return "w1";
295     case dwarf_w2_mips64:
296       return "w2";
297     case dwarf_w3_mips64:
298       return "w3";
299     case dwarf_w4_mips64:
300       return "w4";
301     case dwarf_w5_mips64:
302       return "w5";
303     case dwarf_w6_mips64:
304       return "w6";
305     case dwarf_w7_mips64:
306       return "w7";
307     case dwarf_w8_mips64:
308       return "w8";
309     case dwarf_w9_mips64:
310       return "w9";
311     case dwarf_w10_mips64:
312       return "w10";
313     case dwarf_w11_mips64:
314       return "w11";
315     case dwarf_w12_mips64:
316       return "w12";
317     case dwarf_w13_mips64:
318       return "w13";
319     case dwarf_w14_mips64:
320       return "w14";
321     case dwarf_w15_mips64:
322       return "w15";
323     case dwarf_w16_mips64:
324       return "w16";
325     case dwarf_w17_mips64:
326       return "w17";
327     case dwarf_w18_mips64:
328       return "w18";
329     case dwarf_w19_mips64:
330       return "w19";
331     case dwarf_w20_mips64:
332       return "w20";
333     case dwarf_w21_mips64:
334       return "w21";
335     case dwarf_w22_mips64:
336       return "w22";
337     case dwarf_w23_mips64:
338       return "w23";
339     case dwarf_w24_mips64:
340       return "w24";
341     case dwarf_w25_mips64:
342       return "w25";
343     case dwarf_w26_mips64:
344       return "w26";
345     case dwarf_w27_mips64:
346       return "w27";
347     case dwarf_w28_mips64:
348       return "w28";
349     case dwarf_w29_mips64:
350       return "w29";
351     case dwarf_w30_mips64:
352       return "w30";
353     case dwarf_w31_mips64:
354       return "w31";
355     case dwarf_mir_mips64:
356       return "mir";
357     case dwarf_mcsr_mips64:
358       return "mcsr";
359     case dwarf_config5_mips64:
360       return "config5";
361     default:
362       break;
363     }
364     return nullptr;
365   }
366 
367   switch (reg_num) {
368   case dwarf_zero_mips64:
369     return "r0";
370   case dwarf_r1_mips64:
371     return "r1";
372   case dwarf_r2_mips64:
373     return "r2";
374   case dwarf_r3_mips64:
375     return "r3";
376   case dwarf_r4_mips64:
377     return "r4";
378   case dwarf_r5_mips64:
379     return "r5";
380   case dwarf_r6_mips64:
381     return "r6";
382   case dwarf_r7_mips64:
383     return "r7";
384   case dwarf_r8_mips64:
385     return "r8";
386   case dwarf_r9_mips64:
387     return "r9";
388   case dwarf_r10_mips64:
389     return "r10";
390   case dwarf_r11_mips64:
391     return "r11";
392   case dwarf_r12_mips64:
393     return "r12";
394   case dwarf_r13_mips64:
395     return "r13";
396   case dwarf_r14_mips64:
397     return "r14";
398   case dwarf_r15_mips64:
399     return "r15";
400   case dwarf_r16_mips64:
401     return "r16";
402   case dwarf_r17_mips64:
403     return "r17";
404   case dwarf_r18_mips64:
405     return "r18";
406   case dwarf_r19_mips64:
407     return "r19";
408   case dwarf_r20_mips64:
409     return "r20";
410   case dwarf_r21_mips64:
411     return "r21";
412   case dwarf_r22_mips64:
413     return "r22";
414   case dwarf_r23_mips64:
415     return "r23";
416   case dwarf_r24_mips64:
417     return "r24";
418   case dwarf_r25_mips64:
419     return "r25";
420   case dwarf_r26_mips64:
421     return "r26";
422   case dwarf_r27_mips64:
423     return "r27";
424   case dwarf_gp_mips64:
425     return "gp";
426   case dwarf_sp_mips64:
427     return "sp";
428   case dwarf_r30_mips64:
429     return "fp";
430   case dwarf_ra_mips64:
431     return "ra";
432   case dwarf_sr_mips64:
433     return "sr";
434   case dwarf_lo_mips64:
435     return "lo";
436   case dwarf_hi_mips64:
437     return "hi";
438   case dwarf_bad_mips64:
439     return "bad";
440   case dwarf_cause_mips64:
441     return "cause";
442   case dwarf_pc_mips64:
443     return "pc";
444   case dwarf_f0_mips64:
445     return "f0";
446   case dwarf_f1_mips64:
447     return "f1";
448   case dwarf_f2_mips64:
449     return "f2";
450   case dwarf_f3_mips64:
451     return "f3";
452   case dwarf_f4_mips64:
453     return "f4";
454   case dwarf_f5_mips64:
455     return "f5";
456   case dwarf_f6_mips64:
457     return "f6";
458   case dwarf_f7_mips64:
459     return "f7";
460   case dwarf_f8_mips64:
461     return "f8";
462   case dwarf_f9_mips64:
463     return "f9";
464   case dwarf_f10_mips64:
465     return "f10";
466   case dwarf_f11_mips64:
467     return "f11";
468   case dwarf_f12_mips64:
469     return "f12";
470   case dwarf_f13_mips64:
471     return "f13";
472   case dwarf_f14_mips64:
473     return "f14";
474   case dwarf_f15_mips64:
475     return "f15";
476   case dwarf_f16_mips64:
477     return "f16";
478   case dwarf_f17_mips64:
479     return "f17";
480   case dwarf_f18_mips64:
481     return "f18";
482   case dwarf_f19_mips64:
483     return "f19";
484   case dwarf_f20_mips64:
485     return "f20";
486   case dwarf_f21_mips64:
487     return "f21";
488   case dwarf_f22_mips64:
489     return "f22";
490   case dwarf_f23_mips64:
491     return "f23";
492   case dwarf_f24_mips64:
493     return "f24";
494   case dwarf_f25_mips64:
495     return "f25";
496   case dwarf_f26_mips64:
497     return "f26";
498   case dwarf_f27_mips64:
499     return "f27";
500   case dwarf_f28_mips64:
501     return "f28";
502   case dwarf_f29_mips64:
503     return "f29";
504   case dwarf_f30_mips64:
505     return "f30";
506   case dwarf_f31_mips64:
507     return "f31";
508   case dwarf_fcsr_mips64:
509     return "fcsr";
510   case dwarf_fir_mips64:
511     return "fir";
512   case dwarf_w0_mips64:
513     return "w0";
514   case dwarf_w1_mips64:
515     return "w1";
516   case dwarf_w2_mips64:
517     return "w2";
518   case dwarf_w3_mips64:
519     return "w3";
520   case dwarf_w4_mips64:
521     return "w4";
522   case dwarf_w5_mips64:
523     return "w5";
524   case dwarf_w6_mips64:
525     return "w6";
526   case dwarf_w7_mips64:
527     return "w7";
528   case dwarf_w8_mips64:
529     return "w8";
530   case dwarf_w9_mips64:
531     return "w9";
532   case dwarf_w10_mips64:
533     return "w10";
534   case dwarf_w11_mips64:
535     return "w11";
536   case dwarf_w12_mips64:
537     return "w12";
538   case dwarf_w13_mips64:
539     return "w13";
540   case dwarf_w14_mips64:
541     return "w14";
542   case dwarf_w15_mips64:
543     return "w15";
544   case dwarf_w16_mips64:
545     return "w16";
546   case dwarf_w17_mips64:
547     return "w17";
548   case dwarf_w18_mips64:
549     return "w18";
550   case dwarf_w19_mips64:
551     return "w19";
552   case dwarf_w20_mips64:
553     return "w20";
554   case dwarf_w21_mips64:
555     return "w21";
556   case dwarf_w22_mips64:
557     return "w22";
558   case dwarf_w23_mips64:
559     return "w23";
560   case dwarf_w24_mips64:
561     return "w24";
562   case dwarf_w25_mips64:
563     return "w25";
564   case dwarf_w26_mips64:
565     return "w26";
566   case dwarf_w27_mips64:
567     return "w27";
568   case dwarf_w28_mips64:
569     return "w28";
570   case dwarf_w29_mips64:
571     return "w29";
572   case dwarf_w30_mips64:
573     return "w30";
574   case dwarf_w31_mips64:
575     return "w31";
576   case dwarf_mcsr_mips64:
577     return "mcsr";
578   case dwarf_mir_mips64:
579     return "mir";
580   case dwarf_config5_mips64:
581     return "config5";
582   }
583   return nullptr;
584 }
585 
586 bool EmulateInstructionMIPS64::GetRegisterInfo(RegisterKind reg_kind,
587                                                uint32_t reg_num,
588                                                RegisterInfo &reg_info) {
589   if (reg_kind == eRegisterKindGeneric) {
590     switch (reg_num) {
591     case LLDB_REGNUM_GENERIC_PC:
592       reg_kind = eRegisterKindDWARF;
593       reg_num = dwarf_pc_mips64;
594       break;
595     case LLDB_REGNUM_GENERIC_SP:
596       reg_kind = eRegisterKindDWARF;
597       reg_num = dwarf_sp_mips64;
598       break;
599     case LLDB_REGNUM_GENERIC_FP:
600       reg_kind = eRegisterKindDWARF;
601       reg_num = dwarf_r30_mips64;
602       break;
603     case LLDB_REGNUM_GENERIC_RA:
604       reg_kind = eRegisterKindDWARF;
605       reg_num = dwarf_ra_mips64;
606       break;
607     case LLDB_REGNUM_GENERIC_FLAGS:
608       reg_kind = eRegisterKindDWARF;
609       reg_num = dwarf_sr_mips64;
610       break;
611     default:
612       return false;
613     }
614   }
615 
616   if (reg_kind == eRegisterKindDWARF) {
617     ::memset(&reg_info, 0, sizeof(RegisterInfo));
618     ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
619 
620     if (reg_num == dwarf_sr_mips64 || reg_num == dwarf_fcsr_mips64 ||
621         reg_num == dwarf_fir_mips64 || reg_num == dwarf_mcsr_mips64 ||
622         reg_num == dwarf_mir_mips64 || reg_num == dwarf_config5_mips64) {
623       reg_info.byte_size = 4;
624       reg_info.format = eFormatHex;
625       reg_info.encoding = eEncodingUint;
626     } else if ((int)reg_num >= dwarf_zero_mips64 &&
627                (int)reg_num <= dwarf_f31_mips64) {
628       reg_info.byte_size = 8;
629       reg_info.format = eFormatHex;
630       reg_info.encoding = eEncodingUint;
631     } else if ((int)reg_num >= dwarf_w0_mips64 &&
632                (int)reg_num <= dwarf_w31_mips64) {
633       reg_info.byte_size = 16;
634       reg_info.format = eFormatVectorOfUInt8;
635       reg_info.encoding = eEncodingVector;
636     } else {
637       return false;
638     }
639 
640     reg_info.name = GetRegisterName(reg_num, false);
641     reg_info.alt_name = GetRegisterName(reg_num, true);
642     reg_info.kinds[eRegisterKindDWARF] = reg_num;
643 
644     switch (reg_num) {
645     case dwarf_r30_mips64:
646       reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
647       break;
648     case dwarf_ra_mips64:
649       reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
650       break;
651     case dwarf_sp_mips64:
652       reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
653       break;
654     case dwarf_pc_mips64:
655       reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
656       break;
657     case dwarf_sr_mips64:
658       reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
659       break;
660     default:
661       break;
662     }
663     return true;
664   }
665   return false;
666 }
667 
668 EmulateInstructionMIPS64::MipsOpcode *
669 EmulateInstructionMIPS64::GetOpcodeForInstruction(const char *op_name) {
670   static EmulateInstructionMIPS64::MipsOpcode g_opcodes[] = {
671       // Prologue/Epilogue instructions
672       {"DADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu,
673        "DADDIU rt, rs, immediate"},
674       {"ADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu,
675        "ADDIU  rt, rs, immediate"},
676       {"SD", &EmulateInstructionMIPS64::Emulate_SD, "SD     rt, offset(rs)"},
677       {"LD", &EmulateInstructionMIPS64::Emulate_LD, "LD     rt, offset(base)"},
678       {"DSUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
679        "DSUBU  rd, rs, rt"},
680       {"SUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
681        "SUBU   rd, rs, rt"},
682       {"DADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
683        "DADDU  rd, rs, rt"},
684       {"ADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
685        "ADDU   rd, rs, rt"},
686       {"LUI", &EmulateInstructionMIPS64::Emulate_LUI, "LUI    rt, immediate"},
687 
688       // Load/Store  instructions
689       /* Following list of emulated instructions are required by implementation
690          of hardware watchpoint
691          for MIPS in lldb. As we just need the address accessed by instructions,
692          we have generalised
693          all these instructions in 2 functions depending on their addressing
694          modes */
695 
696       {"LB", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
697        "LB    rt, offset(base)"},
698       {"LBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
699        "LBE   rt, offset(base)"},
700       {"LBU", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
701        "LBU   rt, offset(base)"},
702       {"LBUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
703        "LBUE  rt, offset(base)"},
704       {"LDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
705        "LDC1  ft, offset(base)"},
706       {"LDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
707        "LDL   rt, offset(base)"},
708       {"LDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
709        "LDR   rt, offset(base)"},
710       {"LLD", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
711        "LLD   rt, offset(base)"},
712       {"LDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
713        "LDC2  rt, offset(base)"},
714       {"LDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
715        "LDXC1 fd, index (base)"},
716       {"LH", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
717        "LH    rt, offset(base)"},
718       {"LHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
719        "LHE   rt, offset(base)"},
720       {"LHU", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
721        "LHU   rt, offset(base)"},
722       {"LHUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
723        "LHUE  rt, offset(base)"},
724       {"LL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
725        "LL    rt, offset(base)"},
726       {"LLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
727        "LLE   rt, offset(base)"},
728       {"LUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
729        "LUXC1 fd, index (base)"},
730       {"LW", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
731        "LW    rt, offset(rs)"},
732       {"LWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
733        "LWC1  ft, offset(base)"},
734       {"LWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
735        "LWC2  rt, offset(base)"},
736       {"LWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
737        "LWE   rt, offset(base)"},
738       {"LWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
739        "LWL   rt, offset(base)"},
740       {"LWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
741        "LWLE  rt, offset(base)"},
742       {"LWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
743        "LWR   rt, offset(base)"},
744       {"LWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
745        "LWRE  rt, offset(base)"},
746       {"LWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
747        "LWXC1 fd, index (base)"},
748 
749       {"SB", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
750        "SB    rt, offset(base)"},
751       {"SBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
752        "SBE   rt, offset(base)"},
753       {"SC", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
754        "SC    rt, offset(base)"},
755       {"SCE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
756        "SCE   rt, offset(base)"},
757       {"SCD", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
758        "SCD   rt, offset(base)"},
759       {"SDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
760        "SDL   rt, offset(base)"},
761       {"SDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
762        "SDR   rt, offset(base)"},
763       {"SDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
764        "SDC1  ft, offset(base)"},
765       {"SDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
766        "SDC2  rt, offset(base)"},
767       {"SDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
768        "SDXC1 fs, index (base)"},
769       {"SH", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
770        "SH    rt, offset(base)"},
771       {"SHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
772        "SHE   rt, offset(base)"},
773       {"SUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
774        "SUXC1 fs, index (base)"},
775       {"SW", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
776        "SW    rt, offset(rs)"},
777       {"SWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
778        "SWC1  ft, offset(base)"},
779       {"SWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
780        "SWC2  rt, offset(base)"},
781       {"SWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
782        "SWE   rt, offset(base)"},
783       {"SWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
784        "SWL   rt, offset(base)"},
785       {"SWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
786        "SWLE  rt, offset(base)"},
787       {"SWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
788        "SWR   rt, offset(base)"},
789       {"SWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
790        "SWRE  rt, offset(base)"},
791       {"SWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
792        "SWXC1 fs, index (base)"},
793 
794       // Branch instructions
795       {"BEQ", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"},
796       {"BEQ64", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"},
797       {"BNE", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"},
798       {"BNE64", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"},
799       {"BEQL", &EmulateInstructionMIPS64::Emulate_BXX_3ops,
800        "BEQL rs,rt,offset"},
801       {"BNEL", &EmulateInstructionMIPS64::Emulate_BXX_3ops,
802        "BNEL rs,rt,offset"},
803       {"BGEZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
804        "BGEZALL rt,offset"},
805       {"BAL", &EmulateInstructionMIPS64::Emulate_BAL, "BAL offset"},
806       {"BGEZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
807        "BGEZAL rs,offset"},
808       {"BALC", &EmulateInstructionMIPS64::Emulate_BALC, "BALC offset"},
809       {"BC", &EmulateInstructionMIPS64::Emulate_BC, "BC offset"},
810       {"BGEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"},
811       {"BGEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"},
812       {"BLEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
813        "BLEZALC rs,offset"},
814       {"BGEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
815        "BGEZALC rs,offset"},
816       {"BLTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
817        "BLTZALC rs,offset"},
818       {"BGTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
819        "BGTZALC rs,offset"},
820       {"BEQZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
821        "BEQZALC rs,offset"},
822       {"BNEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
823        "BNEZALC rs,offset"},
824       {"BEQC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
825        "BEQC rs,rt,offset"},
826       {"BEQC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
827        "BEQC rs,rt,offset"},
828       {"BNEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
829        "BNEC rs,rt,offset"},
830       {"BNEC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
831        "BNEC rs,rt,offset"},
832       {"BLTC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
833        "BLTC rs,rt,offset"},
834       {"BLTC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
835        "BLTC rs,rt,offset"},
836       {"BGEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
837        "BGEC rs,rt,offset"},
838       {"BGEC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
839        "BGEC rs,rt,offset"},
840       {"BLTUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
841        "BLTUC rs,rt,offset"},
842       {"BLTUC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
843        "BLTUC rs,rt,offset"},
844       {"BGEUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
845        "BGEUC rs,rt,offset"},
846       {"BGEUC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
847        "BGEUC rs,rt,offset"},
848       {"BLTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
849        "BLTZC rt,offset"},
850       {"BLTZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
851        "BLTZC rt,offset"},
852       {"BLEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
853        "BLEZC rt,offset"},
854       {"BLEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
855        "BLEZC rt,offset"},
856       {"BGEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
857        "BGEZC rt,offset"},
858       {"BGEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
859        "BGEZC rt,offset"},
860       {"BGTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
861        "BGTZC rt,offset"},
862       {"BGTZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
863        "BGTZC rt,offset"},
864       {"BEQZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
865        "BEQZC rt,offset"},
866       {"BEQZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
867        "BEQZC rt,offset"},
868       {"BNEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
869        "BNEZC rt,offset"},
870       {"BNEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
871        "BNEZC rt,offset"},
872       {"BGEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZL rt,offset"},
873       {"BGTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"},
874       {"BGTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"},
875       {"BGTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZL rt,offset"},
876       {"BLEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"},
877       {"BLEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"},
878       {"BLEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZL rt,offset"},
879       {"BLTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"},
880       {"BLTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"},
881       {"BLTZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
882        "BLTZAL rt,offset"},
883       {"BLTZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
884        "BLTZALL rt,offset"},
885       {"BLTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZL rt,offset"},
886       {"BOVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
887        "BOVC rs,rt,offset"},
888       {"BNVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
889        "BNVC rs,rt,offset"},
890       {"J", &EmulateInstructionMIPS64::Emulate_J, "J target"},
891       {"JAL", &EmulateInstructionMIPS64::Emulate_JAL, "JAL target"},
892       {"JALX", &EmulateInstructionMIPS64::Emulate_JAL, "JALX target"},
893       {"JALR", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target"},
894       {"JALR64", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target"},
895       {"JALR_HB", &EmulateInstructionMIPS64::Emulate_JALR, "JALR.HB target"},
896       {"JIALC", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"},
897       {"JIALC64", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"},
898       {"JIC", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"},
899       {"JIC64", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"},
900       {"JR", &EmulateInstructionMIPS64::Emulate_JR, "JR target"},
901       {"JR64", &EmulateInstructionMIPS64::Emulate_JR, "JR target"},
902       {"JR_HB", &EmulateInstructionMIPS64::Emulate_JR, "JR.HB target"},
903       {"BC1F", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1F cc, offset"},
904       {"BC1T", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1T cc, offset"},
905       {"BC1FL", &EmulateInstructionMIPS64::Emulate_FP_branch,
906        "BC1FL cc, offset"},
907       {"BC1TL", &EmulateInstructionMIPS64::Emulate_FP_branch,
908        "BC1TL cc, offset"},
909       {"BC1EQZ", &EmulateInstructionMIPS64::Emulate_BC1EQZ,
910        "BC1EQZ ft, offset"},
911       {"BC1NEZ", &EmulateInstructionMIPS64::Emulate_BC1NEZ,
912        "BC1NEZ ft, offset"},
913       {"BC1ANY2F", &EmulateInstructionMIPS64::Emulate_3D_branch,
914        "BC1ANY2F cc, offset"},
915       {"BC1ANY2T", &EmulateInstructionMIPS64::Emulate_3D_branch,
916        "BC1ANY2T cc, offset"},
917       {"BC1ANY4F", &EmulateInstructionMIPS64::Emulate_3D_branch,
918        "BC1ANY4F cc, offset"},
919       {"BC1ANY4T", &EmulateInstructionMIPS64::Emulate_3D_branch,
920        "BC1ANY4T cc, offset"},
921       {"BNZ_B", &EmulateInstructionMIPS64::Emulate_BNZB, "BNZ.b wt,s16"},
922       {"BNZ_H", &EmulateInstructionMIPS64::Emulate_BNZH, "BNZ.h wt,s16"},
923       {"BNZ_W", &EmulateInstructionMIPS64::Emulate_BNZW, "BNZ.w wt,s16"},
924       {"BNZ_D", &EmulateInstructionMIPS64::Emulate_BNZD, "BNZ.d wt,s16"},
925       {"BZ_B", &EmulateInstructionMIPS64::Emulate_BZB, "BZ.b wt,s16"},
926       {"BZ_H", &EmulateInstructionMIPS64::Emulate_BZH, "BZ.h wt,s16"},
927       {"BZ_W", &EmulateInstructionMIPS64::Emulate_BZW, "BZ.w wt,s16"},
928       {"BZ_D", &EmulateInstructionMIPS64::Emulate_BZD, "BZ.d wt,s16"},
929       {"BNZ_V", &EmulateInstructionMIPS64::Emulate_BNZV, "BNZ.V wt,s16"},
930       {"BZ_V", &EmulateInstructionMIPS64::Emulate_BZV, "BZ.V wt,s16"},
931   };
932 
933   static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes);
934 
935   for (size_t i = 0; i < k_num_mips_opcodes; ++i) {
936     if (!strcasecmp(g_opcodes[i].op_name, op_name))
937       return &g_opcodes[i];
938   }
939 
940   return nullptr;
941 }
942 
943 bool EmulateInstructionMIPS64::ReadInstruction() {
944   bool success = false;
945   m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
946                                 LLDB_INVALID_ADDRESS, &success);
947   if (success) {
948     Context read_inst_context;
949     read_inst_context.type = eContextReadOpcode;
950     read_inst_context.SetNoArgs();
951     m_opcode.SetOpcode32(
952         ReadMemoryUnsigned(read_inst_context, m_addr, 4, 0, &success),
953         GetByteOrder());
954   }
955   if (!success)
956     m_addr = LLDB_INVALID_ADDRESS;
957   return success;
958 }
959 
960 bool EmulateInstructionMIPS64::EvaluateInstruction(uint32_t evaluate_options) {
961   bool success = false;
962   llvm::MCInst mc_insn;
963   uint64_t insn_size;
964   DataExtractor data;
965 
966   /* Keep the complexity of the decode logic with the llvm::MCDisassembler
967    * class. */
968   if (m_opcode.GetData(data)) {
969     llvm::MCDisassembler::DecodeStatus decode_status;
970     llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());
971     decode_status = m_disasm->getInstruction(mc_insn, insn_size, raw_insn,
972                                              m_addr, llvm::nulls());
973     if (decode_status != llvm::MCDisassembler::Success)
974       return false;
975   }
976 
977   /*
978    * mc_insn.getOpcode() returns decoded opcode. However to make use
979    * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc".
980   */
981   const char *op_name = m_insn_info->getName(mc_insn.getOpcode()).data();
982 
983   if (op_name == nullptr)
984     return false;
985 
986   /*
987    * Decoding has been done already. Just get the call-back function
988    * and emulate the instruction.
989   */
990   MipsOpcode *opcode_data = GetOpcodeForInstruction(op_name);
991 
992   if (opcode_data == nullptr)
993     return false;
994 
995   uint64_t old_pc = 0, new_pc = 0;
996   const bool auto_advance_pc =
997       evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
998 
999   if (auto_advance_pc) {
1000     old_pc =
1001         ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1002     if (!success)
1003       return false;
1004   }
1005 
1006   /* emulate instruction */
1007   success = (this->*opcode_data->callback)(mc_insn);
1008   if (!success)
1009     return false;
1010 
1011   if (auto_advance_pc) {
1012     new_pc =
1013         ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1014     if (!success)
1015       return false;
1016 
1017     /* If we haven't changed the PC, change it here */
1018     if (old_pc == new_pc) {
1019       new_pc += 4;
1020       Context context;
1021       if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1022                                  new_pc))
1023         return false;
1024     }
1025   }
1026 
1027   return true;
1028 }
1029 
1030 bool EmulateInstructionMIPS64::CreateFunctionEntryUnwind(
1031     UnwindPlan &unwind_plan) {
1032   unwind_plan.Clear();
1033   unwind_plan.SetRegisterKind(eRegisterKindDWARF);
1034 
1035   UnwindPlan::RowSP row(new UnwindPlan::Row);
1036   const bool can_replace = false;
1037 
1038   // Our previous Call Frame Address is the stack pointer
1039   row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips64, 0);
1040 
1041   // Our previous PC is in the RA
1042   row->SetRegisterLocationToRegister(dwarf_pc_mips64, dwarf_ra_mips64,
1043                                      can_replace);
1044 
1045   unwind_plan.AppendRow(row);
1046 
1047   // All other registers are the same.
1048   unwind_plan.SetSourceName("EmulateInstructionMIPS64");
1049   unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1050   unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
1051   unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
1052   unwind_plan.SetReturnAddressRegister(dwarf_ra_mips64);
1053 
1054   return true;
1055 }
1056 
1057 bool EmulateInstructionMIPS64::nonvolatile_reg_p(uint64_t regnum) {
1058   switch (regnum) {
1059   case dwarf_r16_mips64:
1060   case dwarf_r17_mips64:
1061   case dwarf_r18_mips64:
1062   case dwarf_r19_mips64:
1063   case dwarf_r20_mips64:
1064   case dwarf_r21_mips64:
1065   case dwarf_r22_mips64:
1066   case dwarf_r23_mips64:
1067   case dwarf_gp_mips64:
1068   case dwarf_sp_mips64:
1069   case dwarf_r30_mips64:
1070   case dwarf_ra_mips64:
1071     return true;
1072   default:
1073     return false;
1074   }
1075   return false;
1076 }
1077 
1078 bool EmulateInstructionMIPS64::Emulate_DADDiu(llvm::MCInst &insn) {
1079   // DADDIU rt, rs, immediate
1080   // GPR[rt] <- GPR[rs] + sign_extend(immediate)
1081 
1082   uint8_t dst, src;
1083   bool success = false;
1084   const uint32_t imm16 = insn.getOperand(2).getImm();
1085   int64_t imm = SignedBits(imm16, 15, 0);
1086 
1087   dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1088   src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1089 
1090   // If immediate is greater than 2^16 - 1 then clang generate LUI,
1091   // (D)ADDIU,(D)SUBU instructions in prolog. Example lui    $1, 0x2 daddiu $1,
1092   // $1, -0x5920 dsubu  $sp, $sp, $1 In this case, (D)ADDIU dst and src will be
1093   // same and not equal to sp
1094   if (dst == src) {
1095     Context context;
1096 
1097     /* read <src> register */
1098     const uint64_t src_opd_val = ReadRegisterUnsigned(
1099         eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
1100     if (!success)
1101       return false;
1102 
1103     /* Check if this is daddiu sp, sp, imm16 */
1104     if (dst == dwarf_sp_mips64) {
1105       /*
1106        * From the MIPS IV spec:
1107        *
1108        * The term “unsigned” in the instruction name is a misnomer; this
1109        * operation is 64-bit modulo arithmetic that does not trap on overflow.
1110        * It is appropriate for arithmetic which is not signed, such as address
1111        * arithmetic, or integer arithmetic environments that ignore overflow,
1112        * such as “C” language arithmetic.
1113        *
1114        * Assume 2's complement and rely on unsigned overflow here.
1115        */
1116       uint64_t result = src_opd_val + imm;
1117       RegisterInfo reg_info_sp;
1118 
1119       if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp))
1120         context.SetRegisterPlusOffset(reg_info_sp, imm);
1121 
1122       /* We are allocating bytes on stack */
1123       context.type = eContextAdjustStackPointer;
1124 
1125       WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips64,
1126                             result);
1127       return true;
1128     }
1129 
1130     imm += src_opd_val;
1131     context.SetImmediateSigned(imm);
1132     context.type = eContextImmediate;
1133 
1134     if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1135                                dwarf_zero_mips64 + dst, imm))
1136       return false;
1137   }
1138 
1139   return true;
1140 }
1141 
1142 bool EmulateInstructionMIPS64::Emulate_SD(llvm::MCInst &insn) {
1143   uint64_t address;
1144   RegisterInfo reg_info_base;
1145   RegisterInfo reg_info_src;
1146   bool success = false;
1147   uint32_t imm16 = insn.getOperand(2).getImm();
1148   uint64_t imm = SignedBits(imm16, 15, 0);
1149   uint32_t src, base;
1150   Context bad_vaddr_context;
1151 
1152   src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1153   base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1154 
1155   if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base,
1156                        reg_info_base) ||
1157       !GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src,
1158                        reg_info_src))
1159     return false;
1160 
1161   /* read SP */
1162   address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + base,
1163                                  0, &success);
1164   if (!success)
1165     return false;
1166 
1167   /* destination address */
1168   address = address + imm;
1169 
1170   /* We look for sp based non-volatile register stores */
1171   if (nonvolatile_reg_p(src)) {
1172     Context context;
1173     RegisterValue data_src;
1174     context.type = eContextPushRegisterOnStack;
1175     context.SetRegisterToRegisterPlusOffset(reg_info_src, reg_info_base, 0);
1176 
1177     uint8_t buffer[RegisterValue::kMaxRegisterByteSize];
1178     Status error;
1179 
1180     if (!ReadRegister(&reg_info_base, data_src))
1181       return false;
1182 
1183     if (data_src.GetAsMemoryData(&reg_info_src, buffer, reg_info_src.byte_size,
1184                                  eByteOrderLittle, error) == 0)
1185       return false;
1186 
1187     if (!WriteMemory(context, address, buffer, reg_info_src.byte_size))
1188       return false;
1189   }
1190 
1191   /* Set the bad_vaddr register with base address used in the instruction */
1192   bad_vaddr_context.type = eContextInvalid;
1193   WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64,
1194                         address);
1195 
1196   return true;
1197 }
1198 
1199 bool EmulateInstructionMIPS64::Emulate_LD(llvm::MCInst &insn) {
1200   bool success = false;
1201   uint32_t src, base;
1202   int64_t imm, address;
1203   Context bad_vaddr_context;
1204 
1205   src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1206   base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1207   imm = insn.getOperand(2).getImm();
1208 
1209   RegisterInfo reg_info_base;
1210   if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base,
1211                        reg_info_base))
1212     return false;
1213 
1214   /* read base register */
1215   address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + base,
1216                                  0, &success);
1217   if (!success)
1218     return false;
1219 
1220   /* destination address */
1221   address = address + imm;
1222 
1223   /* Set the bad_vaddr register with base address used in the instruction */
1224   bad_vaddr_context.type = eContextInvalid;
1225   WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64,
1226                         address);
1227 
1228   if (nonvolatile_reg_p(src)) {
1229     RegisterValue data_src;
1230     RegisterInfo reg_info_src;
1231 
1232     if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src,
1233                          reg_info_src))
1234       return false;
1235 
1236     Context context;
1237     context.type = eContextRegisterLoad;
1238 
1239     return WriteRegister(context, &reg_info_src, data_src);
1240   }
1241 
1242   return false;
1243 }
1244 
1245 bool EmulateInstructionMIPS64::Emulate_LUI(llvm::MCInst &insn) {
1246   // LUI rt, immediate
1247   // GPR[rt] <- sign_extend(immediate << 16)
1248 
1249   const uint32_t imm32 = insn.getOperand(1).getImm() << 16;
1250   int64_t imm = SignedBits(imm32, 31, 0);
1251   uint8_t rt;
1252   Context context;
1253 
1254   rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1255   context.SetImmediateSigned(imm);
1256   context.type = eContextImmediate;
1257 
1258   return WriteRegisterUnsigned(context, eRegisterKindDWARF,
1259                                dwarf_zero_mips64 + rt, imm);
1260 }
1261 
1262 bool EmulateInstructionMIPS64::Emulate_DSUBU_DADDU(llvm::MCInst &insn) {
1263   // DSUBU sp, <src>, <rt>
1264   // DADDU sp, <src>, <rt>
1265   // DADDU dst, sp, <rt>
1266 
1267   bool success = false;
1268   uint64_t result;
1269   uint8_t src, dst, rt;
1270   const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1271 
1272   dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1273   src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1274 
1275   /* Check if sp is destination register */
1276   if (dst == dwarf_sp_mips64) {
1277     rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1278 
1279     /* read <src> register */
1280     uint64_t src_opd_val = ReadRegisterUnsigned(
1281         eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
1282     if (!success)
1283       return false;
1284 
1285     /* read <rt > register */
1286     uint64_t rt_opd_val = ReadRegisterUnsigned(
1287         eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
1288     if (!success)
1289       return false;
1290 
1291     if (!strcasecmp(op_name, "DSUBU") || !strcasecmp(op_name, "SUBU"))
1292       result = src_opd_val - rt_opd_val;
1293     else
1294       result = src_opd_val + rt_opd_val;
1295 
1296     Context context;
1297     RegisterInfo reg_info_sp;
1298     if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp))
1299       context.SetRegisterPlusOffset(reg_info_sp, rt_opd_val);
1300 
1301     /* We are allocating bytes on stack */
1302     context.type = eContextAdjustStackPointer;
1303 
1304     WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips64, result);
1305 
1306     return true;
1307   } else if (src == dwarf_sp_mips64) {
1308     rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1309 
1310     /* read <src> register */
1311     uint64_t src_opd_val = ReadRegisterUnsigned(
1312         eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
1313     if (!success)
1314       return false;
1315 
1316     /* read <rt> register */
1317     uint64_t rt_opd_val = ReadRegisterUnsigned(
1318         eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
1319     if (!success)
1320       return false;
1321 
1322     Context context;
1323 
1324     if (!strcasecmp(op_name, "DSUBU") || !strcasecmp(op_name, "SUBU"))
1325       result = src_opd_val - rt_opd_val;
1326     else
1327       result = src_opd_val + rt_opd_val;
1328 
1329     context.SetImmediateSigned(result);
1330     context.type = eContextImmediate;
1331 
1332     if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1333                                dwarf_zero_mips64 + dst, result))
1334       return false;
1335   }
1336 
1337   return true;
1338 }
1339 
1340 /*
1341     Emulate below MIPS branch instructions.
1342     BEQ, BNE : Branch on condition
1343     BEQL, BNEL : Branch likely
1344 */
1345 bool EmulateInstructionMIPS64::Emulate_BXX_3ops(llvm::MCInst &insn) {
1346   bool success = false;
1347   uint32_t rs, rt;
1348   int64_t offset, pc, rs_val, rt_val, target = 0;
1349   const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1350 
1351   rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1352   rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1353   offset = insn.getOperand(2).getImm();
1354 
1355   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1356   if (!success)
1357     return false;
1358 
1359   rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1360                                          dwarf_zero_mips64 + rs, 0, &success);
1361   if (!success)
1362     return false;
1363 
1364   rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1365                                          dwarf_zero_mips64 + rt, 0, &success);
1366   if (!success)
1367     return false;
1368 
1369   if (!strcasecmp(op_name, "BEQ") || !strcasecmp(op_name, "BEQL")
1370        || !strcasecmp(op_name, "BEQ64") ) {
1371     if (rs_val == rt_val)
1372       target = pc + offset;
1373     else
1374       target = pc + 8;
1375   } else if (!strcasecmp(op_name, "BNE") || !strcasecmp(op_name, "BNEL")
1376               || !strcasecmp(op_name, "BNE64")) {
1377     if (rs_val != rt_val)
1378       target = pc + offset;
1379     else
1380       target = pc + 8;
1381   }
1382 
1383   Context context;
1384   context.type = eContextRelativeBranchImmediate;
1385   context.SetImmediate(offset);
1386 
1387   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1388                                target);
1389 }
1390 
1391 /*
1392     Emulate below MIPS Non-Compact conditional branch and link instructions.
1393     BLTZAL, BGEZAL      :
1394     BLTZALL, BGEZALL    : Branch likely
1395 */
1396 bool EmulateInstructionMIPS64::Emulate_Bcond_Link(llvm::MCInst &insn) {
1397   bool success = false;
1398   uint32_t rs;
1399   int64_t offset, pc, target = 0;
1400   int64_t rs_val;
1401   const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1402 
1403   rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1404   offset = insn.getOperand(1).getImm();
1405 
1406   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1407   if (!success)
1408     return false;
1409 
1410   rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1411                                          dwarf_zero_mips64 + rs, 0, &success);
1412   if (!success)
1413     return false;
1414 
1415   if (!strcasecmp(op_name, "BLTZAL") || !strcasecmp(op_name, "BLTZALL")) {
1416     if (rs_val < 0)
1417       target = pc + offset;
1418     else
1419       target = pc + 8;
1420   } else if (!strcasecmp(op_name, "BGEZAL") ||
1421              !strcasecmp(op_name, "BGEZALL")) {
1422     if (rs_val >= 0)
1423       target = pc + offset;
1424     else
1425       target = pc + 8;
1426   }
1427 
1428   Context context;
1429 
1430   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1431                              target))
1432     return false;
1433 
1434   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1435                              pc + 8))
1436     return false;
1437 
1438   return true;
1439 }
1440 
1441 bool EmulateInstructionMIPS64::Emulate_BAL(llvm::MCInst &insn) {
1442   bool success = false;
1443   int64_t offset, pc, target;
1444 
1445   /*
1446    * BAL offset
1447    *      offset = sign_ext (offset << 2)
1448    *      RA = PC + 8
1449    *      PC = PC + offset
1450   */
1451   offset = insn.getOperand(0).getImm();
1452 
1453   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1454   if (!success)
1455     return false;
1456 
1457   target = pc + offset;
1458 
1459   Context context;
1460 
1461   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1462                              target))
1463     return false;
1464 
1465   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1466                              pc + 8))
1467     return false;
1468 
1469   return true;
1470 }
1471 
1472 bool EmulateInstructionMIPS64::Emulate_BALC(llvm::MCInst &insn) {
1473   bool success = false;
1474   int64_t offset, pc, target;
1475 
1476   /*
1477    * BALC offset
1478    *      offset = sign_ext (offset << 2)
1479    *      RA = PC + 4
1480    *      PC = PC + 4 + offset
1481   */
1482   offset = insn.getOperand(0).getImm();
1483 
1484   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1485   if (!success)
1486     return false;
1487 
1488   target = pc + offset;
1489 
1490   Context context;
1491 
1492   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1493                              target))
1494     return false;
1495 
1496   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1497                              pc + 4))
1498     return false;
1499 
1500   return true;
1501 }
1502 
1503 /*
1504     Emulate below MIPS conditional branch and link instructions.
1505     BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches
1506 */
1507 bool EmulateInstructionMIPS64::Emulate_Bcond_Link_C(llvm::MCInst &insn) {
1508   bool success = false;
1509   uint32_t rs;
1510   int64_t offset, pc, rs_val, target = 0;
1511   const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1512 
1513   rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1514   offset = insn.getOperand(1).getImm();
1515 
1516   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1517   if (!success)
1518     return false;
1519 
1520   rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1521                                          dwarf_zero_mips64 + rs, 0, &success);
1522   if (!success)
1523     return false;
1524 
1525   if (!strcasecmp(op_name, "BLEZALC")) {
1526     if (rs_val <= 0)
1527       target = pc + offset;
1528     else
1529       target = pc + 4;
1530   } else if (!strcasecmp(op_name, "BGEZALC")) {
1531     if (rs_val >= 0)
1532       target = pc + offset;
1533     else
1534       target = pc + 4;
1535   } else if (!strcasecmp(op_name, "BLTZALC")) {
1536     if (rs_val < 0)
1537       target = pc + offset;
1538     else
1539       target = pc + 4;
1540   } else if (!strcasecmp(op_name, "BGTZALC")) {
1541     if (rs_val > 0)
1542       target = pc + offset;
1543     else
1544       target = pc + 4;
1545   } else if (!strcasecmp(op_name, "BEQZALC")) {
1546     if (rs_val == 0)
1547       target = pc + offset;
1548     else
1549       target = pc + 4;
1550   } else if (!strcasecmp(op_name, "BNEZALC")) {
1551     if (rs_val != 0)
1552       target = pc + offset;
1553     else
1554       target = pc + 4;
1555   }
1556 
1557   Context context;
1558 
1559   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1560                              target))
1561     return false;
1562 
1563   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1564                              pc + 4))
1565     return false;
1566 
1567   return true;
1568 }
1569 
1570 /*
1571     Emulate below MIPS branch instructions.
1572     BLTZL, BGEZL, BGTZL, BLEZL : Branch likely
1573     BLTZ, BGEZ, BGTZ, BLEZ     : Non-compact branches
1574 */
1575 bool EmulateInstructionMIPS64::Emulate_BXX_2ops(llvm::MCInst &insn) {
1576   bool success = false;
1577   uint32_t rs;
1578   int64_t offset, pc, rs_val, target = 0;
1579   const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1580 
1581   rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1582   offset = insn.getOperand(1).getImm();
1583 
1584   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1585   if (!success)
1586     return false;
1587 
1588   rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1589                                          dwarf_zero_mips64 + rs, 0, &success);
1590   if (!success)
1591     return false;
1592 
1593   if (!strcasecmp(op_name, "BLTZL") || !strcasecmp(op_name, "BLTZ")
1594        || !strcasecmp(op_name, "BLTZ64")) {
1595     if (rs_val < 0)
1596       target = pc + offset;
1597     else
1598       target = pc + 8;
1599   } else if (!strcasecmp(op_name, "BGEZL") || !strcasecmp(op_name, "BGEZ")
1600               || !strcasecmp(op_name, "BGEZ64")) {
1601     if (rs_val >= 0)
1602       target = pc + offset;
1603     else
1604       target = pc + 8;
1605   } else if (!strcasecmp(op_name, "BGTZL") || !strcasecmp(op_name, "BGTZ")
1606               || !strcasecmp(op_name, "BGTZ64")) {
1607     if (rs_val > 0)
1608       target = pc + offset;
1609     else
1610       target = pc + 8;
1611   } else if (!strcasecmp(op_name, "BLEZL") || !strcasecmp(op_name, "BLEZ")
1612               || !strcasecmp(op_name, "BLEZ64")) {
1613     if (rs_val <= 0)
1614       target = pc + offset;
1615     else
1616       target = pc + 8;
1617   }
1618 
1619   Context context;
1620   context.type = eContextRelativeBranchImmediate;
1621   context.SetImmediate(offset);
1622 
1623   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1624                                target);
1625 }
1626 
1627 bool EmulateInstructionMIPS64::Emulate_BC(llvm::MCInst &insn) {
1628   bool success = false;
1629   int64_t offset, pc, target;
1630 
1631   /*
1632    * BC offset
1633    *      offset = sign_ext (offset << 2)
1634    *      PC = PC + 4 + offset
1635   */
1636   offset = insn.getOperand(0).getImm();
1637 
1638   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1639   if (!success)
1640     return false;
1641 
1642   target = pc + offset;
1643 
1644   Context context;
1645 
1646   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1647                                target);
1648 }
1649 
1650 static int IsAdd64bitOverflow(int64_t a, int64_t b) {
1651   int64_t r = (uint64_t)a + (uint64_t)b;
1652   return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
1653 }
1654 
1655 /*
1656     Emulate below MIPS branch instructions.
1657     BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch
1658    instructions with no delay slot
1659 */
1660 bool EmulateInstructionMIPS64::Emulate_BXX_3ops_C(llvm::MCInst &insn) {
1661   bool success = false;
1662   uint32_t rs, rt;
1663   int64_t offset, pc, rs_val, rt_val, target = 0;
1664   const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1665   uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
1666 
1667   rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1668   rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1669   offset = insn.getOperand(2).getImm();
1670 
1671   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1672   if (!success)
1673     return false;
1674 
1675   rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1676                                          dwarf_zero_mips64 + rs, 0, &success);
1677   if (!success)
1678     return false;
1679 
1680   rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1681                                          dwarf_zero_mips64 + rt, 0, &success);
1682   if (!success)
1683     return false;
1684 
1685   if (!strcasecmp(op_name, "BEQC") || !strcasecmp(op_name, "BEQC64")) {
1686     if (rs_val == rt_val)
1687       target = pc + offset;
1688     else
1689       target = pc + 4;
1690   } else if (!strcasecmp(op_name, "BNEC") || !strcasecmp(op_name, "BNEC64")) {
1691     if (rs_val != rt_val)
1692       target = pc + offset;
1693     else
1694       target = pc + 4;
1695   } else if (!strcasecmp(op_name, "BLTC") || !strcasecmp(op_name, "BLTC64")) {
1696     if (rs_val < rt_val)
1697       target = pc + offset;
1698     else
1699       target = pc + 4;
1700   } else if (!strcasecmp(op_name, "BGEC64") || !strcasecmp(op_name, "BGEC")) {
1701     if (rs_val >= rt_val)
1702       target = pc + offset;
1703     else
1704       target = pc + 4;
1705   } else if (!strcasecmp(op_name, "BLTUC") || !strcasecmp(op_name, "BLTUC64")) {
1706     if (rs_val < rt_val)
1707       target = pc + offset;
1708     else
1709       target = pc + 4;
1710   } else if (!strcasecmp(op_name, "BGEUC") || !strcasecmp(op_name, "BGEUC64")) {
1711     if ((uint32_t)rs_val >= (uint32_t)rt_val)
1712       target = pc + offset;
1713     else
1714       target = pc + 4;
1715   } else if (!strcasecmp(op_name, "BOVC")) {
1716     if (IsAdd64bitOverflow(rs_val, rt_val))
1717       target = pc + offset;
1718     else
1719       target = pc + 4;
1720   } else if (!strcasecmp(op_name, "BNVC")) {
1721     if (!IsAdd64bitOverflow(rs_val, rt_val))
1722       target = pc + offset;
1723     else
1724       target = pc + 4;
1725   }
1726 
1727   Context context;
1728   context.type = eContextRelativeBranchImmediate;
1729   context.SetImmediate(current_inst_size + offset);
1730 
1731   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1732                                target);
1733 }
1734 
1735 /*
1736     Emulate below MIPS branch instructions.
1737     BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches
1738 */
1739 bool EmulateInstructionMIPS64::Emulate_BXX_2ops_C(llvm::MCInst &insn) {
1740   bool success = false;
1741   uint32_t rs;
1742   int64_t offset, pc, target = 0;
1743   int64_t rs_val;
1744   const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1745   uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
1746 
1747   rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1748   offset = insn.getOperand(1).getImm();
1749 
1750   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1751   if (!success)
1752     return false;
1753 
1754   rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1755                                          dwarf_zero_mips64 + rs, 0, &success);
1756   if (!success)
1757     return false;
1758 
1759   if (!strcasecmp(op_name, "BLTZC") || !strcasecmp(op_name, "BLTZC64")) {
1760     if (rs_val < 0)
1761       target = pc + offset;
1762     else
1763       target = pc + 4;
1764   } else if (!strcasecmp(op_name, "BLEZC") || !strcasecmp(op_name, "BLEZC64")) {
1765     if (rs_val <= 0)
1766       target = pc + offset;
1767     else
1768       target = pc + 4;
1769   } else if (!strcasecmp(op_name, "BGEZC") || !strcasecmp(op_name, "BGEZC64")) {
1770     if (rs_val >= 0)
1771       target = pc + offset;
1772     else
1773       target = pc + 4;
1774   } else if (!strcasecmp(op_name, "BGTZC") || !strcasecmp(op_name, "BGTZC64")) {
1775     if (rs_val > 0)
1776       target = pc + offset;
1777     else
1778       target = pc + 4;
1779   } else if (!strcasecmp(op_name, "BEQZC") || !strcasecmp(op_name, "BEQZC64")) {
1780     if (rs_val == 0)
1781       target = pc + offset;
1782     else
1783       target = pc + 4;
1784   } else if (!strcasecmp(op_name, "BNEZC") || !strcasecmp(op_name, "BNEZC64")) {
1785     if (rs_val != 0)
1786       target = pc + offset;
1787     else
1788       target = pc + 4;
1789   }
1790 
1791   Context context;
1792   context.type = eContextRelativeBranchImmediate;
1793   context.SetImmediate(current_inst_size + offset);
1794 
1795   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1796                                target);
1797 }
1798 
1799 bool EmulateInstructionMIPS64::Emulate_J(llvm::MCInst &insn) {
1800   bool success = false;
1801   uint64_t offset, pc;
1802 
1803   /*
1804    * J offset
1805    *      offset = sign_ext (offset << 2)
1806    *      PC = PC[63-28] | offset
1807   */
1808   offset = insn.getOperand(0).getImm();
1809 
1810   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1811   if (!success)
1812     return false;
1813 
1814   /* This is a PC-region branch and not PC-relative */
1815   pc = (pc & 0xFFFFFFFFF0000000ULL) | offset;
1816 
1817   Context context;
1818 
1819   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1820                                pc);
1821 }
1822 
1823 bool EmulateInstructionMIPS64::Emulate_JAL(llvm::MCInst &insn) {
1824   bool success = false;
1825   uint64_t offset, target, pc;
1826 
1827   /*
1828    * JAL offset
1829    *      offset = sign_ext (offset << 2)
1830    *      PC = PC[63-28] | offset
1831   */
1832   offset = insn.getOperand(0).getImm();
1833 
1834   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1835   if (!success)
1836     return false;
1837 
1838   /* This is a PC-region branch and not PC-relative */
1839   target = (pc & 0xFFFFFFFFF0000000ULL) | offset;
1840 
1841   Context context;
1842 
1843   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1844                              target))
1845     return false;
1846 
1847   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1848                              pc + 8))
1849     return false;
1850 
1851   return true;
1852 }
1853 
1854 bool EmulateInstructionMIPS64::Emulate_JALR(llvm::MCInst &insn) {
1855   bool success = false;
1856   uint32_t rs, rt;
1857   uint64_t pc, rs_val;
1858 
1859   /*
1860    * JALR rt, rs
1861    *      GPR[rt] = PC + 8
1862    *      PC = GPR[rs]
1863   */
1864   rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1865   rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1866 
1867   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1868   if (!success)
1869     return false;
1870 
1871   rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0,
1872                                 &success);
1873   if (!success)
1874     return false;
1875 
1876   Context context;
1877 
1878   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1879                              rs_val))
1880     return false;
1881 
1882   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1883                              dwarf_zero_mips64 + rt, pc + 8))
1884     return false;
1885 
1886   return true;
1887 }
1888 
1889 bool EmulateInstructionMIPS64::Emulate_JIALC(llvm::MCInst &insn) {
1890   bool success = false;
1891   uint32_t rt;
1892   int64_t target, offset, pc, rt_val;
1893 
1894   /*
1895    * JIALC rt, offset
1896    *      offset = sign_ext (offset)
1897    *      PC = GPR[rt] + offset
1898    *      RA = PC + 4
1899   */
1900   rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1901   offset = insn.getOperand(1).getImm();
1902 
1903   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1904   if (!success)
1905     return false;
1906 
1907   rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1908                                          dwarf_zero_mips64 + rt, 0, &success);
1909   if (!success)
1910     return false;
1911 
1912   target = rt_val + offset;
1913 
1914   Context context;
1915 
1916   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1917                              target))
1918     return false;
1919 
1920   if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1921                              pc + 4))
1922     return false;
1923 
1924   return true;
1925 }
1926 
1927 bool EmulateInstructionMIPS64::Emulate_JIC(llvm::MCInst &insn) {
1928   bool success = false;
1929   uint32_t rt;
1930   int64_t target, offset, rt_val;
1931 
1932   /*
1933    * JIC rt, offset
1934    *      offset = sign_ext (offset)
1935    *      PC = GPR[rt] + offset
1936   */
1937   rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1938   offset = insn.getOperand(1).getImm();
1939 
1940   rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1941                                          dwarf_zero_mips64 + rt, 0, &success);
1942   if (!success)
1943     return false;
1944 
1945   target = rt_val + offset;
1946 
1947   Context context;
1948 
1949   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1950                                target);
1951 }
1952 
1953 bool EmulateInstructionMIPS64::Emulate_JR(llvm::MCInst &insn) {
1954   bool success = false;
1955   uint32_t rs;
1956   uint64_t rs_val;
1957 
1958   /*
1959    * JR rs
1960    *      PC = GPR[rs]
1961   */
1962   rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1963 
1964   rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0,
1965                                 &success);
1966   if (!success)
1967     return false;
1968 
1969   Context context;
1970 
1971   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1972                                rs_val);
1973 }
1974 
1975 /*
1976     Emulate Branch on FP True/False
1977     BC1F, BC1FL :   Branch on FP False (L stands for branch likely)
1978     BC1T, BC1TL :   Branch on FP True  (L stands for branch likely)
1979 */
1980 bool EmulateInstructionMIPS64::Emulate_FP_branch(llvm::MCInst &insn) {
1981   bool success = false;
1982   uint32_t cc, fcsr;
1983   int64_t pc, offset, target = 0;
1984   const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1985 
1986   /*
1987    * BC1F cc, offset
1988    *  condition <- (FPConditionCode(cc) == 0)
1989    *      if condition then
1990    *          offset = sign_ext (offset)
1991    *          PC = PC + offset
1992   */
1993   cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1994   offset = insn.getOperand(1).getImm();
1995 
1996   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1997   if (!success)
1998     return false;
1999 
2000   fcsr =
2001       ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
2002   if (!success)
2003     return false;
2004 
2005   /* fcsr[23], fcsr[25-31] are vaild condition bits */
2006   fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2007 
2008   if (!strcasecmp(op_name, "BC1F") || !strcasecmp(op_name, "BC1FL")) {
2009     if ((fcsr & (1 << cc)) == 0)
2010       target = pc + offset;
2011     else
2012       target = pc + 8;
2013   } else if (!strcasecmp(op_name, "BC1T") || !strcasecmp(op_name, "BC1TL")) {
2014     if ((fcsr & (1 << cc)) != 0)
2015       target = pc + offset;
2016     else
2017       target = pc + 8;
2018   }
2019 
2020   Context context;
2021 
2022   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2023                                target);
2024 }
2025 
2026 bool EmulateInstructionMIPS64::Emulate_BC1EQZ(llvm::MCInst &insn) {
2027   bool success = false;
2028   uint32_t ft;
2029   uint64_t ft_val;
2030   int64_t target, pc, offset;
2031 
2032   /*
2033    * BC1EQZ ft, offset
2034    *  condition <- (FPR[ft].bit0 == 0)
2035    *      if condition then
2036    *          offset = sign_ext (offset)
2037    *          PC = PC + 4 + offset
2038   */
2039   ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2040   offset = insn.getOperand(1).getImm();
2041 
2042   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2043   if (!success)
2044     return false;
2045 
2046   ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0,
2047                                 &success);
2048   if (!success)
2049     return false;
2050 
2051   if ((ft_val & 1) == 0)
2052     target = pc + 4 + offset;
2053   else
2054     target = pc + 8;
2055 
2056   Context context;
2057 
2058   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2059                                target);
2060 }
2061 
2062 bool EmulateInstructionMIPS64::Emulate_BC1NEZ(llvm::MCInst &insn) {
2063   bool success = false;
2064   uint32_t ft;
2065   uint64_t ft_val;
2066   int64_t target, pc, offset;
2067 
2068   /*
2069    * BC1NEZ ft, offset
2070    *  condition <- (FPR[ft].bit0 != 0)
2071    *      if condition then
2072    *          offset = sign_ext (offset)
2073    *          PC = PC + 4 + offset
2074   */
2075   ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2076   offset = insn.getOperand(1).getImm();
2077 
2078   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2079   if (!success)
2080     return false;
2081 
2082   ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0,
2083                                 &success);
2084   if (!success)
2085     return false;
2086 
2087   if ((ft_val & 1) != 0)
2088     target = pc + 4 + offset;
2089   else
2090     target = pc + 8;
2091 
2092   Context context;
2093 
2094   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2095                                target);
2096 }
2097 
2098 /*
2099     Emulate MIPS-3D Branch instructions
2100     BC1ANY2F, BC1ANY2T  : Branch on Any of Two Floating Point Condition Codes
2101    False/True
2102     BC1ANY4F, BC1ANY4T  : Branch on Any of Four Floating Point Condition Codes
2103    False/True
2104 */
2105 bool EmulateInstructionMIPS64::Emulate_3D_branch(llvm::MCInst &insn) {
2106   bool success = false;
2107   uint32_t cc, fcsr;
2108   int64_t pc, offset, target = 0;
2109   const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
2110 
2111   cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2112   offset = insn.getOperand(1).getImm();
2113 
2114   pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2115   if (!success)
2116     return false;
2117 
2118   fcsr = (uint32_t)ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips64,
2119                                         0, &success);
2120   if (!success)
2121     return false;
2122 
2123   /* fcsr[23], fcsr[25-31] are vaild condition bits */
2124   fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2125 
2126   if (!strcasecmp(op_name, "BC1ANY2F")) {
2127     /* if any one bit is 0 */
2128     if (((fcsr >> cc) & 3) != 3)
2129       target = pc + offset;
2130     else
2131       target = pc + 8;
2132   } else if (!strcasecmp(op_name, "BC1ANY2T")) {
2133     /* if any one bit is 1 */
2134     if (((fcsr >> cc) & 3) != 0)
2135       target = pc + offset;
2136     else
2137       target = pc + 8;
2138   } else if (!strcasecmp(op_name, "BC1ANY4F")) {
2139     /* if any one bit is 0 */
2140     if (((fcsr >> cc) & 0xf) != 0xf)
2141       target = pc + offset;
2142     else
2143       target = pc + 8;
2144   } else if (!strcasecmp(op_name, "BC1ANY4T")) {
2145     /* if any one bit is 1 */
2146     if (((fcsr >> cc) & 0xf) != 0)
2147       target = pc + offset;
2148     else
2149       target = pc + 8;
2150   }
2151 
2152   Context context;
2153 
2154   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2155                                target);
2156 }
2157 
2158 bool EmulateInstructionMIPS64::Emulate_BNZB(llvm::MCInst &insn) {
2159   return Emulate_MSA_Branch_DF(insn, 1, true);
2160 }
2161 
2162 bool EmulateInstructionMIPS64::Emulate_BNZH(llvm::MCInst &insn) {
2163   return Emulate_MSA_Branch_DF(insn, 2, true);
2164 }
2165 
2166 bool EmulateInstructionMIPS64::Emulate_BNZW(llvm::MCInst &insn) {
2167   return Emulate_MSA_Branch_DF(insn, 4, true);
2168 }
2169 
2170 bool EmulateInstructionMIPS64::Emulate_BNZD(llvm::MCInst &insn) {
2171   return Emulate_MSA_Branch_DF(insn, 8, true);
2172 }
2173 
2174 bool EmulateInstructionMIPS64::Emulate_BZB(llvm::MCInst &insn) {
2175   return Emulate_MSA_Branch_DF(insn, 1, false);
2176 }
2177 
2178 bool EmulateInstructionMIPS64::Emulate_BZH(llvm::MCInst &insn) {
2179   return Emulate_MSA_Branch_DF(insn, 2, false);
2180 }
2181 
2182 bool EmulateInstructionMIPS64::Emulate_BZW(llvm::MCInst &insn) {
2183   return Emulate_MSA_Branch_DF(insn, 4, false);
2184 }
2185 
2186 bool EmulateInstructionMIPS64::Emulate_BZD(llvm::MCInst &insn) {
2187   return Emulate_MSA_Branch_DF(insn, 8, false);
2188 }
2189 
2190 bool EmulateInstructionMIPS64::Emulate_MSA_Branch_DF(llvm::MCInst &insn,
2191                                                      int element_byte_size,
2192                                                      bool bnz) {
2193   bool success = false, branch_hit = true;
2194   int64_t target = 0;
2195   RegisterValue reg_value;
2196   const uint8_t *ptr = nullptr;
2197 
2198   uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2199   int64_t offset = insn.getOperand(1).getImm();
2200 
2201   int64_t pc =
2202       ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2203   if (!success)
2204     return false;
2205 
2206   if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value))
2207     ptr = (const uint8_t *)reg_value.GetBytes();
2208   else
2209     return false;
2210 
2211   for (int i = 0; i < 16 / element_byte_size; i++) {
2212     switch (element_byte_size) {
2213     case 1:
2214       if ((*ptr == 0 && bnz) || (*ptr != 0 && !bnz))
2215         branch_hit = false;
2216       break;
2217     case 2:
2218       if ((*(const uint16_t *)ptr == 0 && bnz) ||
2219           (*(const uint16_t *)ptr != 0 && !bnz))
2220         branch_hit = false;
2221       break;
2222     case 4:
2223       if ((*(const uint32_t *)ptr == 0 && bnz) ||
2224           (*(const uint32_t *)ptr != 0 && !bnz))
2225         branch_hit = false;
2226       break;
2227     case 8:
2228       if ((*(const uint64_t *)ptr == 0 && bnz) ||
2229           (*(const uint64_t *)ptr != 0 && !bnz))
2230         branch_hit = false;
2231       break;
2232     }
2233     if (!branch_hit)
2234       break;
2235     ptr = ptr + element_byte_size;
2236   }
2237 
2238   if (branch_hit)
2239     target = pc + offset;
2240   else
2241     target = pc + 8;
2242 
2243   Context context;
2244   context.type = eContextRelativeBranchImmediate;
2245 
2246   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2247                                target);
2248 }
2249 
2250 bool EmulateInstructionMIPS64::Emulate_BNZV(llvm::MCInst &insn) {
2251   return Emulate_MSA_Branch_V(insn, true);
2252 }
2253 
2254 bool EmulateInstructionMIPS64::Emulate_BZV(llvm::MCInst &insn) {
2255   return Emulate_MSA_Branch_V(insn, false);
2256 }
2257 
2258 bool EmulateInstructionMIPS64::Emulate_MSA_Branch_V(llvm::MCInst &insn,
2259                                                     bool bnz) {
2260   bool success = false;
2261   int64_t target = 0;
2262   llvm::APInt wr_val = llvm::APInt::getNullValue(128);
2263   llvm::APInt fail_value = llvm::APInt::getMaxValue(128);
2264   llvm::APInt zero_value = llvm::APInt::getNullValue(128);
2265   RegisterValue reg_value;
2266 
2267   uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2268   int64_t offset = insn.getOperand(1).getImm();
2269 
2270   int64_t pc =
2271       ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2272   if (!success)
2273     return false;
2274 
2275   if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value))
2276     wr_val = reg_value.GetAsUInt128(fail_value);
2277   else
2278     return false;
2279 
2280   if ((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) ||
2281       (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz))
2282     target = pc + offset;
2283   else
2284     target = pc + 8;
2285 
2286   Context context;
2287   context.type = eContextRelativeBranchImmediate;
2288 
2289   return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2290                                target);
2291 }
2292 
2293 bool EmulateInstructionMIPS64::Emulate_LDST_Imm(llvm::MCInst &insn) {
2294   bool success = false;
2295   uint32_t base;
2296   int64_t imm, address;
2297   Context bad_vaddr_context;
2298 
2299   uint32_t num_operands = insn.getNumOperands();
2300   base =
2301       m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
2302   imm = insn.getOperand(num_operands - 1).getImm();
2303 
2304   RegisterInfo reg_info_base;
2305   if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base,
2306                        reg_info_base))
2307     return false;
2308 
2309   /* read base register */
2310   address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0,
2311                                  &success);
2312   if (!success)
2313     return false;
2314 
2315   /* destination address */
2316   address = address + imm;
2317 
2318   /* Set the bad_vaddr register with base address used in the instruction */
2319   bad_vaddr_context.type = eContextInvalid;
2320   WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
2321                         address);
2322 
2323   return true;
2324 }
2325 
2326 bool EmulateInstructionMIPS64::Emulate_LDST_Reg(llvm::MCInst &insn) {
2327   bool success = false;
2328   uint32_t base, index;
2329   int64_t address, index_address;
2330   Context bad_vaddr_context;
2331 
2332   uint32_t num_operands = insn.getNumOperands();
2333   base =
2334       m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
2335   index =
2336       m_reg_info->getEncodingValue(insn.getOperand(num_operands - 1).getReg());
2337 
2338   RegisterInfo reg_info_base, reg_info_index;
2339   if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base,
2340                        reg_info_base))
2341     return false;
2342 
2343   if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + index,
2344                        reg_info_index))
2345     return false;
2346 
2347   /* read base register */
2348   address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0,
2349                                  &success);
2350   if (!success)
2351     return false;
2352 
2353   /* read index register */
2354   index_address = ReadRegisterUnsigned(eRegisterKindDWARF,
2355                                        dwarf_zero_mips + index, 0, &success);
2356   if (!success)
2357     return false;
2358 
2359   /* destination address */
2360   address = address + index_address;
2361 
2362   /* Set the bad_vaddr register with base address used in the instruction */
2363   bad_vaddr_context.type = eContextInvalid;
2364   WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
2365                         address);
2366 
2367   return true;
2368 }
2369