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>(m_asm_info.get(), 167 m_reg_info.get(), nullptr); 168 assert(m_context.get()); 169 170 m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context)); 171 assert(m_disasm.get()); 172 } 173 174 void EmulateInstructionMIPS64::Initialize() { 175 PluginManager::RegisterPlugin(GetPluginNameStatic(), 176 GetPluginDescriptionStatic(), CreateInstance); 177 } 178 179 void EmulateInstructionMIPS64::Terminate() { 180 PluginManager::UnregisterPlugin(CreateInstance); 181 } 182 183 ConstString EmulateInstructionMIPS64::GetPluginNameStatic() { 184 ConstString g_plugin_name("lldb.emulate-instruction.mips64"); 185 return g_plugin_name; 186 } 187 188 lldb_private::ConstString EmulateInstructionMIPS64::GetPluginName() { 189 static ConstString g_plugin_name("EmulateInstructionMIPS64"); 190 return g_plugin_name; 191 } 192 193 const char *EmulateInstructionMIPS64::GetPluginDescriptionStatic() { 194 return "Emulate instructions for the MIPS64 architecture."; 195 } 196 197 EmulateInstruction * 198 EmulateInstructionMIPS64::CreateInstance(const ArchSpec &arch, 199 InstructionType inst_type) { 200 if (EmulateInstructionMIPS64::SupportsEmulatingInstructionsOfTypeStatic( 201 inst_type)) { 202 if (arch.GetTriple().getArch() == llvm::Triple::mips64 || 203 arch.GetTriple().getArch() == llvm::Triple::mips64el) { 204 return new EmulateInstructionMIPS64(arch); 205 } 206 } 207 208 return nullptr; 209 } 210 211 bool EmulateInstructionMIPS64::SetTargetTriple(const ArchSpec &arch) { 212 return arch.GetTriple().getArch() == llvm::Triple::mips64 || 213 arch.GetTriple().getArch() == llvm::Triple::mips64el; 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 // Prologue/Epilogue instructions 671 {"DADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu, 672 "DADDIU rt, rs, immediate"}, 673 {"ADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu, 674 "ADDIU rt, rs, immediate"}, 675 {"SD", &EmulateInstructionMIPS64::Emulate_SD, "SD rt, offset(rs)"}, 676 {"LD", &EmulateInstructionMIPS64::Emulate_LD, "LD rt, offset(base)"}, 677 {"DSUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU, 678 "DSUBU rd, rs, rt"}, 679 {"SUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU, 680 "SUBU rd, rs, rt"}, 681 {"DADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU, 682 "DADDU rd, rs, rt"}, 683 {"ADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU, 684 "ADDU rd, rs, rt"}, 685 {"LUI", &EmulateInstructionMIPS64::Emulate_LUI, "LUI rt, immediate"}, 686 687 // Load/Store instructions 688 /* Following list of emulated instructions are required by implementation 689 of hardware watchpoint 690 for MIPS in lldb. As we just need the address accessed by instructions, 691 we have generalised 692 all these instructions in 2 functions depending on their addressing 693 modes */ 694 695 {"LB", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 696 "LB rt, offset(base)"}, 697 {"LBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 698 "LBE rt, offset(base)"}, 699 {"LBU", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 700 "LBU rt, offset(base)"}, 701 {"LBUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 702 "LBUE rt, offset(base)"}, 703 {"LDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 704 "LDC1 ft, offset(base)"}, 705 {"LDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 706 "LDL rt, offset(base)"}, 707 {"LDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 708 "LDR rt, offset(base)"}, 709 {"LLD", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 710 "LLD rt, offset(base)"}, 711 {"LDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 712 "LDC2 rt, offset(base)"}, 713 {"LDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, 714 "LDXC1 fd, index (base)"}, 715 {"LH", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 716 "LH rt, offset(base)"}, 717 {"LHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 718 "LHE rt, offset(base)"}, 719 {"LHU", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 720 "LHU rt, offset(base)"}, 721 {"LHUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 722 "LHUE rt, offset(base)"}, 723 {"LL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 724 "LL rt, offset(base)"}, 725 {"LLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 726 "LLE rt, offset(base)"}, 727 {"LUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, 728 "LUXC1 fd, index (base)"}, 729 {"LW", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 730 "LW rt, offset(rs)"}, 731 {"LWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 732 "LWC1 ft, offset(base)"}, 733 {"LWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 734 "LWC2 rt, offset(base)"}, 735 {"LWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 736 "LWE rt, offset(base)"}, 737 {"LWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 738 "LWL rt, offset(base)"}, 739 {"LWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 740 "LWLE rt, offset(base)"}, 741 {"LWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 742 "LWR rt, offset(base)"}, 743 {"LWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 744 "LWRE rt, offset(base)"}, 745 {"LWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, 746 "LWXC1 fd, index (base)"}, 747 748 {"SB", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 749 "SB rt, offset(base)"}, 750 {"SBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 751 "SBE rt, offset(base)"}, 752 {"SC", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 753 "SC rt, offset(base)"}, 754 {"SCE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 755 "SCE rt, offset(base)"}, 756 {"SCD", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 757 "SCD rt, offset(base)"}, 758 {"SDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 759 "SDL rt, offset(base)"}, 760 {"SDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 761 "SDR rt, offset(base)"}, 762 {"SDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 763 "SDC1 ft, offset(base)"}, 764 {"SDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 765 "SDC2 rt, offset(base)"}, 766 {"SDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, 767 "SDXC1 fs, index (base)"}, 768 {"SH", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 769 "SH rt, offset(base)"}, 770 {"SHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 771 "SHE rt, offset(base)"}, 772 {"SUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, 773 "SUXC1 fs, index (base)"}, 774 {"SW", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 775 "SW rt, offset(rs)"}, 776 {"SWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 777 "SWC1 ft, offset(base)"}, 778 {"SWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 779 "SWC2 rt, offset(base)"}, 780 {"SWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 781 "SWE rt, offset(base)"}, 782 {"SWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 783 "SWL rt, offset(base)"}, 784 {"SWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 785 "SWLE rt, offset(base)"}, 786 {"SWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 787 "SWR rt, offset(base)"}, 788 {"SWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, 789 "SWRE rt, offset(base)"}, 790 {"SWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, 791 "SWXC1 fs, index (base)"}, 792 793 // Branch instructions 794 {"BEQ", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"}, 795 {"BEQ64", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"}, 796 {"BNE", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"}, 797 {"BNE64", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"}, 798 {"BEQL", &EmulateInstructionMIPS64::Emulate_BXX_3ops, 799 "BEQL rs,rt,offset"}, 800 {"BNEL", &EmulateInstructionMIPS64::Emulate_BXX_3ops, 801 "BNEL rs,rt,offset"}, 802 {"BGEZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, 803 "BGEZALL rt,offset"}, 804 {"BAL", &EmulateInstructionMIPS64::Emulate_BAL, "BAL offset"}, 805 {"BGEZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, 806 "BGEZAL rs,offset"}, 807 {"BALC", &EmulateInstructionMIPS64::Emulate_BALC, "BALC offset"}, 808 {"BC", &EmulateInstructionMIPS64::Emulate_BC, "BC offset"}, 809 {"BGEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"}, 810 {"BGEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"}, 811 {"BLEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C, 812 "BLEZALC rs,offset"}, 813 {"BGEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C, 814 "BGEZALC rs,offset"}, 815 {"BLTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C, 816 "BLTZALC rs,offset"}, 817 {"BGTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C, 818 "BGTZALC rs,offset"}, 819 {"BEQZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C, 820 "BEQZALC rs,offset"}, 821 {"BNEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C, 822 "BNEZALC rs,offset"}, 823 {"BEQC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, 824 "BEQC rs,rt,offset"}, 825 {"BEQC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, 826 "BEQC rs,rt,offset"}, 827 {"BNEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, 828 "BNEC rs,rt,offset"}, 829 {"BNEC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, 830 "BNEC rs,rt,offset"}, 831 {"BLTC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, 832 "BLTC rs,rt,offset"}, 833 {"BLTC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, 834 "BLTC rs,rt,offset"}, 835 {"BGEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, 836 "BGEC rs,rt,offset"}, 837 {"BGEC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, 838 "BGEC rs,rt,offset"}, 839 {"BLTUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, 840 "BLTUC rs,rt,offset"}, 841 {"BLTUC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, 842 "BLTUC rs,rt,offset"}, 843 {"BGEUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, 844 "BGEUC rs,rt,offset"}, 845 {"BGEUC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, 846 "BGEUC rs,rt,offset"}, 847 {"BLTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, 848 "BLTZC rt,offset"}, 849 {"BLTZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, 850 "BLTZC rt,offset"}, 851 {"BLEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, 852 "BLEZC rt,offset"}, 853 {"BLEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, 854 "BLEZC rt,offset"}, 855 {"BGEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, 856 "BGEZC rt,offset"}, 857 {"BGEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, 858 "BGEZC rt,offset"}, 859 {"BGTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, 860 "BGTZC rt,offset"}, 861 {"BGTZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, 862 "BGTZC rt,offset"}, 863 {"BEQZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, 864 "BEQZC rt,offset"}, 865 {"BEQZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, 866 "BEQZC rt,offset"}, 867 {"BNEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, 868 "BNEZC rt,offset"}, 869 {"BNEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, 870 "BNEZC rt,offset"}, 871 {"BGEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZL rt,offset"}, 872 {"BGTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"}, 873 {"BGTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"}, 874 {"BGTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZL rt,offset"}, 875 {"BLEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"}, 876 {"BLEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"}, 877 {"BLEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZL rt,offset"}, 878 {"BLTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"}, 879 {"BLTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"}, 880 {"BLTZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, 881 "BLTZAL rt,offset"}, 882 {"BLTZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, 883 "BLTZALL rt,offset"}, 884 {"BLTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZL rt,offset"}, 885 {"BOVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, 886 "BOVC rs,rt,offset"}, 887 {"BNVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, 888 "BNVC rs,rt,offset"}, 889 {"J", &EmulateInstructionMIPS64::Emulate_J, "J target"}, 890 {"JAL", &EmulateInstructionMIPS64::Emulate_JAL, "JAL target"}, 891 {"JALX", &EmulateInstructionMIPS64::Emulate_JAL, "JALX target"}, 892 {"JALR", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target"}, 893 {"JALR64", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target"}, 894 {"JALR_HB", &EmulateInstructionMIPS64::Emulate_JALR, "JALR.HB target"}, 895 {"JIALC", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"}, 896 {"JIALC64", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"}, 897 {"JIC", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"}, 898 {"JIC64", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"}, 899 {"JR", &EmulateInstructionMIPS64::Emulate_JR, "JR target"}, 900 {"JR64", &EmulateInstructionMIPS64::Emulate_JR, "JR target"}, 901 {"JR_HB", &EmulateInstructionMIPS64::Emulate_JR, "JR.HB target"}, 902 {"BC1F", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1F cc, offset"}, 903 {"BC1T", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1T cc, offset"}, 904 {"BC1FL", &EmulateInstructionMIPS64::Emulate_FP_branch, 905 "BC1FL cc, offset"}, 906 {"BC1TL", &EmulateInstructionMIPS64::Emulate_FP_branch, 907 "BC1TL cc, offset"}, 908 {"BC1EQZ", &EmulateInstructionMIPS64::Emulate_BC1EQZ, 909 "BC1EQZ ft, offset"}, 910 {"BC1NEZ", &EmulateInstructionMIPS64::Emulate_BC1NEZ, 911 "BC1NEZ ft, offset"}, 912 {"BC1ANY2F", &EmulateInstructionMIPS64::Emulate_3D_branch, 913 "BC1ANY2F cc, offset"}, 914 {"BC1ANY2T", &EmulateInstructionMIPS64::Emulate_3D_branch, 915 "BC1ANY2T cc, offset"}, 916 {"BC1ANY4F", &EmulateInstructionMIPS64::Emulate_3D_branch, 917 "BC1ANY4F cc, offset"}, 918 {"BC1ANY4T", &EmulateInstructionMIPS64::Emulate_3D_branch, 919 "BC1ANY4T cc, offset"}, 920 {"BNZ_B", &EmulateInstructionMIPS64::Emulate_BNZB, "BNZ.b wt,s16"}, 921 {"BNZ_H", &EmulateInstructionMIPS64::Emulate_BNZH, "BNZ.h wt,s16"}, 922 {"BNZ_W", &EmulateInstructionMIPS64::Emulate_BNZW, "BNZ.w wt,s16"}, 923 {"BNZ_D", &EmulateInstructionMIPS64::Emulate_BNZD, "BNZ.d wt,s16"}, 924 {"BZ_B", &EmulateInstructionMIPS64::Emulate_BZB, "BZ.b wt,s16"}, 925 {"BZ_H", &EmulateInstructionMIPS64::Emulate_BZH, "BZ.h wt,s16"}, 926 {"BZ_W", &EmulateInstructionMIPS64::Emulate_BZW, "BZ.w wt,s16"}, 927 {"BZ_D", &EmulateInstructionMIPS64::Emulate_BZD, "BZ.d wt,s16"}, 928 {"BNZ_V", &EmulateInstructionMIPS64::Emulate_BNZV, "BNZ.V wt,s16"}, 929 {"BZ_V", &EmulateInstructionMIPS64::Emulate_BZV, "BZ.V wt,s16"}, 930 }; 931 932 static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes); 933 934 for (size_t i = 0; i < k_num_mips_opcodes; ++i) { 935 if (!strcasecmp(g_opcodes[i].op_name, op_name)) 936 return &g_opcodes[i]; 937 } 938 939 return nullptr; 940 } 941 942 bool EmulateInstructionMIPS64::ReadInstruction() { 943 bool success = false; 944 m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 945 LLDB_INVALID_ADDRESS, &success); 946 if (success) { 947 Context read_inst_context; 948 read_inst_context.type = eContextReadOpcode; 949 read_inst_context.SetNoArgs(); 950 m_opcode.SetOpcode32( 951 ReadMemoryUnsigned(read_inst_context, m_addr, 4, 0, &success), 952 GetByteOrder()); 953 } 954 if (!success) 955 m_addr = LLDB_INVALID_ADDRESS; 956 return success; 957 } 958 959 bool EmulateInstructionMIPS64::EvaluateInstruction(uint32_t evaluate_options) { 960 bool success = false; 961 llvm::MCInst mc_insn; 962 uint64_t insn_size; 963 DataExtractor data; 964 965 /* Keep the complexity of the decode logic with the llvm::MCDisassembler 966 * class. */ 967 if (m_opcode.GetData(data)) { 968 llvm::MCDisassembler::DecodeStatus decode_status; 969 llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize()); 970 decode_status = m_disasm->getInstruction(mc_insn, insn_size, raw_insn, 971 m_addr, llvm::nulls()); 972 if (decode_status != llvm::MCDisassembler::Success) 973 return false; 974 } 975 976 /* 977 * mc_insn.getOpcode() returns decoded opcode. However to make use 978 * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc". 979 */ 980 const char *op_name = m_insn_info->getName(mc_insn.getOpcode()).data(); 981 982 if (op_name == nullptr) 983 return false; 984 985 /* 986 * Decoding has been done already. Just get the call-back function 987 * and emulate the instruction. 988 */ 989 MipsOpcode *opcode_data = GetOpcodeForInstruction(op_name); 990 991 if (opcode_data == nullptr) 992 return false; 993 994 uint64_t old_pc = 0, new_pc = 0; 995 const bool auto_advance_pc = 996 evaluate_options & eEmulateInstructionOptionAutoAdvancePC; 997 998 if (auto_advance_pc) { 999 old_pc = 1000 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1001 if (!success) 1002 return false; 1003 } 1004 1005 /* emulate instruction */ 1006 success = (this->*opcode_data->callback)(mc_insn); 1007 if (!success) 1008 return false; 1009 1010 if (auto_advance_pc) { 1011 new_pc = 1012 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1013 if (!success) 1014 return false; 1015 1016 /* If we haven't changed the PC, change it here */ 1017 if (old_pc == new_pc) { 1018 new_pc += 4; 1019 Context context; 1020 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1021 new_pc)) 1022 return false; 1023 } 1024 } 1025 1026 return true; 1027 } 1028 1029 bool EmulateInstructionMIPS64::CreateFunctionEntryUnwind( 1030 UnwindPlan &unwind_plan) { 1031 unwind_plan.Clear(); 1032 unwind_plan.SetRegisterKind(eRegisterKindDWARF); 1033 1034 UnwindPlan::RowSP row(new UnwindPlan::Row); 1035 const bool can_replace = false; 1036 1037 // Our previous Call Frame Address is the stack pointer 1038 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips64, 0); 1039 1040 // Our previous PC is in the RA 1041 row->SetRegisterLocationToRegister(dwarf_pc_mips64, dwarf_ra_mips64, 1042 can_replace); 1043 1044 unwind_plan.AppendRow(row); 1045 1046 // All other registers are the same. 1047 unwind_plan.SetSourceName("EmulateInstructionMIPS64"); 1048 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); 1049 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); 1050 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); 1051 unwind_plan.SetReturnAddressRegister(dwarf_ra_mips64); 1052 1053 return true; 1054 } 1055 1056 bool EmulateInstructionMIPS64::nonvolatile_reg_p(uint64_t regnum) { 1057 switch (regnum) { 1058 case dwarf_r16_mips64: 1059 case dwarf_r17_mips64: 1060 case dwarf_r18_mips64: 1061 case dwarf_r19_mips64: 1062 case dwarf_r20_mips64: 1063 case dwarf_r21_mips64: 1064 case dwarf_r22_mips64: 1065 case dwarf_r23_mips64: 1066 case dwarf_gp_mips64: 1067 case dwarf_sp_mips64: 1068 case dwarf_r30_mips64: 1069 case dwarf_ra_mips64: 1070 return true; 1071 default: 1072 return false; 1073 } 1074 return false; 1075 } 1076 1077 bool EmulateInstructionMIPS64::Emulate_DADDiu(llvm::MCInst &insn) { 1078 // DADDIU rt, rs, immediate 1079 // GPR[rt] <- GPR[rs] + sign_extend(immediate) 1080 1081 uint8_t dst, src; 1082 bool success = false; 1083 const uint32_t imm16 = insn.getOperand(2).getImm(); 1084 int64_t imm = SignedBits(imm16, 15, 0); 1085 1086 dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1087 src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); 1088 1089 // If immediate is greater than 2^16 - 1 then clang generate LUI, 1090 // (D)ADDIU,(D)SUBU instructions in prolog. Example lui $1, 0x2 daddiu $1, 1091 // $1, -0x5920 dsubu $sp, $sp, $1 In this case, (D)ADDIU dst and src will be 1092 // same and not equal to sp 1093 if (dst == src) { 1094 Context context; 1095 1096 /* read <src> register */ 1097 const uint64_t src_opd_val = ReadRegisterUnsigned( 1098 eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success); 1099 if (!success) 1100 return false; 1101 1102 /* Check if this is daddiu sp, sp, imm16 */ 1103 if (dst == dwarf_sp_mips64) { 1104 /* 1105 * From the MIPS IV spec: 1106 * 1107 * The term “unsigned” in the instruction name is a misnomer; this 1108 * operation is 64-bit modulo arithmetic that does not trap on overflow. 1109 * It is appropriate for arithmetic which is not signed, such as address 1110 * arithmetic, or integer arithmetic environments that ignore overflow, 1111 * such as “C” language arithmetic. 1112 * 1113 * Assume 2's complement and rely on unsigned overflow here. 1114 */ 1115 uint64_t result = src_opd_val + imm; 1116 RegisterInfo reg_info_sp; 1117 1118 if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp)) 1119 context.SetRegisterPlusOffset(reg_info_sp, imm); 1120 1121 /* We are allocating bytes on stack */ 1122 context.type = eContextAdjustStackPointer; 1123 1124 WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips64, 1125 result); 1126 return true; 1127 } 1128 1129 imm += src_opd_val; 1130 context.SetImmediateSigned(imm); 1131 context.type = eContextImmediate; 1132 1133 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, 1134 dwarf_zero_mips64 + dst, imm)) 1135 return false; 1136 } 1137 1138 return true; 1139 } 1140 1141 bool EmulateInstructionMIPS64::Emulate_SD(llvm::MCInst &insn) { 1142 uint64_t address; 1143 RegisterInfo reg_info_base; 1144 RegisterInfo reg_info_src; 1145 bool success = false; 1146 uint32_t imm16 = insn.getOperand(2).getImm(); 1147 uint64_t imm = SignedBits(imm16, 15, 0); 1148 uint32_t src, base; 1149 Context bad_vaddr_context; 1150 1151 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1152 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); 1153 1154 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base, 1155 reg_info_base) || 1156 !GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src, 1157 reg_info_src)) 1158 return false; 1159 1160 /* read SP */ 1161 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + base, 1162 0, &success); 1163 if (!success) 1164 return false; 1165 1166 /* destination address */ 1167 address = address + imm; 1168 1169 /* We look for sp based non-volatile register stores */ 1170 if (nonvolatile_reg_p(src)) { 1171 Context context; 1172 RegisterValue data_src; 1173 context.type = eContextPushRegisterOnStack; 1174 context.SetRegisterToRegisterPlusOffset(reg_info_src, reg_info_base, 0); 1175 1176 uint8_t buffer[RegisterValue::kMaxRegisterByteSize]; 1177 Status error; 1178 1179 if (!ReadRegister(®_info_base, data_src)) 1180 return false; 1181 1182 if (data_src.GetAsMemoryData(®_info_src, buffer, reg_info_src.byte_size, 1183 eByteOrderLittle, error) == 0) 1184 return false; 1185 1186 if (!WriteMemory(context, address, buffer, reg_info_src.byte_size)) 1187 return false; 1188 } 1189 1190 /* Set the bad_vaddr register with base address used in the instruction */ 1191 bad_vaddr_context.type = eContextInvalid; 1192 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64, 1193 address); 1194 1195 return true; 1196 } 1197 1198 bool EmulateInstructionMIPS64::Emulate_LD(llvm::MCInst &insn) { 1199 bool success = false; 1200 uint32_t src, base; 1201 int64_t imm, address; 1202 Context bad_vaddr_context; 1203 1204 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1205 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); 1206 imm = insn.getOperand(2).getImm(); 1207 1208 RegisterInfo reg_info_base; 1209 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base, 1210 reg_info_base)) 1211 return false; 1212 1213 /* read base register */ 1214 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + base, 1215 0, &success); 1216 if (!success) 1217 return false; 1218 1219 /* destination address */ 1220 address = address + imm; 1221 1222 /* Set the bad_vaddr register with base address used in the instruction */ 1223 bad_vaddr_context.type = eContextInvalid; 1224 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64, 1225 address); 1226 1227 if (nonvolatile_reg_p(src)) { 1228 RegisterValue data_src; 1229 RegisterInfo reg_info_src; 1230 1231 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src, 1232 reg_info_src)) 1233 return false; 1234 1235 Context context; 1236 context.type = eContextRegisterLoad; 1237 1238 return WriteRegister(context, ®_info_src, data_src); 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 return WriteRegisterUnsigned(context, eRegisterKindDWARF, 1258 dwarf_zero_mips64 + rt, imm); 1259 } 1260 1261 bool EmulateInstructionMIPS64::Emulate_DSUBU_DADDU(llvm::MCInst &insn) { 1262 // DSUBU sp, <src>, <rt> 1263 // DADDU sp, <src>, <rt> 1264 // DADDU dst, sp, <rt> 1265 1266 bool success = false; 1267 uint64_t result; 1268 uint8_t src, dst, rt; 1269 const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); 1270 1271 dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1272 src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); 1273 1274 /* Check if sp is destination register */ 1275 if (dst == dwarf_sp_mips64) { 1276 rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg()); 1277 1278 /* read <src> register */ 1279 uint64_t src_opd_val = ReadRegisterUnsigned( 1280 eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success); 1281 if (!success) 1282 return false; 1283 1284 /* read <rt > register */ 1285 uint64_t rt_opd_val = ReadRegisterUnsigned( 1286 eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success); 1287 if (!success) 1288 return false; 1289 1290 if (!strcasecmp(op_name, "DSUBU") || !strcasecmp(op_name, "SUBU")) 1291 result = src_opd_val - rt_opd_val; 1292 else 1293 result = src_opd_val + rt_opd_val; 1294 1295 Context context; 1296 RegisterInfo reg_info_sp; 1297 if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp)) 1298 context.SetRegisterPlusOffset(reg_info_sp, rt_opd_val); 1299 1300 /* We are allocating bytes on stack */ 1301 context.type = eContextAdjustStackPointer; 1302 1303 WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips64, result); 1304 1305 return true; 1306 } else if (src == dwarf_sp_mips64) { 1307 rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg()); 1308 1309 /* read <src> register */ 1310 uint64_t src_opd_val = ReadRegisterUnsigned( 1311 eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success); 1312 if (!success) 1313 return false; 1314 1315 /* read <rt> register */ 1316 uint64_t rt_opd_val = ReadRegisterUnsigned( 1317 eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success); 1318 if (!success) 1319 return false; 1320 1321 Context context; 1322 1323 if (!strcasecmp(op_name, "DSUBU") || !strcasecmp(op_name, "SUBU")) 1324 result = src_opd_val - rt_opd_val; 1325 else 1326 result = src_opd_val + rt_opd_val; 1327 1328 context.SetImmediateSigned(result); 1329 context.type = eContextImmediate; 1330 1331 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, 1332 dwarf_zero_mips64 + dst, result)) 1333 return false; 1334 } 1335 1336 return true; 1337 } 1338 1339 /* 1340 Emulate below MIPS branch instructions. 1341 BEQ, BNE : Branch on condition 1342 BEQL, BNEL : Branch likely 1343 */ 1344 bool EmulateInstructionMIPS64::Emulate_BXX_3ops(llvm::MCInst &insn) { 1345 bool success = false; 1346 uint32_t rs, rt; 1347 int64_t offset, pc, rs_val, rt_val, target = 0; 1348 const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); 1349 1350 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1351 rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); 1352 offset = insn.getOperand(2).getImm(); 1353 1354 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1355 if (!success) 1356 return false; 1357 1358 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, 1359 dwarf_zero_mips64 + rs, 0, &success); 1360 if (!success) 1361 return false; 1362 1363 rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, 1364 dwarf_zero_mips64 + rt, 0, &success); 1365 if (!success) 1366 return false; 1367 1368 if (!strcasecmp(op_name, "BEQ") || !strcasecmp(op_name, "BEQL") 1369 || !strcasecmp(op_name, "BEQ64") ) { 1370 if (rs_val == rt_val) 1371 target = pc + offset; 1372 else 1373 target = pc + 8; 1374 } else if (!strcasecmp(op_name, "BNE") || !strcasecmp(op_name, "BNEL") 1375 || !strcasecmp(op_name, "BNE64")) { 1376 if (rs_val != rt_val) 1377 target = pc + offset; 1378 else 1379 target = pc + 8; 1380 } 1381 1382 Context context; 1383 context.type = eContextRelativeBranchImmediate; 1384 context.SetImmediate(offset); 1385 1386 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1387 target); 1388 } 1389 1390 /* 1391 Emulate below MIPS Non-Compact conditional branch and link instructions. 1392 BLTZAL, BGEZAL : 1393 BLTZALL, BGEZALL : Branch likely 1394 */ 1395 bool EmulateInstructionMIPS64::Emulate_Bcond_Link(llvm::MCInst &insn) { 1396 bool success = false; 1397 uint32_t rs; 1398 int64_t offset, pc, target = 0; 1399 int64_t rs_val; 1400 const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); 1401 1402 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1403 offset = insn.getOperand(1).getImm(); 1404 1405 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1406 if (!success) 1407 return false; 1408 1409 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, 1410 dwarf_zero_mips64 + rs, 0, &success); 1411 if (!success) 1412 return false; 1413 1414 if (!strcasecmp(op_name, "BLTZAL") || !strcasecmp(op_name, "BLTZALL")) { 1415 if (rs_val < 0) 1416 target = pc + offset; 1417 else 1418 target = pc + 8; 1419 } else if (!strcasecmp(op_name, "BGEZAL") || 1420 !strcasecmp(op_name, "BGEZALL")) { 1421 if (rs_val >= 0) 1422 target = pc + offset; 1423 else 1424 target = pc + 8; 1425 } 1426 1427 Context context; 1428 1429 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1430 target)) 1431 return false; 1432 1433 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64, 1434 pc + 8)) 1435 return false; 1436 1437 return true; 1438 } 1439 1440 bool EmulateInstructionMIPS64::Emulate_BAL(llvm::MCInst &insn) { 1441 bool success = false; 1442 int64_t offset, pc, target; 1443 1444 /* 1445 * BAL offset 1446 * offset = sign_ext (offset << 2) 1447 * RA = PC + 8 1448 * PC = PC + offset 1449 */ 1450 offset = insn.getOperand(0).getImm(); 1451 1452 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1453 if (!success) 1454 return false; 1455 1456 target = pc + offset; 1457 1458 Context context; 1459 1460 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1461 target)) 1462 return false; 1463 1464 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64, 1465 pc + 8)) 1466 return false; 1467 1468 return true; 1469 } 1470 1471 bool EmulateInstructionMIPS64::Emulate_BALC(llvm::MCInst &insn) { 1472 bool success = false; 1473 int64_t offset, pc, target; 1474 1475 /* 1476 * BALC offset 1477 * offset = sign_ext (offset << 2) 1478 * RA = PC + 4 1479 * PC = PC + 4 + offset 1480 */ 1481 offset = insn.getOperand(0).getImm(); 1482 1483 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1484 if (!success) 1485 return false; 1486 1487 target = pc + offset; 1488 1489 Context context; 1490 1491 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1492 target)) 1493 return false; 1494 1495 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64, 1496 pc + 4)) 1497 return false; 1498 1499 return true; 1500 } 1501 1502 /* 1503 Emulate below MIPS conditional branch and link instructions. 1504 BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches 1505 */ 1506 bool EmulateInstructionMIPS64::Emulate_Bcond_Link_C(llvm::MCInst &insn) { 1507 bool success = false; 1508 uint32_t rs; 1509 int64_t offset, pc, rs_val, target = 0; 1510 const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); 1511 1512 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1513 offset = insn.getOperand(1).getImm(); 1514 1515 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1516 if (!success) 1517 return false; 1518 1519 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, 1520 dwarf_zero_mips64 + rs, 0, &success); 1521 if (!success) 1522 return false; 1523 1524 if (!strcasecmp(op_name, "BLEZALC")) { 1525 if (rs_val <= 0) 1526 target = pc + offset; 1527 else 1528 target = pc + 4; 1529 } else if (!strcasecmp(op_name, "BGEZALC")) { 1530 if (rs_val >= 0) 1531 target = pc + offset; 1532 else 1533 target = pc + 4; 1534 } else if (!strcasecmp(op_name, "BLTZALC")) { 1535 if (rs_val < 0) 1536 target = pc + offset; 1537 else 1538 target = pc + 4; 1539 } else if (!strcasecmp(op_name, "BGTZALC")) { 1540 if (rs_val > 0) 1541 target = pc + offset; 1542 else 1543 target = pc + 4; 1544 } else if (!strcasecmp(op_name, "BEQZALC")) { 1545 if (rs_val == 0) 1546 target = pc + offset; 1547 else 1548 target = pc + 4; 1549 } else if (!strcasecmp(op_name, "BNEZALC")) { 1550 if (rs_val != 0) 1551 target = pc + offset; 1552 else 1553 target = pc + 4; 1554 } 1555 1556 Context context; 1557 1558 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1559 target)) 1560 return false; 1561 1562 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64, 1563 pc + 4)) 1564 return false; 1565 1566 return true; 1567 } 1568 1569 /* 1570 Emulate below MIPS branch instructions. 1571 BLTZL, BGEZL, BGTZL, BLEZL : Branch likely 1572 BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches 1573 */ 1574 bool EmulateInstructionMIPS64::Emulate_BXX_2ops(llvm::MCInst &insn) { 1575 bool success = false; 1576 uint32_t rs; 1577 int64_t offset, pc, rs_val, target = 0; 1578 const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); 1579 1580 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1581 offset = insn.getOperand(1).getImm(); 1582 1583 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1584 if (!success) 1585 return false; 1586 1587 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, 1588 dwarf_zero_mips64 + rs, 0, &success); 1589 if (!success) 1590 return false; 1591 1592 if (!strcasecmp(op_name, "BLTZL") || !strcasecmp(op_name, "BLTZ") 1593 || !strcasecmp(op_name, "BLTZ64")) { 1594 if (rs_val < 0) 1595 target = pc + offset; 1596 else 1597 target = pc + 8; 1598 } else if (!strcasecmp(op_name, "BGEZL") || !strcasecmp(op_name, "BGEZ") 1599 || !strcasecmp(op_name, "BGEZ64")) { 1600 if (rs_val >= 0) 1601 target = pc + offset; 1602 else 1603 target = pc + 8; 1604 } else if (!strcasecmp(op_name, "BGTZL") || !strcasecmp(op_name, "BGTZ") 1605 || !strcasecmp(op_name, "BGTZ64")) { 1606 if (rs_val > 0) 1607 target = pc + offset; 1608 else 1609 target = pc + 8; 1610 } else if (!strcasecmp(op_name, "BLEZL") || !strcasecmp(op_name, "BLEZ") 1611 || !strcasecmp(op_name, "BLEZ64")) { 1612 if (rs_val <= 0) 1613 target = pc + offset; 1614 else 1615 target = pc + 8; 1616 } 1617 1618 Context context; 1619 context.type = eContextRelativeBranchImmediate; 1620 context.SetImmediate(offset); 1621 1622 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1623 target); 1624 } 1625 1626 bool EmulateInstructionMIPS64::Emulate_BC(llvm::MCInst &insn) { 1627 bool success = false; 1628 int64_t offset, pc, target; 1629 1630 /* 1631 * BC offset 1632 * offset = sign_ext (offset << 2) 1633 * PC = PC + 4 + offset 1634 */ 1635 offset = insn.getOperand(0).getImm(); 1636 1637 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1638 if (!success) 1639 return false; 1640 1641 target = pc + offset; 1642 1643 Context context; 1644 1645 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1646 target); 1647 } 1648 1649 static int IsAdd64bitOverflow(int64_t a, int64_t b) { 1650 int64_t r = (uint64_t)a + (uint64_t)b; 1651 return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0); 1652 } 1653 1654 /* 1655 Emulate below MIPS branch instructions. 1656 BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch 1657 instructions with no delay slot 1658 */ 1659 bool EmulateInstructionMIPS64::Emulate_BXX_3ops_C(llvm::MCInst &insn) { 1660 bool success = false; 1661 uint32_t rs, rt; 1662 int64_t offset, pc, rs_val, rt_val, target = 0; 1663 const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); 1664 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); 1665 1666 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1667 rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); 1668 offset = insn.getOperand(2).getImm(); 1669 1670 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1671 if (!success) 1672 return false; 1673 1674 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, 1675 dwarf_zero_mips64 + rs, 0, &success); 1676 if (!success) 1677 return false; 1678 1679 rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, 1680 dwarf_zero_mips64 + rt, 0, &success); 1681 if (!success) 1682 return false; 1683 1684 if (!strcasecmp(op_name, "BEQC") || !strcasecmp(op_name, "BEQC64")) { 1685 if (rs_val == rt_val) 1686 target = pc + offset; 1687 else 1688 target = pc + 4; 1689 } else if (!strcasecmp(op_name, "BNEC") || !strcasecmp(op_name, "BNEC64")) { 1690 if (rs_val != rt_val) 1691 target = pc + offset; 1692 else 1693 target = pc + 4; 1694 } else if (!strcasecmp(op_name, "BLTC") || !strcasecmp(op_name, "BLTC64")) { 1695 if (rs_val < rt_val) 1696 target = pc + offset; 1697 else 1698 target = pc + 4; 1699 } else if (!strcasecmp(op_name, "BGEC64") || !strcasecmp(op_name, "BGEC")) { 1700 if (rs_val >= rt_val) 1701 target = pc + offset; 1702 else 1703 target = pc + 4; 1704 } else if (!strcasecmp(op_name, "BLTUC") || !strcasecmp(op_name, "BLTUC64")) { 1705 if (rs_val < rt_val) 1706 target = pc + offset; 1707 else 1708 target = pc + 4; 1709 } else if (!strcasecmp(op_name, "BGEUC") || !strcasecmp(op_name, "BGEUC64")) { 1710 if ((uint32_t)rs_val >= (uint32_t)rt_val) 1711 target = pc + offset; 1712 else 1713 target = pc + 4; 1714 } else if (!strcasecmp(op_name, "BOVC")) { 1715 if (IsAdd64bitOverflow(rs_val, rt_val)) 1716 target = pc + offset; 1717 else 1718 target = pc + 4; 1719 } else if (!strcasecmp(op_name, "BNVC")) { 1720 if (!IsAdd64bitOverflow(rs_val, rt_val)) 1721 target = pc + offset; 1722 else 1723 target = pc + 4; 1724 } 1725 1726 Context context; 1727 context.type = eContextRelativeBranchImmediate; 1728 context.SetImmediate(current_inst_size + offset); 1729 1730 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1731 target); 1732 } 1733 1734 /* 1735 Emulate below MIPS branch instructions. 1736 BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches 1737 */ 1738 bool EmulateInstructionMIPS64::Emulate_BXX_2ops_C(llvm::MCInst &insn) { 1739 bool success = false; 1740 uint32_t rs; 1741 int64_t offset, pc, target = 0; 1742 int64_t rs_val; 1743 const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); 1744 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); 1745 1746 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1747 offset = insn.getOperand(1).getImm(); 1748 1749 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1750 if (!success) 1751 return false; 1752 1753 rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, 1754 dwarf_zero_mips64 + rs, 0, &success); 1755 if (!success) 1756 return false; 1757 1758 if (!strcasecmp(op_name, "BLTZC") || !strcasecmp(op_name, "BLTZC64")) { 1759 if (rs_val < 0) 1760 target = pc + offset; 1761 else 1762 target = pc + 4; 1763 } else if (!strcasecmp(op_name, "BLEZC") || !strcasecmp(op_name, "BLEZC64")) { 1764 if (rs_val <= 0) 1765 target = pc + offset; 1766 else 1767 target = pc + 4; 1768 } else if (!strcasecmp(op_name, "BGEZC") || !strcasecmp(op_name, "BGEZC64")) { 1769 if (rs_val >= 0) 1770 target = pc + offset; 1771 else 1772 target = pc + 4; 1773 } else if (!strcasecmp(op_name, "BGTZC") || !strcasecmp(op_name, "BGTZC64")) { 1774 if (rs_val > 0) 1775 target = pc + offset; 1776 else 1777 target = pc + 4; 1778 } else if (!strcasecmp(op_name, "BEQZC") || !strcasecmp(op_name, "BEQZC64")) { 1779 if (rs_val == 0) 1780 target = pc + offset; 1781 else 1782 target = pc + 4; 1783 } else if (!strcasecmp(op_name, "BNEZC") || !strcasecmp(op_name, "BNEZC64")) { 1784 if (rs_val != 0) 1785 target = pc + offset; 1786 else 1787 target = pc + 4; 1788 } 1789 1790 Context context; 1791 context.type = eContextRelativeBranchImmediate; 1792 context.SetImmediate(current_inst_size + offset); 1793 1794 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1795 target); 1796 } 1797 1798 bool EmulateInstructionMIPS64::Emulate_J(llvm::MCInst &insn) { 1799 bool success = false; 1800 uint64_t offset, pc; 1801 1802 /* 1803 * J offset 1804 * offset = sign_ext (offset << 2) 1805 * PC = PC[63-28] | offset 1806 */ 1807 offset = insn.getOperand(0).getImm(); 1808 1809 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1810 if (!success) 1811 return false; 1812 1813 /* This is a PC-region branch and not PC-relative */ 1814 pc = (pc & 0xFFFFFFFFF0000000ULL) | offset; 1815 1816 Context context; 1817 1818 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1819 pc); 1820 } 1821 1822 bool EmulateInstructionMIPS64::Emulate_JAL(llvm::MCInst &insn) { 1823 bool success = false; 1824 uint64_t offset, target, pc; 1825 1826 /* 1827 * JAL offset 1828 * offset = sign_ext (offset << 2) 1829 * PC = PC[63-28] | offset 1830 */ 1831 offset = insn.getOperand(0).getImm(); 1832 1833 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1834 if (!success) 1835 return false; 1836 1837 /* This is a PC-region branch and not PC-relative */ 1838 target = (pc & 0xFFFFFFFFF0000000ULL) | offset; 1839 1840 Context context; 1841 1842 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1843 target)) 1844 return false; 1845 1846 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64, 1847 pc + 8)) 1848 return false; 1849 1850 return true; 1851 } 1852 1853 bool EmulateInstructionMIPS64::Emulate_JALR(llvm::MCInst &insn) { 1854 bool success = false; 1855 uint32_t rs, rt; 1856 uint64_t pc, rs_val; 1857 1858 /* 1859 * JALR rt, rs 1860 * GPR[rt] = PC + 8 1861 * PC = GPR[rs] 1862 */ 1863 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1864 rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); 1865 1866 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1867 if (!success) 1868 return false; 1869 1870 rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, 1871 &success); 1872 if (!success) 1873 return false; 1874 1875 Context context; 1876 1877 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1878 rs_val)) 1879 return false; 1880 1881 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, 1882 dwarf_zero_mips64 + rt, pc + 8)) 1883 return false; 1884 1885 return true; 1886 } 1887 1888 bool EmulateInstructionMIPS64::Emulate_JIALC(llvm::MCInst &insn) { 1889 bool success = false; 1890 uint32_t rt; 1891 int64_t target, offset, pc, rt_val; 1892 1893 /* 1894 * JIALC rt, offset 1895 * offset = sign_ext (offset) 1896 * PC = GPR[rt] + offset 1897 * RA = PC + 4 1898 */ 1899 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1900 offset = insn.getOperand(1).getImm(); 1901 1902 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1903 if (!success) 1904 return false; 1905 1906 rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, 1907 dwarf_zero_mips64 + rt, 0, &success); 1908 if (!success) 1909 return false; 1910 1911 target = rt_val + offset; 1912 1913 Context context; 1914 1915 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1916 target)) 1917 return false; 1918 1919 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64, 1920 pc + 4)) 1921 return false; 1922 1923 return true; 1924 } 1925 1926 bool EmulateInstructionMIPS64::Emulate_JIC(llvm::MCInst &insn) { 1927 bool success = false; 1928 uint32_t rt; 1929 int64_t target, offset, rt_val; 1930 1931 /* 1932 * JIC rt, offset 1933 * offset = sign_ext (offset) 1934 * PC = GPR[rt] + offset 1935 */ 1936 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1937 offset = insn.getOperand(1).getImm(); 1938 1939 rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, 1940 dwarf_zero_mips64 + rt, 0, &success); 1941 if (!success) 1942 return false; 1943 1944 target = rt_val + offset; 1945 1946 Context context; 1947 1948 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1949 target); 1950 } 1951 1952 bool EmulateInstructionMIPS64::Emulate_JR(llvm::MCInst &insn) { 1953 bool success = false; 1954 uint32_t rs; 1955 uint64_t rs_val; 1956 1957 /* 1958 * JR rs 1959 * PC = GPR[rs] 1960 */ 1961 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1962 1963 rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, 1964 &success); 1965 if (!success) 1966 return false; 1967 1968 Context context; 1969 1970 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 1971 rs_val); 1972 } 1973 1974 /* 1975 Emulate Branch on FP True/False 1976 BC1F, BC1FL : Branch on FP False (L stands for branch likely) 1977 BC1T, BC1TL : Branch on FP True (L stands for branch likely) 1978 */ 1979 bool EmulateInstructionMIPS64::Emulate_FP_branch(llvm::MCInst &insn) { 1980 bool success = false; 1981 uint32_t cc, fcsr; 1982 int64_t pc, offset, target = 0; 1983 const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); 1984 1985 /* 1986 * BC1F cc, offset 1987 * condition <- (FPConditionCode(cc) == 0) 1988 * if condition then 1989 * offset = sign_ext (offset) 1990 * PC = PC + offset 1991 */ 1992 cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 1993 offset = insn.getOperand(1).getImm(); 1994 1995 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1996 if (!success) 1997 return false; 1998 1999 fcsr = 2000 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success); 2001 if (!success) 2002 return false; 2003 2004 /* fcsr[23], fcsr[25-31] are vaild condition bits */ 2005 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); 2006 2007 if (!strcasecmp(op_name, "BC1F") || !strcasecmp(op_name, "BC1FL")) { 2008 if ((fcsr & (1 << cc)) == 0) 2009 target = pc + offset; 2010 else 2011 target = pc + 8; 2012 } else if (!strcasecmp(op_name, "BC1T") || !strcasecmp(op_name, "BC1TL")) { 2013 if ((fcsr & (1 << cc)) != 0) 2014 target = pc + offset; 2015 else 2016 target = pc + 8; 2017 } 2018 2019 Context context; 2020 2021 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 2022 target); 2023 } 2024 2025 bool EmulateInstructionMIPS64::Emulate_BC1EQZ(llvm::MCInst &insn) { 2026 bool success = false; 2027 uint32_t ft; 2028 uint64_t ft_val; 2029 int64_t target, pc, offset; 2030 2031 /* 2032 * BC1EQZ ft, offset 2033 * condition <- (FPR[ft].bit0 == 0) 2034 * if condition then 2035 * offset = sign_ext (offset) 2036 * PC = PC + 4 + offset 2037 */ 2038 ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 2039 offset = insn.getOperand(1).getImm(); 2040 2041 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 2042 if (!success) 2043 return false; 2044 2045 ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0, 2046 &success); 2047 if (!success) 2048 return false; 2049 2050 if ((ft_val & 1) == 0) 2051 target = pc + 4 + offset; 2052 else 2053 target = pc + 8; 2054 2055 Context context; 2056 2057 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 2058 target); 2059 } 2060 2061 bool EmulateInstructionMIPS64::Emulate_BC1NEZ(llvm::MCInst &insn) { 2062 bool success = false; 2063 uint32_t ft; 2064 uint64_t ft_val; 2065 int64_t target, pc, offset; 2066 2067 /* 2068 * BC1NEZ ft, offset 2069 * condition <- (FPR[ft].bit0 != 0) 2070 * if condition then 2071 * offset = sign_ext (offset) 2072 * PC = PC + 4 + offset 2073 */ 2074 ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 2075 offset = insn.getOperand(1).getImm(); 2076 2077 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 2078 if (!success) 2079 return false; 2080 2081 ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0, 2082 &success); 2083 if (!success) 2084 return false; 2085 2086 if ((ft_val & 1) != 0) 2087 target = pc + 4 + offset; 2088 else 2089 target = pc + 8; 2090 2091 Context context; 2092 2093 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 2094 target); 2095 } 2096 2097 /* 2098 Emulate MIPS-3D Branch instructions 2099 BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes 2100 False/True 2101 BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes 2102 False/True 2103 */ 2104 bool EmulateInstructionMIPS64::Emulate_3D_branch(llvm::MCInst &insn) { 2105 bool success = false; 2106 uint32_t cc, fcsr; 2107 int64_t pc, offset, target = 0; 2108 const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); 2109 2110 cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 2111 offset = insn.getOperand(1).getImm(); 2112 2113 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 2114 if (!success) 2115 return false; 2116 2117 fcsr = (uint32_t)ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips64, 2118 0, &success); 2119 if (!success) 2120 return false; 2121 2122 /* fcsr[23], fcsr[25-31] are vaild condition bits */ 2123 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); 2124 2125 if (!strcasecmp(op_name, "BC1ANY2F")) { 2126 /* if any one bit is 0 */ 2127 if (((fcsr >> cc) & 3) != 3) 2128 target = pc + offset; 2129 else 2130 target = pc + 8; 2131 } else if (!strcasecmp(op_name, "BC1ANY2T")) { 2132 /* if any one bit is 1 */ 2133 if (((fcsr >> cc) & 3) != 0) 2134 target = pc + offset; 2135 else 2136 target = pc + 8; 2137 } else if (!strcasecmp(op_name, "BC1ANY4F")) { 2138 /* if any one bit is 0 */ 2139 if (((fcsr >> cc) & 0xf) != 0xf) 2140 target = pc + offset; 2141 else 2142 target = pc + 8; 2143 } else if (!strcasecmp(op_name, "BC1ANY4T")) { 2144 /* if any one bit is 1 */ 2145 if (((fcsr >> cc) & 0xf) != 0) 2146 target = pc + offset; 2147 else 2148 target = pc + 8; 2149 } 2150 2151 Context context; 2152 2153 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 2154 target); 2155 } 2156 2157 bool EmulateInstructionMIPS64::Emulate_BNZB(llvm::MCInst &insn) { 2158 return Emulate_MSA_Branch_DF(insn, 1, true); 2159 } 2160 2161 bool EmulateInstructionMIPS64::Emulate_BNZH(llvm::MCInst &insn) { 2162 return Emulate_MSA_Branch_DF(insn, 2, true); 2163 } 2164 2165 bool EmulateInstructionMIPS64::Emulate_BNZW(llvm::MCInst &insn) { 2166 return Emulate_MSA_Branch_DF(insn, 4, true); 2167 } 2168 2169 bool EmulateInstructionMIPS64::Emulate_BNZD(llvm::MCInst &insn) { 2170 return Emulate_MSA_Branch_DF(insn, 8, true); 2171 } 2172 2173 bool EmulateInstructionMIPS64::Emulate_BZB(llvm::MCInst &insn) { 2174 return Emulate_MSA_Branch_DF(insn, 1, false); 2175 } 2176 2177 bool EmulateInstructionMIPS64::Emulate_BZH(llvm::MCInst &insn) { 2178 return Emulate_MSA_Branch_DF(insn, 2, false); 2179 } 2180 2181 bool EmulateInstructionMIPS64::Emulate_BZW(llvm::MCInst &insn) { 2182 return Emulate_MSA_Branch_DF(insn, 4, false); 2183 } 2184 2185 bool EmulateInstructionMIPS64::Emulate_BZD(llvm::MCInst &insn) { 2186 return Emulate_MSA_Branch_DF(insn, 8, false); 2187 } 2188 2189 bool EmulateInstructionMIPS64::Emulate_MSA_Branch_DF(llvm::MCInst &insn, 2190 int element_byte_size, 2191 bool bnz) { 2192 bool success = false, branch_hit = true; 2193 int64_t target = 0; 2194 RegisterValue reg_value; 2195 const uint8_t *ptr = nullptr; 2196 2197 uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 2198 int64_t offset = insn.getOperand(1).getImm(); 2199 2200 int64_t pc = 2201 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 2202 if (!success) 2203 return false; 2204 2205 if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value)) 2206 ptr = (const uint8_t *)reg_value.GetBytes(); 2207 else 2208 return false; 2209 2210 for (int i = 0; i < 16 / element_byte_size; i++) { 2211 switch (element_byte_size) { 2212 case 1: 2213 if ((*ptr == 0 && bnz) || (*ptr != 0 && !bnz)) 2214 branch_hit = false; 2215 break; 2216 case 2: 2217 if ((*(const uint16_t *)ptr == 0 && bnz) || 2218 (*(const uint16_t *)ptr != 0 && !bnz)) 2219 branch_hit = false; 2220 break; 2221 case 4: 2222 if ((*(const uint32_t *)ptr == 0 && bnz) || 2223 (*(const uint32_t *)ptr != 0 && !bnz)) 2224 branch_hit = false; 2225 break; 2226 case 8: 2227 if ((*(const uint64_t *)ptr == 0 && bnz) || 2228 (*(const uint64_t *)ptr != 0 && !bnz)) 2229 branch_hit = false; 2230 break; 2231 } 2232 if (!branch_hit) 2233 break; 2234 ptr = ptr + element_byte_size; 2235 } 2236 2237 if (branch_hit) 2238 target = pc + offset; 2239 else 2240 target = pc + 8; 2241 2242 Context context; 2243 context.type = eContextRelativeBranchImmediate; 2244 2245 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 2246 target); 2247 } 2248 2249 bool EmulateInstructionMIPS64::Emulate_BNZV(llvm::MCInst &insn) { 2250 return Emulate_MSA_Branch_V(insn, true); 2251 } 2252 2253 bool EmulateInstructionMIPS64::Emulate_BZV(llvm::MCInst &insn) { 2254 return Emulate_MSA_Branch_V(insn, false); 2255 } 2256 2257 bool EmulateInstructionMIPS64::Emulate_MSA_Branch_V(llvm::MCInst &insn, 2258 bool bnz) { 2259 bool success = false; 2260 int64_t target = 0; 2261 llvm::APInt wr_val = llvm::APInt::getNullValue(128); 2262 llvm::APInt fail_value = llvm::APInt::getMaxValue(128); 2263 llvm::APInt zero_value = llvm::APInt::getNullValue(128); 2264 RegisterValue reg_value; 2265 2266 uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); 2267 int64_t offset = insn.getOperand(1).getImm(); 2268 2269 int64_t pc = 2270 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 2271 if (!success) 2272 return false; 2273 2274 if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value)) 2275 wr_val = reg_value.GetAsUInt128(fail_value); 2276 else 2277 return false; 2278 2279 if ((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) || 2280 (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz)) 2281 target = pc + offset; 2282 else 2283 target = pc + 8; 2284 2285 Context context; 2286 context.type = eContextRelativeBranchImmediate; 2287 2288 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, 2289 target); 2290 } 2291 2292 bool EmulateInstructionMIPS64::Emulate_LDST_Imm(llvm::MCInst &insn) { 2293 bool success = false; 2294 uint32_t base; 2295 int64_t imm, address; 2296 Context bad_vaddr_context; 2297 2298 uint32_t num_operands = insn.getNumOperands(); 2299 base = 2300 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg()); 2301 imm = insn.getOperand(num_operands - 1).getImm(); 2302 2303 RegisterInfo reg_info_base; 2304 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base, 2305 reg_info_base)) 2306 return false; 2307 2308 /* read base register */ 2309 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0, 2310 &success); 2311 if (!success) 2312 return false; 2313 2314 /* destination address */ 2315 address = address + imm; 2316 2317 /* Set the bad_vaddr register with base address used in the instruction */ 2318 bad_vaddr_context.type = eContextInvalid; 2319 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, 2320 address); 2321 2322 return true; 2323 } 2324 2325 bool EmulateInstructionMIPS64::Emulate_LDST_Reg(llvm::MCInst &insn) { 2326 bool success = false; 2327 uint32_t base, index; 2328 int64_t address, index_address; 2329 Context bad_vaddr_context; 2330 2331 uint32_t num_operands = insn.getNumOperands(); 2332 base = 2333 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg()); 2334 index = 2335 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 1).getReg()); 2336 2337 RegisterInfo reg_info_base, reg_info_index; 2338 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base, 2339 reg_info_base)) 2340 return false; 2341 2342 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + index, 2343 reg_info_index)) 2344 return false; 2345 2346 /* read base register */ 2347 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0, 2348 &success); 2349 if (!success) 2350 return false; 2351 2352 /* read index register */ 2353 index_address = ReadRegisterUnsigned(eRegisterKindDWARF, 2354 dwarf_zero_mips + index, 0, &success); 2355 if (!success) 2356 return false; 2357 2358 /* destination address */ 2359 address = address + index_address; 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