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