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