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