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