[NFC][AArch64] Explicitly define undefined bits for instructions (#122129)
[llvm-project.git] / lldb / source / Plugins / Instruction / MIPS / EmulateInstructionMIPS.cpp
blob76d7a8272f3fc69e57d54ddb52bab5da2f0edeaf
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 //===----------------------------------------------------------------------===//
9 #include "EmulateInstructionMIPS.h"
11 #include <cstdlib>
12 #include <optional>
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"
36 #include "llvm/ADT/STLExtras.h"
38 #include "Plugins/Process/Utility/InstructionUtils.h"
39 #include "Plugins/Process/Utility/RegisterContext_mips.h"
41 using namespace lldb;
42 using namespace lldb_private;
44 LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionMIPS, InstructionMIPS)
46 #define UInt(x) ((uint64_t)x)
47 #define integer int64_t
50 // EmulateInstructionMIPS implementation
53 #ifdef __mips__
54 extern "C" {
55 void LLVMInitializeMipsTargetInfo();
56 void LLVMInitializeMipsTarget();
57 void LLVMInitializeMipsAsmPrinter();
58 void LLVMInitializeMipsTargetMC();
59 void LLVMInitializeMipsDisassembler();
61 #endif
63 EmulateInstructionMIPS::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.getTriple(), Status);
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.
80 #ifdef __mips__
81 if (!target) {
82 LLVMInitializeMipsTargetInfo();
83 LLVMInitializeMipsTarget();
84 LLVMInitializeMipsAsmPrinter();
85 LLVMInitializeMipsTargetMC();
86 LLVMInitializeMipsDisassembler();
87 target = llvm::TargetRegistry::lookupTarget(triple.getTriple(), Status);
89 #endif
91 assert(target);
93 llvm::StringRef cpu;
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;
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,";
150 m_reg_info.reset(target->createMCRegInfo(triple.getTriple()));
151 assert(m_reg_info.get());
153 m_insn_info.reset(target->createMCInstrInfo());
154 assert(m_insn_info.get());
156 llvm::MCTargetOptions MCOptions;
157 m_asm_info.reset(
158 target->createMCAsmInfo(*m_reg_info, triple.getTriple(), MCOptions));
159 m_subtype_info.reset(
160 target->createMCSubtargetInfo(triple.getTriple(), cpu, features));
161 assert(m_asm_info.get() && m_subtype_info.get());
163 m_context = std::make_unique<llvm::MCContext>(
164 triple, m_asm_info.get(), m_reg_info.get(), m_subtype_info.get());
165 assert(m_context.get());
167 m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context));
168 assert(m_disasm.get());
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,";
176 m_alt_subtype_info.reset(
177 target->createMCSubtargetInfo(triple.getTriple(), cpu, features));
178 assert(m_alt_subtype_info.get());
180 m_alt_disasm.reset(
181 target->createMCDisassembler(*m_alt_subtype_info, *m_context));
182 assert(m_alt_disasm.get());
184 m_next_inst_size = 0;
185 m_use_alt_disaasm = false;
188 void EmulateInstructionMIPS::Initialize() {
189 PluginManager::RegisterPlugin(GetPluginNameStatic(),
190 GetPluginDescriptionStatic(), CreateInstance);
193 void EmulateInstructionMIPS::Terminate() {
194 PluginManager::UnregisterPlugin(CreateInstance);
197 llvm::StringRef EmulateInstructionMIPS::GetPluginDescriptionStatic() {
198 return "Emulate instructions for the MIPS32 architecture.";
201 EmulateInstruction *
202 EmulateInstructionMIPS::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);
212 return nullptr;
215 bool EmulateInstructionMIPS::SetTargetTriple(const ArchSpec &arch) {
216 return arch.GetTriple().getArch() == llvm::Triple::mips ||
217 arch.GetTriple().getArch() == llvm::Triple::mipsel;
220 const 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;
367 return nullptr;
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";
586 return nullptr;
589 std::optional<RegisterInfo>
590 EmulateInstructionMIPS::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 {};
619 if (reg_kind == eRegisterKindDWARF) {
620 RegisterInfo reg_info;
621 ::memset(&reg_info, 0, sizeof(RegisterInfo));
622 ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
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 {};
644 reg_info.name = GetRegisterName(reg_num, false);
645 reg_info.alt_name = GetRegisterName(reg_num, true);
646 reg_info.kinds[eRegisterKindDWARF] = reg_num;
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;
667 return reg_info;
669 return {};
672 EmulateInstructionMIPS::MipsOpcode *
673 EmulateInstructionMIPS::GetOpcodeForInstruction(llvm::StringRef name) {
674 static EmulateInstructionMIPS::MipsOpcode g_opcodes[] = {
675 // Prologue/Epilogue instructions
676 {"ADDiu", &EmulateInstructionMIPS::Emulate_ADDiu,
677 "ADDIU rt, rs, immediate"},
678 {"SW", &EmulateInstructionMIPS::Emulate_SW, "SW rt, offset(rs)"},
679 {"LW", &EmulateInstructionMIPS::Emulate_LW, "LW rt, offset(base)"},
680 {"SUBU", &EmulateInstructionMIPS::Emulate_SUBU_ADDU, "SUBU rd, rs, rt"},
681 {"ADDU", &EmulateInstructionMIPS::Emulate_SUBU_ADDU, "ADDU rd, rs, rt"},
682 {"LUI", &EmulateInstructionMIPS::Emulate_LUI, "LUI rt, immediate"},
684 // MicroMIPS Prologue/Epilogue instructions
685 {"ADDIUSP_MM", &EmulateInstructionMIPS::Emulate_ADDIUSP,
686 "ADDIU immediate"},
687 {"ADDIUS5_MM", &EmulateInstructionMIPS::Emulate_ADDIUS5,
688 "ADDIUS5 rd,immediate"},
689 {"SWSP_MM", &EmulateInstructionMIPS::Emulate_SWSP, "SWSP rt,offset(sp)"},
690 {"SWM16_MM", &EmulateInstructionMIPS::Emulate_SWM16_32,
691 "SWM16 reglist,offset(sp)"},
692 {"SWM32_MM", &EmulateInstructionMIPS::Emulate_SWM16_32,
693 "SWM32 reglist,offset(base)"},
694 {"SWP_MM", &EmulateInstructionMIPS::Emulate_SWM16_32,
695 "SWP rs1,offset(base)"},
696 {"LWSP_MM", &EmulateInstructionMIPS::Emulate_LWSP, "LWSP rt,offset(sp)"},
697 {"LWM16_MM", &EmulateInstructionMIPS::Emulate_LWM16_32,
698 "LWM16 reglist,offset(sp)"},
699 {"LWM32_MM", &EmulateInstructionMIPS::Emulate_LWM16_32,
700 "LWM32 reglist,offset(base)"},
701 {"LWP_MM", &EmulateInstructionMIPS::Emulate_LWM16_32,
702 "LWP rd,offset(base)"},
703 {"JRADDIUSP", &EmulateInstructionMIPS::Emulate_JRADDIUSP,
704 "JRADDIUSP immediate"},
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 */
714 {"LB", &EmulateInstructionMIPS::Emulate_LDST_Imm,
715 "LB rt, offset(base)"},
716 {"LBE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
717 "LBE rt, offset(base)"},
718 {"LBU", &EmulateInstructionMIPS::Emulate_LDST_Imm,
719 "LBU rt, offset(base)"},
720 {"LBUE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
721 "LBUE rt, offset(base)"},
722 {"LDC1", &EmulateInstructionMIPS::Emulate_LDST_Imm,
723 "LDC1 ft, offset(base)"},
724 {"LD", &EmulateInstructionMIPS::Emulate_LDST_Imm,
725 "LD rt, offset(base)"},
726 {"LDL", &EmulateInstructionMIPS::Emulate_LDST_Imm,
727 "LDL rt, offset(base)"},
728 {"LDR", &EmulateInstructionMIPS::Emulate_LDST_Imm,
729 "LDR rt, offset(base)"},
730 {"LLD", &EmulateInstructionMIPS::Emulate_LDST_Imm,
731 "LLD rt, offset(base)"},
732 {"LDC2", &EmulateInstructionMIPS::Emulate_LDST_Imm,
733 "LDC2 rt, offset(base)"},
734 {"LDXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,
735 "LDXC1 fd, index (base)"},
736 {"LH", &EmulateInstructionMIPS::Emulate_LDST_Imm,
737 "LH rt, offset(base)"},
738 {"LHE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
739 "LHE rt, offset(base)"},
740 {"LHU", &EmulateInstructionMIPS::Emulate_LDST_Imm,
741 "LHU rt, offset(base)"},
742 {"LHUE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
743 "LHUE rt, offset(base)"},
744 {"LL", &EmulateInstructionMIPS::Emulate_LDST_Imm,
745 "LL rt, offset(base)"},
746 {"LLE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
747 "LLE rt, offset(base)"},
748 {"LUXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,
749 "LUXC1 fd, index (base)"},
750 {"LW", &EmulateInstructionMIPS::Emulate_LDST_Imm,
751 "LW rt, offset(base)"},
752 {"LWC1", &EmulateInstructionMIPS::Emulate_LDST_Imm,
753 "LWC1 ft, offset(base)"},
754 {"LWC2", &EmulateInstructionMIPS::Emulate_LDST_Imm,
755 "LWC2 rt, offset(base)"},
756 {"LWE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
757 "LWE rt, offset(base)"},
758 {"LWL", &EmulateInstructionMIPS::Emulate_LDST_Imm,
759 "LWL rt, offset(base)"},
760 {"LWLE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
761 "LWLE rt, offset(base)"},
762 {"LWR", &EmulateInstructionMIPS::Emulate_LDST_Imm,
763 "LWR rt, offset(base)"},
764 {"LWRE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
765 "LWRE rt, offset(base)"},
766 {"LWXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,
767 "LWXC1 fd, index (base)"},
768 {"LLX", &EmulateInstructionMIPS::Emulate_LDST_Imm,
769 "LLX rt, offset(base)"},
770 {"LLXE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
771 "LLXE rt, offset(base)"},
772 {"LLDX", &EmulateInstructionMIPS::Emulate_LDST_Imm,
773 "LLDX rt, offset(base)"},
775 {"SB", &EmulateInstructionMIPS::Emulate_LDST_Imm,
776 "SB rt, offset(base)"},
777 {"SBE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
778 "SBE rt, offset(base)"},
779 {"SC", &EmulateInstructionMIPS::Emulate_LDST_Imm,
780 "SC rt, offset(base)"},
781 {"SCE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
782 "SCE rt, offset(base)"},
783 {"SCD", &EmulateInstructionMIPS::Emulate_LDST_Imm,
784 "SCD rt, offset(base)"},
785 {"SD", &EmulateInstructionMIPS::Emulate_LDST_Imm,
786 "SD rt, offset(base)"},
787 {"SDL", &EmulateInstructionMIPS::Emulate_LDST_Imm,
788 "SDL rt, offset(base)"},
789 {"SDR", &EmulateInstructionMIPS::Emulate_LDST_Imm,
790 "SDR rt, offset(base)"},
791 {"SDC1", &EmulateInstructionMIPS::Emulate_LDST_Imm,
792 "SDC1 ft, offset(base)"},
793 {"SDC2", &EmulateInstructionMIPS::Emulate_LDST_Imm,
794 "SDC2 rt, offset(base)"},
795 {"SDXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,
796 "SDXC1 fs, index(base)"},
797 {"SH", &EmulateInstructionMIPS::Emulate_LDST_Imm,
798 "SH rt, offset(base)"},
799 {"SHE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
800 "SHE rt, offset(base)"},
801 {"SUXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,
802 "SUXC1 fs, index (base)"},
803 {"SWC1", &EmulateInstructionMIPS::Emulate_LDST_Imm,
804 "SWC1 ft, offset(base)"},
805 {"SWC2", &EmulateInstructionMIPS::Emulate_LDST_Imm,
806 "SWC2 rt, offset(base)"},
807 {"SWE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
808 "SWE rt, offset(base)"},
809 {"SWL", &EmulateInstructionMIPS::Emulate_LDST_Imm,
810 "SWL rt, offset(base)"},
811 {"SWLE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
812 "SWLE rt, offset(base)"},
813 {"SWR", &EmulateInstructionMIPS::Emulate_LDST_Imm,
814 "SWR rt, offset(base)"},
815 {"SWRE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
816 "SWRE rt, offset(base)"},
817 {"SWXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,
818 "SWXC1 fs, index (base)"},
819 {"SCX", &EmulateInstructionMIPS::Emulate_LDST_Imm,
820 "SCX rt, offset(base)"},
821 {"SCXE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
822 "SCXE rt, offset(base)"},
823 {"SCDX", &EmulateInstructionMIPS::Emulate_LDST_Imm,
824 "SCDX rt, offset(base)"},
826 // MicroMIPS Load/Store instructions
827 {"LBU16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
828 "LBU16 rt, decoded_offset(base)"},
829 {"LHU16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
830 "LHU16 rt, left_shifted_offset(base)"},
831 {"LW16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
832 "LW16 rt, left_shifted_offset(base)"},
833 {"LWGP_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
834 "LWGP rt, left_shifted_offset(gp)"},
835 {"SH16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
836 "SH16 rt, left_shifted_offset(base)"},
837 {"SW16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
838 "SW16 rt, left_shifted_offset(base)"},
839 {"SW_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
840 "SWSP rt, left_shifted_offset(base)"},
841 {"SB16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
842 "SB16 rt, offset(base)"},
844 // Branch instructions
845 {"BEQ", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BEQ rs,rt,offset"},
846 {"BNE", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BNE rs,rt,offset"},
847 {"BEQL", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BEQL rs,rt,offset"},
848 {"BNEL", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BNEL rs,rt,offset"},
849 {"BGEZALL", &EmulateInstructionMIPS::Emulate_Bcond_Link,
850 "BGEZALL rt,offset"},
851 {"BAL", &EmulateInstructionMIPS::Emulate_BAL, "BAL offset"},
852 {"BGEZAL", &EmulateInstructionMIPS::Emulate_Bcond_Link,
853 "BGEZAL rs,offset"},
854 {"BALC", &EmulateInstructionMIPS::Emulate_BALC, "BALC offset"},
855 {"BC", &EmulateInstructionMIPS::Emulate_BC, "BC offset"},
856 {"BGEZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGEZ rs,offset"},
857 {"BLEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,
858 "BLEZALC rs,offset"},
859 {"BGEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,
860 "BGEZALC rs,offset"},
861 {"BLTZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,
862 "BLTZALC rs,offset"},
863 {"BGTZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,
864 "BGTZALC rs,offset"},
865 {"BEQZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,
866 "BEQZALC rs,offset"},
867 {"BNEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,
868 "BNEZALC rs,offset"},
869 {"BEQC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
870 "BEQC rs,rt,offset"},
871 {"BNEC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
872 "BNEC rs,rt,offset"},
873 {"BLTC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
874 "BLTC rs,rt,offset"},
875 {"BGEC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
876 "BGEC rs,rt,offset"},
877 {"BLTUC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
878 "BLTUC rs,rt,offset"},
879 {"BGEUC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
880 "BGEUC rs,rt,offset"},
881 {"BLTZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BLTZC rt,offset"},
882 {"BLEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BLEZC rt,offset"},
883 {"BGEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BGEZC rt,offset"},
884 {"BGTZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BGTZC rt,offset"},
885 {"BEQZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BEQZC rt,offset"},
886 {"BNEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BNEZC rt,offset"},
887 {"BGEZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGEZL rt,offset"},
888 {"BGTZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGTZ rt,offset"},
889 {"BGTZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGTZL rt,offset"},
890 {"BLEZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLEZ rt,offset"},
891 {"BLEZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLEZL rt,offset"},
892 {"BLTZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLTZ rt,offset"},
893 {"BLTZAL", &EmulateInstructionMIPS::Emulate_Bcond_Link,
894 "BLTZAL rt,offset"},
895 {"BLTZALL", &EmulateInstructionMIPS::Emulate_Bcond_Link,
896 "BLTZALL rt,offset"},
897 {"BLTZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLTZL rt,offset"},
898 {"BOVC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
899 "BOVC rs,rt,offset"},
900 {"BNVC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
901 "BNVC rs,rt,offset"},
902 {"J", &EmulateInstructionMIPS::Emulate_J, "J target"},
903 {"JAL", &EmulateInstructionMIPS::Emulate_JAL, "JAL target"},
904 {"JALX", &EmulateInstructionMIPS::Emulate_JAL, "JALX target"},
905 {"JALR", &EmulateInstructionMIPS::Emulate_JALR, "JALR target"},
906 {"JALR_HB", &EmulateInstructionMIPS::Emulate_JALR, "JALR.HB target"},
907 {"JIALC", &EmulateInstructionMIPS::Emulate_JIALC, "JIALC rt,offset"},
908 {"JIC", &EmulateInstructionMIPS::Emulate_JIC, "JIC rt,offset"},
909 {"JR", &EmulateInstructionMIPS::Emulate_JR, "JR target"},
910 {"JR_HB", &EmulateInstructionMIPS::Emulate_JR, "JR.HB target"},
911 {"BC1F", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1F cc, offset"},
912 {"BC1T", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1T cc, offset"},
913 {"BC1FL", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1FL cc, offset"},
914 {"BC1TL", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1TL cc, offset"},
915 {"BC1EQZ", &EmulateInstructionMIPS::Emulate_BC1EQZ, "BC1EQZ ft, offset"},
916 {"BC1NEZ", &EmulateInstructionMIPS::Emulate_BC1NEZ, "BC1NEZ ft, offset"},
917 {"BC1ANY2F", &EmulateInstructionMIPS::Emulate_3D_branch,
918 "BC1ANY2F cc, offset"},
919 {"BC1ANY2T", &EmulateInstructionMIPS::Emulate_3D_branch,
920 "BC1ANY2T cc, offset"},
921 {"BC1ANY4F", &EmulateInstructionMIPS::Emulate_3D_branch,
922 "BC1ANY4F cc, offset"},
923 {"BC1ANY4T", &EmulateInstructionMIPS::Emulate_3D_branch,
924 "BC1ANY4T cc, offset"},
925 {"BNZ_B", &EmulateInstructionMIPS::Emulate_BNZB, "BNZ.b wt,s16"},
926 {"BNZ_H", &EmulateInstructionMIPS::Emulate_BNZH, "BNZ.h wt,s16"},
927 {"BNZ_W", &EmulateInstructionMIPS::Emulate_BNZW, "BNZ.w wt,s16"},
928 {"BNZ_D", &EmulateInstructionMIPS::Emulate_BNZD, "BNZ.d wt,s16"},
929 {"BZ_B", &EmulateInstructionMIPS::Emulate_BZB, "BZ.b wt,s16"},
930 {"BZ_H", &EmulateInstructionMIPS::Emulate_BZH, "BZ.h wt,s16"},
931 {"BZ_W", &EmulateInstructionMIPS::Emulate_BZW, "BZ.w wt,s16"},
932 {"BZ_D", &EmulateInstructionMIPS::Emulate_BZD, "BZ.d wt,s16"},
933 {"BNZ_V", &EmulateInstructionMIPS::Emulate_BNZV, "BNZ.V wt,s16"},
934 {"BZ_V", &EmulateInstructionMIPS::Emulate_BZV, "BZ.V wt,s16"},
936 // MicroMIPS Branch instructions
937 {"B16_MM", &EmulateInstructionMIPS::Emulate_B16_MM, "B16 offset"},
938 {"BEQZ16_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,
939 "BEQZ16 rs, offset"},
940 {"BNEZ16_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,
941 "BNEZ16 rs, offset"},
942 {"BEQZC_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,
943 "BEQZC rs, offset"},
944 {"BNEZC_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,
945 "BNEZC rs, offset"},
946 {"BGEZALS_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,
947 "BGEZALS rs, offset"},
948 {"BLTZALS_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,
949 "BLTZALS rs, offset"},
950 {"JALR16_MM", &EmulateInstructionMIPS::Emulate_JALRx16_MM, "JALR16 rs"},
951 {"JALRS16_MM", &EmulateInstructionMIPS::Emulate_JALRx16_MM, "JALRS16 rs"},
952 {"JR16_MM", &EmulateInstructionMIPS::Emulate_JR, "JR16 rs rs"},
953 {"JRC16_MM", &EmulateInstructionMIPS::Emulate_JR, "JRC16 rs rs"},
954 {"JALS_MM", &EmulateInstructionMIPS::Emulate_JALx, "JALS target"},
955 {"JALX_MM", &EmulateInstructionMIPS::Emulate_JALx, "JALX target"},
956 {"JALRS_MM", &EmulateInstructionMIPS::Emulate_JALRS, "JALRS rt, rs"},
959 for (MipsOpcode &opcode : g_opcodes) {
960 if (name.equals_insensitive(opcode.op_name))
961 return &opcode;
963 return nullptr;
966 uint32_t
967 EmulateInstructionMIPS::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());
974 if (m_use_alt_disaasm)
975 decode_status = m_alt_disasm->getInstruction(
976 mc_insn, next_inst_size, raw_insn, inst_addr, llvm::nulls());
977 else
978 decode_status = m_disasm->getInstruction(mc_insn, next_inst_size, raw_insn,
979 inst_addr, llvm::nulls());
981 if (decode_status != llvm::MCDisassembler::Success)
982 return false;
984 return m_insn_info->get(mc_insn.getOpcode()).getSize();
987 bool EmulateInstructionMIPS::SetInstruction(const Opcode &insn_opcode,
988 const Address &inst_addr,
989 Target *target) {
990 m_use_alt_disaasm = false;
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;
998 * The address belongs to microMIPS function. To find the size of
999 * next instruction use microMIPS disassembler.
1001 m_use_alt_disaasm = true;
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);
1008 const size_t bytes_read =
1009 target->ReadMemory(next_addr, /* Address of next instruction */
1010 buf, sizeof(uint32_t), error,
1011 false, /* force_live_memory */
1012 &load_addr);
1014 if (bytes_read == 0)
1015 return true;
1017 DataExtractor data(buf, sizeof(uint32_t), GetByteOrder(),
1018 GetAddressByteSize());
1019 m_next_inst_size = GetSizeOfInstruction(data, next_inst_addr);
1020 return true;
1021 } else {
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.
1027 m_next_inst_size = 4;
1028 return true;
1031 return false;
1034 bool EmulateInstructionMIPS::ReadInstruction() {
1035 bool success = false;
1036 m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
1037 LLDB_INVALID_ADDRESS, &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 ReadMemoryUnsigned(read_inst_context, m_addr, 4, 0, &success),
1044 GetByteOrder());
1046 if (!success)
1047 m_addr = LLDB_INVALID_ADDRESS;
1048 return success;
1051 bool EmulateInstructionMIPS::EvaluateInstruction(uint32_t evaluate_options) {
1052 bool success = false;
1053 llvm::MCInst mc_insn;
1054 uint64_t insn_size;
1055 DataExtractor data;
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(mc_insn, insn_size, raw_insn,
1064 m_addr, llvm::nulls());
1065 else
1066 decode_status = m_disasm->getInstruction(mc_insn, insn_size, raw_insn,
1067 m_addr, llvm::nulls());
1069 if (decode_status != llvm::MCDisassembler::Success)
1070 return false;
1074 * mc_insn.getOpcode() returns decoded opcode. However to make use
1075 * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc".
1077 const char *op_name = m_insn_info->getName(mc_insn.getOpcode()).data();
1079 if (op_name == nullptr)
1080 return false;
1083 * Decoding has been done already. Just get the call-back function
1084 * and emulate the instruction.
1086 MipsOpcode *opcode_data = GetOpcodeForInstruction(op_name);
1088 if (opcode_data == nullptr)
1089 return false;
1091 uint64_t old_pc = 0, new_pc = 0;
1092 const bool auto_advance_pc =
1093 evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
1095 if (auto_advance_pc) {
1096 old_pc =
1097 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
1098 if (!success)
1099 return false;
1102 /* emulate instruction */
1103 success = (this->*opcode_data->callback)(mc_insn);
1104 if (!success)
1105 return false;
1107 if (auto_advance_pc) {
1108 new_pc =
1109 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
1110 if (!success)
1111 return false;
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, eRegisterKindDWARF, dwarf_pc_mips,
1118 new_pc))
1119 return false;
1123 return true;
1126 bool EmulateInstructionMIPS::CreateFunctionEntryUnwind(
1127 UnwindPlan &unwind_plan) {
1128 unwind_plan.Clear();
1129 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
1131 UnwindPlan::RowSP row(new UnwindPlan::Row);
1132 const bool can_replace = false;
1134 // Our previous Call Frame Address is the stack pointer
1135 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips, 0);
1137 // Our previous PC is in the RA
1138 row->SetRegisterLocationToRegister(dwarf_pc_mips, dwarf_ra_mips, can_replace);
1140 unwind_plan.AppendRow(row);
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);
1149 return true;
1152 bool 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;
1170 return false;
1173 bool EmulateInstructionMIPS::Emulate_ADDiu(llvm::MCInst &insn) {
1174 // ADDIU rt, rs, immediate
1175 // GPR[rt] <- GPR[rs] + sign_extend(immediate)
1177 uint8_t dst, src;
1178 bool success = false;
1179 const uint32_t imm16 = insn.getOperand(2).getImm();
1180 int64_t imm = SignedBits(imm16, 15, 0);
1182 dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1183 src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
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;
1192 /* read <src> register */
1193 const int64_t src_opd_val = ReadRegisterUnsigned(
1194 eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success);
1195 if (!success)
1196 return false;
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(eRegisterKindDWARF, dwarf_sp_mips);
1203 if (reg_info_sp)
1204 context.SetRegisterPlusOffset(*reg_info_sp, imm);
1206 /* We are allocating bytes on stack */
1207 context.type = eContextAdjustStackPointer;
1209 WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);
1210 return true;
1213 imm += src_opd_val;
1214 context.SetImmediateSigned(imm);
1215 context.type = eContextImmediate;
1217 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1218 dwarf_zero_mips + dst, imm))
1219 return false;
1222 return true;
1225 bool EmulateInstructionMIPS::Emulate_SW(llvm::MCInst &insn) {
1226 bool success = false;
1227 uint32_t imm16 = insn.getOperand(2).getImm();
1228 uint32_t imm = SignedBits(imm16, 15, 0);
1229 uint32_t src, base;
1230 int32_t address;
1231 Context bad_vaddr_context;
1233 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1234 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1236 std::optional<RegisterInfo> reg_info_base =
1237 GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base);
1238 if (!reg_info_base)
1239 return false;
1241 /* read base register */
1242 address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1243 dwarf_zero_mips + base, 0, &success);
1244 if (!success)
1245 return false;
1247 /* destination address */
1248 address = address + imm;
1250 /* Set the bad_vaddr register with base address used in the instruction */
1251 bad_vaddr_context.type = eContextInvalid;
1252 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
1253 address);
1255 /* We look for sp based non-volatile register stores */
1256 if (nonvolatile_reg_p(src)) {
1257 std::optional<RegisterInfo> reg_info_src =
1258 GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src);
1259 if (!reg_info_src)
1260 return false;
1262 Context context;
1263 context.type = eContextPushRegisterOnStack;
1264 context.SetRegisterToRegisterPlusOffset(*reg_info_src, *reg_info_base, 0);
1266 RegisterValue::BytesContainer buffer(reg_info_src->byte_size);
1267 Status error;
1269 std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);
1270 if (!data_src)
1271 return false;
1273 if (data_src->GetAsMemoryData(*reg_info_src, buffer.data(),
1274 reg_info_src->byte_size, eByteOrderLittle,
1275 error) == 0)
1276 return false;
1278 if (!WriteMemory(context, address, buffer.data(), reg_info_src->byte_size))
1279 return false;
1281 return true;
1284 return false;
1287 bool 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;
1293 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1294 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1295 imm = insn.getOperand(2).getImm();
1297 if (GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))
1298 return false;
1300 /* read base register */
1301 address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1302 dwarf_zero_mips + base, 0, &success);
1303 if (!success)
1304 return false;
1306 /* destination address */
1307 address = address + imm;
1309 /* Set the bad_vaddr register with base address used in the instruction */
1310 bad_vaddr_context.type = eContextInvalid;
1311 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
1312 address);
1314 if (nonvolatile_reg_p(src)) {
1315 RegisterValue data_src;
1316 std::optional<RegisterInfo> reg_info_src =
1317 GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src);
1318 if (!reg_info_src)
1319 return false;
1321 Context context;
1322 context.type = eContextPopRegisterOffStack;
1323 context.SetAddress(address);
1325 return WriteRegister(context, *reg_info_src, data_src);
1328 return false;
1331 bool EmulateInstructionMIPS::Emulate_SUBU_ADDU(llvm::MCInst &insn) {
1332 // SUBU sp, <src>, <rt>
1333 // ADDU sp, <src>, <rt>
1334 // ADDU dst, sp, <rt>
1336 bool success = false;
1337 uint64_t result;
1338 uint8_t src, dst, rt;
1339 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1341 dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1342 src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1344 /* Check if sp is destination register */
1345 if (dst == dwarf_sp_mips) {
1346 rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1348 /* read <src> register */
1349 uint64_t src_opd_val = ReadRegisterUnsigned(
1350 eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success);
1351 if (!success)
1352 return false;
1354 /* read <rt > register */
1355 uint64_t rt_opd_val = ReadRegisterUnsigned(
1356 eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
1357 if (!success)
1358 return false;
1360 if (op_name.equals_insensitive("SUBU"))
1361 result = src_opd_val - rt_opd_val;
1362 else
1363 result = src_opd_val + rt_opd_val;
1365 Context context;
1366 std::optional<RegisterInfo> reg_info_sp =
1367 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);
1368 if (reg_info_sp)
1369 context.SetRegisterPlusOffset(*reg_info_sp, rt_opd_val);
1371 /* We are allocating bytes on stack */
1372 context.type = eContextAdjustStackPointer;
1374 WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);
1376 return true;
1377 } else if (src == dwarf_sp_mips) {
1378 rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1380 /* read <src> register */
1381 uint64_t src_opd_val = ReadRegisterUnsigned(
1382 eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success);
1383 if (!success)
1384 return false;
1386 /* read <rt> register */
1387 uint64_t rt_opd_val = ReadRegisterUnsigned(
1388 eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
1389 if (!success)
1390 return false;
1392 Context context;
1394 if (op_name.equals_insensitive("SUBU"))
1395 result = src_opd_val - rt_opd_val;
1396 else
1397 result = src_opd_val + rt_opd_val;
1399 context.SetImmediateSigned(result);
1400 context.type = eContextImmediate;
1402 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1403 dwarf_zero_mips + dst, result))
1404 return false;
1407 return true;
1410 bool EmulateInstructionMIPS::Emulate_LUI(llvm::MCInst &insn) {
1411 // LUI rt, immediate
1412 // GPR[rt] <- sign_extend(immediate << 16)
1414 const uint32_t imm32 = insn.getOperand(1).getImm() << 16;
1415 int64_t imm = SignedBits(imm32, 31, 0);
1416 uint8_t rt;
1417 Context context;
1419 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1420 context.SetImmediateSigned(imm);
1421 context.type = eContextImmediate;
1423 return WriteRegisterUnsigned(context, eRegisterKindDWARF,
1424 dwarf_zero_mips + rt, imm);
1427 bool EmulateInstructionMIPS::Emulate_ADDIUSP(llvm::MCInst &insn) {
1428 bool success = false;
1429 const uint32_t imm9 = insn.getOperand(0).getImm();
1430 uint64_t result;
1432 // This instruction operates implicitly on stack pointer, so read <sp>
1433 // register.
1434 uint64_t src_opd_val =
1435 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_sp_mips, 0, &success);
1436 if (!success)
1437 return false;
1439 result = src_opd_val + imm9;
1441 Context context;
1442 std::optional<RegisterInfo> reg_info_sp =
1443 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);
1444 if (reg_info_sp)
1445 context.SetRegisterPlusOffset(*reg_info_sp, imm9);
1447 // We are adjusting the stack.
1448 context.type = eContextAdjustStackPointer;
1450 WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);
1451 return true;
1454 bool EmulateInstructionMIPS::Emulate_ADDIUS5(llvm::MCInst &insn) {
1455 bool success = false;
1456 uint32_t base;
1457 const uint32_t imm4 = insn.getOperand(2).getImm();
1458 uint64_t result;
1460 // The source and destination register is same for this instruction.
1461 base = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
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 eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
1468 if (!success)
1469 return false;
1471 result = src_opd_val + imm4;
1473 Context context;
1474 std::optional<RegisterInfo> reg_info_sp =
1475 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);
1476 if (reg_info_sp)
1477 context.SetRegisterPlusOffset(*reg_info_sp, imm4);
1479 // We are adjusting the stack.
1480 context.type = eContextAdjustStackPointer;
1482 WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);
1485 return true;
1488 bool EmulateInstructionMIPS::Emulate_SWSP(llvm::MCInst &insn) {
1489 bool success = false;
1490 uint32_t imm5 = insn.getOperand(2).getImm();
1491 uint32_t src, base;
1492 Context bad_vaddr_context;
1493 uint32_t address;
1495 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1496 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1498 std::optional<RegisterInfo> reg_info_base =
1499 GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base);
1500 if (!reg_info_base)
1501 return false;
1503 // read base register
1504 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0,
1505 &success);
1506 if (!success)
1507 return false;
1509 // destination address
1510 address = address + imm5;
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(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
1517 address);
1519 // We look for sp based non-volatile register stores.
1520 if (base == dwarf_sp_mips && nonvolatile_reg_p(src)) {
1521 RegisterInfo reg_info_src = {};
1522 Context context;
1523 context.type = eContextPushRegisterOnStack;
1524 context.SetRegisterToRegisterPlusOffset(reg_info_src, *reg_info_base, 0);
1526 RegisterValue::BytesContainer buffer(reg_info_src.byte_size);
1527 Status error;
1529 std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);
1530 if (!data_src)
1531 return false;
1533 if (data_src->GetAsMemoryData(reg_info_src, buffer.data(),
1534 reg_info_src.byte_size, eByteOrderLittle,
1535 error) == 0)
1536 return false;
1538 if (!WriteMemory(context, address, buffer.data(), reg_info_src.byte_size))
1539 return false;
1541 return true;
1544 return false;
1547 /* Emulate SWM16,SWM32 and SWP instruction.
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.
1553 bool 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.
1559 // Base register is second last operand of the instruction.
1560 base =
1561 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
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;
1568 // offset is always the last operand.
1569 uint32_t offset = insn.getOperand(num_operands - 1).getImm();
1571 std::optional<RegisterInfo> reg_info_base =
1572 GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base);
1573 if (!reg_info_base)
1574 return false;
1576 // read SP
1577 uint32_t base_address = ReadRegisterUnsigned(
1578 eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
1579 if (!success)
1580 return false;
1582 // Resulting base addrss
1583 base_address = base_address + offset;
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(insn.getOperand(i).getReg());
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.
1597 if (!nonvolatile_reg_p(src))
1598 return false;
1600 std::optional<RegisterInfo> reg_info_src =
1601 GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src);
1602 if (!reg_info_src)
1603 return false;
1605 Context context;
1606 context.type = eContextPushRegisterOnStack;
1607 context.SetRegisterToRegisterPlusOffset(*reg_info_src, *reg_info_base, 0);
1609 RegisterValue::BytesContainer buffer(reg_info_src->byte_size);
1610 Status error;
1612 std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);
1613 if (!data_src)
1614 return false;
1616 if (data_src->GetAsMemoryData(*reg_info_src, buffer.data(),
1617 reg_info_src->byte_size, eByteOrderLittle,
1618 error) == 0)
1619 return false;
1621 if (!WriteMemory(context, base_address, buffer.data(),
1622 reg_info_src->byte_size))
1623 return false;
1625 // Stack address for next register
1626 base_address = base_address + reg_info_src->byte_size;
1628 return true;
1631 bool EmulateInstructionMIPS::Emulate_LWSP(llvm::MCInst &insn) {
1632 bool success = false;
1633 uint32_t src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1634 uint32_t base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1635 uint32_t imm5 = insn.getOperand(2).getImm();
1636 Context bad_vaddr_context;
1638 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))
1639 return false;
1641 // read base register
1642 uint32_t base_address = ReadRegisterUnsigned(
1643 eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
1644 if (!success)
1645 return false;
1647 base_address = base_address + imm5;
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(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
1654 base_address);
1656 if (base == dwarf_sp_mips && nonvolatile_reg_p(src)) {
1657 RegisterValue data_src;
1658 std::optional<RegisterInfo> reg_info_src =
1659 GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src);
1660 if (!reg_info_src)
1661 return false;
1663 Context context;
1664 context.type = eContextPopRegisterOffStack;
1665 context.SetAddress(base_address);
1667 return WriteRegister(context, *reg_info_src, data_src);
1670 return false;
1673 /* Emulate LWM16, LWM32 and LWP instructions.
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.
1679 bool 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(num_operands - 1)
1685 .getImm(); // imm is the last operand in the instruction.
1687 // Base register is second last operand of the instruction.
1688 base =
1689 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
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;
1696 uint32_t base_address = ReadRegisterUnsigned(
1697 eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
1698 if (!success)
1699 return false;
1701 base_address = base_address + imm;
1703 RegisterValue data_dst;
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(insn.getOperand(i).getReg());
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.
1717 if (!nonvolatile_reg_p(dst))
1718 return false;
1720 std::optional<RegisterInfo> reg_info_dst =
1721 GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + dst);
1722 if (!reg_info_dst)
1723 return false;
1725 Context context;
1726 context.type = eContextPopRegisterOffStack;
1727 context.SetAddress(base_address + (i * 4));
1729 if (!WriteRegister(context, *reg_info_dst, data_dst))
1730 return false;
1733 return true;
1736 bool EmulateInstructionMIPS::Emulate_JRADDIUSP(llvm::MCInst &insn) {
1737 bool success = false;
1738 int32_t imm5 = insn.getOperand(0).getImm();
1740 /* JRADDIUSP immediate
1741 * PC <- RA
1742 * SP <- SP + zero_extend(Immediate << 2)
1745 // This instruction operates implicitly on stack pointer, so read <sp>
1746 // register.
1747 int32_t src_opd_val =
1748 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_sp_mips, 0, &success);
1749 if (!success)
1750 return false;
1752 int32_t ra_val =
1753 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_ra_mips, 0, &success);
1754 if (!success)
1755 return false;
1757 int32_t result = src_opd_val + imm5;
1759 Context context;
1761 // Update the PC
1762 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
1763 ra_val))
1764 return false;
1766 std::optional<RegisterInfo> reg_info_sp =
1767 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);
1768 if (reg_info_sp)
1769 context.SetRegisterPlusOffset(*reg_info_sp, imm5);
1771 // We are adjusting stack
1772 context.type = eContextAdjustStackPointer;
1774 // update SP
1775 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips,
1776 result);
1779 static 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);
1785 Emulate below MIPS branch instructions.
1786 BEQ, BNE : Branch on condition
1787 BEQL, BNEL : Branch likely
1789 bool 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(insn.getOpcode());
1795 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1796 rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1797 offset = insn.getOperand(2).getImm();
1799 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
1800 if (!success)
1801 return false;
1803 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1804 dwarf_zero_mips + rs, 0, &success);
1805 if (!success)
1806 return false;
1808 rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1809 dwarf_zero_mips + rt, 0, &success);
1810 if (!success)
1811 return false;
1813 if (op_name.equals_insensitive("BEQ") || op_name.equals_insensitive("BEQL")) {
1814 if (rs_val == rt_val)
1815 target = pc + offset;
1816 else
1817 target = pc + 8;
1818 } else if (op_name.equals_insensitive("BNE") ||
1819 op_name.equals_insensitive("BNEL")) {
1820 if (rs_val != rt_val)
1821 target = pc + offset;
1822 else
1823 target = pc + 8;
1826 Context context;
1827 context.type = eContextRelativeBranchImmediate;
1828 context.SetImmediate(offset);
1830 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
1831 target);
1835 Emulate below MIPS branch instructions.
1836 BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch
1837 instructions with no delay slot
1839 bool 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(insn.getOpcode());
1844 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
1846 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1847 rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1848 offset = insn.getOperand(2).getImm();
1850 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
1851 if (!success)
1852 return false;
1854 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1855 dwarf_zero_mips + rs, 0, &success);
1856 if (!success)
1857 return false;
1859 rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1860 dwarf_zero_mips + rt, 0, &success);
1861 if (!success)
1862 return false;
1864 if (op_name.equals_insensitive("BEQC")) {
1865 if (rs_val == rt_val)
1866 target = pc + offset;
1867 else
1868 target = pc + 4;
1869 } else if (op_name.equals_insensitive("BNEC")) {
1870 if (rs_val != rt_val)
1871 target = pc + offset;
1872 else
1873 target = pc + 4;
1874 } else if (op_name.equals_insensitive("BLTC")) {
1875 if (rs_val < rt_val)
1876 target = pc + offset;
1877 else
1878 target = pc + 4;
1879 } else if (op_name.equals_insensitive("BGEC")) {
1880 if (rs_val >= rt_val)
1881 target = pc + offset;
1882 else
1883 target = pc + 4;
1884 } else if (op_name.equals_insensitive("BLTUC")) {
1885 if (rs_val < rt_val)
1886 target = pc + offset;
1887 else
1888 target = pc + 4;
1889 } else if (op_name.equals_insensitive("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("BOVC")) {
1895 if (IsAdd64bitOverflow(rs_val, rt_val))
1896 target = pc + offset;
1897 else
1898 target = pc + 4;
1899 } else if (op_name.equals_insensitive("BNVC")) {
1900 if (!IsAdd64bitOverflow(rs_val, rt_val))
1901 target = pc + offset;
1902 else
1903 target = pc + 4;
1906 Context context;
1907 context.type = eContextRelativeBranchImmediate;
1908 context.SetImmediate(current_inst_size + offset);
1910 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
1911 target);
1915 Emulate below MIPS conditional branch and link instructions.
1916 BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches
1918 bool 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(insn.getOpcode());
1925 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1926 offset = insn.getOperand(1).getImm();
1928 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
1929 if (!success)
1930 return false;
1932 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1933 dwarf_zero_mips + rs, 0, &success);
1934 if (!success)
1935 return false;
1937 if (op_name.equals_insensitive("BLEZALC")) {
1938 if (rs_val <= 0)
1939 target = pc + offset;
1940 else
1941 target = pc + 4;
1942 } else if (op_name.equals_insensitive("BGEZALC")) {
1943 if (rs_val >= 0)
1944 target = pc + offset;
1945 else
1946 target = pc + 4;
1947 } else if (op_name.equals_insensitive("BLTZALC")) {
1948 if (rs_val < 0)
1949 target = pc + offset;
1950 else
1951 target = pc + 4;
1952 } else if (op_name.equals_insensitive("BGTZALC")) {
1953 if (rs_val > 0)
1954 target = pc + offset;
1955 else
1956 target = pc + 4;
1957 } else if (op_name.equals_insensitive("BEQZALC")) {
1958 if (rs_val == 0)
1959 target = pc + offset;
1960 else
1961 target = pc + 4;
1962 } else if (op_name.equals_insensitive("BNEZALC")) {
1963 if (rs_val != 0)
1964 target = pc + offset;
1965 else
1966 target = pc + 4;
1969 Context context;
1971 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
1972 target))
1973 return false;
1975 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
1976 pc + 4))
1977 return false;
1979 return true;
1983 Emulate below MIPS Non-Compact conditional branch and link instructions.
1984 BLTZAL, BGEZAL :
1985 BLTZALL, BGEZALL : Branch likely
1987 bool 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(insn.getOpcode());
1994 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1995 offset = insn.getOperand(1).getImm();
1997 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
1998 if (!success)
1999 return false;
2001 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2002 dwarf_zero_mips + rs, 0, &success);
2003 if (!success)
2004 return false;
2006 if (op_name.equals_insensitive("BLTZAL") ||
2007 op_name.equals_insensitive("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("BGEZAL") ||
2013 op_name.equals_insensitive("BGEZALL")) {
2014 if ((int32_t)rs_val >= 0)
2015 target = pc + offset;
2016 else
2017 target = pc + 8;
2020 Context context;
2022 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2023 target))
2024 return false;
2026 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2027 pc + 8))
2028 return false;
2030 return true;
2034 Emulate below MIPS branch instructions.
2035 BLTZL, BGEZL, BGTZL, BLEZL : Branch likely
2036 BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches
2038 bool 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(insn.getOpcode());
2045 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2046 offset = insn.getOperand(1).getImm();
2048 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2049 if (!success)
2050 return false;
2052 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2053 dwarf_zero_mips + rs, 0, &success);
2054 if (!success)
2055 return false;
2057 if (op_name.equals_insensitive("BLTZL") ||
2058 op_name.equals_insensitive("BLTZ")) {
2059 if (rs_val < 0)
2060 target = pc + offset;
2061 else
2062 target = pc + 8;
2063 } else if (op_name.equals_insensitive("BGEZL") ||
2064 op_name.equals_insensitive("BGEZ")) {
2065 if (rs_val >= 0)
2066 target = pc + offset;
2067 else
2068 target = pc + 8;
2069 } else if (op_name.equals_insensitive("BGTZL") ||
2070 op_name.equals_insensitive("BGTZ")) {
2071 if (rs_val > 0)
2072 target = pc + offset;
2073 else
2074 target = pc + 8;
2075 } else if (op_name.equals_insensitive("BLEZL") ||
2076 op_name.equals_insensitive("BLEZ")) {
2077 if (rs_val <= 0)
2078 target = pc + offset;
2079 else
2080 target = pc + 8;
2083 Context context;
2084 context.type = eContextRelativeBranchImmediate;
2085 context.SetImmediate(offset);
2087 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2088 target);
2092 Emulate below MIPS branch instructions.
2093 BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches
2095 bool 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(insn.getOpcode());
2101 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
2103 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2104 offset = insn.getOperand(1).getImm();
2106 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2107 if (!success)
2108 return false;
2110 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2111 dwarf_zero_mips + rs, 0, &success);
2112 if (!success)
2113 return false;
2115 if (op_name.equals_insensitive("BLTZC")) {
2116 if (rs_val < 0)
2117 target = pc + offset;
2118 else
2119 target = pc + 4;
2120 } else if (op_name.equals_insensitive("BLEZC")) {
2121 if (rs_val <= 0)
2122 target = pc + offset;
2123 else
2124 target = pc + 4;
2125 } else if (op_name.equals_insensitive("BGEZC")) {
2126 if (rs_val >= 0)
2127 target = pc + offset;
2128 else
2129 target = pc + 4;
2130 } else if (op_name.equals_insensitive("BGTZC")) {
2131 if (rs_val > 0)
2132 target = pc + offset;
2133 else
2134 target = pc + 4;
2135 } else if (op_name.equals_insensitive("BEQZC")) {
2136 if (rs_val == 0)
2137 target = pc + offset;
2138 else
2139 target = pc + 4;
2140 } else if (op_name.equals_insensitive("BNEZC")) {
2141 if (rs_val != 0)
2142 target = pc + offset;
2143 else
2144 target = pc + 4;
2147 Context context;
2148 context.type = eContextRelativeBranchImmediate;
2149 context.SetImmediate(current_inst_size + offset);
2151 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2152 target);
2155 bool 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(insn.getOpcode()).getSize();
2160 offset = insn.getOperand(0).getImm();
2162 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2163 if (!success)
2164 return false;
2166 // unconditional branch
2167 target = pc + offset;
2169 Context context;
2170 context.type = eContextRelativeBranchImmediate;
2171 context.SetImmediate(current_inst_size + offset);
2173 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2174 target);
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.
2182 bool 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(insn.getOpcode()).getSize();
2186 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2187 bool update_ra = false;
2188 uint32_t ra_offset = 0;
2191 * BEQZ16 rs, offset
2192 * condition <- (GPR[rs] = 0)
2193 * if condition then
2194 * PC = PC + sign_ext (offset || 0)
2196 * BNEZ16 rs, offset
2197 * condition <- (GPR[rs] != 0)
2198 * if condition then
2199 * PC = PC + sign_ext (offset || 0)
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)
2207 uint32_t rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2208 int32_t offset = insn.getOperand(1).getImm();
2210 int32_t pc =
2211 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2212 if (!success)
2213 return false;
2215 int32_t rs_val = (int32_t)ReadRegisterUnsigned(
2216 eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
2217 if (!success)
2218 return false;
2220 if (op_name.equals_insensitive("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("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("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("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("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
2252 update_ra = true;
2253 ra_offset = 6;
2254 } else if (op_name.equals_insensitive("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
2260 update_ra = true;
2261 ra_offset = 6;
2264 Context context;
2265 context.type = eContextRelativeBranchImmediate;
2266 context.SetImmediate(current_inst_size + offset);
2268 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2269 target))
2270 return false;
2272 if (update_ra) {
2273 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2274 pc + ra_offset))
2275 return false;
2277 return true;
2280 /* Emulate micromips jump instructions.
2281 JALR16,JALRS16
2283 bool 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(insn.getOpcode());
2288 uint32_t rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2290 uint32_t pc =
2291 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2292 if (!success)
2293 return false;
2295 uint32_t rs_val = ReadRegisterUnsigned(eRegisterKindDWARF,
2296 dwarf_zero_mips + rs, 0, &success);
2297 if (!success)
2298 return false;
2300 if (op_name.equals_insensitive("JALR16_MM"))
2301 ra_offset = 6; // 2-byte instruction with 4-byte delay slot.
2302 else if (op_name.equals_insensitive("JALRS16_MM"))
2303 ra_offset = 4; // 2-byte instruction with 2-byte delay slot.
2305 Context context;
2307 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2308 rs_val))
2309 return false;
2311 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2312 pc + ra_offset))
2313 return false;
2315 return true;
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.
2322 bool 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(insn.getOpcode());
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
2337 offset = insn.getOperand(0).getImm();
2339 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2340 if (!success)
2341 return false;
2343 // These are PC-region branches and not PC-relative.
2344 if (op_name.equals_insensitive("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("JALX_MM")) {
2349 // target address is in the “current” 256 MB-aligned region
2350 target = (pc & 0xF0000000UL) | offset;
2351 ra_offset = 8;
2354 Context context;
2356 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2357 target))
2358 return false;
2360 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2361 pc + ra_offset))
2362 return false;
2364 return true;
2367 bool 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;
2373 JALRS rt, rs
2374 GPR[rt] <- PC + 6
2375 PC <- GPR[rs]
2378 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2379 rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
2381 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2382 dwarf_zero_mips + rs, 0, &success);
2383 if (!success)
2384 return false;
2386 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2387 if (!success)
2388 return false;
2390 Context context;
2392 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2393 rs_val))
2394 return false;
2396 // This is 4-byte instruction with 2-byte delay slot.
2397 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_zero_mips + rt,
2398 pc + 6))
2399 return false;
2401 return true;
2404 bool EmulateInstructionMIPS::Emulate_BAL(llvm::MCInst &insn) {
2405 bool success = false;
2406 int32_t offset, pc, target;
2409 * BAL offset
2410 * offset = sign_ext (offset << 2)
2411 * RA = PC + 8
2412 * PC = PC + offset
2414 offset = insn.getOperand(0).getImm();
2416 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2417 if (!success)
2418 return false;
2420 target = pc + offset;
2422 Context context;
2424 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2425 target))
2426 return false;
2428 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2429 pc + 8))
2430 return false;
2432 return true;
2435 bool EmulateInstructionMIPS::Emulate_BALC(llvm::MCInst &insn) {
2436 bool success = false;
2437 int32_t offset, pc, target;
2440 * BALC offset
2441 * offset = sign_ext (offset << 2)
2442 * RA = PC + 4
2443 * PC = PC + 4 + offset
2445 offset = insn.getOperand(0).getImm();
2447 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2448 if (!success)
2449 return false;
2451 target = pc + offset;
2453 Context context;
2455 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2456 target))
2457 return false;
2459 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2460 pc + 4))
2461 return false;
2463 return true;
2466 bool EmulateInstructionMIPS::Emulate_BC(llvm::MCInst &insn) {
2467 bool success = false;
2468 int32_t offset, pc, target;
2471 * BC offset
2472 * offset = sign_ext (offset << 2)
2473 * PC = PC + 4 + offset
2475 offset = insn.getOperand(0).getImm();
2477 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2478 if (!success)
2479 return false;
2481 target = pc + offset;
2483 Context context;
2485 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2486 target);
2489 bool EmulateInstructionMIPS::Emulate_J(llvm::MCInst &insn) {
2490 bool success = false;
2491 uint32_t offset, pc;
2494 * J offset
2495 * offset = sign_ext (offset << 2)
2496 * PC = PC[63-28] | offset
2498 offset = insn.getOperand(0).getImm();
2500 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2501 if (!success)
2502 return false;
2504 /* This is a PC-region branch and not PC-relative */
2505 pc = (pc & 0xF0000000UL) | offset;
2507 Context context;
2509 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, pc);
2512 bool EmulateInstructionMIPS::Emulate_JAL(llvm::MCInst &insn) {
2513 bool success = false;
2514 uint32_t offset, target, pc;
2517 * JAL offset
2518 * offset = sign_ext (offset << 2)
2519 * PC = PC[63-28] | offset
2521 offset = insn.getOperand(0).getImm();
2523 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2524 if (!success)
2525 return false;
2527 /* This is a PC-region branch and not PC-relative */
2528 target = (pc & 0xF0000000UL) | offset;
2530 Context context;
2532 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2533 target))
2534 return false;
2536 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2537 pc + 8))
2538 return false;
2540 return true;
2543 bool EmulateInstructionMIPS::Emulate_JALR(llvm::MCInst &insn) {
2544 bool success = false;
2545 uint32_t rs, rt;
2546 uint32_t pc, rs_val;
2549 * JALR rt, rs
2550 * GPR[rt] = PC + 8
2551 * PC = GPR[rs]
2553 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2554 rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
2556 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2557 if (!success)
2558 return false;
2560 rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + rs, 0,
2561 &success);
2562 if (!success)
2563 return false;
2565 Context context;
2567 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2568 rs_val))
2569 return false;
2571 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_zero_mips + rt,
2572 pc + 8))
2573 return false;
2575 return true;
2578 bool EmulateInstructionMIPS::Emulate_JIALC(llvm::MCInst &insn) {
2579 bool success = false;
2580 uint32_t rt;
2581 int32_t target, offset, pc, rt_val;
2584 * JIALC rt, offset
2585 * offset = sign_ext (offset)
2586 * PC = GPR[rt] + offset
2587 * RA = PC + 4
2589 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2590 offset = insn.getOperand(1).getImm();
2592 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2593 if (!success)
2594 return false;
2596 rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2597 dwarf_zero_mips + rt, 0, &success);
2598 if (!success)
2599 return false;
2601 target = rt_val + offset;
2603 Context context;
2605 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2606 target))
2607 return false;
2609 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2610 pc + 4))
2611 return false;
2613 return true;
2616 bool EmulateInstructionMIPS::Emulate_JIC(llvm::MCInst &insn) {
2617 bool success = false;
2618 uint32_t rt;
2619 int32_t target, offset, rt_val;
2622 * JIC rt, offset
2623 * offset = sign_ext (offset)
2624 * PC = GPR[rt] + offset
2626 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2627 offset = insn.getOperand(1).getImm();
2629 rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2630 dwarf_zero_mips + rt, 0, &success);
2631 if (!success)
2632 return false;
2634 target = rt_val + offset;
2636 Context context;
2638 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2639 target);
2642 bool EmulateInstructionMIPS::Emulate_JR(llvm::MCInst &insn) {
2643 bool success = false;
2644 uint32_t rs;
2645 uint32_t rs_val;
2648 * JR rs
2649 * PC = GPR[rs]
2651 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2653 rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + rs, 0,
2654 &success);
2655 if (!success)
2656 return false;
2658 Context context;
2660 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2661 rs_val);
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)
2669 bool 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(insn.getOpcode());
2675 cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2676 offset = insn.getOperand(1).getImm();
2678 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2679 if (!success)
2680 return false;
2682 fcsr = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);
2683 if (!success)
2684 return false;
2686 /* fcsr[23], fcsr[25-31] are vaild condition bits */
2687 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2689 if (op_name.equals_insensitive("BC1F") ||
2690 op_name.equals_insensitive("BC1FL")) {
2691 if ((fcsr & (1 << cc)) == 0)
2692 target = pc + offset;
2693 else
2694 target = pc + 8;
2695 } else if (op_name.equals_insensitive("BC1T") ||
2696 op_name.equals_insensitive("BC1TL")) {
2697 if ((fcsr & (1 << cc)) != 0)
2698 target = pc + offset;
2699 else
2700 target = pc + 8;
2702 Context context;
2704 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2705 target);
2708 bool 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;
2715 * BC1EQZ ft, offset
2716 * condition <- (FPR[ft].bit0 == 0)
2717 * if condition then
2718 * offset = sign_ext (offset)
2719 * PC = PC + 4 + offset
2721 ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2722 offset = insn.getOperand(1).getImm();
2724 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2725 if (!success)
2726 return false;
2728 ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + ft, 0,
2729 &success);
2730 if (!success)
2731 return false;
2733 if ((ft_val & 1) == 0)
2734 target = pc + 4 + offset;
2735 else
2736 target = pc + 8;
2738 Context context;
2740 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2741 target);
2744 bool 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;
2751 * BC1NEZ ft, offset
2752 * condition <- (FPR[ft].bit0 != 0)
2753 * if condition then
2754 * offset = sign_ext (offset)
2755 * PC = PC + 4 + offset
2757 ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2758 offset = insn.getOperand(1).getImm();
2760 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2761 if (!success)
2762 return false;
2764 ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + ft, 0,
2765 &success);
2766 if (!success)
2767 return false;
2769 if ((ft_val & 1) != 0)
2770 target = pc + 4 + offset;
2771 else
2772 target = pc + 8;
2774 Context context;
2776 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2777 target);
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
2787 bool 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(insn.getOpcode());
2793 cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2794 offset = insn.getOperand(1).getImm();
2796 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2797 if (!success)
2798 return false;
2800 fcsr = (uint32_t)ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips, 0,
2801 &success);
2802 if (!success)
2803 return false;
2805 /* fcsr[23], fcsr[25-31] are vaild condition bits */
2806 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2808 if (op_name.equals_insensitive("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("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("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("BC1ANY4T")) {
2827 /* if any one bit is 1 */
2828 if (((fcsr >> cc) & 0xf) != 0)
2829 target = pc + offset;
2830 else
2831 target = pc + 8;
2833 Context context;
2835 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2836 target);
2839 bool EmulateInstructionMIPS::Emulate_BNZB(llvm::MCInst &insn) {
2840 return Emulate_MSA_Branch_DF(insn, 1, true);
2843 bool EmulateInstructionMIPS::Emulate_BNZH(llvm::MCInst &insn) {
2844 return Emulate_MSA_Branch_DF(insn, 2, true);
2847 bool EmulateInstructionMIPS::Emulate_BNZW(llvm::MCInst &insn) {
2848 return Emulate_MSA_Branch_DF(insn, 4, true);
2851 bool EmulateInstructionMIPS::Emulate_BNZD(llvm::MCInst &insn) {
2852 return Emulate_MSA_Branch_DF(insn, 8, true);
2855 bool EmulateInstructionMIPS::Emulate_BZB(llvm::MCInst &insn) {
2856 return Emulate_MSA_Branch_DF(insn, 1, false);
2859 bool EmulateInstructionMIPS::Emulate_BZH(llvm::MCInst &insn) {
2860 return Emulate_MSA_Branch_DF(insn, 2, false);
2863 bool EmulateInstructionMIPS::Emulate_BZW(llvm::MCInst &insn) {
2864 return Emulate_MSA_Branch_DF(insn, 4, false);
2867 bool EmulateInstructionMIPS::Emulate_BZD(llvm::MCInst &insn) {
2868 return Emulate_MSA_Branch_DF(insn, 8, false);
2871 bool 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;
2879 uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2880 int32_t offset = insn.getOperand(1).getImm();
2882 int32_t pc =
2883 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2884 if (!success)
2885 return false;
2887 if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value))
2888 ptr = (const uint8_t *)reg_value.GetBytes();
2889 else
2890 return false;
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;
2914 if (!branch_hit)
2915 break;
2916 ptr = ptr + element_byte_size;
2919 if (branch_hit)
2920 target = pc + offset;
2921 else
2922 target = pc + 8;
2924 Context context;
2925 context.type = eContextRelativeBranchImmediate;
2927 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2928 target);
2931 bool EmulateInstructionMIPS::Emulate_BNZV(llvm::MCInst &insn) {
2932 return Emulate_MSA_Branch_V(insn, true);
2935 bool EmulateInstructionMIPS::Emulate_BZV(llvm::MCInst &insn) {
2936 return Emulate_MSA_Branch_V(insn, false);
2939 bool 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(128);
2944 llvm::APInt fail_value = llvm::APInt::getMaxValue(128);
2945 llvm::APInt zero_value = llvm::APInt::getZero(128);
2946 RegisterValue reg_value;
2948 uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2949 int32_t offset = insn.getOperand(1).getImm();
2951 int32_t pc =
2952 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2953 if (!success)
2954 return false;
2956 if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value))
2957 wr_val = reg_value.GetAsUInt128(fail_value);
2958 else
2959 return false;
2961 if ((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) ||
2962 (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz))
2963 target = pc + offset;
2964 else
2965 target = pc + 8;
2967 Context context;
2968 context.type = eContextRelativeBranchImmediate;
2970 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2971 target);
2974 bool 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;
2980 uint32_t num_operands = insn.getNumOperands();
2981 base =
2982 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
2983 imm = insn.getOperand(num_operands - 1).getImm();
2985 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))
2986 return false;
2988 /* read base register */
2989 address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2990 dwarf_zero_mips + base, 0, &success);
2991 if (!success)
2992 return false;
2994 /* destination address */
2995 address = address + imm;
2997 /* Set the bad_vaddr register with base address used in the instruction */
2998 bad_vaddr_context.type = eContextInvalid;
2999 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
3000 address);
3002 return true;
3005 bool 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;
3011 uint32_t num_operands = insn.getNumOperands();
3012 base =
3013 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
3014 index =
3015 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 1).getReg());
3017 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))
3018 return false;
3020 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + index))
3021 return false;
3023 /* read base register */
3024 address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
3025 dwarf_zero_mips + base, 0, &success);
3026 if (!success)
3027 return false;
3029 /* read index register */
3030 index_address = (int32_t)ReadRegisterUnsigned(
3031 eRegisterKindDWARF, dwarf_zero_mips + index, 0, &success);
3032 if (!success)
3033 return false;
3035 /* destination address */
3036 address = address + index_address;
3038 /* Set the bad_vaddr register with base address used in the instruction */
3039 bad_vaddr_context.type = eContextInvalid;
3040 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
3041 address);
3043 return true;