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