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
41using namespace lldb;
42using namespace lldb_private;
43
44LLDB_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__
54extern "C" {
55void LLVMInitializeMipsTargetInfo();
56void LLVMInitializeMipsTarget();
57void LLVMInitializeMipsAsmPrinter();
58void LLVMInitializeMipsTargetMC();
59void LLVMInitializeMipsDisassembler();
60}
61#endif
62
63EmulateInstructionMIPS64::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
175void EmulateInstructionMIPS64::Initialize() {
176  PluginManager::RegisterPlugin(GetPluginNameStatic(),
177                                GetPluginDescriptionStatic(), CreateInstance);
178}
179
180void EmulateInstructionMIPS64::Terminate() {
181  PluginManager::UnregisterPlugin(CreateInstance);
182}
183
184llvm::StringRef EmulateInstructionMIPS64::GetPluginDescriptionStatic() {
185  return "Emulate instructions for the MIPS64 architecture.";
186}
187
188EmulateInstruction *
189EmulateInstructionMIPS64::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
202bool EmulateInstructionMIPS64::SetTargetTriple(const ArchSpec &arch) {
203  return arch.GetTriple().getArch() == llvm::Triple::mips64 ||
204         arch.GetTriple().getArch() == llvm::Triple::mips64el;
205}
206
207const 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
576std::optional<RegisterInfo>
577EmulateInstructionMIPS64::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
659EmulateInstructionMIPS64::MipsOpcode *
660EmulateInstructionMIPS64::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
931bool 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
948bool 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
1015bool 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
1042bool 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
1063bool 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
1127bool 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    std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);
1161    if (!data_src)
1162      return false;
1163
1164    Status error;
1165    RegisterValue::BytesContainer buffer(reg_info_src->byte_size);
1166    if (data_src->GetAsMemoryData(*reg_info_src, buffer.data(),
1167                                  reg_info_src->byte_size, eByteOrderLittle,
1168                                  error) == 0)
1169      return false;
1170
1171    if (!WriteMemory(context, address, buffer.data(), reg_info_src->byte_size))
1172      return false;
1173  }
1174
1175  /* Set the bad_vaddr register with base address used in the instruction */
1176  bad_vaddr_context.type = eContextInvalid;
1177  WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64,
1178                        address);
1179
1180  return true;
1181}
1182
1183bool EmulateInstructionMIPS64::Emulate_LD(llvm::MCInst &insn) {
1184  bool success = false;
1185  uint32_t src, base;
1186  int64_t imm, address;
1187  Context bad_vaddr_context;
1188
1189  src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1190  base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1191  imm = insn.getOperand(2).getImm();
1192
1193  if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base))
1194    return false;
1195
1196  /* read base register */
1197  address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + base,
1198                                 0, &success);
1199  if (!success)
1200    return false;
1201
1202  /* destination address */
1203  address = address + imm;
1204
1205  /* Set the bad_vaddr register with base address used in the instruction */
1206  bad_vaddr_context.type = eContextInvalid;
1207  WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64,
1208                        address);
1209
1210  if (nonvolatile_reg_p(src)) {
1211    RegisterValue data_src;
1212    std::optional<RegisterInfo> reg_info_src =
1213        GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src);
1214    if (!reg_info_src)
1215      return false;
1216
1217    Context context;
1218    context.type = eContextRegisterLoad;
1219
1220    return WriteRegister(context, *reg_info_src, data_src);
1221  }
1222
1223  return false;
1224}
1225
1226bool EmulateInstructionMIPS64::Emulate_LUI(llvm::MCInst &insn) {
1227  // LUI rt, immediate
1228  // GPR[rt] <- sign_extend(immediate << 16)
1229
1230  const uint32_t imm32 = insn.getOperand(1).getImm() << 16;
1231  int64_t imm = SignedBits(imm32, 31, 0);
1232  uint8_t rt;
1233  Context context;
1234
1235  rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1236  context.SetImmediateSigned(imm);
1237  context.type = eContextImmediate;
1238
1239  return WriteRegisterUnsigned(context, eRegisterKindDWARF,
1240                               dwarf_zero_mips64 + rt, imm);
1241}
1242
1243bool EmulateInstructionMIPS64::Emulate_DSUBU_DADDU(llvm::MCInst &insn) {
1244  // DSUBU sp, <src>, <rt>
1245  // DADDU sp, <src>, <rt>
1246  // DADDU dst, sp, <rt>
1247
1248  bool success = false;
1249  uint64_t result;
1250  uint8_t src, dst, rt;
1251  llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1252
1253  dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1254  src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1255
1256  /* Check if sp is destination register */
1257  if (dst == dwarf_sp_mips64) {
1258    rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1259
1260    /* read <src> register */
1261    uint64_t src_opd_val = ReadRegisterUnsigned(
1262        eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
1263    if (!success)
1264      return false;
1265
1266    /* read <rt > register */
1267    uint64_t rt_opd_val = ReadRegisterUnsigned(
1268        eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
1269    if (!success)
1270      return false;
1271
1272    if (op_name.equals_insensitive("DSUBU") ||
1273        op_name.equals_insensitive("SUBU"))
1274      result = src_opd_val - rt_opd_val;
1275    else
1276      result = src_opd_val + rt_opd_val;
1277
1278    Context context;
1279    std::optional<RegisterInfo> reg_info_sp =
1280        GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64);
1281    if (reg_info_sp)
1282      context.SetRegisterPlusOffset(*reg_info_sp, rt_opd_val);
1283
1284    /* We are allocating bytes on stack */
1285    context.type = eContextAdjustStackPointer;
1286
1287    WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips64, result);
1288
1289    return true;
1290  } else if (src == dwarf_sp_mips64) {
1291    rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1292
1293    /* read <src> register */
1294    uint64_t src_opd_val = ReadRegisterUnsigned(
1295        eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
1296    if (!success)
1297      return false;
1298
1299    /* read <rt> register */
1300    uint64_t rt_opd_val = ReadRegisterUnsigned(
1301        eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
1302    if (!success)
1303      return false;
1304
1305    Context context;
1306
1307    if (op_name.equals_insensitive("DSUBU") ||
1308        op_name.equals_insensitive("SUBU"))
1309      result = src_opd_val - rt_opd_val;
1310    else
1311      result = src_opd_val + rt_opd_val;
1312
1313    context.SetImmediateSigned(result);
1314    context.type = eContextImmediate;
1315
1316    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1317                               dwarf_zero_mips64 + dst, result))
1318      return false;
1319  }
1320
1321  return true;
1322}
1323
1324/*
1325    Emulate below MIPS branch instructions.
1326    BEQ, BNE : Branch on condition
1327    BEQL, BNEL : Branch likely
1328*/
1329bool EmulateInstructionMIPS64::Emulate_BXX_3ops(llvm::MCInst &insn) {
1330  bool success = false;
1331  uint32_t rs, rt;
1332  int64_t offset, pc, rs_val, rt_val, target = 0;
1333  llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1334
1335  rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1336  rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1337  offset = insn.getOperand(2).getImm();
1338
1339  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1340  if (!success)
1341    return false;
1342
1343  rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1344                                         dwarf_zero_mips64 + rs, 0, &success);
1345  if (!success)
1346    return false;
1347
1348  rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1349                                         dwarf_zero_mips64 + rt, 0, &success);
1350  if (!success)
1351    return false;
1352
1353  if (op_name.equals_insensitive("BEQ") || op_name.equals_insensitive("BEQL") ||
1354      op_name.equals_insensitive("BEQ64")) {
1355    if (rs_val == rt_val)
1356      target = pc + offset;
1357    else
1358      target = pc + 8;
1359  } else if (op_name.equals_insensitive("BNE") ||
1360             op_name.equals_insensitive("BNEL") ||
1361             op_name.equals_insensitive("BNE64")) {
1362    if (rs_val != rt_val)
1363      target = pc + offset;
1364    else
1365      target = pc + 8;
1366  }
1367
1368  Context context;
1369  context.type = eContextRelativeBranchImmediate;
1370  context.SetImmediate(offset);
1371
1372  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1373                               target);
1374}
1375
1376/*
1377    Emulate below MIPS Non-Compact conditional branch and link instructions.
1378    BLTZAL, BGEZAL      :
1379    BLTZALL, BGEZALL    : Branch likely
1380*/
1381bool EmulateInstructionMIPS64::Emulate_Bcond_Link(llvm::MCInst &insn) {
1382  bool success = false;
1383  uint32_t rs;
1384  int64_t offset, pc, target = 0;
1385  int64_t rs_val;
1386  llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1387
1388  rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1389  offset = insn.getOperand(1).getImm();
1390
1391  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1392  if (!success)
1393    return false;
1394
1395  rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1396                                         dwarf_zero_mips64 + rs, 0, &success);
1397  if (!success)
1398    return false;
1399
1400  if (op_name.equals_insensitive("BLTZAL") ||
1401      op_name.equals_insensitive("BLTZALL")) {
1402    if (rs_val < 0)
1403      target = pc + offset;
1404    else
1405      target = pc + 8;
1406  } else if (op_name.equals_insensitive("BGEZAL") ||
1407             op_name.equals_insensitive("BGEZALL")) {
1408    if (rs_val >= 0)
1409      target = pc + offset;
1410    else
1411      target = pc + 8;
1412  }
1413
1414  Context context;
1415
1416  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1417                             target))
1418    return false;
1419
1420  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1421                             pc + 8))
1422    return false;
1423
1424  return true;
1425}
1426
1427bool EmulateInstructionMIPS64::Emulate_BAL(llvm::MCInst &insn) {
1428  bool success = false;
1429  int64_t offset, pc, target;
1430
1431  /*
1432   * BAL offset
1433   *      offset = sign_ext (offset << 2)
1434   *      RA = PC + 8
1435   *      PC = PC + offset
1436  */
1437  offset = insn.getOperand(0).getImm();
1438
1439  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1440  if (!success)
1441    return false;
1442
1443  target = pc + offset;
1444
1445  Context context;
1446
1447  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1448                             target))
1449    return false;
1450
1451  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1452                             pc + 8))
1453    return false;
1454
1455  return true;
1456}
1457
1458bool EmulateInstructionMIPS64::Emulate_BALC(llvm::MCInst &insn) {
1459  bool success = false;
1460  int64_t offset, pc, target;
1461
1462  /*
1463   * BALC offset
1464   *      offset = sign_ext (offset << 2)
1465   *      RA = PC + 4
1466   *      PC = PC + 4 + offset
1467  */
1468  offset = insn.getOperand(0).getImm();
1469
1470  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1471  if (!success)
1472    return false;
1473
1474  target = pc + offset;
1475
1476  Context context;
1477
1478  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1479                             target))
1480    return false;
1481
1482  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1483                             pc + 4))
1484    return false;
1485
1486  return true;
1487}
1488
1489/*
1490    Emulate below MIPS conditional branch and link instructions.
1491    BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches
1492*/
1493bool EmulateInstructionMIPS64::Emulate_Bcond_Link_C(llvm::MCInst &insn) {
1494  bool success = false;
1495  uint32_t rs;
1496  int64_t offset, pc, rs_val, target = 0;
1497  llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1498
1499  rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1500  offset = insn.getOperand(1).getImm();
1501
1502  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1503  if (!success)
1504    return false;
1505
1506  rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1507                                         dwarf_zero_mips64 + rs, 0, &success);
1508  if (!success)
1509    return false;
1510
1511  if (op_name.equals_insensitive("BLEZALC")) {
1512    if (rs_val <= 0)
1513      target = pc + offset;
1514    else
1515      target = pc + 4;
1516  } else if (op_name.equals_insensitive("BGEZALC")) {
1517    if (rs_val >= 0)
1518      target = pc + offset;
1519    else
1520      target = pc + 4;
1521  } else if (op_name.equals_insensitive("BLTZALC")) {
1522    if (rs_val < 0)
1523      target = pc + offset;
1524    else
1525      target = pc + 4;
1526  } else if (op_name.equals_insensitive("BGTZALC")) {
1527    if (rs_val > 0)
1528      target = pc + offset;
1529    else
1530      target = pc + 4;
1531  } else if (op_name.equals_insensitive("BEQZALC")) {
1532    if (rs_val == 0)
1533      target = pc + offset;
1534    else
1535      target = pc + 4;
1536  } else if (op_name.equals_insensitive("BNEZALC")) {
1537    if (rs_val != 0)
1538      target = pc + offset;
1539    else
1540      target = pc + 4;
1541  }
1542
1543  Context context;
1544
1545  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1546                             target))
1547    return false;
1548
1549  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1550                             pc + 4))
1551    return false;
1552
1553  return true;
1554}
1555
1556/*
1557    Emulate below MIPS branch instructions.
1558    BLTZL, BGEZL, BGTZL, BLEZL : Branch likely
1559    BLTZ, BGEZ, BGTZ, BLEZ     : Non-compact branches
1560*/
1561bool EmulateInstructionMIPS64::Emulate_BXX_2ops(llvm::MCInst &insn) {
1562  bool success = false;
1563  uint32_t rs;
1564  int64_t offset, pc, rs_val, target = 0;
1565  llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1566
1567  rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1568  offset = insn.getOperand(1).getImm();
1569
1570  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1571  if (!success)
1572    return false;
1573
1574  rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1575                                         dwarf_zero_mips64 + rs, 0, &success);
1576  if (!success)
1577    return false;
1578
1579  if (op_name.equals_insensitive("BLTZL") ||
1580      op_name.equals_insensitive("BLTZ") ||
1581      op_name.equals_insensitive("BLTZ64")) {
1582    if (rs_val < 0)
1583      target = pc + offset;
1584    else
1585      target = pc + 8;
1586  } else if (op_name.equals_insensitive("BGEZL") ||
1587             op_name.equals_insensitive("BGEZ") ||
1588             op_name.equals_insensitive("BGEZ64")) {
1589    if (rs_val >= 0)
1590      target = pc + offset;
1591    else
1592      target = pc + 8;
1593  } else if (op_name.equals_insensitive("BGTZL") ||
1594             op_name.equals_insensitive("BGTZ") ||
1595             op_name.equals_insensitive("BGTZ64")) {
1596    if (rs_val > 0)
1597      target = pc + offset;
1598    else
1599      target = pc + 8;
1600  } else if (op_name.equals_insensitive("BLEZL") ||
1601             op_name.equals_insensitive("BLEZ") ||
1602             op_name.equals_insensitive("BLEZ64")) {
1603    if (rs_val <= 0)
1604      target = pc + offset;
1605    else
1606      target = pc + 8;
1607  }
1608
1609  Context context;
1610  context.type = eContextRelativeBranchImmediate;
1611  context.SetImmediate(offset);
1612
1613  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1614                               target);
1615}
1616
1617bool EmulateInstructionMIPS64::Emulate_BC(llvm::MCInst &insn) {
1618  bool success = false;
1619  int64_t offset, pc, target;
1620
1621  /*
1622   * BC offset
1623   *      offset = sign_ext (offset << 2)
1624   *      PC = PC + 4 + offset
1625  */
1626  offset = insn.getOperand(0).getImm();
1627
1628  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1629  if (!success)
1630    return false;
1631
1632  target = pc + offset;
1633
1634  Context context;
1635
1636  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1637                               target);
1638}
1639
1640static int IsAdd64bitOverflow(int64_t a, int64_t b) {
1641  int64_t r = (uint64_t)a + (uint64_t)b;
1642  return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
1643}
1644
1645/*
1646    Emulate below MIPS branch instructions.
1647    BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch
1648   instructions with no delay slot
1649*/
1650bool EmulateInstructionMIPS64::Emulate_BXX_3ops_C(llvm::MCInst &insn) {
1651  bool success = false;
1652  uint32_t rs, rt;
1653  int64_t offset, pc, rs_val, rt_val, target = 0;
1654  llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1655  uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
1656
1657  rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1658  rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1659  offset = insn.getOperand(2).getImm();
1660
1661  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1662  if (!success)
1663    return false;
1664
1665  rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1666                                         dwarf_zero_mips64 + rs, 0, &success);
1667  if (!success)
1668    return false;
1669
1670  rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1671                                         dwarf_zero_mips64 + rt, 0, &success);
1672  if (!success)
1673    return false;
1674
1675  if (op_name.equals_insensitive("BEQC") ||
1676      op_name.equals_insensitive("BEQC64")) {
1677    if (rs_val == rt_val)
1678      target = pc + offset;
1679    else
1680      target = pc + 4;
1681  } else if (op_name.equals_insensitive("BNEC") ||
1682             op_name.equals_insensitive("BNEC64")) {
1683    if (rs_val != rt_val)
1684      target = pc + offset;
1685    else
1686      target = pc + 4;
1687  } else if (op_name.equals_insensitive("BLTC") ||
1688             op_name.equals_insensitive("BLTC64")) {
1689    if (rs_val < rt_val)
1690      target = pc + offset;
1691    else
1692      target = pc + 4;
1693  } else if (op_name.equals_insensitive("BGEC64") ||
1694             op_name.equals_insensitive("BGEC")) {
1695    if (rs_val >= rt_val)
1696      target = pc + offset;
1697    else
1698      target = pc + 4;
1699  } else if (op_name.equals_insensitive("BLTUC") ||
1700             op_name.equals_insensitive("BLTUC64")) {
1701    if (rs_val < rt_val)
1702      target = pc + offset;
1703    else
1704      target = pc + 4;
1705  } else if (op_name.equals_insensitive("BGEUC") ||
1706             op_name.equals_insensitive("BGEUC64")) {
1707    if ((uint32_t)rs_val >= (uint32_t)rt_val)
1708      target = pc + offset;
1709    else
1710      target = pc + 4;
1711  } else if (op_name.equals_insensitive("BOVC")) {
1712    if (IsAdd64bitOverflow(rs_val, rt_val))
1713      target = pc + offset;
1714    else
1715      target = pc + 4;
1716  } else if (op_name.equals_insensitive("BNVC")) {
1717    if (!IsAdd64bitOverflow(rs_val, rt_val))
1718      target = pc + offset;
1719    else
1720      target = pc + 4;
1721  }
1722
1723  Context context;
1724  context.type = eContextRelativeBranchImmediate;
1725  context.SetImmediate(current_inst_size + offset);
1726
1727  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1728                               target);
1729}
1730
1731/*
1732    Emulate below MIPS branch instructions.
1733    BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches
1734*/
1735bool EmulateInstructionMIPS64::Emulate_BXX_2ops_C(llvm::MCInst &insn) {
1736  bool success = false;
1737  uint32_t rs;
1738  int64_t offset, pc, target = 0;
1739  int64_t rs_val;
1740  llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1741  uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
1742
1743  rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1744  offset = insn.getOperand(1).getImm();
1745
1746  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1747  if (!success)
1748    return false;
1749
1750  rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1751                                         dwarf_zero_mips64 + rs, 0, &success);
1752  if (!success)
1753    return false;
1754
1755  if (op_name.equals_insensitive("BLTZC") ||
1756      op_name.equals_insensitive("BLTZC64")) {
1757    if (rs_val < 0)
1758      target = pc + offset;
1759    else
1760      target = pc + 4;
1761  } else if (op_name.equals_insensitive("BLEZC") ||
1762             op_name.equals_insensitive("BLEZC64")) {
1763    if (rs_val <= 0)
1764      target = pc + offset;
1765    else
1766      target = pc + 4;
1767  } else if (op_name.equals_insensitive("BGEZC") ||
1768             op_name.equals_insensitive("BGEZC64")) {
1769    if (rs_val >= 0)
1770      target = pc + offset;
1771    else
1772      target = pc + 4;
1773  } else if (op_name.equals_insensitive("BGTZC") ||
1774             op_name.equals_insensitive("BGTZC64")) {
1775    if (rs_val > 0)
1776      target = pc + offset;
1777    else
1778      target = pc + 4;
1779  } else if (op_name.equals_insensitive("BEQZC") ||
1780             op_name.equals_insensitive("BEQZC64")) {
1781    if (rs_val == 0)
1782      target = pc + offset;
1783    else
1784      target = pc + 4;
1785  } else if (op_name.equals_insensitive("BNEZC") ||
1786             op_name.equals_insensitive("BNEZC64")) {
1787    if (rs_val != 0)
1788      target = pc + offset;
1789    else
1790      target = pc + 4;
1791  }
1792
1793  Context context;
1794  context.type = eContextRelativeBranchImmediate;
1795  context.SetImmediate(current_inst_size + offset);
1796
1797  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1798                               target);
1799}
1800
1801bool EmulateInstructionMIPS64::Emulate_J(llvm::MCInst &insn) {
1802  bool success = false;
1803  uint64_t offset, pc;
1804
1805  /*
1806   * J offset
1807   *      offset = sign_ext (offset << 2)
1808   *      PC = PC[63-28] | offset
1809  */
1810  offset = insn.getOperand(0).getImm();
1811
1812  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1813  if (!success)
1814    return false;
1815
1816  /* This is a PC-region branch and not PC-relative */
1817  pc = (pc & 0xFFFFFFFFF0000000ULL) | offset;
1818
1819  Context context;
1820
1821  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1822                               pc);
1823}
1824
1825bool EmulateInstructionMIPS64::Emulate_JAL(llvm::MCInst &insn) {
1826  bool success = false;
1827  uint64_t offset, target, pc;
1828
1829  /*
1830   * JAL offset
1831   *      offset = sign_ext (offset << 2)
1832   *      PC = PC[63-28] | offset
1833  */
1834  offset = insn.getOperand(0).getImm();
1835
1836  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1837  if (!success)
1838    return false;
1839
1840  /* This is a PC-region branch and not PC-relative */
1841  target = (pc & 0xFFFFFFFFF0000000ULL) | offset;
1842
1843  Context context;
1844
1845  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1846                             target))
1847    return false;
1848
1849  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1850                             pc + 8))
1851    return false;
1852
1853  return true;
1854}
1855
1856bool EmulateInstructionMIPS64::Emulate_JALR(llvm::MCInst &insn) {
1857  bool success = false;
1858  uint32_t rs, rt;
1859  uint64_t pc, rs_val;
1860
1861  /*
1862   * JALR rt, rs
1863   *      GPR[rt] = PC + 8
1864   *      PC = GPR[rs]
1865  */
1866  rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1867  rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1868
1869  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1870  if (!success)
1871    return false;
1872
1873  rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0,
1874                                &success);
1875  if (!success)
1876    return false;
1877
1878  Context context;
1879
1880  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1881                             rs_val))
1882    return false;
1883
1884  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1885                             dwarf_zero_mips64 + rt, pc + 8))
1886    return false;
1887
1888  return true;
1889}
1890
1891bool EmulateInstructionMIPS64::Emulate_JIALC(llvm::MCInst &insn) {
1892  bool success = false;
1893  uint32_t rt;
1894  int64_t target, offset, pc, rt_val;
1895
1896  /*
1897   * JIALC rt, offset
1898   *      offset = sign_ext (offset)
1899   *      PC = GPR[rt] + offset
1900   *      RA = PC + 4
1901  */
1902  rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1903  offset = insn.getOperand(1).getImm();
1904
1905  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1906  if (!success)
1907    return false;
1908
1909  rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1910                                         dwarf_zero_mips64 + rt, 0, &success);
1911  if (!success)
1912    return false;
1913
1914  target = rt_val + offset;
1915
1916  Context context;
1917
1918  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1919                             target))
1920    return false;
1921
1922  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1923                             pc + 4))
1924    return false;
1925
1926  return true;
1927}
1928
1929bool EmulateInstructionMIPS64::Emulate_JIC(llvm::MCInst &insn) {
1930  bool success = false;
1931  uint32_t rt;
1932  int64_t target, offset, rt_val;
1933
1934  /*
1935   * JIC rt, offset
1936   *      offset = sign_ext (offset)
1937   *      PC = GPR[rt] + offset
1938  */
1939  rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1940  offset = insn.getOperand(1).getImm();
1941
1942  rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1943                                         dwarf_zero_mips64 + rt, 0, &success);
1944  if (!success)
1945    return false;
1946
1947  target = rt_val + offset;
1948
1949  Context context;
1950
1951  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1952                               target);
1953}
1954
1955bool EmulateInstructionMIPS64::Emulate_JR(llvm::MCInst &insn) {
1956  bool success = false;
1957  uint32_t rs;
1958  uint64_t rs_val;
1959
1960  /*
1961   * JR rs
1962   *      PC = GPR[rs]
1963  */
1964  rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1965
1966  rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0,
1967                                &success);
1968  if (!success)
1969    return false;
1970
1971  Context context;
1972
1973  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1974                               rs_val);
1975}
1976
1977/*
1978    Emulate Branch on FP True/False
1979    BC1F, BC1FL :   Branch on FP False (L stands for branch likely)
1980    BC1T, BC1TL :   Branch on FP True  (L stands for branch likely)
1981*/
1982bool EmulateInstructionMIPS64::Emulate_FP_branch(llvm::MCInst &insn) {
1983  bool success = false;
1984  uint32_t cc, fcsr;
1985  int64_t pc, offset, target = 0;
1986  llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1987
1988  /*
1989   * BC1F cc, offset
1990   *  condition <- (FPConditionCode(cc) == 0)
1991   *      if condition then
1992   *          offset = sign_ext (offset)
1993   *          PC = PC + offset
1994  */
1995  cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1996  offset = insn.getOperand(1).getImm();
1997
1998  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1999  if (!success)
2000    return false;
2001
2002  fcsr =
2003      ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
2004  if (!success)
2005    return false;
2006
2007  /* fcsr[23], fcsr[25-31] are vaild condition bits */
2008  fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2009
2010  if (op_name.equals_insensitive("BC1F") ||
2011      op_name.equals_insensitive("BC1FL")) {
2012    if ((fcsr & (1 << cc)) == 0)
2013      target = pc + offset;
2014    else
2015      target = pc + 8;
2016  } else if (op_name.equals_insensitive("BC1T") ||
2017             op_name.equals_insensitive("BC1TL")) {
2018    if ((fcsr & (1 << cc)) != 0)
2019      target = pc + offset;
2020    else
2021      target = pc + 8;
2022  }
2023
2024  Context context;
2025
2026  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2027                               target);
2028}
2029
2030bool EmulateInstructionMIPS64::Emulate_BC1EQZ(llvm::MCInst &insn) {
2031  bool success = false;
2032  uint32_t ft;
2033  uint64_t ft_val;
2034  int64_t target, pc, offset;
2035
2036  /*
2037   * BC1EQZ ft, offset
2038   *  condition <- (FPR[ft].bit0 == 0)
2039   *      if condition then
2040   *          offset = sign_ext (offset)
2041   *          PC = PC + 4 + offset
2042  */
2043  ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2044  offset = insn.getOperand(1).getImm();
2045
2046  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2047  if (!success)
2048    return false;
2049
2050  ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0,
2051                                &success);
2052  if (!success)
2053    return false;
2054
2055  if ((ft_val & 1) == 0)
2056    target = pc + 4 + offset;
2057  else
2058    target = pc + 8;
2059
2060  Context context;
2061
2062  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2063                               target);
2064}
2065
2066bool EmulateInstructionMIPS64::Emulate_BC1NEZ(llvm::MCInst &insn) {
2067  bool success = false;
2068  uint32_t ft;
2069  uint64_t ft_val;
2070  int64_t target, pc, offset;
2071
2072  /*
2073   * BC1NEZ ft, offset
2074   *  condition <- (FPR[ft].bit0 != 0)
2075   *      if condition then
2076   *          offset = sign_ext (offset)
2077   *          PC = PC + 4 + offset
2078  */
2079  ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2080  offset = insn.getOperand(1).getImm();
2081
2082  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2083  if (!success)
2084    return false;
2085
2086  ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0,
2087                                &success);
2088  if (!success)
2089    return false;
2090
2091  if ((ft_val & 1) != 0)
2092    target = pc + 4 + offset;
2093  else
2094    target = pc + 8;
2095
2096  Context context;
2097
2098  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2099                               target);
2100}
2101
2102/*
2103    Emulate MIPS-3D Branch instructions
2104    BC1ANY2F, BC1ANY2T  : Branch on Any of Two Floating Point Condition Codes
2105   False/True
2106    BC1ANY4F, BC1ANY4T  : Branch on Any of Four Floating Point Condition Codes
2107   False/True
2108*/
2109bool EmulateInstructionMIPS64::Emulate_3D_branch(llvm::MCInst &insn) {
2110  bool success = false;
2111  uint32_t cc, fcsr;
2112  int64_t pc, offset, target = 0;
2113  llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2114
2115  cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2116  offset = insn.getOperand(1).getImm();
2117
2118  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2119  if (!success)
2120    return false;
2121
2122  fcsr = (uint32_t)ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips64,
2123                                        0, &success);
2124  if (!success)
2125    return false;
2126
2127  /* fcsr[23], fcsr[25-31] are vaild condition bits */
2128  fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2129
2130  if (op_name.equals_insensitive("BC1ANY2F")) {
2131    /* if any one bit is 0 */
2132    if (((fcsr >> cc) & 3) != 3)
2133      target = pc + offset;
2134    else
2135      target = pc + 8;
2136  } else if (op_name.equals_insensitive("BC1ANY2T")) {
2137    /* if any one bit is 1 */
2138    if (((fcsr >> cc) & 3) != 0)
2139      target = pc + offset;
2140    else
2141      target = pc + 8;
2142  } else if (op_name.equals_insensitive("BC1ANY4F")) {
2143    /* if any one bit is 0 */
2144    if (((fcsr >> cc) & 0xf) != 0xf)
2145      target = pc + offset;
2146    else
2147      target = pc + 8;
2148  } else if (op_name.equals_insensitive("BC1ANY4T")) {
2149    /* if any one bit is 1 */
2150    if (((fcsr >> cc) & 0xf) != 0)
2151      target = pc + offset;
2152    else
2153      target = pc + 8;
2154  }
2155
2156  Context context;
2157
2158  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2159                               target);
2160}
2161
2162bool EmulateInstructionMIPS64::Emulate_BNZB(llvm::MCInst &insn) {
2163  return Emulate_MSA_Branch_DF(insn, 1, true);
2164}
2165
2166bool EmulateInstructionMIPS64::Emulate_BNZH(llvm::MCInst &insn) {
2167  return Emulate_MSA_Branch_DF(insn, 2, true);
2168}
2169
2170bool EmulateInstructionMIPS64::Emulate_BNZW(llvm::MCInst &insn) {
2171  return Emulate_MSA_Branch_DF(insn, 4, true);
2172}
2173
2174bool EmulateInstructionMIPS64::Emulate_BNZD(llvm::MCInst &insn) {
2175  return Emulate_MSA_Branch_DF(insn, 8, true);
2176}
2177
2178bool EmulateInstructionMIPS64::Emulate_BZB(llvm::MCInst &insn) {
2179  return Emulate_MSA_Branch_DF(insn, 1, false);
2180}
2181
2182bool EmulateInstructionMIPS64::Emulate_BZH(llvm::MCInst &insn) {
2183  return Emulate_MSA_Branch_DF(insn, 2, false);
2184}
2185
2186bool EmulateInstructionMIPS64::Emulate_BZW(llvm::MCInst &insn) {
2187  return Emulate_MSA_Branch_DF(insn, 4, false);
2188}
2189
2190bool EmulateInstructionMIPS64::Emulate_BZD(llvm::MCInst &insn) {
2191  return Emulate_MSA_Branch_DF(insn, 8, false);
2192}
2193
2194bool EmulateInstructionMIPS64::Emulate_MSA_Branch_DF(llvm::MCInst &insn,
2195                                                     int element_byte_size,
2196                                                     bool bnz) {
2197  bool success = false, branch_hit = true;
2198  int64_t target = 0;
2199  RegisterValue reg_value;
2200  const uint8_t *ptr = nullptr;
2201
2202  uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2203  int64_t offset = insn.getOperand(1).getImm();
2204
2205  int64_t pc =
2206      ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2207  if (!success)
2208    return false;
2209
2210  if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value))
2211    ptr = (const uint8_t *)reg_value.GetBytes();
2212  else
2213    return false;
2214
2215  for (int i = 0; i < 16 / element_byte_size; i++) {
2216    switch (element_byte_size) {
2217    case 1:
2218      if ((*ptr == 0 && bnz) || (*ptr != 0 && !bnz))
2219        branch_hit = false;
2220      break;
2221    case 2:
2222      if ((*(const uint16_t *)ptr == 0 && bnz) ||
2223          (*(const uint16_t *)ptr != 0 && !bnz))
2224        branch_hit = false;
2225      break;
2226    case 4:
2227      if ((*(const uint32_t *)ptr == 0 && bnz) ||
2228          (*(const uint32_t *)ptr != 0 && !bnz))
2229        branch_hit = false;
2230      break;
2231    case 8:
2232      if ((*(const uint64_t *)ptr == 0 && bnz) ||
2233          (*(const uint64_t *)ptr != 0 && !bnz))
2234        branch_hit = false;
2235      break;
2236    }
2237    if (!branch_hit)
2238      break;
2239    ptr = ptr + element_byte_size;
2240  }
2241
2242  if (branch_hit)
2243    target = pc + offset;
2244  else
2245    target = pc + 8;
2246
2247  Context context;
2248  context.type = eContextRelativeBranchImmediate;
2249
2250  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2251                               target);
2252}
2253
2254bool EmulateInstructionMIPS64::Emulate_BNZV(llvm::MCInst &insn) {
2255  return Emulate_MSA_Branch_V(insn, true);
2256}
2257
2258bool EmulateInstructionMIPS64::Emulate_BZV(llvm::MCInst &insn) {
2259  return Emulate_MSA_Branch_V(insn, false);
2260}
2261
2262bool EmulateInstructionMIPS64::Emulate_MSA_Branch_V(llvm::MCInst &insn,
2263                                                    bool bnz) {
2264  bool success = false;
2265  int64_t target = 0;
2266  llvm::APInt wr_val = llvm::APInt::getZero(128);
2267  llvm::APInt fail_value = llvm::APInt::getMaxValue(128);
2268  llvm::APInt zero_value = llvm::APInt::getZero(128);
2269  RegisterValue reg_value;
2270
2271  uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2272  int64_t offset = insn.getOperand(1).getImm();
2273
2274  int64_t pc =
2275      ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2276  if (!success)
2277    return false;
2278
2279  if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value))
2280    wr_val = reg_value.GetAsUInt128(fail_value);
2281  else
2282    return false;
2283
2284  if ((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) ||
2285      (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz))
2286    target = pc + offset;
2287  else
2288    target = pc + 8;
2289
2290  Context context;
2291  context.type = eContextRelativeBranchImmediate;
2292
2293  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2294                               target);
2295}
2296
2297bool EmulateInstructionMIPS64::Emulate_LDST_Imm(llvm::MCInst &insn) {
2298  bool success = false;
2299  uint32_t base;
2300  int64_t imm, address;
2301  Context bad_vaddr_context;
2302
2303  uint32_t num_operands = insn.getNumOperands();
2304  base =
2305      m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
2306  imm = insn.getOperand(num_operands - 1).getImm();
2307
2308  if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))
2309    return false;
2310
2311  /* read base register */
2312  address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0,
2313                                 &success);
2314  if (!success)
2315    return false;
2316
2317  /* destination address */
2318  address = address + imm;
2319
2320  /* Set the bad_vaddr register with base address used in the instruction */
2321  bad_vaddr_context.type = eContextInvalid;
2322  WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
2323                        address);
2324
2325  return true;
2326}
2327
2328bool EmulateInstructionMIPS64::Emulate_LDST_Reg(llvm::MCInst &insn) {
2329  bool success = false;
2330  uint32_t base, index;
2331  int64_t address, index_address;
2332  Context bad_vaddr_context;
2333
2334  uint32_t num_operands = insn.getNumOperands();
2335  base =
2336      m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
2337  index =
2338      m_reg_info->getEncodingValue(insn.getOperand(num_operands - 1).getReg());
2339
2340  if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))
2341    return false;
2342
2343  if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + index))
2344    return false;
2345
2346  /* read base register */
2347  address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0,
2348                                 &success);
2349  if (!success)
2350    return false;
2351
2352  /* read index register */
2353  index_address = ReadRegisterUnsigned(eRegisterKindDWARF,
2354                                       dwarf_zero_mips + index, 0, &success);
2355  if (!success)
2356    return false;
2357
2358  /* destination address */
2359  address = address + index_address;
2360
2361  /* Set the bad_vaddr register with base address used in the instruction */
2362  bad_vaddr_context.type = eContextInvalid;
2363  WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
2364                        address);
2365
2366  return true;
2367}
2368