brintos

brintos / llvm-project-archived public Read only

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