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