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