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

source code of lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp