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