3042 lines · cpp
1//===-- EmulateInstructionMIPS.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 "EmulateInstructionMIPS.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/Symbol/UnwindPlan.h"18#include "lldb/Target/Target.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(EmulateInstructionMIPS, InstructionMIPS)45 46#define UInt(x) ((uint64_t)x)47#define integer int64_t48 49//50// EmulateInstructionMIPS implementation51//52 53#ifdef __mips__54extern "C" {55void LLVMInitializeMipsTargetInfo();56void LLVMInitializeMipsTarget();57void LLVMInitializeMipsAsmPrinter();58void LLVMInitializeMipsTargetMC();59void LLVMInitializeMipsDisassembler();60}61#endif62 63EmulateInstructionMIPS::EmulateInstructionMIPS(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 150 m_reg_info.reset(target->createMCRegInfo(triple));151 assert(m_reg_info.get());152 153 m_insn_info.reset(target->createMCInstrInfo());154 assert(m_insn_info.get());155 156 llvm::MCTargetOptions MCOptions;157 m_asm_info.reset(target->createMCAsmInfo(*m_reg_info, triple, MCOptions));158 m_subtype_info.reset(target->createMCSubtargetInfo(triple, cpu, features));159 assert(m_asm_info.get() && m_subtype_info.get());160 161 m_context = std::make_unique<llvm::MCContext>(162 triple, m_asm_info.get(), m_reg_info.get(), m_subtype_info.get());163 assert(m_context.get());164 165 m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context));166 assert(m_disasm.get());167 168 /* Create alternate disassembler for microMIPS */169 if (arch_flags & ArchSpec::eMIPSAse_mips16)170 features += "+mips16,";171 else if (arch_flags & ArchSpec::eMIPSAse_micromips)172 features += "+micromips,";173 174 m_alt_subtype_info.reset(175 target->createMCSubtargetInfo(triple, cpu, features));176 assert(m_alt_subtype_info.get());177 178 m_alt_disasm.reset(179 target->createMCDisassembler(*m_alt_subtype_info, *m_context));180 assert(m_alt_disasm.get());181 182 m_next_inst_size = 0;183 m_use_alt_disaasm = false;184}185 186void EmulateInstructionMIPS::Initialize() {187 PluginManager::RegisterPlugin(GetPluginNameStatic(),188 GetPluginDescriptionStatic(), CreateInstance);189}190 191void EmulateInstructionMIPS::Terminate() {192 PluginManager::UnregisterPlugin(CreateInstance);193}194 195llvm::StringRef EmulateInstructionMIPS::GetPluginDescriptionStatic() {196 return "Emulate instructions for the MIPS32 architecture.";197}198 199EmulateInstruction *200EmulateInstructionMIPS::CreateInstance(const ArchSpec &arch,201 InstructionType inst_type) {202 if (EmulateInstructionMIPS::SupportsEmulatingInstructionsOfTypeStatic(203 inst_type)) {204 if (arch.GetTriple().getArch() == llvm::Triple::mips ||205 arch.GetTriple().getArch() == llvm::Triple::mipsel) {206 return new EmulateInstructionMIPS(arch);207 }208 }209 210 return nullptr;211}212 213bool EmulateInstructionMIPS::SetTargetTriple(const ArchSpec &arch) {214 return arch.GetTriple().getArch() == llvm::Triple::mips ||215 arch.GetTriple().getArch() == llvm::Triple::mipsel;216}217 218const char *EmulateInstructionMIPS::GetRegisterName(unsigned reg_num,219 bool alternate_name) {220 if (alternate_name) {221 switch (reg_num) {222 case dwarf_sp_mips:223 return "r29";224 case dwarf_r30_mips:225 return "r30";226 case dwarf_ra_mips:227 return "r31";228 case dwarf_f0_mips:229 return "f0";230 case dwarf_f1_mips:231 return "f1";232 case dwarf_f2_mips:233 return "f2";234 case dwarf_f3_mips:235 return "f3";236 case dwarf_f4_mips:237 return "f4";238 case dwarf_f5_mips:239 return "f5";240 case dwarf_f6_mips:241 return "f6";242 case dwarf_f7_mips:243 return "f7";244 case dwarf_f8_mips:245 return "f8";246 case dwarf_f9_mips:247 return "f9";248 case dwarf_f10_mips:249 return "f10";250 case dwarf_f11_mips:251 return "f11";252 case dwarf_f12_mips:253 return "f12";254 case dwarf_f13_mips:255 return "f13";256 case dwarf_f14_mips:257 return "f14";258 case dwarf_f15_mips:259 return "f15";260 case dwarf_f16_mips:261 return "f16";262 case dwarf_f17_mips:263 return "f17";264 case dwarf_f18_mips:265 return "f18";266 case dwarf_f19_mips:267 return "f19";268 case dwarf_f20_mips:269 return "f20";270 case dwarf_f21_mips:271 return "f21";272 case dwarf_f22_mips:273 return "f22";274 case dwarf_f23_mips:275 return "f23";276 case dwarf_f24_mips:277 return "f24";278 case dwarf_f25_mips:279 return "f25";280 case dwarf_f26_mips:281 return "f26";282 case dwarf_f27_mips:283 return "f27";284 case dwarf_f28_mips:285 return "f28";286 case dwarf_f29_mips:287 return "f29";288 case dwarf_f30_mips:289 return "f30";290 case dwarf_f31_mips:291 return "f31";292 case dwarf_w0_mips:293 return "w0";294 case dwarf_w1_mips:295 return "w1";296 case dwarf_w2_mips:297 return "w2";298 case dwarf_w3_mips:299 return "w3";300 case dwarf_w4_mips:301 return "w4";302 case dwarf_w5_mips:303 return "w5";304 case dwarf_w6_mips:305 return "w6";306 case dwarf_w7_mips:307 return "w7";308 case dwarf_w8_mips:309 return "w8";310 case dwarf_w9_mips:311 return "w9";312 case dwarf_w10_mips:313 return "w10";314 case dwarf_w11_mips:315 return "w11";316 case dwarf_w12_mips:317 return "w12";318 case dwarf_w13_mips:319 return "w13";320 case dwarf_w14_mips:321 return "w14";322 case dwarf_w15_mips:323 return "w15";324 case dwarf_w16_mips:325 return "w16";326 case dwarf_w17_mips:327 return "w17";328 case dwarf_w18_mips:329 return "w18";330 case dwarf_w19_mips:331 return "w19";332 case dwarf_w20_mips:333 return "w20";334 case dwarf_w21_mips:335 return "w21";336 case dwarf_w22_mips:337 return "w22";338 case dwarf_w23_mips:339 return "w23";340 case dwarf_w24_mips:341 return "w24";342 case dwarf_w25_mips:343 return "w25";344 case dwarf_w26_mips:345 return "w26";346 case dwarf_w27_mips:347 return "w27";348 case dwarf_w28_mips:349 return "w28";350 case dwarf_w29_mips:351 return "w29";352 case dwarf_w30_mips:353 return "w30";354 case dwarf_w31_mips:355 return "w31";356 case dwarf_mir_mips:357 return "mir";358 case dwarf_mcsr_mips:359 return "mcsr";360 case dwarf_config5_mips:361 return "config5";362 default:363 break;364 }365 return nullptr;366 }367 368 switch (reg_num) {369 case dwarf_zero_mips:370 return "r0";371 case dwarf_r1_mips:372 return "r1";373 case dwarf_r2_mips:374 return "r2";375 case dwarf_r3_mips:376 return "r3";377 case dwarf_r4_mips:378 return "r4";379 case dwarf_r5_mips:380 return "r5";381 case dwarf_r6_mips:382 return "r6";383 case dwarf_r7_mips:384 return "r7";385 case dwarf_r8_mips:386 return "r8";387 case dwarf_r9_mips:388 return "r9";389 case dwarf_r10_mips:390 return "r10";391 case dwarf_r11_mips:392 return "r11";393 case dwarf_r12_mips:394 return "r12";395 case dwarf_r13_mips:396 return "r13";397 case dwarf_r14_mips:398 return "r14";399 case dwarf_r15_mips:400 return "r15";401 case dwarf_r16_mips:402 return "r16";403 case dwarf_r17_mips:404 return "r17";405 case dwarf_r18_mips:406 return "r18";407 case dwarf_r19_mips:408 return "r19";409 case dwarf_r20_mips:410 return "r20";411 case dwarf_r21_mips:412 return "r21";413 case dwarf_r22_mips:414 return "r22";415 case dwarf_r23_mips:416 return "r23";417 case dwarf_r24_mips:418 return "r24";419 case dwarf_r25_mips:420 return "r25";421 case dwarf_r26_mips:422 return "r26";423 case dwarf_r27_mips:424 return "r27";425 case dwarf_gp_mips:426 return "gp";427 case dwarf_sp_mips:428 return "sp";429 case dwarf_r30_mips:430 return "fp";431 case dwarf_ra_mips:432 return "ra";433 case dwarf_sr_mips:434 return "sr";435 case dwarf_lo_mips:436 return "lo";437 case dwarf_hi_mips:438 return "hi";439 case dwarf_bad_mips:440 return "bad";441 case dwarf_cause_mips:442 return "cause";443 case dwarf_pc_mips:444 return "pc";445 case dwarf_f0_mips:446 return "f0";447 case dwarf_f1_mips:448 return "f1";449 case dwarf_f2_mips:450 return "f2";451 case dwarf_f3_mips:452 return "f3";453 case dwarf_f4_mips:454 return "f4";455 case dwarf_f5_mips:456 return "f5";457 case dwarf_f6_mips:458 return "f6";459 case dwarf_f7_mips:460 return "f7";461 case dwarf_f8_mips:462 return "f8";463 case dwarf_f9_mips:464 return "f9";465 case dwarf_f10_mips:466 return "f10";467 case dwarf_f11_mips:468 return "f11";469 case dwarf_f12_mips:470 return "f12";471 case dwarf_f13_mips:472 return "f13";473 case dwarf_f14_mips:474 return "f14";475 case dwarf_f15_mips:476 return "f15";477 case dwarf_f16_mips:478 return "f16";479 case dwarf_f17_mips:480 return "f17";481 case dwarf_f18_mips:482 return "f18";483 case dwarf_f19_mips:484 return "f19";485 case dwarf_f20_mips:486 return "f20";487 case dwarf_f21_mips:488 return "f21";489 case dwarf_f22_mips:490 return "f22";491 case dwarf_f23_mips:492 return "f23";493 case dwarf_f24_mips:494 return "f24";495 case dwarf_f25_mips:496 return "f25";497 case dwarf_f26_mips:498 return "f26";499 case dwarf_f27_mips:500 return "f27";501 case dwarf_f28_mips:502 return "f28";503 case dwarf_f29_mips:504 return "f29";505 case dwarf_f30_mips:506 return "f30";507 case dwarf_f31_mips:508 return "f31";509 case dwarf_fcsr_mips:510 return "fcsr";511 case dwarf_fir_mips:512 return "fir";513 case dwarf_w0_mips:514 return "w0";515 case dwarf_w1_mips:516 return "w1";517 case dwarf_w2_mips:518 return "w2";519 case dwarf_w3_mips:520 return "w3";521 case dwarf_w4_mips:522 return "w4";523 case dwarf_w5_mips:524 return "w5";525 case dwarf_w6_mips:526 return "w6";527 case dwarf_w7_mips:528 return "w7";529 case dwarf_w8_mips:530 return "w8";531 case dwarf_w9_mips:532 return "w9";533 case dwarf_w10_mips:534 return "w10";535 case dwarf_w11_mips:536 return "w11";537 case dwarf_w12_mips:538 return "w12";539 case dwarf_w13_mips:540 return "w13";541 case dwarf_w14_mips:542 return "w14";543 case dwarf_w15_mips:544 return "w15";545 case dwarf_w16_mips:546 return "w16";547 case dwarf_w17_mips:548 return "w17";549 case dwarf_w18_mips:550 return "w18";551 case dwarf_w19_mips:552 return "w19";553 case dwarf_w20_mips:554 return "w20";555 case dwarf_w21_mips:556 return "w21";557 case dwarf_w22_mips:558 return "w22";559 case dwarf_w23_mips:560 return "w23";561 case dwarf_w24_mips:562 return "w24";563 case dwarf_w25_mips:564 return "w25";565 case dwarf_w26_mips:566 return "w26";567 case dwarf_w27_mips:568 return "w27";569 case dwarf_w28_mips:570 return "w28";571 case dwarf_w29_mips:572 return "w29";573 case dwarf_w30_mips:574 return "w30";575 case dwarf_w31_mips:576 return "w31";577 case dwarf_mcsr_mips:578 return "mcsr";579 case dwarf_mir_mips:580 return "mir";581 case dwarf_config5_mips:582 return "config5";583 }584 return nullptr;585}586 587std::optional<RegisterInfo>588EmulateInstructionMIPS::GetRegisterInfo(RegisterKind reg_kind,589 uint32_t reg_num) {590 if (reg_kind == eRegisterKindGeneric) {591 switch (reg_num) {592 case LLDB_REGNUM_GENERIC_PC:593 reg_kind = eRegisterKindDWARF;594 reg_num = dwarf_pc_mips;595 break;596 case LLDB_REGNUM_GENERIC_SP:597 reg_kind = eRegisterKindDWARF;598 reg_num = dwarf_sp_mips;599 break;600 case LLDB_REGNUM_GENERIC_FP:601 reg_kind = eRegisterKindDWARF;602 reg_num = dwarf_r30_mips;603 break;604 case LLDB_REGNUM_GENERIC_RA:605 reg_kind = eRegisterKindDWARF;606 reg_num = dwarf_ra_mips;607 break;608 case LLDB_REGNUM_GENERIC_FLAGS:609 reg_kind = eRegisterKindDWARF;610 reg_num = dwarf_sr_mips;611 break;612 default:613 return {};614 }615 }616 617 if (reg_kind == eRegisterKindDWARF) {618 RegisterInfo reg_info;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_mips || reg_num == dwarf_fcsr_mips ||623 reg_num == dwarf_fir_mips || reg_num == dwarf_mcsr_mips ||624 reg_num == dwarf_mir_mips || reg_num == dwarf_config5_mips) {625 reg_info.byte_size = 4;626 reg_info.format = eFormatHex;627 reg_info.encoding = eEncodingUint;628 } else if ((int)reg_num >= dwarf_zero_mips &&629 (int)reg_num <= dwarf_f31_mips) {630 reg_info.byte_size = 4;631 reg_info.format = eFormatHex;632 reg_info.encoding = eEncodingUint;633 } else if ((int)reg_num >= dwarf_w0_mips &&634 (int)reg_num <= dwarf_w31_mips) {635 reg_info.byte_size = 16;636 reg_info.format = eFormatVectorOfUInt8;637 reg_info.encoding = eEncodingVector;638 } else {639 return {};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_mips:648 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;649 break;650 case dwarf_ra_mips:651 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;652 break;653 case dwarf_sp_mips:654 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;655 break;656 case dwarf_pc_mips:657 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;658 break;659 case dwarf_sr_mips:660 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;661 break;662 default:663 break;664 }665 return reg_info;666 }667 return {};668}669 670EmulateInstructionMIPS::MipsOpcode *671EmulateInstructionMIPS::GetOpcodeForInstruction(llvm::StringRef name) {672 static EmulateInstructionMIPS::MipsOpcode g_opcodes[] = {673 // Prologue/Epilogue instructions674 {"ADDiu", &EmulateInstructionMIPS::Emulate_ADDiu,675 "ADDIU rt, rs, immediate"},676 {"SW", &EmulateInstructionMIPS::Emulate_SW, "SW rt, offset(rs)"},677 {"LW", &EmulateInstructionMIPS::Emulate_LW, "LW rt, offset(base)"},678 {"SUBU", &EmulateInstructionMIPS::Emulate_SUBU_ADDU, "SUBU rd, rs, rt"},679 {"ADDU", &EmulateInstructionMIPS::Emulate_SUBU_ADDU, "ADDU rd, rs, rt"},680 {"LUI", &EmulateInstructionMIPS::Emulate_LUI, "LUI rt, immediate"},681 682 // MicroMIPS Prologue/Epilogue instructions683 {"ADDIUSP_MM", &EmulateInstructionMIPS::Emulate_ADDIUSP,684 "ADDIU immediate"},685 {"ADDIUS5_MM", &EmulateInstructionMIPS::Emulate_ADDIUS5,686 "ADDIUS5 rd,immediate"},687 {"SWSP_MM", &EmulateInstructionMIPS::Emulate_SWSP, "SWSP rt,offset(sp)"},688 {"SWM16_MM", &EmulateInstructionMIPS::Emulate_SWM16_32,689 "SWM16 reglist,offset(sp)"},690 {"SWM32_MM", &EmulateInstructionMIPS::Emulate_SWM16_32,691 "SWM32 reglist,offset(base)"},692 {"SWP_MM", &EmulateInstructionMIPS::Emulate_SWM16_32,693 "SWP rs1,offset(base)"},694 {"LWSP_MM", &EmulateInstructionMIPS::Emulate_LWSP, "LWSP rt,offset(sp)"},695 {"LWM16_MM", &EmulateInstructionMIPS::Emulate_LWM16_32,696 "LWM16 reglist,offset(sp)"},697 {"LWM32_MM", &EmulateInstructionMIPS::Emulate_LWM16_32,698 "LWM32 reglist,offset(base)"},699 {"LWP_MM", &EmulateInstructionMIPS::Emulate_LWM16_32,700 "LWP rd,offset(base)"},701 {"JRADDIUSP", &EmulateInstructionMIPS::Emulate_JRADDIUSP,702 "JRADDIUSP immediate"},703 704 // Load/Store instructions705 /* Following list of emulated instructions are required by implementation706 of hardware watchpoint707 for MIPS in lldb. As we just need the address accessed by instructions,708 we have generalised709 all these instructions in 2 functions depending on their addressing710 modes */711 712 {"LB", &EmulateInstructionMIPS::Emulate_LDST_Imm,713 "LB rt, offset(base)"},714 {"LBE", &EmulateInstructionMIPS::Emulate_LDST_Imm,715 "LBE rt, offset(base)"},716 {"LBU", &EmulateInstructionMIPS::Emulate_LDST_Imm,717 "LBU rt, offset(base)"},718 {"LBUE", &EmulateInstructionMIPS::Emulate_LDST_Imm,719 "LBUE rt, offset(base)"},720 {"LDC1", &EmulateInstructionMIPS::Emulate_LDST_Imm,721 "LDC1 ft, offset(base)"},722 {"LD", &EmulateInstructionMIPS::Emulate_LDST_Imm,723 "LD rt, offset(base)"},724 {"LDL", &EmulateInstructionMIPS::Emulate_LDST_Imm,725 "LDL rt, offset(base)"},726 {"LDR", &EmulateInstructionMIPS::Emulate_LDST_Imm,727 "LDR rt, offset(base)"},728 {"LLD", &EmulateInstructionMIPS::Emulate_LDST_Imm,729 "LLD rt, offset(base)"},730 {"LDC2", &EmulateInstructionMIPS::Emulate_LDST_Imm,731 "LDC2 rt, offset(base)"},732 {"LDXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,733 "LDXC1 fd, index (base)"},734 {"LH", &EmulateInstructionMIPS::Emulate_LDST_Imm,735 "LH rt, offset(base)"},736 {"LHE", &EmulateInstructionMIPS::Emulate_LDST_Imm,737 "LHE rt, offset(base)"},738 {"LHU", &EmulateInstructionMIPS::Emulate_LDST_Imm,739 "LHU rt, offset(base)"},740 {"LHUE", &EmulateInstructionMIPS::Emulate_LDST_Imm,741 "LHUE rt, offset(base)"},742 {"LL", &EmulateInstructionMIPS::Emulate_LDST_Imm,743 "LL rt, offset(base)"},744 {"LLE", &EmulateInstructionMIPS::Emulate_LDST_Imm,745 "LLE rt, offset(base)"},746 {"LUXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,747 "LUXC1 fd, index (base)"},748 {"LW", &EmulateInstructionMIPS::Emulate_LDST_Imm,749 "LW rt, offset(base)"},750 {"LWC1", &EmulateInstructionMIPS::Emulate_LDST_Imm,751 "LWC1 ft, offset(base)"},752 {"LWC2", &EmulateInstructionMIPS::Emulate_LDST_Imm,753 "LWC2 rt, offset(base)"},754 {"LWE", &EmulateInstructionMIPS::Emulate_LDST_Imm,755 "LWE rt, offset(base)"},756 {"LWL", &EmulateInstructionMIPS::Emulate_LDST_Imm,757 "LWL rt, offset(base)"},758 {"LWLE", &EmulateInstructionMIPS::Emulate_LDST_Imm,759 "LWLE rt, offset(base)"},760 {"LWR", &EmulateInstructionMIPS::Emulate_LDST_Imm,761 "LWR rt, offset(base)"},762 {"LWRE", &EmulateInstructionMIPS::Emulate_LDST_Imm,763 "LWRE rt, offset(base)"},764 {"LWXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,765 "LWXC1 fd, index (base)"},766 {"LLX", &EmulateInstructionMIPS::Emulate_LDST_Imm,767 "LLX rt, offset(base)"},768 {"LLXE", &EmulateInstructionMIPS::Emulate_LDST_Imm,769 "LLXE rt, offset(base)"},770 {"LLDX", &EmulateInstructionMIPS::Emulate_LDST_Imm,771 "LLDX rt, offset(base)"},772 773 {"SB", &EmulateInstructionMIPS::Emulate_LDST_Imm,774 "SB rt, offset(base)"},775 {"SBE", &EmulateInstructionMIPS::Emulate_LDST_Imm,776 "SBE rt, offset(base)"},777 {"SC", &EmulateInstructionMIPS::Emulate_LDST_Imm,778 "SC rt, offset(base)"},779 {"SCE", &EmulateInstructionMIPS::Emulate_LDST_Imm,780 "SCE rt, offset(base)"},781 {"SCD", &EmulateInstructionMIPS::Emulate_LDST_Imm,782 "SCD rt, offset(base)"},783 {"SD", &EmulateInstructionMIPS::Emulate_LDST_Imm,784 "SD rt, offset(base)"},785 {"SDL", &EmulateInstructionMIPS::Emulate_LDST_Imm,786 "SDL rt, offset(base)"},787 {"SDR", &EmulateInstructionMIPS::Emulate_LDST_Imm,788 "SDR rt, offset(base)"},789 {"SDC1", &EmulateInstructionMIPS::Emulate_LDST_Imm,790 "SDC1 ft, offset(base)"},791 {"SDC2", &EmulateInstructionMIPS::Emulate_LDST_Imm,792 "SDC2 rt, offset(base)"},793 {"SDXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,794 "SDXC1 fs, index(base)"},795 {"SH", &EmulateInstructionMIPS::Emulate_LDST_Imm,796 "SH rt, offset(base)"},797 {"SHE", &EmulateInstructionMIPS::Emulate_LDST_Imm,798 "SHE rt, offset(base)"},799 {"SUXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,800 "SUXC1 fs, index (base)"},801 {"SWC1", &EmulateInstructionMIPS::Emulate_LDST_Imm,802 "SWC1 ft, offset(base)"},803 {"SWC2", &EmulateInstructionMIPS::Emulate_LDST_Imm,804 "SWC2 rt, offset(base)"},805 {"SWE", &EmulateInstructionMIPS::Emulate_LDST_Imm,806 "SWE rt, offset(base)"},807 {"SWL", &EmulateInstructionMIPS::Emulate_LDST_Imm,808 "SWL rt, offset(base)"},809 {"SWLE", &EmulateInstructionMIPS::Emulate_LDST_Imm,810 "SWLE rt, offset(base)"},811 {"SWR", &EmulateInstructionMIPS::Emulate_LDST_Imm,812 "SWR rt, offset(base)"},813 {"SWRE", &EmulateInstructionMIPS::Emulate_LDST_Imm,814 "SWRE rt, offset(base)"},815 {"SWXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,816 "SWXC1 fs, index (base)"},817 {"SCX", &EmulateInstructionMIPS::Emulate_LDST_Imm,818 "SCX rt, offset(base)"},819 {"SCXE", &EmulateInstructionMIPS::Emulate_LDST_Imm,820 "SCXE rt, offset(base)"},821 {"SCDX", &EmulateInstructionMIPS::Emulate_LDST_Imm,822 "SCDX rt, offset(base)"},823 824 // MicroMIPS Load/Store instructions825 {"LBU16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,826 "LBU16 rt, decoded_offset(base)"},827 {"LHU16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,828 "LHU16 rt, left_shifted_offset(base)"},829 {"LW16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,830 "LW16 rt, left_shifted_offset(base)"},831 {"LWGP_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,832 "LWGP rt, left_shifted_offset(gp)"},833 {"SH16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,834 "SH16 rt, left_shifted_offset(base)"},835 {"SW16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,836 "SW16 rt, left_shifted_offset(base)"},837 {"SW_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,838 "SWSP rt, left_shifted_offset(base)"},839 {"SB16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,840 "SB16 rt, offset(base)"},841 842 // Branch instructions843 {"BEQ", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BEQ rs,rt,offset"},844 {"BNE", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BNE rs,rt,offset"},845 {"BEQL", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BEQL rs,rt,offset"},846 {"BNEL", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BNEL rs,rt,offset"},847 {"BGEZALL", &EmulateInstructionMIPS::Emulate_Bcond_Link,848 "BGEZALL rt,offset"},849 {"BAL", &EmulateInstructionMIPS::Emulate_BAL, "BAL offset"},850 {"BGEZAL", &EmulateInstructionMIPS::Emulate_Bcond_Link,851 "BGEZAL rs,offset"},852 {"BALC", &EmulateInstructionMIPS::Emulate_BALC, "BALC offset"},853 {"BC", &EmulateInstructionMIPS::Emulate_BC, "BC offset"},854 {"BGEZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGEZ rs,offset"},855 {"BLEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,856 "BLEZALC rs,offset"},857 {"BGEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,858 "BGEZALC rs,offset"},859 {"BLTZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,860 "BLTZALC rs,offset"},861 {"BGTZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,862 "BGTZALC rs,offset"},863 {"BEQZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,864 "BEQZALC rs,offset"},865 {"BNEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,866 "BNEZALC rs,offset"},867 {"BEQC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,868 "BEQC rs,rt,offset"},869 {"BNEC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,870 "BNEC rs,rt,offset"},871 {"BLTC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,872 "BLTC rs,rt,offset"},873 {"BGEC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,874 "BGEC rs,rt,offset"},875 {"BLTUC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,876 "BLTUC rs,rt,offset"},877 {"BGEUC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,878 "BGEUC rs,rt,offset"},879 {"BLTZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BLTZC rt,offset"},880 {"BLEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BLEZC rt,offset"},881 {"BGEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BGEZC rt,offset"},882 {"BGTZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BGTZC rt,offset"},883 {"BEQZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BEQZC rt,offset"},884 {"BNEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BNEZC rt,offset"},885 {"BGEZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGEZL rt,offset"},886 {"BGTZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGTZ rt,offset"},887 {"BGTZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGTZL rt,offset"},888 {"BLEZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLEZ rt,offset"},889 {"BLEZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLEZL rt,offset"},890 {"BLTZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLTZ rt,offset"},891 {"BLTZAL", &EmulateInstructionMIPS::Emulate_Bcond_Link,892 "BLTZAL rt,offset"},893 {"BLTZALL", &EmulateInstructionMIPS::Emulate_Bcond_Link,894 "BLTZALL rt,offset"},895 {"BLTZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLTZL rt,offset"},896 {"BOVC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,897 "BOVC rs,rt,offset"},898 {"BNVC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,899 "BNVC rs,rt,offset"},900 {"J", &EmulateInstructionMIPS::Emulate_J, "J target"},901 {"JAL", &EmulateInstructionMIPS::Emulate_JAL, "JAL target"},902 {"JALX", &EmulateInstructionMIPS::Emulate_JAL, "JALX target"},903 {"JALR", &EmulateInstructionMIPS::Emulate_JALR, "JALR target"},904 {"JALR_HB", &EmulateInstructionMIPS::Emulate_JALR, "JALR.HB target"},905 {"JIALC", &EmulateInstructionMIPS::Emulate_JIALC, "JIALC rt,offset"},906 {"JIC", &EmulateInstructionMIPS::Emulate_JIC, "JIC rt,offset"},907 {"JR", &EmulateInstructionMIPS::Emulate_JR, "JR target"},908 {"JR_HB", &EmulateInstructionMIPS::Emulate_JR, "JR.HB target"},909 {"BC1F", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1F cc, offset"},910 {"BC1T", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1T cc, offset"},911 {"BC1FL", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1FL cc, offset"},912 {"BC1TL", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1TL cc, offset"},913 {"BC1EQZ", &EmulateInstructionMIPS::Emulate_BC1EQZ, "BC1EQZ ft, offset"},914 {"BC1NEZ", &EmulateInstructionMIPS::Emulate_BC1NEZ, "BC1NEZ ft, offset"},915 {"BC1ANY2F", &EmulateInstructionMIPS::Emulate_3D_branch,916 "BC1ANY2F cc, offset"},917 {"BC1ANY2T", &EmulateInstructionMIPS::Emulate_3D_branch,918 "BC1ANY2T cc, offset"},919 {"BC1ANY4F", &EmulateInstructionMIPS::Emulate_3D_branch,920 "BC1ANY4F cc, offset"},921 {"BC1ANY4T", &EmulateInstructionMIPS::Emulate_3D_branch,922 "BC1ANY4T cc, offset"},923 {"BNZ_B", &EmulateInstructionMIPS::Emulate_BNZB, "BNZ.b wt,s16"},924 {"BNZ_H", &EmulateInstructionMIPS::Emulate_BNZH, "BNZ.h wt,s16"},925 {"BNZ_W", &EmulateInstructionMIPS::Emulate_BNZW, "BNZ.w wt,s16"},926 {"BNZ_D", &EmulateInstructionMIPS::Emulate_BNZD, "BNZ.d wt,s16"},927 {"BZ_B", &EmulateInstructionMIPS::Emulate_BZB, "BZ.b wt,s16"},928 {"BZ_H", &EmulateInstructionMIPS::Emulate_BZH, "BZ.h wt,s16"},929 {"BZ_W", &EmulateInstructionMIPS::Emulate_BZW, "BZ.w wt,s16"},930 {"BZ_D", &EmulateInstructionMIPS::Emulate_BZD, "BZ.d wt,s16"},931 {"BNZ_V", &EmulateInstructionMIPS::Emulate_BNZV, "BNZ.V wt,s16"},932 {"BZ_V", &EmulateInstructionMIPS::Emulate_BZV, "BZ.V wt,s16"},933 934 // MicroMIPS Branch instructions935 {"B16_MM", &EmulateInstructionMIPS::Emulate_B16_MM, "B16 offset"},936 {"BEQZ16_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,937 "BEQZ16 rs, offset"},938 {"BNEZ16_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,939 "BNEZ16 rs, offset"},940 {"BEQZC_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,941 "BEQZC rs, offset"},942 {"BNEZC_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,943 "BNEZC rs, offset"},944 {"BGEZALS_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,945 "BGEZALS rs, offset"},946 {"BLTZALS_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,947 "BLTZALS rs, offset"},948 {"JALR16_MM", &EmulateInstructionMIPS::Emulate_JALRx16_MM, "JALR16 rs"},949 {"JALRS16_MM", &EmulateInstructionMIPS::Emulate_JALRx16_MM, "JALRS16 rs"},950 {"JR16_MM", &EmulateInstructionMIPS::Emulate_JR, "JR16 rs rs"},951 {"JRC16_MM", &EmulateInstructionMIPS::Emulate_JR, "JRC16 rs rs"},952 {"JALS_MM", &EmulateInstructionMIPS::Emulate_JALx, "JALS target"},953 {"JALX_MM", &EmulateInstructionMIPS::Emulate_JALx, "JALX target"},954 {"JALRS_MM", &EmulateInstructionMIPS::Emulate_JALRS, "JALRS rt, rs"},955 };956 957 for (MipsOpcode &opcode : g_opcodes) {958 if (name.equals_insensitive(opcode.op_name))959 return &opcode;960 }961 return nullptr;962}963 964uint32_t965EmulateInstructionMIPS::GetSizeOfInstruction(lldb_private::DataExtractor &data,966 uint64_t inst_addr) {967 uint64_t next_inst_size = 0;968 llvm::MCInst mc_insn;969 llvm::MCDisassembler::DecodeStatus decode_status;970 llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());971 972 if (m_use_alt_disaasm)973 decode_status = m_alt_disasm->getInstruction(974 mc_insn, next_inst_size, raw_insn, inst_addr, llvm::nulls());975 else976 decode_status = m_disasm->getInstruction(mc_insn, next_inst_size, raw_insn,977 inst_addr, llvm::nulls());978 979 if (decode_status != llvm::MCDisassembler::Success)980 return false;981 982 return m_insn_info->get(mc_insn.getOpcode()).getSize();983}984 985bool EmulateInstructionMIPS::SetInstruction(const Opcode &insn_opcode,986 const Address &inst_addr,987 Target *target) {988 m_use_alt_disaasm = false;989 990 if (EmulateInstruction::SetInstruction(insn_opcode, inst_addr, target)) {991 if (inst_addr.GetAddressClass() == AddressClass::eCodeAlternateISA) {992 Status error;993 lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;994 995 /*996 * The address belongs to microMIPS function. To find the size of997 * next instruction use microMIPS disassembler.998 */999 m_use_alt_disaasm = true;1000 1001 uint32_t current_inst_size = insn_opcode.GetByteSize();1002 uint8_t buf[sizeof(uint32_t)];1003 uint64_t next_inst_addr = (m_addr & (~1ull)) + current_inst_size;1004 Address next_addr(next_inst_addr);1005 1006 const size_t bytes_read = target->ReadMemory(1007 next_addr, /* Address of next instruction */1008 buf, sizeof(uint32_t), error, false, /* force_live_memory */1009 &load_addr);1010 1011 if (bytes_read == 0)1012 return true;1013 1014 DataExtractor data(buf, sizeof(uint32_t), GetByteOrder(),1015 GetAddressByteSize());1016 m_next_inst_size = GetSizeOfInstruction(data, next_inst_addr);1017 return true;1018 } else {1019 /*1020 * If the address class is not AddressClass::eCodeAlternateISA then1021 * the function is not microMIPS. In this case instruction size is1022 * always 4 bytes.1023 */1024 m_next_inst_size = 4;1025 return true;1026 }1027 }1028 return false;1029}1030 1031bool EmulateInstructionMIPS::ReadInstruction() {1032 bool success = false;1033 m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,1034 LLDB_INVALID_ADDRESS, &success);1035 if (success) {1036 Context read_inst_context;1037 read_inst_context.type = eContextReadOpcode;1038 read_inst_context.SetNoArgs();1039 m_opcode.SetOpcode32(1040 ReadMemoryUnsigned(read_inst_context, m_addr, 4, 0, &success),1041 GetByteOrder());1042 }1043 if (!success)1044 m_addr = LLDB_INVALID_ADDRESS;1045 return success;1046}1047 1048bool EmulateInstructionMIPS::EvaluateInstruction(uint32_t evaluate_options) {1049 bool success = false;1050 llvm::MCInst mc_insn;1051 uint64_t insn_size;1052 DataExtractor data;1053 1054 /* Keep the complexity of the decode logic with the llvm::MCDisassembler1055 * class. */1056 if (m_opcode.GetData(data)) {1057 llvm::MCDisassembler::DecodeStatus decode_status;1058 llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());1059 if (m_use_alt_disaasm)1060 decode_status = m_alt_disasm->getInstruction(mc_insn, insn_size, raw_insn,1061 m_addr, llvm::nulls());1062 else1063 decode_status = m_disasm->getInstruction(mc_insn, insn_size, raw_insn,1064 m_addr, llvm::nulls());1065 1066 if (decode_status != llvm::MCDisassembler::Success)1067 return false;1068 }1069 1070 /*1071 * mc_insn.getOpcode() returns decoded opcode. However to make use1072 * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc".1073 */1074 const char *op_name = m_insn_info->getName(mc_insn.getOpcode()).data();1075 1076 if (op_name == nullptr)1077 return false;1078 1079 /*1080 * Decoding has been done already. Just get the call-back function1081 * and emulate the instruction.1082 */1083 MipsOpcode *opcode_data = GetOpcodeForInstruction(op_name);1084 1085 if (opcode_data == nullptr)1086 return false;1087 1088 uint64_t old_pc = 0, new_pc = 0;1089 const bool auto_advance_pc =1090 evaluate_options & eEmulateInstructionOptionAutoAdvancePC;1091 1092 if (auto_advance_pc) {1093 old_pc =1094 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);1095 if (!success)1096 return false;1097 }1098 1099 /* emulate instruction */1100 success = (this->*opcode_data->callback)(mc_insn);1101 if (!success)1102 return false;1103 1104 if (auto_advance_pc) {1105 new_pc =1106 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);1107 if (!success)1108 return false;1109 1110 /* If we haven't changed the PC, change it here */1111 if (old_pc == new_pc) {1112 new_pc += 4;1113 Context context;1114 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,1115 new_pc))1116 return false;1117 }1118 }1119 1120 return true;1121}1122 1123bool EmulateInstructionMIPS::CreateFunctionEntryUnwind(1124 UnwindPlan &unwind_plan) {1125 unwind_plan.Clear();1126 unwind_plan.SetRegisterKind(eRegisterKindDWARF);1127 1128 UnwindPlan::Row row;1129 const bool can_replace = false;1130 1131 // Our previous Call Frame Address is the stack pointer1132 row.GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips, 0);1133 1134 // Our previous PC is in the RA1135 row.SetRegisterLocationToRegister(dwarf_pc_mips, dwarf_ra_mips, can_replace);1136 1137 unwind_plan.AppendRow(std::move(row));1138 1139 // All other registers are the same.1140 unwind_plan.SetSourceName("EmulateInstructionMIPS");1141 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);1142 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);1143 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);1144 unwind_plan.SetReturnAddressRegister(dwarf_ra_mips);1145 1146 return true;1147}1148 1149bool EmulateInstructionMIPS::nonvolatile_reg_p(uint32_t regnum) {1150 switch (regnum) {1151 case dwarf_r16_mips:1152 case dwarf_r17_mips:1153 case dwarf_r18_mips:1154 case dwarf_r19_mips:1155 case dwarf_r20_mips:1156 case dwarf_r21_mips:1157 case dwarf_r22_mips:1158 case dwarf_r23_mips:1159 case dwarf_gp_mips:1160 case dwarf_sp_mips:1161 case dwarf_r30_mips:1162 case dwarf_ra_mips:1163 return true;1164 default:1165 return false;1166 }1167 return false;1168}1169 1170bool EmulateInstructionMIPS::Emulate_ADDiu(llvm::MCInst &insn) {1171 // ADDIU rt, rs, immediate1172 // GPR[rt] <- GPR[rs] + sign_extend(immediate)1173 1174 uint8_t dst, src;1175 bool success = false;1176 const uint32_t imm16 = insn.getOperand(2).getImm();1177 int64_t imm = SignedBits(imm16, 15, 0);1178 1179 dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1180 src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());1181 1182 // If immediate value is greater then 2^16 - 1 then clang generate LUI,1183 // ADDIU, SUBU instructions in prolog. Example lui $1, 0x2 addiu $1, $1,1184 // -0x5920 subu $sp, $sp, $1 In this case, ADDIU dst and src will be same1185 // and not equal to sp1186 if (dst == src) {1187 Context context;1188 1189 /* read <src> register */1190 const int64_t src_opd_val = ReadRegisterUnsigned(1191 eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success);1192 if (!success)1193 return false;1194 1195 /* Check if this is daddiu sp, sp, imm16 */1196 if (dst == dwarf_sp_mips) {1197 uint64_t result = src_opd_val + imm;1198 std::optional<RegisterInfo> reg_info_sp =1199 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);1200 if (reg_info_sp)1201 context.SetRegisterPlusOffset(*reg_info_sp, imm);1202 1203 /* We are allocating bytes on stack */1204 context.type = eContextAdjustStackPointer;1205 1206 WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);1207 return true;1208 }1209 1210 imm += src_opd_val;1211 context.SetImmediateSigned(imm);1212 context.type = eContextImmediate;1213 1214 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,1215 dwarf_zero_mips + dst, imm))1216 return false;1217 }1218 1219 return true;1220}1221 1222bool EmulateInstructionMIPS::Emulate_SW(llvm::MCInst &insn) {1223 bool success = false;1224 uint32_t imm16 = insn.getOperand(2).getImm();1225 uint32_t imm = SignedBits(imm16, 15, 0);1226 uint32_t src, base;1227 int32_t address;1228 Context bad_vaddr_context;1229 1230 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1231 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());1232 1233 std::optional<RegisterInfo> reg_info_base =1234 GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base);1235 if (!reg_info_base)1236 return false;1237 1238 /* read base register */1239 address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,1240 dwarf_zero_mips + base, 0, &success);1241 if (!success)1242 return false;1243 1244 /* destination address */1245 address = address + imm;1246 1247 /* Set the bad_vaddr register with base address used in the instruction */1248 bad_vaddr_context.type = eContextInvalid;1249 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,1250 address);1251 1252 /* We look for sp based non-volatile register stores */1253 if (nonvolatile_reg_p(src)) {1254 std::optional<RegisterInfo> reg_info_src =1255 GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src);1256 if (!reg_info_src)1257 return false;1258 1259 Context context;1260 context.type = eContextPushRegisterOnStack;1261 context.SetRegisterToRegisterPlusOffset(*reg_info_src, *reg_info_base, 0);1262 1263 RegisterValue::BytesContainer buffer(reg_info_src->byte_size);1264 Status error;1265 1266 std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);1267 if (!data_src)1268 return false;1269 1270 if (data_src->GetAsMemoryData(*reg_info_src, buffer.data(),1271 reg_info_src->byte_size, eByteOrderLittle,1272 error) == 0)1273 return false;1274 1275 if (!WriteMemory(context, address, buffer.data(), reg_info_src->byte_size))1276 return false;1277 1278 return true;1279 }1280 1281 return false;1282}1283 1284bool EmulateInstructionMIPS::Emulate_LW(llvm::MCInst &insn) {1285 bool success = false;1286 uint32_t src, base;1287 int32_t imm, address;1288 Context bad_vaddr_context;1289 1290 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1291 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());1292 imm = insn.getOperand(2).getImm();1293 1294 if (GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))1295 return false;1296 1297 /* read base register */1298 address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,1299 dwarf_zero_mips + base, 0, &success);1300 if (!success)1301 return false;1302 1303 /* destination address */1304 address = address + imm;1305 1306 /* Set the bad_vaddr register with base address used in the instruction */1307 bad_vaddr_context.type = eContextInvalid;1308 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,1309 address);1310 1311 if (nonvolatile_reg_p(src)) {1312 RegisterValue data_src;1313 std::optional<RegisterInfo> reg_info_src =1314 GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src);1315 if (!reg_info_src)1316 return false;1317 1318 Context context;1319 context.type = eContextPopRegisterOffStack;1320 context.SetAddress(address);1321 1322 return WriteRegister(context, *reg_info_src, data_src);1323 }1324 1325 return false;1326}1327 1328bool EmulateInstructionMIPS::Emulate_SUBU_ADDU(llvm::MCInst &insn) {1329 // SUBU sp, <src>, <rt>1330 // ADDU sp, <src>, <rt>1331 // ADDU dst, sp, <rt>1332 1333 bool success = false;1334 uint64_t result;1335 uint8_t src, dst, rt;1336 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());1337 1338 dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1339 src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());1340 1341 /* Check if sp is destination register */1342 if (dst == dwarf_sp_mips) {1343 rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());1344 1345 /* read <src> register */1346 uint64_t src_opd_val = ReadRegisterUnsigned(1347 eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success);1348 if (!success)1349 return false;1350 1351 /* read <rt > register */1352 uint64_t rt_opd_val = ReadRegisterUnsigned(1353 eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);1354 if (!success)1355 return false;1356 1357 if (op_name.equals_insensitive("SUBU"))1358 result = src_opd_val - rt_opd_val;1359 else1360 result = src_opd_val + rt_opd_val;1361 1362 Context context;1363 std::optional<RegisterInfo> reg_info_sp =1364 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);1365 if (reg_info_sp)1366 context.SetRegisterPlusOffset(*reg_info_sp, rt_opd_val);1367 1368 /* We are allocating bytes on stack */1369 context.type = eContextAdjustStackPointer;1370 1371 WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);1372 1373 return true;1374 } else if (src == dwarf_sp_mips) {1375 rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());1376 1377 /* read <src> register */1378 uint64_t src_opd_val = ReadRegisterUnsigned(1379 eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success);1380 if (!success)1381 return false;1382 1383 /* read <rt> register */1384 uint64_t rt_opd_val = ReadRegisterUnsigned(1385 eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);1386 if (!success)1387 return false;1388 1389 Context context;1390 1391 if (op_name.equals_insensitive("SUBU"))1392 result = src_opd_val - rt_opd_val;1393 else1394 result = src_opd_val + rt_opd_val;1395 1396 context.SetImmediateSigned(result);1397 context.type = eContextImmediate;1398 1399 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,1400 dwarf_zero_mips + dst, result))1401 return false;1402 }1403 1404 return true;1405}1406 1407bool EmulateInstructionMIPS::Emulate_LUI(llvm::MCInst &insn) {1408 // LUI rt, immediate1409 // GPR[rt] <- sign_extend(immediate << 16)1410 1411 const uint32_t imm32 = insn.getOperand(1).getImm() << 16;1412 int64_t imm = SignedBits(imm32, 31, 0);1413 uint8_t rt;1414 Context context;1415 1416 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1417 context.SetImmediateSigned(imm);1418 context.type = eContextImmediate;1419 1420 return WriteRegisterUnsigned(context, eRegisterKindDWARF,1421 dwarf_zero_mips + rt, imm);1422}1423 1424bool EmulateInstructionMIPS::Emulate_ADDIUSP(llvm::MCInst &insn) {1425 bool success = false;1426 const uint32_t imm9 = insn.getOperand(0).getImm();1427 uint64_t result;1428 1429 // This instruction operates implicitly on stack pointer, so read <sp>1430 // register.1431 uint64_t src_opd_val =1432 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_sp_mips, 0, &success);1433 if (!success)1434 return false;1435 1436 result = src_opd_val + imm9;1437 1438 Context context;1439 std::optional<RegisterInfo> reg_info_sp =1440 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);1441 if (reg_info_sp)1442 context.SetRegisterPlusOffset(*reg_info_sp, imm9);1443 1444 // We are adjusting the stack.1445 context.type = eContextAdjustStackPointer;1446 1447 WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);1448 return true;1449}1450 1451bool EmulateInstructionMIPS::Emulate_ADDIUS5(llvm::MCInst &insn) {1452 bool success = false;1453 uint32_t base;1454 const uint32_t imm4 = insn.getOperand(2).getImm();1455 uint64_t result;1456 1457 // The source and destination register is same for this instruction.1458 base = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1459 1460 // We are looking for stack adjustment only1461 if (base == dwarf_sp_mips) {1462 // Read stack pointer register1463 uint64_t src_opd_val = ReadRegisterUnsigned(1464 eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);1465 if (!success)1466 return false;1467 1468 result = src_opd_val + imm4;1469 1470 Context context;1471 std::optional<RegisterInfo> reg_info_sp =1472 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);1473 if (reg_info_sp)1474 context.SetRegisterPlusOffset(*reg_info_sp, imm4);1475 1476 // We are adjusting the stack.1477 context.type = eContextAdjustStackPointer;1478 1479 WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);1480 }1481 1482 return true;1483}1484 1485bool EmulateInstructionMIPS::Emulate_SWSP(llvm::MCInst &insn) {1486 bool success = false;1487 uint32_t imm5 = insn.getOperand(2).getImm();1488 uint32_t src, base;1489 Context bad_vaddr_context;1490 uint32_t address;1491 1492 src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1493 base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());1494 1495 std::optional<RegisterInfo> reg_info_base =1496 GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base);1497 if (!reg_info_base)1498 return false;1499 1500 // read base register1501 address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0,1502 &success);1503 if (!success)1504 return false;1505 1506 // destination address1507 address = address + imm5;1508 1509 // We use bad_vaddr_context to store base address which is used by H/W1510 // watchpoint Set the bad_vaddr register with base address used in the1511 // instruction1512 bad_vaddr_context.type = eContextInvalid;1513 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,1514 address);1515 1516 // We look for sp based non-volatile register stores.1517 if (base == dwarf_sp_mips && nonvolatile_reg_p(src)) {1518 RegisterInfo reg_info_src = {};1519 Context context;1520 context.type = eContextPushRegisterOnStack;1521 context.SetRegisterToRegisterPlusOffset(reg_info_src, *reg_info_base, 0);1522 1523 RegisterValue::BytesContainer buffer(reg_info_src.byte_size);1524 Status error;1525 1526 std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);1527 if (!data_src)1528 return false;1529 1530 if (data_src->GetAsMemoryData(reg_info_src, buffer.data(),1531 reg_info_src.byte_size, eByteOrderLittle,1532 error) == 0)1533 return false;1534 1535 if (!WriteMemory(context, address, buffer.data(), reg_info_src.byte_size))1536 return false;1537 1538 return true;1539 }1540 1541 return false;1542}1543 1544/* Emulate SWM16,SWM32 and SWP instruction.1545 1546 SWM16 always has stack pointer as a base register (but it is still available1547 in MCInst as an operand).1548 SWM32 and SWP can have base register other than stack pointer.1549*/1550bool EmulateInstructionMIPS::Emulate_SWM16_32(llvm::MCInst &insn) {1551 bool success = false;1552 uint32_t src, base;1553 uint32_t num_operands = insn.getNumOperands(); // No of operands vary based on1554 // no of regs to store.1555 1556 // Base register is second last operand of the instruction.1557 base =1558 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());1559 1560 // We are looking for sp based stores so if base is not a stack pointer then1561 // don't proceed.1562 if (base != dwarf_sp_mips)1563 return false;1564 1565 // offset is always the last operand.1566 uint32_t offset = insn.getOperand(num_operands - 1).getImm();1567 1568 std::optional<RegisterInfo> reg_info_base =1569 GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base);1570 if (!reg_info_base)1571 return false;1572 1573 // read SP1574 uint32_t base_address = ReadRegisterUnsigned(1575 eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);1576 if (!success)1577 return false;1578 1579 // Resulting base addrss1580 base_address = base_address + offset;1581 1582 // Total no of registers to be stored are num_operands-2.1583 for (uint32_t i = 0; i < num_operands - 2; i++) {1584 // Get the register number to be stored.1585 src = m_reg_info->getEncodingValue(insn.getOperand(i).getReg());1586 1587 /*1588 Record only non-volatile stores.1589 This check is required for SWP instruction because source operand could1590 be any register.1591 SWM16 and SWM32 instruction always has saved registers as source1592 operands.1593 */1594 if (!nonvolatile_reg_p(src))1595 return false;1596 1597 std::optional<RegisterInfo> reg_info_src =1598 GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src);1599 if (!reg_info_src)1600 return false;1601 1602 Context context;1603 context.type = eContextPushRegisterOnStack;1604 context.SetRegisterToRegisterPlusOffset(*reg_info_src, *reg_info_base, 0);1605 1606 RegisterValue::BytesContainer buffer(reg_info_src->byte_size);1607 Status error;1608 1609 std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);1610 if (!data_src)1611 return false;1612 1613 if (data_src->GetAsMemoryData(*reg_info_src, buffer.data(),1614 reg_info_src->byte_size, eByteOrderLittle,1615 error) == 0)1616 return false;1617 1618 if (!WriteMemory(context, base_address, buffer.data(),1619 reg_info_src->byte_size))1620 return false;1621 1622 // Stack address for next register1623 base_address = base_address + reg_info_src->byte_size;1624 }1625 return true;1626}1627 1628bool EmulateInstructionMIPS::Emulate_LWSP(llvm::MCInst &insn) {1629 bool success = false;1630 uint32_t src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1631 uint32_t base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());1632 uint32_t imm5 = insn.getOperand(2).getImm();1633 Context bad_vaddr_context;1634 1635 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))1636 return false;1637 1638 // read base register1639 uint32_t base_address = ReadRegisterUnsigned(1640 eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);1641 if (!success)1642 return false;1643 1644 base_address = base_address + imm5;1645 1646 // We use bad_vaddr_context to store base address which is used by H/W1647 // watchpoint Set the bad_vaddr register with base address used in the1648 // instruction1649 bad_vaddr_context.type = eContextInvalid;1650 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,1651 base_address);1652 1653 if (base == dwarf_sp_mips && nonvolatile_reg_p(src)) {1654 RegisterValue data_src;1655 std::optional<RegisterInfo> reg_info_src =1656 GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src);1657 if (!reg_info_src)1658 return false;1659 1660 Context context;1661 context.type = eContextPopRegisterOffStack;1662 context.SetAddress(base_address);1663 1664 return WriteRegister(context, *reg_info_src, data_src);1665 }1666 1667 return false;1668}1669 1670/* Emulate LWM16, LWM32 and LWP instructions.1671 1672 LWM16 always has stack pointer as a base register (but it is still available1673 in MCInst as an operand).1674 LWM32 and LWP can have base register other than stack pointer.1675*/1676bool EmulateInstructionMIPS::Emulate_LWM16_32(llvm::MCInst &insn) {1677 bool success = false;1678 uint32_t dst, base;1679 uint32_t num_operands = insn.getNumOperands(); // No of operands vary based on1680 // no of regs to store.1681 uint32_t imm = insn.getOperand(num_operands - 1)1682 .getImm(); // imm is the last operand in the instruction.1683 1684 // Base register is second last operand of the instruction.1685 base =1686 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());1687 1688 // We are looking for sp based loads so if base is not a stack pointer then1689 // don't proceed.1690 if (base != dwarf_sp_mips)1691 return false;1692 1693 uint32_t base_address = ReadRegisterUnsigned(1694 eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);1695 if (!success)1696 return false;1697 1698 base_address = base_address + imm;1699 1700 RegisterValue data_dst;1701 1702 // Total no of registers to be re-stored are num_operands-2.1703 for (uint32_t i = 0; i < num_operands - 2; i++) {1704 // Get the register number to be re-stored.1705 dst = m_reg_info->getEncodingValue(insn.getOperand(i).getReg());1706 1707 /*1708 Record only non-volatile loads.1709 This check is required for LWP instruction because destination operand1710 could be any register.1711 LWM16 and LWM32 instruction always has saved registers as destination1712 operands.1713 */1714 if (!nonvolatile_reg_p(dst))1715 return false;1716 1717 std::optional<RegisterInfo> reg_info_dst =1718 GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + dst);1719 if (!reg_info_dst)1720 return false;1721 1722 Context context;1723 context.type = eContextPopRegisterOffStack;1724 context.SetAddress(base_address + (i * 4));1725 1726 if (!WriteRegister(context, *reg_info_dst, data_dst))1727 return false;1728 }1729 1730 return true;1731}1732 1733bool EmulateInstructionMIPS::Emulate_JRADDIUSP(llvm::MCInst &insn) {1734 bool success = false;1735 int32_t imm5 = insn.getOperand(0).getImm();1736 1737 /* JRADDIUSP immediate1738 * PC <- RA1739 * SP <- SP + zero_extend(Immediate << 2)1740 */1741 1742 // This instruction operates implicitly on stack pointer, so read <sp>1743 // register.1744 int32_t src_opd_val =1745 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_sp_mips, 0, &success);1746 if (!success)1747 return false;1748 1749 int32_t ra_val =1750 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_ra_mips, 0, &success);1751 if (!success)1752 return false;1753 1754 int32_t result = src_opd_val + imm5;1755 1756 Context context;1757 1758 // Update the PC1759 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,1760 ra_val))1761 return false;1762 1763 std::optional<RegisterInfo> reg_info_sp =1764 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);1765 if (reg_info_sp)1766 context.SetRegisterPlusOffset(*reg_info_sp, imm5);1767 1768 // We are adjusting stack1769 context.type = eContextAdjustStackPointer;1770 1771 // update SP1772 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips,1773 result);1774}1775 1776static int IsAdd64bitOverflow(int32_t a, int32_t b) {1777 int32_t r = (uint32_t)a + (uint32_t)b;1778 return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);1779}1780 1781/*1782 Emulate below MIPS branch instructions.1783 BEQ, BNE : Branch on condition1784 BEQL, BNEL : Branch likely1785*/1786bool EmulateInstructionMIPS::Emulate_BXX_3ops(llvm::MCInst &insn) {1787 bool success = false;1788 uint32_t rs, rt;1789 int32_t offset, pc, target = 0, rs_val, rt_val;1790 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());1791 1792 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1793 rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());1794 offset = insn.getOperand(2).getImm();1795 1796 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);1797 if (!success)1798 return false;1799 1800 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,1801 dwarf_zero_mips + rs, 0, &success);1802 if (!success)1803 return false;1804 1805 rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,1806 dwarf_zero_mips + rt, 0, &success);1807 if (!success)1808 return false;1809 1810 if (op_name.equals_insensitive("BEQ") || op_name.equals_insensitive("BEQL")) {1811 if (rs_val == rt_val)1812 target = pc + offset;1813 else1814 target = pc + 8;1815 } else if (op_name.equals_insensitive("BNE") ||1816 op_name.equals_insensitive("BNEL")) {1817 if (rs_val != rt_val)1818 target = pc + offset;1819 else1820 target = pc + 8;1821 }1822 1823 Context context;1824 context.type = eContextRelativeBranchImmediate;1825 context.SetImmediate(offset);1826 1827 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,1828 target);1829}1830 1831/*1832 Emulate below MIPS branch instructions.1833 BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch1834 instructions with no delay slot1835*/1836bool EmulateInstructionMIPS::Emulate_BXX_3ops_C(llvm::MCInst &insn) {1837 bool success = false;1838 uint32_t rs, rt;1839 int32_t offset, pc, target = 0, rs_val, rt_val;1840 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());1841 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();1842 1843 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1844 rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());1845 offset = insn.getOperand(2).getImm();1846 1847 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);1848 if (!success)1849 return false;1850 1851 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,1852 dwarf_zero_mips + rs, 0, &success);1853 if (!success)1854 return false;1855 1856 rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,1857 dwarf_zero_mips + rt, 0, &success);1858 if (!success)1859 return false;1860 1861 if (op_name.equals_insensitive("BEQC")) {1862 if (rs_val == rt_val)1863 target = pc + offset;1864 else1865 target = pc + 4;1866 } else if (op_name.equals_insensitive("BNEC")) {1867 if (rs_val != rt_val)1868 target = pc + offset;1869 else1870 target = pc + 4;1871 } else if (op_name.equals_insensitive("BLTC")) {1872 if (rs_val < rt_val)1873 target = pc + offset;1874 else1875 target = pc + 4;1876 } else if (op_name.equals_insensitive("BGEC")) {1877 if (rs_val >= rt_val)1878 target = pc + offset;1879 else1880 target = pc + 4;1881 } else if (op_name.equals_insensitive("BLTUC")) {1882 if (rs_val < rt_val)1883 target = pc + offset;1884 else1885 target = pc + 4;1886 } else if (op_name.equals_insensitive("BGEUC")) {1887 if ((uint32_t)rs_val >= (uint32_t)rt_val)1888 target = pc + offset;1889 else1890 target = pc + 4;1891 } else if (op_name.equals_insensitive("BOVC")) {1892 if (IsAdd64bitOverflow(rs_val, rt_val))1893 target = pc + offset;1894 else1895 target = pc + 4;1896 } else if (op_name.equals_insensitive("BNVC")) {1897 if (!IsAdd64bitOverflow(rs_val, rt_val))1898 target = pc + offset;1899 else1900 target = pc + 4;1901 }1902 1903 Context context;1904 context.type = eContextRelativeBranchImmediate;1905 context.SetImmediate(current_inst_size + offset);1906 1907 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,1908 target);1909}1910 1911/*1912 Emulate below MIPS conditional branch and link instructions.1913 BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches1914*/1915bool EmulateInstructionMIPS::Emulate_Bcond_Link_C(llvm::MCInst &insn) {1916 bool success = false;1917 uint32_t rs;1918 int32_t offset, pc, target = 0;1919 int32_t rs_val;1920 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());1921 1922 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1923 offset = insn.getOperand(1).getImm();1924 1925 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);1926 if (!success)1927 return false;1928 1929 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,1930 dwarf_zero_mips + rs, 0, &success);1931 if (!success)1932 return false;1933 1934 if (op_name.equals_insensitive("BLEZALC")) {1935 if (rs_val <= 0)1936 target = pc + offset;1937 else1938 target = pc + 4;1939 } else if (op_name.equals_insensitive("BGEZALC")) {1940 if (rs_val >= 0)1941 target = pc + offset;1942 else1943 target = pc + 4;1944 } else if (op_name.equals_insensitive("BLTZALC")) {1945 if (rs_val < 0)1946 target = pc + offset;1947 else1948 target = pc + 4;1949 } else if (op_name.equals_insensitive("BGTZALC")) {1950 if (rs_val > 0)1951 target = pc + offset;1952 else1953 target = pc + 4;1954 } else if (op_name.equals_insensitive("BEQZALC")) {1955 if (rs_val == 0)1956 target = pc + offset;1957 else1958 target = pc + 4;1959 } else if (op_name.equals_insensitive("BNEZALC")) {1960 if (rs_val != 0)1961 target = pc + offset;1962 else1963 target = pc + 4;1964 }1965 1966 Context context;1967 1968 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,1969 target))1970 return false;1971 1972 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,1973 pc + 4))1974 return false;1975 1976 return true;1977}1978 1979/*1980 Emulate below MIPS Non-Compact conditional branch and link instructions.1981 BLTZAL, BGEZAL :1982 BLTZALL, BGEZALL : Branch likely1983*/1984bool EmulateInstructionMIPS::Emulate_Bcond_Link(llvm::MCInst &insn) {1985 bool success = false;1986 uint32_t rs;1987 int32_t offset, pc, target = 0;1988 int32_t rs_val;1989 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());1990 1991 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1992 offset = insn.getOperand(1).getImm();1993 1994 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);1995 if (!success)1996 return false;1997 1998 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,1999 dwarf_zero_mips + rs, 0, &success);2000 if (!success)2001 return false;2002 2003 if (op_name.equals_insensitive("BLTZAL") ||2004 op_name.equals_insensitive("BLTZALL")) {2005 if ((int32_t)rs_val < 0)2006 target = pc + offset;2007 else2008 target = pc + 8;2009 } else if (op_name.equals_insensitive("BGEZAL") ||2010 op_name.equals_insensitive("BGEZALL")) {2011 if ((int32_t)rs_val >= 0)2012 target = pc + offset;2013 else2014 target = pc + 8;2015 }2016 2017 Context context;2018 2019 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2020 target))2021 return false;2022 2023 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,2024 pc + 8))2025 return false;2026 2027 return true;2028}2029 2030/*2031 Emulate below MIPS branch instructions.2032 BLTZL, BGEZL, BGTZL, BLEZL : Branch likely2033 BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches2034*/2035bool EmulateInstructionMIPS::Emulate_BXX_2ops(llvm::MCInst &insn) {2036 bool success = false;2037 uint32_t rs;2038 int32_t offset, pc, target = 0;2039 int32_t rs_val;2040 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());2041 2042 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2043 offset = insn.getOperand(1).getImm();2044 2045 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2046 if (!success)2047 return false;2048 2049 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,2050 dwarf_zero_mips + rs, 0, &success);2051 if (!success)2052 return false;2053 2054 if (op_name.equals_insensitive("BLTZL") ||2055 op_name.equals_insensitive("BLTZ")) {2056 if (rs_val < 0)2057 target = pc + offset;2058 else2059 target = pc + 8;2060 } else if (op_name.equals_insensitive("BGEZL") ||2061 op_name.equals_insensitive("BGEZ")) {2062 if (rs_val >= 0)2063 target = pc + offset;2064 else2065 target = pc + 8;2066 } else if (op_name.equals_insensitive("BGTZL") ||2067 op_name.equals_insensitive("BGTZ")) {2068 if (rs_val > 0)2069 target = pc + offset;2070 else2071 target = pc + 8;2072 } else if (op_name.equals_insensitive("BLEZL") ||2073 op_name.equals_insensitive("BLEZ")) {2074 if (rs_val <= 0)2075 target = pc + offset;2076 else2077 target = pc + 8;2078 }2079 2080 Context context;2081 context.type = eContextRelativeBranchImmediate;2082 context.SetImmediate(offset);2083 2084 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2085 target);2086}2087 2088/*2089 Emulate below MIPS branch instructions.2090 BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches2091*/2092bool EmulateInstructionMIPS::Emulate_BXX_2ops_C(llvm::MCInst &insn) {2093 bool success = false;2094 uint32_t rs;2095 int32_t offset, pc, target = 0;2096 int32_t rs_val;2097 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());2098 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();2099 2100 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2101 offset = insn.getOperand(1).getImm();2102 2103 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2104 if (!success)2105 return false;2106 2107 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,2108 dwarf_zero_mips + rs, 0, &success);2109 if (!success)2110 return false;2111 2112 if (op_name.equals_insensitive("BLTZC")) {2113 if (rs_val < 0)2114 target = pc + offset;2115 else2116 target = pc + 4;2117 } else if (op_name.equals_insensitive("BLEZC")) {2118 if (rs_val <= 0)2119 target = pc + offset;2120 else2121 target = pc + 4;2122 } else if (op_name.equals_insensitive("BGEZC")) {2123 if (rs_val >= 0)2124 target = pc + offset;2125 else2126 target = pc + 4;2127 } else if (op_name.equals_insensitive("BGTZC")) {2128 if (rs_val > 0)2129 target = pc + offset;2130 else2131 target = pc + 4;2132 } else if (op_name.equals_insensitive("BEQZC")) {2133 if (rs_val == 0)2134 target = pc + offset;2135 else2136 target = pc + 4;2137 } else if (op_name.equals_insensitive("BNEZC")) {2138 if (rs_val != 0)2139 target = pc + offset;2140 else2141 target = pc + 4;2142 }2143 2144 Context context;2145 context.type = eContextRelativeBranchImmediate;2146 context.SetImmediate(current_inst_size + offset);2147 2148 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2149 target);2150}2151 2152bool EmulateInstructionMIPS::Emulate_B16_MM(llvm::MCInst &insn) {2153 bool success = false;2154 int32_t offset, pc, target;2155 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();2156 2157 offset = insn.getOperand(0).getImm();2158 2159 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2160 if (!success)2161 return false;2162 2163 // unconditional branch2164 target = pc + offset;2165 2166 Context context;2167 context.type = eContextRelativeBranchImmediate;2168 context.SetImmediate(current_inst_size + offset);2169 2170 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2171 target);2172}2173 2174/*2175 BEQZC, BNEZC are 32 bit compact instructions without a delay slot.2176 BEQZ16, BNEZ16 are 16 bit instructions with delay slot.2177 BGEZALS, BLTZALS are 16 bit instructions with short (2-byte) delay slot.2178*/2179bool EmulateInstructionMIPS::Emulate_Branch_MM(llvm::MCInst &insn) {2180 bool success = false;2181 int32_t target = 0;2182 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();2183 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());2184 bool update_ra = false;2185 uint32_t ra_offset = 0;2186 2187 /*2188 * BEQZ16 rs, offset2189 * condition <- (GPR[rs] = 0)2190 * if condition then2191 * PC = PC + sign_ext (offset || 0)2192 *2193 * BNEZ16 rs, offset2194 * condition <- (GPR[rs] != 0)2195 * if condition then2196 * PC = PC + sign_ext (offset || 0)2197 *2198 * BEQZC rs, offset (compact instruction: No delay slot)2199 * condition <- (GPR[rs] == 0)2200 * if condition then2201 * PC = PC + 4 + sign_ext (offset || 0)2202 */2203 2204 uint32_t rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2205 int32_t offset = insn.getOperand(1).getImm();2206 2207 int32_t pc =2208 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2209 if (!success)2210 return false;2211 2212 int32_t rs_val = (int32_t)ReadRegisterUnsigned(2213 eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);2214 if (!success)2215 return false;2216 2217 if (op_name.equals_insensitive("BEQZ16_MM")) {2218 if (rs_val == 0)2219 target = pc + offset;2220 else2221 target = pc + current_inst_size +2222 m_next_inst_size; // Skip delay slot instruction.2223 } else if (op_name.equals_insensitive("BNEZ16_MM")) {2224 if (rs_val != 0)2225 target = pc + offset;2226 else2227 target = pc + current_inst_size +2228 m_next_inst_size; // Skip delay slot instruction.2229 } else if (op_name.equals_insensitive("BEQZC_MM")) {2230 if (rs_val == 0)2231 target = pc + 4 + offset;2232 else2233 target =2234 pc +2235 4; // 32 bit instruction and does not have delay slot instruction.2236 } else if (op_name.equals_insensitive("BNEZC_MM")) {2237 if (rs_val != 0)2238 target = pc + 4 + offset;2239 else2240 target =2241 pc +2242 4; // 32 bit instruction and does not have delay slot instruction.2243 } else if (op_name.equals_insensitive("BGEZALS_MM")) {2244 if (rs_val >= 0)2245 target = pc + offset;2246 else2247 target = pc + 6; // 32 bit instruction with short (2-byte) delay slot2248 2249 update_ra = true;2250 ra_offset = 6;2251 } else if (op_name.equals_insensitive("BLTZALS_MM")) {2252 if (rs_val >= 0)2253 target = pc + offset;2254 else2255 target = pc + 6; // 32 bit instruction with short (2-byte) delay slot2256 2257 update_ra = true;2258 ra_offset = 6;2259 }2260 2261 Context context;2262 context.type = eContextRelativeBranchImmediate;2263 context.SetImmediate(current_inst_size + offset);2264 2265 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2266 target))2267 return false;2268 2269 if (update_ra) {2270 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,2271 pc + ra_offset))2272 return false;2273 }2274 return true;2275}2276 2277/* Emulate micromips jump instructions.2278 JALR16,JALRS162279*/2280bool EmulateInstructionMIPS::Emulate_JALRx16_MM(llvm::MCInst &insn) {2281 bool success = false;2282 uint32_t ra_offset = 0;2283 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());2284 2285 uint32_t rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2286 2287 uint32_t pc =2288 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2289 if (!success)2290 return false;2291 2292 uint32_t rs_val = ReadRegisterUnsigned(eRegisterKindDWARF,2293 dwarf_zero_mips + rs, 0, &success);2294 if (!success)2295 return false;2296 2297 if (op_name.equals_insensitive("JALR16_MM"))2298 ra_offset = 6; // 2-byte instruction with 4-byte delay slot.2299 else if (op_name.equals_insensitive("JALRS16_MM"))2300 ra_offset = 4; // 2-byte instruction with 2-byte delay slot.2301 2302 Context context;2303 2304 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2305 rs_val))2306 return false;2307 2308 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,2309 pc + ra_offset))2310 return false;2311 2312 return true;2313}2314 2315/* Emulate JALS and JALX instructions.2316 JALS 32 bit instruction with short (2-byte) delay slot.2317 JALX 32 bit instruction with 4-byte delay slot.2318*/2319bool EmulateInstructionMIPS::Emulate_JALx(llvm::MCInst &insn) {2320 bool success = false;2321 uint32_t offset = 0, target = 0, pc = 0, ra_offset = 0;2322 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());2323 2324 /*2325 * JALS target2326 * RA = PC + 62327 * offset = sign_ext (offset << 1)2328 * PC = PC[31-27] | offset2329 * JALX target2330 * RA = PC + 82331 * offset = sign_ext (offset << 2)2332 * PC = PC[31-28] | offset2333 */2334 offset = insn.getOperand(0).getImm();2335 2336 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2337 if (!success)2338 return false;2339 2340 // These are PC-region branches and not PC-relative.2341 if (op_name.equals_insensitive("JALS_MM")) {2342 // target address is in the “current” 128 MB-aligned region2343 target = (pc & 0xF8000000UL) | offset;2344 ra_offset = 6;2345 } else if (op_name.equals_insensitive("JALX_MM")) {2346 // target address is in the “current” 256 MB-aligned region2347 target = (pc & 0xF0000000UL) | offset;2348 ra_offset = 8;2349 }2350 2351 Context context;2352 2353 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2354 target))2355 return false;2356 2357 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,2358 pc + ra_offset))2359 return false;2360 2361 return true;2362}2363 2364bool EmulateInstructionMIPS::Emulate_JALRS(llvm::MCInst &insn) {2365 bool success = false;2366 uint32_t rs = 0, rt = 0;2367 int32_t pc = 0, rs_val = 0;2368 2369 /*2370 JALRS rt, rs2371 GPR[rt] <- PC + 62372 PC <- GPR[rs]2373 */2374 2375 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2376 rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());2377 2378 rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,2379 dwarf_zero_mips + rs, 0, &success);2380 if (!success)2381 return false;2382 2383 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2384 if (!success)2385 return false;2386 2387 Context context;2388 2389 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2390 rs_val))2391 return false;2392 2393 // This is 4-byte instruction with 2-byte delay slot.2394 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_zero_mips + rt,2395 pc + 6))2396 return false;2397 2398 return true;2399}2400 2401bool EmulateInstructionMIPS::Emulate_BAL(llvm::MCInst &insn) {2402 bool success = false;2403 int32_t offset, pc, target;2404 2405 /*2406 * BAL offset2407 * offset = sign_ext (offset << 2)2408 * RA = PC + 82409 * PC = PC + offset2410 */2411 offset = insn.getOperand(0).getImm();2412 2413 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2414 if (!success)2415 return false;2416 2417 target = pc + offset;2418 2419 Context context;2420 2421 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2422 target))2423 return false;2424 2425 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,2426 pc + 8))2427 return false;2428 2429 return true;2430}2431 2432bool EmulateInstructionMIPS::Emulate_BALC(llvm::MCInst &insn) {2433 bool success = false;2434 int32_t offset, pc, target;2435 2436 /*2437 * BALC offset2438 * offset = sign_ext (offset << 2)2439 * RA = PC + 42440 * PC = PC + 4 + offset2441 */2442 offset = insn.getOperand(0).getImm();2443 2444 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2445 if (!success)2446 return false;2447 2448 target = pc + offset;2449 2450 Context context;2451 2452 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2453 target))2454 return false;2455 2456 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,2457 pc + 4))2458 return false;2459 2460 return true;2461}2462 2463bool EmulateInstructionMIPS::Emulate_BC(llvm::MCInst &insn) {2464 bool success = false;2465 int32_t offset, pc, target;2466 2467 /*2468 * BC offset2469 * offset = sign_ext (offset << 2)2470 * PC = PC + 4 + offset2471 */2472 offset = insn.getOperand(0).getImm();2473 2474 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2475 if (!success)2476 return false;2477 2478 target = pc + offset;2479 2480 Context context;2481 2482 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2483 target);2484}2485 2486bool EmulateInstructionMIPS::Emulate_J(llvm::MCInst &insn) {2487 bool success = false;2488 uint32_t offset, pc;2489 2490 /*2491 * J offset2492 * offset = sign_ext (offset << 2)2493 * PC = PC[63-28] | offset2494 */2495 offset = insn.getOperand(0).getImm();2496 2497 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2498 if (!success)2499 return false;2500 2501 /* This is a PC-region branch and not PC-relative */2502 pc = (pc & 0xF0000000UL) | offset;2503 2504 Context context;2505 2506 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, pc);2507}2508 2509bool EmulateInstructionMIPS::Emulate_JAL(llvm::MCInst &insn) {2510 bool success = false;2511 uint32_t offset, target, pc;2512 2513 /*2514 * JAL offset2515 * offset = sign_ext (offset << 2)2516 * PC = PC[63-28] | offset2517 */2518 offset = insn.getOperand(0).getImm();2519 2520 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2521 if (!success)2522 return false;2523 2524 /* This is a PC-region branch and not PC-relative */2525 target = (pc & 0xF0000000UL) | offset;2526 2527 Context context;2528 2529 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2530 target))2531 return false;2532 2533 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,2534 pc + 8))2535 return false;2536 2537 return true;2538}2539 2540bool EmulateInstructionMIPS::Emulate_JALR(llvm::MCInst &insn) {2541 bool success = false;2542 uint32_t rs, rt;2543 uint32_t pc, rs_val;2544 2545 /*2546 * JALR rt, rs2547 * GPR[rt] = PC + 82548 * PC = GPR[rs]2549 */2550 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2551 rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());2552 2553 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2554 if (!success)2555 return false;2556 2557 rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + rs, 0,2558 &success);2559 if (!success)2560 return false;2561 2562 Context context;2563 2564 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2565 rs_val))2566 return false;2567 2568 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_zero_mips + rt,2569 pc + 8))2570 return false;2571 2572 return true;2573}2574 2575bool EmulateInstructionMIPS::Emulate_JIALC(llvm::MCInst &insn) {2576 bool success = false;2577 uint32_t rt;2578 int32_t target, offset, pc, rt_val;2579 2580 /*2581 * JIALC rt, offset2582 * offset = sign_ext (offset)2583 * PC = GPR[rt] + offset2584 * RA = PC + 42585 */2586 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2587 offset = insn.getOperand(1).getImm();2588 2589 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2590 if (!success)2591 return false;2592 2593 rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,2594 dwarf_zero_mips + rt, 0, &success);2595 if (!success)2596 return false;2597 2598 target = rt_val + offset;2599 2600 Context context;2601 2602 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2603 target))2604 return false;2605 2606 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,2607 pc + 4))2608 return false;2609 2610 return true;2611}2612 2613bool EmulateInstructionMIPS::Emulate_JIC(llvm::MCInst &insn) {2614 bool success = false;2615 uint32_t rt;2616 int32_t target, offset, rt_val;2617 2618 /*2619 * JIC rt, offset2620 * offset = sign_ext (offset)2621 * PC = GPR[rt] + offset2622 */2623 rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2624 offset = insn.getOperand(1).getImm();2625 2626 rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,2627 dwarf_zero_mips + rt, 0, &success);2628 if (!success)2629 return false;2630 2631 target = rt_val + offset;2632 2633 Context context;2634 2635 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2636 target);2637}2638 2639bool EmulateInstructionMIPS::Emulate_JR(llvm::MCInst &insn) {2640 bool success = false;2641 uint32_t rs;2642 uint32_t rs_val;2643 2644 /*2645 * JR rs2646 * PC = GPR[rs]2647 */2648 rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2649 2650 rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + rs, 0,2651 &success);2652 if (!success)2653 return false;2654 2655 Context context;2656 2657 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2658 rs_val);2659}2660 2661/*2662 Emulate Branch on FP True/False2663 BC1F, BC1FL : Branch on FP False (L stands for branch likely)2664 BC1T, BC1TL : Branch on FP True (L stands for branch likely)2665*/2666bool EmulateInstructionMIPS::Emulate_FP_branch(llvm::MCInst &insn) {2667 bool success = false;2668 uint32_t cc, fcsr;2669 int32_t pc, offset, target = 0;2670 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());2671 2672 cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2673 offset = insn.getOperand(1).getImm();2674 2675 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2676 if (!success)2677 return false;2678 2679 fcsr = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);2680 if (!success)2681 return false;2682 2683 /* fcsr[23], fcsr[25-31] are vaild condition bits */2684 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);2685 2686 if (op_name.equals_insensitive("BC1F") ||2687 op_name.equals_insensitive("BC1FL")) {2688 if ((fcsr & (1 << cc)) == 0)2689 target = pc + offset;2690 else2691 target = pc + 8;2692 } else if (op_name.equals_insensitive("BC1T") ||2693 op_name.equals_insensitive("BC1TL")) {2694 if ((fcsr & (1 << cc)) != 0)2695 target = pc + offset;2696 else2697 target = pc + 8;2698 }2699 Context context;2700 2701 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2702 target);2703}2704 2705bool EmulateInstructionMIPS::Emulate_BC1EQZ(llvm::MCInst &insn) {2706 bool success = false;2707 uint32_t ft;2708 uint32_t ft_val;2709 int32_t target, pc, offset;2710 2711 /*2712 * BC1EQZ ft, offset2713 * condition <- (FPR[ft].bit0 == 0)2714 * if condition then2715 * offset = sign_ext (offset)2716 * PC = PC + 4 + offset2717 */2718 ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2719 offset = insn.getOperand(1).getImm();2720 2721 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2722 if (!success)2723 return false;2724 2725 ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + ft, 0,2726 &success);2727 if (!success)2728 return false;2729 2730 if ((ft_val & 1) == 0)2731 target = pc + 4 + offset;2732 else2733 target = pc + 8;2734 2735 Context context;2736 2737 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2738 target);2739}2740 2741bool EmulateInstructionMIPS::Emulate_BC1NEZ(llvm::MCInst &insn) {2742 bool success = false;2743 uint32_t ft;2744 uint32_t ft_val;2745 int32_t target, pc, offset;2746 2747 /*2748 * BC1NEZ ft, offset2749 * condition <- (FPR[ft].bit0 != 0)2750 * if condition then2751 * offset = sign_ext (offset)2752 * PC = PC + 4 + offset2753 */2754 ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2755 offset = insn.getOperand(1).getImm();2756 2757 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2758 if (!success)2759 return false;2760 2761 ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + ft, 0,2762 &success);2763 if (!success)2764 return false;2765 2766 if ((ft_val & 1) != 0)2767 target = pc + 4 + offset;2768 else2769 target = pc + 8;2770 2771 Context context;2772 2773 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2774 target);2775}2776 2777/*2778 Emulate MIPS-3D Branch instructions2779 BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes2780 False/True2781 BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes2782 False/True2783*/2784bool EmulateInstructionMIPS::Emulate_3D_branch(llvm::MCInst &insn) {2785 bool success = false;2786 uint32_t cc, fcsr;2787 int32_t pc, offset, target = 0;2788 llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());2789 2790 cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2791 offset = insn.getOperand(1).getImm();2792 2793 pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2794 if (!success)2795 return false;2796 2797 fcsr = (uint32_t)ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips, 0,2798 &success);2799 if (!success)2800 return false;2801 2802 /* fcsr[23], fcsr[25-31] are vaild condition bits */2803 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);2804 2805 if (op_name.equals_insensitive("BC1ANY2F")) {2806 /* if any one bit is 0 */2807 if (((fcsr >> cc) & 3) != 3)2808 target = pc + offset;2809 else2810 target = pc + 8;2811 } else if (op_name.equals_insensitive("BC1ANY2T")) {2812 /* if any one bit is 1 */2813 if (((fcsr >> cc) & 3) != 0)2814 target = pc + offset;2815 else2816 target = pc + 8;2817 } else if (op_name.equals_insensitive("BC1ANY4F")) {2818 /* if any one bit is 0 */2819 if (((fcsr >> cc) & 0xf) != 0xf)2820 target = pc + offset;2821 else2822 target = pc + 8;2823 } else if (op_name.equals_insensitive("BC1ANY4T")) {2824 /* if any one bit is 1 */2825 if (((fcsr >> cc) & 0xf) != 0)2826 target = pc + offset;2827 else2828 target = pc + 8;2829 }2830 Context context;2831 2832 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2833 target);2834}2835 2836bool EmulateInstructionMIPS::Emulate_BNZB(llvm::MCInst &insn) {2837 return Emulate_MSA_Branch_DF(insn, 1, true);2838}2839 2840bool EmulateInstructionMIPS::Emulate_BNZH(llvm::MCInst &insn) {2841 return Emulate_MSA_Branch_DF(insn, 2, true);2842}2843 2844bool EmulateInstructionMIPS::Emulate_BNZW(llvm::MCInst &insn) {2845 return Emulate_MSA_Branch_DF(insn, 4, true);2846}2847 2848bool EmulateInstructionMIPS::Emulate_BNZD(llvm::MCInst &insn) {2849 return Emulate_MSA_Branch_DF(insn, 8, true);2850}2851 2852bool EmulateInstructionMIPS::Emulate_BZB(llvm::MCInst &insn) {2853 return Emulate_MSA_Branch_DF(insn, 1, false);2854}2855 2856bool EmulateInstructionMIPS::Emulate_BZH(llvm::MCInst &insn) {2857 return Emulate_MSA_Branch_DF(insn, 2, false);2858}2859 2860bool EmulateInstructionMIPS::Emulate_BZW(llvm::MCInst &insn) {2861 return Emulate_MSA_Branch_DF(insn, 4, false);2862}2863 2864bool EmulateInstructionMIPS::Emulate_BZD(llvm::MCInst &insn) {2865 return Emulate_MSA_Branch_DF(insn, 8, false);2866}2867 2868bool EmulateInstructionMIPS::Emulate_MSA_Branch_DF(llvm::MCInst &insn,2869 int element_byte_size,2870 bool bnz) {2871 bool success = false, branch_hit = true;2872 int32_t target = 0;2873 RegisterValue reg_value;2874 const uint8_t *ptr = nullptr;2875 2876 uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2877 int32_t offset = insn.getOperand(1).getImm();2878 2879 int32_t pc =2880 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2881 if (!success)2882 return false;2883 2884 if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value))2885 ptr = (const uint8_t *)reg_value.GetBytes();2886 else2887 return false;2888 2889 for (int i = 0; i < 16 / element_byte_size; i++) {2890 switch (element_byte_size) {2891 case 1:2892 if ((*ptr == 0 && bnz) || (*ptr != 0 && !bnz))2893 branch_hit = false;2894 break;2895 case 2:2896 if ((*(const uint16_t *)ptr == 0 && bnz) ||2897 (*(const uint16_t *)ptr != 0 && !bnz))2898 branch_hit = false;2899 break;2900 case 4:2901 if ((*(const uint32_t *)ptr == 0 && bnz) ||2902 (*(const uint32_t *)ptr != 0 && !bnz))2903 branch_hit = false;2904 break;2905 case 8:2906 if ((*(const uint64_t *)ptr == 0 && bnz) ||2907 (*(const uint64_t *)ptr != 0 && !bnz))2908 branch_hit = false;2909 break;2910 }2911 if (!branch_hit)2912 break;2913 ptr = ptr + element_byte_size;2914 }2915 2916 if (branch_hit)2917 target = pc + offset;2918 else2919 target = pc + 8;2920 2921 Context context;2922 context.type = eContextRelativeBranchImmediate;2923 2924 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2925 target);2926}2927 2928bool EmulateInstructionMIPS::Emulate_BNZV(llvm::MCInst &insn) {2929 return Emulate_MSA_Branch_V(insn, true);2930}2931 2932bool EmulateInstructionMIPS::Emulate_BZV(llvm::MCInst &insn) {2933 return Emulate_MSA_Branch_V(insn, false);2934}2935 2936bool EmulateInstructionMIPS::Emulate_MSA_Branch_V(llvm::MCInst &insn,2937 bool bnz) {2938 bool success = false;2939 int32_t target = 0;2940 llvm::APInt wr_val = llvm::APInt::getZero(128);2941 llvm::APInt fail_value = llvm::APInt::getMaxValue(128);2942 llvm::APInt zero_value = llvm::APInt::getZero(128);2943 RegisterValue reg_value;2944 2945 uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2946 int32_t offset = insn.getOperand(1).getImm();2947 2948 int32_t pc =2949 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2950 if (!success)2951 return false;2952 2953 if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value))2954 wr_val = reg_value.GetAsUInt128(fail_value);2955 else2956 return false;2957 2958 if ((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) ||2959 (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz))2960 target = pc + offset;2961 else2962 target = pc + 8;2963 2964 Context context;2965 context.type = eContextRelativeBranchImmediate;2966 2967 return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2968 target);2969}2970 2971bool EmulateInstructionMIPS::Emulate_LDST_Imm(llvm::MCInst &insn) {2972 bool success = false;2973 uint32_t base;2974 int32_t imm, address;2975 Context bad_vaddr_context;2976 2977 uint32_t num_operands = insn.getNumOperands();2978 base =2979 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());2980 imm = insn.getOperand(num_operands - 1).getImm();2981 2982 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))2983 return false;2984 2985 /* read base register */2986 address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,2987 dwarf_zero_mips + base, 0, &success);2988 if (!success)2989 return false;2990 2991 /* destination address */2992 address = address + imm;2993 2994 /* Set the bad_vaddr register with base address used in the instruction */2995 bad_vaddr_context.type = eContextInvalid;2996 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,2997 address);2998 2999 return true;3000}3001 3002bool EmulateInstructionMIPS::Emulate_LDST_Reg(llvm::MCInst &insn) {3003 bool success = false;3004 uint32_t base, index;3005 int32_t address, index_address;3006 Context bad_vaddr_context;3007 3008 uint32_t num_operands = insn.getNumOperands();3009 base =3010 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());3011 index =3012 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 1).getReg());3013 3014 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))3015 return false;3016 3017 if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + index))3018 return false;3019 3020 /* read base register */3021 address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,3022 dwarf_zero_mips + base, 0, &success);3023 if (!success)3024 return false;3025 3026 /* read index register */3027 index_address = (int32_t)ReadRegisterUnsigned(3028 eRegisterKindDWARF, dwarf_zero_mips + index, 0, &success);3029 if (!success)3030 return false;3031 3032 /* destination address */3033 address = address + index_address;3034 3035 /* Set the bad_vaddr register with base address used in the instruction */3036 bad_vaddr_context.type = eContextInvalid;3037 WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,3038 address);3039 3040 return true;3041}3042