1 //===-- EmulateInstructionMIPS64.cpp -----------------------------*- C++-*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "EmulateInstructionMIPS64.h"
11
12 #include <stdlib.h>
13
14 #include "lldb/Core/Address.h"
15 #include "lldb/Core/Opcode.h"
16 #include "lldb/Core/PluginManager.h"
17 #include "lldb/Host/PosixApi.h"
18 #include "lldb/Symbol/UnwindPlan.h"
19 #include "lldb/Utility/ArchSpec.h"
20 #include "lldb/Utility/ConstString.h"
21 #include "lldb/Utility/DataExtractor.h"
22 #include "lldb/Utility/RegisterValue.h"
23 #include "lldb/Utility/Stream.h"
24 #include "llvm-c/Disassembler.h"
25 #include "llvm/MC/MCAsmInfo.h"
26 #include "llvm/MC/MCContext.h"
27 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
28 #include "llvm/MC/MCInst.h"
29 #include "llvm/MC/MCInstrInfo.h"
30 #include "llvm/MC/MCRegisterInfo.h"
31 #include "llvm/MC/MCSubtargetInfo.h"
32 #include "llvm/Support/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
43 #define UInt(x) ((uint64_t)x)
44 #define integer int64_t
45
46 //----------------------------------------------------------------------
47 //
48 // EmulateInstructionMIPS64 implementation
49 //
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
EmulateInstructionMIPS64(const lldb_private::ArchSpec & arch)62 EmulateInstructionMIPS64::EmulateInstructionMIPS64(
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 if (arch_flags & ArchSpec::eMIPSAse_mips16)
149 features += "+mips16,";
150 if (arch_flags & ArchSpec::eMIPSAse_micromips)
151 features += "+micromips,";
152
153 m_reg_info.reset(target->createMCRegInfo(triple.getTriple()));
154 assert(m_reg_info.get());
155
156 m_insn_info.reset(target->createMCInstrInfo());
157 assert(m_insn_info.get());
158
159 m_asm_info.reset(target->createMCAsmInfo(*m_reg_info, triple.getTriple()));
160 m_subtype_info.reset(
161 target->createMCSubtargetInfo(triple.getTriple(), cpu, features));
162 assert(m_asm_info.get() && m_subtype_info.get());
163
164 m_context.reset(
165 new llvm::MCContext(m_asm_info.get(), m_reg_info.get(), nullptr));
166 assert(m_context.get());
167
168 m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context));
169 assert(m_disasm.get());
170 }
171
Initialize()172 void EmulateInstructionMIPS64::Initialize() {
173 PluginManager::RegisterPlugin(GetPluginNameStatic(),
174 GetPluginDescriptionStatic(), CreateInstance);
175 }
176
Terminate()177 void EmulateInstructionMIPS64::Terminate() {
178 PluginManager::UnregisterPlugin(CreateInstance);
179 }
180
GetPluginNameStatic()181 ConstString EmulateInstructionMIPS64::GetPluginNameStatic() {
182 ConstString g_plugin_name("lldb.emulate-instruction.mips64");
183 return g_plugin_name;
184 }
185
GetPluginName()186 lldb_private::ConstString EmulateInstructionMIPS64::GetPluginName() {
187 static ConstString g_plugin_name("EmulateInstructionMIPS64");
188 return g_plugin_name;
189 }
190
GetPluginDescriptionStatic()191 const char *EmulateInstructionMIPS64::GetPluginDescriptionStatic() {
192 return "Emulate instructions for the MIPS64 architecture.";
193 }
194
195 EmulateInstruction *
CreateInstance(const ArchSpec & arch,InstructionType inst_type)196 EmulateInstructionMIPS64::CreateInstance(const ArchSpec &arch,
197 InstructionType inst_type) {
198 if (EmulateInstructionMIPS64::SupportsEmulatingInstructionsOfTypeStatic(
199 inst_type)) {
200 if (arch.GetTriple().getArch() == llvm::Triple::mips64 ||
201 arch.GetTriple().getArch() == llvm::Triple::mips64el) {
202 return new EmulateInstructionMIPS64(arch);
203 }
204 }
205
206 return NULL;
207 }
208
SetTargetTriple(const ArchSpec & arch)209 bool EmulateInstructionMIPS64::SetTargetTriple(const ArchSpec &arch) {
210 return arch.GetTriple().getArch() == llvm::Triple::mips64 ||
211 arch.GetTriple().getArch() == llvm::Triple::mips64el;
212 }
213
GetRegisterName(unsigned reg_num,bool alternate_name)214 const char *EmulateInstructionMIPS64::GetRegisterName(unsigned reg_num,
215 bool alternate_name) {
216 if (alternate_name) {
217 switch (reg_num) {
218 case dwarf_sp_mips64:
219 return "r29";
220 case dwarf_r30_mips64:
221 return "r30";
222 case dwarf_ra_mips64:
223 return "r31";
224 case dwarf_f0_mips64:
225 return "f0";
226 case dwarf_f1_mips64:
227 return "f1";
228 case dwarf_f2_mips64:
229 return "f2";
230 case dwarf_f3_mips64:
231 return "f3";
232 case dwarf_f4_mips64:
233 return "f4";
234 case dwarf_f5_mips64:
235 return "f5";
236 case dwarf_f6_mips64:
237 return "f6";
238 case dwarf_f7_mips64:
239 return "f7";
240 case dwarf_f8_mips64:
241 return "f8";
242 case dwarf_f9_mips64:
243 return "f9";
244 case dwarf_f10_mips64:
245 return "f10";
246 case dwarf_f11_mips64:
247 return "f11";
248 case dwarf_f12_mips64:
249 return "f12";
250 case dwarf_f13_mips64:
251 return "f13";
252 case dwarf_f14_mips64:
253 return "f14";
254 case dwarf_f15_mips64:
255 return "f15";
256 case dwarf_f16_mips64:
257 return "f16";
258 case dwarf_f17_mips64:
259 return "f17";
260 case dwarf_f18_mips64:
261 return "f18";
262 case dwarf_f19_mips64:
263 return "f19";
264 case dwarf_f20_mips64:
265 return "f20";
266 case dwarf_f21_mips64:
267 return "f21";
268 case dwarf_f22_mips64:
269 return "f22";
270 case dwarf_f23_mips64:
271 return "f23";
272 case dwarf_f24_mips64:
273 return "f24";
274 case dwarf_f25_mips64:
275 return "f25";
276 case dwarf_f26_mips64:
277 return "f26";
278 case dwarf_f27_mips64:
279 return "f27";
280 case dwarf_f28_mips64:
281 return "f28";
282 case dwarf_f29_mips64:
283 return "f29";
284 case dwarf_f30_mips64:
285 return "f30";
286 case dwarf_f31_mips64:
287 return "f31";
288 case dwarf_w0_mips64:
289 return "w0";
290 case dwarf_w1_mips64:
291 return "w1";
292 case dwarf_w2_mips64:
293 return "w2";
294 case dwarf_w3_mips64:
295 return "w3";
296 case dwarf_w4_mips64:
297 return "w4";
298 case dwarf_w5_mips64:
299 return "w5";
300 case dwarf_w6_mips64:
301 return "w6";
302 case dwarf_w7_mips64:
303 return "w7";
304 case dwarf_w8_mips64:
305 return "w8";
306 case dwarf_w9_mips64:
307 return "w9";
308 case dwarf_w10_mips64:
309 return "w10";
310 case dwarf_w11_mips64:
311 return "w11";
312 case dwarf_w12_mips64:
313 return "w12";
314 case dwarf_w13_mips64:
315 return "w13";
316 case dwarf_w14_mips64:
317 return "w14";
318 case dwarf_w15_mips64:
319 return "w15";
320 case dwarf_w16_mips64:
321 return "w16";
322 case dwarf_w17_mips64:
323 return "w17";
324 case dwarf_w18_mips64:
325 return "w18";
326 case dwarf_w19_mips64:
327 return "w19";
328 case dwarf_w20_mips64:
329 return "w20";
330 case dwarf_w21_mips64:
331 return "w21";
332 case dwarf_w22_mips64:
333 return "w22";
334 case dwarf_w23_mips64:
335 return "w23";
336 case dwarf_w24_mips64:
337 return "w24";
338 case dwarf_w25_mips64:
339 return "w25";
340 case dwarf_w26_mips64:
341 return "w26";
342 case dwarf_w27_mips64:
343 return "w27";
344 case dwarf_w28_mips64:
345 return "w28";
346 case dwarf_w29_mips64:
347 return "w29";
348 case dwarf_w30_mips64:
349 return "w30";
350 case dwarf_w31_mips64:
351 return "w31";
352 case dwarf_mir_mips64:
353 return "mir";
354 case dwarf_mcsr_mips64:
355 return "mcsr";
356 case dwarf_config5_mips64:
357 return "config5";
358 default:
359 break;
360 }
361 return nullptr;
362 }
363
364 switch (reg_num) {
365 case dwarf_zero_mips64:
366 return "r0";
367 case dwarf_r1_mips64:
368 return "r1";
369 case dwarf_r2_mips64:
370 return "r2";
371 case dwarf_r3_mips64:
372 return "r3";
373 case dwarf_r4_mips64:
374 return "r4";
375 case dwarf_r5_mips64:
376 return "r5";
377 case dwarf_r6_mips64:
378 return "r6";
379 case dwarf_r7_mips64:
380 return "r7";
381 case dwarf_r8_mips64:
382 return "r8";
383 case dwarf_r9_mips64:
384 return "r9";
385 case dwarf_r10_mips64:
386 return "r10";
387 case dwarf_r11_mips64:
388 return "r11";
389 case dwarf_r12_mips64:
390 return "r12";
391 case dwarf_r13_mips64:
392 return "r13";
393 case dwarf_r14_mips64:
394 return "r14";
395 case dwarf_r15_mips64:
396 return "r15";
397 case dwarf_r16_mips64:
398 return "r16";
399 case dwarf_r17_mips64:
400 return "r17";
401 case dwarf_r18_mips64:
402 return "r18";
403 case dwarf_r19_mips64:
404 return "r19";
405 case dwarf_r20_mips64:
406 return "r20";
407 case dwarf_r21_mips64:
408 return "r21";
409 case dwarf_r22_mips64:
410 return "r22";
411 case dwarf_r23_mips64:
412 return "r23";
413 case dwarf_r24_mips64:
414 return "r24";
415 case dwarf_r25_mips64:
416 return "r25";
417 case dwarf_r26_mips64:
418 return "r26";
419 case dwarf_r27_mips64:
420 return "r27";
421 case dwarf_gp_mips64:
422 return "gp";
423 case dwarf_sp_mips64:
424 return "sp";
425 case dwarf_r30_mips64:
426 return "fp";
427 case dwarf_ra_mips64:
428 return "ra";
429 case dwarf_sr_mips64:
430 return "sr";
431 case dwarf_lo_mips64:
432 return "lo";
433 case dwarf_hi_mips64:
434 return "hi";
435 case dwarf_bad_mips64:
436 return "bad";
437 case dwarf_cause_mips64:
438 return "cause";
439 case dwarf_pc_mips64:
440 return "pc";
441 case dwarf_f0_mips64:
442 return "f0";
443 case dwarf_f1_mips64:
444 return "f1";
445 case dwarf_f2_mips64:
446 return "f2";
447 case dwarf_f3_mips64:
448 return "f3";
449 case dwarf_f4_mips64:
450 return "f4";
451 case dwarf_f5_mips64:
452 return "f5";
453 case dwarf_f6_mips64:
454 return "f6";
455 case dwarf_f7_mips64:
456 return "f7";
457 case dwarf_f8_mips64:
458 return "f8";
459 case dwarf_f9_mips64:
460 return "f9";
461 case dwarf_f10_mips64:
462 return "f10";
463 case dwarf_f11_mips64:
464 return "f11";
465 case dwarf_f12_mips64:
466 return "f12";
467 case dwarf_f13_mips64:
468 return "f13";
469 case dwarf_f14_mips64:
470 return "f14";
471 case dwarf_f15_mips64:
472 return "f15";
473 case dwarf_f16_mips64:
474 return "f16";
475 case dwarf_f17_mips64:
476 return "f17";
477 case dwarf_f18_mips64:
478 return "f18";
479 case dwarf_f19_mips64:
480 return "f19";
481 case dwarf_f20_mips64:
482 return "f20";
483 case dwarf_f21_mips64:
484 return "f21";
485 case dwarf_f22_mips64:
486 return "f22";
487 case dwarf_f23_mips64:
488 return "f23";
489 case dwarf_f24_mips64:
490 return "f24";
491 case dwarf_f25_mips64:
492 return "f25";
493 case dwarf_f26_mips64:
494 return "f26";
495 case dwarf_f27_mips64:
496 return "f27";
497 case dwarf_f28_mips64:
498 return "f28";
499 case dwarf_f29_mips64:
500 return "f29";
501 case dwarf_f30_mips64:
502 return "f30";
503 case dwarf_f31_mips64:
504 return "f31";
505 case dwarf_fcsr_mips64:
506 return "fcsr";
507 case dwarf_fir_mips64:
508 return "fir";
509 case dwarf_w0_mips64:
510 return "w0";
511 case dwarf_w1_mips64:
512 return "w1";
513 case dwarf_w2_mips64:
514 return "w2";
515 case dwarf_w3_mips64:
516 return "w3";
517 case dwarf_w4_mips64:
518 return "w4";
519 case dwarf_w5_mips64:
520 return "w5";
521 case dwarf_w6_mips64:
522 return "w6";
523 case dwarf_w7_mips64:
524 return "w7";
525 case dwarf_w8_mips64:
526 return "w8";
527 case dwarf_w9_mips64:
528 return "w9";
529 case dwarf_w10_mips64:
530 return "w10";
531 case dwarf_w11_mips64:
532 return "w11";
533 case dwarf_w12_mips64:
534 return "w12";
535 case dwarf_w13_mips64:
536 return "w13";
537 case dwarf_w14_mips64:
538 return "w14";
539 case dwarf_w15_mips64:
540 return "w15";
541 case dwarf_w16_mips64:
542 return "w16";
543 case dwarf_w17_mips64:
544 return "w17";
545 case dwarf_w18_mips64:
546 return "w18";
547 case dwarf_w19_mips64:
548 return "w19";
549 case dwarf_w20_mips64:
550 return "w20";
551 case dwarf_w21_mips64:
552 return "w21";
553 case dwarf_w22_mips64:
554 return "w22";
555 case dwarf_w23_mips64:
556 return "w23";
557 case dwarf_w24_mips64:
558 return "w24";
559 case dwarf_w25_mips64:
560 return "w25";
561 case dwarf_w26_mips64:
562 return "w26";
563 case dwarf_w27_mips64:
564 return "w27";
565 case dwarf_w28_mips64:
566 return "w28";
567 case dwarf_w29_mips64:
568 return "w29";
569 case dwarf_w30_mips64:
570 return "w30";
571 case dwarf_w31_mips64:
572 return "w31";
573 case dwarf_mcsr_mips64:
574 return "mcsr";
575 case dwarf_mir_mips64:
576 return "mir";
577 case dwarf_config5_mips64:
578 return "config5";
579 }
580 return nullptr;
581 }
582
GetRegisterInfo(RegisterKind reg_kind,uint32_t reg_num,RegisterInfo & reg_info)583 bool EmulateInstructionMIPS64::GetRegisterInfo(RegisterKind reg_kind,
584 uint32_t reg_num,
585 RegisterInfo ®_info) {
586 if (reg_kind == eRegisterKindGeneric) {
587 switch (reg_num) {
588 case LLDB_REGNUM_GENERIC_PC:
589 reg_kind = eRegisterKindDWARF;
590 reg_num = dwarf_pc_mips64;
591 break;
592 case LLDB_REGNUM_GENERIC_SP:
593 reg_kind = eRegisterKindDWARF;
594 reg_num = dwarf_sp_mips64;
595 break;
596 case LLDB_REGNUM_GENERIC_FP:
597 reg_kind = eRegisterKindDWARF;
598 reg_num = dwarf_r30_mips64;
599 break;
600 case LLDB_REGNUM_GENERIC_RA:
601 reg_kind = eRegisterKindDWARF;
602 reg_num = dwarf_ra_mips64;
603 break;
604 case LLDB_REGNUM_GENERIC_FLAGS:
605 reg_kind = eRegisterKindDWARF;
606 reg_num = dwarf_sr_mips64;
607 break;
608 default:
609 return false;
610 }
611 }
612
613 if (reg_kind == eRegisterKindDWARF) {
614 ::memset(®_info, 0, sizeof(RegisterInfo));
615 ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
616
617 if (reg_num == dwarf_sr_mips64 || reg_num == dwarf_fcsr_mips64 ||
618 reg_num == dwarf_fir_mips64 || reg_num == dwarf_mcsr_mips64 ||
619 reg_num == dwarf_mir_mips64 || reg_num == dwarf_config5_mips64) {
620 reg_info.byte_size = 4;
621 reg_info.format = eFormatHex;
622 reg_info.encoding = eEncodingUint;
623 } else if ((int)reg_num >= dwarf_zero_mips64 &&
624 (int)reg_num <= dwarf_f31_mips64) {
625 reg_info.byte_size = 8;
626 reg_info.format = eFormatHex;
627 reg_info.encoding = eEncodingUint;
628 } else if ((int)reg_num >= dwarf_w0_mips64 &&
629 (int)reg_num <= dwarf_w31_mips64) {
630 reg_info.byte_size = 16;
631 reg_info.format = eFormatVectorOfUInt8;
632 reg_info.encoding = eEncodingVector;
633 } else {
634 return false;
635 }
636
637 reg_info.name = GetRegisterName(reg_num, false);
638 reg_info.alt_name = GetRegisterName(reg_num, true);
639 reg_info.kinds[eRegisterKindDWARF] = reg_num;
640
641 switch (reg_num) {
642 case dwarf_r30_mips64:
643 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
644 break;
645 case dwarf_ra_mips64:
646 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
647 break;
648 case dwarf_sp_mips64:
649 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
650 break;
651 case dwarf_pc_mips64:
652 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
653 break;
654 case dwarf_sr_mips64:
655 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
656 break;
657 default:
658 break;
659 }
660 return true;
661 }
662 return false;
663 }
664
665 EmulateInstructionMIPS64::MipsOpcode *
GetOpcodeForInstruction(const char * op_name)666 EmulateInstructionMIPS64::GetOpcodeForInstruction(const char *op_name) {
667 static EmulateInstructionMIPS64::MipsOpcode g_opcodes[] = {
668 //----------------------------------------------------------------------
669 // Prologue/Epilogue instructions
670 //----------------------------------------------------------------------
671 {"DADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu,
672 "DADDIU rt, rs, immediate"},
673 {"ADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu,
674 "ADDIU rt, rs, immediate"},
675 {"SD", &EmulateInstructionMIPS64::Emulate_SD, "SD rt, offset(rs)"},
676 {"LD", &EmulateInstructionMIPS64::Emulate_LD, "LD rt, offset(base)"},
677 {"DSUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
678 "DSUBU rd, rs, rt"},
679 {"SUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
680 "SUBU rd, rs, rt"},
681 {"DADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
682 "DADDU rd, rs, rt"},
683 {"ADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
684 "ADDU rd, rs, rt"},
685 {"LUI", &EmulateInstructionMIPS64::Emulate_LUI, "LUI rt, immediate"},
686
687 //----------------------------------------------------------------------
688 // Load/Store instructions
689 //----------------------------------------------------------------------
690 /* Following list of emulated instructions are required by implementation
691 of hardware watchpoint
692 for MIPS in lldb. As we just need the address accessed by instructions,
693 we have generalised
694 all these instructions in 2 functions depending on their addressing
695 modes */
696
697 {"LB", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
698 "LB rt, offset(base)"},
699 {"LBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
700 "LBE rt, offset(base)"},
701 {"LBU", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
702 "LBU rt, offset(base)"},
703 {"LBUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
704 "LBUE rt, offset(base)"},
705 {"LDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
706 "LDC1 ft, offset(base)"},
707 {"LDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
708 "LDL rt, offset(base)"},
709 {"LDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
710 "LDR rt, offset(base)"},
711 {"LLD", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
712 "LLD rt, offset(base)"},
713 {"LDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
714 "LDC2 rt, offset(base)"},
715 {"LDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
716 "LDXC1 fd, index (base)"},
717 {"LH", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
718 "LH rt, offset(base)"},
719 {"LHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
720 "LHE rt, offset(base)"},
721 {"LHU", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
722 "LHU rt, offset(base)"},
723 {"LHUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
724 "LHUE rt, offset(base)"},
725 {"LL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
726 "LL rt, offset(base)"},
727 {"LLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
728 "LLE rt, offset(base)"},
729 {"LUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
730 "LUXC1 fd, index (base)"},
731 {"LW", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
732 "LW rt, offset(rs)"},
733 {"LWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
734 "LWC1 ft, offset(base)"},
735 {"LWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
736 "LWC2 rt, offset(base)"},
737 {"LWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
738 "LWE rt, offset(base)"},
739 {"LWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
740 "LWL rt, offset(base)"},
741 {"LWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
742 "LWLE rt, offset(base)"},
743 {"LWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
744 "LWR rt, offset(base)"},
745 {"LWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
746 "LWRE rt, offset(base)"},
747 {"LWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
748 "LWXC1 fd, index (base)"},
749
750 {"SB", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
751 "SB rt, offset(base)"},
752 {"SBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
753 "SBE rt, offset(base)"},
754 {"SC", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
755 "SC rt, offset(base)"},
756 {"SCE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
757 "SCE rt, offset(base)"},
758 {"SCD", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
759 "SCD rt, offset(base)"},
760 {"SDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
761 "SDL rt, offset(base)"},
762 {"SDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
763 "SDR rt, offset(base)"},
764 {"SDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
765 "SDC1 ft, offset(base)"},
766 {"SDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
767 "SDC2 rt, offset(base)"},
768 {"SDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
769 "SDXC1 fs, index (base)"},
770 {"SH", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
771 "SH rt, offset(base)"},
772 {"SHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
773 "SHE rt, offset(base)"},
774 {"SUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
775 "SUXC1 fs, index (base)"},
776 {"SW", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
777 "SW rt, offset(rs)"},
778 {"SWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
779 "SWC1 ft, offset(base)"},
780 {"SWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
781 "SWC2 rt, offset(base)"},
782 {"SWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
783 "SWE rt, offset(base)"},
784 {"SWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
785 "SWL rt, offset(base)"},
786 {"SWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
787 "SWLE rt, offset(base)"},
788 {"SWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
789 "SWR rt, offset(base)"},
790 {"SWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
791 "SWRE rt, offset(base)"},
792 {"SWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
793 "SWXC1 fs, index (base)"},
794
795 //----------------------------------------------------------------------
796 // Branch instructions
797 //----------------------------------------------------------------------
798 {"BEQ", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"},
799 {"BEQ64", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"},
800 {"BNE", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"},
801 {"BNE64", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"},
802 {"BEQL", &EmulateInstructionMIPS64::Emulate_BXX_3ops,
803 "BEQL rs,rt,offset"},
804 {"BNEL", &EmulateInstructionMIPS64::Emulate_BXX_3ops,
805 "BNEL rs,rt,offset"},
806 {"BGEZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
807 "BGEZALL rt,offset"},
808 {"BAL", &EmulateInstructionMIPS64::Emulate_BAL, "BAL offset"},
809 {"BGEZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
810 "BGEZAL rs,offset"},
811 {"BALC", &EmulateInstructionMIPS64::Emulate_BALC, "BALC offset"},
812 {"BC", &EmulateInstructionMIPS64::Emulate_BC, "BC offset"},
813 {"BGEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"},
814 {"BGEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"},
815 {"BLEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
816 "BLEZALC rs,offset"},
817 {"BGEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
818 "BGEZALC rs,offset"},
819 {"BLTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
820 "BLTZALC rs,offset"},
821 {"BGTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
822 "BGTZALC rs,offset"},
823 {"BEQZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
824 "BEQZALC rs,offset"},
825 {"BNEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
826 "BNEZALC rs,offset"},
827 {"BEQC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
828 "BEQC rs,rt,offset"},
829 {"BEQC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
830 "BEQC rs,rt,offset"},
831 {"BNEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
832 "BNEC rs,rt,offset"},
833 {"BNEC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
834 "BNEC rs,rt,offset"},
835 {"BLTC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
836 "BLTC rs,rt,offset"},
837 {"BLTC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
838 "BLTC rs,rt,offset"},
839 {"BGEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
840 "BGEC rs,rt,offset"},
841 {"BGEC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
842 "BGEC rs,rt,offset"},
843 {"BLTUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
844 "BLTUC rs,rt,offset"},
845 {"BLTUC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
846 "BLTUC rs,rt,offset"},
847 {"BGEUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
848 "BGEUC rs,rt,offset"},
849 {"BGEUC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
850 "BGEUC rs,rt,offset"},
851 {"BLTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
852 "BLTZC rt,offset"},
853 {"BLTZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
854 "BLTZC rt,offset"},
855 {"BLEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
856 "BLEZC rt,offset"},
857 {"BLEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
858 "BLEZC rt,offset"},
859 {"BGEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
860 "BGEZC rt,offset"},
861 {"BGEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
862 "BGEZC rt,offset"},
863 {"BGTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
864 "BGTZC rt,offset"},
865 {"BGTZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
866 "BGTZC rt,offset"},
867 {"BEQZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
868 "BEQZC rt,offset"},
869 {"BEQZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
870 "BEQZC rt,offset"},
871 {"BNEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
872 "BNEZC rt,offset"},
873 {"BNEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
874 "BNEZC rt,offset"},
875 {"BGEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZL rt,offset"},
876 {"BGTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"},
877 {"BGTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"},
878 {"BGTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZL rt,offset"},
879 {"BLEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"},
880 {"BLEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"},
881 {"BLEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZL rt,offset"},
882 {"BLTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"},
883 {"BLTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"},
884 {"BLTZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
885 "BLTZAL rt,offset"},
886 {"BLTZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
887 "BLTZALL rt,offset"},
888 {"BLTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZL rt,offset"},
889 {"BOVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
890 "BOVC rs,rt,offset"},
891 {"BNVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
892 "BNVC rs,rt,offset"},
893 {"J", &EmulateInstructionMIPS64::Emulate_J, "J target"},
894 {"JAL", &EmulateInstructionMIPS64::Emulate_JAL, "JAL target"},
895 {"JALX", &EmulateInstructionMIPS64::Emulate_JAL, "JALX target"},
896 {"JALR", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target"},
897 {"JALR64", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target"},
898 {"JALR_HB", &EmulateInstructionMIPS64::Emulate_JALR, "JALR.HB target"},
899 {"JIALC", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"},
900 {"JIALC64", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"},
901 {"JIC", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"},
902 {"JIC64", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"},
903 {"JR", &EmulateInstructionMIPS64::Emulate_JR, "JR target"},
904 {"JR64", &EmulateInstructionMIPS64::Emulate_JR, "JR target"},
905 {"JR_HB", &EmulateInstructionMIPS64::Emulate_JR, "JR.HB target"},
906 {"BC1F", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1F cc, offset"},
907 {"BC1T", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1T cc, offset"},
908 {"BC1FL", &EmulateInstructionMIPS64::Emulate_FP_branch,
909 "BC1FL cc, offset"},
910 {"BC1TL", &EmulateInstructionMIPS64::Emulate_FP_branch,
911 "BC1TL cc, offset"},
912 {"BC1EQZ", &EmulateInstructionMIPS64::Emulate_BC1EQZ,
913 "BC1EQZ ft, offset"},
914 {"BC1NEZ", &EmulateInstructionMIPS64::Emulate_BC1NEZ,
915 "BC1NEZ ft, offset"},
916 {"BC1ANY2F", &EmulateInstructionMIPS64::Emulate_3D_branch,
917 "BC1ANY2F cc, offset"},
918 {"BC1ANY2T", &EmulateInstructionMIPS64::Emulate_3D_branch,
919 "BC1ANY2T cc, offset"},
920 {"BC1ANY4F", &EmulateInstructionMIPS64::Emulate_3D_branch,
921 "BC1ANY4F cc, offset"},
922 {"BC1ANY4T", &EmulateInstructionMIPS64::Emulate_3D_branch,
923 "BC1ANY4T cc, offset"},
924 {"BNZ_B", &EmulateInstructionMIPS64::Emulate_BNZB, "BNZ.b wt,s16"},
925 {"BNZ_H", &EmulateInstructionMIPS64::Emulate_BNZH, "BNZ.h wt,s16"},
926 {"BNZ_W", &EmulateInstructionMIPS64::Emulate_BNZW, "BNZ.w wt,s16"},
927 {"BNZ_D", &EmulateInstructionMIPS64::Emulate_BNZD, "BNZ.d wt,s16"},
928 {"BZ_B", &EmulateInstructionMIPS64::Emulate_BZB, "BZ.b wt,s16"},
929 {"BZ_H", &EmulateInstructionMIPS64::Emulate_BZH, "BZ.h wt,s16"},
930 {"BZ_W", &EmulateInstructionMIPS64::Emulate_BZW, "BZ.w wt,s16"},
931 {"BZ_D", &EmulateInstructionMIPS64::Emulate_BZD, "BZ.d wt,s16"},
932 {"BNZ_V", &EmulateInstructionMIPS64::Emulate_BNZV, "BNZ.V wt,s16"},
933 {"BZ_V", &EmulateInstructionMIPS64::Emulate_BZV, "BZ.V wt,s16"},
934 };
935
936 static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes);
937
938 for (size_t i = 0; i < k_num_mips_opcodes; ++i) {
939 if (!strcasecmp(g_opcodes[i].op_name, op_name))
940 return &g_opcodes[i];
941 }
942
943 return NULL;
944 }
945
ReadInstruction()946 bool EmulateInstructionMIPS64::ReadInstruction() {
947 bool success = false;
948 m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
949 LLDB_INVALID_ADDRESS, &success);
950 if (success) {
951 Context read_inst_context;
952 read_inst_context.type = eContextReadOpcode;
953 read_inst_context.SetNoArgs();
954 m_opcode.SetOpcode32(
955 ReadMemoryUnsigned(read_inst_context, m_addr, 4, 0, &success),
956 GetByteOrder());
957 }
958 if (!success)
959 m_addr = LLDB_INVALID_ADDRESS;
960 return success;
961 }
962
EvaluateInstruction(uint32_t evaluate_options)963 bool EmulateInstructionMIPS64::EvaluateInstruction(uint32_t evaluate_options) {
964 bool success = false;
965 llvm::MCInst mc_insn;
966 uint64_t insn_size;
967 DataExtractor data;
968
969 /* Keep the complexity of the decode logic with the llvm::MCDisassembler
970 * class. */
971 if (m_opcode.GetData(data)) {
972 llvm::MCDisassembler::DecodeStatus decode_status;
973 llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());
974 decode_status = m_disasm->getInstruction(
975 mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls());
976 if (decode_status != llvm::MCDisassembler::Success)
977 return false;
978 }
979
980 /*
981 * mc_insn.getOpcode() returns decoded opcode. However to make use
982 * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc".
983 */
984 const char *op_name = m_insn_info->getName(mc_insn.getOpcode()).data();
985
986 if (op_name == NULL)
987 return false;
988
989 /*
990 * Decoding has been done already. Just get the call-back function
991 * and emulate the instruction.
992 */
993 MipsOpcode *opcode_data = GetOpcodeForInstruction(op_name);
994
995 if (opcode_data == NULL)
996 return false;
997
998 uint64_t old_pc = 0, new_pc = 0;
999 const bool auto_advance_pc =
1000 evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
1001
1002 if (auto_advance_pc) {
1003 old_pc =
1004 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1005 if (!success)
1006 return false;
1007 }
1008
1009 /* emulate instruction */
1010 success = (this->*opcode_data->callback)(mc_insn);
1011 if (!success)
1012 return false;
1013
1014 if (auto_advance_pc) {
1015 new_pc =
1016 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1017 if (!success)
1018 return false;
1019
1020 /* If we haven't changed the PC, change it here */
1021 if (old_pc == new_pc) {
1022 new_pc += 4;
1023 Context context;
1024 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1025 new_pc))
1026 return false;
1027 }
1028 }
1029
1030 return true;
1031 }
1032
CreateFunctionEntryUnwind(UnwindPlan & unwind_plan)1033 bool EmulateInstructionMIPS64::CreateFunctionEntryUnwind(
1034 UnwindPlan &unwind_plan) {
1035 unwind_plan.Clear();
1036 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
1037
1038 UnwindPlan::RowSP row(new UnwindPlan::Row);
1039 const bool can_replace = false;
1040
1041 // Our previous Call Frame Address is the stack pointer
1042 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips64, 0);
1043
1044 // Our previous PC is in the RA
1045 row->SetRegisterLocationToRegister(dwarf_pc_mips64, dwarf_ra_mips64,
1046 can_replace);
1047
1048 unwind_plan.AppendRow(row);
1049
1050 // All other registers are the same.
1051 unwind_plan.SetSourceName("EmulateInstructionMIPS64");
1052 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1053 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
1054 unwind_plan.SetReturnAddressRegister(dwarf_ra_mips64);
1055
1056 return true;
1057 }
1058
nonvolatile_reg_p(uint64_t regnum)1059 bool EmulateInstructionMIPS64::nonvolatile_reg_p(uint64_t regnum) {
1060 switch (regnum) {
1061 case dwarf_r16_mips64:
1062 case dwarf_r17_mips64:
1063 case dwarf_r18_mips64:
1064 case dwarf_r19_mips64:
1065 case dwarf_r20_mips64:
1066 case dwarf_r21_mips64:
1067 case dwarf_r22_mips64:
1068 case dwarf_r23_mips64:
1069 case dwarf_gp_mips64:
1070 case dwarf_sp_mips64:
1071 case dwarf_r30_mips64:
1072 case dwarf_ra_mips64:
1073 return true;
1074 default:
1075 return false;
1076 }
1077 return false;
1078 }
1079
Emulate_DADDiu(llvm::MCInst & insn)1080 bool EmulateInstructionMIPS64::Emulate_DADDiu(llvm::MCInst &insn) {
1081 // DADDIU rt, rs, immediate
1082 // GPR[rt] <- GPR[rs] + sign_extend(immediate)
1083
1084 uint8_t dst, src;
1085 bool success = false;
1086 const uint32_t imm16 = insn.getOperand(2).getImm();
1087 int64_t imm = SignedBits(imm16, 15, 0);
1088
1089 dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1090 src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1091
1092 // If immediate is greater than 2^16 - 1 then clang generate LUI,
1093 // (D)ADDIU,(D)SUBU instructions in prolog. Example lui $1, 0x2 daddiu $1,
1094 // $1, -0x5920 dsubu $sp, $sp, $1 In this case, (D)ADDIU dst and src will be
1095 // same and not equal to sp
1096 if (dst == src) {
1097 Context context;
1098
1099 /* read <src> register */
1100 const uint64_t src_opd_val = ReadRegisterUnsigned(
1101 eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
1102 if (!success)
1103 return false;
1104
1105 /* Check if this is daddiu sp, sp, imm16 */
1106 if (dst == dwarf_sp_mips64) {
1107 /*
1108 * From the MIPS IV spec:
1109 *
1110 * The term “unsigned” in the instruction name is a misnomer; this
1111 * operation is 64-bit modulo arithmetic that does not trap on overflow.
1112 * It is appropriate for arithmetic which is not signed, such as address
1113 * arithmetic, or integer arithmetic environments that ignore overflow,
1114 * such as “C” language arithmetic.
1115 *
1116 * Assume 2's complement and rely on unsigned overflow here.
1117 */
1118 uint64_t result = src_opd_val + imm;
1119 RegisterInfo reg_info_sp;
1120
1121 if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp))
1122 context.SetRegisterPlusOffset(reg_info_sp, imm);
1123
1124 /* We are allocating bytes on stack */
1125 context.type = eContextAdjustStackPointer;
1126
1127 WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips64,
1128 result);
1129 return true;
1130 }
1131
1132 imm += src_opd_val;
1133 context.SetImmediateSigned(imm);
1134 context.type = eContextImmediate;
1135
1136 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1137 dwarf_zero_mips64 + dst, imm))
1138 return false;
1139 }
1140
1141 return true;
1142 }
1143
Emulate_SD(llvm::MCInst & insn)1144 bool EmulateInstructionMIPS64::Emulate_SD(llvm::MCInst &insn) {
1145 uint64_t address;
1146 RegisterInfo reg_info_base;
1147 RegisterInfo reg_info_src;
1148 bool success = false;
1149 uint32_t imm16 = insn.getOperand(2).getImm();
1150 uint64_t imm = SignedBits(imm16, 15, 0);
1151 uint32_t src, base;
1152 Context bad_vaddr_context;
1153
1154 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1155 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1156
1157 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base,
1158 reg_info_base) ||
1159 !GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src,
1160 reg_info_src))
1161 return false;
1162
1163 /* read SP */
1164 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + base,
1165 0, &success);
1166 if (!success)
1167 return false;
1168
1169 /* destination address */
1170 address = address + imm;
1171
1172 /* We look for sp based non-volatile register stores */
1173 if (nonvolatile_reg_p(src)) {
1174 Context context;
1175 RegisterValue data_src;
1176 context.type = eContextPushRegisterOnStack;
1177 context.SetRegisterToRegisterPlusOffset(reg_info_src, reg_info_base, 0);
1178
1179 uint8_t buffer[RegisterValue::kMaxRegisterByteSize];
1180 Status error;
1181
1182 if (!ReadRegister(®_info_base, data_src))
1183 return false;
1184
1185 if (data_src.GetAsMemoryData(®_info_src, buffer, reg_info_src.byte_size,
1186 eByteOrderLittle, error) == 0)
1187 return false;
1188
1189 if (!WriteMemory(context, address, buffer, reg_info_src.byte_size))
1190 return false;
1191 }
1192
1193 /* Set the bad_vaddr register with base address used in the instruction */
1194 bad_vaddr_context.type = eContextInvalid;
1195 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64,
1196 address);
1197
1198 return true;
1199 }
1200
Emulate_LD(llvm::MCInst & insn)1201 bool EmulateInstructionMIPS64::Emulate_LD(llvm::MCInst &insn) {
1202 bool success = false;
1203 uint32_t src, base;
1204 int64_t imm, address;
1205 Context bad_vaddr_context;
1206
1207 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1208 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1209 imm = insn.getOperand(2).getImm();
1210
1211 RegisterInfo reg_info_base;
1212 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base,
1213 reg_info_base))
1214 return false;
1215
1216 /* read base register */
1217 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + base,
1218 0, &success);
1219 if (!success)
1220 return false;
1221
1222 /* destination address */
1223 address = address + imm;
1224
1225 /* Set the bad_vaddr register with base address used in the instruction */
1226 bad_vaddr_context.type = eContextInvalid;
1227 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64,
1228 address);
1229
1230 if (nonvolatile_reg_p(src)) {
1231 RegisterValue data_src;
1232 RegisterInfo reg_info_src;
1233
1234 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src,
1235 reg_info_src))
1236 return false;
1237
1238 Context context;
1239 context.type = eContextRegisterLoad;
1240
1241 return WriteRegister(context, ®_info_src, data_src);
1242 }
1243
1244 return false;
1245 }
1246
Emulate_LUI(llvm::MCInst & insn)1247 bool EmulateInstructionMIPS64::Emulate_LUI(llvm::MCInst &insn) {
1248 // LUI rt, immediate
1249 // GPR[rt] <- sign_extend(immediate << 16)
1250
1251 const uint32_t imm32 = insn.getOperand(1).getImm() << 16;
1252 int64_t imm = SignedBits(imm32, 31, 0);
1253 uint8_t rt;
1254 Context context;
1255
1256 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1257 context.SetImmediateSigned(imm);
1258 context.type = eContextImmediate;
1259
1260 return WriteRegisterUnsigned(context, eRegisterKindDWARF,
1261 dwarf_zero_mips64 + rt, imm);
1262 }
1263
Emulate_DSUBU_DADDU(llvm::MCInst & insn)1264 bool EmulateInstructionMIPS64::Emulate_DSUBU_DADDU(llvm::MCInst &insn) {
1265 // DSUBU sp, <src>, <rt>
1266 // DADDU sp, <src>, <rt>
1267 // DADDU dst, sp, <rt>
1268
1269 bool success = false;
1270 uint64_t result;
1271 uint8_t src, dst, rt;
1272 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1273
1274 dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1275 src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1276
1277 /* Check if sp is destination register */
1278 if (dst == dwarf_sp_mips64) {
1279 rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1280
1281 /* read <src> register */
1282 uint64_t src_opd_val = ReadRegisterUnsigned(
1283 eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
1284 if (!success)
1285 return false;
1286
1287 /* read <rt > register */
1288 uint64_t rt_opd_val = ReadRegisterUnsigned(
1289 eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
1290 if (!success)
1291 return false;
1292
1293 if (!strcasecmp(op_name, "DSUBU") || !strcasecmp(op_name, "SUBU"))
1294 result = src_opd_val - rt_opd_val;
1295 else
1296 result = src_opd_val + rt_opd_val;
1297
1298 Context context;
1299 RegisterInfo reg_info_sp;
1300 if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp))
1301 context.SetRegisterPlusOffset(reg_info_sp, rt_opd_val);
1302
1303 /* We are allocating bytes on stack */
1304 context.type = eContextAdjustStackPointer;
1305
1306 WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips64, result);
1307
1308 return true;
1309 } else if (src == dwarf_sp_mips64) {
1310 rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1311
1312 /* read <src> register */
1313 uint64_t src_opd_val = ReadRegisterUnsigned(
1314 eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
1315 if (!success)
1316 return false;
1317
1318 /* read <rt> register */
1319 uint64_t rt_opd_val = ReadRegisterUnsigned(
1320 eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
1321 if (!success)
1322 return false;
1323
1324 Context context;
1325
1326 if (!strcasecmp(op_name, "DSUBU") || !strcasecmp(op_name, "SUBU"))
1327 result = src_opd_val - rt_opd_val;
1328 else
1329 result = src_opd_val + rt_opd_val;
1330
1331 context.SetImmediateSigned(result);
1332 context.type = eContextImmediate;
1333
1334 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1335 dwarf_zero_mips64 + dst, result))
1336 return false;
1337 }
1338
1339 return true;
1340 }
1341
1342 /*
1343 Emulate below MIPS branch instructions.
1344 BEQ, BNE : Branch on condition
1345 BEQL, BNEL : Branch likely
1346 */
Emulate_BXX_3ops(llvm::MCInst & insn)1347 bool EmulateInstructionMIPS64::Emulate_BXX_3ops(llvm::MCInst &insn) {
1348 bool success = false;
1349 uint32_t rs, rt;
1350 int64_t offset, pc, rs_val, rt_val, target = 0;
1351 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1352
1353 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1354 rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1355 offset = insn.getOperand(2).getImm();
1356
1357 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1358 if (!success)
1359 return false;
1360
1361 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1362 dwarf_zero_mips64 + rs, 0, &success);
1363 if (!success)
1364 return false;
1365
1366 rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1367 dwarf_zero_mips64 + rt, 0, &success);
1368 if (!success)
1369 return false;
1370
1371 if (!strcasecmp(op_name, "BEQ") || !strcasecmp(op_name, "BEQL")
1372 || !strcasecmp(op_name, "BEQ64") ) {
1373 if (rs_val == rt_val)
1374 target = pc + offset;
1375 else
1376 target = pc + 8;
1377 } else if (!strcasecmp(op_name, "BNE") || !strcasecmp(op_name, "BNEL")
1378 || !strcasecmp(op_name, "BNE64")) {
1379 if (rs_val != rt_val)
1380 target = pc + offset;
1381 else
1382 target = pc + 8;
1383 }
1384
1385 Context context;
1386 context.type = eContextRelativeBranchImmediate;
1387 context.SetImmediate(offset);
1388
1389 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1390 target);
1391 }
1392
1393 /*
1394 Emulate below MIPS Non-Compact conditional branch and link instructions.
1395 BLTZAL, BGEZAL :
1396 BLTZALL, BGEZALL : Branch likely
1397 */
Emulate_Bcond_Link(llvm::MCInst & insn)1398 bool EmulateInstructionMIPS64::Emulate_Bcond_Link(llvm::MCInst &insn) {
1399 bool success = false;
1400 uint32_t rs;
1401 int64_t offset, pc, target = 0;
1402 int64_t rs_val;
1403 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1404
1405 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1406 offset = insn.getOperand(1).getImm();
1407
1408 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1409 if (!success)
1410 return false;
1411
1412 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1413 dwarf_zero_mips64 + rs, 0, &success);
1414 if (!success)
1415 return false;
1416
1417 if (!strcasecmp(op_name, "BLTZAL") || !strcasecmp(op_name, "BLTZALL")) {
1418 if (rs_val < 0)
1419 target = pc + offset;
1420 else
1421 target = pc + 8;
1422 } else if (!strcasecmp(op_name, "BGEZAL") ||
1423 !strcasecmp(op_name, "BGEZALL")) {
1424 if (rs_val >= 0)
1425 target = pc + offset;
1426 else
1427 target = pc + 8;
1428 }
1429
1430 Context context;
1431
1432 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1433 target))
1434 return false;
1435
1436 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1437 pc + 8))
1438 return false;
1439
1440 return true;
1441 }
1442
Emulate_BAL(llvm::MCInst & insn)1443 bool EmulateInstructionMIPS64::Emulate_BAL(llvm::MCInst &insn) {
1444 bool success = false;
1445 int64_t offset, pc, target;
1446
1447 /*
1448 * BAL offset
1449 * offset = sign_ext (offset << 2)
1450 * RA = PC + 8
1451 * PC = PC + offset
1452 */
1453 offset = insn.getOperand(0).getImm();
1454
1455 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1456 if (!success)
1457 return false;
1458
1459 target = pc + offset;
1460
1461 Context context;
1462
1463 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1464 target))
1465 return false;
1466
1467 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1468 pc + 8))
1469 return false;
1470
1471 return true;
1472 }
1473
Emulate_BALC(llvm::MCInst & insn)1474 bool EmulateInstructionMIPS64::Emulate_BALC(llvm::MCInst &insn) {
1475 bool success = false;
1476 int64_t offset, pc, target;
1477
1478 /*
1479 * BALC offset
1480 * offset = sign_ext (offset << 2)
1481 * RA = PC + 4
1482 * PC = PC + 4 + offset
1483 */
1484 offset = insn.getOperand(0).getImm();
1485
1486 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1487 if (!success)
1488 return false;
1489
1490 target = pc + offset;
1491
1492 Context context;
1493
1494 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1495 target))
1496 return false;
1497
1498 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1499 pc + 4))
1500 return false;
1501
1502 return true;
1503 }
1504
1505 /*
1506 Emulate below MIPS conditional branch and link instructions.
1507 BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches
1508 */
Emulate_Bcond_Link_C(llvm::MCInst & insn)1509 bool EmulateInstructionMIPS64::Emulate_Bcond_Link_C(llvm::MCInst &insn) {
1510 bool success = false;
1511 uint32_t rs;
1512 int64_t offset, pc, rs_val, target = 0;
1513 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1514
1515 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1516 offset = insn.getOperand(1).getImm();
1517
1518 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1519 if (!success)
1520 return false;
1521
1522 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1523 dwarf_zero_mips64 + rs, 0, &success);
1524 if (!success)
1525 return false;
1526
1527 if (!strcasecmp(op_name, "BLEZALC")) {
1528 if (rs_val <= 0)
1529 target = pc + offset;
1530 else
1531 target = pc + 4;
1532 } else if (!strcasecmp(op_name, "BGEZALC")) {
1533 if (rs_val >= 0)
1534 target = pc + offset;
1535 else
1536 target = pc + 4;
1537 } else if (!strcasecmp(op_name, "BLTZALC")) {
1538 if (rs_val < 0)
1539 target = pc + offset;
1540 else
1541 target = pc + 4;
1542 } else if (!strcasecmp(op_name, "BGTZALC")) {
1543 if (rs_val > 0)
1544 target = pc + offset;
1545 else
1546 target = pc + 4;
1547 } else if (!strcasecmp(op_name, "BEQZALC")) {
1548 if (rs_val == 0)
1549 target = pc + offset;
1550 else
1551 target = pc + 4;
1552 } else if (!strcasecmp(op_name, "BNEZALC")) {
1553 if (rs_val != 0)
1554 target = pc + offset;
1555 else
1556 target = pc + 4;
1557 }
1558
1559 Context context;
1560
1561 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1562 target))
1563 return false;
1564
1565 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1566 pc + 4))
1567 return false;
1568
1569 return true;
1570 }
1571
1572 /*
1573 Emulate below MIPS branch instructions.
1574 BLTZL, BGEZL, BGTZL, BLEZL : Branch likely
1575 BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches
1576 */
Emulate_BXX_2ops(llvm::MCInst & insn)1577 bool EmulateInstructionMIPS64::Emulate_BXX_2ops(llvm::MCInst &insn) {
1578 bool success = false;
1579 uint32_t rs;
1580 int64_t offset, pc, rs_val, target = 0;
1581 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1582
1583 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1584 offset = insn.getOperand(1).getImm();
1585
1586 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1587 if (!success)
1588 return false;
1589
1590 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1591 dwarf_zero_mips64 + rs, 0, &success);
1592 if (!success)
1593 return false;
1594
1595 if (!strcasecmp(op_name, "BLTZL") || !strcasecmp(op_name, "BLTZ")
1596 || !strcasecmp(op_name, "BLTZ64")) {
1597 if (rs_val < 0)
1598 target = pc + offset;
1599 else
1600 target = pc + 8;
1601 } else if (!strcasecmp(op_name, "BGEZL") || !strcasecmp(op_name, "BGEZ")
1602 || !strcasecmp(op_name, "BGEZ64")) {
1603 if (rs_val >= 0)
1604 target = pc + offset;
1605 else
1606 target = pc + 8;
1607 } else if (!strcasecmp(op_name, "BGTZL") || !strcasecmp(op_name, "BGTZ")
1608 || !strcasecmp(op_name, "BGTZ64")) {
1609 if (rs_val > 0)
1610 target = pc + offset;
1611 else
1612 target = pc + 8;
1613 } else if (!strcasecmp(op_name, "BLEZL") || !strcasecmp(op_name, "BLEZ")
1614 || !strcasecmp(op_name, "BLEZ64")) {
1615 if (rs_val <= 0)
1616 target = pc + offset;
1617 else
1618 target = pc + 8;
1619 }
1620
1621 Context context;
1622 context.type = eContextRelativeBranchImmediate;
1623 context.SetImmediate(offset);
1624
1625 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1626 target);
1627 }
1628
Emulate_BC(llvm::MCInst & insn)1629 bool EmulateInstructionMIPS64::Emulate_BC(llvm::MCInst &insn) {
1630 bool success = false;
1631 int64_t offset, pc, target;
1632
1633 /*
1634 * BC offset
1635 * offset = sign_ext (offset << 2)
1636 * PC = PC + 4 + offset
1637 */
1638 offset = insn.getOperand(0).getImm();
1639
1640 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1641 if (!success)
1642 return false;
1643
1644 target = pc + offset;
1645
1646 Context context;
1647
1648 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1649 target);
1650 }
1651
IsAdd64bitOverflow(int64_t a,int64_t b)1652 static int IsAdd64bitOverflow(int64_t a, int64_t b) {
1653 int64_t r = (uint64_t)a + (uint64_t)b;
1654 return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
1655 }
1656
1657 /*
1658 Emulate below MIPS branch instructions.
1659 BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch
1660 instructions with no delay slot
1661 */
Emulate_BXX_3ops_C(llvm::MCInst & insn)1662 bool EmulateInstructionMIPS64::Emulate_BXX_3ops_C(llvm::MCInst &insn) {
1663 bool success = false;
1664 uint32_t rs, rt;
1665 int64_t offset, pc, rs_val, rt_val, target = 0;
1666 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1667 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
1668
1669 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1670 rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1671 offset = insn.getOperand(2).getImm();
1672
1673 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1674 if (!success)
1675 return false;
1676
1677 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1678 dwarf_zero_mips64 + rs, 0, &success);
1679 if (!success)
1680 return false;
1681
1682 rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1683 dwarf_zero_mips64 + rt, 0, &success);
1684 if (!success)
1685 return false;
1686
1687 if (!strcasecmp(op_name, "BEQC") || !strcasecmp(op_name, "BEQC64")) {
1688 if (rs_val == rt_val)
1689 target = pc + offset;
1690 else
1691 target = pc + 4;
1692 } else if (!strcasecmp(op_name, "BNEC") || !strcasecmp(op_name, "BNEC64")) {
1693 if (rs_val != rt_val)
1694 target = pc + offset;
1695 else
1696 target = pc + 4;
1697 } else if (!strcasecmp(op_name, "BLTC") || !strcasecmp(op_name, "BLTC64")) {
1698 if (rs_val < rt_val)
1699 target = pc + offset;
1700 else
1701 target = pc + 4;
1702 } else if (!strcasecmp(op_name, "BGEC64") || !strcasecmp(op_name, "BGEC")) {
1703 if (rs_val >= rt_val)
1704 target = pc + offset;
1705 else
1706 target = pc + 4;
1707 } else if (!strcasecmp(op_name, "BLTUC") || !strcasecmp(op_name, "BLTUC64")) {
1708 if (rs_val < rt_val)
1709 target = pc + offset;
1710 else
1711 target = pc + 4;
1712 } else if (!strcasecmp(op_name, "BGEUC") || !strcasecmp(op_name, "BGEUC64")) {
1713 if ((uint32_t)rs_val >= (uint32_t)rt_val)
1714 target = pc + offset;
1715 else
1716 target = pc + 4;
1717 } else if (!strcasecmp(op_name, "BOVC")) {
1718 if (IsAdd64bitOverflow(rs_val, rt_val))
1719 target = pc + offset;
1720 else
1721 target = pc + 4;
1722 } else if (!strcasecmp(op_name, "BNVC")) {
1723 if (!IsAdd64bitOverflow(rs_val, rt_val))
1724 target = pc + offset;
1725 else
1726 target = pc + 4;
1727 }
1728
1729 Context context;
1730 context.type = eContextRelativeBranchImmediate;
1731 context.SetImmediate(current_inst_size + offset);
1732
1733 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1734 target);
1735 }
1736
1737 /*
1738 Emulate below MIPS branch instructions.
1739 BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches
1740 */
Emulate_BXX_2ops_C(llvm::MCInst & insn)1741 bool EmulateInstructionMIPS64::Emulate_BXX_2ops_C(llvm::MCInst &insn) {
1742 bool success = false;
1743 uint32_t rs;
1744 int64_t offset, pc, target = 0;
1745 int64_t rs_val;
1746 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1747 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
1748
1749 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1750 offset = insn.getOperand(1).getImm();
1751
1752 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1753 if (!success)
1754 return false;
1755
1756 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1757 dwarf_zero_mips64 + rs, 0, &success);
1758 if (!success)
1759 return false;
1760
1761 if (!strcasecmp(op_name, "BLTZC") || !strcasecmp(op_name, "BLTZC64")) {
1762 if (rs_val < 0)
1763 target = pc + offset;
1764 else
1765 target = pc + 4;
1766 } else if (!strcasecmp(op_name, "BLEZC") || !strcasecmp(op_name, "BLEZC64")) {
1767 if (rs_val <= 0)
1768 target = pc + offset;
1769 else
1770 target = pc + 4;
1771 } else if (!strcasecmp(op_name, "BGEZC") || !strcasecmp(op_name, "BGEZC64")) {
1772 if (rs_val >= 0)
1773 target = pc + offset;
1774 else
1775 target = pc + 4;
1776 } else if (!strcasecmp(op_name, "BGTZC") || !strcasecmp(op_name, "BGTZC64")) {
1777 if (rs_val > 0)
1778 target = pc + offset;
1779 else
1780 target = pc + 4;
1781 } else if (!strcasecmp(op_name, "BEQZC") || !strcasecmp(op_name, "BEQZC64")) {
1782 if (rs_val == 0)
1783 target = pc + offset;
1784 else
1785 target = pc + 4;
1786 } else if (!strcasecmp(op_name, "BNEZC") || !strcasecmp(op_name, "BNEZC64")) {
1787 if (rs_val != 0)
1788 target = pc + offset;
1789 else
1790 target = pc + 4;
1791 }
1792
1793 Context context;
1794 context.type = eContextRelativeBranchImmediate;
1795 context.SetImmediate(current_inst_size + offset);
1796
1797 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1798 target);
1799 }
1800
Emulate_J(llvm::MCInst & insn)1801 bool EmulateInstructionMIPS64::Emulate_J(llvm::MCInst &insn) {
1802 bool success = false;
1803 uint64_t offset, pc;
1804
1805 /*
1806 * J offset
1807 * offset = sign_ext (offset << 2)
1808 * PC = PC[63-28] | offset
1809 */
1810 offset = insn.getOperand(0).getImm();
1811
1812 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1813 if (!success)
1814 return false;
1815
1816 /* This is a PC-region branch and not PC-relative */
1817 pc = (pc & 0xFFFFFFFFF0000000ULL) | offset;
1818
1819 Context context;
1820
1821 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1822 pc);
1823 }
1824
Emulate_JAL(llvm::MCInst & insn)1825 bool EmulateInstructionMIPS64::Emulate_JAL(llvm::MCInst &insn) {
1826 bool success = false;
1827 uint64_t offset, target, pc;
1828
1829 /*
1830 * JAL offset
1831 * offset = sign_ext (offset << 2)
1832 * PC = PC[63-28] | offset
1833 */
1834 offset = insn.getOperand(0).getImm();
1835
1836 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1837 if (!success)
1838 return false;
1839
1840 /* This is a PC-region branch and not PC-relative */
1841 target = (pc & 0xFFFFFFFFF0000000ULL) | offset;
1842
1843 Context context;
1844
1845 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1846 target))
1847 return false;
1848
1849 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1850 pc + 8))
1851 return false;
1852
1853 return true;
1854 }
1855
Emulate_JALR(llvm::MCInst & insn)1856 bool EmulateInstructionMIPS64::Emulate_JALR(llvm::MCInst &insn) {
1857 bool success = false;
1858 uint32_t rs, rt;
1859 uint64_t pc, rs_val;
1860
1861 /*
1862 * JALR rt, rs
1863 * GPR[rt] = PC + 8
1864 * PC = GPR[rs]
1865 */
1866 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1867 rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1868
1869 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1870 if (!success)
1871 return false;
1872
1873 rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0,
1874 &success);
1875 if (!success)
1876 return false;
1877
1878 Context context;
1879
1880 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1881 rs_val))
1882 return false;
1883
1884 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1885 dwarf_zero_mips64 + rt, pc + 8))
1886 return false;
1887
1888 return true;
1889 }
1890
Emulate_JIALC(llvm::MCInst & insn)1891 bool EmulateInstructionMIPS64::Emulate_JIALC(llvm::MCInst &insn) {
1892 bool success = false;
1893 uint32_t rt;
1894 int64_t target, offset, pc, rt_val;
1895
1896 /*
1897 * JIALC rt, offset
1898 * offset = sign_ext (offset)
1899 * PC = GPR[rt] + offset
1900 * RA = PC + 4
1901 */
1902 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1903 offset = insn.getOperand(1).getImm();
1904
1905 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1906 if (!success)
1907 return false;
1908
1909 rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1910 dwarf_zero_mips64 + rt, 0, &success);
1911 if (!success)
1912 return false;
1913
1914 target = rt_val + offset;
1915
1916 Context context;
1917
1918 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1919 target))
1920 return false;
1921
1922 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1923 pc + 4))
1924 return false;
1925
1926 return true;
1927 }
1928
Emulate_JIC(llvm::MCInst & insn)1929 bool EmulateInstructionMIPS64::Emulate_JIC(llvm::MCInst &insn) {
1930 bool success = false;
1931 uint32_t rt;
1932 int64_t target, offset, rt_val;
1933
1934 /*
1935 * JIC rt, offset
1936 * offset = sign_ext (offset)
1937 * PC = GPR[rt] + offset
1938 */
1939 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1940 offset = insn.getOperand(1).getImm();
1941
1942 rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1943 dwarf_zero_mips64 + rt, 0, &success);
1944 if (!success)
1945 return false;
1946
1947 target = rt_val + offset;
1948
1949 Context context;
1950
1951 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1952 target);
1953 }
1954
Emulate_JR(llvm::MCInst & insn)1955 bool EmulateInstructionMIPS64::Emulate_JR(llvm::MCInst &insn) {
1956 bool success = false;
1957 uint32_t rs;
1958 uint64_t rs_val;
1959
1960 /*
1961 * JR rs
1962 * PC = GPR[rs]
1963 */
1964 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1965
1966 rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0,
1967 &success);
1968 if (!success)
1969 return false;
1970
1971 Context context;
1972
1973 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1974 rs_val);
1975 }
1976
1977 /*
1978 Emulate Branch on FP True/False
1979 BC1F, BC1FL : Branch on FP False (L stands for branch likely)
1980 BC1T, BC1TL : Branch on FP True (L stands for branch likely)
1981 */
Emulate_FP_branch(llvm::MCInst & insn)1982 bool EmulateInstructionMIPS64::Emulate_FP_branch(llvm::MCInst &insn) {
1983 bool success = false;
1984 uint32_t cc, fcsr;
1985 int64_t pc, offset, target = 0;
1986 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
1987
1988 /*
1989 * BC1F cc, offset
1990 * condition <- (FPConditionCode(cc) == 0)
1991 * if condition then
1992 * offset = sign_ext (offset)
1993 * PC = PC + offset
1994 */
1995 cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1996 offset = insn.getOperand(1).getImm();
1997
1998 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1999 if (!success)
2000 return false;
2001
2002 fcsr =
2003 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
2004 if (!success)
2005 return false;
2006
2007 /* fcsr[23], fcsr[25-31] are vaild condition bits */
2008 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2009
2010 if (!strcasecmp(op_name, "BC1F") || !strcasecmp(op_name, "BC1FL")) {
2011 if ((fcsr & (1 << cc)) == 0)
2012 target = pc + offset;
2013 else
2014 target = pc + 8;
2015 } else if (!strcasecmp(op_name, "BC1T") || !strcasecmp(op_name, "BC1TL")) {
2016 if ((fcsr & (1 << cc)) != 0)
2017 target = pc + offset;
2018 else
2019 target = pc + 8;
2020 }
2021
2022 Context context;
2023
2024 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2025 target);
2026 }
2027
Emulate_BC1EQZ(llvm::MCInst & insn)2028 bool EmulateInstructionMIPS64::Emulate_BC1EQZ(llvm::MCInst &insn) {
2029 bool success = false;
2030 uint32_t ft;
2031 uint64_t ft_val;
2032 int64_t target, pc, offset;
2033
2034 /*
2035 * BC1EQZ ft, offset
2036 * condition <- (FPR[ft].bit0 == 0)
2037 * if condition then
2038 * offset = sign_ext (offset)
2039 * PC = PC + 4 + offset
2040 */
2041 ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2042 offset = insn.getOperand(1).getImm();
2043
2044 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2045 if (!success)
2046 return false;
2047
2048 ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0,
2049 &success);
2050 if (!success)
2051 return false;
2052
2053 if ((ft_val & 1) == 0)
2054 target = pc + 4 + offset;
2055 else
2056 target = pc + 8;
2057
2058 Context context;
2059
2060 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2061 target);
2062 }
2063
Emulate_BC1NEZ(llvm::MCInst & insn)2064 bool EmulateInstructionMIPS64::Emulate_BC1NEZ(llvm::MCInst &insn) {
2065 bool success = false;
2066 uint32_t ft;
2067 uint64_t ft_val;
2068 int64_t target, pc, offset;
2069
2070 /*
2071 * BC1NEZ ft, offset
2072 * condition <- (FPR[ft].bit0 != 0)
2073 * if condition then
2074 * offset = sign_ext (offset)
2075 * PC = PC + 4 + offset
2076 */
2077 ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2078 offset = insn.getOperand(1).getImm();
2079
2080 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2081 if (!success)
2082 return false;
2083
2084 ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0,
2085 &success);
2086 if (!success)
2087 return false;
2088
2089 if ((ft_val & 1) != 0)
2090 target = pc + 4 + offset;
2091 else
2092 target = pc + 8;
2093
2094 Context context;
2095
2096 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2097 target);
2098 }
2099
2100 /*
2101 Emulate MIPS-3D Branch instructions
2102 BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes
2103 False/True
2104 BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes
2105 False/True
2106 */
Emulate_3D_branch(llvm::MCInst & insn)2107 bool EmulateInstructionMIPS64::Emulate_3D_branch(llvm::MCInst &insn) {
2108 bool success = false;
2109 uint32_t cc, fcsr;
2110 int64_t pc, offset, target = 0;
2111 const char *op_name = m_insn_info->getName(insn.getOpcode()).data();
2112
2113 cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2114 offset = insn.getOperand(1).getImm();
2115
2116 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2117 if (!success)
2118 return false;
2119
2120 fcsr = (uint32_t)ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips64,
2121 0, &success);
2122 if (!success)
2123 return false;
2124
2125 /* fcsr[23], fcsr[25-31] are vaild condition bits */
2126 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2127
2128 if (!strcasecmp(op_name, "BC1ANY2F")) {
2129 /* if any one bit is 0 */
2130 if (((fcsr >> cc) & 3) != 3)
2131 target = pc + offset;
2132 else
2133 target = pc + 8;
2134 } else if (!strcasecmp(op_name, "BC1ANY2T")) {
2135 /* if any one bit is 1 */
2136 if (((fcsr >> cc) & 3) != 0)
2137 target = pc + offset;
2138 else
2139 target = pc + 8;
2140 } else if (!strcasecmp(op_name, "BC1ANY4F")) {
2141 /* if any one bit is 0 */
2142 if (((fcsr >> cc) & 0xf) != 0xf)
2143 target = pc + offset;
2144 else
2145 target = pc + 8;
2146 } else if (!strcasecmp(op_name, "BC1ANY4T")) {
2147 /* if any one bit is 1 */
2148 if (((fcsr >> cc) & 0xf) != 0)
2149 target = pc + offset;
2150 else
2151 target = pc + 8;
2152 }
2153
2154 Context context;
2155
2156 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2157 target);
2158 }
2159
Emulate_BNZB(llvm::MCInst & insn)2160 bool EmulateInstructionMIPS64::Emulate_BNZB(llvm::MCInst &insn) {
2161 return Emulate_MSA_Branch_DF(insn, 1, true);
2162 }
2163
Emulate_BNZH(llvm::MCInst & insn)2164 bool EmulateInstructionMIPS64::Emulate_BNZH(llvm::MCInst &insn) {
2165 return Emulate_MSA_Branch_DF(insn, 2, true);
2166 }
2167
Emulate_BNZW(llvm::MCInst & insn)2168 bool EmulateInstructionMIPS64::Emulate_BNZW(llvm::MCInst &insn) {
2169 return Emulate_MSA_Branch_DF(insn, 4, true);
2170 }
2171
Emulate_BNZD(llvm::MCInst & insn)2172 bool EmulateInstructionMIPS64::Emulate_BNZD(llvm::MCInst &insn) {
2173 return Emulate_MSA_Branch_DF(insn, 8, true);
2174 }
2175
Emulate_BZB(llvm::MCInst & insn)2176 bool EmulateInstructionMIPS64::Emulate_BZB(llvm::MCInst &insn) {
2177 return Emulate_MSA_Branch_DF(insn, 1, false);
2178 }
2179
Emulate_BZH(llvm::MCInst & insn)2180 bool EmulateInstructionMIPS64::Emulate_BZH(llvm::MCInst &insn) {
2181 return Emulate_MSA_Branch_DF(insn, 2, false);
2182 }
2183
Emulate_BZW(llvm::MCInst & insn)2184 bool EmulateInstructionMIPS64::Emulate_BZW(llvm::MCInst &insn) {
2185 return Emulate_MSA_Branch_DF(insn, 4, false);
2186 }
2187
Emulate_BZD(llvm::MCInst & insn)2188 bool EmulateInstructionMIPS64::Emulate_BZD(llvm::MCInst &insn) {
2189 return Emulate_MSA_Branch_DF(insn, 8, false);
2190 }
2191
Emulate_MSA_Branch_DF(llvm::MCInst & insn,int element_byte_size,bool bnz)2192 bool EmulateInstructionMIPS64::Emulate_MSA_Branch_DF(llvm::MCInst &insn,
2193 int element_byte_size,
2194 bool bnz) {
2195 bool success = false, branch_hit = true;
2196 int64_t target = 0;
2197 RegisterValue reg_value;
2198 const uint8_t *ptr = NULL;
2199
2200 uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2201 int64_t offset = insn.getOperand(1).getImm();
2202
2203 int64_t pc =
2204 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2205 if (!success)
2206 return false;
2207
2208 if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value))
2209 ptr = (const uint8_t *)reg_value.GetBytes();
2210 else
2211 return false;
2212
2213 for (int i = 0; i < 16 / element_byte_size; i++) {
2214 switch (element_byte_size) {
2215 case 1:
2216 if ((*ptr == 0 && bnz) || (*ptr != 0 && !bnz))
2217 branch_hit = false;
2218 break;
2219 case 2:
2220 if ((*(const uint16_t *)ptr == 0 && bnz) ||
2221 (*(const uint16_t *)ptr != 0 && !bnz))
2222 branch_hit = false;
2223 break;
2224 case 4:
2225 if ((*(const uint32_t *)ptr == 0 && bnz) ||
2226 (*(const uint32_t *)ptr != 0 && !bnz))
2227 branch_hit = false;
2228 break;
2229 case 8:
2230 if ((*(const uint64_t *)ptr == 0 && bnz) ||
2231 (*(const uint64_t *)ptr != 0 && !bnz))
2232 branch_hit = false;
2233 break;
2234 }
2235 if (!branch_hit)
2236 break;
2237 ptr = ptr + element_byte_size;
2238 }
2239
2240 if (branch_hit)
2241 target = pc + offset;
2242 else
2243 target = pc + 8;
2244
2245 Context context;
2246 context.type = eContextRelativeBranchImmediate;
2247
2248 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2249 target);
2250 }
2251
Emulate_BNZV(llvm::MCInst & insn)2252 bool EmulateInstructionMIPS64::Emulate_BNZV(llvm::MCInst &insn) {
2253 return Emulate_MSA_Branch_V(insn, true);
2254 }
2255
Emulate_BZV(llvm::MCInst & insn)2256 bool EmulateInstructionMIPS64::Emulate_BZV(llvm::MCInst &insn) {
2257 return Emulate_MSA_Branch_V(insn, false);
2258 }
2259
Emulate_MSA_Branch_V(llvm::MCInst & insn,bool bnz)2260 bool EmulateInstructionMIPS64::Emulate_MSA_Branch_V(llvm::MCInst &insn,
2261 bool bnz) {
2262 bool success = false;
2263 int64_t target = 0;
2264 llvm::APInt wr_val = llvm::APInt::getNullValue(128);
2265 llvm::APInt fail_value = llvm::APInt::getMaxValue(128);
2266 llvm::APInt zero_value = llvm::APInt::getNullValue(128);
2267 RegisterValue reg_value;
2268
2269 uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2270 int64_t offset = insn.getOperand(1).getImm();
2271
2272 int64_t pc =
2273 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2274 if (!success)
2275 return false;
2276
2277 if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value))
2278 wr_val = reg_value.GetAsUInt128(fail_value);
2279 else
2280 return false;
2281
2282 if ((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) ||
2283 (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz))
2284 target = pc + offset;
2285 else
2286 target = pc + 8;
2287
2288 Context context;
2289 context.type = eContextRelativeBranchImmediate;
2290
2291 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2292 target);
2293 }
2294
Emulate_LDST_Imm(llvm::MCInst & insn)2295 bool EmulateInstructionMIPS64::Emulate_LDST_Imm(llvm::MCInst &insn) {
2296 bool success = false;
2297 uint32_t base;
2298 int64_t imm, address;
2299 Context bad_vaddr_context;
2300
2301 uint32_t num_operands = insn.getNumOperands();
2302 base =
2303 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
2304 imm = insn.getOperand(num_operands - 1).getImm();
2305
2306 RegisterInfo reg_info_base;
2307 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base,
2308 reg_info_base))
2309 return false;
2310
2311 /* read base register */
2312 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0,
2313 &success);
2314 if (!success)
2315 return false;
2316
2317 /* destination address */
2318 address = address + imm;
2319
2320 /* Set the bad_vaddr register with base address used in the instruction */
2321 bad_vaddr_context.type = eContextInvalid;
2322 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
2323 address);
2324
2325 return true;
2326 }
2327
Emulate_LDST_Reg(llvm::MCInst & insn)2328 bool EmulateInstructionMIPS64::Emulate_LDST_Reg(llvm::MCInst &insn) {
2329 bool success = false;
2330 uint32_t base, index;
2331 int64_t address, index_address;
2332 Context bad_vaddr_context;
2333
2334 uint32_t num_operands = insn.getNumOperands();
2335 base =
2336 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
2337 index =
2338 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 1).getReg());
2339
2340 RegisterInfo reg_info_base, reg_info_index;
2341 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base,
2342 reg_info_base))
2343 return false;
2344
2345 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + index,
2346 reg_info_index))
2347 return false;
2348
2349 /* read base register */
2350 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0,
2351 &success);
2352 if (!success)
2353 return false;
2354
2355 /* read index register */
2356 index_address = ReadRegisterUnsigned(eRegisterKindDWARF,
2357 dwarf_zero_mips + index, 0, &success);
2358 if (!success)
2359 return false;
2360
2361 /* destination address */
2362 address = address + index_address;
2363
2364 /* Set the bad_vaddr register with base address used in the instruction */
2365 bad_vaddr_context.type = eContextInvalid;
2366 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
2367 address);
2368
2369 return true;
2370 }
2371