LLDB  mainline
EmulateInstructionMIPS64.cpp
Go to the documentation of this file.
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 
10 
11 #include <stdlib.h>
12 
13 #include "lldb/Core/Address.h"
14 #include "lldb/Core/Opcode.h"
16 #include "lldb/Host/PosixApi.h"
17 #include "lldb/Symbol/UnwindPlan.h"
18 #include "lldb/Utility/ArchSpec.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 
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 
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 
170  PluginManager::RegisterPlugin(GetPluginNameStatic(),
172 }
173 
175  PluginManager::UnregisterPlugin(CreateInstance);
176 }
177 
179  ConstString g_plugin_name("lldb.emulate-instruction.mips64");
180  return g_plugin_name;
181 }
182 
184  static ConstString g_plugin_name("EmulateInstructionMIPS64");
185  return g_plugin_name;
186 }
187 
189  return "Emulate instructions for the MIPS64 architecture.";
190 }
191 
194  InstructionType inst_type) {
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 NULL;
204 }
205 
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";
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";
575  return "config5";
576  }
577  return nullptr;
578 }
579 
581  uint32_t reg_num,
582  RegisterInfo &reg_info) {
583  if (reg_kind == eRegisterKindGeneric) {
584  switch (reg_num) {
586  reg_kind = eRegisterKindDWARF;
587  reg_num = dwarf_pc_mips64;
588  break;
590  reg_kind = eRegisterKindDWARF;
591  reg_num = dwarf_sp_mips64;
592  break;
594  reg_kind = eRegisterKindDWARF;
595  reg_num = dwarf_r30_mips64;
596  break;
598  reg_kind = eRegisterKindDWARF;
599  reg_num = dwarf_ra_mips64;
600  break;
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:
641  break;
642  case dwarf_ra_mips64:
644  break;
645  case dwarf_sp_mips64:
647  break;
648  case dwarf_pc_mips64:
650  break;
651  case dwarf_sr_mips64:
653  break;
654  default:
655  break;
656  }
657  return true;
658  }
659  return false;
660 }
661 
664  static EmulateInstructionMIPS64::MipsOpcode g_opcodes[] = {
665  // Prologue/Epilogue instructions
667  "DADDIU rt, rs, immediate"},
669  "ADDIU rt, rs, immediate"},
670  {"SD", &EmulateInstructionMIPS64::Emulate_SD, "SD rt, offset(rs)"},
671  {"LD", &EmulateInstructionMIPS64::Emulate_LD, "LD rt, offset(base)"},
673  "DSUBU rd, rs, rt"},
675  "SUBU rd, rs, rt"},
677  "DADDU rd, rs, rt"},
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 
691  "LB rt, offset(base)"},
693  "LBE rt, offset(base)"},
695  "LBU rt, offset(base)"},
697  "LBUE rt, offset(base)"},
699  "LDC1 ft, offset(base)"},
701  "LDL rt, offset(base)"},
703  "LDR rt, offset(base)"},
705  "LLD rt, offset(base)"},
707  "LDC2 rt, offset(base)"},
709  "LDXC1 fd, index (base)"},
711  "LH rt, offset(base)"},
713  "LHE rt, offset(base)"},
715  "LHU rt, offset(base)"},
717  "LHUE rt, offset(base)"},
719  "LL rt, offset(base)"},
721  "LLE rt, offset(base)"},
723  "LUXC1 fd, index (base)"},
725  "LW rt, offset(rs)"},
727  "LWC1 ft, offset(base)"},
729  "LWC2 rt, offset(base)"},
731  "LWE rt, offset(base)"},
733  "LWL rt, offset(base)"},
735  "LWLE rt, offset(base)"},
737  "LWR rt, offset(base)"},
739  "LWRE rt, offset(base)"},
741  "LWXC1 fd, index (base)"},
742 
744  "SB rt, offset(base)"},
746  "SBE rt, offset(base)"},
748  "SC rt, offset(base)"},
750  "SCE rt, offset(base)"},
752  "SCD rt, offset(base)"},
754  "SDL rt, offset(base)"},
756  "SDR rt, offset(base)"},
758  "SDC1 ft, offset(base)"},
760  "SDC2 rt, offset(base)"},
762  "SDXC1 fs, index (base)"},
764  "SH rt, offset(base)"},
766  "SHE rt, offset(base)"},
768  "SUXC1 fs, index (base)"},
770  "SW rt, offset(rs)"},
772  "SWC1 ft, offset(base)"},
774  "SWC2 rt, offset(base)"},
776  "SWE rt, offset(base)"},
778  "SWL rt, offset(base)"},
780  "SWLE rt, offset(base)"},
782  "SWR rt, offset(base)"},
784  "SWRE rt, offset(base)"},
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"},
794  "BEQL rs,rt,offset"},
796  "BNEL rs,rt,offset"},
798  "BGEZALL rt,offset"},
799  {"BAL", &EmulateInstructionMIPS64::Emulate_BAL, "BAL offset"},
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"},
807  "BLEZALC rs,offset"},
809  "BGEZALC rs,offset"},
811  "BLTZALC rs,offset"},
813  "BGTZALC rs,offset"},
815  "BEQZALC rs,offset"},
817  "BNEZALC rs,offset"},
819  "BEQC rs,rt,offset"},
821  "BEQC rs,rt,offset"},
823  "BNEC rs,rt,offset"},
825  "BNEC rs,rt,offset"},
827  "BLTC rs,rt,offset"},
829  "BLTC rs,rt,offset"},
831  "BGEC rs,rt,offset"},
833  "BGEC rs,rt,offset"},
835  "BLTUC rs,rt,offset"},
837  "BLTUC rs,rt,offset"},
839  "BGEUC rs,rt,offset"},
841  "BGEUC rs,rt,offset"},
843  "BLTZC rt,offset"},
845  "BLTZC rt,offset"},
847  "BLEZC rt,offset"},
849  "BLEZC rt,offset"},
851  "BGEZC rt,offset"},
853  "BGEZC rt,offset"},
855  "BGTZC rt,offset"},
857  "BGTZC rt,offset"},
859  "BEQZC rt,offset"},
861  "BEQZC rt,offset"},
863  "BNEZC rt,offset"},
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"},
876  "BLTZAL rt,offset"},
878  "BLTZALL rt,offset"},
879  {"BLTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZL rt,offset"},
881  "BOVC rs,rt,offset"},
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"},
900  "BC1FL cc, offset"},
902  "BC1TL cc, offset"},
904  "BC1EQZ ft, offset"},
906  "BC1NEZ ft, offset"},
908  "BC1ANY2F cc, offset"},
910  "BC1ANY2T cc, offset"},
912  "BC1ANY4F cc, offset"},
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 NULL;
935 }
936 
938  bool success = false;
940  LLDB_INVALID_ADDRESS, &success);
941  if (success) {
942  Context read_inst_context;
943  read_inst_context.type = eContextReadOpcode;
944  read_inst_context.SetNoArgs();
946  ReadMemoryUnsigned(read_inst_context, m_addr, 4, 0, &success),
947  GetByteOrder());
948  }
949  if (!success)
951  return success;
952 }
953 
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 == NULL)
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 == NULL)
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 =
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 =
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;
1016  new_pc))
1017  return false;
1018  }
1019  }
1020 
1021  return true;
1022 }
1023 
1025  UnwindPlan &unwind_plan) {
1026  unwind_plan.Clear();
1027  unwind_plan.SetRegisterKind(eRegisterKindDWARF);
1028 
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);
1046 
1047  return true;
1048 }
1049 
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 
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 
1113  context.SetRegisterPlusOffset(reg_info_sp, imm);
1114 
1115  /* We are allocating bytes on stack */
1116  context.type = eContextAdjustStackPointer;
1117 
1119  result);
1120  return true;
1121  }
1122 
1123  imm += src_opd_val;
1124  context.SetImmediateSigned(imm);
1125  context.type = eContextImmediate;
1126 
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 
1149  reg_info_base) ||
1151  reg_info_src))
1152  return false;
1153 
1154  /* read SP */
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;
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;
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;
1204  reg_info_base))
1205  return false;
1206 
1207  /* read base register */
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;
1219  address);
1220 
1221  if (nonvolatile_reg_p(src)) {
1222  RegisterValue data_src;
1223  RegisterInfo reg_info_src;
1224 
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 
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;
1292  context.SetRegisterPlusOffset(reg_info_sp, rt_opd_val);
1293 
1294  /* We are allocating bytes on stack */
1295  context.type = eContextAdjustStackPointer;
1296 
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 
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 */
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 
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;
1378  context.SetImmediate(offset);
1379 
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 */
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 
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 
1424  target))
1425  return false;
1426 
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 
1447  if (!success)
1448  return false;
1449 
1450  target = pc + offset;
1451 
1452  Context context;
1453 
1455  target))
1456  return false;
1457 
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 
1478  if (!success)
1479  return false;
1480 
1481  target = pc + offset;
1482 
1483  Context context;
1484 
1486  target))
1487  return false;
1488 
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 */
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 
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 
1553  target))
1554  return false;
1555 
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 */
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 
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;
1614  context.SetImmediate(offset);
1615 
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 
1632  if (!success)
1633  return false;
1634 
1635  target = pc + offset;
1636 
1637  Context context;
1638 
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 */
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 
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;
1722  context.SetImmediate(current_inst_size + offset);
1723 
1725  target);
1726 }
1727 
1728 /*
1729  Emulate below MIPS branch instructions.
1730  BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches
1731 */
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 
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;
1786  context.SetImmediate(current_inst_size + offset);
1787 
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 
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 
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 
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 
1837  target))
1838  return false;
1839 
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 
1861  if (!success)
1862  return false;
1863 
1865  &success);
1866  if (!success)
1867  return false;
1868 
1869  Context context;
1870 
1872  rs_val))
1873  return false;
1874 
1876  dwarf_zero_mips64 + rt, pc + 8))
1877  return false;
1878 
1879  return true;
1880 }
1881 
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 
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 
1910  target))
1911  return false;
1912 
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 
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 
1958  &success);
1959  if (!success)
1960  return false;
1961 
1962  Context context;
1963 
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 */
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 
1990  if (!success)
1991  return false;
1992 
1993  fcsr =
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 
2016  target);
2017 }
2018 
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 
2036  if (!success)
2037  return false;
2038 
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 
2052  target);
2053 }
2054 
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 
2072  if (!success)
2073  return false;
2074 
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 
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 */
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 
2108  if (!success)
2109  return false;
2110 
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 
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 
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 = NULL;
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 =
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;
2238 
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 
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 =
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;
2281 
2283  target);
2284 }
2285 
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;
2299  reg_info_base))
2300  return false;
2301 
2302  /* read base register */
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;
2314  address);
2315 
2316  return true;
2317 }
2318 
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;
2333  reg_info_base))
2334  return false;
2335 
2337  reg_info_index))
2338  return false;
2339 
2340  /* read base register */
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;
2358  address);
2359 
2360  return true;
2361 }
bool Emulate_MSA_Branch_V(llvm::MCInst &insn, bool bnz)
uint32_t GetFlags() const
Definition: ArchSpec.h:501
#define LLDB_REGNUM_GENERIC_PC
Definition: lldb-defines.h:63
An data extractor class.
Definition: DataExtractor.h:47
bool ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value)
Core GetCore() const
Definition: ArchSpec.h:410
void SetSourceName(const char *)
Definition: UnwindPlan.cpp:542
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
uint64_t ReadRegisterUnsigned(const RegisterInfo *reg_info, uint64_t fail_value, bool *success_ptr)
bool GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num, lldb_private::RegisterInfo &reg_info) override
void SetImmediateSigned(int64_t signed_immediate)
#define LLDB_REGNUM_GENERIC_RA
Definition: lldb-defines.h:66
bool WriteRegister(const Context &context, const RegisterInfo *ref_info, const RegisterValue &reg_value)
bool Emulate_JR(llvm::MCInst &insn)
bool EvaluateInstruction(uint32_t evaluate_options) override
uint32_t GetAsMemoryData(const RegisterInfo *reg_info, void *dst, uint32_t dst_len, lldb::ByteOrder dst_byte_order, Status &error) const
lldb::ByteOrder GetByteOrder() const
static bool SupportsEmulatingInstructionsOfTypeStatic(lldb_private::InstructionType inst_type)
static lldb_private::EmulateInstruction * CreateInstance(const lldb_private::ArchSpec &arch, lldb_private::InstructionType inst_type)
An architecture specification class.
Definition: ArchSpec.h:32
static int IsAdd64bitOverflow(int64_t a, int64_t b)
lldb_private::ConstString GetPluginName() override
bool Emulate_J(llvm::MCInst &insn)
uint32_t GetData(DataExtractor &data) const
Definition: Opcode.cpp:81
bool nonvolatile_reg_p(uint64_t regnum)
#define LLDB_REGNUM_GENERIC_SP
Definition: lldb-defines.h:64
bool Emulate_DADDiu(llvm::MCInst &insn)
bool Emulate_SD(llvm::MCInst &insn)
"lldb/Core/EmulateInstruction.h" A class that allows emulation of CPU opcodes.
uint64_t ReadMemoryUnsigned(const Context &context, lldb::addr_t addr, size_t byte_size, uint64_t fail_value, bool *success_ptr)
bool Emulate_BZB(llvm::MCInst &insn)
bool WriteMemory(const Context &context, lldb::addr_t addr, const void *src, size_t src_len)
bool Emulate_BZH(llvm::MCInst &insn)
bool Emulate_LD(llvm::MCInst &insn)
bool Emulate_BC(llvm::MCInst &insn)
EmulateInstructionMIPS64(const lldb_private::ArchSpec &arch)
static MipsOpcode * GetOpcodeForInstruction(const char *op_name)
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:431
bool Emulate_BZW(llvm::MCInst &insn)
bool SetTargetTriple(const lldb_private::ArchSpec &arch) override
bool Emulate_BXX_2ops(llvm::MCInst &insn)
bool CreateFunctionEntryUnwind(lldb_private::UnwindPlan &unwind_plan) override
#define LLDB_REGNUM_GENERIC_FP
Definition: lldb-defines.h:65
void SetRegisterPlusOffset(RegisterInfo base_reg, int64_t signed_offset)
#define LLDB_INVALID_ADDRESS
Invalid value definitions.
Definition: lldb-defines.h:85
bool Emulate_BZV(llvm::MCInst &insn)
std::shared_ptr< Row > RowSP
Definition: UnwindPlan.h:366
void AppendRow(const RowSP &row_sp)
Definition: UnwindPlan.cpp:355
bool Emulate_BNZB(llvm::MCInst &insn)
bool Emulate_JALR(llvm::MCInst &insn)
void SetRegisterToRegisterPlusOffset(RegisterInfo data_reg, RegisterInfo base_reg, int64_t offset)
bool Emulate_BNZV(llvm::MCInst &insn)
const void * GetBytes() const
#define LLDB_REGNUM_GENERIC_FLAGS
Definition: lldb-defines.h:67
bool Emulate_3D_branch(llvm::MCInst &insn)
void SetRegisterKind(lldb::RegisterKind kind)
Definition: UnwindPlan.h:408
void SetOpcode32(uint32_t inst, lldb::ByteOrder order)
Definition: Opcode.h:176
bool Emulate_BC1EQZ(llvm::MCInst &insn)
bool Emulate_BXX_3ops(llvm::MCInst &insn)
bool Emulate_JIC(llvm::MCInst &insn)
bool Emulate_MSA_Branch_DF(llvm::MCInst &insn, int element_byte_size, bool bnz)
InstructionType
Instruction types.
bool Emulate_Bcond_Link_C(llvm::MCInst &insn)
uint64_t GetByteSize() const
Get the number of bytes contained in this object.
bool Emulate_BNZH(llvm::MCInst &insn)
bool Emulate_BXX_2ops_C(llvm::MCInst &insn)
void SetUnwindPlanValidAtAllInstructions(lldb_private::LazyBool valid_at_all_insn)
Definition: UnwindPlan.h:461
static lldb_private::ConstString GetPluginNameStatic()
bool Emulate_LUI(llvm::MCInst &insn)
bool Emulate_BALC(llvm::MCInst &insn)
const uint8_t * GetDataStart() const
Get the data start pointer.
A uniqued constant string class.
Definition: ConstString.h:38
bool Emulate_BNZW(llvm::MCInst &insn)
bool Emulate_JAL(llvm::MCInst &insn)
bool Emulate_FP_branch(llvm::MCInst &insn)
Definition: SBAddress.h:15
bool Emulate_BXX_3ops_C(llvm::MCInst &insn)
bool Emulate_JIALC(llvm::MCInst &insn)
int strcasecmp(const char *s1, const char *s2)
llvm::APInt GetAsUInt128(const llvm::APInt &fail_value, bool *success_ptr=nullptr) const
bool WriteRegisterUnsigned(const Context &context, const RegisterInfo *reg_info, uint64_t reg_value)
bool(EmulateInstructionMIPS64::* callback)(llvm::MCInst &insn)
bool Emulate_BAL(llvm::MCInst &insn)
bool Emulate_LDST_Imm(llvm::MCInst &insn)
bool Emulate_LDST_Reg(llvm::MCInst &insn)
static const char * GetPluginDescriptionStatic()
const char * GetRegisterName(unsigned reg_num, bool altnernate_name)
bool Emulate_DSUBU_DADDU(llvm::MCInst &insn)
bool Emulate_BC1NEZ(llvm::MCInst &insn)
void SetSourcedFromCompiler(lldb_private::LazyBool from_compiler)
Definition: UnwindPlan.h:449
static int64_t SignedBits(const uint64_t value, const uint64_t msbit, const uint64_t lsbit)
bool Emulate_Bcond_Link(llvm::MCInst &insn)
void SetReturnAddressRegister(uint32_t regnum)
Definition: UnwindPlan.h:410
An error handling class.
Definition: Status.h:44
bool Emulate_BNZD(llvm::MCInst &insn)
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:90
bool Emulate_BZD(llvm::MCInst &insn)