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