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
41 using namespace lldb;
42 using namespace lldb_private;
43
LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionMIPS,InstructionMIPS)44 LLDB_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__
54 extern "C" {
55 void LLVMInitializeMipsTargetInfo();
56 void LLVMInitializeMipsTarget();
57 void LLVMInitializeMipsAsmPrinter();
58 void LLVMInitializeMipsTargetMC();
59 void LLVMInitializeMipsDisassembler();
60 }
61 #endif
62
EmulateInstructionMIPS(const lldb_private::ArchSpec & arch)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);
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(target->createMCRegInfo(triple.getTriple()));
151 assert(m_reg_info.get());
152
153 m_insn_info.reset(target->createMCInstrInfo());
154 assert(m_insn_info.get());
155
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());
162
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());
166
167 m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *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 target->createMCSubtargetInfo(triple.getTriple(), cpu, features));
178 assert(m_alt_subtype_info.get());
179
180 m_alt_disasm.reset(
181 target->createMCDisassembler(*m_alt_subtype_info, *m_context));
182 assert(m_alt_disasm.get());
183
184 m_next_inst_size = 0;
185 m_use_alt_disaasm = false;
186 }
187
Initialize()188 void EmulateInstructionMIPS::Initialize() {
189 PluginManager::RegisterPlugin(GetPluginNameStatic(),
190 GetPluginDescriptionStatic(), CreateInstance);
191 }
192
Terminate()193 void EmulateInstructionMIPS::Terminate() {
194 PluginManager::UnregisterPlugin(CreateInstance);
195 }
196
GetPluginDescriptionStatic()197 llvm::StringRef EmulateInstructionMIPS::GetPluginDescriptionStatic() {
198 return "Emulate instructions for the MIPS32 architecture.";
199 }
200
201 EmulateInstruction *
CreateInstance(const ArchSpec & arch,InstructionType inst_type)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);
209 }
210 }
211
212 return nullptr;
213 }
214
SetTargetTriple(const ArchSpec & arch)215 bool EmulateInstructionMIPS::SetTargetTriple(const ArchSpec &arch) {
216 return arch.GetTriple().getArch() == llvm::Triple::mips ||
217 arch.GetTriple().getArch() == llvm::Triple::mipsel;
218 }
219
GetRegisterName(unsigned reg_num,bool alternate_name)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;
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
589 std::optional<RegisterInfo>
GetRegisterInfo(RegisterKind reg_kind,uint32_t reg_num)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 {};
616 }
617 }
618
619 if (reg_kind == eRegisterKindDWARF) {
620 RegisterInfo reg_info;
621 ::memset(®_info, 0, sizeof(RegisterInfo));
622 ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, 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, false);
645 reg_info.alt_name = GetRegisterName(reg_num, 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
672 EmulateInstructionMIPS::MipsOpcode *
GetOpcodeForInstruction(llvm::StringRef name)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"},
683
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"},
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 {"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)"},
774
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)"},
825
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)"},
843
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"},
935
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"},
957 };
958
959 for (MipsOpcode &opcode : g_opcodes) {
960 if (name.equals_insensitive(opcode.op_name))
961 return &opcode;
962 }
963 return nullptr;
964 }
965
966 uint32_t
GetSizeOfInstruction(lldb_private::DataExtractor & data,uint64_t inst_addr)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());
973
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());
980
981 if (decode_status != llvm::MCDisassembler::Success)
982 return false;
983
984 return m_insn_info->get(mc_insn.getOpcode()).getSize();
985 }
986
SetInstruction(const Opcode & insn_opcode,const Address & inst_addr,Target * target)987 bool 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(next_addr, /* Address of next instruction */
1010 buf, sizeof(uint32_t), error,
1011 false, /* force_live_memory */
1012 &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, 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
ReadInstruction()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());
1045 }
1046 if (!success)
1047 m_addr = LLDB_INVALID_ADDRESS;
1048 return success;
1049 }
1050
EvaluateInstruction(uint32_t evaluate_options)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;
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(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());
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(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(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(eRegisterKindDWARF, dwarf_pc_mips, 0, &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(eRegisterKindDWARF, dwarf_pc_mips, 0, &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, eRegisterKindDWARF, dwarf_pc_mips,
1118 new_pc))
1119 return false;
1120 }
1121 }
1122
1123 return true;
1124 }
1125
CreateFunctionEntryUnwind(UnwindPlan & unwind_plan)1126 bool 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(dwarf_sp_mips, 0);
1136
1137 // Our previous PC is in the RA
1138 row->SetRegisterLocationToRegister(dwarf_pc_mips, dwarf_ra_mips, can_replace);
1139
1140 unwind_plan.AppendRow(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
nonvolatile_reg_p(uint32_t regnum)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;
1169 }
1170 return false;
1171 }
1172
Emulate_ADDiu(llvm::MCInst & insn)1173 bool 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(2).getImm();
1180 int64_t imm = SignedBits(imm16, 15, 0);
1181
1182 dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1183 src = m_reg_info->getEncodingValue(insn.getOperand(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 eRegisterKindDWARF, dwarf_zero_mips + src, 0, &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(eRegisterKindDWARF, dwarf_sp_mips);
1203 if (reg_info_sp)
1204 context.SetRegisterPlusOffset(*reg_info_sp, imm);
1205
1206 /* We are allocating bytes on stack */
1207 context.type = eContextAdjustStackPointer;
1208
1209 WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);
1210 return true;
1211 }
1212
1213 imm += src_opd_val;
1214 context.SetImmediateSigned(imm);
1215 context.type = eContextImmediate;
1216
1217 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1218 dwarf_zero_mips + dst, imm))
1219 return false;
1220 }
1221
1222 return true;
1223 }
1224
Emulate_SW(llvm::MCInst & insn)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;
1232
1233 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1234 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1235
1236 std::optional<RegisterInfo> reg_info_base =
1237 GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base);
1238 if (!reg_info_base)
1239 return false;
1240
1241 /* read base register */
1242 address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1243 dwarf_zero_mips + base, 0, &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(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
1253 address);
1254
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;
1261
1262 Context context;
1263 context.type = eContextPushRegisterOnStack;
1264 context.SetRegisterToRegisterPlusOffset(*reg_info_src, *reg_info_base, 0);
1265
1266 uint8_t buffer[RegisterValue::kMaxRegisterByteSize];
1267 Status error;
1268
1269 std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);
1270 if (!data_src)
1271 return false;
1272
1273 if (data_src->GetAsMemoryData(*reg_info_src, buffer,
1274 reg_info_src->byte_size, eByteOrderLittle,
1275 error) == 0)
1276 return false;
1277
1278 if (!WriteMemory(context, address, buffer, reg_info_src->byte_size))
1279 return false;
1280
1281 return true;
1282 }
1283
1284 return false;
1285 }
1286
Emulate_LW(llvm::MCInst & insn)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;
1292
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();
1296
1297 if (GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))
1298 return false;
1299
1300 /* read base register */
1301 address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1302 dwarf_zero_mips + base, 0, &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(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
1312 address);
1313
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;
1320
1321 Context context;
1322 context.type = eContextPopRegisterOffStack;
1323 context.SetAddress(address);
1324
1325 return WriteRegister(context, *reg_info_src, data_src);
1326 }
1327
1328 return false;
1329 }
1330
Emulate_SUBU_ADDU(llvm::MCInst & insn)1331 bool 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(insn.getOpcode());
1340
1341 dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1342 src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1343
1344 /* Check if sp is destination register */
1345 if (dst == dwarf_sp_mips) {
1346 rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1347
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;
1353
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;
1359
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;
1364
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);
1370
1371 /* We are allocating bytes on stack */
1372 context.type = eContextAdjustStackPointer;
1373
1374 WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);
1375
1376 return true;
1377 } else if (src == dwarf_sp_mips) {
1378 rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1379
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;
1385
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;
1391
1392 Context context;
1393
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;
1398
1399 context.SetImmediateSigned(result);
1400 context.type = eContextImmediate;
1401
1402 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1403 dwarf_zero_mips + dst, result))
1404 return false;
1405 }
1406
1407 return true;
1408 }
1409
Emulate_LUI(llvm::MCInst & insn)1410 bool 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(1).getImm() << 16;
1415 int64_t imm = SignedBits(imm32, 31, 0);
1416 uint8_t rt;
1417 Context context;
1418
1419 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1420 context.SetImmediateSigned(imm);
1421 context.type = eContextImmediate;
1422
1423 return WriteRegisterUnsigned(context, eRegisterKindDWARF,
1424 dwarf_zero_mips + rt, imm);
1425 }
1426
Emulate_ADDIUSP(llvm::MCInst & insn)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;
1431
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;
1438
1439 result = src_opd_val + imm9;
1440
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);
1446
1447 // We are adjusting the stack.
1448 context.type = eContextAdjustStackPointer;
1449
1450 WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);
1451 return true;
1452 }
1453
Emulate_ADDIUS5(llvm::MCInst & insn)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;
1459
1460 // The source and destination register is same for this instruction.
1461 base = m_reg_info->getEncodingValue(insn.getOperand(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 eRegisterKindDWARF, dwarf_zero_mips + base, 0, &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(eRegisterKindDWARF, dwarf_sp_mips);
1476 if (reg_info_sp)
1477 context.SetRegisterPlusOffset(*reg_info_sp, imm4);
1478
1479 // We are adjusting the stack.
1480 context.type = eContextAdjustStackPointer;
1481
1482 WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);
1483 }
1484
1485 return true;
1486 }
1487
Emulate_SWSP(llvm::MCInst & insn)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;
1494
1495 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1496 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1497
1498 std::optional<RegisterInfo> reg_info_base =
1499 GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base);
1500 if (!reg_info_base)
1501 return false;
1502
1503 // read base register
1504 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0,
1505 &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(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
1517 address);
1518
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);
1525
1526 uint8_t buffer[RegisterValue::kMaxRegisterByteSize];
1527 Status error;
1528
1529 std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);
1530 if (!data_src)
1531 return false;
1532
1533 if (data_src->GetAsMemoryData(reg_info_src, buffer, reg_info_src.byte_size,
1534 eByteOrderLittle, error) == 0)
1535 return false;
1536
1537 if (!WriteMemory(context, address, buffer, reg_info_src.byte_size))
1538 return false;
1539
1540 return true;
1541 }
1542
1543 return false;
1544 }
1545
1546 /* Emulate SWM16,SWM32 and SWP instruction.
1547
1548 SWM16 always has stack pointer as a base register (but it is still available
1549 in MCInst as an operand).
1550 SWM32 and SWP can have base register other than stack pointer.
1551 */
Emulate_SWM16_32(llvm::MCInst & insn)1552 bool EmulateInstructionMIPS::Emulate_SWM16_32(llvm::MCInst &insn) {
1553 bool success = false;
1554 uint32_t src, base;
1555 uint32_t num_operands = insn.getNumOperands(); // No of operands vary based on
1556 // no of regs to store.
1557
1558 // Base register is second last operand of the instruction.
1559 base =
1560 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
1561
1562 // We are looking for sp based stores so if base is not a stack pointer then
1563 // don't proceed.
1564 if (base != dwarf_sp_mips)
1565 return false;
1566
1567 // offset is always the last operand.
1568 uint32_t offset = insn.getOperand(num_operands - 1).getImm();
1569
1570 std::optional<RegisterInfo> reg_info_base =
1571 GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base);
1572 if (!reg_info_base)
1573 return false;
1574
1575 // read SP
1576 uint32_t base_address = ReadRegisterUnsigned(
1577 eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
1578 if (!success)
1579 return false;
1580
1581 // Resulting base addrss
1582 base_address = base_address + offset;
1583
1584 // Total no of registers to be stored are num_operands-2.
1585 for (uint32_t i = 0; i < num_operands - 2; i++) {
1586 // Get the register number to be stored.
1587 src = m_reg_info->getEncodingValue(insn.getOperand(i).getReg());
1588
1589 /*
1590 Record only non-volatile stores.
1591 This check is required for SWP instruction because source operand could
1592 be any register.
1593 SWM16 and SWM32 instruction always has saved registers as source
1594 operands.
1595 */
1596 if (!nonvolatile_reg_p(src))
1597 return false;
1598
1599 std::optional<RegisterInfo> reg_info_src =
1600 GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src);
1601 if (!reg_info_src)
1602 return false;
1603
1604 Context context;
1605 context.type = eContextPushRegisterOnStack;
1606 context.SetRegisterToRegisterPlusOffset(*reg_info_src, *reg_info_base, 0);
1607
1608 uint8_t buffer[RegisterValue::kMaxRegisterByteSize];
1609 Status error;
1610
1611 std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);
1612 if (!data_src)
1613 return false;
1614
1615 if (data_src->GetAsMemoryData(*reg_info_src, buffer,
1616 reg_info_src->byte_size, eByteOrderLittle,
1617 error) == 0)
1618 return false;
1619
1620 if (!WriteMemory(context, base_address, buffer, reg_info_src->byte_size))
1621 return false;
1622
1623 // Stack address for next register
1624 base_address = base_address + reg_info_src->byte_size;
1625 }
1626 return true;
1627 }
1628
Emulate_LWSP(llvm::MCInst & insn)1629 bool EmulateInstructionMIPS::Emulate_LWSP(llvm::MCInst &insn) {
1630 bool success = false;
1631 uint32_t src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1632 uint32_t base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1633 uint32_t imm5 = insn.getOperand(2).getImm();
1634 Context bad_vaddr_context;
1635
1636 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))
1637 return false;
1638
1639 // read base register
1640 uint32_t base_address = ReadRegisterUnsigned(
1641 eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
1642 if (!success)
1643 return false;
1644
1645 base_address = base_address + imm5;
1646
1647 // We use bad_vaddr_context to store base address which is used by H/W
1648 // watchpoint Set the bad_vaddr register with base address used in the
1649 // instruction
1650 bad_vaddr_context.type = eContextInvalid;
1651 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
1652 base_address);
1653
1654 if (base == dwarf_sp_mips && nonvolatile_reg_p(src)) {
1655 RegisterValue data_src;
1656 std::optional<RegisterInfo> reg_info_src =
1657 GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src);
1658 if (!reg_info_src)
1659 return false;
1660
1661 Context context;
1662 context.type = eContextPopRegisterOffStack;
1663 context.SetAddress(base_address);
1664
1665 return WriteRegister(context, *reg_info_src, data_src);
1666 }
1667
1668 return false;
1669 }
1670
1671 /* Emulate LWM16, LWM32 and LWP instructions.
1672
1673 LWM16 always has stack pointer as a base register (but it is still available
1674 in MCInst as an operand).
1675 LWM32 and LWP can have base register other than stack pointer.
1676 */
Emulate_LWM16_32(llvm::MCInst & insn)1677 bool EmulateInstructionMIPS::Emulate_LWM16_32(llvm::MCInst &insn) {
1678 bool success = false;
1679 uint32_t dst, base;
1680 uint32_t num_operands = insn.getNumOperands(); // No of operands vary based on
1681 // no of regs to store.
1682 uint32_t imm = insn.getOperand(num_operands - 1)
1683 .getImm(); // imm is the last operand in the instruction.
1684
1685 // Base register is second last operand of the instruction.
1686 base =
1687 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
1688
1689 // We are looking for sp based loads so if base is not a stack pointer then
1690 // don't proceed.
1691 if (base != dwarf_sp_mips)
1692 return false;
1693
1694 uint32_t base_address = ReadRegisterUnsigned(
1695 eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
1696 if (!success)
1697 return false;
1698
1699 base_address = base_address + imm;
1700
1701 RegisterValue data_dst;
1702
1703 // Total no of registers to be re-stored are num_operands-2.
1704 for (uint32_t i = 0; i < num_operands - 2; i++) {
1705 // Get the register number to be re-stored.
1706 dst = m_reg_info->getEncodingValue(insn.getOperand(i).getReg());
1707
1708 /*
1709 Record only non-volatile loads.
1710 This check is required for LWP instruction because destination operand
1711 could be any register.
1712 LWM16 and LWM32 instruction always has saved registers as destination
1713 operands.
1714 */
1715 if (!nonvolatile_reg_p(dst))
1716 return false;
1717
1718 std::optional<RegisterInfo> reg_info_dst =
1719 GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + dst);
1720 if (!reg_info_dst)
1721 return false;
1722
1723 Context context;
1724 context.type = eContextPopRegisterOffStack;
1725 context.SetAddress(base_address + (i * 4));
1726
1727 if (!WriteRegister(context, *reg_info_dst, data_dst))
1728 return false;
1729 }
1730
1731 return true;
1732 }
1733
Emulate_JRADDIUSP(llvm::MCInst & insn)1734 bool EmulateInstructionMIPS::Emulate_JRADDIUSP(llvm::MCInst &insn) {
1735 bool success = false;
1736 int32_t imm5 = insn.getOperand(0).getImm();
1737
1738 /* JRADDIUSP immediate
1739 * PC <- RA
1740 * SP <- SP + zero_extend(Immediate << 2)
1741 */
1742
1743 // This instruction operates implicitly on stack pointer, so read <sp>
1744 // register.
1745 int32_t src_opd_val =
1746 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_sp_mips, 0, &success);
1747 if (!success)
1748 return false;
1749
1750 int32_t ra_val =
1751 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_ra_mips, 0, &success);
1752 if (!success)
1753 return false;
1754
1755 int32_t result = src_opd_val + imm5;
1756
1757 Context context;
1758
1759 // Update the PC
1760 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
1761 ra_val))
1762 return false;
1763
1764 std::optional<RegisterInfo> reg_info_sp =
1765 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);
1766 if (reg_info_sp)
1767 context.SetRegisterPlusOffset(*reg_info_sp, imm5);
1768
1769 // We are adjusting stack
1770 context.type = eContextAdjustStackPointer;
1771
1772 // update SP
1773 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips,
1774 result);
1775 }
1776
IsAdd64bitOverflow(int32_t a,int32_t b)1777 static int IsAdd64bitOverflow(int32_t a, int32_t b) {
1778 int32_t r = (uint32_t)a + (uint32_t)b;
1779 return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
1780 }
1781
1782 /*
1783 Emulate below MIPS branch instructions.
1784 BEQ, BNE : Branch on condition
1785 BEQL, BNEL : Branch likely
1786 */
Emulate_BXX_3ops(llvm::MCInst & insn)1787 bool EmulateInstructionMIPS::Emulate_BXX_3ops(llvm::MCInst &insn) {
1788 bool success = false;
1789 uint32_t rs, rt;
1790 int32_t offset, pc, target = 0, rs_val, rt_val;
1791 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1792
1793 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1794 rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1795 offset = insn.getOperand(2).getImm();
1796
1797 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
1798 if (!success)
1799 return false;
1800
1801 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1802 dwarf_zero_mips + rs, 0, &success);
1803 if (!success)
1804 return false;
1805
1806 rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1807 dwarf_zero_mips + rt, 0, &success);
1808 if (!success)
1809 return false;
1810
1811 if (op_name.equals_insensitive("BEQ") || op_name.equals_insensitive("BEQL")) {
1812 if (rs_val == rt_val)
1813 target = pc + offset;
1814 else
1815 target = pc + 8;
1816 } else if (op_name.equals_insensitive("BNE") ||
1817 op_name.equals_insensitive("BNEL")) {
1818 if (rs_val != rt_val)
1819 target = pc + offset;
1820 else
1821 target = pc + 8;
1822 }
1823
1824 Context context;
1825 context.type = eContextRelativeBranchImmediate;
1826 context.SetImmediate(offset);
1827
1828 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
1829 target);
1830 }
1831
1832 /*
1833 Emulate below MIPS branch instructions.
1834 BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch
1835 instructions with no delay slot
1836 */
Emulate_BXX_3ops_C(llvm::MCInst & insn)1837 bool EmulateInstructionMIPS::Emulate_BXX_3ops_C(llvm::MCInst &insn) {
1838 bool success = false;
1839 uint32_t rs, rt;
1840 int32_t offset, pc, target = 0, rs_val, rt_val;
1841 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1842 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
1843
1844 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1845 rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1846 offset = insn.getOperand(2).getImm();
1847
1848 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
1849 if (!success)
1850 return false;
1851
1852 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1853 dwarf_zero_mips + rs, 0, &success);
1854 if (!success)
1855 return false;
1856
1857 rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1858 dwarf_zero_mips + rt, 0, &success);
1859 if (!success)
1860 return false;
1861
1862 if (op_name.equals_insensitive("BEQC")) {
1863 if (rs_val == rt_val)
1864 target = pc + offset;
1865 else
1866 target = pc + 4;
1867 } else if (op_name.equals_insensitive("BNEC")) {
1868 if (rs_val != rt_val)
1869 target = pc + offset;
1870 else
1871 target = pc + 4;
1872 } else if (op_name.equals_insensitive("BLTC")) {
1873 if (rs_val < rt_val)
1874 target = pc + offset;
1875 else
1876 target = pc + 4;
1877 } else if (op_name.equals_insensitive("BGEC")) {
1878 if (rs_val >= rt_val)
1879 target = pc + offset;
1880 else
1881 target = pc + 4;
1882 } else if (op_name.equals_insensitive("BLTUC")) {
1883 if (rs_val < rt_val)
1884 target = pc + offset;
1885 else
1886 target = pc + 4;
1887 } else if (op_name.equals_insensitive("BGEUC")) {
1888 if ((uint32_t)rs_val >= (uint32_t)rt_val)
1889 target = pc + offset;
1890 else
1891 target = pc + 4;
1892 } else if (op_name.equals_insensitive("BOVC")) {
1893 if (IsAdd64bitOverflow(rs_val, rt_val))
1894 target = pc + offset;
1895 else
1896 target = pc + 4;
1897 } else if (op_name.equals_insensitive("BNVC")) {
1898 if (!IsAdd64bitOverflow(rs_val, rt_val))
1899 target = pc + offset;
1900 else
1901 target = pc + 4;
1902 }
1903
1904 Context context;
1905 context.type = eContextRelativeBranchImmediate;
1906 context.SetImmediate(current_inst_size + offset);
1907
1908 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
1909 target);
1910 }
1911
1912 /*
1913 Emulate below MIPS conditional branch and link instructions.
1914 BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches
1915 */
Emulate_Bcond_Link_C(llvm::MCInst & insn)1916 bool EmulateInstructionMIPS::Emulate_Bcond_Link_C(llvm::MCInst &insn) {
1917 bool success = false;
1918 uint32_t rs;
1919 int32_t offset, pc, target = 0;
1920 int32_t rs_val;
1921 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1922
1923 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1924 offset = insn.getOperand(1).getImm();
1925
1926 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
1927 if (!success)
1928 return false;
1929
1930 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1931 dwarf_zero_mips + rs, 0, &success);
1932 if (!success)
1933 return false;
1934
1935 if (op_name.equals_insensitive("BLEZALC")) {
1936 if (rs_val <= 0)
1937 target = pc + offset;
1938 else
1939 target = pc + 4;
1940 } else if (op_name.equals_insensitive("BGEZALC")) {
1941 if (rs_val >= 0)
1942 target = pc + offset;
1943 else
1944 target = pc + 4;
1945 } else if (op_name.equals_insensitive("BLTZALC")) {
1946 if (rs_val < 0)
1947 target = pc + offset;
1948 else
1949 target = pc + 4;
1950 } else if (op_name.equals_insensitive("BGTZALC")) {
1951 if (rs_val > 0)
1952 target = pc + offset;
1953 else
1954 target = pc + 4;
1955 } else if (op_name.equals_insensitive("BEQZALC")) {
1956 if (rs_val == 0)
1957 target = pc + offset;
1958 else
1959 target = pc + 4;
1960 } else if (op_name.equals_insensitive("BNEZALC")) {
1961 if (rs_val != 0)
1962 target = pc + offset;
1963 else
1964 target = pc + 4;
1965 }
1966
1967 Context context;
1968
1969 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
1970 target))
1971 return false;
1972
1973 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
1974 pc + 4))
1975 return false;
1976
1977 return true;
1978 }
1979
1980 /*
1981 Emulate below MIPS Non-Compact conditional branch and link instructions.
1982 BLTZAL, BGEZAL :
1983 BLTZALL, BGEZALL : Branch likely
1984 */
Emulate_Bcond_Link(llvm::MCInst & insn)1985 bool EmulateInstructionMIPS::Emulate_Bcond_Link(llvm::MCInst &insn) {
1986 bool success = false;
1987 uint32_t rs;
1988 int32_t offset, pc, target = 0;
1989 int32_t rs_val;
1990 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1991
1992 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1993 offset = insn.getOperand(1).getImm();
1994
1995 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
1996 if (!success)
1997 return false;
1998
1999 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2000 dwarf_zero_mips + rs, 0, &success);
2001 if (!success)
2002 return false;
2003
2004 if (op_name.equals_insensitive("BLTZAL") ||
2005 op_name.equals_insensitive("BLTZALL")) {
2006 if ((int32_t)rs_val < 0)
2007 target = pc + offset;
2008 else
2009 target = pc + 8;
2010 } else if (op_name.equals_insensitive("BGEZAL") ||
2011 op_name.equals_insensitive("BGEZALL")) {
2012 if ((int32_t)rs_val >= 0)
2013 target = pc + offset;
2014 else
2015 target = pc + 8;
2016 }
2017
2018 Context context;
2019
2020 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2021 target))
2022 return false;
2023
2024 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2025 pc + 8))
2026 return false;
2027
2028 return true;
2029 }
2030
2031 /*
2032 Emulate below MIPS branch instructions.
2033 BLTZL, BGEZL, BGTZL, BLEZL : Branch likely
2034 BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches
2035 */
Emulate_BXX_2ops(llvm::MCInst & insn)2036 bool EmulateInstructionMIPS::Emulate_BXX_2ops(llvm::MCInst &insn) {
2037 bool success = false;
2038 uint32_t rs;
2039 int32_t offset, pc, target = 0;
2040 int32_t rs_val;
2041 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2042
2043 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2044 offset = insn.getOperand(1).getImm();
2045
2046 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2047 if (!success)
2048 return false;
2049
2050 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2051 dwarf_zero_mips + rs, 0, &success);
2052 if (!success)
2053 return false;
2054
2055 if (op_name.equals_insensitive("BLTZL") ||
2056 op_name.equals_insensitive("BLTZ")) {
2057 if (rs_val < 0)
2058 target = pc + offset;
2059 else
2060 target = pc + 8;
2061 } else if (op_name.equals_insensitive("BGEZL") ||
2062 op_name.equals_insensitive("BGEZ")) {
2063 if (rs_val >= 0)
2064 target = pc + offset;
2065 else
2066 target = pc + 8;
2067 } else if (op_name.equals_insensitive("BGTZL") ||
2068 op_name.equals_insensitive("BGTZ")) {
2069 if (rs_val > 0)
2070 target = pc + offset;
2071 else
2072 target = pc + 8;
2073 } else if (op_name.equals_insensitive("BLEZL") ||
2074 op_name.equals_insensitive("BLEZ")) {
2075 if (rs_val <= 0)
2076 target = pc + offset;
2077 else
2078 target = pc + 8;
2079 }
2080
2081 Context context;
2082 context.type = eContextRelativeBranchImmediate;
2083 context.SetImmediate(offset);
2084
2085 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2086 target);
2087 }
2088
2089 /*
2090 Emulate below MIPS branch instructions.
2091 BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches
2092 */
Emulate_BXX_2ops_C(llvm::MCInst & insn)2093 bool EmulateInstructionMIPS::Emulate_BXX_2ops_C(llvm::MCInst &insn) {
2094 bool success = false;
2095 uint32_t rs;
2096 int32_t offset, pc, target = 0;
2097 int32_t rs_val;
2098 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2099 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
2100
2101 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2102 offset = insn.getOperand(1).getImm();
2103
2104 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2105 if (!success)
2106 return false;
2107
2108 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2109 dwarf_zero_mips + rs, 0, &success);
2110 if (!success)
2111 return false;
2112
2113 if (op_name.equals_insensitive("BLTZC")) {
2114 if (rs_val < 0)
2115 target = pc + offset;
2116 else
2117 target = pc + 4;
2118 } else if (op_name.equals_insensitive("BLEZC")) {
2119 if (rs_val <= 0)
2120 target = pc + offset;
2121 else
2122 target = pc + 4;
2123 } else if (op_name.equals_insensitive("BGEZC")) {
2124 if (rs_val >= 0)
2125 target = pc + offset;
2126 else
2127 target = pc + 4;
2128 } else if (op_name.equals_insensitive("BGTZC")) {
2129 if (rs_val > 0)
2130 target = pc + offset;
2131 else
2132 target = pc + 4;
2133 } else if (op_name.equals_insensitive("BEQZC")) {
2134 if (rs_val == 0)
2135 target = pc + offset;
2136 else
2137 target = pc + 4;
2138 } else if (op_name.equals_insensitive("BNEZC")) {
2139 if (rs_val != 0)
2140 target = pc + offset;
2141 else
2142 target = pc + 4;
2143 }
2144
2145 Context context;
2146 context.type = eContextRelativeBranchImmediate;
2147 context.SetImmediate(current_inst_size + offset);
2148
2149 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2150 target);
2151 }
2152
Emulate_B16_MM(llvm::MCInst & insn)2153 bool EmulateInstructionMIPS::Emulate_B16_MM(llvm::MCInst &insn) {
2154 bool success = false;
2155 int32_t offset, pc, target;
2156 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
2157
2158 offset = insn.getOperand(0).getImm();
2159
2160 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2161 if (!success)
2162 return false;
2163
2164 // unconditional branch
2165 target = pc + offset;
2166
2167 Context context;
2168 context.type = eContextRelativeBranchImmediate;
2169 context.SetImmediate(current_inst_size + offset);
2170
2171 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2172 target);
2173 }
2174
2175 /*
2176 BEQZC, BNEZC are 32 bit compact instructions without a delay slot.
2177 BEQZ16, BNEZ16 are 16 bit instructions with delay slot.
2178 BGEZALS, BLTZALS are 16 bit instructions with short (2-byte) delay slot.
2179 */
Emulate_Branch_MM(llvm::MCInst & insn)2180 bool EmulateInstructionMIPS::Emulate_Branch_MM(llvm::MCInst &insn) {
2181 bool success = false;
2182 int32_t target = 0;
2183 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
2184 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2185 bool update_ra = false;
2186 uint32_t ra_offset = 0;
2187
2188 /*
2189 * BEQZ16 rs, offset
2190 * condition <- (GPR[rs] = 0)
2191 * if condition then
2192 * PC = PC + sign_ext (offset || 0)
2193 *
2194 * BNEZ16 rs, offset
2195 * condition <- (GPR[rs] != 0)
2196 * if condition then
2197 * PC = PC + sign_ext (offset || 0)
2198 *
2199 * BEQZC rs, offset (compact instruction: No delay slot)
2200 * condition <- (GPR[rs] == 0)
2201 * if condition then
2202 * PC = PC + 4 + sign_ext (offset || 0)
2203 */
2204
2205 uint32_t rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2206 int32_t offset = insn.getOperand(1).getImm();
2207
2208 int32_t pc =
2209 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2210 if (!success)
2211 return false;
2212
2213 int32_t rs_val = (int32_t)ReadRegisterUnsigned(
2214 eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
2215 if (!success)
2216 return false;
2217
2218 if (op_name.equals_insensitive("BEQZ16_MM")) {
2219 if (rs_val == 0)
2220 target = pc + offset;
2221 else
2222 target = pc + current_inst_size +
2223 m_next_inst_size; // Skip delay slot instruction.
2224 } else if (op_name.equals_insensitive("BNEZ16_MM")) {
2225 if (rs_val != 0)
2226 target = pc + offset;
2227 else
2228 target = pc + current_inst_size +
2229 m_next_inst_size; // Skip delay slot instruction.
2230 } else if (op_name.equals_insensitive("BEQZC_MM")) {
2231 if (rs_val == 0)
2232 target = pc + 4 + offset;
2233 else
2234 target =
2235 pc +
2236 4; // 32 bit instruction and does not have delay slot instruction.
2237 } else if (op_name.equals_insensitive("BNEZC_MM")) {
2238 if (rs_val != 0)
2239 target = pc + 4 + offset;
2240 else
2241 target =
2242 pc +
2243 4; // 32 bit instruction and does not have delay slot instruction.
2244 } else if (op_name.equals_insensitive("BGEZALS_MM")) {
2245 if (rs_val >= 0)
2246 target = pc + offset;
2247 else
2248 target = pc + 6; // 32 bit instruction with short (2-byte) delay slot
2249
2250 update_ra = true;
2251 ra_offset = 6;
2252 } else if (op_name.equals_insensitive("BLTZALS_MM")) {
2253 if (rs_val >= 0)
2254 target = pc + offset;
2255 else
2256 target = pc + 6; // 32 bit instruction with short (2-byte) delay slot
2257
2258 update_ra = true;
2259 ra_offset = 6;
2260 }
2261
2262 Context context;
2263 context.type = eContextRelativeBranchImmediate;
2264 context.SetImmediate(current_inst_size + offset);
2265
2266 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2267 target))
2268 return false;
2269
2270 if (update_ra) {
2271 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2272 pc + ra_offset))
2273 return false;
2274 }
2275 return true;
2276 }
2277
2278 /* Emulate micromips jump instructions.
2279 JALR16,JALRS16
2280 */
Emulate_JALRx16_MM(llvm::MCInst & insn)2281 bool EmulateInstructionMIPS::Emulate_JALRx16_MM(llvm::MCInst &insn) {
2282 bool success = false;
2283 uint32_t ra_offset = 0;
2284 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2285
2286 uint32_t rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2287
2288 uint32_t pc =
2289 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2290 if (!success)
2291 return false;
2292
2293 uint32_t rs_val = ReadRegisterUnsigned(eRegisterKindDWARF,
2294 dwarf_zero_mips + rs, 0, &success);
2295 if (!success)
2296 return false;
2297
2298 if (op_name.equals_insensitive("JALR16_MM"))
2299 ra_offset = 6; // 2-byte instruction with 4-byte delay slot.
2300 else if (op_name.equals_insensitive("JALRS16_MM"))
2301 ra_offset = 4; // 2-byte instruction with 2-byte delay slot.
2302
2303 Context context;
2304
2305 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2306 rs_val))
2307 return false;
2308
2309 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2310 pc + ra_offset))
2311 return false;
2312
2313 return true;
2314 }
2315
2316 /* Emulate JALS and JALX instructions.
2317 JALS 32 bit instruction with short (2-byte) delay slot.
2318 JALX 32 bit instruction with 4-byte delay slot.
2319 */
Emulate_JALx(llvm::MCInst & insn)2320 bool EmulateInstructionMIPS::Emulate_JALx(llvm::MCInst &insn) {
2321 bool success = false;
2322 uint32_t offset = 0, target = 0, pc = 0, ra_offset = 0;
2323 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2324
2325 /*
2326 * JALS target
2327 * RA = PC + 6
2328 * offset = sign_ext (offset << 1)
2329 * PC = PC[31-27] | offset
2330 * JALX target
2331 * RA = PC + 8
2332 * offset = sign_ext (offset << 2)
2333 * PC = PC[31-28] | offset
2334 */
2335 offset = insn.getOperand(0).getImm();
2336
2337 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2338 if (!success)
2339 return false;
2340
2341 // These are PC-region branches and not PC-relative.
2342 if (op_name.equals_insensitive("JALS_MM")) {
2343 // target address is in the “current” 128 MB-aligned region
2344 target = (pc & 0xF8000000UL) | offset;
2345 ra_offset = 6;
2346 } else if (op_name.equals_insensitive("JALX_MM")) {
2347 // target address is in the “current” 256 MB-aligned region
2348 target = (pc & 0xF0000000UL) | offset;
2349 ra_offset = 8;
2350 }
2351
2352 Context context;
2353
2354 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2355 target))
2356 return false;
2357
2358 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2359 pc + ra_offset))
2360 return false;
2361
2362 return true;
2363 }
2364
Emulate_JALRS(llvm::MCInst & insn)2365 bool EmulateInstructionMIPS::Emulate_JALRS(llvm::MCInst &insn) {
2366 bool success = false;
2367 uint32_t rs = 0, rt = 0;
2368 int32_t pc = 0, rs_val = 0;
2369
2370 /*
2371 JALRS rt, rs
2372 GPR[rt] <- PC + 6
2373 PC <- GPR[rs]
2374 */
2375
2376 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2377 rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
2378
2379 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2380 dwarf_zero_mips + rs, 0, &success);
2381 if (!success)
2382 return false;
2383
2384 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2385 if (!success)
2386 return false;
2387
2388 Context context;
2389
2390 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2391 rs_val))
2392 return false;
2393
2394 // This is 4-byte instruction with 2-byte delay slot.
2395 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_zero_mips + rt,
2396 pc + 6))
2397 return false;
2398
2399 return true;
2400 }
2401
Emulate_BAL(llvm::MCInst & insn)2402 bool EmulateInstructionMIPS::Emulate_BAL(llvm::MCInst &insn) {
2403 bool success = false;
2404 int32_t offset, pc, target;
2405
2406 /*
2407 * BAL offset
2408 * offset = sign_ext (offset << 2)
2409 * RA = PC + 8
2410 * PC = PC + offset
2411 */
2412 offset = insn.getOperand(0).getImm();
2413
2414 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2415 if (!success)
2416 return false;
2417
2418 target = pc + offset;
2419
2420 Context context;
2421
2422 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2423 target))
2424 return false;
2425
2426 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2427 pc + 8))
2428 return false;
2429
2430 return true;
2431 }
2432
Emulate_BALC(llvm::MCInst & insn)2433 bool EmulateInstructionMIPS::Emulate_BALC(llvm::MCInst &insn) {
2434 bool success = false;
2435 int32_t offset, pc, target;
2436
2437 /*
2438 * BALC offset
2439 * offset = sign_ext (offset << 2)
2440 * RA = PC + 4
2441 * PC = PC + 4 + offset
2442 */
2443 offset = insn.getOperand(0).getImm();
2444
2445 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2446 if (!success)
2447 return false;
2448
2449 target = pc + offset;
2450
2451 Context context;
2452
2453 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2454 target))
2455 return false;
2456
2457 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2458 pc + 4))
2459 return false;
2460
2461 return true;
2462 }
2463
Emulate_BC(llvm::MCInst & insn)2464 bool EmulateInstructionMIPS::Emulate_BC(llvm::MCInst &insn) {
2465 bool success = false;
2466 int32_t offset, pc, target;
2467
2468 /*
2469 * BC offset
2470 * offset = sign_ext (offset << 2)
2471 * PC = PC + 4 + offset
2472 */
2473 offset = insn.getOperand(0).getImm();
2474
2475 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2476 if (!success)
2477 return false;
2478
2479 target = pc + offset;
2480
2481 Context context;
2482
2483 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2484 target);
2485 }
2486
Emulate_J(llvm::MCInst & insn)2487 bool EmulateInstructionMIPS::Emulate_J(llvm::MCInst &insn) {
2488 bool success = false;
2489 uint32_t offset, pc;
2490
2491 /*
2492 * J offset
2493 * offset = sign_ext (offset << 2)
2494 * PC = PC[63-28] | offset
2495 */
2496 offset = insn.getOperand(0).getImm();
2497
2498 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2499 if (!success)
2500 return false;
2501
2502 /* This is a PC-region branch and not PC-relative */
2503 pc = (pc & 0xF0000000UL) | offset;
2504
2505 Context context;
2506
2507 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, pc);
2508 }
2509
Emulate_JAL(llvm::MCInst & insn)2510 bool EmulateInstructionMIPS::Emulate_JAL(llvm::MCInst &insn) {
2511 bool success = false;
2512 uint32_t offset, target, pc;
2513
2514 /*
2515 * JAL offset
2516 * offset = sign_ext (offset << 2)
2517 * PC = PC[63-28] | offset
2518 */
2519 offset = insn.getOperand(0).getImm();
2520
2521 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2522 if (!success)
2523 return false;
2524
2525 /* This is a PC-region branch and not PC-relative */
2526 target = (pc & 0xF0000000UL) | offset;
2527
2528 Context context;
2529
2530 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2531 target))
2532 return false;
2533
2534 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2535 pc + 8))
2536 return false;
2537
2538 return true;
2539 }
2540
Emulate_JALR(llvm::MCInst & insn)2541 bool EmulateInstructionMIPS::Emulate_JALR(llvm::MCInst &insn) {
2542 bool success = false;
2543 uint32_t rs, rt;
2544 uint32_t pc, rs_val;
2545
2546 /*
2547 * JALR rt, rs
2548 * GPR[rt] = PC + 8
2549 * PC = GPR[rs]
2550 */
2551 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2552 rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
2553
2554 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2555 if (!success)
2556 return false;
2557
2558 rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + rs, 0,
2559 &success);
2560 if (!success)
2561 return false;
2562
2563 Context context;
2564
2565 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2566 rs_val))
2567 return false;
2568
2569 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_zero_mips + rt,
2570 pc + 8))
2571 return false;
2572
2573 return true;
2574 }
2575
Emulate_JIALC(llvm::MCInst & insn)2576 bool EmulateInstructionMIPS::Emulate_JIALC(llvm::MCInst &insn) {
2577 bool success = false;
2578 uint32_t rt;
2579 int32_t target, offset, pc, rt_val;
2580
2581 /*
2582 * JIALC rt, offset
2583 * offset = sign_ext (offset)
2584 * PC = GPR[rt] + offset
2585 * RA = PC + 4
2586 */
2587 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2588 offset = insn.getOperand(1).getImm();
2589
2590 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2591 if (!success)
2592 return false;
2593
2594 rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2595 dwarf_zero_mips + rt, 0, &success);
2596 if (!success)
2597 return false;
2598
2599 target = rt_val + offset;
2600
2601 Context context;
2602
2603 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2604 target))
2605 return false;
2606
2607 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2608 pc + 4))
2609 return false;
2610
2611 return true;
2612 }
2613
Emulate_JIC(llvm::MCInst & insn)2614 bool EmulateInstructionMIPS::Emulate_JIC(llvm::MCInst &insn) {
2615 bool success = false;
2616 uint32_t rt;
2617 int32_t target, offset, rt_val;
2618
2619 /*
2620 * JIC rt, offset
2621 * offset = sign_ext (offset)
2622 * PC = GPR[rt] + offset
2623 */
2624 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2625 offset = insn.getOperand(1).getImm();
2626
2627 rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2628 dwarf_zero_mips + rt, 0, &success);
2629 if (!success)
2630 return false;
2631
2632 target = rt_val + offset;
2633
2634 Context context;
2635
2636 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2637 target);
2638 }
2639
Emulate_JR(llvm::MCInst & insn)2640 bool EmulateInstructionMIPS::Emulate_JR(llvm::MCInst &insn) {
2641 bool success = false;
2642 uint32_t rs;
2643 uint32_t rs_val;
2644
2645 /*
2646 * JR rs
2647 * PC = GPR[rs]
2648 */
2649 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2650
2651 rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + rs, 0,
2652 &success);
2653 if (!success)
2654 return false;
2655
2656 Context context;
2657
2658 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2659 rs_val);
2660 }
2661
2662 /*
2663 Emulate Branch on FP True/False
2664 BC1F, BC1FL : Branch on FP False (L stands for branch likely)
2665 BC1T, BC1TL : Branch on FP True (L stands for branch likely)
2666 */
Emulate_FP_branch(llvm::MCInst & insn)2667 bool EmulateInstructionMIPS::Emulate_FP_branch(llvm::MCInst &insn) {
2668 bool success = false;
2669 uint32_t cc, fcsr;
2670 int32_t pc, offset, target = 0;
2671 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2672
2673 cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2674 offset = insn.getOperand(1).getImm();
2675
2676 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2677 if (!success)
2678 return false;
2679
2680 fcsr = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);
2681 if (!success)
2682 return false;
2683
2684 /* fcsr[23], fcsr[25-31] are vaild condition bits */
2685 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2686
2687 if (op_name.equals_insensitive("BC1F") ||
2688 op_name.equals_insensitive("BC1FL")) {
2689 if ((fcsr & (1 << cc)) == 0)
2690 target = pc + offset;
2691 else
2692 target = pc + 8;
2693 } else if (op_name.equals_insensitive("BC1T") ||
2694 op_name.equals_insensitive("BC1TL")) {
2695 if ((fcsr & (1 << cc)) != 0)
2696 target = pc + offset;
2697 else
2698 target = pc + 8;
2699 }
2700 Context context;
2701
2702 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2703 target);
2704 }
2705
Emulate_BC1EQZ(llvm::MCInst & insn)2706 bool EmulateInstructionMIPS::Emulate_BC1EQZ(llvm::MCInst &insn) {
2707 bool success = false;
2708 uint32_t ft;
2709 uint32_t ft_val;
2710 int32_t target, pc, offset;
2711
2712 /*
2713 * BC1EQZ ft, offset
2714 * condition <- (FPR[ft].bit0 == 0)
2715 * if condition then
2716 * offset = sign_ext (offset)
2717 * PC = PC + 4 + offset
2718 */
2719 ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2720 offset = insn.getOperand(1).getImm();
2721
2722 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2723 if (!success)
2724 return false;
2725
2726 ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + ft, 0,
2727 &success);
2728 if (!success)
2729 return false;
2730
2731 if ((ft_val & 1) == 0)
2732 target = pc + 4 + offset;
2733 else
2734 target = pc + 8;
2735
2736 Context context;
2737
2738 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2739 target);
2740 }
2741
Emulate_BC1NEZ(llvm::MCInst & insn)2742 bool EmulateInstructionMIPS::Emulate_BC1NEZ(llvm::MCInst &insn) {
2743 bool success = false;
2744 uint32_t ft;
2745 uint32_t ft_val;
2746 int32_t target, pc, offset;
2747
2748 /*
2749 * BC1NEZ ft, offset
2750 * condition <- (FPR[ft].bit0 != 0)
2751 * if condition then
2752 * offset = sign_ext (offset)
2753 * PC = PC + 4 + offset
2754 */
2755 ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2756 offset = insn.getOperand(1).getImm();
2757
2758 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2759 if (!success)
2760 return false;
2761
2762 ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + ft, 0,
2763 &success);
2764 if (!success)
2765 return false;
2766
2767 if ((ft_val & 1) != 0)
2768 target = pc + 4 + offset;
2769 else
2770 target = pc + 8;
2771
2772 Context context;
2773
2774 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2775 target);
2776 }
2777
2778 /*
2779 Emulate MIPS-3D Branch instructions
2780 BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes
2781 False/True
2782 BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes
2783 False/True
2784 */
Emulate_3D_branch(llvm::MCInst & insn)2785 bool EmulateInstructionMIPS::Emulate_3D_branch(llvm::MCInst &insn) {
2786 bool success = false;
2787 uint32_t cc, fcsr;
2788 int32_t pc, offset, target = 0;
2789 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2790
2791 cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2792 offset = insn.getOperand(1).getImm();
2793
2794 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2795 if (!success)
2796 return false;
2797
2798 fcsr = (uint32_t)ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips, 0,
2799 &success);
2800 if (!success)
2801 return false;
2802
2803 /* fcsr[23], fcsr[25-31] are vaild condition bits */
2804 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2805
2806 if (op_name.equals_insensitive("BC1ANY2F")) {
2807 /* if any one bit is 0 */
2808 if (((fcsr >> cc) & 3) != 3)
2809 target = pc + offset;
2810 else
2811 target = pc + 8;
2812 } else if (op_name.equals_insensitive("BC1ANY2T")) {
2813 /* if any one bit is 1 */
2814 if (((fcsr >> cc) & 3) != 0)
2815 target = pc + offset;
2816 else
2817 target = pc + 8;
2818 } else if (op_name.equals_insensitive("BC1ANY4F")) {
2819 /* if any one bit is 0 */
2820 if (((fcsr >> cc) & 0xf) != 0xf)
2821 target = pc + offset;
2822 else
2823 target = pc + 8;
2824 } else if (op_name.equals_insensitive("BC1ANY4T")) {
2825 /* if any one bit is 1 */
2826 if (((fcsr >> cc) & 0xf) != 0)
2827 target = pc + offset;
2828 else
2829 target = pc + 8;
2830 }
2831 Context context;
2832
2833 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2834 target);
2835 }
2836
Emulate_BNZB(llvm::MCInst & insn)2837 bool EmulateInstructionMIPS::Emulate_BNZB(llvm::MCInst &insn) {
2838 return Emulate_MSA_Branch_DF(insn, 1, true);
2839 }
2840
Emulate_BNZH(llvm::MCInst & insn)2841 bool EmulateInstructionMIPS::Emulate_BNZH(llvm::MCInst &insn) {
2842 return Emulate_MSA_Branch_DF(insn, 2, true);
2843 }
2844
Emulate_BNZW(llvm::MCInst & insn)2845 bool EmulateInstructionMIPS::Emulate_BNZW(llvm::MCInst &insn) {
2846 return Emulate_MSA_Branch_DF(insn, 4, true);
2847 }
2848
Emulate_BNZD(llvm::MCInst & insn)2849 bool EmulateInstructionMIPS::Emulate_BNZD(llvm::MCInst &insn) {
2850 return Emulate_MSA_Branch_DF(insn, 8, true);
2851 }
2852
Emulate_BZB(llvm::MCInst & insn)2853 bool EmulateInstructionMIPS::Emulate_BZB(llvm::MCInst &insn) {
2854 return Emulate_MSA_Branch_DF(insn, 1, false);
2855 }
2856
Emulate_BZH(llvm::MCInst & insn)2857 bool EmulateInstructionMIPS::Emulate_BZH(llvm::MCInst &insn) {
2858 return Emulate_MSA_Branch_DF(insn, 2, false);
2859 }
2860
Emulate_BZW(llvm::MCInst & insn)2861 bool EmulateInstructionMIPS::Emulate_BZW(llvm::MCInst &insn) {
2862 return Emulate_MSA_Branch_DF(insn, 4, false);
2863 }
2864
Emulate_BZD(llvm::MCInst & insn)2865 bool EmulateInstructionMIPS::Emulate_BZD(llvm::MCInst &insn) {
2866 return Emulate_MSA_Branch_DF(insn, 8, false);
2867 }
2868
Emulate_MSA_Branch_DF(llvm::MCInst & insn,int element_byte_size,bool bnz)2869 bool EmulateInstructionMIPS::Emulate_MSA_Branch_DF(llvm::MCInst &insn,
2870 int element_byte_size,
2871 bool bnz) {
2872 bool success = false, branch_hit = true;
2873 int32_t target = 0;
2874 RegisterValue reg_value;
2875 const uint8_t *ptr = nullptr;
2876
2877 uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2878 int32_t offset = insn.getOperand(1).getImm();
2879
2880 int32_t pc =
2881 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2882 if (!success)
2883 return false;
2884
2885 if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value))
2886 ptr = (const uint8_t *)reg_value.GetBytes();
2887 else
2888 return false;
2889
2890 for (int i = 0; i < 16 / element_byte_size; i++) {
2891 switch (element_byte_size) {
2892 case 1:
2893 if ((*ptr == 0 && bnz) || (*ptr != 0 && !bnz))
2894 branch_hit = false;
2895 break;
2896 case 2:
2897 if ((*(const uint16_t *)ptr == 0 && bnz) ||
2898 (*(const uint16_t *)ptr != 0 && !bnz))
2899 branch_hit = false;
2900 break;
2901 case 4:
2902 if ((*(const uint32_t *)ptr == 0 && bnz) ||
2903 (*(const uint32_t *)ptr != 0 && !bnz))
2904 branch_hit = false;
2905 break;
2906 case 8:
2907 if ((*(const uint64_t *)ptr == 0 && bnz) ||
2908 (*(const uint64_t *)ptr != 0 && !bnz))
2909 branch_hit = false;
2910 break;
2911 }
2912 if (!branch_hit)
2913 break;
2914 ptr = ptr + element_byte_size;
2915 }
2916
2917 if (branch_hit)
2918 target = pc + offset;
2919 else
2920 target = pc + 8;
2921
2922 Context context;
2923 context.type = eContextRelativeBranchImmediate;
2924
2925 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2926 target);
2927 }
2928
Emulate_BNZV(llvm::MCInst & insn)2929 bool EmulateInstructionMIPS::Emulate_BNZV(llvm::MCInst &insn) {
2930 return Emulate_MSA_Branch_V(insn, true);
2931 }
2932
Emulate_BZV(llvm::MCInst & insn)2933 bool EmulateInstructionMIPS::Emulate_BZV(llvm::MCInst &insn) {
2934 return Emulate_MSA_Branch_V(insn, false);
2935 }
2936
Emulate_MSA_Branch_V(llvm::MCInst & insn,bool bnz)2937 bool EmulateInstructionMIPS::Emulate_MSA_Branch_V(llvm::MCInst &insn,
2938 bool bnz) {
2939 bool success = false;
2940 int32_t target = 0;
2941 llvm::APInt wr_val = llvm::APInt::getZero(128);
2942 llvm::APInt fail_value = llvm::APInt::getMaxValue(128);
2943 llvm::APInt zero_value = llvm::APInt::getZero(128);
2944 RegisterValue reg_value;
2945
2946 uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2947 int32_t offset = insn.getOperand(1).getImm();
2948
2949 int32_t pc =
2950 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2951 if (!success)
2952 return false;
2953
2954 if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value))
2955 wr_val = reg_value.GetAsUInt128(fail_value);
2956 else
2957 return false;
2958
2959 if ((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) ||
2960 (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz))
2961 target = pc + offset;
2962 else
2963 target = pc + 8;
2964
2965 Context context;
2966 context.type = eContextRelativeBranchImmediate;
2967
2968 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2969 target);
2970 }
2971
Emulate_LDST_Imm(llvm::MCInst & insn)2972 bool EmulateInstructionMIPS::Emulate_LDST_Imm(llvm::MCInst &insn) {
2973 bool success = false;
2974 uint32_t base;
2975 int32_t imm, address;
2976 Context bad_vaddr_context;
2977
2978 uint32_t num_operands = insn.getNumOperands();
2979 base =
2980 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
2981 imm = insn.getOperand(num_operands - 1).getImm();
2982
2983 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))
2984 return false;
2985
2986 /* read base register */
2987 address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2988 dwarf_zero_mips + base, 0, &success);
2989 if (!success)
2990 return false;
2991
2992 /* destination address */
2993 address = address + imm;
2994
2995 /* Set the bad_vaddr register with base address used in the instruction */
2996 bad_vaddr_context.type = eContextInvalid;
2997 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
2998 address);
2999
3000 return true;
3001 }
3002
Emulate_LDST_Reg(llvm::MCInst & insn)3003 bool EmulateInstructionMIPS::Emulate_LDST_Reg(llvm::MCInst &insn) {
3004 bool success = false;
3005 uint32_t base, index;
3006 int32_t address, index_address;
3007 Context bad_vaddr_context;
3008
3009 uint32_t num_operands = insn.getNumOperands();
3010 base =
3011 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
3012 index =
3013 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 1).getReg());
3014
3015 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))
3016 return false;
3017
3018 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + index))
3019 return false;
3020
3021 /* read base register */
3022 address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
3023 dwarf_zero_mips + base, 0, &success);
3024 if (!success)
3025 return false;
3026
3027 /* read index register */
3028 index_address = (int32_t)ReadRegisterUnsigned(
3029 eRegisterKindDWARF, dwarf_zero_mips + index, 0, &success);
3030 if (!success)
3031 return false;
3032
3033 /* destination address */
3034 address = address + index_address;
3035
3036 /* Set the bad_vaddr register with base address used in the instruction */
3037 bad_vaddr_context.type = eContextInvalid;
3038 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
3039 address);
3040
3041 return true;
3042 }
3043