Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
39648 views
//===-- EmulateInstructionMIPS.cpp ----------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "EmulateInstructionMIPS.h"910#include <cstdlib>11#include <optional>1213#include "lldb/Core/Address.h"14#include "lldb/Core/Opcode.h"15#include "lldb/Core/PluginManager.h"16#include "lldb/Symbol/UnwindPlan.h"17#include "lldb/Target/Target.h"18#include "lldb/Utility/ArchSpec.h"19#include "lldb/Utility/ConstString.h"20#include "lldb/Utility/DataExtractor.h"21#include "lldb/Utility/RegisterValue.h"22#include "lldb/Utility/Stream.h"23#include "llvm-c/Disassembler.h"24#include "llvm/MC/MCAsmInfo.h"25#include "llvm/MC/MCContext.h"26#include "llvm/MC/MCDisassembler/MCDisassembler.h"27#include "llvm/MC/MCInst.h"28#include "llvm/MC/MCInstrInfo.h"29#include "llvm/MC/MCRegisterInfo.h"30#include "llvm/MC/MCSubtargetInfo.h"31#include "llvm/MC/MCTargetOptions.h"32#include "llvm/MC/TargetRegistry.h"33#include "llvm/Support/TargetSelect.h"3435#include "llvm/ADT/STLExtras.h"3637#include "Plugins/Process/Utility/InstructionUtils.h"38#include "Plugins/Process/Utility/RegisterContext_mips.h"3940using namespace lldb;41using namespace lldb_private;4243LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionMIPS, InstructionMIPS)4445#define UInt(x) ((uint64_t)x)46#define integer int64_t4748//49// EmulateInstructionMIPS implementation50//5152#ifdef __mips__53extern "C" {54void LLVMInitializeMipsTargetInfo();55void LLVMInitializeMipsTarget();56void LLVMInitializeMipsAsmPrinter();57void LLVMInitializeMipsTargetMC();58void LLVMInitializeMipsDisassembler();59}60#endif6162EmulateInstructionMIPS::EmulateInstructionMIPS(63const lldb_private::ArchSpec &arch)64: EmulateInstruction(arch) {65/* Create instance of llvm::MCDisassembler */66std::string Status;67llvm::Triple triple = arch.GetTriple();68const llvm::Target *target =69llvm::TargetRegistry::lookupTarget(triple.getTriple(), Status);7071/*72* If we fail to get the target then we haven't registered it. The73* SystemInitializerCommon74* does not initialize targets, MCs and disassemblers. However we need the75* MCDisassembler76* to decode the instructions so that the decoding complexity stays with LLVM.77* Initialize the MIPS targets and disassemblers.78*/79#ifdef __mips__80if (!target) {81LLVMInitializeMipsTargetInfo();82LLVMInitializeMipsTarget();83LLVMInitializeMipsAsmPrinter();84LLVMInitializeMipsTargetMC();85LLVMInitializeMipsDisassembler();86target = llvm::TargetRegistry::lookupTarget(triple.getTriple(), Status);87}88#endif8990assert(target);9192llvm::StringRef cpu;9394switch (arch.GetCore()) {95case ArchSpec::eCore_mips32:96case ArchSpec::eCore_mips32el:97cpu = "mips32";98break;99case ArchSpec::eCore_mips32r2:100case ArchSpec::eCore_mips32r2el:101cpu = "mips32r2";102break;103case ArchSpec::eCore_mips32r3:104case ArchSpec::eCore_mips32r3el:105cpu = "mips32r3";106break;107case ArchSpec::eCore_mips32r5:108case ArchSpec::eCore_mips32r5el:109cpu = "mips32r5";110break;111case ArchSpec::eCore_mips32r6:112case ArchSpec::eCore_mips32r6el:113cpu = "mips32r6";114break;115case ArchSpec::eCore_mips64:116case ArchSpec::eCore_mips64el:117cpu = "mips64";118break;119case ArchSpec::eCore_mips64r2:120case ArchSpec::eCore_mips64r2el:121cpu = "mips64r2";122break;123case ArchSpec::eCore_mips64r3:124case ArchSpec::eCore_mips64r3el:125cpu = "mips64r3";126break;127case ArchSpec::eCore_mips64r5:128case ArchSpec::eCore_mips64r5el:129cpu = "mips64r5";130break;131case ArchSpec::eCore_mips64r6:132case ArchSpec::eCore_mips64r6el:133cpu = "mips64r6";134break;135default:136cpu = "generic";137break;138}139140std::string features;141uint32_t arch_flags = arch.GetFlags();142if (arch_flags & ArchSpec::eMIPSAse_msa)143features += "+msa,";144if (arch_flags & ArchSpec::eMIPSAse_dsp)145features += "+dsp,";146if (arch_flags & ArchSpec::eMIPSAse_dspr2)147features += "+dspr2,";148149m_reg_info.reset(target->createMCRegInfo(triple.getTriple()));150assert(m_reg_info.get());151152m_insn_info.reset(target->createMCInstrInfo());153assert(m_insn_info.get());154155llvm::MCTargetOptions MCOptions;156m_asm_info.reset(157target->createMCAsmInfo(*m_reg_info, triple.getTriple(), MCOptions));158m_subtype_info.reset(159target->createMCSubtargetInfo(triple.getTriple(), cpu, features));160assert(m_asm_info.get() && m_subtype_info.get());161162m_context = std::make_unique<llvm::MCContext>(163triple, m_asm_info.get(), m_reg_info.get(), m_subtype_info.get());164assert(m_context.get());165166m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context));167assert(m_disasm.get());168169/* Create alternate disassembler for microMIPS */170if (arch_flags & ArchSpec::eMIPSAse_mips16)171features += "+mips16,";172else if (arch_flags & ArchSpec::eMIPSAse_micromips)173features += "+micromips,";174175m_alt_subtype_info.reset(176target->createMCSubtargetInfo(triple.getTriple(), cpu, features));177assert(m_alt_subtype_info.get());178179m_alt_disasm.reset(180target->createMCDisassembler(*m_alt_subtype_info, *m_context));181assert(m_alt_disasm.get());182183m_next_inst_size = 0;184m_use_alt_disaasm = false;185}186187void EmulateInstructionMIPS::Initialize() {188PluginManager::RegisterPlugin(GetPluginNameStatic(),189GetPluginDescriptionStatic(), CreateInstance);190}191192void EmulateInstructionMIPS::Terminate() {193PluginManager::UnregisterPlugin(CreateInstance);194}195196llvm::StringRef EmulateInstructionMIPS::GetPluginDescriptionStatic() {197return "Emulate instructions for the MIPS32 architecture.";198}199200EmulateInstruction *201EmulateInstructionMIPS::CreateInstance(const ArchSpec &arch,202InstructionType inst_type) {203if (EmulateInstructionMIPS::SupportsEmulatingInstructionsOfTypeStatic(204inst_type)) {205if (arch.GetTriple().getArch() == llvm::Triple::mips ||206arch.GetTriple().getArch() == llvm::Triple::mipsel) {207return new EmulateInstructionMIPS(arch);208}209}210211return nullptr;212}213214bool EmulateInstructionMIPS::SetTargetTriple(const ArchSpec &arch) {215return arch.GetTriple().getArch() == llvm::Triple::mips ||216arch.GetTriple().getArch() == llvm::Triple::mipsel;217}218219const char *EmulateInstructionMIPS::GetRegisterName(unsigned reg_num,220bool alternate_name) {221if (alternate_name) {222switch (reg_num) {223case dwarf_sp_mips:224return "r29";225case dwarf_r30_mips:226return "r30";227case dwarf_ra_mips:228return "r31";229case dwarf_f0_mips:230return "f0";231case dwarf_f1_mips:232return "f1";233case dwarf_f2_mips:234return "f2";235case dwarf_f3_mips:236return "f3";237case dwarf_f4_mips:238return "f4";239case dwarf_f5_mips:240return "f5";241case dwarf_f6_mips:242return "f6";243case dwarf_f7_mips:244return "f7";245case dwarf_f8_mips:246return "f8";247case dwarf_f9_mips:248return "f9";249case dwarf_f10_mips:250return "f10";251case dwarf_f11_mips:252return "f11";253case dwarf_f12_mips:254return "f12";255case dwarf_f13_mips:256return "f13";257case dwarf_f14_mips:258return "f14";259case dwarf_f15_mips:260return "f15";261case dwarf_f16_mips:262return "f16";263case dwarf_f17_mips:264return "f17";265case dwarf_f18_mips:266return "f18";267case dwarf_f19_mips:268return "f19";269case dwarf_f20_mips:270return "f20";271case dwarf_f21_mips:272return "f21";273case dwarf_f22_mips:274return "f22";275case dwarf_f23_mips:276return "f23";277case dwarf_f24_mips:278return "f24";279case dwarf_f25_mips:280return "f25";281case dwarf_f26_mips:282return "f26";283case dwarf_f27_mips:284return "f27";285case dwarf_f28_mips:286return "f28";287case dwarf_f29_mips:288return "f29";289case dwarf_f30_mips:290return "f30";291case dwarf_f31_mips:292return "f31";293case dwarf_w0_mips:294return "w0";295case dwarf_w1_mips:296return "w1";297case dwarf_w2_mips:298return "w2";299case dwarf_w3_mips:300return "w3";301case dwarf_w4_mips:302return "w4";303case dwarf_w5_mips:304return "w5";305case dwarf_w6_mips:306return "w6";307case dwarf_w7_mips:308return "w7";309case dwarf_w8_mips:310return "w8";311case dwarf_w9_mips:312return "w9";313case dwarf_w10_mips:314return "w10";315case dwarf_w11_mips:316return "w11";317case dwarf_w12_mips:318return "w12";319case dwarf_w13_mips:320return "w13";321case dwarf_w14_mips:322return "w14";323case dwarf_w15_mips:324return "w15";325case dwarf_w16_mips:326return "w16";327case dwarf_w17_mips:328return "w17";329case dwarf_w18_mips:330return "w18";331case dwarf_w19_mips:332return "w19";333case dwarf_w20_mips:334return "w20";335case dwarf_w21_mips:336return "w21";337case dwarf_w22_mips:338return "w22";339case dwarf_w23_mips:340return "w23";341case dwarf_w24_mips:342return "w24";343case dwarf_w25_mips:344return "w25";345case dwarf_w26_mips:346return "w26";347case dwarf_w27_mips:348return "w27";349case dwarf_w28_mips:350return "w28";351case dwarf_w29_mips:352return "w29";353case dwarf_w30_mips:354return "w30";355case dwarf_w31_mips:356return "w31";357case dwarf_mir_mips:358return "mir";359case dwarf_mcsr_mips:360return "mcsr";361case dwarf_config5_mips:362return "config5";363default:364break;365}366return nullptr;367}368369switch (reg_num) {370case dwarf_zero_mips:371return "r0";372case dwarf_r1_mips:373return "r1";374case dwarf_r2_mips:375return "r2";376case dwarf_r3_mips:377return "r3";378case dwarf_r4_mips:379return "r4";380case dwarf_r5_mips:381return "r5";382case dwarf_r6_mips:383return "r6";384case dwarf_r7_mips:385return "r7";386case dwarf_r8_mips:387return "r8";388case dwarf_r9_mips:389return "r9";390case dwarf_r10_mips:391return "r10";392case dwarf_r11_mips:393return "r11";394case dwarf_r12_mips:395return "r12";396case dwarf_r13_mips:397return "r13";398case dwarf_r14_mips:399return "r14";400case dwarf_r15_mips:401return "r15";402case dwarf_r16_mips:403return "r16";404case dwarf_r17_mips:405return "r17";406case dwarf_r18_mips:407return "r18";408case dwarf_r19_mips:409return "r19";410case dwarf_r20_mips:411return "r20";412case dwarf_r21_mips:413return "r21";414case dwarf_r22_mips:415return "r22";416case dwarf_r23_mips:417return "r23";418case dwarf_r24_mips:419return "r24";420case dwarf_r25_mips:421return "r25";422case dwarf_r26_mips:423return "r26";424case dwarf_r27_mips:425return "r27";426case dwarf_gp_mips:427return "gp";428case dwarf_sp_mips:429return "sp";430case dwarf_r30_mips:431return "fp";432case dwarf_ra_mips:433return "ra";434case dwarf_sr_mips:435return "sr";436case dwarf_lo_mips:437return "lo";438case dwarf_hi_mips:439return "hi";440case dwarf_bad_mips:441return "bad";442case dwarf_cause_mips:443return "cause";444case dwarf_pc_mips:445return "pc";446case dwarf_f0_mips:447return "f0";448case dwarf_f1_mips:449return "f1";450case dwarf_f2_mips:451return "f2";452case dwarf_f3_mips:453return "f3";454case dwarf_f4_mips:455return "f4";456case dwarf_f5_mips:457return "f5";458case dwarf_f6_mips:459return "f6";460case dwarf_f7_mips:461return "f7";462case dwarf_f8_mips:463return "f8";464case dwarf_f9_mips:465return "f9";466case dwarf_f10_mips:467return "f10";468case dwarf_f11_mips:469return "f11";470case dwarf_f12_mips:471return "f12";472case dwarf_f13_mips:473return "f13";474case dwarf_f14_mips:475return "f14";476case dwarf_f15_mips:477return "f15";478case dwarf_f16_mips:479return "f16";480case dwarf_f17_mips:481return "f17";482case dwarf_f18_mips:483return "f18";484case dwarf_f19_mips:485return "f19";486case dwarf_f20_mips:487return "f20";488case dwarf_f21_mips:489return "f21";490case dwarf_f22_mips:491return "f22";492case dwarf_f23_mips:493return "f23";494case dwarf_f24_mips:495return "f24";496case dwarf_f25_mips:497return "f25";498case dwarf_f26_mips:499return "f26";500case dwarf_f27_mips:501return "f27";502case dwarf_f28_mips:503return "f28";504case dwarf_f29_mips:505return "f29";506case dwarf_f30_mips:507return "f30";508case dwarf_f31_mips:509return "f31";510case dwarf_fcsr_mips:511return "fcsr";512case dwarf_fir_mips:513return "fir";514case dwarf_w0_mips:515return "w0";516case dwarf_w1_mips:517return "w1";518case dwarf_w2_mips:519return "w2";520case dwarf_w3_mips:521return "w3";522case dwarf_w4_mips:523return "w4";524case dwarf_w5_mips:525return "w5";526case dwarf_w6_mips:527return "w6";528case dwarf_w7_mips:529return "w7";530case dwarf_w8_mips:531return "w8";532case dwarf_w9_mips:533return "w9";534case dwarf_w10_mips:535return "w10";536case dwarf_w11_mips:537return "w11";538case dwarf_w12_mips:539return "w12";540case dwarf_w13_mips:541return "w13";542case dwarf_w14_mips:543return "w14";544case dwarf_w15_mips:545return "w15";546case dwarf_w16_mips:547return "w16";548case dwarf_w17_mips:549return "w17";550case dwarf_w18_mips:551return "w18";552case dwarf_w19_mips:553return "w19";554case dwarf_w20_mips:555return "w20";556case dwarf_w21_mips:557return "w21";558case dwarf_w22_mips:559return "w22";560case dwarf_w23_mips:561return "w23";562case dwarf_w24_mips:563return "w24";564case dwarf_w25_mips:565return "w25";566case dwarf_w26_mips:567return "w26";568case dwarf_w27_mips:569return "w27";570case dwarf_w28_mips:571return "w28";572case dwarf_w29_mips:573return "w29";574case dwarf_w30_mips:575return "w30";576case dwarf_w31_mips:577return "w31";578case dwarf_mcsr_mips:579return "mcsr";580case dwarf_mir_mips:581return "mir";582case dwarf_config5_mips:583return "config5";584}585return nullptr;586}587588std::optional<RegisterInfo>589EmulateInstructionMIPS::GetRegisterInfo(RegisterKind reg_kind,590uint32_t reg_num) {591if (reg_kind == eRegisterKindGeneric) {592switch (reg_num) {593case LLDB_REGNUM_GENERIC_PC:594reg_kind = eRegisterKindDWARF;595reg_num = dwarf_pc_mips;596break;597case LLDB_REGNUM_GENERIC_SP:598reg_kind = eRegisterKindDWARF;599reg_num = dwarf_sp_mips;600break;601case LLDB_REGNUM_GENERIC_FP:602reg_kind = eRegisterKindDWARF;603reg_num = dwarf_r30_mips;604break;605case LLDB_REGNUM_GENERIC_RA:606reg_kind = eRegisterKindDWARF;607reg_num = dwarf_ra_mips;608break;609case LLDB_REGNUM_GENERIC_FLAGS:610reg_kind = eRegisterKindDWARF;611reg_num = dwarf_sr_mips;612break;613default:614return {};615}616}617618if (reg_kind == eRegisterKindDWARF) {619RegisterInfo reg_info;620::memset(®_info, 0, sizeof(RegisterInfo));621::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));622623if (reg_num == dwarf_sr_mips || reg_num == dwarf_fcsr_mips ||624reg_num == dwarf_fir_mips || reg_num == dwarf_mcsr_mips ||625reg_num == dwarf_mir_mips || reg_num == dwarf_config5_mips) {626reg_info.byte_size = 4;627reg_info.format = eFormatHex;628reg_info.encoding = eEncodingUint;629} else if ((int)reg_num >= dwarf_zero_mips &&630(int)reg_num <= dwarf_f31_mips) {631reg_info.byte_size = 4;632reg_info.format = eFormatHex;633reg_info.encoding = eEncodingUint;634} else if ((int)reg_num >= dwarf_w0_mips &&635(int)reg_num <= dwarf_w31_mips) {636reg_info.byte_size = 16;637reg_info.format = eFormatVectorOfUInt8;638reg_info.encoding = eEncodingVector;639} else {640return {};641}642643reg_info.name = GetRegisterName(reg_num, false);644reg_info.alt_name = GetRegisterName(reg_num, true);645reg_info.kinds[eRegisterKindDWARF] = reg_num;646647switch (reg_num) {648case dwarf_r30_mips:649reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;650break;651case dwarf_ra_mips:652reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;653break;654case dwarf_sp_mips:655reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;656break;657case dwarf_pc_mips:658reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;659break;660case dwarf_sr_mips:661reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;662break;663default:664break;665}666return reg_info;667}668return {};669}670671EmulateInstructionMIPS::MipsOpcode *672EmulateInstructionMIPS::GetOpcodeForInstruction(llvm::StringRef name) {673static EmulateInstructionMIPS::MipsOpcode g_opcodes[] = {674// Prologue/Epilogue instructions675{"ADDiu", &EmulateInstructionMIPS::Emulate_ADDiu,676"ADDIU rt, rs, immediate"},677{"SW", &EmulateInstructionMIPS::Emulate_SW, "SW rt, offset(rs)"},678{"LW", &EmulateInstructionMIPS::Emulate_LW, "LW rt, offset(base)"},679{"SUBU", &EmulateInstructionMIPS::Emulate_SUBU_ADDU, "SUBU rd, rs, rt"},680{"ADDU", &EmulateInstructionMIPS::Emulate_SUBU_ADDU, "ADDU rd, rs, rt"},681{"LUI", &EmulateInstructionMIPS::Emulate_LUI, "LUI rt, immediate"},682683// MicroMIPS Prologue/Epilogue instructions684{"ADDIUSP_MM", &EmulateInstructionMIPS::Emulate_ADDIUSP,685"ADDIU immediate"},686{"ADDIUS5_MM", &EmulateInstructionMIPS::Emulate_ADDIUS5,687"ADDIUS5 rd,immediate"},688{"SWSP_MM", &EmulateInstructionMIPS::Emulate_SWSP, "SWSP rt,offset(sp)"},689{"SWM16_MM", &EmulateInstructionMIPS::Emulate_SWM16_32,690"SWM16 reglist,offset(sp)"},691{"SWM32_MM", &EmulateInstructionMIPS::Emulate_SWM16_32,692"SWM32 reglist,offset(base)"},693{"SWP_MM", &EmulateInstructionMIPS::Emulate_SWM16_32,694"SWP rs1,offset(base)"},695{"LWSP_MM", &EmulateInstructionMIPS::Emulate_LWSP, "LWSP rt,offset(sp)"},696{"LWM16_MM", &EmulateInstructionMIPS::Emulate_LWM16_32,697"LWM16 reglist,offset(sp)"},698{"LWM32_MM", &EmulateInstructionMIPS::Emulate_LWM16_32,699"LWM32 reglist,offset(base)"},700{"LWP_MM", &EmulateInstructionMIPS::Emulate_LWM16_32,701"LWP rd,offset(base)"},702{"JRADDIUSP", &EmulateInstructionMIPS::Emulate_JRADDIUSP,703"JRADDIUSP immediate"},704705// Load/Store instructions706/* Following list of emulated instructions are required by implementation707of hardware watchpoint708for MIPS in lldb. As we just need the address accessed by instructions,709we have generalised710all these instructions in 2 functions depending on their addressing711modes */712713{"LB", &EmulateInstructionMIPS::Emulate_LDST_Imm,714"LB rt, offset(base)"},715{"LBE", &EmulateInstructionMIPS::Emulate_LDST_Imm,716"LBE rt, offset(base)"},717{"LBU", &EmulateInstructionMIPS::Emulate_LDST_Imm,718"LBU rt, offset(base)"},719{"LBUE", &EmulateInstructionMIPS::Emulate_LDST_Imm,720"LBUE rt, offset(base)"},721{"LDC1", &EmulateInstructionMIPS::Emulate_LDST_Imm,722"LDC1 ft, offset(base)"},723{"LD", &EmulateInstructionMIPS::Emulate_LDST_Imm,724"LD rt, offset(base)"},725{"LDL", &EmulateInstructionMIPS::Emulate_LDST_Imm,726"LDL rt, offset(base)"},727{"LDR", &EmulateInstructionMIPS::Emulate_LDST_Imm,728"LDR rt, offset(base)"},729{"LLD", &EmulateInstructionMIPS::Emulate_LDST_Imm,730"LLD rt, offset(base)"},731{"LDC2", &EmulateInstructionMIPS::Emulate_LDST_Imm,732"LDC2 rt, offset(base)"},733{"LDXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,734"LDXC1 fd, index (base)"},735{"LH", &EmulateInstructionMIPS::Emulate_LDST_Imm,736"LH rt, offset(base)"},737{"LHE", &EmulateInstructionMIPS::Emulate_LDST_Imm,738"LHE rt, offset(base)"},739{"LHU", &EmulateInstructionMIPS::Emulate_LDST_Imm,740"LHU rt, offset(base)"},741{"LHUE", &EmulateInstructionMIPS::Emulate_LDST_Imm,742"LHUE rt, offset(base)"},743{"LL", &EmulateInstructionMIPS::Emulate_LDST_Imm,744"LL rt, offset(base)"},745{"LLE", &EmulateInstructionMIPS::Emulate_LDST_Imm,746"LLE rt, offset(base)"},747{"LUXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,748"LUXC1 fd, index (base)"},749{"LW", &EmulateInstructionMIPS::Emulate_LDST_Imm,750"LW rt, offset(base)"},751{"LWC1", &EmulateInstructionMIPS::Emulate_LDST_Imm,752"LWC1 ft, offset(base)"},753{"LWC2", &EmulateInstructionMIPS::Emulate_LDST_Imm,754"LWC2 rt, offset(base)"},755{"LWE", &EmulateInstructionMIPS::Emulate_LDST_Imm,756"LWE rt, offset(base)"},757{"LWL", &EmulateInstructionMIPS::Emulate_LDST_Imm,758"LWL rt, offset(base)"},759{"LWLE", &EmulateInstructionMIPS::Emulate_LDST_Imm,760"LWLE rt, offset(base)"},761{"LWR", &EmulateInstructionMIPS::Emulate_LDST_Imm,762"LWR rt, offset(base)"},763{"LWRE", &EmulateInstructionMIPS::Emulate_LDST_Imm,764"LWRE rt, offset(base)"},765{"LWXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,766"LWXC1 fd, index (base)"},767{"LLX", &EmulateInstructionMIPS::Emulate_LDST_Imm,768"LLX rt, offset(base)"},769{"LLXE", &EmulateInstructionMIPS::Emulate_LDST_Imm,770"LLXE rt, offset(base)"},771{"LLDX", &EmulateInstructionMIPS::Emulate_LDST_Imm,772"LLDX rt, offset(base)"},773774{"SB", &EmulateInstructionMIPS::Emulate_LDST_Imm,775"SB rt, offset(base)"},776{"SBE", &EmulateInstructionMIPS::Emulate_LDST_Imm,777"SBE rt, offset(base)"},778{"SC", &EmulateInstructionMIPS::Emulate_LDST_Imm,779"SC rt, offset(base)"},780{"SCE", &EmulateInstructionMIPS::Emulate_LDST_Imm,781"SCE rt, offset(base)"},782{"SCD", &EmulateInstructionMIPS::Emulate_LDST_Imm,783"SCD rt, offset(base)"},784{"SD", &EmulateInstructionMIPS::Emulate_LDST_Imm,785"SD rt, offset(base)"},786{"SDL", &EmulateInstructionMIPS::Emulate_LDST_Imm,787"SDL rt, offset(base)"},788{"SDR", &EmulateInstructionMIPS::Emulate_LDST_Imm,789"SDR rt, offset(base)"},790{"SDC1", &EmulateInstructionMIPS::Emulate_LDST_Imm,791"SDC1 ft, offset(base)"},792{"SDC2", &EmulateInstructionMIPS::Emulate_LDST_Imm,793"SDC2 rt, offset(base)"},794{"SDXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,795"SDXC1 fs, index(base)"},796{"SH", &EmulateInstructionMIPS::Emulate_LDST_Imm,797"SH rt, offset(base)"},798{"SHE", &EmulateInstructionMIPS::Emulate_LDST_Imm,799"SHE rt, offset(base)"},800{"SUXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,801"SUXC1 fs, index (base)"},802{"SWC1", &EmulateInstructionMIPS::Emulate_LDST_Imm,803"SWC1 ft, offset(base)"},804{"SWC2", &EmulateInstructionMIPS::Emulate_LDST_Imm,805"SWC2 rt, offset(base)"},806{"SWE", &EmulateInstructionMIPS::Emulate_LDST_Imm,807"SWE rt, offset(base)"},808{"SWL", &EmulateInstructionMIPS::Emulate_LDST_Imm,809"SWL rt, offset(base)"},810{"SWLE", &EmulateInstructionMIPS::Emulate_LDST_Imm,811"SWLE rt, offset(base)"},812{"SWR", &EmulateInstructionMIPS::Emulate_LDST_Imm,813"SWR rt, offset(base)"},814{"SWRE", &EmulateInstructionMIPS::Emulate_LDST_Imm,815"SWRE rt, offset(base)"},816{"SWXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,817"SWXC1 fs, index (base)"},818{"SCX", &EmulateInstructionMIPS::Emulate_LDST_Imm,819"SCX rt, offset(base)"},820{"SCXE", &EmulateInstructionMIPS::Emulate_LDST_Imm,821"SCXE rt, offset(base)"},822{"SCDX", &EmulateInstructionMIPS::Emulate_LDST_Imm,823"SCDX rt, offset(base)"},824825// MicroMIPS Load/Store instructions826{"LBU16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,827"LBU16 rt, decoded_offset(base)"},828{"LHU16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,829"LHU16 rt, left_shifted_offset(base)"},830{"LW16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,831"LW16 rt, left_shifted_offset(base)"},832{"LWGP_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,833"LWGP rt, left_shifted_offset(gp)"},834{"SH16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,835"SH16 rt, left_shifted_offset(base)"},836{"SW16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,837"SW16 rt, left_shifted_offset(base)"},838{"SW_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,839"SWSP rt, left_shifted_offset(base)"},840{"SB16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,841"SB16 rt, offset(base)"},842843// Branch instructions844{"BEQ", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BEQ rs,rt,offset"},845{"BNE", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BNE rs,rt,offset"},846{"BEQL", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BEQL rs,rt,offset"},847{"BNEL", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BNEL rs,rt,offset"},848{"BGEZALL", &EmulateInstructionMIPS::Emulate_Bcond_Link,849"BGEZALL rt,offset"},850{"BAL", &EmulateInstructionMIPS::Emulate_BAL, "BAL offset"},851{"BGEZAL", &EmulateInstructionMIPS::Emulate_Bcond_Link,852"BGEZAL rs,offset"},853{"BALC", &EmulateInstructionMIPS::Emulate_BALC, "BALC offset"},854{"BC", &EmulateInstructionMIPS::Emulate_BC, "BC offset"},855{"BGEZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGEZ rs,offset"},856{"BLEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,857"BLEZALC rs,offset"},858{"BGEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,859"BGEZALC rs,offset"},860{"BLTZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,861"BLTZALC rs,offset"},862{"BGTZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,863"BGTZALC rs,offset"},864{"BEQZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,865"BEQZALC rs,offset"},866{"BNEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,867"BNEZALC rs,offset"},868{"BEQC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,869"BEQC rs,rt,offset"},870{"BNEC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,871"BNEC rs,rt,offset"},872{"BLTC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,873"BLTC rs,rt,offset"},874{"BGEC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,875"BGEC rs,rt,offset"},876{"BLTUC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,877"BLTUC rs,rt,offset"},878{"BGEUC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,879"BGEUC rs,rt,offset"},880{"BLTZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BLTZC rt,offset"},881{"BLEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BLEZC rt,offset"},882{"BGEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BGEZC rt,offset"},883{"BGTZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BGTZC rt,offset"},884{"BEQZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BEQZC rt,offset"},885{"BNEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BNEZC rt,offset"},886{"BGEZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGEZL rt,offset"},887{"BGTZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGTZ rt,offset"},888{"BGTZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGTZL rt,offset"},889{"BLEZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLEZ rt,offset"},890{"BLEZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLEZL rt,offset"},891{"BLTZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLTZ rt,offset"},892{"BLTZAL", &EmulateInstructionMIPS::Emulate_Bcond_Link,893"BLTZAL rt,offset"},894{"BLTZALL", &EmulateInstructionMIPS::Emulate_Bcond_Link,895"BLTZALL rt,offset"},896{"BLTZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLTZL rt,offset"},897{"BOVC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,898"BOVC rs,rt,offset"},899{"BNVC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,900"BNVC rs,rt,offset"},901{"J", &EmulateInstructionMIPS::Emulate_J, "J target"},902{"JAL", &EmulateInstructionMIPS::Emulate_JAL, "JAL target"},903{"JALX", &EmulateInstructionMIPS::Emulate_JAL, "JALX target"},904{"JALR", &EmulateInstructionMIPS::Emulate_JALR, "JALR target"},905{"JALR_HB", &EmulateInstructionMIPS::Emulate_JALR, "JALR.HB target"},906{"JIALC", &EmulateInstructionMIPS::Emulate_JIALC, "JIALC rt,offset"},907{"JIC", &EmulateInstructionMIPS::Emulate_JIC, "JIC rt,offset"},908{"JR", &EmulateInstructionMIPS::Emulate_JR, "JR target"},909{"JR_HB", &EmulateInstructionMIPS::Emulate_JR, "JR.HB target"},910{"BC1F", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1F cc, offset"},911{"BC1T", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1T cc, offset"},912{"BC1FL", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1FL cc, offset"},913{"BC1TL", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1TL cc, offset"},914{"BC1EQZ", &EmulateInstructionMIPS::Emulate_BC1EQZ, "BC1EQZ ft, offset"},915{"BC1NEZ", &EmulateInstructionMIPS::Emulate_BC1NEZ, "BC1NEZ ft, offset"},916{"BC1ANY2F", &EmulateInstructionMIPS::Emulate_3D_branch,917"BC1ANY2F cc, offset"},918{"BC1ANY2T", &EmulateInstructionMIPS::Emulate_3D_branch,919"BC1ANY2T cc, offset"},920{"BC1ANY4F", &EmulateInstructionMIPS::Emulate_3D_branch,921"BC1ANY4F cc, offset"},922{"BC1ANY4T", &EmulateInstructionMIPS::Emulate_3D_branch,923"BC1ANY4T cc, offset"},924{"BNZ_B", &EmulateInstructionMIPS::Emulate_BNZB, "BNZ.b wt,s16"},925{"BNZ_H", &EmulateInstructionMIPS::Emulate_BNZH, "BNZ.h wt,s16"},926{"BNZ_W", &EmulateInstructionMIPS::Emulate_BNZW, "BNZ.w wt,s16"},927{"BNZ_D", &EmulateInstructionMIPS::Emulate_BNZD, "BNZ.d wt,s16"},928{"BZ_B", &EmulateInstructionMIPS::Emulate_BZB, "BZ.b wt,s16"},929{"BZ_H", &EmulateInstructionMIPS::Emulate_BZH, "BZ.h wt,s16"},930{"BZ_W", &EmulateInstructionMIPS::Emulate_BZW, "BZ.w wt,s16"},931{"BZ_D", &EmulateInstructionMIPS::Emulate_BZD, "BZ.d wt,s16"},932{"BNZ_V", &EmulateInstructionMIPS::Emulate_BNZV, "BNZ.V wt,s16"},933{"BZ_V", &EmulateInstructionMIPS::Emulate_BZV, "BZ.V wt,s16"},934935// MicroMIPS Branch instructions936{"B16_MM", &EmulateInstructionMIPS::Emulate_B16_MM, "B16 offset"},937{"BEQZ16_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,938"BEQZ16 rs, offset"},939{"BNEZ16_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,940"BNEZ16 rs, offset"},941{"BEQZC_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,942"BEQZC rs, offset"},943{"BNEZC_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,944"BNEZC rs, offset"},945{"BGEZALS_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,946"BGEZALS rs, offset"},947{"BLTZALS_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,948"BLTZALS rs, offset"},949{"JALR16_MM", &EmulateInstructionMIPS::Emulate_JALRx16_MM, "JALR16 rs"},950{"JALRS16_MM", &EmulateInstructionMIPS::Emulate_JALRx16_MM, "JALRS16 rs"},951{"JR16_MM", &EmulateInstructionMIPS::Emulate_JR, "JR16 rs rs"},952{"JRC16_MM", &EmulateInstructionMIPS::Emulate_JR, "JRC16 rs rs"},953{"JALS_MM", &EmulateInstructionMIPS::Emulate_JALx, "JALS target"},954{"JALX_MM", &EmulateInstructionMIPS::Emulate_JALx, "JALX target"},955{"JALRS_MM", &EmulateInstructionMIPS::Emulate_JALRS, "JALRS rt, rs"},956};957958for (MipsOpcode &opcode : g_opcodes) {959if (name.equals_insensitive(opcode.op_name))960return &opcode;961}962return nullptr;963}964965uint32_t966EmulateInstructionMIPS::GetSizeOfInstruction(lldb_private::DataExtractor &data,967uint64_t inst_addr) {968uint64_t next_inst_size = 0;969llvm::MCInst mc_insn;970llvm::MCDisassembler::DecodeStatus decode_status;971llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());972973if (m_use_alt_disaasm)974decode_status = m_alt_disasm->getInstruction(975mc_insn, next_inst_size, raw_insn, inst_addr, llvm::nulls());976else977decode_status = m_disasm->getInstruction(mc_insn, next_inst_size, raw_insn,978inst_addr, llvm::nulls());979980if (decode_status != llvm::MCDisassembler::Success)981return false;982983return m_insn_info->get(mc_insn.getOpcode()).getSize();984}985986bool EmulateInstructionMIPS::SetInstruction(const Opcode &insn_opcode,987const Address &inst_addr,988Target *target) {989m_use_alt_disaasm = false;990991if (EmulateInstruction::SetInstruction(insn_opcode, inst_addr, target)) {992if (inst_addr.GetAddressClass() == AddressClass::eCodeAlternateISA) {993Status error;994lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;995996/*997* The address belongs to microMIPS function. To find the size of998* next instruction use microMIPS disassembler.999*/1000m_use_alt_disaasm = true;10011002uint32_t current_inst_size = insn_opcode.GetByteSize();1003uint8_t buf[sizeof(uint32_t)];1004uint64_t next_inst_addr = (m_addr & (~1ull)) + current_inst_size;1005Address next_addr(next_inst_addr);10061007const size_t bytes_read =1008target->ReadMemory(next_addr, /* Address of next instruction */1009buf, sizeof(uint32_t), error,1010false, /* force_live_memory */1011&load_addr);10121013if (bytes_read == 0)1014return true;10151016DataExtractor data(buf, sizeof(uint32_t), GetByteOrder(),1017GetAddressByteSize());1018m_next_inst_size = GetSizeOfInstruction(data, next_inst_addr);1019return true;1020} else {1021/*1022* If the address class is not AddressClass::eCodeAlternateISA then1023* the function is not microMIPS. In this case instruction size is1024* always 4 bytes.1025*/1026m_next_inst_size = 4;1027return true;1028}1029}1030return false;1031}10321033bool EmulateInstructionMIPS::ReadInstruction() {1034bool success = false;1035m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,1036LLDB_INVALID_ADDRESS, &success);1037if (success) {1038Context read_inst_context;1039read_inst_context.type = eContextReadOpcode;1040read_inst_context.SetNoArgs();1041m_opcode.SetOpcode32(1042ReadMemoryUnsigned(read_inst_context, m_addr, 4, 0, &success),1043GetByteOrder());1044}1045if (!success)1046m_addr = LLDB_INVALID_ADDRESS;1047return success;1048}10491050bool EmulateInstructionMIPS::EvaluateInstruction(uint32_t evaluate_options) {1051bool success = false;1052llvm::MCInst mc_insn;1053uint64_t insn_size;1054DataExtractor data;10551056/* Keep the complexity of the decode logic with the llvm::MCDisassembler1057* class. */1058if (m_opcode.GetData(data)) {1059llvm::MCDisassembler::DecodeStatus decode_status;1060llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());1061if (m_use_alt_disaasm)1062decode_status = m_alt_disasm->getInstruction(mc_insn, insn_size, raw_insn,1063m_addr, llvm::nulls());1064else1065decode_status = m_disasm->getInstruction(mc_insn, insn_size, raw_insn,1066m_addr, llvm::nulls());10671068if (decode_status != llvm::MCDisassembler::Success)1069return false;1070}10711072/*1073* mc_insn.getOpcode() returns decoded opcode. However to make use1074* of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc".1075*/1076const char *op_name = m_insn_info->getName(mc_insn.getOpcode()).data();10771078if (op_name == nullptr)1079return false;10801081/*1082* Decoding has been done already. Just get the call-back function1083* and emulate the instruction.1084*/1085MipsOpcode *opcode_data = GetOpcodeForInstruction(op_name);10861087if (opcode_data == nullptr)1088return false;10891090uint64_t old_pc = 0, new_pc = 0;1091const bool auto_advance_pc =1092evaluate_options & eEmulateInstructionOptionAutoAdvancePC;10931094if (auto_advance_pc) {1095old_pc =1096ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);1097if (!success)1098return false;1099}11001101/* emulate instruction */1102success = (this->*opcode_data->callback)(mc_insn);1103if (!success)1104return false;11051106if (auto_advance_pc) {1107new_pc =1108ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);1109if (!success)1110return false;11111112/* If we haven't changed the PC, change it here */1113if (old_pc == new_pc) {1114new_pc += 4;1115Context context;1116if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,1117new_pc))1118return false;1119}1120}11211122return true;1123}11241125bool EmulateInstructionMIPS::CreateFunctionEntryUnwind(1126UnwindPlan &unwind_plan) {1127unwind_plan.Clear();1128unwind_plan.SetRegisterKind(eRegisterKindDWARF);11291130UnwindPlan::RowSP row(new UnwindPlan::Row);1131const bool can_replace = false;11321133// Our previous Call Frame Address is the stack pointer1134row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips, 0);11351136// Our previous PC is in the RA1137row->SetRegisterLocationToRegister(dwarf_pc_mips, dwarf_ra_mips, can_replace);11381139unwind_plan.AppendRow(row);11401141// All other registers are the same.1142unwind_plan.SetSourceName("EmulateInstructionMIPS");1143unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);1144unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);1145unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);1146unwind_plan.SetReturnAddressRegister(dwarf_ra_mips);11471148return true;1149}11501151bool EmulateInstructionMIPS::nonvolatile_reg_p(uint32_t regnum) {1152switch (regnum) {1153case dwarf_r16_mips:1154case dwarf_r17_mips:1155case dwarf_r18_mips:1156case dwarf_r19_mips:1157case dwarf_r20_mips:1158case dwarf_r21_mips:1159case dwarf_r22_mips:1160case dwarf_r23_mips:1161case dwarf_gp_mips:1162case dwarf_sp_mips:1163case dwarf_r30_mips:1164case dwarf_ra_mips:1165return true;1166default:1167return false;1168}1169return false;1170}11711172bool EmulateInstructionMIPS::Emulate_ADDiu(llvm::MCInst &insn) {1173// ADDIU rt, rs, immediate1174// GPR[rt] <- GPR[rs] + sign_extend(immediate)11751176uint8_t dst, src;1177bool success = false;1178const uint32_t imm16 = insn.getOperand(2).getImm();1179int64_t imm = SignedBits(imm16, 15, 0);11801181dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1182src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());11831184// If immediate value is greater then 2^16 - 1 then clang generate LUI,1185// ADDIU, SUBU instructions in prolog. Example lui $1, 0x2 addiu $1, $1,1186// -0x5920 subu $sp, $sp, $1 In this case, ADDIU dst and src will be same1187// and not equal to sp1188if (dst == src) {1189Context context;11901191/* read <src> register */1192const int64_t src_opd_val = ReadRegisterUnsigned(1193eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success);1194if (!success)1195return false;11961197/* Check if this is daddiu sp, sp, imm16 */1198if (dst == dwarf_sp_mips) {1199uint64_t result = src_opd_val + imm;1200std::optional<RegisterInfo> reg_info_sp =1201GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);1202if (reg_info_sp)1203context.SetRegisterPlusOffset(*reg_info_sp, imm);12041205/* We are allocating bytes on stack */1206context.type = eContextAdjustStackPointer;12071208WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);1209return true;1210}12111212imm += src_opd_val;1213context.SetImmediateSigned(imm);1214context.type = eContextImmediate;12151216if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,1217dwarf_zero_mips + dst, imm))1218return false;1219}12201221return true;1222}12231224bool EmulateInstructionMIPS::Emulate_SW(llvm::MCInst &insn) {1225bool success = false;1226uint32_t imm16 = insn.getOperand(2).getImm();1227uint32_t imm = SignedBits(imm16, 15, 0);1228uint32_t src, base;1229int32_t address;1230Context bad_vaddr_context;12311232src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1233base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());12341235std::optional<RegisterInfo> reg_info_base =1236GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base);1237if (!reg_info_base)1238return false;12391240/* read base register */1241address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,1242dwarf_zero_mips + base, 0, &success);1243if (!success)1244return false;12451246/* destination address */1247address = address + imm;12481249/* Set the bad_vaddr register with base address used in the instruction */1250bad_vaddr_context.type = eContextInvalid;1251WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,1252address);12531254/* We look for sp based non-volatile register stores */1255if (nonvolatile_reg_p(src)) {1256std::optional<RegisterInfo> reg_info_src =1257GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src);1258if (!reg_info_src)1259return false;12601261Context context;1262context.type = eContextPushRegisterOnStack;1263context.SetRegisterToRegisterPlusOffset(*reg_info_src, *reg_info_base, 0);12641265RegisterValue::BytesContainer buffer(reg_info_src->byte_size);1266Status error;12671268std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);1269if (!data_src)1270return false;12711272if (data_src->GetAsMemoryData(*reg_info_src, buffer.data(),1273reg_info_src->byte_size, eByteOrderLittle,1274error) == 0)1275return false;12761277if (!WriteMemory(context, address, buffer.data(), reg_info_src->byte_size))1278return false;12791280return true;1281}12821283return false;1284}12851286bool EmulateInstructionMIPS::Emulate_LW(llvm::MCInst &insn) {1287bool success = false;1288uint32_t src, base;1289int32_t imm, address;1290Context bad_vaddr_context;12911292src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1293base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());1294imm = insn.getOperand(2).getImm();12951296if (GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))1297return false;12981299/* read base register */1300address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,1301dwarf_zero_mips + base, 0, &success);1302if (!success)1303return false;13041305/* destination address */1306address = address + imm;13071308/* Set the bad_vaddr register with base address used in the instruction */1309bad_vaddr_context.type = eContextInvalid;1310WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,1311address);13121313if (nonvolatile_reg_p(src)) {1314RegisterValue data_src;1315std::optional<RegisterInfo> reg_info_src =1316GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src);1317if (!reg_info_src)1318return false;13191320Context context;1321context.type = eContextPopRegisterOffStack;1322context.SetAddress(address);13231324return WriteRegister(context, *reg_info_src, data_src);1325}13261327return false;1328}13291330bool EmulateInstructionMIPS::Emulate_SUBU_ADDU(llvm::MCInst &insn) {1331// SUBU sp, <src>, <rt>1332// ADDU sp, <src>, <rt>1333// ADDU dst, sp, <rt>13341335bool success = false;1336uint64_t result;1337uint8_t src, dst, rt;1338llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());13391340dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1341src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());13421343/* Check if sp is destination register */1344if (dst == dwarf_sp_mips) {1345rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());13461347/* read <src> register */1348uint64_t src_opd_val = ReadRegisterUnsigned(1349eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success);1350if (!success)1351return false;13521353/* read <rt > register */1354uint64_t rt_opd_val = ReadRegisterUnsigned(1355eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);1356if (!success)1357return false;13581359if (op_name.equals_insensitive("SUBU"))1360result = src_opd_val - rt_opd_val;1361else1362result = src_opd_val + rt_opd_val;13631364Context context;1365std::optional<RegisterInfo> reg_info_sp =1366GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);1367if (reg_info_sp)1368context.SetRegisterPlusOffset(*reg_info_sp, rt_opd_val);13691370/* We are allocating bytes on stack */1371context.type = eContextAdjustStackPointer;13721373WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);13741375return true;1376} else if (src == dwarf_sp_mips) {1377rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());13781379/* read <src> register */1380uint64_t src_opd_val = ReadRegisterUnsigned(1381eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success);1382if (!success)1383return false;13841385/* read <rt> register */1386uint64_t rt_opd_val = ReadRegisterUnsigned(1387eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);1388if (!success)1389return false;13901391Context context;13921393if (op_name.equals_insensitive("SUBU"))1394result = src_opd_val - rt_opd_val;1395else1396result = src_opd_val + rt_opd_val;13971398context.SetImmediateSigned(result);1399context.type = eContextImmediate;14001401if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,1402dwarf_zero_mips + dst, result))1403return false;1404}14051406return true;1407}14081409bool EmulateInstructionMIPS::Emulate_LUI(llvm::MCInst &insn) {1410// LUI rt, immediate1411// GPR[rt] <- sign_extend(immediate << 16)14121413const uint32_t imm32 = insn.getOperand(1).getImm() << 16;1414int64_t imm = SignedBits(imm32, 31, 0);1415uint8_t rt;1416Context context;14171418rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1419context.SetImmediateSigned(imm);1420context.type = eContextImmediate;14211422return WriteRegisterUnsigned(context, eRegisterKindDWARF,1423dwarf_zero_mips + rt, imm);1424}14251426bool EmulateInstructionMIPS::Emulate_ADDIUSP(llvm::MCInst &insn) {1427bool success = false;1428const uint32_t imm9 = insn.getOperand(0).getImm();1429uint64_t result;14301431// This instruction operates implicitly on stack pointer, so read <sp>1432// register.1433uint64_t src_opd_val =1434ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_sp_mips, 0, &success);1435if (!success)1436return false;14371438result = src_opd_val + imm9;14391440Context context;1441std::optional<RegisterInfo> reg_info_sp =1442GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);1443if (reg_info_sp)1444context.SetRegisterPlusOffset(*reg_info_sp, imm9);14451446// We are adjusting the stack.1447context.type = eContextAdjustStackPointer;14481449WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);1450return true;1451}14521453bool EmulateInstructionMIPS::Emulate_ADDIUS5(llvm::MCInst &insn) {1454bool success = false;1455uint32_t base;1456const uint32_t imm4 = insn.getOperand(2).getImm();1457uint64_t result;14581459// The source and destination register is same for this instruction.1460base = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());14611462// We are looking for stack adjustment only1463if (base == dwarf_sp_mips) {1464// Read stack pointer register1465uint64_t src_opd_val = ReadRegisterUnsigned(1466eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);1467if (!success)1468return false;14691470result = src_opd_val + imm4;14711472Context context;1473std::optional<RegisterInfo> reg_info_sp =1474GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);1475if (reg_info_sp)1476context.SetRegisterPlusOffset(*reg_info_sp, imm4);14771478// We are adjusting the stack.1479context.type = eContextAdjustStackPointer;14801481WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);1482}14831484return true;1485}14861487bool EmulateInstructionMIPS::Emulate_SWSP(llvm::MCInst &insn) {1488bool success = false;1489uint32_t imm5 = insn.getOperand(2).getImm();1490uint32_t src, base;1491Context bad_vaddr_context;1492uint32_t address;14931494src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1495base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());14961497std::optional<RegisterInfo> reg_info_base =1498GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base);1499if (!reg_info_base)1500return false;15011502// read base register1503address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0,1504&success);1505if (!success)1506return false;15071508// destination address1509address = address + imm5;15101511// We use bad_vaddr_context to store base address which is used by H/W1512// watchpoint Set the bad_vaddr register with base address used in the1513// instruction1514bad_vaddr_context.type = eContextInvalid;1515WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,1516address);15171518// We look for sp based non-volatile register stores.1519if (base == dwarf_sp_mips && nonvolatile_reg_p(src)) {1520RegisterInfo reg_info_src = {};1521Context context;1522context.type = eContextPushRegisterOnStack;1523context.SetRegisterToRegisterPlusOffset(reg_info_src, *reg_info_base, 0);15241525RegisterValue::BytesContainer buffer(reg_info_src.byte_size);1526Status error;15271528std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);1529if (!data_src)1530return false;15311532if (data_src->GetAsMemoryData(reg_info_src, buffer.data(),1533reg_info_src.byte_size, eByteOrderLittle,1534error) == 0)1535return false;15361537if (!WriteMemory(context, address, buffer.data(), reg_info_src.byte_size))1538return false;15391540return true;1541}15421543return false;1544}15451546/* Emulate SWM16,SWM32 and SWP instruction.15471548SWM16 always has stack pointer as a base register (but it is still available1549in MCInst as an operand).1550SWM32 and SWP can have base register other than stack pointer.1551*/1552bool EmulateInstructionMIPS::Emulate_SWM16_32(llvm::MCInst &insn) {1553bool success = false;1554uint32_t src, base;1555uint32_t num_operands = insn.getNumOperands(); // No of operands vary based on1556// no of regs to store.15571558// Base register is second last operand of the instruction.1559base =1560m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());15611562// We are looking for sp based stores so if base is not a stack pointer then1563// don't proceed.1564if (base != dwarf_sp_mips)1565return false;15661567// offset is always the last operand.1568uint32_t offset = insn.getOperand(num_operands - 1).getImm();15691570std::optional<RegisterInfo> reg_info_base =1571GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base);1572if (!reg_info_base)1573return false;15741575// read SP1576uint32_t base_address = ReadRegisterUnsigned(1577eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);1578if (!success)1579return false;15801581// Resulting base addrss1582base_address = base_address + offset;15831584// Total no of registers to be stored are num_operands-2.1585for (uint32_t i = 0; i < num_operands - 2; i++) {1586// Get the register number to be stored.1587src = m_reg_info->getEncodingValue(insn.getOperand(i).getReg());15881589/*1590Record only non-volatile stores.1591This check is required for SWP instruction because source operand could1592be any register.1593SWM16 and SWM32 instruction always has saved registers as source1594operands.1595*/1596if (!nonvolatile_reg_p(src))1597return false;15981599std::optional<RegisterInfo> reg_info_src =1600GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src);1601if (!reg_info_src)1602return false;16031604Context context;1605context.type = eContextPushRegisterOnStack;1606context.SetRegisterToRegisterPlusOffset(*reg_info_src, *reg_info_base, 0);16071608RegisterValue::BytesContainer buffer(reg_info_src->byte_size);1609Status error;16101611std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);1612if (!data_src)1613return false;16141615if (data_src->GetAsMemoryData(*reg_info_src, buffer.data(),1616reg_info_src->byte_size, eByteOrderLittle,1617error) == 0)1618return false;16191620if (!WriteMemory(context, base_address, buffer.data(),1621reg_info_src->byte_size))1622return false;16231624// Stack address for next register1625base_address = base_address + reg_info_src->byte_size;1626}1627return true;1628}16291630bool EmulateInstructionMIPS::Emulate_LWSP(llvm::MCInst &insn) {1631bool success = false;1632uint32_t src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1633uint32_t base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());1634uint32_t imm5 = insn.getOperand(2).getImm();1635Context bad_vaddr_context;16361637if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))1638return false;16391640// read base register1641uint32_t base_address = ReadRegisterUnsigned(1642eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);1643if (!success)1644return false;16451646base_address = base_address + imm5;16471648// We use bad_vaddr_context to store base address which is used by H/W1649// watchpoint Set the bad_vaddr register with base address used in the1650// instruction1651bad_vaddr_context.type = eContextInvalid;1652WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,1653base_address);16541655if (base == dwarf_sp_mips && nonvolatile_reg_p(src)) {1656RegisterValue data_src;1657std::optional<RegisterInfo> reg_info_src =1658GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src);1659if (!reg_info_src)1660return false;16611662Context context;1663context.type = eContextPopRegisterOffStack;1664context.SetAddress(base_address);16651666return WriteRegister(context, *reg_info_src, data_src);1667}16681669return false;1670}16711672/* Emulate LWM16, LWM32 and LWP instructions.16731674LWM16 always has stack pointer as a base register (but it is still available1675in MCInst as an operand).1676LWM32 and LWP can have base register other than stack pointer.1677*/1678bool EmulateInstructionMIPS::Emulate_LWM16_32(llvm::MCInst &insn) {1679bool success = false;1680uint32_t dst, base;1681uint32_t num_operands = insn.getNumOperands(); // No of operands vary based on1682// no of regs to store.1683uint32_t imm = insn.getOperand(num_operands - 1)1684.getImm(); // imm is the last operand in the instruction.16851686// Base register is second last operand of the instruction.1687base =1688m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());16891690// We are looking for sp based loads so if base is not a stack pointer then1691// don't proceed.1692if (base != dwarf_sp_mips)1693return false;16941695uint32_t base_address = ReadRegisterUnsigned(1696eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);1697if (!success)1698return false;16991700base_address = base_address + imm;17011702RegisterValue data_dst;17031704// Total no of registers to be re-stored are num_operands-2.1705for (uint32_t i = 0; i < num_operands - 2; i++) {1706// Get the register number to be re-stored.1707dst = m_reg_info->getEncodingValue(insn.getOperand(i).getReg());17081709/*1710Record only non-volatile loads.1711This check is required for LWP instruction because destination operand1712could be any register.1713LWM16 and LWM32 instruction always has saved registers as destination1714operands.1715*/1716if (!nonvolatile_reg_p(dst))1717return false;17181719std::optional<RegisterInfo> reg_info_dst =1720GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + dst);1721if (!reg_info_dst)1722return false;17231724Context context;1725context.type = eContextPopRegisterOffStack;1726context.SetAddress(base_address + (i * 4));17271728if (!WriteRegister(context, *reg_info_dst, data_dst))1729return false;1730}17311732return true;1733}17341735bool EmulateInstructionMIPS::Emulate_JRADDIUSP(llvm::MCInst &insn) {1736bool success = false;1737int32_t imm5 = insn.getOperand(0).getImm();17381739/* JRADDIUSP immediate1740* PC <- RA1741* SP <- SP + zero_extend(Immediate << 2)1742*/17431744// This instruction operates implicitly on stack pointer, so read <sp>1745// register.1746int32_t src_opd_val =1747ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_sp_mips, 0, &success);1748if (!success)1749return false;17501751int32_t ra_val =1752ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_ra_mips, 0, &success);1753if (!success)1754return false;17551756int32_t result = src_opd_val + imm5;17571758Context context;17591760// Update the PC1761if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,1762ra_val))1763return false;17641765std::optional<RegisterInfo> reg_info_sp =1766GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);1767if (reg_info_sp)1768context.SetRegisterPlusOffset(*reg_info_sp, imm5);17691770// We are adjusting stack1771context.type = eContextAdjustStackPointer;17721773// update SP1774return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips,1775result);1776}17771778static int IsAdd64bitOverflow(int32_t a, int32_t b) {1779int32_t r = (uint32_t)a + (uint32_t)b;1780return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);1781}17821783/*1784Emulate below MIPS branch instructions.1785BEQ, BNE : Branch on condition1786BEQL, BNEL : Branch likely1787*/1788bool EmulateInstructionMIPS::Emulate_BXX_3ops(llvm::MCInst &insn) {1789bool success = false;1790uint32_t rs, rt;1791int32_t offset, pc, target = 0, rs_val, rt_val;1792llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());17931794rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1795rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());1796offset = insn.getOperand(2).getImm();17971798pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);1799if (!success)1800return false;18011802rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,1803dwarf_zero_mips + rs, 0, &success);1804if (!success)1805return false;18061807rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,1808dwarf_zero_mips + rt, 0, &success);1809if (!success)1810return false;18111812if (op_name.equals_insensitive("BEQ") || op_name.equals_insensitive("BEQL")) {1813if (rs_val == rt_val)1814target = pc + offset;1815else1816target = pc + 8;1817} else if (op_name.equals_insensitive("BNE") ||1818op_name.equals_insensitive("BNEL")) {1819if (rs_val != rt_val)1820target = pc + offset;1821else1822target = pc + 8;1823}18241825Context context;1826context.type = eContextRelativeBranchImmediate;1827context.SetImmediate(offset);18281829return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,1830target);1831}18321833/*1834Emulate below MIPS branch instructions.1835BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch1836instructions with no delay slot1837*/1838bool EmulateInstructionMIPS::Emulate_BXX_3ops_C(llvm::MCInst &insn) {1839bool success = false;1840uint32_t rs, rt;1841int32_t offset, pc, target = 0, rs_val, rt_val;1842llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());1843uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();18441845rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1846rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());1847offset = insn.getOperand(2).getImm();18481849pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);1850if (!success)1851return false;18521853rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,1854dwarf_zero_mips + rs, 0, &success);1855if (!success)1856return false;18571858rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,1859dwarf_zero_mips + rt, 0, &success);1860if (!success)1861return false;18621863if (op_name.equals_insensitive("BEQC")) {1864if (rs_val == rt_val)1865target = pc + offset;1866else1867target = pc + 4;1868} else if (op_name.equals_insensitive("BNEC")) {1869if (rs_val != rt_val)1870target = pc + offset;1871else1872target = pc + 4;1873} else if (op_name.equals_insensitive("BLTC")) {1874if (rs_val < rt_val)1875target = pc + offset;1876else1877target = pc + 4;1878} else if (op_name.equals_insensitive("BGEC")) {1879if (rs_val >= rt_val)1880target = pc + offset;1881else1882target = pc + 4;1883} else if (op_name.equals_insensitive("BLTUC")) {1884if (rs_val < rt_val)1885target = pc + offset;1886else1887target = pc + 4;1888} else if (op_name.equals_insensitive("BGEUC")) {1889if ((uint32_t)rs_val >= (uint32_t)rt_val)1890target = pc + offset;1891else1892target = pc + 4;1893} else if (op_name.equals_insensitive("BOVC")) {1894if (IsAdd64bitOverflow(rs_val, rt_val))1895target = pc + offset;1896else1897target = pc + 4;1898} else if (op_name.equals_insensitive("BNVC")) {1899if (!IsAdd64bitOverflow(rs_val, rt_val))1900target = pc + offset;1901else1902target = pc + 4;1903}19041905Context context;1906context.type = eContextRelativeBranchImmediate;1907context.SetImmediate(current_inst_size + offset);19081909return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,1910target);1911}19121913/*1914Emulate below MIPS conditional branch and link instructions.1915BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches1916*/1917bool EmulateInstructionMIPS::Emulate_Bcond_Link_C(llvm::MCInst &insn) {1918bool success = false;1919uint32_t rs;1920int32_t offset, pc, target = 0;1921int32_t rs_val;1922llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());19231924rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1925offset = insn.getOperand(1).getImm();19261927pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);1928if (!success)1929return false;19301931rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,1932dwarf_zero_mips + rs, 0, &success);1933if (!success)1934return false;19351936if (op_name.equals_insensitive("BLEZALC")) {1937if (rs_val <= 0)1938target = pc + offset;1939else1940target = pc + 4;1941} else if (op_name.equals_insensitive("BGEZALC")) {1942if (rs_val >= 0)1943target = pc + offset;1944else1945target = pc + 4;1946} else if (op_name.equals_insensitive("BLTZALC")) {1947if (rs_val < 0)1948target = pc + offset;1949else1950target = pc + 4;1951} else if (op_name.equals_insensitive("BGTZALC")) {1952if (rs_val > 0)1953target = pc + offset;1954else1955target = pc + 4;1956} else if (op_name.equals_insensitive("BEQZALC")) {1957if (rs_val == 0)1958target = pc + offset;1959else1960target = pc + 4;1961} else if (op_name.equals_insensitive("BNEZALC")) {1962if (rs_val != 0)1963target = pc + offset;1964else1965target = pc + 4;1966}19671968Context context;19691970if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,1971target))1972return false;19731974if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,1975pc + 4))1976return false;19771978return true;1979}19801981/*1982Emulate below MIPS Non-Compact conditional branch and link instructions.1983BLTZAL, BGEZAL :1984BLTZALL, BGEZALL : Branch likely1985*/1986bool EmulateInstructionMIPS::Emulate_Bcond_Link(llvm::MCInst &insn) {1987bool success = false;1988uint32_t rs;1989int32_t offset, pc, target = 0;1990int32_t rs_val;1991llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());19921993rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1994offset = insn.getOperand(1).getImm();19951996pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);1997if (!success)1998return false;19992000rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,2001dwarf_zero_mips + rs, 0, &success);2002if (!success)2003return false;20042005if (op_name.equals_insensitive("BLTZAL") ||2006op_name.equals_insensitive("BLTZALL")) {2007if ((int32_t)rs_val < 0)2008target = pc + offset;2009else2010target = pc + 8;2011} else if (op_name.equals_insensitive("BGEZAL") ||2012op_name.equals_insensitive("BGEZALL")) {2013if ((int32_t)rs_val >= 0)2014target = pc + offset;2015else2016target = pc + 8;2017}20182019Context context;20202021if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2022target))2023return false;20242025if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,2026pc + 8))2027return false;20282029return true;2030}20312032/*2033Emulate below MIPS branch instructions.2034BLTZL, BGEZL, BGTZL, BLEZL : Branch likely2035BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches2036*/2037bool EmulateInstructionMIPS::Emulate_BXX_2ops(llvm::MCInst &insn) {2038bool success = false;2039uint32_t rs;2040int32_t offset, pc, target = 0;2041int32_t rs_val;2042llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());20432044rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2045offset = insn.getOperand(1).getImm();20462047pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2048if (!success)2049return false;20502051rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,2052dwarf_zero_mips + rs, 0, &success);2053if (!success)2054return false;20552056if (op_name.equals_insensitive("BLTZL") ||2057op_name.equals_insensitive("BLTZ")) {2058if (rs_val < 0)2059target = pc + offset;2060else2061target = pc + 8;2062} else if (op_name.equals_insensitive("BGEZL") ||2063op_name.equals_insensitive("BGEZ")) {2064if (rs_val >= 0)2065target = pc + offset;2066else2067target = pc + 8;2068} else if (op_name.equals_insensitive("BGTZL") ||2069op_name.equals_insensitive("BGTZ")) {2070if (rs_val > 0)2071target = pc + offset;2072else2073target = pc + 8;2074} else if (op_name.equals_insensitive("BLEZL") ||2075op_name.equals_insensitive("BLEZ")) {2076if (rs_val <= 0)2077target = pc + offset;2078else2079target = pc + 8;2080}20812082Context context;2083context.type = eContextRelativeBranchImmediate;2084context.SetImmediate(offset);20852086return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2087target);2088}20892090/*2091Emulate below MIPS branch instructions.2092BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches2093*/2094bool EmulateInstructionMIPS::Emulate_BXX_2ops_C(llvm::MCInst &insn) {2095bool success = false;2096uint32_t rs;2097int32_t offset, pc, target = 0;2098int32_t rs_val;2099llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());2100uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();21012102rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2103offset = insn.getOperand(1).getImm();21042105pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2106if (!success)2107return false;21082109rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,2110dwarf_zero_mips + rs, 0, &success);2111if (!success)2112return false;21132114if (op_name.equals_insensitive("BLTZC")) {2115if (rs_val < 0)2116target = pc + offset;2117else2118target = pc + 4;2119} else if (op_name.equals_insensitive("BLEZC")) {2120if (rs_val <= 0)2121target = pc + offset;2122else2123target = pc + 4;2124} else if (op_name.equals_insensitive("BGEZC")) {2125if (rs_val >= 0)2126target = pc + offset;2127else2128target = pc + 4;2129} else if (op_name.equals_insensitive("BGTZC")) {2130if (rs_val > 0)2131target = pc + offset;2132else2133target = pc + 4;2134} else if (op_name.equals_insensitive("BEQZC")) {2135if (rs_val == 0)2136target = pc + offset;2137else2138target = pc + 4;2139} else if (op_name.equals_insensitive("BNEZC")) {2140if (rs_val != 0)2141target = pc + offset;2142else2143target = pc + 4;2144}21452146Context context;2147context.type = eContextRelativeBranchImmediate;2148context.SetImmediate(current_inst_size + offset);21492150return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2151target);2152}21532154bool EmulateInstructionMIPS::Emulate_B16_MM(llvm::MCInst &insn) {2155bool success = false;2156int32_t offset, pc, target;2157uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();21582159offset = insn.getOperand(0).getImm();21602161pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2162if (!success)2163return false;21642165// unconditional branch2166target = pc + offset;21672168Context context;2169context.type = eContextRelativeBranchImmediate;2170context.SetImmediate(current_inst_size + offset);21712172return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2173target);2174}21752176/*2177BEQZC, BNEZC are 32 bit compact instructions without a delay slot.2178BEQZ16, BNEZ16 are 16 bit instructions with delay slot.2179BGEZALS, BLTZALS are 16 bit instructions with short (2-byte) delay slot.2180*/2181bool EmulateInstructionMIPS::Emulate_Branch_MM(llvm::MCInst &insn) {2182bool success = false;2183int32_t target = 0;2184uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();2185llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());2186bool update_ra = false;2187uint32_t ra_offset = 0;21882189/*2190* BEQZ16 rs, offset2191* condition <- (GPR[rs] = 0)2192* if condition then2193* PC = PC + sign_ext (offset || 0)2194*2195* BNEZ16 rs, offset2196* condition <- (GPR[rs] != 0)2197* if condition then2198* PC = PC + sign_ext (offset || 0)2199*2200* BEQZC rs, offset (compact instruction: No delay slot)2201* condition <- (GPR[rs] == 0)2202* if condition then2203* PC = PC + 4 + sign_ext (offset || 0)2204*/22052206uint32_t rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2207int32_t offset = insn.getOperand(1).getImm();22082209int32_t pc =2210ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2211if (!success)2212return false;22132214int32_t rs_val = (int32_t)ReadRegisterUnsigned(2215eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);2216if (!success)2217return false;22182219if (op_name.equals_insensitive("BEQZ16_MM")) {2220if (rs_val == 0)2221target = pc + offset;2222else2223target = pc + current_inst_size +2224m_next_inst_size; // Skip delay slot instruction.2225} else if (op_name.equals_insensitive("BNEZ16_MM")) {2226if (rs_val != 0)2227target = pc + offset;2228else2229target = pc + current_inst_size +2230m_next_inst_size; // Skip delay slot instruction.2231} else if (op_name.equals_insensitive("BEQZC_MM")) {2232if (rs_val == 0)2233target = pc + 4 + offset;2234else2235target =2236pc +22374; // 32 bit instruction and does not have delay slot instruction.2238} else if (op_name.equals_insensitive("BNEZC_MM")) {2239if (rs_val != 0)2240target = pc + 4 + offset;2241else2242target =2243pc +22444; // 32 bit instruction and does not have delay slot instruction.2245} else if (op_name.equals_insensitive("BGEZALS_MM")) {2246if (rs_val >= 0)2247target = pc + offset;2248else2249target = pc + 6; // 32 bit instruction with short (2-byte) delay slot22502251update_ra = true;2252ra_offset = 6;2253} else if (op_name.equals_insensitive("BLTZALS_MM")) {2254if (rs_val >= 0)2255target = pc + offset;2256else2257target = pc + 6; // 32 bit instruction with short (2-byte) delay slot22582259update_ra = true;2260ra_offset = 6;2261}22622263Context context;2264context.type = eContextRelativeBranchImmediate;2265context.SetImmediate(current_inst_size + offset);22662267if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2268target))2269return false;22702271if (update_ra) {2272if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,2273pc + ra_offset))2274return false;2275}2276return true;2277}22782279/* Emulate micromips jump instructions.2280JALR16,JALRS162281*/2282bool EmulateInstructionMIPS::Emulate_JALRx16_MM(llvm::MCInst &insn) {2283bool success = false;2284uint32_t ra_offset = 0;2285llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());22862287uint32_t rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());22882289uint32_t pc =2290ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2291if (!success)2292return false;22932294uint32_t rs_val = ReadRegisterUnsigned(eRegisterKindDWARF,2295dwarf_zero_mips + rs, 0, &success);2296if (!success)2297return false;22982299if (op_name.equals_insensitive("JALR16_MM"))2300ra_offset = 6; // 2-byte instruction with 4-byte delay slot.2301else if (op_name.equals_insensitive("JALRS16_MM"))2302ra_offset = 4; // 2-byte instruction with 2-byte delay slot.23032304Context context;23052306if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2307rs_val))2308return false;23092310if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,2311pc + ra_offset))2312return false;23132314return true;2315}23162317/* Emulate JALS and JALX instructions.2318JALS 32 bit instruction with short (2-byte) delay slot.2319JALX 32 bit instruction with 4-byte delay slot.2320*/2321bool EmulateInstructionMIPS::Emulate_JALx(llvm::MCInst &insn) {2322bool success = false;2323uint32_t offset = 0, target = 0, pc = 0, ra_offset = 0;2324llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());23252326/*2327* JALS target2328* RA = PC + 62329* offset = sign_ext (offset << 1)2330* PC = PC[31-27] | offset2331* JALX target2332* RA = PC + 82333* offset = sign_ext (offset << 2)2334* PC = PC[31-28] | offset2335*/2336offset = insn.getOperand(0).getImm();23372338pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2339if (!success)2340return false;23412342// These are PC-region branches and not PC-relative.2343if (op_name.equals_insensitive("JALS_MM")) {2344// target address is in the “current” 128 MB-aligned region2345target = (pc & 0xF8000000UL) | offset;2346ra_offset = 6;2347} else if (op_name.equals_insensitive("JALX_MM")) {2348// target address is in the “current” 256 MB-aligned region2349target = (pc & 0xF0000000UL) | offset;2350ra_offset = 8;2351}23522353Context context;23542355if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2356target))2357return false;23582359if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,2360pc + ra_offset))2361return false;23622363return true;2364}23652366bool EmulateInstructionMIPS::Emulate_JALRS(llvm::MCInst &insn) {2367bool success = false;2368uint32_t rs = 0, rt = 0;2369int32_t pc = 0, rs_val = 0;23702371/*2372JALRS rt, rs2373GPR[rt] <- PC + 62374PC <- GPR[rs]2375*/23762377rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2378rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());23792380rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,2381dwarf_zero_mips + rs, 0, &success);2382if (!success)2383return false;23842385pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2386if (!success)2387return false;23882389Context context;23902391if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2392rs_val))2393return false;23942395// This is 4-byte instruction with 2-byte delay slot.2396if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_zero_mips + rt,2397pc + 6))2398return false;23992400return true;2401}24022403bool EmulateInstructionMIPS::Emulate_BAL(llvm::MCInst &insn) {2404bool success = false;2405int32_t offset, pc, target;24062407/*2408* BAL offset2409* offset = sign_ext (offset << 2)2410* RA = PC + 82411* PC = PC + offset2412*/2413offset = insn.getOperand(0).getImm();24142415pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2416if (!success)2417return false;24182419target = pc + offset;24202421Context context;24222423if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2424target))2425return false;24262427if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,2428pc + 8))2429return false;24302431return true;2432}24332434bool EmulateInstructionMIPS::Emulate_BALC(llvm::MCInst &insn) {2435bool success = false;2436int32_t offset, pc, target;24372438/*2439* BALC offset2440* offset = sign_ext (offset << 2)2441* RA = PC + 42442* PC = PC + 4 + offset2443*/2444offset = insn.getOperand(0).getImm();24452446pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2447if (!success)2448return false;24492450target = pc + offset;24512452Context context;24532454if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2455target))2456return false;24572458if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,2459pc + 4))2460return false;24612462return true;2463}24642465bool EmulateInstructionMIPS::Emulate_BC(llvm::MCInst &insn) {2466bool success = false;2467int32_t offset, pc, target;24682469/*2470* BC offset2471* offset = sign_ext (offset << 2)2472* PC = PC + 4 + offset2473*/2474offset = insn.getOperand(0).getImm();24752476pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2477if (!success)2478return false;24792480target = pc + offset;24812482Context context;24832484return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2485target);2486}24872488bool EmulateInstructionMIPS::Emulate_J(llvm::MCInst &insn) {2489bool success = false;2490uint32_t offset, pc;24912492/*2493* J offset2494* offset = sign_ext (offset << 2)2495* PC = PC[63-28] | offset2496*/2497offset = insn.getOperand(0).getImm();24982499pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2500if (!success)2501return false;25022503/* This is a PC-region branch and not PC-relative */2504pc = (pc & 0xF0000000UL) | offset;25052506Context context;25072508return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, pc);2509}25102511bool EmulateInstructionMIPS::Emulate_JAL(llvm::MCInst &insn) {2512bool success = false;2513uint32_t offset, target, pc;25142515/*2516* JAL offset2517* offset = sign_ext (offset << 2)2518* PC = PC[63-28] | offset2519*/2520offset = insn.getOperand(0).getImm();25212522pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2523if (!success)2524return false;25252526/* This is a PC-region branch and not PC-relative */2527target = (pc & 0xF0000000UL) | offset;25282529Context context;25302531if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2532target))2533return false;25342535if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,2536pc + 8))2537return false;25382539return true;2540}25412542bool EmulateInstructionMIPS::Emulate_JALR(llvm::MCInst &insn) {2543bool success = false;2544uint32_t rs, rt;2545uint32_t pc, rs_val;25462547/*2548* JALR rt, rs2549* GPR[rt] = PC + 82550* PC = GPR[rs]2551*/2552rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2553rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());25542555pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2556if (!success)2557return false;25582559rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + rs, 0,2560&success);2561if (!success)2562return false;25632564Context context;25652566if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2567rs_val))2568return false;25692570if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_zero_mips + rt,2571pc + 8))2572return false;25732574return true;2575}25762577bool EmulateInstructionMIPS::Emulate_JIALC(llvm::MCInst &insn) {2578bool success = false;2579uint32_t rt;2580int32_t target, offset, pc, rt_val;25812582/*2583* JIALC rt, offset2584* offset = sign_ext (offset)2585* PC = GPR[rt] + offset2586* RA = PC + 42587*/2588rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2589offset = insn.getOperand(1).getImm();25902591pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2592if (!success)2593return false;25942595rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,2596dwarf_zero_mips + rt, 0, &success);2597if (!success)2598return false;25992600target = rt_val + offset;26012602Context context;26032604if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2605target))2606return false;26072608if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,2609pc + 4))2610return false;26112612return true;2613}26142615bool EmulateInstructionMIPS::Emulate_JIC(llvm::MCInst &insn) {2616bool success = false;2617uint32_t rt;2618int32_t target, offset, rt_val;26192620/*2621* JIC rt, offset2622* offset = sign_ext (offset)2623* PC = GPR[rt] + offset2624*/2625rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2626offset = insn.getOperand(1).getImm();26272628rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,2629dwarf_zero_mips + rt, 0, &success);2630if (!success)2631return false;26322633target = rt_val + offset;26342635Context context;26362637return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2638target);2639}26402641bool EmulateInstructionMIPS::Emulate_JR(llvm::MCInst &insn) {2642bool success = false;2643uint32_t rs;2644uint32_t rs_val;26452646/*2647* JR rs2648* PC = GPR[rs]2649*/2650rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());26512652rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + rs, 0,2653&success);2654if (!success)2655return false;26562657Context context;26582659return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2660rs_val);2661}26622663/*2664Emulate Branch on FP True/False2665BC1F, BC1FL : Branch on FP False (L stands for branch likely)2666BC1T, BC1TL : Branch on FP True (L stands for branch likely)2667*/2668bool EmulateInstructionMIPS::Emulate_FP_branch(llvm::MCInst &insn) {2669bool success = false;2670uint32_t cc, fcsr;2671int32_t pc, offset, target = 0;2672llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());26732674cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2675offset = insn.getOperand(1).getImm();26762677pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2678if (!success)2679return false;26802681fcsr = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);2682if (!success)2683return false;26842685/* fcsr[23], fcsr[25-31] are vaild condition bits */2686fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);26872688if (op_name.equals_insensitive("BC1F") ||2689op_name.equals_insensitive("BC1FL")) {2690if ((fcsr & (1 << cc)) == 0)2691target = pc + offset;2692else2693target = pc + 8;2694} else if (op_name.equals_insensitive("BC1T") ||2695op_name.equals_insensitive("BC1TL")) {2696if ((fcsr & (1 << cc)) != 0)2697target = pc + offset;2698else2699target = pc + 8;2700}2701Context context;27022703return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2704target);2705}27062707bool EmulateInstructionMIPS::Emulate_BC1EQZ(llvm::MCInst &insn) {2708bool success = false;2709uint32_t ft;2710uint32_t ft_val;2711int32_t target, pc, offset;27122713/*2714* BC1EQZ ft, offset2715* condition <- (FPR[ft].bit0 == 0)2716* if condition then2717* offset = sign_ext (offset)2718* PC = PC + 4 + offset2719*/2720ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2721offset = insn.getOperand(1).getImm();27222723pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2724if (!success)2725return false;27262727ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + ft, 0,2728&success);2729if (!success)2730return false;27312732if ((ft_val & 1) == 0)2733target = pc + 4 + offset;2734else2735target = pc + 8;27362737Context context;27382739return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2740target);2741}27422743bool EmulateInstructionMIPS::Emulate_BC1NEZ(llvm::MCInst &insn) {2744bool success = false;2745uint32_t ft;2746uint32_t ft_val;2747int32_t target, pc, offset;27482749/*2750* BC1NEZ ft, offset2751* condition <- (FPR[ft].bit0 != 0)2752* if condition then2753* offset = sign_ext (offset)2754* PC = PC + 4 + offset2755*/2756ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2757offset = insn.getOperand(1).getImm();27582759pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2760if (!success)2761return false;27622763ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + ft, 0,2764&success);2765if (!success)2766return false;27672768if ((ft_val & 1) != 0)2769target = pc + 4 + offset;2770else2771target = pc + 8;27722773Context context;27742775return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2776target);2777}27782779/*2780Emulate MIPS-3D Branch instructions2781BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes2782False/True2783BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes2784False/True2785*/2786bool EmulateInstructionMIPS::Emulate_3D_branch(llvm::MCInst &insn) {2787bool success = false;2788uint32_t cc, fcsr;2789int32_t pc, offset, target = 0;2790llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());27912792cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2793offset = insn.getOperand(1).getImm();27942795pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2796if (!success)2797return false;27982799fcsr = (uint32_t)ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips, 0,2800&success);2801if (!success)2802return false;28032804/* fcsr[23], fcsr[25-31] are vaild condition bits */2805fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);28062807if (op_name.equals_insensitive("BC1ANY2F")) {2808/* if any one bit is 0 */2809if (((fcsr >> cc) & 3) != 3)2810target = pc + offset;2811else2812target = pc + 8;2813} else if (op_name.equals_insensitive("BC1ANY2T")) {2814/* if any one bit is 1 */2815if (((fcsr >> cc) & 3) != 0)2816target = pc + offset;2817else2818target = pc + 8;2819} else if (op_name.equals_insensitive("BC1ANY4F")) {2820/* if any one bit is 0 */2821if (((fcsr >> cc) & 0xf) != 0xf)2822target = pc + offset;2823else2824target = pc + 8;2825} else if (op_name.equals_insensitive("BC1ANY4T")) {2826/* if any one bit is 1 */2827if (((fcsr >> cc) & 0xf) != 0)2828target = pc + offset;2829else2830target = pc + 8;2831}2832Context context;28332834return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2835target);2836}28372838bool EmulateInstructionMIPS::Emulate_BNZB(llvm::MCInst &insn) {2839return Emulate_MSA_Branch_DF(insn, 1, true);2840}28412842bool EmulateInstructionMIPS::Emulate_BNZH(llvm::MCInst &insn) {2843return Emulate_MSA_Branch_DF(insn, 2, true);2844}28452846bool EmulateInstructionMIPS::Emulate_BNZW(llvm::MCInst &insn) {2847return Emulate_MSA_Branch_DF(insn, 4, true);2848}28492850bool EmulateInstructionMIPS::Emulate_BNZD(llvm::MCInst &insn) {2851return Emulate_MSA_Branch_DF(insn, 8, true);2852}28532854bool EmulateInstructionMIPS::Emulate_BZB(llvm::MCInst &insn) {2855return Emulate_MSA_Branch_DF(insn, 1, false);2856}28572858bool EmulateInstructionMIPS::Emulate_BZH(llvm::MCInst &insn) {2859return Emulate_MSA_Branch_DF(insn, 2, false);2860}28612862bool EmulateInstructionMIPS::Emulate_BZW(llvm::MCInst &insn) {2863return Emulate_MSA_Branch_DF(insn, 4, false);2864}28652866bool EmulateInstructionMIPS::Emulate_BZD(llvm::MCInst &insn) {2867return Emulate_MSA_Branch_DF(insn, 8, false);2868}28692870bool EmulateInstructionMIPS::Emulate_MSA_Branch_DF(llvm::MCInst &insn,2871int element_byte_size,2872bool bnz) {2873bool success = false, branch_hit = true;2874int32_t target = 0;2875RegisterValue reg_value;2876const uint8_t *ptr = nullptr;28772878uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2879int32_t offset = insn.getOperand(1).getImm();28802881int32_t pc =2882ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2883if (!success)2884return false;28852886if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value))2887ptr = (const uint8_t *)reg_value.GetBytes();2888else2889return false;28902891for (int i = 0; i < 16 / element_byte_size; i++) {2892switch (element_byte_size) {2893case 1:2894if ((*ptr == 0 && bnz) || (*ptr != 0 && !bnz))2895branch_hit = false;2896break;2897case 2:2898if ((*(const uint16_t *)ptr == 0 && bnz) ||2899(*(const uint16_t *)ptr != 0 && !bnz))2900branch_hit = false;2901break;2902case 4:2903if ((*(const uint32_t *)ptr == 0 && bnz) ||2904(*(const uint32_t *)ptr != 0 && !bnz))2905branch_hit = false;2906break;2907case 8:2908if ((*(const uint64_t *)ptr == 0 && bnz) ||2909(*(const uint64_t *)ptr != 0 && !bnz))2910branch_hit = false;2911break;2912}2913if (!branch_hit)2914break;2915ptr = ptr + element_byte_size;2916}29172918if (branch_hit)2919target = pc + offset;2920else2921target = pc + 8;29222923Context context;2924context.type = eContextRelativeBranchImmediate;29252926return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2927target);2928}29292930bool EmulateInstructionMIPS::Emulate_BNZV(llvm::MCInst &insn) {2931return Emulate_MSA_Branch_V(insn, true);2932}29332934bool EmulateInstructionMIPS::Emulate_BZV(llvm::MCInst &insn) {2935return Emulate_MSA_Branch_V(insn, false);2936}29372938bool EmulateInstructionMIPS::Emulate_MSA_Branch_V(llvm::MCInst &insn,2939bool bnz) {2940bool success = false;2941int32_t target = 0;2942llvm::APInt wr_val = llvm::APInt::getZero(128);2943llvm::APInt fail_value = llvm::APInt::getMaxValue(128);2944llvm::APInt zero_value = llvm::APInt::getZero(128);2945RegisterValue reg_value;29462947uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2948int32_t offset = insn.getOperand(1).getImm();29492950int32_t pc =2951ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);2952if (!success)2953return false;29542955if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value))2956wr_val = reg_value.GetAsUInt128(fail_value);2957else2958return false;29592960if ((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) ||2961(!llvm::APInt::isSameValue(zero_value, wr_val) && bnz))2962target = pc + offset;2963else2964target = pc + 8;29652966Context context;2967context.type = eContextRelativeBranchImmediate;29682969return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,2970target);2971}29722973bool EmulateInstructionMIPS::Emulate_LDST_Imm(llvm::MCInst &insn) {2974bool success = false;2975uint32_t base;2976int32_t imm, address;2977Context bad_vaddr_context;29782979uint32_t num_operands = insn.getNumOperands();2980base =2981m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());2982imm = insn.getOperand(num_operands - 1).getImm();29832984if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))2985return false;29862987/* read base register */2988address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,2989dwarf_zero_mips + base, 0, &success);2990if (!success)2991return false;29922993/* destination address */2994address = address + imm;29952996/* Set the bad_vaddr register with base address used in the instruction */2997bad_vaddr_context.type = eContextInvalid;2998WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,2999address);30003001return true;3002}30033004bool EmulateInstructionMIPS::Emulate_LDST_Reg(llvm::MCInst &insn) {3005bool success = false;3006uint32_t base, index;3007int32_t address, index_address;3008Context bad_vaddr_context;30093010uint32_t num_operands = insn.getNumOperands();3011base =3012m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());3013index =3014m_reg_info->getEncodingValue(insn.getOperand(num_operands - 1).getReg());30153016if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))3017return false;30183019if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + index))3020return false;30213022/* read base register */3023address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,3024dwarf_zero_mips + base, 0, &success);3025if (!success)3026return false;30273028/* read index register */3029index_address = (int32_t)ReadRegisterUnsigned(3030eRegisterKindDWARF, dwarf_zero_mips + index, 0, &success);3031if (!success)3032return false;30333034/* destination address */3035address = address + index_address;30363037/* Set the bad_vaddr register with base address used in the instruction */3038bad_vaddr_context.type = eContextInvalid;3039WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,3040address);30413042return true;3043}304430453046