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