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 <cstdlib>
12#include <optional>
13
14#include "lldb/Core/Address.h"
15#include "lldb/Core/Opcode.h"
17#include "lldb/Host/PosixApi.h"
23#include "lldb/Utility/Stream.h"
24#include "llvm-c/Disassembler.h"
25#include "llvm/MC/MCAsmInfo.h"
26#include "llvm/MC/MCContext.h"
27#include "llvm/MC/MCDisassembler/MCDisassembler.h"
28#include "llvm/MC/MCInst.h"
29#include "llvm/MC/MCInstrInfo.h"
30#include "llvm/MC/MCRegisterInfo.h"
31#include "llvm/MC/MCSubtargetInfo.h"
32#include "llvm/MC/MCTargetOptions.h"
33#include "llvm/MC/TargetRegistry.h"
34#include "llvm/Support/TargetSelect.h"
35
36#include "llvm/ADT/STLExtras.h"
37
40
41using namespace lldb;
42using namespace lldb_private;
43
45
46#define UInt(x) ((uint64_t)x)
47#define integer int64_t
48
49//
50// EmulateInstructionMIPS64 implementation
51//
52
53#ifdef __mips__
54extern "C" {
55void LLVMInitializeMipsTargetInfo();
56void LLVMInitializeMipsTarget();
57void LLVMInitializeMipsAsmPrinter();
58void LLVMInitializeMipsTargetMC();
59void LLVMInitializeMipsDisassembler();
60}
61#endif
62
64 const lldb_private::ArchSpec &arch)
65 : EmulateInstruction(arch) {
66 /* Create instance of llvm::MCDisassembler */
67 std::string Status;
68 llvm::Triple triple = arch.GetTriple();
69 const llvm::Target *target =
70 llvm::TargetRegistry::lookupTarget(triple, Status);
71
72/*
73 * If we fail to get the target then we haven't registered it. The
74 * SystemInitializerCommon
75 * does not initialize targets, MCs and disassemblers. However we need the
76 * MCDisassembler
77 * to decode the instructions so that the decoding complexity stays with LLVM.
78 * Initialize the MIPS targets and disassemblers.
79*/
80#ifdef __mips__
81 if (!target) {
82 LLVMInitializeMipsTargetInfo();
83 LLVMInitializeMipsTarget();
84 LLVMInitializeMipsAsmPrinter();
85 LLVMInitializeMipsTargetMC();
86 LLVMInitializeMipsDisassembler();
87 target = llvm::TargetRegistry::lookupTarget(triple, Status);
88 }
89#endif
90
91 assert(target);
92
93 llvm::StringRef cpu;
94
95 switch (arch.GetCore()) {
98 cpu = "mips32";
99 break;
102 cpu = "mips32r2";
103 break;
106 cpu = "mips32r3";
107 break;
110 cpu = "mips32r5";
111 break;
114 cpu = "mips32r6";
115 break;
118 cpu = "mips64";
119 break;
122 cpu = "mips64r2";
123 break;
126 cpu = "mips64r3";
127 break;
130 cpu = "mips64r5";
131 break;
134 cpu = "mips64r6";
135 break;
136 default:
137 cpu = "generic";
138 break;
139 }
140
141 std::string features;
142 uint32_t arch_flags = arch.GetFlags();
143 if (arch_flags & ArchSpec::eMIPSAse_msa)
144 features += "+msa,";
145 if (arch_flags & ArchSpec::eMIPSAse_dsp)
146 features += "+dsp,";
147 if (arch_flags & ArchSpec::eMIPSAse_dspr2)
148 features += "+dspr2,";
149 if (arch_flags & ArchSpec::eMIPSAse_mips16)
150 features += "+mips16,";
151 if (arch_flags & ArchSpec::eMIPSAse_micromips)
152 features += "+micromips,";
153
154 m_reg_info.reset(target->createMCRegInfo(triple));
155 assert(m_reg_info.get());
156
157 m_insn_info.reset(target->createMCInstrInfo());
158 assert(m_insn_info.get());
159
160 m_asm_info.reset(target->createMCAsmInfo(*m_reg_info, triple, m_mc_options));
161 m_subtype_info.reset(target->createMCSubtargetInfo(triple, cpu, features));
162 assert(m_asm_info.get() && m_subtype_info.get());
163
164 m_context = std::make_unique<llvm::MCContext>(
165 triple, m_asm_info.get(), m_reg_info.get(), m_subtype_info.get());
166 assert(m_context.get());
167
168 m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context));
169 assert(m_disasm.get());
170}
171
176
180
182 return "Emulate instructions for the MIPS64 architecture.";
183}
184
187 InstructionType inst_type) {
189 inst_type)) {
190 if (arch.GetTriple().getArch() == llvm::Triple::mips64 ||
191 arch.GetTriple().getArch() == llvm::Triple::mips64el) {
192 return new EmulateInstructionMIPS64(arch);
193 }
194 }
195
196 return nullptr;
197}
198
200 return arch.GetTriple().getArch() == llvm::Triple::mips64 ||
201 arch.GetTriple().getArch() == llvm::Triple::mips64el;
202}
203
204const char *EmulateInstructionMIPS64::GetRegisterName(unsigned reg_num,
205 bool alternate_name) {
206 if (alternate_name) {
207 switch (reg_num) {
208 case dwarf_sp_mips64:
209 return "r29";
210 case dwarf_r30_mips64:
211 return "r30";
212 case dwarf_ra_mips64:
213 return "r31";
214 case dwarf_f0_mips64:
215 return "f0";
216 case dwarf_f1_mips64:
217 return "f1";
218 case dwarf_f2_mips64:
219 return "f2";
220 case dwarf_f3_mips64:
221 return "f3";
222 case dwarf_f4_mips64:
223 return "f4";
224 case dwarf_f5_mips64:
225 return "f5";
226 case dwarf_f6_mips64:
227 return "f6";
228 case dwarf_f7_mips64:
229 return "f7";
230 case dwarf_f8_mips64:
231 return "f8";
232 case dwarf_f9_mips64:
233 return "f9";
234 case dwarf_f10_mips64:
235 return "f10";
236 case dwarf_f11_mips64:
237 return "f11";
238 case dwarf_f12_mips64:
239 return "f12";
240 case dwarf_f13_mips64:
241 return "f13";
242 case dwarf_f14_mips64:
243 return "f14";
244 case dwarf_f15_mips64:
245 return "f15";
246 case dwarf_f16_mips64:
247 return "f16";
248 case dwarf_f17_mips64:
249 return "f17";
250 case dwarf_f18_mips64:
251 return "f18";
252 case dwarf_f19_mips64:
253 return "f19";
254 case dwarf_f20_mips64:
255 return "f20";
256 case dwarf_f21_mips64:
257 return "f21";
258 case dwarf_f22_mips64:
259 return "f22";
260 case dwarf_f23_mips64:
261 return "f23";
262 case dwarf_f24_mips64:
263 return "f24";
264 case dwarf_f25_mips64:
265 return "f25";
266 case dwarf_f26_mips64:
267 return "f26";
268 case dwarf_f27_mips64:
269 return "f27";
270 case dwarf_f28_mips64:
271 return "f28";
272 case dwarf_f29_mips64:
273 return "f29";
274 case dwarf_f30_mips64:
275 return "f30";
276 case dwarf_f31_mips64:
277 return "f31";
278 case dwarf_w0_mips64:
279 return "w0";
280 case dwarf_w1_mips64:
281 return "w1";
282 case dwarf_w2_mips64:
283 return "w2";
284 case dwarf_w3_mips64:
285 return "w3";
286 case dwarf_w4_mips64:
287 return "w4";
288 case dwarf_w5_mips64:
289 return "w5";
290 case dwarf_w6_mips64:
291 return "w6";
292 case dwarf_w7_mips64:
293 return "w7";
294 case dwarf_w8_mips64:
295 return "w8";
296 case dwarf_w9_mips64:
297 return "w9";
298 case dwarf_w10_mips64:
299 return "w10";
300 case dwarf_w11_mips64:
301 return "w11";
302 case dwarf_w12_mips64:
303 return "w12";
304 case dwarf_w13_mips64:
305 return "w13";
306 case dwarf_w14_mips64:
307 return "w14";
308 case dwarf_w15_mips64:
309 return "w15";
310 case dwarf_w16_mips64:
311 return "w16";
312 case dwarf_w17_mips64:
313 return "w17";
314 case dwarf_w18_mips64:
315 return "w18";
316 case dwarf_w19_mips64:
317 return "w19";
318 case dwarf_w20_mips64:
319 return "w20";
320 case dwarf_w21_mips64:
321 return "w21";
322 case dwarf_w22_mips64:
323 return "w22";
324 case dwarf_w23_mips64:
325 return "w23";
326 case dwarf_w24_mips64:
327 return "w24";
328 case dwarf_w25_mips64:
329 return "w25";
330 case dwarf_w26_mips64:
331 return "w26";
332 case dwarf_w27_mips64:
333 return "w27";
334 case dwarf_w28_mips64:
335 return "w28";
336 case dwarf_w29_mips64:
337 return "w29";
338 case dwarf_w30_mips64:
339 return "w30";
340 case dwarf_w31_mips64:
341 return "w31";
342 case dwarf_mir_mips64:
343 return "mir";
345 return "mcsr";
347 return "config5";
348 default:
349 break;
350 }
351 return nullptr;
352 }
353
354 switch (reg_num) {
356 return "r0";
357 case dwarf_r1_mips64:
358 return "r1";
359 case dwarf_r2_mips64:
360 return "r2";
361 case dwarf_r3_mips64:
362 return "r3";
363 case dwarf_r4_mips64:
364 return "r4";
365 case dwarf_r5_mips64:
366 return "r5";
367 case dwarf_r6_mips64:
368 return "r6";
369 case dwarf_r7_mips64:
370 return "r7";
371 case dwarf_r8_mips64:
372 return "r8";
373 case dwarf_r9_mips64:
374 return "r9";
375 case dwarf_r10_mips64:
376 return "r10";
377 case dwarf_r11_mips64:
378 return "r11";
379 case dwarf_r12_mips64:
380 return "r12";
381 case dwarf_r13_mips64:
382 return "r13";
383 case dwarf_r14_mips64:
384 return "r14";
385 case dwarf_r15_mips64:
386 return "r15";
387 case dwarf_r16_mips64:
388 return "r16";
389 case dwarf_r17_mips64:
390 return "r17";
391 case dwarf_r18_mips64:
392 return "r18";
393 case dwarf_r19_mips64:
394 return "r19";
395 case dwarf_r20_mips64:
396 return "r20";
397 case dwarf_r21_mips64:
398 return "r21";
399 case dwarf_r22_mips64:
400 return "r22";
401 case dwarf_r23_mips64:
402 return "r23";
403 case dwarf_r24_mips64:
404 return "r24";
405 case dwarf_r25_mips64:
406 return "r25";
407 case dwarf_r26_mips64:
408 return "r26";
409 case dwarf_r27_mips64:
410 return "r27";
411 case dwarf_gp_mips64:
412 return "gp";
413 case dwarf_sp_mips64:
414 return "sp";
415 case dwarf_r30_mips64:
416 return "fp";
417 case dwarf_ra_mips64:
418 return "ra";
419 case dwarf_sr_mips64:
420 return "sr";
421 case dwarf_lo_mips64:
422 return "lo";
423 case dwarf_hi_mips64:
424 return "hi";
425 case dwarf_bad_mips64:
426 return "bad";
428 return "cause";
429 case dwarf_pc_mips64:
430 return "pc";
431 case dwarf_f0_mips64:
432 return "f0";
433 case dwarf_f1_mips64:
434 return "f1";
435 case dwarf_f2_mips64:
436 return "f2";
437 case dwarf_f3_mips64:
438 return "f3";
439 case dwarf_f4_mips64:
440 return "f4";
441 case dwarf_f5_mips64:
442 return "f5";
443 case dwarf_f6_mips64:
444 return "f6";
445 case dwarf_f7_mips64:
446 return "f7";
447 case dwarf_f8_mips64:
448 return "f8";
449 case dwarf_f9_mips64:
450 return "f9";
451 case dwarf_f10_mips64:
452 return "f10";
453 case dwarf_f11_mips64:
454 return "f11";
455 case dwarf_f12_mips64:
456 return "f12";
457 case dwarf_f13_mips64:
458 return "f13";
459 case dwarf_f14_mips64:
460 return "f14";
461 case dwarf_f15_mips64:
462 return "f15";
463 case dwarf_f16_mips64:
464 return "f16";
465 case dwarf_f17_mips64:
466 return "f17";
467 case dwarf_f18_mips64:
468 return "f18";
469 case dwarf_f19_mips64:
470 return "f19";
471 case dwarf_f20_mips64:
472 return "f20";
473 case dwarf_f21_mips64:
474 return "f21";
475 case dwarf_f22_mips64:
476 return "f22";
477 case dwarf_f23_mips64:
478 return "f23";
479 case dwarf_f24_mips64:
480 return "f24";
481 case dwarf_f25_mips64:
482 return "f25";
483 case dwarf_f26_mips64:
484 return "f26";
485 case dwarf_f27_mips64:
486 return "f27";
487 case dwarf_f28_mips64:
488 return "f28";
489 case dwarf_f29_mips64:
490 return "f29";
491 case dwarf_f30_mips64:
492 return "f30";
493 case dwarf_f31_mips64:
494 return "f31";
496 return "fcsr";
497 case dwarf_fir_mips64:
498 return "fir";
499 case dwarf_w0_mips64:
500 return "w0";
501 case dwarf_w1_mips64:
502 return "w1";
503 case dwarf_w2_mips64:
504 return "w2";
505 case dwarf_w3_mips64:
506 return "w3";
507 case dwarf_w4_mips64:
508 return "w4";
509 case dwarf_w5_mips64:
510 return "w5";
511 case dwarf_w6_mips64:
512 return "w6";
513 case dwarf_w7_mips64:
514 return "w7";
515 case dwarf_w8_mips64:
516 return "w8";
517 case dwarf_w9_mips64:
518 return "w9";
519 case dwarf_w10_mips64:
520 return "w10";
521 case dwarf_w11_mips64:
522 return "w11";
523 case dwarf_w12_mips64:
524 return "w12";
525 case dwarf_w13_mips64:
526 return "w13";
527 case dwarf_w14_mips64:
528 return "w14";
529 case dwarf_w15_mips64:
530 return "w15";
531 case dwarf_w16_mips64:
532 return "w16";
533 case dwarf_w17_mips64:
534 return "w17";
535 case dwarf_w18_mips64:
536 return "w18";
537 case dwarf_w19_mips64:
538 return "w19";
539 case dwarf_w20_mips64:
540 return "w20";
541 case dwarf_w21_mips64:
542 return "w21";
543 case dwarf_w22_mips64:
544 return "w22";
545 case dwarf_w23_mips64:
546 return "w23";
547 case dwarf_w24_mips64:
548 return "w24";
549 case dwarf_w25_mips64:
550 return "w25";
551 case dwarf_w26_mips64:
552 return "w26";
553 case dwarf_w27_mips64:
554 return "w27";
555 case dwarf_w28_mips64:
556 return "w28";
557 case dwarf_w29_mips64:
558 return "w29";
559 case dwarf_w30_mips64:
560 return "w30";
561 case dwarf_w31_mips64:
562 return "w31";
564 return "mcsr";
565 case dwarf_mir_mips64:
566 return "mir";
568 return "config5";
569 }
570 return nullptr;
571}
572
573std::optional<RegisterInfo>
575 uint32_t reg_num) {
576 if (reg_kind == eRegisterKindGeneric) {
577 switch (reg_num) {
579 reg_kind = eRegisterKindDWARF;
580 reg_num = dwarf_pc_mips64;
581 break;
583 reg_kind = eRegisterKindDWARF;
584 reg_num = dwarf_sp_mips64;
585 break;
587 reg_kind = eRegisterKindDWARF;
588 reg_num = dwarf_r30_mips64;
589 break;
591 reg_kind = eRegisterKindDWARF;
592 reg_num = dwarf_ra_mips64;
593 break;
595 reg_kind = eRegisterKindDWARF;
596 reg_num = dwarf_sr_mips64;
597 break;
598 default:
599 return {};
600 }
601 }
602
603 if (reg_kind == eRegisterKindDWARF) {
604 RegisterInfo reg_info;
605 ::memset(&reg_info, 0, sizeof(RegisterInfo));
606 ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
607
608 if (reg_num == dwarf_sr_mips64 || reg_num == dwarf_fcsr_mips64 ||
609 reg_num == dwarf_fir_mips64 || reg_num == dwarf_mcsr_mips64 ||
610 reg_num == dwarf_mir_mips64 || reg_num == dwarf_config5_mips64) {
611 reg_info.byte_size = 4;
612 reg_info.format = eFormatHex;
613 reg_info.encoding = eEncodingUint;
614 } else if ((int)reg_num >= dwarf_zero_mips64 &&
615 (int)reg_num <= dwarf_f31_mips64) {
616 reg_info.byte_size = 8;
617 reg_info.format = eFormatHex;
618 reg_info.encoding = eEncodingUint;
619 } else if ((int)reg_num >= dwarf_w0_mips64 &&
620 (int)reg_num <= dwarf_w31_mips64) {
621 reg_info.byte_size = 16;
622 reg_info.format = eFormatVectorOfUInt8;
623 reg_info.encoding = eEncodingVector;
624 } else {
625 return {};
626 }
627
628 reg_info.name = GetRegisterName(reg_num, false);
629 reg_info.alt_name = GetRegisterName(reg_num, true);
630 reg_info.kinds[eRegisterKindDWARF] = reg_num;
631
632 switch (reg_num) {
633 case dwarf_r30_mips64:
635 break;
636 case dwarf_ra_mips64:
638 break;
639 case dwarf_sp_mips64:
641 break;
642 case dwarf_pc_mips64:
644 break;
645 case dwarf_sr_mips64:
647 break;
648 default:
649 break;
650 }
651 return reg_info;
652 }
653 return {};
654}
655
658 static EmulateInstructionMIPS64::MipsOpcode g_opcodes[] = {
659 // Prologue/Epilogue instructions
661 "DADDIU rt, rs, immediate"},
663 "ADDIU rt, rs, immediate"},
664 {"SD", &EmulateInstructionMIPS64::Emulate_SD, "SD rt, offset(rs)"},
665 {"LD", &EmulateInstructionMIPS64::Emulate_LD, "LD rt, offset(base)"},
667 "DSUBU rd, rs, rt"},
669 "SUBU rd, rs, rt"},
671 "DADDU rd, rs, rt"},
673 "ADDU rd, rs, rt"},
674 {"LUI", &EmulateInstructionMIPS64::Emulate_LUI, "LUI rt, immediate"},
675
676 // Load/Store instructions
677 /* Following list of emulated instructions are required by implementation
678 of hardware watchpoint
679 for MIPS in lldb. As we just need the address accessed by instructions,
680 we have generalised
681 all these instructions in 2 functions depending on their addressing
682 modes */
683
685 "LB rt, offset(base)"},
687 "LBE rt, offset(base)"},
689 "LBU rt, offset(base)"},
691 "LBUE rt, offset(base)"},
693 "LDC1 ft, offset(base)"},
695 "LDL rt, offset(base)"},
697 "LDR rt, offset(base)"},
699 "LLD rt, offset(base)"},
701 "LDC2 rt, offset(base)"},
703 "LDXC1 fd, index (base)"},
705 "LH rt, offset(base)"},
707 "LHE rt, offset(base)"},
709 "LHU rt, offset(base)"},
711 "LHUE rt, offset(base)"},
713 "LL rt, offset(base)"},
715 "LLE rt, offset(base)"},
717 "LUXC1 fd, index (base)"},
719 "LW rt, offset(rs)"},
721 "LWC1 ft, offset(base)"},
723 "LWC2 rt, offset(base)"},
725 "LWE rt, offset(base)"},
727 "LWL rt, offset(base)"},
729 "LWLE rt, offset(base)"},
731 "LWR rt, offset(base)"},
733 "LWRE rt, offset(base)"},
735 "LWXC1 fd, index (base)"},
736
738 "SB rt, offset(base)"},
740 "SBE rt, offset(base)"},
742 "SC rt, offset(base)"},
744 "SCE rt, offset(base)"},
746 "SCD rt, offset(base)"},
748 "SDL rt, offset(base)"},
750 "SDR rt, offset(base)"},
752 "SDC1 ft, offset(base)"},
754 "SDC2 rt, offset(base)"},
756 "SDXC1 fs, index (base)"},
758 "SH rt, offset(base)"},
760 "SHE rt, offset(base)"},
762 "SUXC1 fs, index (base)"},
764 "SW rt, offset(rs)"},
766 "SWC1 ft, offset(base)"},
768 "SWC2 rt, offset(base)"},
770 "SWE rt, offset(base)"},
772 "SWL rt, offset(base)"},
774 "SWLE rt, offset(base)"},
776 "SWR rt, offset(base)"},
778 "SWRE rt, offset(base)"},
780 "SWXC1 fs, index (base)"},
781
782 // Branch instructions
783 {"BEQ", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"},
784 {"BEQ64", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"},
785 {"BNE", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"},
786 {"BNE64", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"},
788 "BEQL rs,rt,offset"},
790 "BNEL rs,rt,offset"},
792 "BGEZALL rt,offset"},
793 {"BAL", &EmulateInstructionMIPS64::Emulate_BAL, "BAL offset"},
795 "BGEZAL rs,offset"},
796 {"BALC", &EmulateInstructionMIPS64::Emulate_BALC, "BALC offset"},
797 {"BC", &EmulateInstructionMIPS64::Emulate_BC, "BC offset"},
798 {"BGEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"},
799 {"BGEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"},
801 "BLEZALC rs,offset"},
803 "BGEZALC rs,offset"},
805 "BLTZALC rs,offset"},
807 "BGTZALC rs,offset"},
809 "BEQZALC rs,offset"},
811 "BNEZALC rs,offset"},
813 "BEQC rs,rt,offset"},
815 "BEQC rs,rt,offset"},
817 "BNEC rs,rt,offset"},
819 "BNEC rs,rt,offset"},
821 "BLTC rs,rt,offset"},
823 "BLTC rs,rt,offset"},
825 "BGEC rs,rt,offset"},
827 "BGEC rs,rt,offset"},
829 "BLTUC rs,rt,offset"},
831 "BLTUC rs,rt,offset"},
833 "BGEUC rs,rt,offset"},
835 "BGEUC rs,rt,offset"},
837 "BLTZC rt,offset"},
839 "BLTZC rt,offset"},
841 "BLEZC rt,offset"},
843 "BLEZC rt,offset"},
845 "BGEZC rt,offset"},
847 "BGEZC rt,offset"},
849 "BGTZC rt,offset"},
851 "BGTZC rt,offset"},
853 "BEQZC rt,offset"},
855 "BEQZC rt,offset"},
857 "BNEZC rt,offset"},
859 "BNEZC rt,offset"},
860 {"BGEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZL rt,offset"},
861 {"BGTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"},
862 {"BGTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"},
863 {"BGTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZL rt,offset"},
864 {"BLEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"},
865 {"BLEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"},
866 {"BLEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZL rt,offset"},
867 {"BLTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"},
868 {"BLTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"},
870 "BLTZAL rt,offset"},
872 "BLTZALL rt,offset"},
873 {"BLTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZL rt,offset"},
875 "BOVC rs,rt,offset"},
877 "BNVC rs,rt,offset"},
878 {"J", &EmulateInstructionMIPS64::Emulate_J, "J target"},
879 {"JAL", &EmulateInstructionMIPS64::Emulate_JAL, "JAL target"},
880 {"JALX", &EmulateInstructionMIPS64::Emulate_JAL, "JALX target"},
881 {"JALR", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target"},
882 {"JALR64", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target"},
883 {"JALR_HB", &EmulateInstructionMIPS64::Emulate_JALR, "JALR.HB target"},
884 {"JIALC", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"},
885 {"JIALC64", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"},
886 {"JIC", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"},
887 {"JIC64", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"},
888 {"JR", &EmulateInstructionMIPS64::Emulate_JR, "JR target"},
889 {"JR64", &EmulateInstructionMIPS64::Emulate_JR, "JR target"},
890 {"JR_HB", &EmulateInstructionMIPS64::Emulate_JR, "JR.HB target"},
891 {"BC1F", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1F cc, offset"},
892 {"BC1T", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1T cc, offset"},
894 "BC1FL cc, offset"},
896 "BC1TL cc, offset"},
898 "BC1EQZ ft, offset"},
900 "BC1NEZ ft, offset"},
902 "BC1ANY2F cc, offset"},
904 "BC1ANY2T cc, offset"},
906 "BC1ANY4F cc, offset"},
908 "BC1ANY4T cc, offset"},
909 {"BNZ_B", &EmulateInstructionMIPS64::Emulate_BNZB, "BNZ.b wt,s16"},
910 {"BNZ_H", &EmulateInstructionMIPS64::Emulate_BNZH, "BNZ.h wt,s16"},
911 {"BNZ_W", &EmulateInstructionMIPS64::Emulate_BNZW, "BNZ.w wt,s16"},
912 {"BNZ_D", &EmulateInstructionMIPS64::Emulate_BNZD, "BNZ.d wt,s16"},
913 {"BZ_B", &EmulateInstructionMIPS64::Emulate_BZB, "BZ.b wt,s16"},
914 {"BZ_H", &EmulateInstructionMIPS64::Emulate_BZH, "BZ.h wt,s16"},
915 {"BZ_W", &EmulateInstructionMIPS64::Emulate_BZW, "BZ.w wt,s16"},
916 {"BZ_D", &EmulateInstructionMIPS64::Emulate_BZD, "BZ.d wt,s16"},
917 {"BNZ_V", &EmulateInstructionMIPS64::Emulate_BNZV, "BNZ.V wt,s16"},
918 {"BZ_V", &EmulateInstructionMIPS64::Emulate_BZV, "BZ.V wt,s16"},
919 };
920
921 for (MipsOpcode &opcode : g_opcodes) {
922 if (op_name.equals_insensitive(opcode.op_name))
923 return &opcode;
924 }
925 return nullptr;
926}
927
929 bool success = false;
931 LLDB_INVALID_ADDRESS, &success);
932 if (success) {
933 Context read_inst_context;
934 read_inst_context.type = eContextReadOpcode;
935 read_inst_context.SetNoArgs();
936 m_opcode.SetOpcode32(
937 ReadMemoryUnsigned(read_inst_context, m_addr, 4, 0, &success),
938 GetByteOrder());
939 }
940 if (!success)
942 return success;
943}
944
945bool EmulateInstructionMIPS64::EvaluateInstruction(uint32_t evaluate_options) {
946 bool success = false;
947 llvm::MCInst mc_insn;
948 uint64_t insn_size;
949 DataExtractor data;
950
951 /* Keep the complexity of the decode logic with the llvm::MCDisassembler
952 * class. */
953 if (m_opcode.GetData(data)) {
954 llvm::MCDisassembler::DecodeStatus decode_status;
955 llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());
956 decode_status = m_disasm->getInstruction(mc_insn, insn_size, raw_insn,
957 m_addr, llvm::nulls());
958 if (decode_status != llvm::MCDisassembler::Success)
959 return false;
960 }
961
962 /*
963 * mc_insn.getOpcode() returns decoded opcode. However to make use
964 * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc".
965 */
966 llvm::StringRef op_name = m_insn_info->getName(mc_insn.getOpcode());
967
968 /*
969 * Decoding has been done already. Just get the call-back function
970 * and emulate the instruction.
971 */
972 MipsOpcode *opcode_data = GetOpcodeForInstruction(op_name);
973
974 if (opcode_data == nullptr)
975 return false;
976
977 uint64_t old_pc = 0, new_pc = 0;
978 const bool auto_advance_pc =
979 evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
980
981 if (auto_advance_pc) {
982 old_pc =
984 if (!success)
985 return false;
986 }
987
988 /* emulate instruction */
989 success = (this->*opcode_data->callback)(mc_insn);
990 if (!success)
991 return false;
992
993 if (auto_advance_pc) {
994 new_pc =
996 if (!success)
997 return false;
998
999 /* If we haven't changed the PC, change it here */
1000 if (old_pc == new_pc) {
1001 new_pc += 4;
1002 Context context;
1004 new_pc))
1005 return false;
1006 }
1007 }
1008
1009 return true;
1010}
1011
1013 UnwindPlan &unwind_plan) {
1014 unwind_plan.Clear();
1016
1017 UnwindPlan::Row row;
1018 const bool can_replace = false;
1019
1020 // Our previous Call Frame Address is the stack pointer
1022
1023 // Our previous PC is in the RA
1025 can_replace);
1026
1027 unwind_plan.AppendRow(std::move(row));
1028
1029 // All other registers are the same.
1030 unwind_plan.SetSourceName("EmulateInstructionMIPS64");
1035
1036 return true;
1037}
1038
1040 switch (regnum) {
1041 case dwarf_r16_mips64:
1042 case dwarf_r17_mips64:
1043 case dwarf_r18_mips64:
1044 case dwarf_r19_mips64:
1045 case dwarf_r20_mips64:
1046 case dwarf_r21_mips64:
1047 case dwarf_r22_mips64:
1048 case dwarf_r23_mips64:
1049 case dwarf_gp_mips64:
1050 case dwarf_sp_mips64:
1051 case dwarf_r30_mips64:
1052 case dwarf_ra_mips64:
1053 return true;
1054 default:
1055 return false;
1056 }
1057 return false;
1058}
1059
1061 // DADDIU rt, rs, immediate
1062 // GPR[rt] <- GPR[rs] + sign_extend(immediate)
1063
1064 uint8_t dst, src;
1065 bool success = false;
1066 const uint32_t imm16 = insn.getOperand(2).getImm();
1067 int64_t imm = SignedBits(imm16, 15, 0);
1068
1069 dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1070 src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1071
1072 // If immediate is greater than 2^16 - 1 then clang generate LUI,
1073 // (D)ADDIU,(D)SUBU instructions in prolog. Example lui $1, 0x2 daddiu $1,
1074 // $1, -0x5920 dsubu $sp, $sp, $1 In this case, (D)ADDIU dst and src will be
1075 // same and not equal to sp
1076 if (dst == src) {
1077 Context context;
1078
1079 /* read <src> register */
1080 const uint64_t src_opd_val = ReadRegisterUnsigned(
1081 eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
1082 if (!success)
1083 return false;
1084
1085 /* Check if this is daddiu sp, sp, imm16 */
1086 if (dst == dwarf_sp_mips64) {
1087 /*
1088 * From the MIPS IV spec:
1089 *
1090 * The term “unsigned” in the instruction name is a misnomer; this
1091 * operation is 64-bit modulo arithmetic that does not trap on overflow.
1092 * It is appropriate for arithmetic which is not signed, such as address
1093 * arithmetic, or integer arithmetic environments that ignore overflow,
1094 * such as “C” language arithmetic.
1095 *
1096 * Assume 2's complement and rely on unsigned overflow here.
1097 */
1098 uint64_t result = src_opd_val + imm;
1099 std::optional<RegisterInfo> reg_info_sp =
1101 if (reg_info_sp)
1102 context.SetRegisterPlusOffset(*reg_info_sp, imm);
1103
1104 /* We are allocating bytes on stack */
1106
1108 result);
1109 return true;
1110 }
1111
1112 imm += src_opd_val;
1113 context.SetImmediateSigned(imm);
1114 context.type = eContextImmediate;
1115
1117 dwarf_zero_mips64 + dst, imm))
1118 return false;
1119 }
1120
1121 return true;
1122}
1123
1125 uint64_t address;
1126 bool success = false;
1127 uint32_t imm16 = insn.getOperand(2).getImm();
1128 uint64_t imm = SignedBits(imm16, 15, 0);
1129 uint32_t src, base;
1130 Context bad_vaddr_context;
1131
1132 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1133 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1134
1135 std::optional<RegisterInfo> reg_info_base =
1137 std::optional<RegisterInfo> reg_info_src =
1139 if (!reg_info_base || !reg_info_src)
1140 return false;
1141
1142 /* read SP */
1144 0, &success);
1145 if (!success)
1146 return false;
1147
1148 /* destination address */
1149 address = address + imm;
1150
1151 /* We look for sp based non-volatile register stores */
1152 if (nonvolatile_reg_p(src)) {
1153 Context context;
1155 context.SetRegisterToRegisterPlusOffset(*reg_info_src, *reg_info_base, 0);
1156
1157 std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);
1158 if (!data_src)
1159 return false;
1160
1161 Status error;
1162 RegisterValue::BytesContainer buffer(reg_info_src->byte_size);
1163 if (data_src->GetAsMemoryData(*reg_info_src, buffer.data(),
1164 reg_info_src->byte_size, eByteOrderLittle,
1165 error) == 0)
1166 return false;
1167
1168 if (!WriteMemory(context, address, buffer.data(), reg_info_src->byte_size))
1169 return false;
1170 }
1171
1172 /* Set the bad_vaddr register with base address used in the instruction */
1173 bad_vaddr_context.type = eContextInvalid;
1175 address);
1176
1177 return true;
1178}
1179
1181 bool success = false;
1182 uint32_t src, base;
1183 int64_t imm, address;
1184 Context bad_vaddr_context;
1185
1186 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1187 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1188 imm = insn.getOperand(2).getImm();
1189
1191 return false;
1192
1193 /* read base register */
1195 0, &success);
1196 if (!success)
1197 return false;
1198
1199 /* destination address */
1200 address = address + imm;
1201
1202 /* Set the bad_vaddr register with base address used in the instruction */
1203 bad_vaddr_context.type = eContextInvalid;
1205 address);
1206
1207 if (nonvolatile_reg_p(src)) {
1208 RegisterValue data_src;
1209 std::optional<RegisterInfo> reg_info_src =
1211 if (!reg_info_src)
1212 return false;
1213
1214 Context context;
1215 context.type = eContextRegisterLoad;
1216
1217 return WriteRegister(context, *reg_info_src, data_src);
1218 }
1219
1220 return false;
1221}
1222
1224 // LUI rt, immediate
1225 // GPR[rt] <- sign_extend(immediate << 16)
1226
1227 const uint32_t imm32 = insn.getOperand(1).getImm() << 16;
1228 int64_t imm = SignedBits(imm32, 31, 0);
1229 uint8_t rt;
1230 Context context;
1231
1232 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1233 context.SetImmediateSigned(imm);
1234 context.type = eContextImmediate;
1235
1237 dwarf_zero_mips64 + rt, imm);
1238}
1239
1241 // DSUBU sp, <src>, <rt>
1242 // DADDU sp, <src>, <rt>
1243 // DADDU dst, sp, <rt>
1244
1245 bool success = false;
1246 uint64_t result;
1247 uint8_t src, dst, rt;
1248 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1249
1250 dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1251 src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1252
1253 /* Check if sp is destination register */
1254 if (dst == dwarf_sp_mips64) {
1255 rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1256
1257 /* read <src> register */
1258 uint64_t src_opd_val = ReadRegisterUnsigned(
1259 eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
1260 if (!success)
1261 return false;
1262
1263 /* read <rt > register */
1264 uint64_t rt_opd_val = ReadRegisterUnsigned(
1265 eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
1266 if (!success)
1267 return false;
1268
1269 if (op_name.equals_insensitive("DSUBU") ||
1270 op_name.equals_insensitive("SUBU"))
1271 result = src_opd_val - rt_opd_val;
1272 else
1273 result = src_opd_val + rt_opd_val;
1274
1275 Context context;
1276 std::optional<RegisterInfo> reg_info_sp =
1278 if (reg_info_sp)
1279 context.SetRegisterPlusOffset(*reg_info_sp, rt_opd_val);
1280
1281 /* We are allocating bytes on stack */
1283
1285
1286 return true;
1287 } else if (src == dwarf_sp_mips64) {
1288 rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1289
1290 /* read <src> register */
1291 uint64_t src_opd_val = ReadRegisterUnsigned(
1292 eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
1293 if (!success)
1294 return false;
1295
1296 /* read <rt> register */
1297 uint64_t rt_opd_val = ReadRegisterUnsigned(
1298 eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
1299 if (!success)
1300 return false;
1301
1302 Context context;
1303
1304 if (op_name.equals_insensitive("DSUBU") ||
1305 op_name.equals_insensitive("SUBU"))
1306 result = src_opd_val - rt_opd_val;
1307 else
1308 result = src_opd_val + rt_opd_val;
1309
1310 context.SetImmediateSigned(result);
1311 context.type = eContextImmediate;
1312
1314 dwarf_zero_mips64 + dst, result))
1315 return false;
1316 }
1317
1318 return true;
1319}
1320
1321/*
1322 Emulate below MIPS branch instructions.
1323 BEQ, BNE : Branch on condition
1324 BEQL, BNEL : Branch likely
1325*/
1327 bool success = false;
1328 uint32_t rs, rt;
1329 int64_t offset, pc, rs_val, rt_val, target = 0;
1330 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1331
1332 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1333 rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1334 offset = insn.getOperand(2).getImm();
1335
1337 if (!success)
1338 return false;
1339
1340 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1341 dwarf_zero_mips64 + rs, 0, &success);
1342 if (!success)
1343 return false;
1344
1345 rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1346 dwarf_zero_mips64 + rt, 0, &success);
1347 if (!success)
1348 return false;
1349
1350 if (op_name.equals_insensitive("BEQ") || op_name.equals_insensitive("BEQL") ||
1351 op_name.equals_insensitive("BEQ64")) {
1352 if (rs_val == rt_val)
1353 target = pc + offset;
1354 else
1355 target = pc + 8;
1356 } else if (op_name.equals_insensitive("BNE") ||
1357 op_name.equals_insensitive("BNEL") ||
1358 op_name.equals_insensitive("BNE64")) {
1359 if (rs_val != rt_val)
1360 target = pc + offset;
1361 else
1362 target = pc + 8;
1363 }
1364
1365 Context context;
1367 context.SetImmediate(offset);
1368
1370 target);
1371}
1372
1373/*
1374 Emulate below MIPS Non-Compact conditional branch and link instructions.
1375 BLTZAL, BGEZAL :
1376 BLTZALL, BGEZALL : Branch likely
1377*/
1379 bool success = false;
1380 uint32_t rs;
1381 int64_t offset, pc, target = 0;
1382 int64_t rs_val;
1383 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1384
1385 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1386 offset = insn.getOperand(1).getImm();
1387
1389 if (!success)
1390 return false;
1391
1392 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1393 dwarf_zero_mips64 + rs, 0, &success);
1394 if (!success)
1395 return false;
1396
1397 if (op_name.equals_insensitive("BLTZAL") ||
1398 op_name.equals_insensitive("BLTZALL")) {
1399 if (rs_val < 0)
1400 target = pc + offset;
1401 else
1402 target = pc + 8;
1403 } else if (op_name.equals_insensitive("BGEZAL") ||
1404 op_name.equals_insensitive("BGEZALL")) {
1405 if (rs_val >= 0)
1406 target = pc + offset;
1407 else
1408 target = pc + 8;
1409 }
1410
1411 Context context;
1412
1414 target))
1415 return false;
1416
1418 pc + 8))
1419 return false;
1420
1421 return true;
1422}
1423
1425 bool success = false;
1426 int64_t offset, pc, target;
1427
1428 /*
1429 * BAL offset
1430 * offset = sign_ext (offset << 2)
1431 * RA = PC + 8
1432 * PC = PC + offset
1433 */
1434 offset = insn.getOperand(0).getImm();
1435
1437 if (!success)
1438 return false;
1439
1440 target = pc + offset;
1441
1442 Context context;
1443
1445 target))
1446 return false;
1447
1449 pc + 8))
1450 return false;
1451
1452 return true;
1453}
1454
1456 bool success = false;
1457 int64_t offset, pc, target;
1458
1459 /*
1460 * BALC offset
1461 * offset = sign_ext (offset << 2)
1462 * RA = PC + 4
1463 * PC = PC + 4 + offset
1464 */
1465 offset = insn.getOperand(0).getImm();
1466
1468 if (!success)
1469 return false;
1470
1471 target = pc + offset;
1472
1473 Context context;
1474
1476 target))
1477 return false;
1478
1480 pc + 4))
1481 return false;
1482
1483 return true;
1484}
1485
1486/*
1487 Emulate below MIPS conditional branch and link instructions.
1488 BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches
1489*/
1491 bool success = false;
1492 uint32_t rs;
1493 int64_t offset, pc, rs_val, target = 0;
1494 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1495
1496 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1497 offset = insn.getOperand(1).getImm();
1498
1500 if (!success)
1501 return false;
1502
1503 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1504 dwarf_zero_mips64 + rs, 0, &success);
1505 if (!success)
1506 return false;
1507
1508 if (op_name.equals_insensitive("BLEZALC")) {
1509 if (rs_val <= 0)
1510 target = pc + offset;
1511 else
1512 target = pc + 4;
1513 } else if (op_name.equals_insensitive("BGEZALC")) {
1514 if (rs_val >= 0)
1515 target = pc + offset;
1516 else
1517 target = pc + 4;
1518 } else if (op_name.equals_insensitive("BLTZALC")) {
1519 if (rs_val < 0)
1520 target = pc + offset;
1521 else
1522 target = pc + 4;
1523 } else if (op_name.equals_insensitive("BGTZALC")) {
1524 if (rs_val > 0)
1525 target = pc + offset;
1526 else
1527 target = pc + 4;
1528 } else if (op_name.equals_insensitive("BEQZALC")) {
1529 if (rs_val == 0)
1530 target = pc + offset;
1531 else
1532 target = pc + 4;
1533 } else if (op_name.equals_insensitive("BNEZALC")) {
1534 if (rs_val != 0)
1535 target = pc + offset;
1536 else
1537 target = pc + 4;
1538 }
1539
1540 Context context;
1541
1543 target))
1544 return false;
1545
1547 pc + 4))
1548 return false;
1549
1550 return true;
1551}
1552
1553/*
1554 Emulate below MIPS branch instructions.
1555 BLTZL, BGEZL, BGTZL, BLEZL : Branch likely
1556 BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches
1557*/
1559 bool success = false;
1560 uint32_t rs;
1561 int64_t offset, pc, rs_val, target = 0;
1562 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1563
1564 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1565 offset = insn.getOperand(1).getImm();
1566
1568 if (!success)
1569 return false;
1570
1571 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1572 dwarf_zero_mips64 + rs, 0, &success);
1573 if (!success)
1574 return false;
1575
1576 if (op_name.equals_insensitive("BLTZL") ||
1577 op_name.equals_insensitive("BLTZ") ||
1578 op_name.equals_insensitive("BLTZ64")) {
1579 if (rs_val < 0)
1580 target = pc + offset;
1581 else
1582 target = pc + 8;
1583 } else if (op_name.equals_insensitive("BGEZL") ||
1584 op_name.equals_insensitive("BGEZ") ||
1585 op_name.equals_insensitive("BGEZ64")) {
1586 if (rs_val >= 0)
1587 target = pc + offset;
1588 else
1589 target = pc + 8;
1590 } else if (op_name.equals_insensitive("BGTZL") ||
1591 op_name.equals_insensitive("BGTZ") ||
1592 op_name.equals_insensitive("BGTZ64")) {
1593 if (rs_val > 0)
1594 target = pc + offset;
1595 else
1596 target = pc + 8;
1597 } else if (op_name.equals_insensitive("BLEZL") ||
1598 op_name.equals_insensitive("BLEZ") ||
1599 op_name.equals_insensitive("BLEZ64")) {
1600 if (rs_val <= 0)
1601 target = pc + offset;
1602 else
1603 target = pc + 8;
1604 }
1605
1606 Context context;
1608 context.SetImmediate(offset);
1609
1611 target);
1612}
1613
1615 bool success = false;
1616 int64_t offset, pc, target;
1617
1618 /*
1619 * BC offset
1620 * offset = sign_ext (offset << 2)
1621 * PC = PC + 4 + offset
1622 */
1623 offset = insn.getOperand(0).getImm();
1624
1626 if (!success)
1627 return false;
1628
1629 target = pc + offset;
1630
1631 Context context;
1632
1634 target);
1635}
1636
1637static int IsAdd64bitOverflow(int64_t a, int64_t b) {
1638 int64_t r = (uint64_t)a + (uint64_t)b;
1639 return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
1640}
1641
1642/*
1643 Emulate below MIPS branch instructions.
1644 BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch
1645 instructions with no delay slot
1646*/
1648 bool success = false;
1649 uint32_t rs, rt;
1650 int64_t offset, pc, rs_val, rt_val, target = 0;
1651 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1652 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
1653
1654 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1655 rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1656 offset = insn.getOperand(2).getImm();
1657
1659 if (!success)
1660 return false;
1661
1662 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1663 dwarf_zero_mips64 + rs, 0, &success);
1664 if (!success)
1665 return false;
1666
1667 rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1668 dwarf_zero_mips64 + rt, 0, &success);
1669 if (!success)
1670 return false;
1671
1672 if (op_name.equals_insensitive("BEQC") ||
1673 op_name.equals_insensitive("BEQC64")) {
1674 if (rs_val == rt_val)
1675 target = pc + offset;
1676 else
1677 target = pc + 4;
1678 } else if (op_name.equals_insensitive("BNEC") ||
1679 op_name.equals_insensitive("BNEC64")) {
1680 if (rs_val != rt_val)
1681 target = pc + offset;
1682 else
1683 target = pc + 4;
1684 } else if (op_name.equals_insensitive("BLTC") ||
1685 op_name.equals_insensitive("BLTC64")) {
1686 if (rs_val < rt_val)
1687 target = pc + offset;
1688 else
1689 target = pc + 4;
1690 } else if (op_name.equals_insensitive("BGEC64") ||
1691 op_name.equals_insensitive("BGEC")) {
1692 if (rs_val >= rt_val)
1693 target = pc + offset;
1694 else
1695 target = pc + 4;
1696 } else if (op_name.equals_insensitive("BLTUC") ||
1697 op_name.equals_insensitive("BLTUC64")) {
1698 if (rs_val < rt_val)
1699 target = pc + offset;
1700 else
1701 target = pc + 4;
1702 } else if (op_name.equals_insensitive("BGEUC") ||
1703 op_name.equals_insensitive("BGEUC64")) {
1704 if ((uint32_t)rs_val >= (uint32_t)rt_val)
1705 target = pc + offset;
1706 else
1707 target = pc + 4;
1708 } else if (op_name.equals_insensitive("BOVC")) {
1709 if (IsAdd64bitOverflow(rs_val, rt_val))
1710 target = pc + offset;
1711 else
1712 target = pc + 4;
1713 } else if (op_name.equals_insensitive("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 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
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 (op_name.equals_insensitive("BLTZC") ||
1753 op_name.equals_insensitive("BLTZC64")) {
1754 if (rs_val < 0)
1755 target = pc + offset;
1756 else
1757 target = pc + 4;
1758 } else if (op_name.equals_insensitive("BLEZC") ||
1759 op_name.equals_insensitive("BLEZC64")) {
1760 if (rs_val <= 0)
1761 target = pc + offset;
1762 else
1763 target = pc + 4;
1764 } else if (op_name.equals_insensitive("BGEZC") ||
1765 op_name.equals_insensitive("BGEZC64")) {
1766 if (rs_val >= 0)
1767 target = pc + offset;
1768 else
1769 target = pc + 4;
1770 } else if (op_name.equals_insensitive("BGTZC") ||
1771 op_name.equals_insensitive("BGTZC64")) {
1772 if (rs_val > 0)
1773 target = pc + offset;
1774 else
1775 target = pc + 4;
1776 } else if (op_name.equals_insensitive("BEQZC") ||
1777 op_name.equals_insensitive("BEQZC64")) {
1778 if (rs_val == 0)
1779 target = pc + offset;
1780 else
1781 target = pc + 4;
1782 } else if (op_name.equals_insensitive("BNEZC") ||
1783 op_name.equals_insensitive("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
1798bool 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
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
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
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
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 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
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 (op_name.equals_insensitive("BC1F") ||
2008 op_name.equals_insensitive("BC1FL")) {
2009 if ((fcsr & (1 << cc)) == 0)
2010 target = pc + offset;
2011 else
2012 target = pc + 8;
2013 } else if (op_name.equals_insensitive("BC1T") ||
2014 op_name.equals_insensitive("BC1TL")) {
2015 if ((fcsr & (1 << cc)) != 0)
2016 target = pc + offset;
2017 else
2018 target = pc + 8;
2019 }
2020
2021 Context context;
2022
2024 target);
2025}
2026
2028 bool success = false;
2029 uint32_t ft;
2030 uint64_t ft_val;
2031 int64_t target, pc, offset;
2032
2033 /*
2034 * BC1EQZ ft, offset
2035 * condition <- (FPR[ft].bit0 == 0)
2036 * if condition then
2037 * offset = sign_ext (offset)
2038 * PC = PC + 4 + offset
2039 */
2040 ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2041 offset = insn.getOperand(1).getImm();
2042
2044 if (!success)
2045 return false;
2046
2048 &success);
2049 if (!success)
2050 return false;
2051
2052 if ((ft_val & 1) == 0)
2053 target = pc + 4 + offset;
2054 else
2055 target = pc + 8;
2056
2057 Context context;
2058
2060 target);
2061}
2062
2064 bool success = false;
2065 uint32_t ft;
2066 uint64_t ft_val;
2067 int64_t target, pc, offset;
2068
2069 /*
2070 * BC1NEZ ft, offset
2071 * condition <- (FPR[ft].bit0 != 0)
2072 * if condition then
2073 * offset = sign_ext (offset)
2074 * PC = PC + 4 + offset
2075 */
2076 ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2077 offset = insn.getOperand(1).getImm();
2078
2080 if (!success)
2081 return false;
2082
2084 &success);
2085 if (!success)
2086 return false;
2087
2088 if ((ft_val & 1) != 0)
2089 target = pc + 4 + offset;
2090 else
2091 target = pc + 8;
2092
2093 Context context;
2094
2096 target);
2097}
2098
2099/*
2100 Emulate MIPS-3D Branch instructions
2101 BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes
2102 False/True
2103 BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes
2104 False/True
2105*/
2107 bool success = false;
2108 uint32_t cc, fcsr;
2109 int64_t pc, offset, target = 0;
2110 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2111
2112 cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2113 offset = insn.getOperand(1).getImm();
2114
2116 if (!success)
2117 return false;
2118
2120 0, &success);
2121 if (!success)
2122 return false;
2123
2124 /* fcsr[23], fcsr[25-31] are vaild condition bits */
2125 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2126
2127 if (op_name.equals_insensitive("BC1ANY2F")) {
2128 /* if any one bit is 0 */
2129 if (((fcsr >> cc) & 3) != 3)
2130 target = pc + offset;
2131 else
2132 target = pc + 8;
2133 } else if (op_name.equals_insensitive("BC1ANY2T")) {
2134 /* if any one bit is 1 */
2135 if (((fcsr >> cc) & 3) != 0)
2136 target = pc + offset;
2137 else
2138 target = pc + 8;
2139 } else if (op_name.equals_insensitive("BC1ANY4F")) {
2140 /* if any one bit is 0 */
2141 if (((fcsr >> cc) & 0xf) != 0xf)
2142 target = pc + offset;
2143 else
2144 target = pc + 8;
2145 } else if (op_name.equals_insensitive("BC1ANY4T")) {
2146 /* if any one bit is 1 */
2147 if (((fcsr >> cc) & 0xf) != 0)
2148 target = pc + offset;
2149 else
2150 target = pc + 8;
2151 }
2152
2153 Context context;
2154
2156 target);
2157}
2158
2160 return Emulate_MSA_Branch_DF(insn, 1, true);
2161}
2162
2164 return Emulate_MSA_Branch_DF(insn, 2, true);
2165}
2166
2168 return Emulate_MSA_Branch_DF(insn, 4, true);
2169}
2170
2172 return Emulate_MSA_Branch_DF(insn, 8, true);
2173}
2174
2176 return Emulate_MSA_Branch_DF(insn, 1, false);
2177}
2178
2180 return Emulate_MSA_Branch_DF(insn, 2, false);
2181}
2182
2184 return Emulate_MSA_Branch_DF(insn, 4, false);
2185}
2186
2188 return Emulate_MSA_Branch_DF(insn, 8, false);
2189}
2190
2192 int element_byte_size,
2193 bool bnz) {
2194 bool success = false, branch_hit = true;
2195 int64_t target = 0;
2196 RegisterValue reg_value;
2197 const uint8_t *ptr = nullptr;
2198
2199 uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2200 int64_t offset = insn.getOperand(1).getImm();
2201
2202 int64_t pc =
2204 if (!success)
2205 return false;
2206
2207 if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value))
2208 ptr = (const uint8_t *)reg_value.GetBytes();
2209 else
2210 return false;
2211
2212 for (int i = 0; i < 16 / element_byte_size; i++) {
2213 switch (element_byte_size) {
2214 case 1:
2215 if ((*ptr == 0 && bnz) || (*ptr != 0 && !bnz))
2216 branch_hit = false;
2217 break;
2218 case 2:
2219 if ((*(const uint16_t *)ptr == 0 && bnz) ||
2220 (*(const uint16_t *)ptr != 0 && !bnz))
2221 branch_hit = false;
2222 break;
2223 case 4:
2224 if ((*(const uint32_t *)ptr == 0 && bnz) ||
2225 (*(const uint32_t *)ptr != 0 && !bnz))
2226 branch_hit = false;
2227 break;
2228 case 8:
2229 if ((*(const uint64_t *)ptr == 0 && bnz) ||
2230 (*(const uint64_t *)ptr != 0 && !bnz))
2231 branch_hit = false;
2232 break;
2233 }
2234 if (!branch_hit)
2235 break;
2236 ptr = ptr + element_byte_size;
2237 }
2238
2239 if (branch_hit)
2240 target = pc + offset;
2241 else
2242 target = pc + 8;
2243
2244 Context context;
2246
2248 target);
2249}
2250
2252 return Emulate_MSA_Branch_V(insn, true);
2253}
2254
2256 return Emulate_MSA_Branch_V(insn, false);
2257}
2258
2260 bool bnz) {
2261 bool success = false;
2262 int64_t target = 0;
2263 llvm::APInt wr_val = llvm::APInt::getZero(128);
2264 llvm::APInt fail_value = llvm::APInt::getMaxValue(128);
2265 llvm::APInt zero_value = llvm::APInt::getZero(128);
2266 RegisterValue reg_value;
2267
2268 uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2269 int64_t offset = insn.getOperand(1).getImm();
2270
2271 int64_t pc =
2273 if (!success)
2274 return false;
2275
2276 if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value))
2277 wr_val = reg_value.GetAsUInt128(fail_value);
2278 else
2279 return false;
2280
2281 if ((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) ||
2282 (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz))
2283 target = pc + offset;
2284 else
2285 target = pc + 8;
2286
2287 Context context;
2289
2291 target);
2292}
2293
2295 bool success = false;
2296 uint32_t base;
2297 int64_t imm, address;
2298 Context bad_vaddr_context;
2299
2300 uint32_t num_operands = insn.getNumOperands();
2301 base =
2302 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
2303 imm = insn.getOperand(num_operands - 1).getImm();
2304
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
2338 return false;
2339
2341 return false;
2342
2343 /* read base register */
2345 &success);
2346 if (!success)
2347 return false;
2348
2349 /* read index register */
2351 dwarf_zero_mips + index, 0, &success);
2352 if (!success)
2353 return false;
2354
2355 /* destination address */
2356 address = address + index_address;
2357
2358 /* Set the bad_vaddr register with base address used in the instruction */
2359 bad_vaddr_context.type = eContextInvalid;
2361 address);
2362
2363 return true;
2364}
static llvm::raw_ostream & error(Stream &strm)
static int IsAdd64bitOverflow(int64_t a, int64_t b)
static int IsAdd64bitOverflow(int32_t a, int32_t b)
#define LLDB_PLUGIN_DEFINE_ADV(ClassName, PluginName)
@ dwarf_f12_mips64
@ dwarf_f25_mips64
@ dwarf_w28_mips64
@ dwarf_f28_mips64
@ dwarf_r1_mips64
@ dwarf_fcsr_mips64
@ dwarf_f8_mips64
@ dwarf_w24_mips64
@ dwarf_gp_mips64
@ dwarf_w23_mips64
@ dwarf_f1_mips64
@ dwarf_r7_mips64
@ dwarf_w13_mips64
@ dwarf_f6_mips64
@ dwarf_f19_mips64
@ dwarf_f20_mips64
@ dwarf_sp_mips64
@ dwarf_r13_mips64
@ dwarf_w14_mips64
@ dwarf_r30_mips64
@ dwarf_lo_mips64
@ dwarf_f17_mips64
@ dwarf_w5_mips64
@ dwarf_f2_mips64
@ dwarf_w8_mips64
@ dwarf_f5_mips64
@ dwarf_f3_mips64
@ dwarf_w22_mips64
@ dwarf_f14_mips64
@ dwarf_f26_mips64
@ dwarf_w11_mips64
@ dwarf_f7_mips64
@ dwarf_r8_mips64
@ dwarf_w9_mips64
@ dwarf_w3_mips64
@ dwarf_w27_mips64
@ dwarf_w12_mips64
@ dwarf_w0_mips64
@ dwarf_f18_mips64
@ dwarf_sr_mips64
@ dwarf_hi_mips64
@ dwarf_f31_mips64
@ dwarf_r19_mips64
@ dwarf_bad_mips64
@ dwarf_f4_mips64
@ dwarf_r3_mips64
@ dwarf_r18_mips64
@ dwarf_f30_mips64
@ dwarf_f15_mips64
@ dwarf_r27_mips64
@ dwarf_mcsr_mips64
@ dwarf_w19_mips64
@ dwarf_w16_mips64
@ dwarf_r5_mips64
@ dwarf_cause_mips64
@ dwarf_r4_mips64
@ dwarf_f22_mips64
@ dwarf_w4_mips64
@ dwarf_r20_mips64
@ dwarf_r11_mips64
@ dwarf_w29_mips64
@ dwarf_r21_mips64
@ dwarf_r22_mips64
@ dwarf_w7_mips64
@ dwarf_f13_mips64
@ dwarf_r6_mips64
@ dwarf_pc_mips64
@ dwarf_f9_mips64
@ dwarf_f10_mips64
@ dwarf_f23_mips64
@ dwarf_r10_mips64
@ dwarf_w31_mips64
@ dwarf_w2_mips64
@ dwarf_f21_mips64
@ dwarf_w6_mips64
@ dwarf_w1_mips64
@ dwarf_f11_mips64
@ dwarf_w26_mips64
@ dwarf_w30_mips64
@ dwarf_w18_mips64
@ dwarf_w15_mips64
@ dwarf_f24_mips64
@ dwarf_f29_mips64
@ dwarf_w17_mips64
@ dwarf_w25_mips64
@ dwarf_f27_mips64
@ dwarf_f16_mips64
@ dwarf_r24_mips64
@ dwarf_r9_mips64
@ dwarf_r23_mips64
@ dwarf_mir_mips64
@ dwarf_r14_mips64
@ dwarf_config5_mips64
@ dwarf_fir_mips64
@ dwarf_r26_mips64
@ dwarf_w21_mips64
@ dwarf_f0_mips64
@ dwarf_r2_mips64
@ dwarf_r12_mips64
@ dwarf_r17_mips64
@ dwarf_r25_mips64
@ dwarf_w20_mips64
@ dwarf_w10_mips64
@ dwarf_r15_mips64
@ dwarf_r16_mips64
@ dwarf_ra_mips64
@ dwarf_zero_mips64
@ dwarf_bad_mips
@ dwarf_zero_mips
std::unique_ptr< llvm::MCAsmInfo > m_asm_info
const char * GetRegisterName(unsigned reg_num, bool alternate_name)
bool Emulate_FP_branch(llvm::MCInst &insn)
bool Emulate_JIALC(llvm::MCInst &insn)
bool Emulate_BNZH(llvm::MCInst &insn)
bool Emulate_BXX_2ops(llvm::MCInst &insn)
static lldb_private::EmulateInstruction * CreateInstance(const lldb_private::ArchSpec &arch, lldb_private::InstructionType inst_type)
bool Emulate_Bcond_Link_C(llvm::MCInst &insn)
bool Emulate_SD(llvm::MCInst &insn)
bool Emulate_LD(llvm::MCInst &insn)
bool Emulate_BAL(llvm::MCInst &insn)
bool Emulate_BC(llvm::MCInst &insn)
bool Emulate_BXX_3ops_C(llvm::MCInst &insn)
bool Emulate_MSA_Branch_V(llvm::MCInst &insn, bool bnz)
bool Emulate_BZD(llvm::MCInst &insn)
bool Emulate_BNZV(llvm::MCInst &insn)
bool Emulate_BXX_3ops(llvm::MCInst &insn)
bool SetTargetTriple(const lldb_private::ArchSpec &arch) override
std::unique_ptr< llvm::MCDisassembler > m_disasm
bool Emulate_JR(llvm::MCInst &insn)
bool Emulate_JIC(llvm::MCInst &insn)
bool Emulate_LUI(llvm::MCInst &insn)
std::unique_ptr< llvm::MCContext > m_context
static MipsOpcode * GetOpcodeForInstruction(llvm::StringRef op_name)
bool Emulate_BXX_2ops_C(llvm::MCInst &insn)
bool Emulate_BNZB(llvm::MCInst &insn)
bool Emulate_3D_branch(llvm::MCInst &insn)
bool Emulate_BNZD(llvm::MCInst &insn)
static llvm::StringRef GetPluginDescriptionStatic()
static bool SupportsEmulatingInstructionsOfTypeStatic(lldb_private::InstructionType inst_type)
bool Emulate_LDST_Reg(llvm::MCInst &insn)
bool Emulate_LDST_Imm(llvm::MCInst &insn)
bool Emulate_BZW(llvm::MCInst &insn)
bool Emulate_DSUBU_DADDU(llvm::MCInst &insn)
bool Emulate_BZB(llvm::MCInst &insn)
bool Emulate_JALR(llvm::MCInst &insn)
bool Emulate_DADDiu(llvm::MCInst &insn)
std::unique_ptr< llvm::MCSubtargetInfo > m_subtype_info
std::unique_ptr< llvm::MCInstrInfo > m_insn_info
bool Emulate_BC1NEZ(llvm::MCInst &insn)
bool Emulate_MSA_Branch_DF(llvm::MCInst &insn, int element_byte_size, bool bnz)
std::unique_ptr< llvm::MCRegisterInfo > m_reg_info
bool Emulate_Bcond_Link(llvm::MCInst &insn)
bool Emulate_BC1EQZ(llvm::MCInst &insn)
bool Emulate_BZH(llvm::MCInst &insn)
bool Emulate_JAL(llvm::MCInst &insn)
bool Emulate_BZV(llvm::MCInst &insn)
bool CreateFunctionEntryUnwind(lldb_private::UnwindPlan &unwind_plan) override
EmulateInstructionMIPS64(const lldb_private::ArchSpec &arch)
bool Emulate_BALC(llvm::MCInst &insn)
std::optional< lldb_private::RegisterInfo > GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num) override
bool Emulate_BNZW(llvm::MCInst &insn)
static llvm::StringRef GetPluginNameStatic()
bool EvaluateInstruction(uint32_t evaluate_options) override
An architecture specification class.
Definition ArchSpec.h:32
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition ArchSpec.h:457
uint32_t GetFlags() const
Definition ArchSpec.h:528
Core GetCore() const
Definition ArchSpec.h:448
An data extractor class.
virtual uint64_t GetByteSize() const
Get the number of bytes contained in this object.
const uint8_t * GetDataStart() const
Get the data start pointer.
"lldb/Core/EmulateInstruction.h" A class that allows emulation of CPU opcodes.
lldb::ByteOrder GetByteOrder() const
std::optional< RegisterValue > ReadRegister(const RegisterInfo &reg_info)
bool WriteRegister(const Context &context, const RegisterInfo &ref_info, const RegisterValue &reg_value)
bool WriteRegisterUnsigned(const Context &context, const RegisterInfo &reg_info, uint64_t reg_value)
bool WriteMemory(const Context &context, lldb::addr_t addr, const void *src, size_t src_len)
uint64_t ReadMemoryUnsigned(const Context &context, lldb::addr_t addr, size_t byte_size, uint64_t fail_value, bool *success_ptr)
uint64_t ReadRegisterUnsigned(const RegisterInfo &reg_info, uint64_t fail_value, bool *success_ptr)
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
llvm::APInt GetAsUInt128(const llvm::APInt &fail_value, bool *success_ptr=nullptr) const
const void * GetBytes() const
llvm::SmallVector< uint8_t, kTypicalRegisterByteSize > BytesContainer
An error handling class.
Definition Status.h:118
void SetIsRegisterPlusOffset(uint32_t reg_num, int32_t offset)
Definition UnwindPlan.h:240
const FAValue & GetCFAValue() const
Definition UnwindPlan.h:365
bool SetRegisterLocationToRegister(uint32_t reg_num, uint32_t other_reg_num, bool can_replace)
void SetUnwindPlanForSignalTrap(lldb_private::LazyBool is_for_signal_trap)
Definition UnwindPlan.h:525
void SetRegisterKind(lldb::RegisterKind kind)
Definition UnwindPlan.h:462
void SetReturnAddressRegister(uint32_t regnum)
Definition UnwindPlan.h:464
void SetSourcedFromCompiler(lldb_private::LazyBool from_compiler)
Definition UnwindPlan.h:501
void SetSourceName(const char *)
void SetUnwindPlanValidAtAllInstructions(lldb_private::LazyBool valid_at_all_insn)
Definition UnwindPlan.h:513
#define LLDB_REGNUM_GENERIC_RA
#define LLDB_REGNUM_GENERIC_SP
#define LLDB_REGNUM_GENERIC_FLAGS
#define LLDB_INVALID_ADDRESS
#define LLDB_INVALID_REGNUM
#define LLDB_REGNUM_GENERIC_PC
#define LLDB_REGNUM_GENERIC_FP
A class that represents a running process on the host machine.
InstructionType
Instruction types.
static int64_t SignedBits(const uint64_t value, const uint64_t msbit, const uint64_t lsbit)
@ eFormatVectorOfUInt8
@ eEncodingVector
vector registers
@ eEncodingUint
unsigned integer
RegisterKind
Register numbering types.
@ eRegisterKindGeneric
insn ptr reg, stack ptr reg, etc not specific to any particular target
@ eRegisterKindDWARF
the register numbers seen DWARF
bool(EmulateInstructionMIPS64::* callback)(llvm::MCInst &insn)
void SetRegisterPlusOffset(RegisterInfo base_reg, int64_t signed_offset)
void SetImmediateSigned(int64_t signed_immediate)
void SetRegisterToRegisterPlusOffset(RegisterInfo data_reg, RegisterInfo base_reg, int64_t offset)
Every register is described in detail including its name, alternate name (optional),...
lldb::Encoding encoding
Encoding of the register bits.
const char * alt_name
Alternate name of this register, can be NULL.
uint32_t byte_size
Size in bytes of the register.
uint32_t kinds[lldb::kNumRegisterKinds]
Holds all of the various register numbers for all register kinds.
const char * name
Name of this register, can't be NULL.
lldb::Format format
Default display format.