Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
39653 views
//===-- EmulateInstructionMIPS64.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 "EmulateInstructionMIPS64.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/Host/PosixApi.h"17#include "lldb/Symbol/UnwindPlan.h"18#include "lldb/Utility/ArchSpec.h"19#include "lldb/Utility/ConstString.h"20#include "lldb/Utility/DataExtractor.h"21#include "lldb/Utility/RegisterValue.h"22#include "lldb/Utility/Stream.h"23#include "llvm-c/Disassembler.h"24#include "llvm/MC/MCAsmInfo.h"25#include "llvm/MC/MCContext.h"26#include "llvm/MC/MCDisassembler/MCDisassembler.h"27#include "llvm/MC/MCInst.h"28#include "llvm/MC/MCInstrInfo.h"29#include "llvm/MC/MCRegisterInfo.h"30#include "llvm/MC/MCSubtargetInfo.h"31#include "llvm/MC/MCTargetOptions.h"32#include "llvm/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(EmulateInstructionMIPS64, InstructionMIPS64)4445#define UInt(x) ((uint64_t)x)46#define integer int64_t4748//49// EmulateInstructionMIPS64 implementation50//5152#ifdef __mips__53extern "C" {54void LLVMInitializeMipsTargetInfo();55void LLVMInitializeMipsTarget();56void LLVMInitializeMipsAsmPrinter();57void LLVMInitializeMipsTargetMC();58void LLVMInitializeMipsDisassembler();59}60#endif6162EmulateInstructionMIPS64::EmulateInstructionMIPS64(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,";148if (arch_flags & ArchSpec::eMIPSAse_mips16)149features += "+mips16,";150if (arch_flags & ArchSpec::eMIPSAse_micromips)151features += "+micromips,";152153m_reg_info.reset(target->createMCRegInfo(triple.getTriple()));154assert(m_reg_info.get());155156m_insn_info.reset(target->createMCInstrInfo());157assert(m_insn_info.get());158159llvm::MCTargetOptions MCOptions;160m_asm_info.reset(161target->createMCAsmInfo(*m_reg_info, triple.getTriple(), MCOptions));162m_subtype_info.reset(163target->createMCSubtargetInfo(triple.getTriple(), cpu, features));164assert(m_asm_info.get() && m_subtype_info.get());165166m_context = std::make_unique<llvm::MCContext>(167triple, m_asm_info.get(), m_reg_info.get(), m_subtype_info.get());168assert(m_context.get());169170m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context));171assert(m_disasm.get());172}173174void EmulateInstructionMIPS64::Initialize() {175PluginManager::RegisterPlugin(GetPluginNameStatic(),176GetPluginDescriptionStatic(), CreateInstance);177}178179void EmulateInstructionMIPS64::Terminate() {180PluginManager::UnregisterPlugin(CreateInstance);181}182183llvm::StringRef EmulateInstructionMIPS64::GetPluginDescriptionStatic() {184return "Emulate instructions for the MIPS64 architecture.";185}186187EmulateInstruction *188EmulateInstructionMIPS64::CreateInstance(const ArchSpec &arch,189InstructionType inst_type) {190if (EmulateInstructionMIPS64::SupportsEmulatingInstructionsOfTypeStatic(191inst_type)) {192if (arch.GetTriple().getArch() == llvm::Triple::mips64 ||193arch.GetTriple().getArch() == llvm::Triple::mips64el) {194return new EmulateInstructionMIPS64(arch);195}196}197198return nullptr;199}200201bool EmulateInstructionMIPS64::SetTargetTriple(const ArchSpec &arch) {202return arch.GetTriple().getArch() == llvm::Triple::mips64 ||203arch.GetTriple().getArch() == llvm::Triple::mips64el;204}205206const char *EmulateInstructionMIPS64::GetRegisterName(unsigned reg_num,207bool alternate_name) {208if (alternate_name) {209switch (reg_num) {210case dwarf_sp_mips64:211return "r29";212case dwarf_r30_mips64:213return "r30";214case dwarf_ra_mips64:215return "r31";216case dwarf_f0_mips64:217return "f0";218case dwarf_f1_mips64:219return "f1";220case dwarf_f2_mips64:221return "f2";222case dwarf_f3_mips64:223return "f3";224case dwarf_f4_mips64:225return "f4";226case dwarf_f5_mips64:227return "f5";228case dwarf_f6_mips64:229return "f6";230case dwarf_f7_mips64:231return "f7";232case dwarf_f8_mips64:233return "f8";234case dwarf_f9_mips64:235return "f9";236case dwarf_f10_mips64:237return "f10";238case dwarf_f11_mips64:239return "f11";240case dwarf_f12_mips64:241return "f12";242case dwarf_f13_mips64:243return "f13";244case dwarf_f14_mips64:245return "f14";246case dwarf_f15_mips64:247return "f15";248case dwarf_f16_mips64:249return "f16";250case dwarf_f17_mips64:251return "f17";252case dwarf_f18_mips64:253return "f18";254case dwarf_f19_mips64:255return "f19";256case dwarf_f20_mips64:257return "f20";258case dwarf_f21_mips64:259return "f21";260case dwarf_f22_mips64:261return "f22";262case dwarf_f23_mips64:263return "f23";264case dwarf_f24_mips64:265return "f24";266case dwarf_f25_mips64:267return "f25";268case dwarf_f26_mips64:269return "f26";270case dwarf_f27_mips64:271return "f27";272case dwarf_f28_mips64:273return "f28";274case dwarf_f29_mips64:275return "f29";276case dwarf_f30_mips64:277return "f30";278case dwarf_f31_mips64:279return "f31";280case dwarf_w0_mips64:281return "w0";282case dwarf_w1_mips64:283return "w1";284case dwarf_w2_mips64:285return "w2";286case dwarf_w3_mips64:287return "w3";288case dwarf_w4_mips64:289return "w4";290case dwarf_w5_mips64:291return "w5";292case dwarf_w6_mips64:293return "w6";294case dwarf_w7_mips64:295return "w7";296case dwarf_w8_mips64:297return "w8";298case dwarf_w9_mips64:299return "w9";300case dwarf_w10_mips64:301return "w10";302case dwarf_w11_mips64:303return "w11";304case dwarf_w12_mips64:305return "w12";306case dwarf_w13_mips64:307return "w13";308case dwarf_w14_mips64:309return "w14";310case dwarf_w15_mips64:311return "w15";312case dwarf_w16_mips64:313return "w16";314case dwarf_w17_mips64:315return "w17";316case dwarf_w18_mips64:317return "w18";318case dwarf_w19_mips64:319return "w19";320case dwarf_w20_mips64:321return "w20";322case dwarf_w21_mips64:323return "w21";324case dwarf_w22_mips64:325return "w22";326case dwarf_w23_mips64:327return "w23";328case dwarf_w24_mips64:329return "w24";330case dwarf_w25_mips64:331return "w25";332case dwarf_w26_mips64:333return "w26";334case dwarf_w27_mips64:335return "w27";336case dwarf_w28_mips64:337return "w28";338case dwarf_w29_mips64:339return "w29";340case dwarf_w30_mips64:341return "w30";342case dwarf_w31_mips64:343return "w31";344case dwarf_mir_mips64:345return "mir";346case dwarf_mcsr_mips64:347return "mcsr";348case dwarf_config5_mips64:349return "config5";350default:351break;352}353return nullptr;354}355356switch (reg_num) {357case dwarf_zero_mips64:358return "r0";359case dwarf_r1_mips64:360return "r1";361case dwarf_r2_mips64:362return "r2";363case dwarf_r3_mips64:364return "r3";365case dwarf_r4_mips64:366return "r4";367case dwarf_r5_mips64:368return "r5";369case dwarf_r6_mips64:370return "r6";371case dwarf_r7_mips64:372return "r7";373case dwarf_r8_mips64:374return "r8";375case dwarf_r9_mips64:376return "r9";377case dwarf_r10_mips64:378return "r10";379case dwarf_r11_mips64:380return "r11";381case dwarf_r12_mips64:382return "r12";383case dwarf_r13_mips64:384return "r13";385case dwarf_r14_mips64:386return "r14";387case dwarf_r15_mips64:388return "r15";389case dwarf_r16_mips64:390return "r16";391case dwarf_r17_mips64:392return "r17";393case dwarf_r18_mips64:394return "r18";395case dwarf_r19_mips64:396return "r19";397case dwarf_r20_mips64:398return "r20";399case dwarf_r21_mips64:400return "r21";401case dwarf_r22_mips64:402return "r22";403case dwarf_r23_mips64:404return "r23";405case dwarf_r24_mips64:406return "r24";407case dwarf_r25_mips64:408return "r25";409case dwarf_r26_mips64:410return "r26";411case dwarf_r27_mips64:412return "r27";413case dwarf_gp_mips64:414return "gp";415case dwarf_sp_mips64:416return "sp";417case dwarf_r30_mips64:418return "fp";419case dwarf_ra_mips64:420return "ra";421case dwarf_sr_mips64:422return "sr";423case dwarf_lo_mips64:424return "lo";425case dwarf_hi_mips64:426return "hi";427case dwarf_bad_mips64:428return "bad";429case dwarf_cause_mips64:430return "cause";431case dwarf_pc_mips64:432return "pc";433case dwarf_f0_mips64:434return "f0";435case dwarf_f1_mips64:436return "f1";437case dwarf_f2_mips64:438return "f2";439case dwarf_f3_mips64:440return "f3";441case dwarf_f4_mips64:442return "f4";443case dwarf_f5_mips64:444return "f5";445case dwarf_f6_mips64:446return "f6";447case dwarf_f7_mips64:448return "f7";449case dwarf_f8_mips64:450return "f8";451case dwarf_f9_mips64:452return "f9";453case dwarf_f10_mips64:454return "f10";455case dwarf_f11_mips64:456return "f11";457case dwarf_f12_mips64:458return "f12";459case dwarf_f13_mips64:460return "f13";461case dwarf_f14_mips64:462return "f14";463case dwarf_f15_mips64:464return "f15";465case dwarf_f16_mips64:466return "f16";467case dwarf_f17_mips64:468return "f17";469case dwarf_f18_mips64:470return "f18";471case dwarf_f19_mips64:472return "f19";473case dwarf_f20_mips64:474return "f20";475case dwarf_f21_mips64:476return "f21";477case dwarf_f22_mips64:478return "f22";479case dwarf_f23_mips64:480return "f23";481case dwarf_f24_mips64:482return "f24";483case dwarf_f25_mips64:484return "f25";485case dwarf_f26_mips64:486return "f26";487case dwarf_f27_mips64:488return "f27";489case dwarf_f28_mips64:490return "f28";491case dwarf_f29_mips64:492return "f29";493case dwarf_f30_mips64:494return "f30";495case dwarf_f31_mips64:496return "f31";497case dwarf_fcsr_mips64:498return "fcsr";499case dwarf_fir_mips64:500return "fir";501case dwarf_w0_mips64:502return "w0";503case dwarf_w1_mips64:504return "w1";505case dwarf_w2_mips64:506return "w2";507case dwarf_w3_mips64:508return "w3";509case dwarf_w4_mips64:510return "w4";511case dwarf_w5_mips64:512return "w5";513case dwarf_w6_mips64:514return "w6";515case dwarf_w7_mips64:516return "w7";517case dwarf_w8_mips64:518return "w8";519case dwarf_w9_mips64:520return "w9";521case dwarf_w10_mips64:522return "w10";523case dwarf_w11_mips64:524return "w11";525case dwarf_w12_mips64:526return "w12";527case dwarf_w13_mips64:528return "w13";529case dwarf_w14_mips64:530return "w14";531case dwarf_w15_mips64:532return "w15";533case dwarf_w16_mips64:534return "w16";535case dwarf_w17_mips64:536return "w17";537case dwarf_w18_mips64:538return "w18";539case dwarf_w19_mips64:540return "w19";541case dwarf_w20_mips64:542return "w20";543case dwarf_w21_mips64:544return "w21";545case dwarf_w22_mips64:546return "w22";547case dwarf_w23_mips64:548return "w23";549case dwarf_w24_mips64:550return "w24";551case dwarf_w25_mips64:552return "w25";553case dwarf_w26_mips64:554return "w26";555case dwarf_w27_mips64:556return "w27";557case dwarf_w28_mips64:558return "w28";559case dwarf_w29_mips64:560return "w29";561case dwarf_w30_mips64:562return "w30";563case dwarf_w31_mips64:564return "w31";565case dwarf_mcsr_mips64:566return "mcsr";567case dwarf_mir_mips64:568return "mir";569case dwarf_config5_mips64:570return "config5";571}572return nullptr;573}574575std::optional<RegisterInfo>576EmulateInstructionMIPS64::GetRegisterInfo(RegisterKind reg_kind,577uint32_t reg_num) {578if (reg_kind == eRegisterKindGeneric) {579switch (reg_num) {580case LLDB_REGNUM_GENERIC_PC:581reg_kind = eRegisterKindDWARF;582reg_num = dwarf_pc_mips64;583break;584case LLDB_REGNUM_GENERIC_SP:585reg_kind = eRegisterKindDWARF;586reg_num = dwarf_sp_mips64;587break;588case LLDB_REGNUM_GENERIC_FP:589reg_kind = eRegisterKindDWARF;590reg_num = dwarf_r30_mips64;591break;592case LLDB_REGNUM_GENERIC_RA:593reg_kind = eRegisterKindDWARF;594reg_num = dwarf_ra_mips64;595break;596case LLDB_REGNUM_GENERIC_FLAGS:597reg_kind = eRegisterKindDWARF;598reg_num = dwarf_sr_mips64;599break;600default:601return {};602}603}604605if (reg_kind == eRegisterKindDWARF) {606RegisterInfo reg_info;607::memset(®_info, 0, sizeof(RegisterInfo));608::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));609610if (reg_num == dwarf_sr_mips64 || reg_num == dwarf_fcsr_mips64 ||611reg_num == dwarf_fir_mips64 || reg_num == dwarf_mcsr_mips64 ||612reg_num == dwarf_mir_mips64 || reg_num == dwarf_config5_mips64) {613reg_info.byte_size = 4;614reg_info.format = eFormatHex;615reg_info.encoding = eEncodingUint;616} else if ((int)reg_num >= dwarf_zero_mips64 &&617(int)reg_num <= dwarf_f31_mips64) {618reg_info.byte_size = 8;619reg_info.format = eFormatHex;620reg_info.encoding = eEncodingUint;621} else if ((int)reg_num >= dwarf_w0_mips64 &&622(int)reg_num <= dwarf_w31_mips64) {623reg_info.byte_size = 16;624reg_info.format = eFormatVectorOfUInt8;625reg_info.encoding = eEncodingVector;626} else {627return {};628}629630reg_info.name = GetRegisterName(reg_num, false);631reg_info.alt_name = GetRegisterName(reg_num, true);632reg_info.kinds[eRegisterKindDWARF] = reg_num;633634switch (reg_num) {635case dwarf_r30_mips64:636reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;637break;638case dwarf_ra_mips64:639reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;640break;641case dwarf_sp_mips64:642reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;643break;644case dwarf_pc_mips64:645reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;646break;647case dwarf_sr_mips64:648reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;649break;650default:651break;652}653return reg_info;654}655return {};656}657658EmulateInstructionMIPS64::MipsOpcode *659EmulateInstructionMIPS64::GetOpcodeForInstruction(llvm::StringRef op_name) {660static EmulateInstructionMIPS64::MipsOpcode g_opcodes[] = {661// Prologue/Epilogue instructions662{"DADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu,663"DADDIU rt, rs, immediate"},664{"ADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu,665"ADDIU rt, rs, immediate"},666{"SD", &EmulateInstructionMIPS64::Emulate_SD, "SD rt, offset(rs)"},667{"LD", &EmulateInstructionMIPS64::Emulate_LD, "LD rt, offset(base)"},668{"DSUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,669"DSUBU rd, rs, rt"},670{"SUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,671"SUBU rd, rs, rt"},672{"DADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,673"DADDU rd, rs, rt"},674{"ADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,675"ADDU rd, rs, rt"},676{"LUI", &EmulateInstructionMIPS64::Emulate_LUI, "LUI rt, immediate"},677678// Load/Store instructions679/* Following list of emulated instructions are required by implementation680of hardware watchpoint681for MIPS in lldb. As we just need the address accessed by instructions,682we have generalised683all these instructions in 2 functions depending on their addressing684modes */685686{"LB", &EmulateInstructionMIPS64::Emulate_LDST_Imm,687"LB rt, offset(base)"},688{"LBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,689"LBE rt, offset(base)"},690{"LBU", &EmulateInstructionMIPS64::Emulate_LDST_Imm,691"LBU rt, offset(base)"},692{"LBUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,693"LBUE rt, offset(base)"},694{"LDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,695"LDC1 ft, offset(base)"},696{"LDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,697"LDL rt, offset(base)"},698{"LDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,699"LDR rt, offset(base)"},700{"LLD", &EmulateInstructionMIPS64::Emulate_LDST_Imm,701"LLD rt, offset(base)"},702{"LDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,703"LDC2 rt, offset(base)"},704{"LDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,705"LDXC1 fd, index (base)"},706{"LH", &EmulateInstructionMIPS64::Emulate_LDST_Imm,707"LH rt, offset(base)"},708{"LHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,709"LHE rt, offset(base)"},710{"LHU", &EmulateInstructionMIPS64::Emulate_LDST_Imm,711"LHU rt, offset(base)"},712{"LHUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,713"LHUE rt, offset(base)"},714{"LL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,715"LL rt, offset(base)"},716{"LLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,717"LLE rt, offset(base)"},718{"LUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,719"LUXC1 fd, index (base)"},720{"LW", &EmulateInstructionMIPS64::Emulate_LDST_Imm,721"LW rt, offset(rs)"},722{"LWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,723"LWC1 ft, offset(base)"},724{"LWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,725"LWC2 rt, offset(base)"},726{"LWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,727"LWE rt, offset(base)"},728{"LWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,729"LWL rt, offset(base)"},730{"LWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,731"LWLE rt, offset(base)"},732{"LWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,733"LWR rt, offset(base)"},734{"LWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,735"LWRE rt, offset(base)"},736{"LWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,737"LWXC1 fd, index (base)"},738739{"SB", &EmulateInstructionMIPS64::Emulate_LDST_Imm,740"SB rt, offset(base)"},741{"SBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,742"SBE rt, offset(base)"},743{"SC", &EmulateInstructionMIPS64::Emulate_LDST_Imm,744"SC rt, offset(base)"},745{"SCE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,746"SCE rt, offset(base)"},747{"SCD", &EmulateInstructionMIPS64::Emulate_LDST_Imm,748"SCD rt, offset(base)"},749{"SDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,750"SDL rt, offset(base)"},751{"SDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,752"SDR rt, offset(base)"},753{"SDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,754"SDC1 ft, offset(base)"},755{"SDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,756"SDC2 rt, offset(base)"},757{"SDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,758"SDXC1 fs, index (base)"},759{"SH", &EmulateInstructionMIPS64::Emulate_LDST_Imm,760"SH rt, offset(base)"},761{"SHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,762"SHE rt, offset(base)"},763{"SUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,764"SUXC1 fs, index (base)"},765{"SW", &EmulateInstructionMIPS64::Emulate_LDST_Imm,766"SW rt, offset(rs)"},767{"SWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,768"SWC1 ft, offset(base)"},769{"SWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,770"SWC2 rt, offset(base)"},771{"SWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,772"SWE rt, offset(base)"},773{"SWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,774"SWL rt, offset(base)"},775{"SWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,776"SWLE rt, offset(base)"},777{"SWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,778"SWR rt, offset(base)"},779{"SWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,780"SWRE rt, offset(base)"},781{"SWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,782"SWXC1 fs, index (base)"},783784// Branch instructions785{"BEQ", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"},786{"BEQ64", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"},787{"BNE", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"},788{"BNE64", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"},789{"BEQL", &EmulateInstructionMIPS64::Emulate_BXX_3ops,790"BEQL rs,rt,offset"},791{"BNEL", &EmulateInstructionMIPS64::Emulate_BXX_3ops,792"BNEL rs,rt,offset"},793{"BGEZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,794"BGEZALL rt,offset"},795{"BAL", &EmulateInstructionMIPS64::Emulate_BAL, "BAL offset"},796{"BGEZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,797"BGEZAL rs,offset"},798{"BALC", &EmulateInstructionMIPS64::Emulate_BALC, "BALC offset"},799{"BC", &EmulateInstructionMIPS64::Emulate_BC, "BC offset"},800{"BGEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"},801{"BGEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"},802{"BLEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,803"BLEZALC rs,offset"},804{"BGEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,805"BGEZALC rs,offset"},806{"BLTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,807"BLTZALC rs,offset"},808{"BGTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,809"BGTZALC rs,offset"},810{"BEQZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,811"BEQZALC rs,offset"},812{"BNEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,813"BNEZALC rs,offset"},814{"BEQC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,815"BEQC rs,rt,offset"},816{"BEQC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,817"BEQC rs,rt,offset"},818{"BNEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,819"BNEC rs,rt,offset"},820{"BNEC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,821"BNEC rs,rt,offset"},822{"BLTC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,823"BLTC rs,rt,offset"},824{"BLTC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,825"BLTC rs,rt,offset"},826{"BGEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,827"BGEC rs,rt,offset"},828{"BGEC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,829"BGEC rs,rt,offset"},830{"BLTUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,831"BLTUC rs,rt,offset"},832{"BLTUC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,833"BLTUC rs,rt,offset"},834{"BGEUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,835"BGEUC rs,rt,offset"},836{"BGEUC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,837"BGEUC rs,rt,offset"},838{"BLTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,839"BLTZC rt,offset"},840{"BLTZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,841"BLTZC rt,offset"},842{"BLEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,843"BLEZC rt,offset"},844{"BLEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,845"BLEZC rt,offset"},846{"BGEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,847"BGEZC rt,offset"},848{"BGEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,849"BGEZC rt,offset"},850{"BGTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,851"BGTZC rt,offset"},852{"BGTZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,853"BGTZC rt,offset"},854{"BEQZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,855"BEQZC rt,offset"},856{"BEQZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,857"BEQZC rt,offset"},858{"BNEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,859"BNEZC rt,offset"},860{"BNEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,861"BNEZC rt,offset"},862{"BGEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZL rt,offset"},863{"BGTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"},864{"BGTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"},865{"BGTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZL rt,offset"},866{"BLEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"},867{"BLEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"},868{"BLEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZL rt,offset"},869{"BLTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"},870{"BLTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"},871{"BLTZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,872"BLTZAL rt,offset"},873{"BLTZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,874"BLTZALL rt,offset"},875{"BLTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZL rt,offset"},876{"BOVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,877"BOVC rs,rt,offset"},878{"BNVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,879"BNVC rs,rt,offset"},880{"J", &EmulateInstructionMIPS64::Emulate_J, "J target"},881{"JAL", &EmulateInstructionMIPS64::Emulate_JAL, "JAL target"},882{"JALX", &EmulateInstructionMIPS64::Emulate_JAL, "JALX target"},883{"JALR", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target"},884{"JALR64", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target"},885{"JALR_HB", &EmulateInstructionMIPS64::Emulate_JALR, "JALR.HB target"},886{"JIALC", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"},887{"JIALC64", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"},888{"JIC", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"},889{"JIC64", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"},890{"JR", &EmulateInstructionMIPS64::Emulate_JR, "JR target"},891{"JR64", &EmulateInstructionMIPS64::Emulate_JR, "JR target"},892{"JR_HB", &EmulateInstructionMIPS64::Emulate_JR, "JR.HB target"},893{"BC1F", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1F cc, offset"},894{"BC1T", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1T cc, offset"},895{"BC1FL", &EmulateInstructionMIPS64::Emulate_FP_branch,896"BC1FL cc, offset"},897{"BC1TL", &EmulateInstructionMIPS64::Emulate_FP_branch,898"BC1TL cc, offset"},899{"BC1EQZ", &EmulateInstructionMIPS64::Emulate_BC1EQZ,900"BC1EQZ ft, offset"},901{"BC1NEZ", &EmulateInstructionMIPS64::Emulate_BC1NEZ,902"BC1NEZ ft, offset"},903{"BC1ANY2F", &EmulateInstructionMIPS64::Emulate_3D_branch,904"BC1ANY2F cc, offset"},905{"BC1ANY2T", &EmulateInstructionMIPS64::Emulate_3D_branch,906"BC1ANY2T cc, offset"},907{"BC1ANY4F", &EmulateInstructionMIPS64::Emulate_3D_branch,908"BC1ANY4F cc, offset"},909{"BC1ANY4T", &EmulateInstructionMIPS64::Emulate_3D_branch,910"BC1ANY4T cc, offset"},911{"BNZ_B", &EmulateInstructionMIPS64::Emulate_BNZB, "BNZ.b wt,s16"},912{"BNZ_H", &EmulateInstructionMIPS64::Emulate_BNZH, "BNZ.h wt,s16"},913{"BNZ_W", &EmulateInstructionMIPS64::Emulate_BNZW, "BNZ.w wt,s16"},914{"BNZ_D", &EmulateInstructionMIPS64::Emulate_BNZD, "BNZ.d wt,s16"},915{"BZ_B", &EmulateInstructionMIPS64::Emulate_BZB, "BZ.b wt,s16"},916{"BZ_H", &EmulateInstructionMIPS64::Emulate_BZH, "BZ.h wt,s16"},917{"BZ_W", &EmulateInstructionMIPS64::Emulate_BZW, "BZ.w wt,s16"},918{"BZ_D", &EmulateInstructionMIPS64::Emulate_BZD, "BZ.d wt,s16"},919{"BNZ_V", &EmulateInstructionMIPS64::Emulate_BNZV, "BNZ.V wt,s16"},920{"BZ_V", &EmulateInstructionMIPS64::Emulate_BZV, "BZ.V wt,s16"},921};922923for (MipsOpcode &opcode : g_opcodes) {924if (op_name.equals_insensitive(opcode.op_name))925return &opcode;926}927return nullptr;928}929930bool EmulateInstructionMIPS64::ReadInstruction() {931bool success = false;932m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,933LLDB_INVALID_ADDRESS, &success);934if (success) {935Context read_inst_context;936read_inst_context.type = eContextReadOpcode;937read_inst_context.SetNoArgs();938m_opcode.SetOpcode32(939ReadMemoryUnsigned(read_inst_context, m_addr, 4, 0, &success),940GetByteOrder());941}942if (!success)943m_addr = LLDB_INVALID_ADDRESS;944return success;945}946947bool EmulateInstructionMIPS64::EvaluateInstruction(uint32_t evaluate_options) {948bool success = false;949llvm::MCInst mc_insn;950uint64_t insn_size;951DataExtractor data;952953/* Keep the complexity of the decode logic with the llvm::MCDisassembler954* class. */955if (m_opcode.GetData(data)) {956llvm::MCDisassembler::DecodeStatus decode_status;957llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());958decode_status = m_disasm->getInstruction(mc_insn, insn_size, raw_insn,959m_addr, llvm::nulls());960if (decode_status != llvm::MCDisassembler::Success)961return false;962}963964/*965* mc_insn.getOpcode() returns decoded opcode. However to make use966* of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc".967*/968llvm::StringRef op_name = m_insn_info->getName(mc_insn.getOpcode());969970/*971* Decoding has been done already. Just get the call-back function972* and emulate the instruction.973*/974MipsOpcode *opcode_data = GetOpcodeForInstruction(op_name);975976if (opcode_data == nullptr)977return false;978979uint64_t old_pc = 0, new_pc = 0;980const bool auto_advance_pc =981evaluate_options & eEmulateInstructionOptionAutoAdvancePC;982983if (auto_advance_pc) {984old_pc =985ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);986if (!success)987return false;988}989990/* emulate instruction */991success = (this->*opcode_data->callback)(mc_insn);992if (!success)993return false;994995if (auto_advance_pc) {996new_pc =997ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);998if (!success)999return false;10001001/* If we haven't changed the PC, change it here */1002if (old_pc == new_pc) {1003new_pc += 4;1004Context context;1005if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,1006new_pc))1007return false;1008}1009}10101011return true;1012}10131014bool EmulateInstructionMIPS64::CreateFunctionEntryUnwind(1015UnwindPlan &unwind_plan) {1016unwind_plan.Clear();1017unwind_plan.SetRegisterKind(eRegisterKindDWARF);10181019UnwindPlan::RowSP row(new UnwindPlan::Row);1020const bool can_replace = false;10211022// Our previous Call Frame Address is the stack pointer1023row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips64, 0);10241025// Our previous PC is in the RA1026row->SetRegisterLocationToRegister(dwarf_pc_mips64, dwarf_ra_mips64,1027can_replace);10281029unwind_plan.AppendRow(row);10301031// All other registers are the same.1032unwind_plan.SetSourceName("EmulateInstructionMIPS64");1033unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);1034unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);1035unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);1036unwind_plan.SetReturnAddressRegister(dwarf_ra_mips64);10371038return true;1039}10401041bool EmulateInstructionMIPS64::nonvolatile_reg_p(uint64_t regnum) {1042switch (regnum) {1043case dwarf_r16_mips64:1044case dwarf_r17_mips64:1045case dwarf_r18_mips64:1046case dwarf_r19_mips64:1047case dwarf_r20_mips64:1048case dwarf_r21_mips64:1049case dwarf_r22_mips64:1050case dwarf_r23_mips64:1051case dwarf_gp_mips64:1052case dwarf_sp_mips64:1053case dwarf_r30_mips64:1054case dwarf_ra_mips64:1055return true;1056default:1057return false;1058}1059return false;1060}10611062bool EmulateInstructionMIPS64::Emulate_DADDiu(llvm::MCInst &insn) {1063// DADDIU rt, rs, immediate1064// GPR[rt] <- GPR[rs] + sign_extend(immediate)10651066uint8_t dst, src;1067bool success = false;1068const uint32_t imm16 = insn.getOperand(2).getImm();1069int64_t imm = SignedBits(imm16, 15, 0);10701071dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1072src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());10731074// If immediate is greater than 2^16 - 1 then clang generate LUI,1075// (D)ADDIU,(D)SUBU instructions in prolog. Example lui $1, 0x2 daddiu $1,1076// $1, -0x5920 dsubu $sp, $sp, $1 In this case, (D)ADDIU dst and src will be1077// same and not equal to sp1078if (dst == src) {1079Context context;10801081/* read <src> register */1082const uint64_t src_opd_val = ReadRegisterUnsigned(1083eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);1084if (!success)1085return false;10861087/* Check if this is daddiu sp, sp, imm16 */1088if (dst == dwarf_sp_mips64) {1089/*1090* From the MIPS IV spec:1091*1092* The term “unsigned” in the instruction name is a misnomer; this1093* operation is 64-bit modulo arithmetic that does not trap on overflow.1094* It is appropriate for arithmetic which is not signed, such as address1095* arithmetic, or integer arithmetic environments that ignore overflow,1096* such as “C” language arithmetic.1097*1098* Assume 2's complement and rely on unsigned overflow here.1099*/1100uint64_t result = src_opd_val + imm;1101std::optional<RegisterInfo> reg_info_sp =1102GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64);1103if (reg_info_sp)1104context.SetRegisterPlusOffset(*reg_info_sp, imm);11051106/* We are allocating bytes on stack */1107context.type = eContextAdjustStackPointer;11081109WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips64,1110result);1111return true;1112}11131114imm += src_opd_val;1115context.SetImmediateSigned(imm);1116context.type = eContextImmediate;11171118if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,1119dwarf_zero_mips64 + dst, imm))1120return false;1121}11221123return true;1124}11251126bool EmulateInstructionMIPS64::Emulate_SD(llvm::MCInst &insn) {1127uint64_t address;1128bool success = false;1129uint32_t imm16 = insn.getOperand(2).getImm();1130uint64_t imm = SignedBits(imm16, 15, 0);1131uint32_t src, base;1132Context bad_vaddr_context;11331134src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1135base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());11361137std::optional<RegisterInfo> reg_info_base =1138GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base);1139std::optional<RegisterInfo> reg_info_src =1140GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src);1141if (!reg_info_base || !reg_info_src)1142return false;11431144/* read SP */1145address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + base,11460, &success);1147if (!success)1148return false;11491150/* destination address */1151address = address + imm;11521153/* We look for sp based non-volatile register stores */1154if (nonvolatile_reg_p(src)) {1155Context context;1156context.type = eContextPushRegisterOnStack;1157context.SetRegisterToRegisterPlusOffset(*reg_info_src, *reg_info_base, 0);11581159std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);1160if (!data_src)1161return false;11621163Status error;1164RegisterValue::BytesContainer buffer(reg_info_src->byte_size);1165if (data_src->GetAsMemoryData(*reg_info_src, buffer.data(),1166reg_info_src->byte_size, eByteOrderLittle,1167error) == 0)1168return false;11691170if (!WriteMemory(context, address, buffer.data(), reg_info_src->byte_size))1171return false;1172}11731174/* Set the bad_vaddr register with base address used in the instruction */1175bad_vaddr_context.type = eContextInvalid;1176WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64,1177address);11781179return true;1180}11811182bool EmulateInstructionMIPS64::Emulate_LD(llvm::MCInst &insn) {1183bool success = false;1184uint32_t src, base;1185int64_t imm, address;1186Context bad_vaddr_context;11871188src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1189base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());1190imm = insn.getOperand(2).getImm();11911192if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base))1193return false;11941195/* read base register */1196address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + base,11970, &success);1198if (!success)1199return false;12001201/* destination address */1202address = address + imm;12031204/* Set the bad_vaddr register with base address used in the instruction */1205bad_vaddr_context.type = eContextInvalid;1206WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64,1207address);12081209if (nonvolatile_reg_p(src)) {1210RegisterValue data_src;1211std::optional<RegisterInfo> reg_info_src =1212GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src);1213if (!reg_info_src)1214return false;12151216Context context;1217context.type = eContextRegisterLoad;12181219return WriteRegister(context, *reg_info_src, data_src);1220}12211222return false;1223}12241225bool EmulateInstructionMIPS64::Emulate_LUI(llvm::MCInst &insn) {1226// LUI rt, immediate1227// GPR[rt] <- sign_extend(immediate << 16)12281229const uint32_t imm32 = insn.getOperand(1).getImm() << 16;1230int64_t imm = SignedBits(imm32, 31, 0);1231uint8_t rt;1232Context context;12331234rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1235context.SetImmediateSigned(imm);1236context.type = eContextImmediate;12371238return WriteRegisterUnsigned(context, eRegisterKindDWARF,1239dwarf_zero_mips64 + rt, imm);1240}12411242bool EmulateInstructionMIPS64::Emulate_DSUBU_DADDU(llvm::MCInst &insn) {1243// DSUBU sp, <src>, <rt>1244// DADDU sp, <src>, <rt>1245// DADDU dst, sp, <rt>12461247bool success = false;1248uint64_t result;1249uint8_t src, dst, rt;1250llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());12511252dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1253src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());12541255/* Check if sp is destination register */1256if (dst == dwarf_sp_mips64) {1257rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());12581259/* read <src> register */1260uint64_t src_opd_val = ReadRegisterUnsigned(1261eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);1262if (!success)1263return false;12641265/* read <rt > register */1266uint64_t rt_opd_val = ReadRegisterUnsigned(1267eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);1268if (!success)1269return false;12701271if (op_name.equals_insensitive("DSUBU") ||1272op_name.equals_insensitive("SUBU"))1273result = src_opd_val - rt_opd_val;1274else1275result = src_opd_val + rt_opd_val;12761277Context context;1278std::optional<RegisterInfo> reg_info_sp =1279GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64);1280if (reg_info_sp)1281context.SetRegisterPlusOffset(*reg_info_sp, rt_opd_val);12821283/* We are allocating bytes on stack */1284context.type = eContextAdjustStackPointer;12851286WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips64, result);12871288return true;1289} else if (src == dwarf_sp_mips64) {1290rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());12911292/* read <src> register */1293uint64_t src_opd_val = ReadRegisterUnsigned(1294eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);1295if (!success)1296return false;12971298/* read <rt> register */1299uint64_t rt_opd_val = ReadRegisterUnsigned(1300eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);1301if (!success)1302return false;13031304Context context;13051306if (op_name.equals_insensitive("DSUBU") ||1307op_name.equals_insensitive("SUBU"))1308result = src_opd_val - rt_opd_val;1309else1310result = src_opd_val + rt_opd_val;13111312context.SetImmediateSigned(result);1313context.type = eContextImmediate;13141315if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,1316dwarf_zero_mips64 + dst, result))1317return false;1318}13191320return true;1321}13221323/*1324Emulate below MIPS branch instructions.1325BEQ, BNE : Branch on condition1326BEQL, BNEL : Branch likely1327*/1328bool EmulateInstructionMIPS64::Emulate_BXX_3ops(llvm::MCInst &insn) {1329bool success = false;1330uint32_t rs, rt;1331int64_t offset, pc, rs_val, rt_val, target = 0;1332llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());13331334rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1335rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());1336offset = insn.getOperand(2).getImm();13371338pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);1339if (!success)1340return false;13411342rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,1343dwarf_zero_mips64 + rs, 0, &success);1344if (!success)1345return false;13461347rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,1348dwarf_zero_mips64 + rt, 0, &success);1349if (!success)1350return false;13511352if (op_name.equals_insensitive("BEQ") || op_name.equals_insensitive("BEQL") ||1353op_name.equals_insensitive("BEQ64")) {1354if (rs_val == rt_val)1355target = pc + offset;1356else1357target = pc + 8;1358} else if (op_name.equals_insensitive("BNE") ||1359op_name.equals_insensitive("BNEL") ||1360op_name.equals_insensitive("BNE64")) {1361if (rs_val != rt_val)1362target = pc + offset;1363else1364target = pc + 8;1365}13661367Context context;1368context.type = eContextRelativeBranchImmediate;1369context.SetImmediate(offset);13701371return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,1372target);1373}13741375/*1376Emulate below MIPS Non-Compact conditional branch and link instructions.1377BLTZAL, BGEZAL :1378BLTZALL, BGEZALL : Branch likely1379*/1380bool EmulateInstructionMIPS64::Emulate_Bcond_Link(llvm::MCInst &insn) {1381bool success = false;1382uint32_t rs;1383int64_t offset, pc, target = 0;1384int64_t rs_val;1385llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());13861387rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1388offset = insn.getOperand(1).getImm();13891390pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);1391if (!success)1392return false;13931394rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,1395dwarf_zero_mips64 + rs, 0, &success);1396if (!success)1397return false;13981399if (op_name.equals_insensitive("BLTZAL") ||1400op_name.equals_insensitive("BLTZALL")) {1401if (rs_val < 0)1402target = pc + offset;1403else1404target = pc + 8;1405} else if (op_name.equals_insensitive("BGEZAL") ||1406op_name.equals_insensitive("BGEZALL")) {1407if (rs_val >= 0)1408target = pc + offset;1409else1410target = pc + 8;1411}14121413Context context;14141415if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,1416target))1417return false;14181419if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,1420pc + 8))1421return false;14221423return true;1424}14251426bool EmulateInstructionMIPS64::Emulate_BAL(llvm::MCInst &insn) {1427bool success = false;1428int64_t offset, pc, target;14291430/*1431* BAL offset1432* offset = sign_ext (offset << 2)1433* RA = PC + 81434* PC = PC + offset1435*/1436offset = insn.getOperand(0).getImm();14371438pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);1439if (!success)1440return false;14411442target = pc + offset;14431444Context context;14451446if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,1447target))1448return false;14491450if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,1451pc + 8))1452return false;14531454return true;1455}14561457bool EmulateInstructionMIPS64::Emulate_BALC(llvm::MCInst &insn) {1458bool success = false;1459int64_t offset, pc, target;14601461/*1462* BALC offset1463* offset = sign_ext (offset << 2)1464* RA = PC + 41465* PC = PC + 4 + offset1466*/1467offset = insn.getOperand(0).getImm();14681469pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);1470if (!success)1471return false;14721473target = pc + offset;14741475Context context;14761477if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,1478target))1479return false;14801481if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,1482pc + 4))1483return false;14841485return true;1486}14871488/*1489Emulate below MIPS conditional branch and link instructions.1490BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches1491*/1492bool EmulateInstructionMIPS64::Emulate_Bcond_Link_C(llvm::MCInst &insn) {1493bool success = false;1494uint32_t rs;1495int64_t offset, pc, rs_val, target = 0;1496llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());14971498rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1499offset = insn.getOperand(1).getImm();15001501pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);1502if (!success)1503return false;15041505rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,1506dwarf_zero_mips64 + rs, 0, &success);1507if (!success)1508return false;15091510if (op_name.equals_insensitive("BLEZALC")) {1511if (rs_val <= 0)1512target = pc + offset;1513else1514target = pc + 4;1515} else if (op_name.equals_insensitive("BGEZALC")) {1516if (rs_val >= 0)1517target = pc + offset;1518else1519target = pc + 4;1520} else if (op_name.equals_insensitive("BLTZALC")) {1521if (rs_val < 0)1522target = pc + offset;1523else1524target = pc + 4;1525} else if (op_name.equals_insensitive("BGTZALC")) {1526if (rs_val > 0)1527target = pc + offset;1528else1529target = pc + 4;1530} else if (op_name.equals_insensitive("BEQZALC")) {1531if (rs_val == 0)1532target = pc + offset;1533else1534target = pc + 4;1535} else if (op_name.equals_insensitive("BNEZALC")) {1536if (rs_val != 0)1537target = pc + offset;1538else1539target = pc + 4;1540}15411542Context context;15431544if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,1545target))1546return false;15471548if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,1549pc + 4))1550return false;15511552return true;1553}15541555/*1556Emulate below MIPS branch instructions.1557BLTZL, BGEZL, BGTZL, BLEZL : Branch likely1558BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches1559*/1560bool EmulateInstructionMIPS64::Emulate_BXX_2ops(llvm::MCInst &insn) {1561bool success = false;1562uint32_t rs;1563int64_t offset, pc, rs_val, target = 0;1564llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());15651566rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1567offset = insn.getOperand(1).getImm();15681569pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);1570if (!success)1571return false;15721573rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,1574dwarf_zero_mips64 + rs, 0, &success);1575if (!success)1576return false;15771578if (op_name.equals_insensitive("BLTZL") ||1579op_name.equals_insensitive("BLTZ") ||1580op_name.equals_insensitive("BLTZ64")) {1581if (rs_val < 0)1582target = pc + offset;1583else1584target = pc + 8;1585} else if (op_name.equals_insensitive("BGEZL") ||1586op_name.equals_insensitive("BGEZ") ||1587op_name.equals_insensitive("BGEZ64")) {1588if (rs_val >= 0)1589target = pc + offset;1590else1591target = pc + 8;1592} else if (op_name.equals_insensitive("BGTZL") ||1593op_name.equals_insensitive("BGTZ") ||1594op_name.equals_insensitive("BGTZ64")) {1595if (rs_val > 0)1596target = pc + offset;1597else1598target = pc + 8;1599} else if (op_name.equals_insensitive("BLEZL") ||1600op_name.equals_insensitive("BLEZ") ||1601op_name.equals_insensitive("BLEZ64")) {1602if (rs_val <= 0)1603target = pc + offset;1604else1605target = pc + 8;1606}16071608Context context;1609context.type = eContextRelativeBranchImmediate;1610context.SetImmediate(offset);16111612return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,1613target);1614}16151616bool EmulateInstructionMIPS64::Emulate_BC(llvm::MCInst &insn) {1617bool success = false;1618int64_t offset, pc, target;16191620/*1621* BC offset1622* offset = sign_ext (offset << 2)1623* PC = PC + 4 + offset1624*/1625offset = insn.getOperand(0).getImm();16261627pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);1628if (!success)1629return false;16301631target = pc + offset;16321633Context context;16341635return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,1636target);1637}16381639static int IsAdd64bitOverflow(int64_t a, int64_t b) {1640int64_t r = (uint64_t)a + (uint64_t)b;1641return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);1642}16431644/*1645Emulate below MIPS branch instructions.1646BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch1647instructions with no delay slot1648*/1649bool EmulateInstructionMIPS64::Emulate_BXX_3ops_C(llvm::MCInst &insn) {1650bool success = false;1651uint32_t rs, rt;1652int64_t offset, pc, rs_val, rt_val, target = 0;1653llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());1654uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();16551656rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1657rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());1658offset = insn.getOperand(2).getImm();16591660pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);1661if (!success)1662return false;16631664rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,1665dwarf_zero_mips64 + rs, 0, &success);1666if (!success)1667return false;16681669rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,1670dwarf_zero_mips64 + rt, 0, &success);1671if (!success)1672return false;16731674if (op_name.equals_insensitive("BEQC") ||1675op_name.equals_insensitive("BEQC64")) {1676if (rs_val == rt_val)1677target = pc + offset;1678else1679target = pc + 4;1680} else if (op_name.equals_insensitive("BNEC") ||1681op_name.equals_insensitive("BNEC64")) {1682if (rs_val != rt_val)1683target = pc + offset;1684else1685target = pc + 4;1686} else if (op_name.equals_insensitive("BLTC") ||1687op_name.equals_insensitive("BLTC64")) {1688if (rs_val < rt_val)1689target = pc + offset;1690else1691target = pc + 4;1692} else if (op_name.equals_insensitive("BGEC64") ||1693op_name.equals_insensitive("BGEC")) {1694if (rs_val >= rt_val)1695target = pc + offset;1696else1697target = pc + 4;1698} else if (op_name.equals_insensitive("BLTUC") ||1699op_name.equals_insensitive("BLTUC64")) {1700if (rs_val < rt_val)1701target = pc + offset;1702else1703target = pc + 4;1704} else if (op_name.equals_insensitive("BGEUC") ||1705op_name.equals_insensitive("BGEUC64")) {1706if ((uint32_t)rs_val >= (uint32_t)rt_val)1707target = pc + offset;1708else1709target = pc + 4;1710} else if (op_name.equals_insensitive("BOVC")) {1711if (IsAdd64bitOverflow(rs_val, rt_val))1712target = pc + offset;1713else1714target = pc + 4;1715} else if (op_name.equals_insensitive("BNVC")) {1716if (!IsAdd64bitOverflow(rs_val, rt_val))1717target = pc + offset;1718else1719target = pc + 4;1720}17211722Context context;1723context.type = eContextRelativeBranchImmediate;1724context.SetImmediate(current_inst_size + offset);17251726return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,1727target);1728}17291730/*1731Emulate below MIPS branch instructions.1732BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches1733*/1734bool EmulateInstructionMIPS64::Emulate_BXX_2ops_C(llvm::MCInst &insn) {1735bool success = false;1736uint32_t rs;1737int64_t offset, pc, target = 0;1738int64_t rs_val;1739llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());1740uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();17411742rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1743offset = insn.getOperand(1).getImm();17441745pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);1746if (!success)1747return false;17481749rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,1750dwarf_zero_mips64 + rs, 0, &success);1751if (!success)1752return false;17531754if (op_name.equals_insensitive("BLTZC") ||1755op_name.equals_insensitive("BLTZC64")) {1756if (rs_val < 0)1757target = pc + offset;1758else1759target = pc + 4;1760} else if (op_name.equals_insensitive("BLEZC") ||1761op_name.equals_insensitive("BLEZC64")) {1762if (rs_val <= 0)1763target = pc + offset;1764else1765target = pc + 4;1766} else if (op_name.equals_insensitive("BGEZC") ||1767op_name.equals_insensitive("BGEZC64")) {1768if (rs_val >= 0)1769target = pc + offset;1770else1771target = pc + 4;1772} else if (op_name.equals_insensitive("BGTZC") ||1773op_name.equals_insensitive("BGTZC64")) {1774if (rs_val > 0)1775target = pc + offset;1776else1777target = pc + 4;1778} else if (op_name.equals_insensitive("BEQZC") ||1779op_name.equals_insensitive("BEQZC64")) {1780if (rs_val == 0)1781target = pc + offset;1782else1783target = pc + 4;1784} else if (op_name.equals_insensitive("BNEZC") ||1785op_name.equals_insensitive("BNEZC64")) {1786if (rs_val != 0)1787target = pc + offset;1788else1789target = pc + 4;1790}17911792Context context;1793context.type = eContextRelativeBranchImmediate;1794context.SetImmediate(current_inst_size + offset);17951796return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,1797target);1798}17991800bool EmulateInstructionMIPS64::Emulate_J(llvm::MCInst &insn) {1801bool success = false;1802uint64_t offset, pc;18031804/*1805* J offset1806* offset = sign_ext (offset << 2)1807* PC = PC[63-28] | offset1808*/1809offset = insn.getOperand(0).getImm();18101811pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);1812if (!success)1813return false;18141815/* This is a PC-region branch and not PC-relative */1816pc = (pc & 0xFFFFFFFFF0000000ULL) | offset;18171818Context context;18191820return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,1821pc);1822}18231824bool EmulateInstructionMIPS64::Emulate_JAL(llvm::MCInst &insn) {1825bool success = false;1826uint64_t offset, target, pc;18271828/*1829* JAL offset1830* offset = sign_ext (offset << 2)1831* PC = PC[63-28] | offset1832*/1833offset = insn.getOperand(0).getImm();18341835pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);1836if (!success)1837return false;18381839/* This is a PC-region branch and not PC-relative */1840target = (pc & 0xFFFFFFFFF0000000ULL) | offset;18411842Context context;18431844if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,1845target))1846return false;18471848if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,1849pc + 8))1850return false;18511852return true;1853}18541855bool EmulateInstructionMIPS64::Emulate_JALR(llvm::MCInst &insn) {1856bool success = false;1857uint32_t rs, rt;1858uint64_t pc, rs_val;18591860/*1861* JALR rt, rs1862* GPR[rt] = PC + 81863* PC = GPR[rs]1864*/1865rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1866rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());18671868pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);1869if (!success)1870return false;18711872rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0,1873&success);1874if (!success)1875return false;18761877Context context;18781879if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,1880rs_val))1881return false;18821883if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,1884dwarf_zero_mips64 + rt, pc + 8))1885return false;18861887return true;1888}18891890bool EmulateInstructionMIPS64::Emulate_JIALC(llvm::MCInst &insn) {1891bool success = false;1892uint32_t rt;1893int64_t target, offset, pc, rt_val;18941895/*1896* JIALC rt, offset1897* offset = sign_ext (offset)1898* PC = GPR[rt] + offset1899* RA = PC + 41900*/1901rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1902offset = insn.getOperand(1).getImm();19031904pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);1905if (!success)1906return false;19071908rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,1909dwarf_zero_mips64 + rt, 0, &success);1910if (!success)1911return false;19121913target = rt_val + offset;19141915Context context;19161917if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,1918target))1919return false;19201921if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,1922pc + 4))1923return false;19241925return true;1926}19271928bool EmulateInstructionMIPS64::Emulate_JIC(llvm::MCInst &insn) {1929bool success = false;1930uint32_t rt;1931int64_t target, offset, rt_val;19321933/*1934* JIC rt, offset1935* offset = sign_ext (offset)1936* PC = GPR[rt] + offset1937*/1938rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1939offset = insn.getOperand(1).getImm();19401941rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,1942dwarf_zero_mips64 + rt, 0, &success);1943if (!success)1944return false;19451946target = rt_val + offset;19471948Context context;19491950return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,1951target);1952}19531954bool EmulateInstructionMIPS64::Emulate_JR(llvm::MCInst &insn) {1955bool success = false;1956uint32_t rs;1957uint64_t rs_val;19581959/*1960* JR rs1961* PC = GPR[rs]1962*/1963rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());19641965rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0,1966&success);1967if (!success)1968return false;19691970Context context;19711972return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,1973rs_val);1974}19751976/*1977Emulate Branch on FP True/False1978BC1F, BC1FL : Branch on FP False (L stands for branch likely)1979BC1T, BC1TL : Branch on FP True (L stands for branch likely)1980*/1981bool EmulateInstructionMIPS64::Emulate_FP_branch(llvm::MCInst &insn) {1982bool success = false;1983uint32_t cc, fcsr;1984int64_t pc, offset, target = 0;1985llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());19861987/*1988* BC1F cc, offset1989* condition <- (FPConditionCode(cc) == 0)1990* if condition then1991* offset = sign_ext (offset)1992* PC = PC + offset1993*/1994cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());1995offset = insn.getOperand(1).getImm();19961997pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);1998if (!success)1999return false;20002001fcsr =2002ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);2003if (!success)2004return false;20052006/* fcsr[23], fcsr[25-31] are vaild condition bits */2007fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);20082009if (op_name.equals_insensitive("BC1F") ||2010op_name.equals_insensitive("BC1FL")) {2011if ((fcsr & (1 << cc)) == 0)2012target = pc + offset;2013else2014target = pc + 8;2015} else if (op_name.equals_insensitive("BC1T") ||2016op_name.equals_insensitive("BC1TL")) {2017if ((fcsr & (1 << cc)) != 0)2018target = pc + offset;2019else2020target = pc + 8;2021}20222023Context context;20242025return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,2026target);2027}20282029bool EmulateInstructionMIPS64::Emulate_BC1EQZ(llvm::MCInst &insn) {2030bool success = false;2031uint32_t ft;2032uint64_t ft_val;2033int64_t target, pc, offset;20342035/*2036* BC1EQZ ft, offset2037* condition <- (FPR[ft].bit0 == 0)2038* if condition then2039* offset = sign_ext (offset)2040* PC = PC + 4 + offset2041*/2042ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2043offset = insn.getOperand(1).getImm();20442045pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);2046if (!success)2047return false;20482049ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0,2050&success);2051if (!success)2052return false;20532054if ((ft_val & 1) == 0)2055target = pc + 4 + offset;2056else2057target = pc + 8;20582059Context context;20602061return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,2062target);2063}20642065bool EmulateInstructionMIPS64::Emulate_BC1NEZ(llvm::MCInst &insn) {2066bool success = false;2067uint32_t ft;2068uint64_t ft_val;2069int64_t target, pc, offset;20702071/*2072* BC1NEZ ft, offset2073* condition <- (FPR[ft].bit0 != 0)2074* if condition then2075* offset = sign_ext (offset)2076* PC = PC + 4 + offset2077*/2078ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2079offset = insn.getOperand(1).getImm();20802081pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);2082if (!success)2083return false;20842085ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0,2086&success);2087if (!success)2088return false;20892090if ((ft_val & 1) != 0)2091target = pc + 4 + offset;2092else2093target = pc + 8;20942095Context context;20962097return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,2098target);2099}21002101/*2102Emulate MIPS-3D Branch instructions2103BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes2104False/True2105BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes2106False/True2107*/2108bool EmulateInstructionMIPS64::Emulate_3D_branch(llvm::MCInst &insn) {2109bool success = false;2110uint32_t cc, fcsr;2111int64_t pc, offset, target = 0;2112llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());21132114cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2115offset = insn.getOperand(1).getImm();21162117pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);2118if (!success)2119return false;21202121fcsr = (uint32_t)ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips64,21220, &success);2123if (!success)2124return false;21252126/* fcsr[23], fcsr[25-31] are vaild condition bits */2127fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);21282129if (op_name.equals_insensitive("BC1ANY2F")) {2130/* if any one bit is 0 */2131if (((fcsr >> cc) & 3) != 3)2132target = pc + offset;2133else2134target = pc + 8;2135} else if (op_name.equals_insensitive("BC1ANY2T")) {2136/* if any one bit is 1 */2137if (((fcsr >> cc) & 3) != 0)2138target = pc + offset;2139else2140target = pc + 8;2141} else if (op_name.equals_insensitive("BC1ANY4F")) {2142/* if any one bit is 0 */2143if (((fcsr >> cc) & 0xf) != 0xf)2144target = pc + offset;2145else2146target = pc + 8;2147} else if (op_name.equals_insensitive("BC1ANY4T")) {2148/* if any one bit is 1 */2149if (((fcsr >> cc) & 0xf) != 0)2150target = pc + offset;2151else2152target = pc + 8;2153}21542155Context context;21562157return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,2158target);2159}21602161bool EmulateInstructionMIPS64::Emulate_BNZB(llvm::MCInst &insn) {2162return Emulate_MSA_Branch_DF(insn, 1, true);2163}21642165bool EmulateInstructionMIPS64::Emulate_BNZH(llvm::MCInst &insn) {2166return Emulate_MSA_Branch_DF(insn, 2, true);2167}21682169bool EmulateInstructionMIPS64::Emulate_BNZW(llvm::MCInst &insn) {2170return Emulate_MSA_Branch_DF(insn, 4, true);2171}21722173bool EmulateInstructionMIPS64::Emulate_BNZD(llvm::MCInst &insn) {2174return Emulate_MSA_Branch_DF(insn, 8, true);2175}21762177bool EmulateInstructionMIPS64::Emulate_BZB(llvm::MCInst &insn) {2178return Emulate_MSA_Branch_DF(insn, 1, false);2179}21802181bool EmulateInstructionMIPS64::Emulate_BZH(llvm::MCInst &insn) {2182return Emulate_MSA_Branch_DF(insn, 2, false);2183}21842185bool EmulateInstructionMIPS64::Emulate_BZW(llvm::MCInst &insn) {2186return Emulate_MSA_Branch_DF(insn, 4, false);2187}21882189bool EmulateInstructionMIPS64::Emulate_BZD(llvm::MCInst &insn) {2190return Emulate_MSA_Branch_DF(insn, 8, false);2191}21922193bool EmulateInstructionMIPS64::Emulate_MSA_Branch_DF(llvm::MCInst &insn,2194int element_byte_size,2195bool bnz) {2196bool success = false, branch_hit = true;2197int64_t target = 0;2198RegisterValue reg_value;2199const uint8_t *ptr = nullptr;22002201uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2202int64_t offset = insn.getOperand(1).getImm();22032204int64_t pc =2205ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);2206if (!success)2207return false;22082209if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value))2210ptr = (const uint8_t *)reg_value.GetBytes();2211else2212return false;22132214for (int i = 0; i < 16 / element_byte_size; i++) {2215switch (element_byte_size) {2216case 1:2217if ((*ptr == 0 && bnz) || (*ptr != 0 && !bnz))2218branch_hit = false;2219break;2220case 2:2221if ((*(const uint16_t *)ptr == 0 && bnz) ||2222(*(const uint16_t *)ptr != 0 && !bnz))2223branch_hit = false;2224break;2225case 4:2226if ((*(const uint32_t *)ptr == 0 && bnz) ||2227(*(const uint32_t *)ptr != 0 && !bnz))2228branch_hit = false;2229break;2230case 8:2231if ((*(const uint64_t *)ptr == 0 && bnz) ||2232(*(const uint64_t *)ptr != 0 && !bnz))2233branch_hit = false;2234break;2235}2236if (!branch_hit)2237break;2238ptr = ptr + element_byte_size;2239}22402241if (branch_hit)2242target = pc + offset;2243else2244target = pc + 8;22452246Context context;2247context.type = eContextRelativeBranchImmediate;22482249return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,2250target);2251}22522253bool EmulateInstructionMIPS64::Emulate_BNZV(llvm::MCInst &insn) {2254return Emulate_MSA_Branch_V(insn, true);2255}22562257bool EmulateInstructionMIPS64::Emulate_BZV(llvm::MCInst &insn) {2258return Emulate_MSA_Branch_V(insn, false);2259}22602261bool EmulateInstructionMIPS64::Emulate_MSA_Branch_V(llvm::MCInst &insn,2262bool bnz) {2263bool success = false;2264int64_t target = 0;2265llvm::APInt wr_val = llvm::APInt::getZero(128);2266llvm::APInt fail_value = llvm::APInt::getMaxValue(128);2267llvm::APInt zero_value = llvm::APInt::getZero(128);2268RegisterValue reg_value;22692270uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());2271int64_t offset = insn.getOperand(1).getImm();22722273int64_t pc =2274ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);2275if (!success)2276return false;22772278if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value))2279wr_val = reg_value.GetAsUInt128(fail_value);2280else2281return false;22822283if ((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) ||2284(!llvm::APInt::isSameValue(zero_value, wr_val) && bnz))2285target = pc + offset;2286else2287target = pc + 8;22882289Context context;2290context.type = eContextRelativeBranchImmediate;22912292return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,2293target);2294}22952296bool EmulateInstructionMIPS64::Emulate_LDST_Imm(llvm::MCInst &insn) {2297bool success = false;2298uint32_t base;2299int64_t imm, address;2300Context bad_vaddr_context;23012302uint32_t num_operands = insn.getNumOperands();2303base =2304m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());2305imm = insn.getOperand(num_operands - 1).getImm();23062307if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))2308return false;23092310/* read base register */2311address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0,2312&success);2313if (!success)2314return false;23152316/* destination address */2317address = address + imm;23182319/* Set the bad_vaddr register with base address used in the instruction */2320bad_vaddr_context.type = eContextInvalid;2321WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,2322address);23232324return true;2325}23262327bool EmulateInstructionMIPS64::Emulate_LDST_Reg(llvm::MCInst &insn) {2328bool success = false;2329uint32_t base, index;2330int64_t address, index_address;2331Context bad_vaddr_context;23322333uint32_t num_operands = insn.getNumOperands();2334base =2335m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());2336index =2337m_reg_info->getEncodingValue(insn.getOperand(num_operands - 1).getReg());23382339if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))2340return false;23412342if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + index))2343return false;23442345/* read base register */2346address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0,2347&success);2348if (!success)2349return false;23502351/* read index register */2352index_address = ReadRegisterUnsigned(eRegisterKindDWARF,2353dwarf_zero_mips + index, 0, &success);2354if (!success)2355return false;23562357/* destination address */2358address = address + index_address;23592360/* Set the bad_vaddr register with base address used in the instruction */2361bad_vaddr_context.type = eContextInvalid;2362WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,2363address);23642365return true;2366}236723682369