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/Core/RegisterValue.h" 18 #include "lldb/Host/PosixApi.h" 19 #include "lldb/Symbol/UnwindPlan.h" 20 #include "lldb/Utility/ArchSpec.h" 21 #include "lldb/Utility/ConstString.h" 22 #include "lldb/Utility/DataExtractor.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 1095 // LUI, (D)ADDIU,(D)SUBU instructions in prolog. 1096 // Example 1097 // lui $1, 0x2 1098 // daddiu $1, $1, -0x5920 1099 // dsubu $sp, $sp, $1 1100 // In this case, (D)ADDIU dst and src will be same and not equal to sp 1101 if (dst == src) { 1102 Context context; 1103 1104 /* read <src> register */ 1105 const int64_t src_opd_val = ReadRegisterUnsigned( 1106 eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success); 1107 if (!success) 1108 return false; 1109 1110 /* Check if this is daddiu sp, sp, imm16 */ 1111 if (dst == dwarf_sp_mips64) { 1112 uint64_t result = src_opd_val + imm; 1113 RegisterInfo reg_info_sp; 1114 1115 if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp)) 1116 context.SetRegisterPlusOffset(reg_info_sp, imm); 1117 1118 /* We are allocating bytes on stack */ 1119 context.type = eContextAdjustStackPointer; 1120 1121 WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips64, 1122 result); 1123 return true; 1124 } 1125 1126 imm += src_opd_val; 1127 context.SetImmediateSigned(imm); 1128 context.type = eContextImmediate; 1129 1130 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, 1131 dwarf_zero_mips64 + dst, imm)) 1132 return false; 1133 } 1134 1135 return true; 1136 } 1137 1138 bool EmulateInstructionMIPS64::Emulate_SD(llvm::MCInst &insn) { 1139 uint64_t address; 1140 RegisterInfo reg_info_base; 1141 RegisterInfo reg_info_src; 1142 bool success = false; 1143 uint32_t imm16 = insn.getOperand(2).getImm(); 1144 uint64_t imm = SignedBits(imm16, 15, 0); 1145 uint32_t src, base; 1146 Context bad_vaddr_context; 1147 1148 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1149 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); 1150 1151 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base, 1152 reg_info_base) || 1153 !GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src, 1154 reg_info_src)) 1155 return false; 1156 1157 /* read SP */ 1158 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + base, 1159 0, &success); 1160 if (!success) 1161 return false; 1162 1163 /* destination address */ 1164 address = address + imm; 1165 1166 /* We look for sp based non-volatile register stores */ 1167 if (nonvolatile_reg_p(src)) { 1168 Context context; 1169 RegisterValue data_src; 1170 context.type = eContextPushRegisterOnStack; 1171 context.SetRegisterToRegisterPlusOffset(reg_info_src, reg_info_base, 0); 1172 1173 uint8_t buffer[RegisterValue::kMaxRegisterByteSize]; 1174 Status error; 1175 1176 if (!ReadRegister(®_info_base, data_src)) 1177 return false; 1178 1179 if (data_src.GetAsMemoryData(®_info_src, buffer, reg_info_src.byte_size, 1180 eByteOrderLittle, error) == 0) 1181 return false; 1182 1183 if (!WriteMemory(context, address, buffer, reg_info_src.byte_size)) 1184 return false; 1185 } 1186 1187 /* Set the bad_vaddr register with base address used in the instruction */ 1188 bad_vaddr_context.type = eContextInvalid; 1189 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64, 1190 address); 1191 1192 return true; 1193 } 1194 1195 bool EmulateInstructionMIPS64::Emulate_LD(llvm::MCInst &insn) { 1196 bool success = false; 1197 uint32_t src, base; 1198 int64_t imm, address; 1199 Context bad_vaddr_context; 1200 1201 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1202 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); 1203 imm = insn.getOperand(2).getImm(); 1204 1205 RegisterInfo reg_info_base; 1206 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base, 1207 reg_info_base)) 1208 return false; 1209 1210 /* read base register */ 1211 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + base, 1212 0, &success); 1213 if (!success) 1214 return false; 1215 1216 /* destination address */ 1217 address = address + imm; 1218 1219 /* Set the bad_vaddr register with base address used in the instruction */ 1220 bad_vaddr_context.type = eContextInvalid; 1221 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64, 1222 address); 1223 1224 if (nonvolatile_reg_p(src)) { 1225 RegisterValue data_src; 1226 RegisterInfo reg_info_src; 1227 1228 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src, 1229 reg_info_src)) 1230 return false; 1231 1232 Context context; 1233 context.type = eContextRegisterLoad; 1234 1235 if (!WriteRegister(context, ®_info_src, data_src)) 1236 return false; 1237 1238 return true; 1239 } 1240 1241 return false; 1242 } 1243 1244 bool EmulateInstructionMIPS64::Emulate_LUI(llvm::MCInst &insn) { 1245 // LUI rt, immediate 1246 // GPR[rt] <- sign_extend(immediate << 16) 1247 1248 const uint32_t imm32 = insn.getOperand(1).getImm() << 16; 1249 int64_t imm = SignedBits(imm32, 31, 0); 1250 uint8_t rt; 1251 Context context; 1252 1253 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1254 context.SetImmediateSigned(imm); 1255 context.type = eContextImmediate; 1256 1257 if (WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_zero_mips64 + rt, 1258 imm)) 1259 return true; 1260 1261 return false; 1262 } 1263 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 */ 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 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1390 target)) 1391 return false; 1392 1393 return true; 1394 } 1395 1396 /* 1397 Emulate below MIPS Non-Compact conditional branch and link instructions. 1398 BLTZAL, BGEZAL : 1399 BLTZALL, BGEZALL : Branch likely 1400 */ 1401 bool EmulateInstructionMIPS64::Emulate_Bcond_Link(llvm::MCInst &insn) { 1402 bool success = false; 1403 uint32_t rs; 1404 int64_t offset, pc, target = 0; 1405 int64_t rs_val; 1406 const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); 1407 1408 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1409 offset = insn.getOperand(1).getImm(); 1410 1411 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1412 if (!success) 1413 return false; 1414 1415 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, 1416 dwarf_zero_mips64 + rs, 0, &success); 1417 if (!success) 1418 return false; 1419 1420 if (!strcasecmp(op_name, "BLTZAL") || !strcasecmp(op_name, "BLTZALL")) { 1421 if (rs_val < 0) 1422 target = pc + offset; 1423 else 1424 target = pc + 8; 1425 } else if (!strcasecmp(op_name, "BGEZAL") || 1426 !strcasecmp(op_name, "BGEZALL")) { 1427 if (rs_val >= 0) 1428 target = pc + offset; 1429 else 1430 target = pc + 8; 1431 } 1432 1433 Context context; 1434 1435 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1436 target)) 1437 return false; 1438 1439 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64, 1440 pc + 8)) 1441 return false; 1442 1443 return true; 1444 } 1445 1446 bool EmulateInstructionMIPS64::Emulate_BAL(llvm::MCInst &insn) { 1447 bool success = false; 1448 int64_t offset, pc, target; 1449 1450 /* 1451 * BAL offset 1452 * offset = sign_ext (offset << 2) 1453 * RA = PC + 8 1454 * PC = PC + offset 1455 */ 1456 offset = insn.getOperand(0).getImm(); 1457 1458 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1459 if (!success) 1460 return false; 1461 1462 target = pc + offset; 1463 1464 Context context; 1465 1466 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1467 target)) 1468 return false; 1469 1470 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64, 1471 pc + 8)) 1472 return false; 1473 1474 return true; 1475 } 1476 1477 bool EmulateInstructionMIPS64::Emulate_BALC(llvm::MCInst &insn) { 1478 bool success = false; 1479 int64_t offset, pc, target; 1480 1481 /* 1482 * BALC offset 1483 * offset = sign_ext (offset << 2) 1484 * RA = PC + 4 1485 * PC = PC + 4 + offset 1486 */ 1487 offset = insn.getOperand(0).getImm(); 1488 1489 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1490 if (!success) 1491 return false; 1492 1493 target = pc + offset; 1494 1495 Context context; 1496 1497 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1498 target)) 1499 return false; 1500 1501 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64, 1502 pc + 4)) 1503 return false; 1504 1505 return true; 1506 } 1507 1508 /* 1509 Emulate below MIPS conditional branch and link instructions. 1510 BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches 1511 */ 1512 bool EmulateInstructionMIPS64::Emulate_Bcond_Link_C(llvm::MCInst &insn) { 1513 bool success = false; 1514 uint32_t rs; 1515 int64_t offset, pc, rs_val, target = 0; 1516 const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); 1517 1518 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1519 offset = insn.getOperand(1).getImm(); 1520 1521 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1522 if (!success) 1523 return false; 1524 1525 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, 1526 dwarf_zero_mips64 + rs, 0, &success); 1527 if (!success) 1528 return false; 1529 1530 if (!strcasecmp(op_name, "BLEZALC")) { 1531 if (rs_val <= 0) 1532 target = pc + offset; 1533 else 1534 target = pc + 4; 1535 } else if (!strcasecmp(op_name, "BGEZALC")) { 1536 if (rs_val >= 0) 1537 target = pc + offset; 1538 else 1539 target = pc + 4; 1540 } else if (!strcasecmp(op_name, "BLTZALC")) { 1541 if (rs_val < 0) 1542 target = pc + offset; 1543 else 1544 target = pc + 4; 1545 } else if (!strcasecmp(op_name, "BGTZALC")) { 1546 if (rs_val > 0) 1547 target = pc + offset; 1548 else 1549 target = pc + 4; 1550 } else if (!strcasecmp(op_name, "BEQZALC")) { 1551 if (rs_val == 0) 1552 target = pc + offset; 1553 else 1554 target = pc + 4; 1555 } else if (!strcasecmp(op_name, "BNEZALC")) { 1556 if (rs_val != 0) 1557 target = pc + offset; 1558 else 1559 target = pc + 4; 1560 } 1561 1562 Context context; 1563 1564 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1565 target)) 1566 return false; 1567 1568 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64, 1569 pc + 4)) 1570 return false; 1571 1572 return true; 1573 } 1574 1575 /* 1576 Emulate below MIPS branch instructions. 1577 BLTZL, BGEZL, BGTZL, BLEZL : Branch likely 1578 BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches 1579 */ 1580 bool EmulateInstructionMIPS64::Emulate_BXX_2ops(llvm::MCInst &insn) { 1581 bool success = false; 1582 uint32_t rs; 1583 int64_t offset, pc, rs_val, target = 0; 1584 const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); 1585 1586 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1587 offset = insn.getOperand(1).getImm(); 1588 1589 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1590 if (!success) 1591 return false; 1592 1593 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, 1594 dwarf_zero_mips64 + rs, 0, &success); 1595 if (!success) 1596 return false; 1597 1598 if (!strcasecmp(op_name, "BLTZL") || !strcasecmp(op_name, "BLTZ") 1599 || !strcasecmp(op_name, "BLTZ64")) { 1600 if (rs_val < 0) 1601 target = pc + offset; 1602 else 1603 target = pc + 8; 1604 } else if (!strcasecmp(op_name, "BGEZL") || !strcasecmp(op_name, "BGEZ") 1605 || !strcasecmp(op_name, "BGEZ64")) { 1606 if (rs_val >= 0) 1607 target = pc + offset; 1608 else 1609 target = pc + 8; 1610 } else if (!strcasecmp(op_name, "BGTZL") || !strcasecmp(op_name, "BGTZ") 1611 || !strcasecmp(op_name, "BGTZ64")) { 1612 if (rs_val > 0) 1613 target = pc + offset; 1614 else 1615 target = pc + 8; 1616 } else if (!strcasecmp(op_name, "BLEZL") || !strcasecmp(op_name, "BLEZ") 1617 || !strcasecmp(op_name, "BLEZ64")) { 1618 if (rs_val <= 0) 1619 target = pc + offset; 1620 else 1621 target = pc + 8; 1622 } 1623 1624 Context context; 1625 context.type = eContextRelativeBranchImmediate; 1626 context.SetImmediate(offset); 1627 1628 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1629 target)) 1630 return false; 1631 1632 return true; 1633 } 1634 1635 bool EmulateInstructionMIPS64::Emulate_BC(llvm::MCInst &insn) { 1636 bool success = false; 1637 int64_t offset, pc, target; 1638 1639 /* 1640 * BC offset 1641 * offset = sign_ext (offset << 2) 1642 * PC = PC + 4 + offset 1643 */ 1644 offset = insn.getOperand(0).getImm(); 1645 1646 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1647 if (!success) 1648 return false; 1649 1650 target = pc + offset; 1651 1652 Context context; 1653 1654 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1655 target)) 1656 return false; 1657 1658 return true; 1659 } 1660 1661 static int IsAdd64bitOverflow(int64_t a, int64_t b) { 1662 int64_t r = (uint64_t)a + (uint64_t)b; 1663 return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0); 1664 } 1665 1666 /* 1667 Emulate below MIPS branch instructions. 1668 BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch 1669 instructions with no delay slot 1670 */ 1671 bool EmulateInstructionMIPS64::Emulate_BXX_3ops_C(llvm::MCInst &insn) { 1672 bool success = false; 1673 uint32_t rs, rt; 1674 int64_t offset, pc, rs_val, rt_val, target = 0; 1675 const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); 1676 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); 1677 1678 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1679 rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); 1680 offset = insn.getOperand(2).getImm(); 1681 1682 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1683 if (!success) 1684 return false; 1685 1686 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, 1687 dwarf_zero_mips64 + rs, 0, &success); 1688 if (!success) 1689 return false; 1690 1691 rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, 1692 dwarf_zero_mips64 + rt, 0, &success); 1693 if (!success) 1694 return false; 1695 1696 if (!strcasecmp(op_name, "BEQC") || !strcasecmp(op_name, "BEQC64")) { 1697 if (rs_val == rt_val) 1698 target = pc + offset; 1699 else 1700 target = pc + 4; 1701 } else if (!strcasecmp(op_name, "BNEC") || !strcasecmp(op_name, "BNEC64")) { 1702 if (rs_val != rt_val) 1703 target = pc + offset; 1704 else 1705 target = pc + 4; 1706 } else if (!strcasecmp(op_name, "BLTC") || !strcasecmp(op_name, "BLTC64")) { 1707 if (rs_val < rt_val) 1708 target = pc + offset; 1709 else 1710 target = pc + 4; 1711 } else if (!strcasecmp(op_name, "BGEC64") || !strcasecmp(op_name, "BGEC")) { 1712 if (rs_val >= rt_val) 1713 target = pc + offset; 1714 else 1715 target = pc + 4; 1716 } else if (!strcasecmp(op_name, "BLTUC") || !strcasecmp(op_name, "BLTUC64")) { 1717 if (rs_val < rt_val) 1718 target = pc + offset; 1719 else 1720 target = pc + 4; 1721 } else if (!strcasecmp(op_name, "BGEUC") || !strcasecmp(op_name, "BGEUC64")) { 1722 if ((uint32_t)rs_val >= (uint32_t)rt_val) 1723 target = pc + offset; 1724 else 1725 target = pc + 4; 1726 } else if (!strcasecmp(op_name, "BOVC")) { 1727 if (IsAdd64bitOverflow(rs_val, rt_val)) 1728 target = pc + offset; 1729 else 1730 target = pc + 4; 1731 } else if (!strcasecmp(op_name, "BNVC")) { 1732 if (!IsAdd64bitOverflow(rs_val, rt_val)) 1733 target = pc + offset; 1734 else 1735 target = pc + 4; 1736 } 1737 1738 Context context; 1739 context.type = eContextRelativeBranchImmediate; 1740 context.SetImmediate(current_inst_size + offset); 1741 1742 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1743 target)) 1744 return false; 1745 1746 return true; 1747 } 1748 1749 /* 1750 Emulate below MIPS branch instructions. 1751 BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches 1752 */ 1753 bool EmulateInstructionMIPS64::Emulate_BXX_2ops_C(llvm::MCInst &insn) { 1754 bool success = false; 1755 uint32_t rs; 1756 int64_t offset, pc, target = 0; 1757 int64_t rs_val; 1758 const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); 1759 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); 1760 1761 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1762 offset = insn.getOperand(1).getImm(); 1763 1764 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1765 if (!success) 1766 return false; 1767 1768 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, 1769 dwarf_zero_mips64 + rs, 0, &success); 1770 if (!success) 1771 return false; 1772 1773 if (!strcasecmp(op_name, "BLTZC") || !strcasecmp(op_name, "BLTZC64")) { 1774 if (rs_val < 0) 1775 target = pc + offset; 1776 else 1777 target = pc + 4; 1778 } else if (!strcasecmp(op_name, "BLEZC") || !strcasecmp(op_name, "BLEZC64")) { 1779 if (rs_val <= 0) 1780 target = pc + offset; 1781 else 1782 target = pc + 4; 1783 } else if (!strcasecmp(op_name, "BGEZC") || !strcasecmp(op_name, "BGEZC64")) { 1784 if (rs_val >= 0) 1785 target = pc + offset; 1786 else 1787 target = pc + 4; 1788 } else if (!strcasecmp(op_name, "BGTZC") || !strcasecmp(op_name, "BGTZC64")) { 1789 if (rs_val > 0) 1790 target = pc + offset; 1791 else 1792 target = pc + 4; 1793 } else if (!strcasecmp(op_name, "BEQZC") || !strcasecmp(op_name, "BEQZC64")) { 1794 if (rs_val == 0) 1795 target = pc + offset; 1796 else 1797 target = pc + 4; 1798 } else if (!strcasecmp(op_name, "BNEZC") || !strcasecmp(op_name, "BNEZC64")) { 1799 if (rs_val != 0) 1800 target = pc + offset; 1801 else 1802 target = pc + 4; 1803 } 1804 1805 Context context; 1806 context.type = eContextRelativeBranchImmediate; 1807 context.SetImmediate(current_inst_size + offset); 1808 1809 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1810 target)) 1811 return false; 1812 1813 return true; 1814 } 1815 1816 bool EmulateInstructionMIPS64::Emulate_J(llvm::MCInst &insn) { 1817 bool success = false; 1818 uint64_t offset, pc; 1819 1820 /* 1821 * J offset 1822 * offset = sign_ext (offset << 2) 1823 * PC = PC[63-28] | offset 1824 */ 1825 offset = insn.getOperand(0).getImm(); 1826 1827 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1828 if (!success) 1829 return false; 1830 1831 /* This is a PC-region branch and not PC-relative */ 1832 pc = (pc & 0xFFFFFFFFF0000000ULL) | offset; 1833 1834 Context context; 1835 1836 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, pc)) 1837 return false; 1838 1839 return true; 1840 } 1841 1842 bool EmulateInstructionMIPS64::Emulate_JAL(llvm::MCInst &insn) { 1843 bool success = false; 1844 uint64_t offset, target, pc; 1845 1846 /* 1847 * JAL offset 1848 * offset = sign_ext (offset << 2) 1849 * PC = PC[63-28] | offset 1850 */ 1851 offset = insn.getOperand(0).getImm(); 1852 1853 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1854 if (!success) 1855 return false; 1856 1857 /* This is a PC-region branch and not PC-relative */ 1858 target = (pc & 0xFFFFFFFFF0000000ULL) | offset; 1859 1860 Context context; 1861 1862 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1863 target)) 1864 return false; 1865 1866 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64, 1867 pc + 8)) 1868 return false; 1869 1870 return true; 1871 } 1872 1873 bool EmulateInstructionMIPS64::Emulate_JALR(llvm::MCInst &insn) { 1874 bool success = false; 1875 uint32_t rs, rt; 1876 uint64_t pc, rs_val; 1877 1878 /* 1879 * JALR rt, rs 1880 * GPR[rt] = PC + 8 1881 * PC = GPR[rs] 1882 */ 1883 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1884 rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); 1885 1886 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1887 if (!success) 1888 return false; 1889 1890 rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, 1891 &success); 1892 if (!success) 1893 return false; 1894 1895 Context context; 1896 1897 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1898 rs_val)) 1899 return false; 1900 1901 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, 1902 dwarf_zero_mips64 + rt, pc + 8)) 1903 return false; 1904 1905 return true; 1906 } 1907 1908 bool EmulateInstructionMIPS64::Emulate_JIALC(llvm::MCInst &insn) { 1909 bool success = false; 1910 uint32_t rt; 1911 int64_t target, offset, pc, rt_val; 1912 1913 /* 1914 * JIALC rt, offset 1915 * offset = sign_ext (offset) 1916 * PC = GPR[rt] + offset 1917 * RA = PC + 4 1918 */ 1919 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1920 offset = insn.getOperand(1).getImm(); 1921 1922 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1923 if (!success) 1924 return false; 1925 1926 rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, 1927 dwarf_zero_mips64 + rt, 0, &success); 1928 if (!success) 1929 return false; 1930 1931 target = rt_val + offset; 1932 1933 Context context; 1934 1935 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1936 target)) 1937 return false; 1938 1939 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64, 1940 pc + 4)) 1941 return false; 1942 1943 return true; 1944 } 1945 1946 bool EmulateInstructionMIPS64::Emulate_JIC(llvm::MCInst &insn) { 1947 bool success = false; 1948 uint32_t rt; 1949 int64_t target, offset, rt_val; 1950 1951 /* 1952 * JIC rt, offset 1953 * offset = sign_ext (offset) 1954 * PC = GPR[rt] + offset 1955 */ 1956 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1957 offset = insn.getOperand(1).getImm(); 1958 1959 rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, 1960 dwarf_zero_mips64 + rt, 0, &success); 1961 if (!success) 1962 return false; 1963 1964 target = rt_val + offset; 1965 1966 Context context; 1967 1968 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1969 target)) 1970 return false; 1971 1972 return true; 1973 } 1974 1975 bool EmulateInstructionMIPS64::Emulate_JR(llvm::MCInst &insn) { 1976 bool success = false; 1977 uint32_t rs; 1978 uint64_t rs_val; 1979 1980 /* 1981 * JR rs 1982 * PC = GPR[rs] 1983 */ 1984 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1985 1986 rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, 1987 &success); 1988 if (!success) 1989 return false; 1990 1991 Context context; 1992 1993 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1994 rs_val)) 1995 return false; 1996 1997 return true; 1998 } 1999 2000 /* 2001 Emulate Branch on FP True/False 2002 BC1F, BC1FL : Branch on FP False (L stands for branch likely) 2003 BC1T, BC1TL : Branch on FP True (L stands for branch likely) 2004 */ 2005 bool EmulateInstructionMIPS64::Emulate_FP_branch(llvm::MCInst &insn) { 2006 bool success = false; 2007 uint32_t cc, fcsr; 2008 int64_t pc, offset, target = 0; 2009 const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); 2010 2011 /* 2012 * BC1F cc, offset 2013 * condition <- (FPConditionCode(cc) == 0) 2014 * if condition then 2015 * offset = sign_ext (offset) 2016 * PC = PC + offset 2017 */ 2018 cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 2019 offset = insn.getOperand(1).getImm(); 2020 2021 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 2022 if (!success) 2023 return false; 2024 2025 fcsr = 2026 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success); 2027 if (!success) 2028 return false; 2029 2030 /* fcsr[23], fcsr[25-31] are vaild condition bits */ 2031 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); 2032 2033 if (!strcasecmp(op_name, "BC1F") || !strcasecmp(op_name, "BC1FL")) { 2034 if ((fcsr & (1 << cc)) == 0) 2035 target = pc + offset; 2036 else 2037 target = pc + 8; 2038 } else if (!strcasecmp(op_name, "BC1T") || !strcasecmp(op_name, "BC1TL")) { 2039 if ((fcsr & (1 << cc)) != 0) 2040 target = pc + offset; 2041 else 2042 target = pc + 8; 2043 } 2044 2045 Context context; 2046 2047 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 2048 target)) 2049 return false; 2050 2051 return true; 2052 } 2053 2054 bool EmulateInstructionMIPS64::Emulate_BC1EQZ(llvm::MCInst &insn) { 2055 bool success = false; 2056 uint32_t ft; 2057 uint64_t ft_val; 2058 int64_t target, pc, offset; 2059 2060 /* 2061 * BC1EQZ ft, offset 2062 * condition <- (FPR[ft].bit0 == 0) 2063 * if condition then 2064 * offset = sign_ext (offset) 2065 * PC = PC + 4 + offset 2066 */ 2067 ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 2068 offset = insn.getOperand(1).getImm(); 2069 2070 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 2071 if (!success) 2072 return false; 2073 2074 ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0, 2075 &success); 2076 if (!success) 2077 return false; 2078 2079 if ((ft_val & 1) == 0) 2080 target = pc + 4 + offset; 2081 else 2082 target = pc + 8; 2083 2084 Context context; 2085 2086 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 2087 target)) 2088 return false; 2089 2090 return true; 2091 } 2092 2093 bool EmulateInstructionMIPS64::Emulate_BC1NEZ(llvm::MCInst &insn) { 2094 bool success = false; 2095 uint32_t ft; 2096 uint64_t ft_val; 2097 int64_t target, pc, offset; 2098 2099 /* 2100 * BC1NEZ ft, offset 2101 * condition <- (FPR[ft].bit0 != 0) 2102 * if condition then 2103 * offset = sign_ext (offset) 2104 * PC = PC + 4 + offset 2105 */ 2106 ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 2107 offset = insn.getOperand(1).getImm(); 2108 2109 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 2110 if (!success) 2111 return false; 2112 2113 ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0, 2114 &success); 2115 if (!success) 2116 return false; 2117 2118 if ((ft_val & 1) != 0) 2119 target = pc + 4 + offset; 2120 else 2121 target = pc + 8; 2122 2123 Context context; 2124 2125 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 2126 target)) 2127 return false; 2128 2129 return true; 2130 } 2131 2132 /* 2133 Emulate MIPS-3D Branch instructions 2134 BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes 2135 False/True 2136 BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes 2137 False/True 2138 */ 2139 bool EmulateInstructionMIPS64::Emulate_3D_branch(llvm::MCInst &insn) { 2140 bool success = false; 2141 uint32_t cc, fcsr; 2142 int64_t pc, offset, target = 0; 2143 const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); 2144 2145 cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 2146 offset = insn.getOperand(1).getImm(); 2147 2148 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 2149 if (!success) 2150 return false; 2151 2152 fcsr = (uint32_t)ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips64, 2153 0, &success); 2154 if (!success) 2155 return false; 2156 2157 /* fcsr[23], fcsr[25-31] are vaild condition bits */ 2158 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); 2159 2160 if (!strcasecmp(op_name, "BC1ANY2F")) { 2161 /* if any one bit is 0 */ 2162 if (((fcsr >> cc) & 3) != 3) 2163 target = pc + offset; 2164 else 2165 target = pc + 8; 2166 } else if (!strcasecmp(op_name, "BC1ANY2T")) { 2167 /* if any one bit is 1 */ 2168 if (((fcsr >> cc) & 3) != 0) 2169 target = pc + offset; 2170 else 2171 target = pc + 8; 2172 } else if (!strcasecmp(op_name, "BC1ANY4F")) { 2173 /* if any one bit is 0 */ 2174 if (((fcsr >> cc) & 0xf) != 0xf) 2175 target = pc + offset; 2176 else 2177 target = pc + 8; 2178 } else if (!strcasecmp(op_name, "BC1ANY4T")) { 2179 /* if any one bit is 1 */ 2180 if (((fcsr >> cc) & 0xf) != 0) 2181 target = pc + offset; 2182 else 2183 target = pc + 8; 2184 } 2185 2186 Context context; 2187 2188 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 2189 target)) 2190 return false; 2191 2192 return true; 2193 } 2194 2195 bool EmulateInstructionMIPS64::Emulate_BNZB(llvm::MCInst &insn) { 2196 return Emulate_MSA_Branch_DF(insn, 1, true); 2197 } 2198 2199 bool EmulateInstructionMIPS64::Emulate_BNZH(llvm::MCInst &insn) { 2200 return Emulate_MSA_Branch_DF(insn, 2, true); 2201 } 2202 2203 bool EmulateInstructionMIPS64::Emulate_BNZW(llvm::MCInst &insn) { 2204 return Emulate_MSA_Branch_DF(insn, 4, true); 2205 } 2206 2207 bool EmulateInstructionMIPS64::Emulate_BNZD(llvm::MCInst &insn) { 2208 return Emulate_MSA_Branch_DF(insn, 8, true); 2209 } 2210 2211 bool EmulateInstructionMIPS64::Emulate_BZB(llvm::MCInst &insn) { 2212 return Emulate_MSA_Branch_DF(insn, 1, false); 2213 } 2214 2215 bool EmulateInstructionMIPS64::Emulate_BZH(llvm::MCInst &insn) { 2216 return Emulate_MSA_Branch_DF(insn, 2, false); 2217 } 2218 2219 bool EmulateInstructionMIPS64::Emulate_BZW(llvm::MCInst &insn) { 2220 return Emulate_MSA_Branch_DF(insn, 4, false); 2221 } 2222 2223 bool EmulateInstructionMIPS64::Emulate_BZD(llvm::MCInst &insn) { 2224 return Emulate_MSA_Branch_DF(insn, 8, false); 2225 } 2226 2227 bool EmulateInstructionMIPS64::Emulate_MSA_Branch_DF(llvm::MCInst &insn, 2228 int element_byte_size, 2229 bool bnz) { 2230 bool success = false, branch_hit = true; 2231 int64_t target = 0; 2232 RegisterValue reg_value; 2233 const uint8_t *ptr = NULL; 2234 2235 uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 2236 int64_t offset = insn.getOperand(1).getImm(); 2237 2238 int64_t pc = 2239 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 2240 if (!success) 2241 return false; 2242 2243 if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value)) 2244 ptr = (const uint8_t *)reg_value.GetBytes(); 2245 else 2246 return false; 2247 2248 for (int i = 0; i < 16 / element_byte_size; i++) { 2249 switch (element_byte_size) { 2250 case 1: 2251 if ((*ptr == 0 && bnz) || (*ptr != 0 && !bnz)) 2252 branch_hit = false; 2253 break; 2254 case 2: 2255 if ((*(const uint16_t *)ptr == 0 && bnz) || 2256 (*(const uint16_t *)ptr != 0 && !bnz)) 2257 branch_hit = false; 2258 break; 2259 case 4: 2260 if ((*(const uint32_t *)ptr == 0 && bnz) || 2261 (*(const uint32_t *)ptr != 0 && !bnz)) 2262 branch_hit = false; 2263 break; 2264 case 8: 2265 if ((*(const uint64_t *)ptr == 0 && bnz) || 2266 (*(const uint64_t *)ptr != 0 && !bnz)) 2267 branch_hit = false; 2268 break; 2269 } 2270 if (!branch_hit) 2271 break; 2272 ptr = ptr + element_byte_size; 2273 } 2274 2275 if (branch_hit) 2276 target = pc + offset; 2277 else 2278 target = pc + 8; 2279 2280 Context context; 2281 context.type = eContextRelativeBranchImmediate; 2282 2283 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 2284 target)) 2285 return false; 2286 2287 return true; 2288 } 2289 2290 bool EmulateInstructionMIPS64::Emulate_BNZV(llvm::MCInst &insn) { 2291 return Emulate_MSA_Branch_V(insn, true); 2292 } 2293 2294 bool EmulateInstructionMIPS64::Emulate_BZV(llvm::MCInst &insn) { 2295 return Emulate_MSA_Branch_V(insn, false); 2296 } 2297 2298 bool EmulateInstructionMIPS64::Emulate_MSA_Branch_V(llvm::MCInst &insn, 2299 bool bnz) { 2300 bool success = false; 2301 int64_t target = 0; 2302 llvm::APInt wr_val = llvm::APInt::getNullValue(128); 2303 llvm::APInt fail_value = llvm::APInt::getMaxValue(128); 2304 llvm::APInt zero_value = llvm::APInt::getNullValue(128); 2305 RegisterValue reg_value; 2306 2307 uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 2308 int64_t offset = insn.getOperand(1).getImm(); 2309 2310 int64_t pc = 2311 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 2312 if (!success) 2313 return false; 2314 2315 if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value)) 2316 wr_val = reg_value.GetAsUInt128(fail_value); 2317 else 2318 return false; 2319 2320 if ((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) || 2321 (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz)) 2322 target = pc + offset; 2323 else 2324 target = pc + 8; 2325 2326 Context context; 2327 context.type = eContextRelativeBranchImmediate; 2328 2329 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 2330 target)) 2331 return false; 2332 2333 return true; 2334 } 2335 2336 bool EmulateInstructionMIPS64::Emulate_LDST_Imm(llvm::MCInst &insn) { 2337 bool success = false; 2338 uint32_t base; 2339 int64_t imm, address; 2340 Context bad_vaddr_context; 2341 2342 uint32_t num_operands = insn.getNumOperands(); 2343 base = 2344 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg()); 2345 imm = insn.getOperand(num_operands - 1).getImm(); 2346 2347 RegisterInfo reg_info_base; 2348 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base, 2349 reg_info_base)) 2350 return false; 2351 2352 /* read base register */ 2353 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0, 2354 &success); 2355 if (!success) 2356 return false; 2357 2358 /* destination address */ 2359 address = address + imm; 2360 2361 /* Set the bad_vaddr register with base address used in the instruction */ 2362 bad_vaddr_context.type = eContextInvalid; 2363 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, 2364 address); 2365 2366 return true; 2367 } 2368 2369 bool EmulateInstructionMIPS64::Emulate_LDST_Reg(llvm::MCInst &insn) { 2370 bool success = false; 2371 uint32_t base, index; 2372 int64_t address, index_address; 2373 Context bad_vaddr_context; 2374 2375 uint32_t num_operands = insn.getNumOperands(); 2376 base = 2377 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg()); 2378 index = 2379 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 1).getReg()); 2380 2381 RegisterInfo reg_info_base, reg_info_index; 2382 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base, 2383 reg_info_base)) 2384 return false; 2385 2386 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + index, 2387 reg_info_index)) 2388 return false; 2389 2390 /* read base register */ 2391 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0, 2392 &success); 2393 if (!success) 2394 return false; 2395 2396 /* read index register */ 2397 index_address = ReadRegisterUnsigned(eRegisterKindDWARF, 2398 dwarf_zero_mips + index, 0, &success); 2399 if (!success) 2400 return false; 2401 2402 /* destination address */ 2403 address = address + index_address; 2404 2405 /* Set the bad_vaddr register with base address used in the instruction */ 2406 bad_vaddr_context.type = eContextInvalid; 2407 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, 2408 address); 2409 2410 return true; 2411 } 2412