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