LLDB mainline
EmulateInstructionMIPS.cpp
Go to the documentation of this file.
1//===-- EmulateInstructionMIPS.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"
18#include "lldb/Target/Target.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// EmulateInstructionMIPS 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
150 m_reg_info.reset(target->createMCRegInfo(triple));
151 assert(m_reg_info.get());
152
153 m_insn_info.reset(target->createMCInstrInfo());
154 assert(m_insn_info.get());
155
156 m_asm_info.reset(target->createMCAsmInfo(*m_reg_info, triple, m_mc_options));
157 m_subtype_info.reset(target->createMCSubtargetInfo(triple, cpu, features));
158 assert(m_asm_info.get() && m_subtype_info.get());
159
160 m_context = std::make_unique<llvm::MCContext>(
161 triple, m_asm_info.get(), m_reg_info.get(), m_subtype_info.get());
162 assert(m_context.get());
163
164 m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context));
165 assert(m_disasm.get());
166
167 /* Create alternate disassembler for microMIPS */
168 if (arch_flags & ArchSpec::eMIPSAse_mips16)
169 features += "+mips16,";
170 else if (arch_flags & ArchSpec::eMIPSAse_micromips)
171 features += "+micromips,";
172
173 m_alt_subtype_info.reset(
174 target->createMCSubtargetInfo(triple, cpu, features));
175 assert(m_alt_subtype_info.get());
176
177 m_alt_disasm.reset(
178 target->createMCDisassembler(*m_alt_subtype_info, *m_context));
179 assert(m_alt_disasm.get());
180
182 m_use_alt_disaasm = false;
183}
184
189
193
195 return "Emulate instructions for the MIPS32 architecture.";
196}
197
200 InstructionType inst_type) {
202 inst_type)) {
203 if (arch.GetTriple().getArch() == llvm::Triple::mips ||
204 arch.GetTriple().getArch() == llvm::Triple::mipsel) {
205 return new EmulateInstructionMIPS(arch);
206 }
207 }
208
209 return nullptr;
210}
211
213 return arch.GetTriple().getArch() == llvm::Triple::mips ||
214 arch.GetTriple().getArch() == llvm::Triple::mipsel;
215}
216
217const char *EmulateInstructionMIPS::GetRegisterName(unsigned reg_num,
218 bool alternate_name) {
219 if (alternate_name) {
220 switch (reg_num) {
221 case dwarf_sp_mips:
222 return "r29";
223 case dwarf_r30_mips:
224 return "r30";
225 case dwarf_ra_mips:
226 return "r31";
227 case dwarf_f0_mips:
228 return "f0";
229 case dwarf_f1_mips:
230 return "f1";
231 case dwarf_f2_mips:
232 return "f2";
233 case dwarf_f3_mips:
234 return "f3";
235 case dwarf_f4_mips:
236 return "f4";
237 case dwarf_f5_mips:
238 return "f5";
239 case dwarf_f6_mips:
240 return "f6";
241 case dwarf_f7_mips:
242 return "f7";
243 case dwarf_f8_mips:
244 return "f8";
245 case dwarf_f9_mips:
246 return "f9";
247 case dwarf_f10_mips:
248 return "f10";
249 case dwarf_f11_mips:
250 return "f11";
251 case dwarf_f12_mips:
252 return "f12";
253 case dwarf_f13_mips:
254 return "f13";
255 case dwarf_f14_mips:
256 return "f14";
257 case dwarf_f15_mips:
258 return "f15";
259 case dwarf_f16_mips:
260 return "f16";
261 case dwarf_f17_mips:
262 return "f17";
263 case dwarf_f18_mips:
264 return "f18";
265 case dwarf_f19_mips:
266 return "f19";
267 case dwarf_f20_mips:
268 return "f20";
269 case dwarf_f21_mips:
270 return "f21";
271 case dwarf_f22_mips:
272 return "f22";
273 case dwarf_f23_mips:
274 return "f23";
275 case dwarf_f24_mips:
276 return "f24";
277 case dwarf_f25_mips:
278 return "f25";
279 case dwarf_f26_mips:
280 return "f26";
281 case dwarf_f27_mips:
282 return "f27";
283 case dwarf_f28_mips:
284 return "f28";
285 case dwarf_f29_mips:
286 return "f29";
287 case dwarf_f30_mips:
288 return "f30";
289 case dwarf_f31_mips:
290 return "f31";
291 case dwarf_w0_mips:
292 return "w0";
293 case dwarf_w1_mips:
294 return "w1";
295 case dwarf_w2_mips:
296 return "w2";
297 case dwarf_w3_mips:
298 return "w3";
299 case dwarf_w4_mips:
300 return "w4";
301 case dwarf_w5_mips:
302 return "w5";
303 case dwarf_w6_mips:
304 return "w6";
305 case dwarf_w7_mips:
306 return "w7";
307 case dwarf_w8_mips:
308 return "w8";
309 case dwarf_w9_mips:
310 return "w9";
311 case dwarf_w10_mips:
312 return "w10";
313 case dwarf_w11_mips:
314 return "w11";
315 case dwarf_w12_mips:
316 return "w12";
317 case dwarf_w13_mips:
318 return "w13";
319 case dwarf_w14_mips:
320 return "w14";
321 case dwarf_w15_mips:
322 return "w15";
323 case dwarf_w16_mips:
324 return "w16";
325 case dwarf_w17_mips:
326 return "w17";
327 case dwarf_w18_mips:
328 return "w18";
329 case dwarf_w19_mips:
330 return "w19";
331 case dwarf_w20_mips:
332 return "w20";
333 case dwarf_w21_mips:
334 return "w21";
335 case dwarf_w22_mips:
336 return "w22";
337 case dwarf_w23_mips:
338 return "w23";
339 case dwarf_w24_mips:
340 return "w24";
341 case dwarf_w25_mips:
342 return "w25";
343 case dwarf_w26_mips:
344 return "w26";
345 case dwarf_w27_mips:
346 return "w27";
347 case dwarf_w28_mips:
348 return "w28";
349 case dwarf_w29_mips:
350 return "w29";
351 case dwarf_w30_mips:
352 return "w30";
353 case dwarf_w31_mips:
354 return "w31";
355 case dwarf_mir_mips:
356 return "mir";
357 case dwarf_mcsr_mips:
358 return "mcsr";
360 return "config5";
361 default:
362 break;
363 }
364 return nullptr;
365 }
366
367 switch (reg_num) {
368 case dwarf_zero_mips:
369 return "r0";
370 case dwarf_r1_mips:
371 return "r1";
372 case dwarf_r2_mips:
373 return "r2";
374 case dwarf_r3_mips:
375 return "r3";
376 case dwarf_r4_mips:
377 return "r4";
378 case dwarf_r5_mips:
379 return "r5";
380 case dwarf_r6_mips:
381 return "r6";
382 case dwarf_r7_mips:
383 return "r7";
384 case dwarf_r8_mips:
385 return "r8";
386 case dwarf_r9_mips:
387 return "r9";
388 case dwarf_r10_mips:
389 return "r10";
390 case dwarf_r11_mips:
391 return "r11";
392 case dwarf_r12_mips:
393 return "r12";
394 case dwarf_r13_mips:
395 return "r13";
396 case dwarf_r14_mips:
397 return "r14";
398 case dwarf_r15_mips:
399 return "r15";
400 case dwarf_r16_mips:
401 return "r16";
402 case dwarf_r17_mips:
403 return "r17";
404 case dwarf_r18_mips:
405 return "r18";
406 case dwarf_r19_mips:
407 return "r19";
408 case dwarf_r20_mips:
409 return "r20";
410 case dwarf_r21_mips:
411 return "r21";
412 case dwarf_r22_mips:
413 return "r22";
414 case dwarf_r23_mips:
415 return "r23";
416 case dwarf_r24_mips:
417 return "r24";
418 case dwarf_r25_mips:
419 return "r25";
420 case dwarf_r26_mips:
421 return "r26";
422 case dwarf_r27_mips:
423 return "r27";
424 case dwarf_gp_mips:
425 return "gp";
426 case dwarf_sp_mips:
427 return "sp";
428 case dwarf_r30_mips:
429 return "fp";
430 case dwarf_ra_mips:
431 return "ra";
432 case dwarf_sr_mips:
433 return "sr";
434 case dwarf_lo_mips:
435 return "lo";
436 case dwarf_hi_mips:
437 return "hi";
438 case dwarf_bad_mips:
439 return "bad";
440 case dwarf_cause_mips:
441 return "cause";
442 case dwarf_pc_mips:
443 return "pc";
444 case dwarf_f0_mips:
445 return "f0";
446 case dwarf_f1_mips:
447 return "f1";
448 case dwarf_f2_mips:
449 return "f2";
450 case dwarf_f3_mips:
451 return "f3";
452 case dwarf_f4_mips:
453 return "f4";
454 case dwarf_f5_mips:
455 return "f5";
456 case dwarf_f6_mips:
457 return "f6";
458 case dwarf_f7_mips:
459 return "f7";
460 case dwarf_f8_mips:
461 return "f8";
462 case dwarf_f9_mips:
463 return "f9";
464 case dwarf_f10_mips:
465 return "f10";
466 case dwarf_f11_mips:
467 return "f11";
468 case dwarf_f12_mips:
469 return "f12";
470 case dwarf_f13_mips:
471 return "f13";
472 case dwarf_f14_mips:
473 return "f14";
474 case dwarf_f15_mips:
475 return "f15";
476 case dwarf_f16_mips:
477 return "f16";
478 case dwarf_f17_mips:
479 return "f17";
480 case dwarf_f18_mips:
481 return "f18";
482 case dwarf_f19_mips:
483 return "f19";
484 case dwarf_f20_mips:
485 return "f20";
486 case dwarf_f21_mips:
487 return "f21";
488 case dwarf_f22_mips:
489 return "f22";
490 case dwarf_f23_mips:
491 return "f23";
492 case dwarf_f24_mips:
493 return "f24";
494 case dwarf_f25_mips:
495 return "f25";
496 case dwarf_f26_mips:
497 return "f26";
498 case dwarf_f27_mips:
499 return "f27";
500 case dwarf_f28_mips:
501 return "f28";
502 case dwarf_f29_mips:
503 return "f29";
504 case dwarf_f30_mips:
505 return "f30";
506 case dwarf_f31_mips:
507 return "f31";
508 case dwarf_fcsr_mips:
509 return "fcsr";
510 case dwarf_fir_mips:
511 return "fir";
512 case dwarf_w0_mips:
513 return "w0";
514 case dwarf_w1_mips:
515 return "w1";
516 case dwarf_w2_mips:
517 return "w2";
518 case dwarf_w3_mips:
519 return "w3";
520 case dwarf_w4_mips:
521 return "w4";
522 case dwarf_w5_mips:
523 return "w5";
524 case dwarf_w6_mips:
525 return "w6";
526 case dwarf_w7_mips:
527 return "w7";
528 case dwarf_w8_mips:
529 return "w8";
530 case dwarf_w9_mips:
531 return "w9";
532 case dwarf_w10_mips:
533 return "w10";
534 case dwarf_w11_mips:
535 return "w11";
536 case dwarf_w12_mips:
537 return "w12";
538 case dwarf_w13_mips:
539 return "w13";
540 case dwarf_w14_mips:
541 return "w14";
542 case dwarf_w15_mips:
543 return "w15";
544 case dwarf_w16_mips:
545 return "w16";
546 case dwarf_w17_mips:
547 return "w17";
548 case dwarf_w18_mips:
549 return "w18";
550 case dwarf_w19_mips:
551 return "w19";
552 case dwarf_w20_mips:
553 return "w20";
554 case dwarf_w21_mips:
555 return "w21";
556 case dwarf_w22_mips:
557 return "w22";
558 case dwarf_w23_mips:
559 return "w23";
560 case dwarf_w24_mips:
561 return "w24";
562 case dwarf_w25_mips:
563 return "w25";
564 case dwarf_w26_mips:
565 return "w26";
566 case dwarf_w27_mips:
567 return "w27";
568 case dwarf_w28_mips:
569 return "w28";
570 case dwarf_w29_mips:
571 return "w29";
572 case dwarf_w30_mips:
573 return "w30";
574 case dwarf_w31_mips:
575 return "w31";
576 case dwarf_mcsr_mips:
577 return "mcsr";
578 case dwarf_mir_mips:
579 return "mir";
581 return "config5";
582 }
583 return nullptr;
584}
585
586std::optional<RegisterInfo>
588 uint32_t reg_num) {
589 if (reg_kind == eRegisterKindGeneric) {
590 switch (reg_num) {
592 reg_kind = eRegisterKindDWARF;
593 reg_num = dwarf_pc_mips;
594 break;
596 reg_kind = eRegisterKindDWARF;
597 reg_num = dwarf_sp_mips;
598 break;
600 reg_kind = eRegisterKindDWARF;
601 reg_num = dwarf_r30_mips;
602 break;
604 reg_kind = eRegisterKindDWARF;
605 reg_num = dwarf_ra_mips;
606 break;
608 reg_kind = eRegisterKindDWARF;
609 reg_num = dwarf_sr_mips;
610 break;
611 default:
612 return {};
613 }
614 }
615
616 if (reg_kind == eRegisterKindDWARF) {
617 RegisterInfo reg_info;
618 ::memset(&reg_info, 0, sizeof(RegisterInfo));
619 ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
620
621 if (reg_num == dwarf_sr_mips || reg_num == dwarf_fcsr_mips ||
622 reg_num == dwarf_fir_mips || reg_num == dwarf_mcsr_mips ||
623 reg_num == dwarf_mir_mips || reg_num == dwarf_config5_mips) {
624 reg_info.byte_size = 4;
625 reg_info.format = eFormatHex;
626 reg_info.encoding = eEncodingUint;
627 } else if ((int)reg_num >= dwarf_zero_mips &&
628 (int)reg_num <= dwarf_f31_mips) {
629 reg_info.byte_size = 4;
630 reg_info.format = eFormatHex;
631 reg_info.encoding = eEncodingUint;
632 } else if ((int)reg_num >= dwarf_w0_mips &&
633 (int)reg_num <= dwarf_w31_mips) {
634 reg_info.byte_size = 16;
635 reg_info.format = eFormatVectorOfUInt8;
636 reg_info.encoding = eEncodingVector;
637 } else {
638 return {};
639 }
640
641 reg_info.name = GetRegisterName(reg_num, false);
642 reg_info.alt_name = GetRegisterName(reg_num, true);
643 reg_info.kinds[eRegisterKindDWARF] = reg_num;
644
645 switch (reg_num) {
646 case dwarf_r30_mips:
648 break;
649 case dwarf_ra_mips:
651 break;
652 case dwarf_sp_mips:
654 break;
655 case dwarf_pc_mips:
657 break;
658 case dwarf_sr_mips:
660 break;
661 default:
662 break;
663 }
664 return reg_info;
665 }
666 return {};
667}
668
671 static EmulateInstructionMIPS::MipsOpcode g_opcodes[] = {
672 // Prologue/Epilogue instructions
674 "ADDIU rt, rs, immediate"},
675 {"SW", &EmulateInstructionMIPS::Emulate_SW, "SW rt, offset(rs)"},
676 {"LW", &EmulateInstructionMIPS::Emulate_LW, "LW rt, offset(base)"},
677 {"SUBU", &EmulateInstructionMIPS::Emulate_SUBU_ADDU, "SUBU rd, rs, rt"},
678 {"ADDU", &EmulateInstructionMIPS::Emulate_SUBU_ADDU, "ADDU rd, rs, rt"},
679 {"LUI", &EmulateInstructionMIPS::Emulate_LUI, "LUI rt, immediate"},
680
681 // MicroMIPS Prologue/Epilogue instructions
683 "ADDIU immediate"},
685 "ADDIUS5 rd,immediate"},
686 {"SWSP_MM", &EmulateInstructionMIPS::Emulate_SWSP, "SWSP rt,offset(sp)"},
688 "SWM16 reglist,offset(sp)"},
690 "SWM32 reglist,offset(base)"},
692 "SWP rs1,offset(base)"},
693 {"LWSP_MM", &EmulateInstructionMIPS::Emulate_LWSP, "LWSP rt,offset(sp)"},
695 "LWM16 reglist,offset(sp)"},
697 "LWM32 reglist,offset(base)"},
699 "LWP rd,offset(base)"},
701 "JRADDIUSP immediate"},
702
703 // Load/Store instructions
704 /* Following list of emulated instructions are required by implementation
705 of hardware watchpoint
706 for MIPS in lldb. As we just need the address accessed by instructions,
707 we have generalised
708 all these instructions in 2 functions depending on their addressing
709 modes */
710
712 "LB rt, offset(base)"},
714 "LBE rt, offset(base)"},
716 "LBU rt, offset(base)"},
718 "LBUE rt, offset(base)"},
720 "LDC1 ft, offset(base)"},
722 "LD rt, offset(base)"},
724 "LDL rt, offset(base)"},
726 "LDR rt, offset(base)"},
728 "LLD rt, offset(base)"},
730 "LDC2 rt, offset(base)"},
732 "LDXC1 fd, index (base)"},
734 "LH rt, offset(base)"},
736 "LHE rt, offset(base)"},
738 "LHU rt, offset(base)"},
740 "LHUE rt, offset(base)"},
742 "LL rt, offset(base)"},
744 "LLE rt, offset(base)"},
746 "LUXC1 fd, index (base)"},
748 "LW rt, offset(base)"},
750 "LWC1 ft, offset(base)"},
752 "LWC2 rt, offset(base)"},
754 "LWE rt, offset(base)"},
756 "LWL rt, offset(base)"},
758 "LWLE rt, offset(base)"},
760 "LWR rt, offset(base)"},
762 "LWRE rt, offset(base)"},
764 "LWXC1 fd, index (base)"},
766 "LLX rt, offset(base)"},
768 "LLXE rt, offset(base)"},
770 "LLDX rt, offset(base)"},
771
773 "SB rt, offset(base)"},
775 "SBE rt, offset(base)"},
777 "SC rt, offset(base)"},
779 "SCE rt, offset(base)"},
781 "SCD rt, offset(base)"},
783 "SD rt, offset(base)"},
785 "SDL rt, offset(base)"},
787 "SDR rt, offset(base)"},
789 "SDC1 ft, offset(base)"},
791 "SDC2 rt, offset(base)"},
793 "SDXC1 fs, index(base)"},
795 "SH rt, offset(base)"},
797 "SHE rt, offset(base)"},
799 "SUXC1 fs, index (base)"},
801 "SWC1 ft, offset(base)"},
803 "SWC2 rt, offset(base)"},
805 "SWE rt, offset(base)"},
807 "SWL rt, offset(base)"},
809 "SWLE rt, offset(base)"},
811 "SWR rt, offset(base)"},
813 "SWRE rt, offset(base)"},
815 "SWXC1 fs, index (base)"},
817 "SCX rt, offset(base)"},
819 "SCXE rt, offset(base)"},
821 "SCDX rt, offset(base)"},
822
823 // MicroMIPS Load/Store instructions
825 "LBU16 rt, decoded_offset(base)"},
827 "LHU16 rt, left_shifted_offset(base)"},
829 "LW16 rt, left_shifted_offset(base)"},
831 "LWGP rt, left_shifted_offset(gp)"},
833 "SH16 rt, left_shifted_offset(base)"},
835 "SW16 rt, left_shifted_offset(base)"},
837 "SWSP rt, left_shifted_offset(base)"},
839 "SB16 rt, offset(base)"},
840
841 // Branch instructions
842 {"BEQ", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BEQ rs,rt,offset"},
843 {"BNE", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BNE rs,rt,offset"},
844 {"BEQL", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BEQL rs,rt,offset"},
845 {"BNEL", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BNEL rs,rt,offset"},
847 "BGEZALL rt,offset"},
848 {"BAL", &EmulateInstructionMIPS::Emulate_BAL, "BAL offset"},
850 "BGEZAL rs,offset"},
851 {"BALC", &EmulateInstructionMIPS::Emulate_BALC, "BALC offset"},
852 {"BC", &EmulateInstructionMIPS::Emulate_BC, "BC offset"},
853 {"BGEZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGEZ rs,offset"},
855 "BLEZALC rs,offset"},
857 "BGEZALC rs,offset"},
859 "BLTZALC rs,offset"},
861 "BGTZALC rs,offset"},
863 "BEQZALC rs,offset"},
865 "BNEZALC rs,offset"},
867 "BEQC rs,rt,offset"},
869 "BNEC rs,rt,offset"},
871 "BLTC rs,rt,offset"},
873 "BGEC rs,rt,offset"},
875 "BLTUC rs,rt,offset"},
877 "BGEUC rs,rt,offset"},
878 {"BLTZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BLTZC rt,offset"},
879 {"BLEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BLEZC rt,offset"},
880 {"BGEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BGEZC rt,offset"},
881 {"BGTZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BGTZC rt,offset"},
882 {"BEQZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BEQZC rt,offset"},
883 {"BNEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BNEZC rt,offset"},
884 {"BGEZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGEZL rt,offset"},
885 {"BGTZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGTZ rt,offset"},
886 {"BGTZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGTZL rt,offset"},
887 {"BLEZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLEZ rt,offset"},
888 {"BLEZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLEZL rt,offset"},
889 {"BLTZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLTZ rt,offset"},
891 "BLTZAL rt,offset"},
893 "BLTZALL rt,offset"},
894 {"BLTZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLTZL rt,offset"},
896 "BOVC rs,rt,offset"},
898 "BNVC rs,rt,offset"},
899 {"J", &EmulateInstructionMIPS::Emulate_J, "J target"},
900 {"JAL", &EmulateInstructionMIPS::Emulate_JAL, "JAL target"},
901 {"JALX", &EmulateInstructionMIPS::Emulate_JAL, "JALX target"},
902 {"JALR", &EmulateInstructionMIPS::Emulate_JALR, "JALR target"},
903 {"JALR_HB", &EmulateInstructionMIPS::Emulate_JALR, "JALR.HB target"},
904 {"JIALC", &EmulateInstructionMIPS::Emulate_JIALC, "JIALC rt,offset"},
905 {"JIC", &EmulateInstructionMIPS::Emulate_JIC, "JIC rt,offset"},
906 {"JR", &EmulateInstructionMIPS::Emulate_JR, "JR target"},
907 {"JR_HB", &EmulateInstructionMIPS::Emulate_JR, "JR.HB target"},
908 {"BC1F", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1F cc, offset"},
909 {"BC1T", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1T cc, offset"},
910 {"BC1FL", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1FL cc, offset"},
911 {"BC1TL", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1TL cc, offset"},
912 {"BC1EQZ", &EmulateInstructionMIPS::Emulate_BC1EQZ, "BC1EQZ ft, offset"},
913 {"BC1NEZ", &EmulateInstructionMIPS::Emulate_BC1NEZ, "BC1NEZ ft, offset"},
915 "BC1ANY2F cc, offset"},
917 "BC1ANY2T cc, offset"},
919 "BC1ANY4F cc, offset"},
921 "BC1ANY4T cc, offset"},
922 {"BNZ_B", &EmulateInstructionMIPS::Emulate_BNZB, "BNZ.b wt,s16"},
923 {"BNZ_H", &EmulateInstructionMIPS::Emulate_BNZH, "BNZ.h wt,s16"},
924 {"BNZ_W", &EmulateInstructionMIPS::Emulate_BNZW, "BNZ.w wt,s16"},
925 {"BNZ_D", &EmulateInstructionMIPS::Emulate_BNZD, "BNZ.d wt,s16"},
926 {"BZ_B", &EmulateInstructionMIPS::Emulate_BZB, "BZ.b wt,s16"},
927 {"BZ_H", &EmulateInstructionMIPS::Emulate_BZH, "BZ.h wt,s16"},
928 {"BZ_W", &EmulateInstructionMIPS::Emulate_BZW, "BZ.w wt,s16"},
929 {"BZ_D", &EmulateInstructionMIPS::Emulate_BZD, "BZ.d wt,s16"},
930 {"BNZ_V", &EmulateInstructionMIPS::Emulate_BNZV, "BNZ.V wt,s16"},
931 {"BZ_V", &EmulateInstructionMIPS::Emulate_BZV, "BZ.V wt,s16"},
932
933 // MicroMIPS Branch instructions
934 {"B16_MM", &EmulateInstructionMIPS::Emulate_B16_MM, "B16 offset"},
936 "BEQZ16 rs, offset"},
938 "BNEZ16 rs, offset"},
940 "BEQZC rs, offset"},
942 "BNEZC rs, offset"},
944 "BGEZALS rs, offset"},
946 "BLTZALS rs, offset"},
947 {"JALR16_MM", &EmulateInstructionMIPS::Emulate_JALRx16_MM, "JALR16 rs"},
948 {"JALRS16_MM", &EmulateInstructionMIPS::Emulate_JALRx16_MM, "JALRS16 rs"},
949 {"JR16_MM", &EmulateInstructionMIPS::Emulate_JR, "JR16 rs rs"},
950 {"JRC16_MM", &EmulateInstructionMIPS::Emulate_JR, "JRC16 rs rs"},
951 {"JALS_MM", &EmulateInstructionMIPS::Emulate_JALx, "JALS target"},
952 {"JALX_MM", &EmulateInstructionMIPS::Emulate_JALx, "JALX target"},
953 {"JALRS_MM", &EmulateInstructionMIPS::Emulate_JALRS, "JALRS rt, rs"},
954 };
955
956 for (MipsOpcode &opcode : g_opcodes) {
957 if (name.equals_insensitive(opcode.op_name))
958 return &opcode;
959 }
960 return nullptr;
961}
962
963uint32_t
965 uint64_t inst_addr) {
966 uint64_t next_inst_size = 0;
967 llvm::MCInst mc_insn;
968 llvm::MCDisassembler::DecodeStatus decode_status;
969 llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());
970
972 decode_status = m_alt_disasm->getInstruction(
973 mc_insn, next_inst_size, raw_insn, inst_addr, llvm::nulls());
974 else
975 decode_status = m_disasm->getInstruction(mc_insn, next_inst_size, raw_insn,
976 inst_addr, llvm::nulls());
977
978 if (decode_status != llvm::MCDisassembler::Success)
979 return false;
980
981 return m_insn_info->get(mc_insn.getOpcode()).getSize();
982}
983
985 const Address &inst_addr,
986 Target *target) {
987 m_use_alt_disaasm = false;
988
989 if (EmulateInstruction::SetInstruction(insn_opcode, inst_addr, target)) {
993
994 /*
995 * The address belongs to microMIPS function. To find the size of
996 * next instruction use microMIPS disassembler.
997 */
998 m_use_alt_disaasm = true;
999
1000 uint32_t current_inst_size = insn_opcode.GetByteSize();
1001 uint8_t buf[sizeof(uint32_t)];
1002 uint64_t next_inst_addr = (m_addr & (~1ull)) + current_inst_size;
1003 Address next_addr(next_inst_addr);
1004
1005 const size_t bytes_read = target->ReadMemory(
1006 next_addr, /* Address of next instruction */
1007 buf, sizeof(uint32_t), error, false, /* force_live_memory */
1008 &load_addr);
1009
1010 if (bytes_read == 0)
1011 return true;
1012
1013 DataExtractor data(buf, sizeof(uint32_t), GetByteOrder(),
1015 m_next_inst_size = GetSizeOfInstruction(data, next_inst_addr);
1016 return true;
1017 } else {
1018 /*
1019 * If the address class is not AddressClass::eCodeAlternateISA then
1020 * the function is not microMIPS. In this case instruction size is
1021 * always 4 bytes.
1022 */
1023 m_next_inst_size = 4;
1024 return true;
1025 }
1026 }
1027 return false;
1028}
1029
1031 bool success = false;
1033 LLDB_INVALID_ADDRESS, &success);
1034 if (success) {
1035 Context read_inst_context;
1036 read_inst_context.type = eContextReadOpcode;
1037 read_inst_context.SetNoArgs();
1038 m_opcode.SetOpcode32(
1039 ReadMemoryUnsigned(read_inst_context, m_addr, 4, 0, &success),
1040 GetByteOrder());
1041 }
1042 if (!success)
1044 return success;
1045}
1046
1047bool EmulateInstructionMIPS::EvaluateInstruction(uint32_t evaluate_options) {
1048 bool success = false;
1049 llvm::MCInst mc_insn;
1050 uint64_t insn_size;
1051 DataExtractor data;
1052
1053 /* Keep the complexity of the decode logic with the llvm::MCDisassembler
1054 * class. */
1055 if (m_opcode.GetData(data)) {
1056 llvm::MCDisassembler::DecodeStatus decode_status;
1057 llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());
1059 decode_status = m_alt_disasm->getInstruction(mc_insn, insn_size, raw_insn,
1060 m_addr, llvm::nulls());
1061 else
1062 decode_status = m_disasm->getInstruction(mc_insn, insn_size, raw_insn,
1063 m_addr, llvm::nulls());
1064
1065 if (decode_status != llvm::MCDisassembler::Success)
1066 return false;
1067 }
1068
1069 /*
1070 * mc_insn.getOpcode() returns decoded opcode. However to make use
1071 * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc".
1072 */
1073 const char *op_name = m_insn_info->getName(mc_insn.getOpcode()).data();
1074
1075 if (op_name == nullptr)
1076 return false;
1077
1078 /*
1079 * Decoding has been done already. Just get the call-back function
1080 * and emulate the instruction.
1081 */
1082 MipsOpcode *opcode_data = GetOpcodeForInstruction(op_name);
1083
1084 if (opcode_data == nullptr)
1085 return false;
1086
1087 uint64_t old_pc = 0, new_pc = 0;
1088 const bool auto_advance_pc =
1089 evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
1090
1091 if (auto_advance_pc) {
1092 old_pc =
1094 if (!success)
1095 return false;
1096 }
1097
1098 /* emulate instruction */
1099 success = (this->*opcode_data->callback)(mc_insn);
1100 if (!success)
1101 return false;
1102
1103 if (auto_advance_pc) {
1104 new_pc =
1106 if (!success)
1107 return false;
1108
1109 /* If we haven't changed the PC, change it here */
1110 if (old_pc == new_pc) {
1111 new_pc += 4;
1112 Context context;
1114 new_pc))
1115 return false;
1116 }
1117 }
1118
1119 return true;
1120}
1121
1123 UnwindPlan &unwind_plan) {
1124 unwind_plan.Clear();
1126
1127 UnwindPlan::Row row;
1128 const bool can_replace = false;
1129
1130 // Our previous Call Frame Address is the stack pointer
1132
1133 // Our previous PC is in the RA
1135
1136 unwind_plan.AppendRow(std::move(row));
1137
1138 // All other registers are the same.
1139 unwind_plan.SetSourceName("EmulateInstructionMIPS");
1144
1145 return true;
1146}
1147
1149 switch (regnum) {
1150 case dwarf_r16_mips:
1151 case dwarf_r17_mips:
1152 case dwarf_r18_mips:
1153 case dwarf_r19_mips:
1154 case dwarf_r20_mips:
1155 case dwarf_r21_mips:
1156 case dwarf_r22_mips:
1157 case dwarf_r23_mips:
1158 case dwarf_gp_mips:
1159 case dwarf_sp_mips:
1160 case dwarf_r30_mips:
1161 case dwarf_ra_mips:
1162 return true;
1163 default:
1164 return false;
1165 }
1166 return false;
1167}
1168
1170 // ADDIU rt, rs, immediate
1171 // GPR[rt] <- GPR[rs] + sign_extend(immediate)
1172
1173 uint8_t dst, src;
1174 bool success = false;
1175 const uint32_t imm16 = insn.getOperand(2).getImm();
1176 int64_t imm = SignedBits(imm16, 15, 0);
1177
1178 dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1179 src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1180
1181 // If immediate value is greater then 2^16 - 1 then clang generate LUI,
1182 // ADDIU, SUBU instructions in prolog. Example lui $1, 0x2 addiu $1, $1,
1183 // -0x5920 subu $sp, $sp, $1 In this case, ADDIU dst and src will be same
1184 // and not equal to sp
1185 if (dst == src) {
1186 Context context;
1187
1188 /* read <src> register */
1189 const int64_t src_opd_val = ReadRegisterUnsigned(
1190 eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success);
1191 if (!success)
1192 return false;
1193
1194 /* Check if this is daddiu sp, sp, imm16 */
1195 if (dst == dwarf_sp_mips) {
1196 uint64_t result = src_opd_val + imm;
1197 std::optional<RegisterInfo> reg_info_sp =
1199 if (reg_info_sp)
1200 context.SetRegisterPlusOffset(*reg_info_sp, imm);
1201
1202 /* We are allocating bytes on stack */
1204
1206 return true;
1207 }
1208
1209 imm += src_opd_val;
1210 context.SetImmediateSigned(imm);
1211 context.type = eContextImmediate;
1212
1214 dwarf_zero_mips + dst, imm))
1215 return false;
1216 }
1217
1218 return true;
1219}
1220
1221bool EmulateInstructionMIPS::Emulate_SW(llvm::MCInst &insn) {
1222 bool success = false;
1223 uint32_t imm16 = insn.getOperand(2).getImm();
1224 uint32_t imm = SignedBits(imm16, 15, 0);
1225 uint32_t src, base;
1226 int32_t address;
1227 Context bad_vaddr_context;
1228
1229 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1230 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1231
1232 std::optional<RegisterInfo> reg_info_base =
1234 if (!reg_info_base)
1235 return false;
1236
1237 /* read base register */
1238 address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1239 dwarf_zero_mips + base, 0, &success);
1240 if (!success)
1241 return false;
1242
1243 /* destination address */
1244 address = address + imm;
1245
1246 /* Set the bad_vaddr register with base address used in the instruction */
1247 bad_vaddr_context.type = eContextInvalid;
1249 address);
1250
1251 /* We look for sp based non-volatile register stores */
1252 if (nonvolatile_reg_p(src)) {
1253 std::optional<RegisterInfo> reg_info_src =
1255 if (!reg_info_src)
1256 return false;
1257
1258 Context context;
1260 context.SetRegisterToRegisterPlusOffset(*reg_info_src, *reg_info_base, 0);
1261
1262 RegisterValue::BytesContainer buffer(reg_info_src->byte_size);
1263 Status error;
1264
1265 std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);
1266 if (!data_src)
1267 return false;
1268
1269 if (data_src->GetAsMemoryData(*reg_info_src, buffer.data(),
1270 reg_info_src->byte_size, eByteOrderLittle,
1271 error) == 0)
1272 return false;
1273
1274 if (!WriteMemory(context, address, buffer.data(), reg_info_src->byte_size))
1275 return false;
1276
1277 return true;
1278 }
1279
1280 return false;
1281}
1282
1283bool EmulateInstructionMIPS::Emulate_LW(llvm::MCInst &insn) {
1284 bool success = false;
1285 uint32_t src, base;
1286 int32_t imm, address;
1287 Context bad_vaddr_context;
1288
1289 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1290 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1291 imm = insn.getOperand(2).getImm();
1292
1294 return false;
1295
1296 /* read base register */
1297 address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1298 dwarf_zero_mips + base, 0, &success);
1299 if (!success)
1300 return false;
1301
1302 /* destination address */
1303 address = address + imm;
1304
1305 /* Set the bad_vaddr register with base address used in the instruction */
1306 bad_vaddr_context.type = eContextInvalid;
1308 address);
1309
1310 if (nonvolatile_reg_p(src)) {
1311 RegisterValue data_src;
1312 std::optional<RegisterInfo> reg_info_src =
1314 if (!reg_info_src)
1315 return false;
1316
1317 Context context;
1319 context.SetAddress(address);
1320
1321 return WriteRegister(context, *reg_info_src, data_src);
1322 }
1323
1324 return false;
1325}
1326
1328 // SUBU sp, <src>, <rt>
1329 // ADDU sp, <src>, <rt>
1330 // ADDU dst, sp, <rt>
1331
1332 bool success = false;
1333 uint64_t result;
1334 uint8_t src, dst, rt;
1335 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1336
1337 dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1338 src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1339
1340 /* Check if sp is destination register */
1341 if (dst == dwarf_sp_mips) {
1342 rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1343
1344 /* read <src> register */
1345 uint64_t src_opd_val = ReadRegisterUnsigned(
1346 eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success);
1347 if (!success)
1348 return false;
1349
1350 /* read <rt > register */
1351 uint64_t rt_opd_val = ReadRegisterUnsigned(
1352 eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
1353 if (!success)
1354 return false;
1355
1356 if (op_name.equals_insensitive("SUBU"))
1357 result = src_opd_val - rt_opd_val;
1358 else
1359 result = src_opd_val + rt_opd_val;
1360
1361 Context context;
1362 std::optional<RegisterInfo> reg_info_sp =
1364 if (reg_info_sp)
1365 context.SetRegisterPlusOffset(*reg_info_sp, rt_opd_val);
1366
1367 /* We are allocating bytes on stack */
1369
1371
1372 return true;
1373 } else if (src == dwarf_sp_mips) {
1374 rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1375
1376 /* read <src> register */
1377 uint64_t src_opd_val = ReadRegisterUnsigned(
1378 eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success);
1379 if (!success)
1380 return false;
1381
1382 /* read <rt> register */
1383 uint64_t rt_opd_val = ReadRegisterUnsigned(
1384 eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
1385 if (!success)
1386 return false;
1387
1388 Context context;
1389
1390 if (op_name.equals_insensitive("SUBU"))
1391 result = src_opd_val - rt_opd_val;
1392 else
1393 result = src_opd_val + rt_opd_val;
1394
1395 context.SetImmediateSigned(result);
1396 context.type = eContextImmediate;
1397
1399 dwarf_zero_mips + dst, result))
1400 return false;
1401 }
1402
1403 return true;
1404}
1405
1406bool EmulateInstructionMIPS::Emulate_LUI(llvm::MCInst &insn) {
1407 // LUI rt, immediate
1408 // GPR[rt] <- sign_extend(immediate << 16)
1409
1410 const uint32_t imm32 = insn.getOperand(1).getImm() << 16;
1411 int64_t imm = SignedBits(imm32, 31, 0);
1412 uint8_t rt;
1413 Context context;
1414
1415 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1416 context.SetImmediateSigned(imm);
1417 context.type = eContextImmediate;
1418
1420 dwarf_zero_mips + rt, imm);
1421}
1422
1424 bool success = false;
1425 const uint32_t imm9 = insn.getOperand(0).getImm();
1426 uint64_t result;
1427
1428 // This instruction operates implicitly on stack pointer, so read <sp>
1429 // register.
1430 uint64_t src_opd_val =
1432 if (!success)
1433 return false;
1434
1435 result = src_opd_val + imm9;
1436
1437 Context context;
1438 std::optional<RegisterInfo> reg_info_sp =
1440 if (reg_info_sp)
1441 context.SetRegisterPlusOffset(*reg_info_sp, imm9);
1442
1443 // We are adjusting the stack.
1445
1447 return true;
1448}
1449
1451 bool success = false;
1452 uint32_t base;
1453 const uint32_t imm4 = insn.getOperand(2).getImm();
1454 uint64_t result;
1455
1456 // The source and destination register is same for this instruction.
1457 base = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1458
1459 // We are looking for stack adjustment only
1460 if (base == dwarf_sp_mips) {
1461 // Read stack pointer register
1462 uint64_t src_opd_val = ReadRegisterUnsigned(
1463 eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
1464 if (!success)
1465 return false;
1466
1467 result = src_opd_val + imm4;
1468
1469 Context context;
1470 std::optional<RegisterInfo> reg_info_sp =
1472 if (reg_info_sp)
1473 context.SetRegisterPlusOffset(*reg_info_sp, imm4);
1474
1475 // We are adjusting the stack.
1477
1479 }
1480
1481 return true;
1482}
1483
1485 bool success = false;
1486 uint32_t imm5 = insn.getOperand(2).getImm();
1487 uint32_t src, base;
1488 Context bad_vaddr_context;
1489 uint32_t address;
1490
1491 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1492 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1493
1494 std::optional<RegisterInfo> reg_info_base =
1496 if (!reg_info_base)
1497 return false;
1498
1499 // read base register
1501 &success);
1502 if (!success)
1503 return false;
1504
1505 // destination address
1506 address = address + imm5;
1507
1508 // We use bad_vaddr_context to store base address which is used by H/W
1509 // watchpoint Set the bad_vaddr register with base address used in the
1510 // instruction
1511 bad_vaddr_context.type = eContextInvalid;
1513 address);
1514
1515 // We look for sp based non-volatile register stores.
1516 if (base == dwarf_sp_mips && nonvolatile_reg_p(src)) {
1517 RegisterInfo reg_info_src = {};
1518 Context context;
1520 context.SetRegisterToRegisterPlusOffset(reg_info_src, *reg_info_base, 0);
1521
1522 RegisterValue::BytesContainer buffer(reg_info_src.byte_size);
1523 Status error;
1524
1525 std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);
1526 if (!data_src)
1527 return false;
1528
1529 if (data_src->GetAsMemoryData(reg_info_src, buffer.data(),
1530 reg_info_src.byte_size, eByteOrderLittle,
1531 error) == 0)
1532 return false;
1533
1534 if (!WriteMemory(context, address, buffer.data(), reg_info_src.byte_size))
1535 return false;
1536
1537 return true;
1538 }
1539
1540 return false;
1541}
1542
1543/* Emulate SWM16,SWM32 and SWP instruction.
1544
1545 SWM16 always has stack pointer as a base register (but it is still available
1546 in MCInst as an operand).
1547 SWM32 and SWP can have base register other than stack pointer.
1548*/
1550 bool success = false;
1551 uint32_t src, base;
1552 uint32_t num_operands = insn.getNumOperands(); // No of operands vary based on
1553 // no of regs to store.
1554
1555 // Base register is second last operand of the instruction.
1556 base =
1557 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
1558
1559 // We are looking for sp based stores so if base is not a stack pointer then
1560 // don't proceed.
1561 if (base != dwarf_sp_mips)
1562 return false;
1563
1564 // offset is always the last operand.
1565 uint32_t offset = insn.getOperand(num_operands - 1).getImm();
1566
1567 std::optional<RegisterInfo> reg_info_base =
1569 if (!reg_info_base)
1570 return false;
1571
1572 // read SP
1573 uint32_t base_address = ReadRegisterUnsigned(
1574 eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
1575 if (!success)
1576 return false;
1577
1578 // Resulting base addrss
1579 base_address = base_address + offset;
1580
1581 // Total no of registers to be stored are num_operands-2.
1582 for (uint32_t i = 0; i < num_operands - 2; i++) {
1583 // Get the register number to be stored.
1584 src = m_reg_info->getEncodingValue(insn.getOperand(i).getReg());
1585
1586 /*
1587 Record only non-volatile stores.
1588 This check is required for SWP instruction because source operand could
1589 be any register.
1590 SWM16 and SWM32 instruction always has saved registers as source
1591 operands.
1592 */
1593 if (!nonvolatile_reg_p(src))
1594 return false;
1595
1596 std::optional<RegisterInfo> reg_info_src =
1598 if (!reg_info_src)
1599 return false;
1600
1601 Context context;
1603 context.SetRegisterToRegisterPlusOffset(*reg_info_src, *reg_info_base, 0);
1604
1605 RegisterValue::BytesContainer buffer(reg_info_src->byte_size);
1606 Status error;
1607
1608 std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);
1609 if (!data_src)
1610 return false;
1611
1612 if (data_src->GetAsMemoryData(*reg_info_src, buffer.data(),
1613 reg_info_src->byte_size, eByteOrderLittle,
1614 error) == 0)
1615 return false;
1616
1617 if (!WriteMemory(context, base_address, buffer.data(),
1618 reg_info_src->byte_size))
1619 return false;
1620
1621 // Stack address for next register
1622 base_address = base_address + reg_info_src->byte_size;
1623 }
1624 return true;
1625}
1626
1628 bool success = false;
1629 uint32_t src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1630 uint32_t base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1631 uint32_t imm5 = insn.getOperand(2).getImm();
1632 Context bad_vaddr_context;
1633
1635 return false;
1636
1637 // read base register
1638 uint32_t base_address = ReadRegisterUnsigned(
1639 eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
1640 if (!success)
1641 return false;
1642
1643 base_address = base_address + imm5;
1644
1645 // We use bad_vaddr_context to store base address which is used by H/W
1646 // watchpoint Set the bad_vaddr register with base address used in the
1647 // instruction
1648 bad_vaddr_context.type = eContextInvalid;
1650 base_address);
1651
1652 if (base == dwarf_sp_mips && nonvolatile_reg_p(src)) {
1653 RegisterValue data_src;
1654 std::optional<RegisterInfo> reg_info_src =
1656 if (!reg_info_src)
1657 return false;
1658
1659 Context context;
1661 context.SetAddress(base_address);
1662
1663 return WriteRegister(context, *reg_info_src, data_src);
1664 }
1665
1666 return false;
1667}
1668
1669/* Emulate LWM16, LWM32 and LWP instructions.
1670
1671 LWM16 always has stack pointer as a base register (but it is still available
1672 in MCInst as an operand).
1673 LWM32 and LWP can have base register other than stack pointer.
1674*/
1676 bool success = false;
1677 uint32_t dst, base;
1678 uint32_t num_operands = insn.getNumOperands(); // No of operands vary based on
1679 // no of regs to store.
1680 uint32_t imm = insn.getOperand(num_operands - 1)
1681 .getImm(); // imm is the last operand in the instruction.
1682
1683 // Base register is second last operand of the instruction.
1684 base =
1685 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
1686
1687 // We are looking for sp based loads so if base is not a stack pointer then
1688 // don't proceed.
1689 if (base != dwarf_sp_mips)
1690 return false;
1691
1692 uint32_t base_address = ReadRegisterUnsigned(
1693 eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
1694 if (!success)
1695 return false;
1696
1697 base_address = base_address + imm;
1698
1699 RegisterValue data_dst;
1700
1701 // Total no of registers to be re-stored are num_operands-2.
1702 for (uint32_t i = 0; i < num_operands - 2; i++) {
1703 // Get the register number to be re-stored.
1704 dst = m_reg_info->getEncodingValue(insn.getOperand(i).getReg());
1705
1706 /*
1707 Record only non-volatile loads.
1708 This check is required for LWP instruction because destination operand
1709 could be any register.
1710 LWM16 and LWM32 instruction always has saved registers as destination
1711 operands.
1712 */
1713 if (!nonvolatile_reg_p(dst))
1714 return false;
1715
1716 std::optional<RegisterInfo> reg_info_dst =
1718 if (!reg_info_dst)
1719 return false;
1720
1721 Context context;
1723 context.SetAddress(base_address + (i * 4));
1724
1725 if (!WriteRegister(context, *reg_info_dst, data_dst))
1726 return false;
1727 }
1728
1729 return true;
1730}
1731
1733 bool success = false;
1734 int32_t imm5 = insn.getOperand(0).getImm();
1735
1736 /* JRADDIUSP immediate
1737 * PC <- RA
1738 * SP <- SP + zero_extend(Immediate << 2)
1739 */
1740
1741 // This instruction operates implicitly on stack pointer, so read <sp>
1742 // register.
1743 int32_t src_opd_val =
1745 if (!success)
1746 return false;
1747
1748 int32_t ra_val =
1750 if (!success)
1751 return false;
1752
1753 int32_t result = src_opd_val + imm5;
1754
1755 Context context;
1756
1757 // Update the PC
1759 ra_val))
1760 return false;
1761
1762 std::optional<RegisterInfo> reg_info_sp =
1764 if (reg_info_sp)
1765 context.SetRegisterPlusOffset(*reg_info_sp, imm5);
1766
1767 // We are adjusting stack
1769
1770 // update SP
1772 result);
1773}
1774
1775static int IsAdd64bitOverflow(int32_t a, int32_t b) {
1776 int32_t r = (uint32_t)a + (uint32_t)b;
1777 return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
1778}
1779
1780/*
1781 Emulate below MIPS branch instructions.
1782 BEQ, BNE : Branch on condition
1783 BEQL, BNEL : Branch likely
1784*/
1786 bool success = false;
1787 uint32_t rs, rt;
1788 int32_t offset, pc, target = 0, rs_val, rt_val;
1789 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1790
1791 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1792 rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1793 offset = insn.getOperand(2).getImm();
1794
1796 if (!success)
1797 return false;
1798
1799 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1800 dwarf_zero_mips + rs, 0, &success);
1801 if (!success)
1802 return false;
1803
1804 rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1805 dwarf_zero_mips + rt, 0, &success);
1806 if (!success)
1807 return false;
1808
1809 if (op_name.equals_insensitive("BEQ") || op_name.equals_insensitive("BEQL")) {
1810 if (rs_val == rt_val)
1811 target = pc + offset;
1812 else
1813 target = pc + 8;
1814 } else if (op_name.equals_insensitive("BNE") ||
1815 op_name.equals_insensitive("BNEL")) {
1816 if (rs_val != rt_val)
1817 target = pc + offset;
1818 else
1819 target = pc + 8;
1820 }
1821
1822 Context context;
1824 context.SetImmediate(offset);
1825
1827 target);
1828}
1829
1830/*
1831 Emulate below MIPS branch instructions.
1832 BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch
1833 instructions with no delay slot
1834*/
1836 bool success = false;
1837 uint32_t rs, rt;
1838 int32_t offset, pc, target = 0, rs_val, rt_val;
1839 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1840 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
1841
1842 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1843 rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1844 offset = insn.getOperand(2).getImm();
1845
1847 if (!success)
1848 return false;
1849
1850 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1851 dwarf_zero_mips + rs, 0, &success);
1852 if (!success)
1853 return false;
1854
1855 rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1856 dwarf_zero_mips + rt, 0, &success);
1857 if (!success)
1858 return false;
1859
1860 if (op_name.equals_insensitive("BEQC")) {
1861 if (rs_val == rt_val)
1862 target = pc + offset;
1863 else
1864 target = pc + 4;
1865 } else if (op_name.equals_insensitive("BNEC")) {
1866 if (rs_val != rt_val)
1867 target = pc + offset;
1868 else
1869 target = pc + 4;
1870 } else if (op_name.equals_insensitive("BLTC")) {
1871 if (rs_val < rt_val)
1872 target = pc + offset;
1873 else
1874 target = pc + 4;
1875 } else if (op_name.equals_insensitive("BGEC")) {
1876 if (rs_val >= rt_val)
1877 target = pc + offset;
1878 else
1879 target = pc + 4;
1880 } else if (op_name.equals_insensitive("BLTUC")) {
1881 if (rs_val < rt_val)
1882 target = pc + offset;
1883 else
1884 target = pc + 4;
1885 } else if (op_name.equals_insensitive("BGEUC")) {
1886 if ((uint32_t)rs_val >= (uint32_t)rt_val)
1887 target = pc + offset;
1888 else
1889 target = pc + 4;
1890 } else if (op_name.equals_insensitive("BOVC")) {
1891 if (IsAdd64bitOverflow(rs_val, rt_val))
1892 target = pc + offset;
1893 else
1894 target = pc + 4;
1895 } else if (op_name.equals_insensitive("BNVC")) {
1896 if (!IsAdd64bitOverflow(rs_val, rt_val))
1897 target = pc + offset;
1898 else
1899 target = pc + 4;
1900 }
1901
1902 Context context;
1904 context.SetImmediate(current_inst_size + offset);
1905
1907 target);
1908}
1909
1910/*
1911 Emulate below MIPS conditional branch and link instructions.
1912 BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches
1913*/
1915 bool success = false;
1916 uint32_t rs;
1917 int32_t offset, pc, target = 0;
1918 int32_t rs_val;
1919 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1920
1921 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1922 offset = insn.getOperand(1).getImm();
1923
1925 if (!success)
1926 return false;
1927
1928 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1929 dwarf_zero_mips + rs, 0, &success);
1930 if (!success)
1931 return false;
1932
1933 if (op_name.equals_insensitive("BLEZALC")) {
1934 if (rs_val <= 0)
1935 target = pc + offset;
1936 else
1937 target = pc + 4;
1938 } else if (op_name.equals_insensitive("BGEZALC")) {
1939 if (rs_val >= 0)
1940 target = pc + offset;
1941 else
1942 target = pc + 4;
1943 } else if (op_name.equals_insensitive("BLTZALC")) {
1944 if (rs_val < 0)
1945 target = pc + offset;
1946 else
1947 target = pc + 4;
1948 } else if (op_name.equals_insensitive("BGTZALC")) {
1949 if (rs_val > 0)
1950 target = pc + offset;
1951 else
1952 target = pc + 4;
1953 } else if (op_name.equals_insensitive("BEQZALC")) {
1954 if (rs_val == 0)
1955 target = pc + offset;
1956 else
1957 target = pc + 4;
1958 } else if (op_name.equals_insensitive("BNEZALC")) {
1959 if (rs_val != 0)
1960 target = pc + offset;
1961 else
1962 target = pc + 4;
1963 }
1964
1965 Context context;
1966
1968 target))
1969 return false;
1970
1972 pc + 4))
1973 return false;
1974
1975 return true;
1976}
1977
1978/*
1979 Emulate below MIPS Non-Compact conditional branch and link instructions.
1980 BLTZAL, BGEZAL :
1981 BLTZALL, BGEZALL : Branch likely
1982*/
1984 bool success = false;
1985 uint32_t rs;
1986 int32_t offset, pc, target = 0;
1987 int32_t rs_val;
1988 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1989
1990 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1991 offset = insn.getOperand(1).getImm();
1992
1994 if (!success)
1995 return false;
1996
1997 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1998 dwarf_zero_mips + rs, 0, &success);
1999 if (!success)
2000 return false;
2001
2002 if (op_name.equals_insensitive("BLTZAL") ||
2003 op_name.equals_insensitive("BLTZALL")) {
2004 if ((int32_t)rs_val < 0)
2005 target = pc + offset;
2006 else
2007 target = pc + 8;
2008 } else if (op_name.equals_insensitive("BGEZAL") ||
2009 op_name.equals_insensitive("BGEZALL")) {
2010 if ((int32_t)rs_val >= 0)
2011 target = pc + offset;
2012 else
2013 target = pc + 8;
2014 }
2015
2016 Context context;
2017
2019 target))
2020 return false;
2021
2023 pc + 8))
2024 return false;
2025
2026 return true;
2027}
2028
2029/*
2030 Emulate below MIPS branch instructions.
2031 BLTZL, BGEZL, BGTZL, BLEZL : Branch likely
2032 BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches
2033*/
2035 bool success = false;
2036 uint32_t rs;
2037 int32_t offset, pc, target = 0;
2038 int32_t rs_val;
2039 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2040
2041 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2042 offset = insn.getOperand(1).getImm();
2043
2045 if (!success)
2046 return false;
2047
2048 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2049 dwarf_zero_mips + rs, 0, &success);
2050 if (!success)
2051 return false;
2052
2053 if (op_name.equals_insensitive("BLTZL") ||
2054 op_name.equals_insensitive("BLTZ")) {
2055 if (rs_val < 0)
2056 target = pc + offset;
2057 else
2058 target = pc + 8;
2059 } else if (op_name.equals_insensitive("BGEZL") ||
2060 op_name.equals_insensitive("BGEZ")) {
2061 if (rs_val >= 0)
2062 target = pc + offset;
2063 else
2064 target = pc + 8;
2065 } else if (op_name.equals_insensitive("BGTZL") ||
2066 op_name.equals_insensitive("BGTZ")) {
2067 if (rs_val > 0)
2068 target = pc + offset;
2069 else
2070 target = pc + 8;
2071 } else if (op_name.equals_insensitive("BLEZL") ||
2072 op_name.equals_insensitive("BLEZ")) {
2073 if (rs_val <= 0)
2074 target = pc + offset;
2075 else
2076 target = pc + 8;
2077 }
2078
2079 Context context;
2081 context.SetImmediate(offset);
2082
2084 target);
2085}
2086
2087/*
2088 Emulate below MIPS branch instructions.
2089 BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches
2090*/
2092 bool success = false;
2093 uint32_t rs;
2094 int32_t offset, pc, target = 0;
2095 int32_t rs_val;
2096 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2097 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
2098
2099 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2100 offset = insn.getOperand(1).getImm();
2101
2103 if (!success)
2104 return false;
2105
2106 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2107 dwarf_zero_mips + rs, 0, &success);
2108 if (!success)
2109 return false;
2110
2111 if (op_name.equals_insensitive("BLTZC")) {
2112 if (rs_val < 0)
2113 target = pc + offset;
2114 else
2115 target = pc + 4;
2116 } else if (op_name.equals_insensitive("BLEZC")) {
2117 if (rs_val <= 0)
2118 target = pc + offset;
2119 else
2120 target = pc + 4;
2121 } else if (op_name.equals_insensitive("BGEZC")) {
2122 if (rs_val >= 0)
2123 target = pc + offset;
2124 else
2125 target = pc + 4;
2126 } else if (op_name.equals_insensitive("BGTZC")) {
2127 if (rs_val > 0)
2128 target = pc + offset;
2129 else
2130 target = pc + 4;
2131 } else if (op_name.equals_insensitive("BEQZC")) {
2132 if (rs_val == 0)
2133 target = pc + offset;
2134 else
2135 target = pc + 4;
2136 } else if (op_name.equals_insensitive("BNEZC")) {
2137 if (rs_val != 0)
2138 target = pc + offset;
2139 else
2140 target = pc + 4;
2141 }
2142
2143 Context context;
2145 context.SetImmediate(current_inst_size + offset);
2146
2148 target);
2149}
2150
2152 bool success = false;
2153 int32_t offset, pc, target;
2154 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
2155
2156 offset = insn.getOperand(0).getImm();
2157
2159 if (!success)
2160 return false;
2161
2162 // unconditional branch
2163 target = pc + offset;
2164
2165 Context context;
2167 context.SetImmediate(current_inst_size + offset);
2168
2170 target);
2171}
2172
2173/*
2174 BEQZC, BNEZC are 32 bit compact instructions without a delay slot.
2175 BEQZ16, BNEZ16 are 16 bit instructions with delay slot.
2176 BGEZALS, BLTZALS are 16 bit instructions with short (2-byte) delay slot.
2177*/
2179 bool success = false;
2180 int32_t target = 0;
2181 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
2182 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2183 bool update_ra = false;
2184 uint32_t ra_offset = 0;
2185
2186 /*
2187 * BEQZ16 rs, offset
2188 * condition <- (GPR[rs] = 0)
2189 * if condition then
2190 * PC = PC + sign_ext (offset || 0)
2191 *
2192 * BNEZ16 rs, offset
2193 * condition <- (GPR[rs] != 0)
2194 * if condition then
2195 * PC = PC + sign_ext (offset || 0)
2196 *
2197 * BEQZC rs, offset (compact instruction: No delay slot)
2198 * condition <- (GPR[rs] == 0)
2199 * if condition then
2200 * PC = PC + 4 + sign_ext (offset || 0)
2201 */
2202
2203 uint32_t rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2204 int32_t offset = insn.getOperand(1).getImm();
2205
2206 int32_t pc =
2208 if (!success)
2209 return false;
2210
2211 int32_t rs_val = (int32_t)ReadRegisterUnsigned(
2212 eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
2213 if (!success)
2214 return false;
2215
2216 if (op_name.equals_insensitive("BEQZ16_MM")) {
2217 if (rs_val == 0)
2218 target = pc + offset;
2219 else
2220 target = pc + current_inst_size +
2221 m_next_inst_size; // Skip delay slot instruction.
2222 } else if (op_name.equals_insensitive("BNEZ16_MM")) {
2223 if (rs_val != 0)
2224 target = pc + offset;
2225 else
2226 target = pc + current_inst_size +
2227 m_next_inst_size; // Skip delay slot instruction.
2228 } else if (op_name.equals_insensitive("BEQZC_MM")) {
2229 if (rs_val == 0)
2230 target = pc + 4 + offset;
2231 else
2232 target =
2233 pc +
2234 4; // 32 bit instruction and does not have delay slot instruction.
2235 } else if (op_name.equals_insensitive("BNEZC_MM")) {
2236 if (rs_val != 0)
2237 target = pc + 4 + offset;
2238 else
2239 target =
2240 pc +
2241 4; // 32 bit instruction and does not have delay slot instruction.
2242 } else if (op_name.equals_insensitive("BGEZALS_MM")) {
2243 if (rs_val >= 0)
2244 target = pc + offset;
2245 else
2246 target = pc + 6; // 32 bit instruction with short (2-byte) delay slot
2247
2248 update_ra = true;
2249 ra_offset = 6;
2250 } else if (op_name.equals_insensitive("BLTZALS_MM")) {
2251 if (rs_val >= 0)
2252 target = pc + offset;
2253 else
2254 target = pc + 6; // 32 bit instruction with short (2-byte) delay slot
2255
2256 update_ra = true;
2257 ra_offset = 6;
2258 }
2259
2260 Context context;
2262 context.SetImmediate(current_inst_size + offset);
2263
2265 target))
2266 return false;
2267
2268 if (update_ra) {
2270 pc + ra_offset))
2271 return false;
2272 }
2273 return true;
2274}
2275
2276/* Emulate micromips jump instructions.
2277 JALR16,JALRS16
2278*/
2280 bool success = false;
2281 uint32_t ra_offset = 0;
2282 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2283
2284 uint32_t rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2285
2286 uint32_t pc =
2288 if (!success)
2289 return false;
2290
2291 uint32_t rs_val = ReadRegisterUnsigned(eRegisterKindDWARF,
2292 dwarf_zero_mips + rs, 0, &success);
2293 if (!success)
2294 return false;
2295
2296 if (op_name.equals_insensitive("JALR16_MM"))
2297 ra_offset = 6; // 2-byte instruction with 4-byte delay slot.
2298 else if (op_name.equals_insensitive("JALRS16_MM"))
2299 ra_offset = 4; // 2-byte instruction with 2-byte delay slot.
2300
2301 Context context;
2302
2304 rs_val))
2305 return false;
2306
2308 pc + ra_offset))
2309 return false;
2310
2311 return true;
2312}
2313
2314/* Emulate JALS and JALX instructions.
2315 JALS 32 bit instruction with short (2-byte) delay slot.
2316 JALX 32 bit instruction with 4-byte delay slot.
2317*/
2319 bool success = false;
2320 uint32_t offset = 0, target = 0, pc = 0, ra_offset = 0;
2321 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2322
2323 /*
2324 * JALS target
2325 * RA = PC + 6
2326 * offset = sign_ext (offset << 1)
2327 * PC = PC[31-27] | offset
2328 * JALX target
2329 * RA = PC + 8
2330 * offset = sign_ext (offset << 2)
2331 * PC = PC[31-28] | offset
2332 */
2333 offset = insn.getOperand(0).getImm();
2334
2336 if (!success)
2337 return false;
2338
2339 // These are PC-region branches and not PC-relative.
2340 if (op_name.equals_insensitive("JALS_MM")) {
2341 // target address is in the “current” 128 MB-aligned region
2342 target = (pc & 0xF8000000UL) | offset;
2343 ra_offset = 6;
2344 } else if (op_name.equals_insensitive("JALX_MM")) {
2345 // target address is in the “current” 256 MB-aligned region
2346 target = (pc & 0xF0000000UL) | offset;
2347 ra_offset = 8;
2348 }
2349
2350 Context context;
2351
2353 target))
2354 return false;
2355
2357 pc + ra_offset))
2358 return false;
2359
2360 return true;
2361}
2362
2364 bool success = false;
2365 uint32_t rs = 0, rt = 0;
2366 int32_t pc = 0, rs_val = 0;
2367
2368 /*
2369 JALRS rt, rs
2370 GPR[rt] <- PC + 6
2371 PC <- GPR[rs]
2372 */
2373
2374 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2375 rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
2376
2377 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2378 dwarf_zero_mips + rs, 0, &success);
2379 if (!success)
2380 return false;
2381
2383 if (!success)
2384 return false;
2385
2386 Context context;
2387
2389 rs_val))
2390 return false;
2391
2392 // This is 4-byte instruction with 2-byte delay slot.
2394 pc + 6))
2395 return false;
2396
2397 return true;
2398}
2399
2400bool EmulateInstructionMIPS::Emulate_BAL(llvm::MCInst &insn) {
2401 bool success = false;
2402 int32_t offset, pc, target;
2403
2404 /*
2405 * BAL offset
2406 * offset = sign_ext (offset << 2)
2407 * RA = PC + 8
2408 * PC = PC + offset
2409 */
2410 offset = insn.getOperand(0).getImm();
2411
2413 if (!success)
2414 return false;
2415
2416 target = pc + offset;
2417
2418 Context context;
2419
2421 target))
2422 return false;
2423
2425 pc + 8))
2426 return false;
2427
2428 return true;
2429}
2430
2432 bool success = false;
2433 int32_t offset, pc, target;
2434
2435 /*
2436 * BALC offset
2437 * offset = sign_ext (offset << 2)
2438 * RA = PC + 4
2439 * PC = PC + 4 + offset
2440 */
2441 offset = insn.getOperand(0).getImm();
2442
2444 if (!success)
2445 return false;
2446
2447 target = pc + offset;
2448
2449 Context context;
2450
2452 target))
2453 return false;
2454
2456 pc + 4))
2457 return false;
2458
2459 return true;
2460}
2461
2462bool EmulateInstructionMIPS::Emulate_BC(llvm::MCInst &insn) {
2463 bool success = false;
2464 int32_t offset, pc, target;
2465
2466 /*
2467 * BC offset
2468 * offset = sign_ext (offset << 2)
2469 * PC = PC + 4 + offset
2470 */
2471 offset = insn.getOperand(0).getImm();
2472
2474 if (!success)
2475 return false;
2476
2477 target = pc + offset;
2478
2479 Context context;
2480
2482 target);
2483}
2484
2485bool EmulateInstructionMIPS::Emulate_J(llvm::MCInst &insn) {
2486 bool success = false;
2487 uint32_t offset, pc;
2488
2489 /*
2490 * J offset
2491 * offset = sign_ext (offset << 2)
2492 * PC = PC[63-28] | offset
2493 */
2494 offset = insn.getOperand(0).getImm();
2495
2497 if (!success)
2498 return false;
2499
2500 /* This is a PC-region branch and not PC-relative */
2501 pc = (pc & 0xF0000000UL) | offset;
2502
2503 Context context;
2504
2506}
2507
2508bool EmulateInstructionMIPS::Emulate_JAL(llvm::MCInst &insn) {
2509 bool success = false;
2510 uint32_t offset, target, pc;
2511
2512 /*
2513 * JAL offset
2514 * offset = sign_ext (offset << 2)
2515 * PC = PC[63-28] | offset
2516 */
2517 offset = insn.getOperand(0).getImm();
2518
2520 if (!success)
2521 return false;
2522
2523 /* This is a PC-region branch and not PC-relative */
2524 target = (pc & 0xF0000000UL) | offset;
2525
2526 Context context;
2527
2529 target))
2530 return false;
2531
2533 pc + 8))
2534 return false;
2535
2536 return true;
2537}
2538
2540 bool success = false;
2541 uint32_t rs, rt;
2542 uint32_t pc, rs_val;
2543
2544 /*
2545 * JALR rt, rs
2546 * GPR[rt] = PC + 8
2547 * PC = GPR[rs]
2548 */
2549 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2550 rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
2551
2553 if (!success)
2554 return false;
2555
2557 &success);
2558 if (!success)
2559 return false;
2560
2561 Context context;
2562
2564 rs_val))
2565 return false;
2566
2568 pc + 8))
2569 return false;
2570
2571 return true;
2572}
2573
2575 bool success = false;
2576 uint32_t rt;
2577 int32_t target, offset, pc, rt_val;
2578
2579 /*
2580 * JIALC rt, offset
2581 * offset = sign_ext (offset)
2582 * PC = GPR[rt] + offset
2583 * RA = PC + 4
2584 */
2585 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2586 offset = insn.getOperand(1).getImm();
2587
2589 if (!success)
2590 return false;
2591
2592 rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2593 dwarf_zero_mips + rt, 0, &success);
2594 if (!success)
2595 return false;
2596
2597 target = rt_val + offset;
2598
2599 Context context;
2600
2602 target))
2603 return false;
2604
2606 pc + 4))
2607 return false;
2608
2609 return true;
2610}
2611
2612bool EmulateInstructionMIPS::Emulate_JIC(llvm::MCInst &insn) {
2613 bool success = false;
2614 uint32_t rt;
2615 int32_t target, offset, rt_val;
2616
2617 /*
2618 * JIC rt, offset
2619 * offset = sign_ext (offset)
2620 * PC = GPR[rt] + offset
2621 */
2622 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2623 offset = insn.getOperand(1).getImm();
2624
2625 rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2626 dwarf_zero_mips + rt, 0, &success);
2627 if (!success)
2628 return false;
2629
2630 target = rt_val + offset;
2631
2632 Context context;
2633
2635 target);
2636}
2637
2638bool EmulateInstructionMIPS::Emulate_JR(llvm::MCInst &insn) {
2639 bool success = false;
2640 uint32_t rs;
2641 uint32_t rs_val;
2642
2643 /*
2644 * JR rs
2645 * PC = GPR[rs]
2646 */
2647 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2648
2650 &success);
2651 if (!success)
2652 return false;
2653
2654 Context context;
2655
2657 rs_val);
2658}
2659
2660/*
2661 Emulate Branch on FP True/False
2662 BC1F, BC1FL : Branch on FP False (L stands for branch likely)
2663 BC1T, BC1TL : Branch on FP True (L stands for branch likely)
2664*/
2666 bool success = false;
2667 uint32_t cc, fcsr;
2668 int32_t pc, offset, target = 0;
2669 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2670
2671 cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2672 offset = insn.getOperand(1).getImm();
2673
2675 if (!success)
2676 return false;
2677
2679 if (!success)
2680 return false;
2681
2682 /* fcsr[23], fcsr[25-31] are vaild condition bits */
2683 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2684
2685 if (op_name.equals_insensitive("BC1F") ||
2686 op_name.equals_insensitive("BC1FL")) {
2687 if ((fcsr & (1 << cc)) == 0)
2688 target = pc + offset;
2689 else
2690 target = pc + 8;
2691 } else if (op_name.equals_insensitive("BC1T") ||
2692 op_name.equals_insensitive("BC1TL")) {
2693 if ((fcsr & (1 << cc)) != 0)
2694 target = pc + offset;
2695 else
2696 target = pc + 8;
2697 }
2698 Context context;
2699
2701 target);
2702}
2703
2705 bool success = false;
2706 uint32_t ft;
2707 uint32_t ft_val;
2708 int32_t target, pc, offset;
2709
2710 /*
2711 * BC1EQZ ft, offset
2712 * condition <- (FPR[ft].bit0 == 0)
2713 * if condition then
2714 * offset = sign_ext (offset)
2715 * PC = PC + 4 + offset
2716 */
2717 ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2718 offset = insn.getOperand(1).getImm();
2719
2721 if (!success)
2722 return false;
2723
2725 &success);
2726 if (!success)
2727 return false;
2728
2729 if ((ft_val & 1) == 0)
2730 target = pc + 4 + offset;
2731 else
2732 target = pc + 8;
2733
2734 Context context;
2735
2737 target);
2738}
2739
2741 bool success = false;
2742 uint32_t ft;
2743 uint32_t ft_val;
2744 int32_t target, pc, offset;
2745
2746 /*
2747 * BC1NEZ ft, offset
2748 * condition <- (FPR[ft].bit0 != 0)
2749 * if condition then
2750 * offset = sign_ext (offset)
2751 * PC = PC + 4 + offset
2752 */
2753 ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2754 offset = insn.getOperand(1).getImm();
2755
2757 if (!success)
2758 return false;
2759
2761 &success);
2762 if (!success)
2763 return false;
2764
2765 if ((ft_val & 1) != 0)
2766 target = pc + 4 + offset;
2767 else
2768 target = pc + 8;
2769
2770 Context context;
2771
2773 target);
2774}
2775
2776/*
2777 Emulate MIPS-3D Branch instructions
2778 BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes
2779 False/True
2780 BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes
2781 False/True
2782*/
2784 bool success = false;
2785 uint32_t cc, fcsr;
2786 int32_t pc, offset, target = 0;
2787 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2788
2789 cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2790 offset = insn.getOperand(1).getImm();
2791
2793 if (!success)
2794 return false;
2795
2797 &success);
2798 if (!success)
2799 return false;
2800
2801 /* fcsr[23], fcsr[25-31] are vaild condition bits */
2802 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2803
2804 if (op_name.equals_insensitive("BC1ANY2F")) {
2805 /* if any one bit is 0 */
2806 if (((fcsr >> cc) & 3) != 3)
2807 target = pc + offset;
2808 else
2809 target = pc + 8;
2810 } else if (op_name.equals_insensitive("BC1ANY2T")) {
2811 /* if any one bit is 1 */
2812 if (((fcsr >> cc) & 3) != 0)
2813 target = pc + offset;
2814 else
2815 target = pc + 8;
2816 } else if (op_name.equals_insensitive("BC1ANY4F")) {
2817 /* if any one bit is 0 */
2818 if (((fcsr >> cc) & 0xf) != 0xf)
2819 target = pc + offset;
2820 else
2821 target = pc + 8;
2822 } else if (op_name.equals_insensitive("BC1ANY4T")) {
2823 /* if any one bit is 1 */
2824 if (((fcsr >> cc) & 0xf) != 0)
2825 target = pc + offset;
2826 else
2827 target = pc + 8;
2828 }
2829 Context context;
2830
2832 target);
2833}
2834
2836 return Emulate_MSA_Branch_DF(insn, 1, true);
2837}
2838
2840 return Emulate_MSA_Branch_DF(insn, 2, true);
2841}
2842
2844 return Emulate_MSA_Branch_DF(insn, 4, true);
2845}
2846
2848 return Emulate_MSA_Branch_DF(insn, 8, true);
2849}
2850
2851bool EmulateInstructionMIPS::Emulate_BZB(llvm::MCInst &insn) {
2852 return Emulate_MSA_Branch_DF(insn, 1, false);
2853}
2854
2855bool EmulateInstructionMIPS::Emulate_BZH(llvm::MCInst &insn) {
2856 return Emulate_MSA_Branch_DF(insn, 2, false);
2857}
2858
2859bool EmulateInstructionMIPS::Emulate_BZW(llvm::MCInst &insn) {
2860 return Emulate_MSA_Branch_DF(insn, 4, false);
2861}
2862
2863bool EmulateInstructionMIPS::Emulate_BZD(llvm::MCInst &insn) {
2864 return Emulate_MSA_Branch_DF(insn, 8, false);
2865}
2866
2868 int element_byte_size,
2869 bool bnz) {
2870 bool success = false, branch_hit = true;
2871 int32_t target = 0;
2872 RegisterValue reg_value;
2873 const uint8_t *ptr = nullptr;
2874
2875 uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2876 int32_t offset = insn.getOperand(1).getImm();
2877
2878 int32_t pc =
2880 if (!success)
2881 return false;
2882
2883 if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value))
2884 ptr = (const uint8_t *)reg_value.GetBytes();
2885 else
2886 return false;
2887
2888 for (int i = 0; i < 16 / element_byte_size; i++) {
2889 switch (element_byte_size) {
2890 case 1:
2891 if ((*ptr == 0 && bnz) || (*ptr != 0 && !bnz))
2892 branch_hit = false;
2893 break;
2894 case 2:
2895 if ((*(const uint16_t *)ptr == 0 && bnz) ||
2896 (*(const uint16_t *)ptr != 0 && !bnz))
2897 branch_hit = false;
2898 break;
2899 case 4:
2900 if ((*(const uint32_t *)ptr == 0 && bnz) ||
2901 (*(const uint32_t *)ptr != 0 && !bnz))
2902 branch_hit = false;
2903 break;
2904 case 8:
2905 if ((*(const uint64_t *)ptr == 0 && bnz) ||
2906 (*(const uint64_t *)ptr != 0 && !bnz))
2907 branch_hit = false;
2908 break;
2909 }
2910 if (!branch_hit)
2911 break;
2912 ptr = ptr + element_byte_size;
2913 }
2914
2915 if (branch_hit)
2916 target = pc + offset;
2917 else
2918 target = pc + 8;
2919
2920 Context context;
2922
2924 target);
2925}
2926
2928 return Emulate_MSA_Branch_V(insn, true);
2929}
2930
2931bool EmulateInstructionMIPS::Emulate_BZV(llvm::MCInst &insn) {
2932 return Emulate_MSA_Branch_V(insn, false);
2933}
2934
2936 bool bnz) {
2937 bool success = false;
2938 int32_t target = 0;
2939 llvm::APInt wr_val = llvm::APInt::getZero(128);
2940 llvm::APInt fail_value = llvm::APInt::getMaxValue(128);
2941 llvm::APInt zero_value = llvm::APInt::getZero(128);
2942 RegisterValue reg_value;
2943
2944 uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2945 int32_t offset = insn.getOperand(1).getImm();
2946
2947 int32_t pc =
2949 if (!success)
2950 return false;
2951
2952 if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value))
2953 wr_val = reg_value.GetAsUInt128(fail_value);
2954 else
2955 return false;
2956
2957 if ((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) ||
2958 (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz))
2959 target = pc + offset;
2960 else
2961 target = pc + 8;
2962
2963 Context context;
2965
2967 target);
2968}
2969
2971 bool success = false;
2972 uint32_t base;
2973 int32_t imm, address;
2974 Context bad_vaddr_context;
2975
2976 uint32_t num_operands = insn.getNumOperands();
2977 base =
2978 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
2979 imm = insn.getOperand(num_operands - 1).getImm();
2980
2982 return false;
2983
2984 /* read base register */
2985 address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2986 dwarf_zero_mips + base, 0, &success);
2987 if (!success)
2988 return false;
2989
2990 /* destination address */
2991 address = address + imm;
2992
2993 /* Set the bad_vaddr register with base address used in the instruction */
2994 bad_vaddr_context.type = eContextInvalid;
2996 address);
2997
2998 return true;
2999}
3000
3002 bool success = false;
3003 uint32_t base, index;
3004 int32_t address, index_address;
3005 Context bad_vaddr_context;
3006
3007 uint32_t num_operands = insn.getNumOperands();
3008 base =
3009 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
3010 index =
3011 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 1).getReg());
3012
3014 return false;
3015
3017 return false;
3018
3019 /* read base register */
3020 address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
3021 dwarf_zero_mips + base, 0, &success);
3022 if (!success)
3023 return false;
3024
3025 /* read index register */
3026 index_address = (int32_t)ReadRegisterUnsigned(
3027 eRegisterKindDWARF, dwarf_zero_mips + index, 0, &success);
3028 if (!success)
3029 return false;
3030
3031 /* destination address */
3032 address = address + index_address;
3033
3034 /* Set the bad_vaddr register with base address used in the instruction */
3035 bad_vaddr_context.type = eContextInvalid;
3037 address);
3038
3039 return true;
3040}
static llvm::raw_ostream & error(Stream &strm)
static int IsAdd64bitOverflow(int32_t a, int32_t b)
#define LLDB_PLUGIN_DEFINE_ADV(ClassName, PluginName)
@ dwarf_r12_mips
@ dwarf_w5_mips
@ dwarf_w16_mips
@ dwarf_f2_mips
@ dwarf_f12_mips
@ dwarf_f28_mips
@ dwarf_f11_mips
@ dwarf_mir_mips
@ dwarf_f8_mips
@ dwarf_f24_mips
@ dwarf_r13_mips
@ dwarf_f23_mips
@ dwarf_lo_mips
@ dwarf_sp_mips
@ dwarf_r26_mips
@ dwarf_config5_mips
@ dwarf_r27_mips
@ dwarf_f15_mips
@ dwarf_w8_mips
@ dwarf_r5_mips
@ dwarf_r22_mips
@ dwarf_r19_mips
@ dwarf_w0_mips
@ dwarf_w22_mips
@ dwarf_r6_mips
@ dwarf_w28_mips
@ dwarf_w19_mips
@ dwarf_sr_mips
@ dwarf_r30_mips
@ dwarf_w20_mips
@ dwarf_f5_mips
@ dwarf_r1_mips
@ dwarf_ra_mips
@ dwarf_f13_mips
@ dwarf_bad_mips
@ dwarf_r2_mips
@ dwarf_w11_mips
@ dwarf_r21_mips
@ dwarf_w3_mips
@ dwarf_f14_mips
@ dwarf_w17_mips
@ dwarf_w15_mips
@ dwarf_r17_mips
@ dwarf_r7_mips
@ dwarf_w2_mips
@ dwarf_fcsr_mips
@ dwarf_f16_mips
@ dwarf_w12_mips
@ dwarf_w7_mips
@ dwarf_f6_mips
@ dwarf_f9_mips
@ dwarf_f20_mips
@ dwarf_hi_mips
@ dwarf_f30_mips
@ dwarf_f17_mips
@ dwarf_cause_mips
@ dwarf_w14_mips
@ dwarf_w23_mips
@ dwarf_gp_mips
@ dwarf_r10_mips
@ dwarf_f31_mips
@ dwarf_w10_mips
@ dwarf_f0_mips
@ dwarf_f27_mips
@ dwarf_r15_mips
@ dwarf_r14_mips
@ dwarf_w31_mips
@ dwarf_r9_mips
@ dwarf_f21_mips
@ dwarf_fir_mips
@ dwarf_w27_mips
@ dwarf_w25_mips
@ dwarf_r8_mips
@ dwarf_r16_mips
@ dwarf_f1_mips
@ dwarf_f7_mips
@ dwarf_r23_mips
@ dwarf_w29_mips
@ dwarf_pc_mips
@ dwarf_w6_mips
@ dwarf_w1_mips
@ dwarf_r25_mips
@ dwarf_w26_mips
@ dwarf_r3_mips
@ dwarf_w4_mips
@ dwarf_f25_mips
@ dwarf_f18_mips
@ dwarf_r24_mips
@ dwarf_w9_mips
@ dwarf_f29_mips
@ dwarf_r4_mips
@ dwarf_f10_mips
@ dwarf_f19_mips
@ dwarf_w18_mips
@ dwarf_w21_mips
@ dwarf_f22_mips
@ dwarf_w24_mips
@ dwarf_zero_mips
@ dwarf_f3_mips
@ dwarf_w30_mips
@ dwarf_mcsr_mips
@ dwarf_r11_mips
@ dwarf_r20_mips
@ dwarf_w13_mips
@ dwarf_f26_mips
@ dwarf_r18_mips
@ dwarf_f4_mips
static lldb_private::EmulateInstruction * CreateInstance(const lldb_private::ArchSpec &arch, lldb_private::InstructionType inst_type)
bool Emulate_J(llvm::MCInst &insn)
bool Emulate_ADDiu(llvm::MCInst &insn)
bool Emulate_SUBU_ADDU(llvm::MCInst &insn)
bool Emulate_BXX_3ops(llvm::MCInst &insn)
bool Emulate_BNZH(llvm::MCInst &insn)
bool Emulate_BZV(llvm::MCInst &insn)
const char * GetRegisterName(unsigned reg_num, bool alternate_name)
bool Emulate_BNZW(llvm::MCInst &insn)
static bool SupportsEmulatingInstructionsOfTypeStatic(lldb_private::InstructionType inst_type)
bool Emulate_LWSP(llvm::MCInst &insn)
bool Emulate_BZD(llvm::MCInst &insn)
EmulateInstructionMIPS(const lldb_private::ArchSpec &arch)
bool Emulate_BZB(llvm::MCInst &insn)
bool EvaluateInstruction(uint32_t evaluate_options) override
bool SetInstruction(const lldb_private::Opcode &insn_opcode, const lldb_private::Address &inst_addr, lldb_private::Target *target) override
bool Emulate_B16_MM(llvm::MCInst &insn)
bool Emulate_SWM16_32(llvm::MCInst &insn)
bool Emulate_Branch_MM(llvm::MCInst &insn)
bool Emulate_BC1EQZ(llvm::MCInst &insn)
uint32_t GetSizeOfInstruction(lldb_private::DataExtractor &data, uint64_t inst_addr)
bool Emulate_SW(llvm::MCInst &insn)
static llvm::StringRef GetPluginDescriptionStatic()
std::unique_ptr< llvm::MCDisassembler > m_alt_disasm
bool Emulate_LWM16_32(llvm::MCInst &insn)
bool Emulate_JAL(llvm::MCInst &insn)
bool Emulate_JR(llvm::MCInst &insn)
bool Emulate_JRADDIUSP(llvm::MCInst &insn)
std::optional< lldb_private::RegisterInfo > GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num) override
bool Emulate_BC(llvm::MCInst &insn)
bool Emulate_Bcond_Link(llvm::MCInst &insn)
bool Emulate_JALx(llvm::MCInst &insn)
bool Emulate_LDST_Reg(llvm::MCInst &insn)
static MipsOpcode * GetOpcodeForInstruction(llvm::StringRef name)
bool Emulate_JALR(llvm::MCInst &insn)
bool Emulate_BZW(llvm::MCInst &insn)
bool Emulate_JIALC(llvm::MCInst &insn)
std::unique_ptr< llvm::MCContext > m_context
bool Emulate_Bcond_Link_C(llvm::MCInst &insn)
static llvm::StringRef GetPluginNameStatic()
std::unique_ptr< llvm::MCDisassembler > m_disasm
bool Emulate_3D_branch(llvm::MCInst &insn)
bool Emulate_BNZB(llvm::MCInst &insn)
bool Emulate_BNZD(llvm::MCInst &insn)
bool Emulate_JALRx16_MM(llvm::MCInst &insn)
bool Emulate_BALC(llvm::MCInst &insn)
bool Emulate_BNZV(llvm::MCInst &insn)
bool Emulate_BXX_3ops_C(llvm::MCInst &insn)
bool nonvolatile_reg_p(uint32_t regnum)
bool Emulate_JIC(llvm::MCInst &insn)
bool SetTargetTriple(const lldb_private::ArchSpec &arch) override
bool Emulate_LW(llvm::MCInst &insn)
bool Emulate_BAL(llvm::MCInst &insn)
bool Emulate_SWSP(llvm::MCInst &insn)
std::unique_ptr< llvm::MCSubtargetInfo > m_subtype_info
bool Emulate_JALRS(llvm::MCInst &insn)
bool Emulate_ADDIUSP(llvm::MCInst &insn)
bool Emulate_BXX_2ops_C(llvm::MCInst &insn)
bool Emulate_FP_branch(llvm::MCInst &insn)
bool Emulate_BXX_2ops(llvm::MCInst &insn)
bool Emulate_LUI(llvm::MCInst &insn)
std::unique_ptr< llvm::MCAsmInfo > m_asm_info
bool Emulate_BZH(llvm::MCInst &insn)
bool Emulate_BC1NEZ(llvm::MCInst &insn)
llvm::MCTargetOptions m_mc_options
bool CreateFunctionEntryUnwind(lldb_private::UnwindPlan &unwind_plan) override
bool Emulate_MSA_Branch_DF(llvm::MCInst &insn, int element_byte_size, bool bnz)
bool Emulate_LDST_Imm(llvm::MCInst &insn)
std::unique_ptr< llvm::MCInstrInfo > m_insn_info
bool Emulate_MSA_Branch_V(llvm::MCInst &insn, bool bnz)
bool Emulate_ADDIUS5(llvm::MCInst &insn)
std::unique_ptr< llvm::MCSubtargetInfo > m_alt_subtype_info
std::unique_ptr< llvm::MCRegisterInfo > m_reg_info
A section + offset based address class.
Definition Address.h:62
AddressClass GetAddressClass() const
Definition Address.cpp:1021
An architecture specification class.
Definition ArchSpec.h:32
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition ArchSpec.h:457
uint32_t GetFlags() const
Definition ArchSpec.h:528
Core GetCore() const
Definition ArchSpec.h:448
An data extractor class.
virtual uint64_t GetByteSize() const
Get the number of bytes contained in this object.
const uint8_t * GetDataStart() const
Get the data start pointer.
"lldb/Core/EmulateInstruction.h" A class that allows emulation of CPU opcodes.
lldb::ByteOrder GetByteOrder() const
std::optional< RegisterValue > ReadRegister(const RegisterInfo &reg_info)
bool WriteRegister(const Context &context, const RegisterInfo &ref_info, const RegisterValue &reg_value)
bool WriteRegisterUnsigned(const Context &context, const RegisterInfo &reg_info, uint64_t reg_value)
bool WriteMemory(const Context &context, lldb::addr_t addr, const void *src, size_t src_len)
uint64_t ReadMemoryUnsigned(const Context &context, lldb::addr_t addr, size_t byte_size, uint64_t fail_value, bool *success_ptr)
virtual bool SetInstruction(const Opcode &insn_opcode, const Address &inst_addr, Target *target)
uint64_t ReadRegisterUnsigned(const RegisterInfo &reg_info, uint64_t fail_value, bool *success_ptr)
uint32_t GetByteSize() const
Definition Opcode.h:231
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
virtual size_t ReadMemory(const Address &addr, void *dst, size_t dst_len, Status &error, bool force_live_memory=false, lldb::addr_t *load_addr_ptr=nullptr, bool *did_read_live_memory=nullptr)
Definition Target.cpp:2004
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
uint64_t addr_t
Definition lldb-types.h:80
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(EmulateInstructionMIPS::* 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.
llvm::ArrayRef< uint8_t > data(const uint8_t *context_base) const
const char * name
Name of this register, can't be NULL.
lldb::Format format
Default display format.