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