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