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