brintos

brintos / llvm-project-archived public Read only

0
0
Text · 30.2 KiB · e84aaaa Raw
819 lines · cpp
1//===-- ARMMCTargetDesc.cpp - ARM Target Descriptions ---------------------===//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// This file provides ARM specific target descriptions.10//11//===----------------------------------------------------------------------===//12 13#include "ARMMCTargetDesc.h"14#include "ARMAddressingModes.h"15#include "ARMBaseInfo.h"16#include "ARMInstPrinter.h"17#include "ARMMCAsmInfo.h"18#include "TargetInfo/ARMTargetInfo.h"19#include "llvm/DebugInfo/CodeView/CodeView.h"20#include "llvm/MC/MCAsmBackend.h"21#include "llvm/MC/MCCodeEmitter.h"22#include "llvm/MC/MCELFStreamer.h"23#include "llvm/MC/MCInstrAnalysis.h"24#include "llvm/MC/MCInstrInfo.h"25#include "llvm/MC/MCObjectWriter.h"26#include "llvm/MC/MCRegisterInfo.h"27#include "llvm/MC/MCStreamer.h"28#include "llvm/MC/MCSubtargetInfo.h"29#include "llvm/MC/TargetRegistry.h"30#include "llvm/Support/Compiler.h"31#include "llvm/Support/ErrorHandling.h"32#include "llvm/TargetParser/Triple.h"33 34using namespace llvm;35 36#define GET_REGINFO_MC_DESC37#include "ARMGenRegisterInfo.inc"38 39static bool getMCRDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,40                                  std::string &Info) {41  if (STI.hasFeature(llvm::ARM::HasV7Ops) &&42      (MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 15) &&43      (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) &&44      // Checks for the deprecated CP15ISB encoding:45      // mcr p15, #0, rX, c7, c5, #446      (MI.getOperand(3).isImm() && MI.getOperand(3).getImm() == 7)) {47    if ((MI.getOperand(5).isImm() && MI.getOperand(5).getImm() == 4)) {48      if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 5) {49        Info = "deprecated since v7, use 'isb'";50        return true;51      }52 53      // Checks for the deprecated CP15DSB encoding:54      // mcr p15, #0, rX, c7, c10, #455      if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 10) {56        Info = "deprecated since v7, use 'dsb'";57        return true;58      }59    }60    // Checks for the deprecated CP15DMB encoding:61    // mcr p15, #0, rX, c7, c10, #562    if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 10 &&63        (MI.getOperand(5).isImm() && MI.getOperand(5).getImm() == 5)) {64      Info = "deprecated since v7, use 'dmb'";65      return true;66    }67  }68  if (STI.hasFeature(llvm::ARM::HasV7Ops) &&69      ((MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 10) ||70       (MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 11))) {71    Info = "since v7, cp10 and cp11 are reserved for advanced SIMD or floating "72           "point instructions";73    return true;74  }75  return false;76}77 78static bool getMRCDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,79                                  std::string &Info) {80  if (STI.hasFeature(llvm::ARM::HasV7Ops) &&81      ((MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 10) ||82       (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 11))) {83    Info = "since v7, cp10 and cp11 are reserved for advanced SIMD or floating "84           "point instructions";85    return true;86  }87  return false;88}89 90static bool getARMStoreDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,91                                       std::string &Info) {92  assert(!STI.hasFeature(llvm::ARM::ModeThumb) &&93         "cannot predicate thumb instructions");94 95  assert(MI.getNumOperands() >= 4 && "expected >= 4 arguments");96  for (unsigned OI = 4, OE = MI.getNumOperands(); OI < OE; ++OI) {97    assert(MI.getOperand(OI).isReg() && "expected register");98    if (MI.getOperand(OI).getReg() == ARM::PC) {99      Info = "use of PC in the list is deprecated";100      return true;101    }102  }103  return false;104}105 106static bool getARMLoadDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,107                                      std::string &Info) {108  assert(!STI.hasFeature(llvm::ARM::ModeThumb) &&109         "cannot predicate thumb instructions");110 111  assert(MI.getNumOperands() >= 4 && "expected >= 4 arguments");112  bool ListContainsPC = false, ListContainsLR = false;113  for (unsigned OI = 4, OE = MI.getNumOperands(); OI < OE; ++OI) {114    assert(MI.getOperand(OI).isReg() && "expected register");115    switch (MI.getOperand(OI).getReg().id()) {116    default:117      break;118    case ARM::LR:119      ListContainsLR = true;120      break;121    case ARM::PC:122      ListContainsPC = true;123      break;124    }125  }126 127  if (ListContainsPC && ListContainsLR) {128    Info = "use of LR and PC simultaneously in the list is deprecated";129    return true;130  }131 132  return false;133}134 135#define GET_INSTRINFO_MC_DESC136#define ENABLE_INSTR_PREDICATE_VERIFIER137#include "ARMGenInstrInfo.inc"138 139#define GET_SUBTARGETINFO_MC_DESC140#include "ARMGenSubtargetInfo.inc"141 142std::string ARM_MC::ParseARMTriple(const Triple &TT, StringRef CPU) {143  std::string ARMArchFeature;144 145  ARM::ArchKind ArchID = ARM::parseArch(TT.getArchName());146  if (ArchID != ARM::ArchKind::INVALID &&  (CPU.empty() || CPU == "generic"))147    ARMArchFeature = (ARMArchFeature + "+" + ARM::getArchName(ArchID)).str();148 149  if (TT.isThumb()) {150    if (!ARMArchFeature.empty())151      ARMArchFeature += ",";152    ARMArchFeature += "+thumb-mode,+v4t";153  }154 155  if (TT.isOSWindows()) {156    if (!ARMArchFeature.empty())157      ARMArchFeature += ",";158    ARMArchFeature += "+noarm";159  }160 161  return ARMArchFeature;162}163 164bool ARM_MC::isPredicated(const MCInst &MI, const MCInstrInfo *MCII) {165  const MCInstrDesc &Desc = MCII->get(MI.getOpcode());166  int PredOpIdx = Desc.findFirstPredOperandIdx();167  return PredOpIdx != -1 && MI.getOperand(PredOpIdx).getImm() != ARMCC::AL;168}169 170bool ARM_MC::isCPSRDefined(const MCInst &MI, const MCInstrInfo *MCII) {171  const MCInstrDesc &Desc = MCII->get(MI.getOpcode());172  for (unsigned I = 0; I < MI.getNumOperands(); ++I) {173    const MCOperand &MO = MI.getOperand(I);174    if (MO.isReg() && MO.getReg() == ARM::CPSR &&175        Desc.operands()[I].isOptionalDef())176      return true;177  }178  return false;179}180 181uint64_t ARM_MC::evaluateBranchTarget(const MCInstrDesc &InstDesc,182                                      uint64_t Addr, int64_t Imm) {183  // For ARM instructions the PC offset is 8 bytes, for Thumb instructions it184  // is 4 bytes.185  uint64_t Offset =186      ((InstDesc.TSFlags & ARMII::FormMask) == ARMII::ThumbFrm) ? 4 : 8;187 188  // A Thumb instruction BLX(i) can be 16-bit aligned while targets Arm code189  // which is 32-bit aligned. The target address for the case is calculated as190  //   targetAddress = Align(PC,4) + imm32;191  // where192  //   Align(x, y) = y * (x DIV y);193  if (InstDesc.getOpcode() == ARM::tBLXi)194    Addr &= ~0x3;195 196  return Addr + Imm + Offset;197}198 199MCSubtargetInfo *ARM_MC::createARMMCSubtargetInfo(const Triple &TT,200                                                  StringRef CPU, StringRef FS) {201  std::string ArchFS = ARM_MC::ParseARMTriple(TT, CPU);202  if (!FS.empty()) {203    if (!ArchFS.empty())204      ArchFS = (Twine(ArchFS) + "," + FS).str();205    else206      ArchFS = std::string(FS);207  }208 209  return createARMMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, ArchFS);210}211 212static MCInstrInfo *createARMMCInstrInfo() {213  MCInstrInfo *X = new MCInstrInfo();214  InitARMMCInstrInfo(X);215  return X;216}217 218void ARM_MC::initLLVMToCVRegMapping(MCRegisterInfo *MRI) {219  // Mapping from CodeView to MC register id.220  static const struct {221    codeview::RegisterId CVReg;222    MCPhysReg Reg;223  } RegMap[] = {224      {codeview::RegisterId::ARM_R0, ARM::R0},225      {codeview::RegisterId::ARM_R1, ARM::R1},226      {codeview::RegisterId::ARM_R2, ARM::R2},227      {codeview::RegisterId::ARM_R3, ARM::R3},228      {codeview::RegisterId::ARM_R4, ARM::R4},229      {codeview::RegisterId::ARM_R5, ARM::R5},230      {codeview::RegisterId::ARM_R6, ARM::R6},231      {codeview::RegisterId::ARM_R7, ARM::R7},232      {codeview::RegisterId::ARM_R8, ARM::R8},233      {codeview::RegisterId::ARM_R9, ARM::R9},234      {codeview::RegisterId::ARM_R10, ARM::R10},235      {codeview::RegisterId::ARM_R11, ARM::R11},236      {codeview::RegisterId::ARM_R12, ARM::R12},237      {codeview::RegisterId::ARM_SP, ARM::SP},238      {codeview::RegisterId::ARM_LR, ARM::LR},239      {codeview::RegisterId::ARM_PC, ARM::PC},240      {codeview::RegisterId::ARM_CPSR, ARM::CPSR},241      {codeview::RegisterId::ARM_FPSCR, ARM::FPSCR},242      {codeview::RegisterId::ARM_FPEXC, ARM::FPEXC},243      {codeview::RegisterId::ARM_FS0, ARM::S0},244      {codeview::RegisterId::ARM_FS1, ARM::S1},245      {codeview::RegisterId::ARM_FS2, ARM::S2},246      {codeview::RegisterId::ARM_FS3, ARM::S3},247      {codeview::RegisterId::ARM_FS4, ARM::S4},248      {codeview::RegisterId::ARM_FS5, ARM::S5},249      {codeview::RegisterId::ARM_FS6, ARM::S6},250      {codeview::RegisterId::ARM_FS7, ARM::S7},251      {codeview::RegisterId::ARM_FS8, ARM::S8},252      {codeview::RegisterId::ARM_FS9, ARM::S9},253      {codeview::RegisterId::ARM_FS10, ARM::S10},254      {codeview::RegisterId::ARM_FS11, ARM::S11},255      {codeview::RegisterId::ARM_FS12, ARM::S12},256      {codeview::RegisterId::ARM_FS13, ARM::S13},257      {codeview::RegisterId::ARM_FS14, ARM::S14},258      {codeview::RegisterId::ARM_FS15, ARM::S15},259      {codeview::RegisterId::ARM_FS16, ARM::S16},260      {codeview::RegisterId::ARM_FS17, ARM::S17},261      {codeview::RegisterId::ARM_FS18, ARM::S18},262      {codeview::RegisterId::ARM_FS19, ARM::S19},263      {codeview::RegisterId::ARM_FS20, ARM::S20},264      {codeview::RegisterId::ARM_FS21, ARM::S21},265      {codeview::RegisterId::ARM_FS22, ARM::S22},266      {codeview::RegisterId::ARM_FS23, ARM::S23},267      {codeview::RegisterId::ARM_FS24, ARM::S24},268      {codeview::RegisterId::ARM_FS25, ARM::S25},269      {codeview::RegisterId::ARM_FS26, ARM::S26},270      {codeview::RegisterId::ARM_FS27, ARM::S27},271      {codeview::RegisterId::ARM_FS28, ARM::S28},272      {codeview::RegisterId::ARM_FS29, ARM::S29},273      {codeview::RegisterId::ARM_FS30, ARM::S30},274      {codeview::RegisterId::ARM_FS31, ARM::S31},275      {codeview::RegisterId::ARM_ND0, ARM::D0},276      {codeview::RegisterId::ARM_ND1, ARM::D1},277      {codeview::RegisterId::ARM_ND2, ARM::D2},278      {codeview::RegisterId::ARM_ND3, ARM::D3},279      {codeview::RegisterId::ARM_ND4, ARM::D4},280      {codeview::RegisterId::ARM_ND5, ARM::D5},281      {codeview::RegisterId::ARM_ND6, ARM::D6},282      {codeview::RegisterId::ARM_ND7, ARM::D7},283      {codeview::RegisterId::ARM_ND8, ARM::D8},284      {codeview::RegisterId::ARM_ND9, ARM::D9},285      {codeview::RegisterId::ARM_ND10, ARM::D10},286      {codeview::RegisterId::ARM_ND11, ARM::D11},287      {codeview::RegisterId::ARM_ND12, ARM::D12},288      {codeview::RegisterId::ARM_ND13, ARM::D13},289      {codeview::RegisterId::ARM_ND14, ARM::D14},290      {codeview::RegisterId::ARM_ND15, ARM::D15},291      {codeview::RegisterId::ARM_ND16, ARM::D16},292      {codeview::RegisterId::ARM_ND17, ARM::D17},293      {codeview::RegisterId::ARM_ND18, ARM::D18},294      {codeview::RegisterId::ARM_ND19, ARM::D19},295      {codeview::RegisterId::ARM_ND20, ARM::D20},296      {codeview::RegisterId::ARM_ND21, ARM::D21},297      {codeview::RegisterId::ARM_ND22, ARM::D22},298      {codeview::RegisterId::ARM_ND23, ARM::D23},299      {codeview::RegisterId::ARM_ND24, ARM::D24},300      {codeview::RegisterId::ARM_ND25, ARM::D25},301      {codeview::RegisterId::ARM_ND26, ARM::D26},302      {codeview::RegisterId::ARM_ND27, ARM::D27},303      {codeview::RegisterId::ARM_ND28, ARM::D28},304      {codeview::RegisterId::ARM_ND29, ARM::D29},305      {codeview::RegisterId::ARM_ND30, ARM::D30},306      {codeview::RegisterId::ARM_ND31, ARM::D31},307      {codeview::RegisterId::ARM_NQ0, ARM::Q0},308      {codeview::RegisterId::ARM_NQ1, ARM::Q1},309      {codeview::RegisterId::ARM_NQ2, ARM::Q2},310      {codeview::RegisterId::ARM_NQ3, ARM::Q3},311      {codeview::RegisterId::ARM_NQ4, ARM::Q4},312      {codeview::RegisterId::ARM_NQ5, ARM::Q5},313      {codeview::RegisterId::ARM_NQ6, ARM::Q6},314      {codeview::RegisterId::ARM_NQ7, ARM::Q7},315      {codeview::RegisterId::ARM_NQ8, ARM::Q8},316      {codeview::RegisterId::ARM_NQ9, ARM::Q9},317      {codeview::RegisterId::ARM_NQ10, ARM::Q10},318      {codeview::RegisterId::ARM_NQ11, ARM::Q11},319      {codeview::RegisterId::ARM_NQ12, ARM::Q12},320      {codeview::RegisterId::ARM_NQ13, ARM::Q13},321      {codeview::RegisterId::ARM_NQ14, ARM::Q14},322      {codeview::RegisterId::ARM_NQ15, ARM::Q15},323  };324  for (const auto &I : RegMap)325    MRI->mapLLVMRegToCVReg(I.Reg, static_cast<int>(I.CVReg));326}327 328static MCRegisterInfo *createARMMCRegisterInfo(const Triple &Triple) {329  MCRegisterInfo *X = new MCRegisterInfo();330  InitARMMCRegisterInfo(X, ARM::LR, 0, 0, ARM::PC);331  ARM_MC::initLLVMToCVRegMapping(X);332  return X;333}334 335static MCAsmInfo *createARMMCAsmInfo(const MCRegisterInfo &MRI,336                                     const Triple &TheTriple,337                                     const MCTargetOptions &Options) {338  MCAsmInfo *MAI;339  if (TheTriple.isOSDarwin() || TheTriple.isOSBinFormatMachO())340    MAI = new ARMMCAsmInfoDarwin(TheTriple);341  else if (TheTriple.isWindowsMSVCEnvironment())342    MAI = new ARMCOFFMCAsmInfoMicrosoft();343  else if (TheTriple.isOSWindows())344    MAI = new ARMCOFFMCAsmInfoGNU();345  else346    MAI = new ARMELFMCAsmInfo(TheTriple);347 348  unsigned Reg = MRI.getDwarfRegNum(ARM::SP, true);349  MAI->addInitialFrameState(MCCFIInstruction::cfiDefCfa(nullptr, Reg, 0));350 351  return MAI;352}353 354static MCStreamer *createELFStreamer(const Triple &T, MCContext &Ctx,355                                     std::unique_ptr<MCAsmBackend> &&MAB,356                                     std::unique_ptr<MCObjectWriter> &&OW,357                                     std::unique_ptr<MCCodeEmitter> &&Emitter) {358  return createARMELFStreamer(359      Ctx, std::move(MAB), std::move(OW), std::move(Emitter),360      (T.getArch() == Triple::thumb || T.getArch() == Triple::thumbeb),361      T.isAndroid());362}363 364static MCStreamer *365createARMMachOStreamer(MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&MAB,366                       std::unique_ptr<MCObjectWriter> &&OW,367                       std::unique_ptr<MCCodeEmitter> &&Emitter) {368  return createMachOStreamer(Ctx, std::move(MAB), std::move(OW),369                             std::move(Emitter), false);370}371 372static MCInstPrinter *createARMMCInstPrinter(const Triple &T,373                                             unsigned SyntaxVariant,374                                             const MCAsmInfo &MAI,375                                             const MCInstrInfo &MII,376                                             const MCRegisterInfo &MRI) {377  if (SyntaxVariant == 0)378    return new ARMInstPrinter(MAI, MII, MRI);379  return nullptr;380}381 382static MCRelocationInfo *createARMMCRelocationInfo(const Triple &TT,383                                                   MCContext &Ctx) {384  if (TT.isOSBinFormatMachO())385    return createARMMachORelocationInfo(Ctx);386  // Default to the stock relocation info.387  return llvm::createMCRelocationInfo(TT, Ctx);388}389 390namespace {391 392class ARMMCInstrAnalysis : public MCInstrAnalysis {393public:394  ARMMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {}395 396  bool isUnconditionalBranch(const MCInst &Inst) const override {397    // BCCs with the "always" predicate are unconditional branches.398    if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)399      return true;400    return MCInstrAnalysis::isUnconditionalBranch(Inst);401  }402 403  bool isConditionalBranch(const MCInst &Inst) const override {404    // BCCs with the "always" predicate are unconditional branches.405    if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)406      return false;407    return MCInstrAnalysis::isConditionalBranch(Inst);408  }409 410  bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,411                      uint64_t &Target) const override {412    const MCInstrDesc &Desc = Info->get(Inst.getOpcode());413 414    // Find the PC-relative immediate operand in the instruction.415    for (unsigned OpNum = 0; OpNum < Desc.getNumOperands(); ++OpNum) {416      if (Inst.getOperand(OpNum).isImm() &&417          Desc.operands()[OpNum].OperandType == MCOI::OPERAND_PCREL) {418        int64_t Imm = Inst.getOperand(OpNum).getImm();419        Target = ARM_MC::evaluateBranchTarget(Desc, Addr, Imm);420        return true;421      }422    }423    return false;424  }425 426  std::optional<uint64_t>427  evaluateMemoryOperandAddress(const MCInst &Inst, const MCSubtargetInfo *STI,428                               uint64_t Addr, uint64_t Size) const override;429 430  std::vector<std::pair<uint64_t, uint64_t>>431  findPltEntries(uint64_t PltSectionVA, ArrayRef<uint8_t> PltContents,432                 const MCSubtargetInfo &STI) const override;433};434 435} // namespace436 437static std::optional<uint64_t>438// NOLINTNEXTLINE(readability-identifier-naming)439evaluateMemOpAddrForAddrMode_i12(const MCInst &Inst, const MCInstrDesc &Desc,440                                 unsigned MemOpIndex, uint64_t Addr) {441  if (MemOpIndex + 1 >= Desc.getNumOperands())442    return std::nullopt;443 444  const MCOperand &MO1 = Inst.getOperand(MemOpIndex);445  const MCOperand &MO2 = Inst.getOperand(MemOpIndex + 1);446  if (!MO1.isReg() || MO1.getReg() != ARM::PC || !MO2.isImm())447    return std::nullopt;448 449  int32_t OffImm = (int32_t)MO2.getImm();450  // Special value for #-0. All others are normal.451  if (OffImm == INT32_MIN)452    OffImm = 0;453  return Addr + OffImm;454}455 456static std::optional<uint64_t>457evaluateMemOpAddrForAddrMode3(const MCInst &Inst, const MCInstrDesc &Desc,458                              unsigned MemOpIndex, uint64_t Addr) {459  if (MemOpIndex + 2 >= Desc.getNumOperands())460    return std::nullopt;461 462  const MCOperand &MO1 = Inst.getOperand(MemOpIndex);463  const MCOperand &MO2 = Inst.getOperand(MemOpIndex + 1);464  const MCOperand &MO3 = Inst.getOperand(MemOpIndex + 2);465  if (!MO1.isReg() || MO1.getReg() != ARM::PC || MO2.getReg() || !MO3.isImm())466    return std::nullopt;467 468  unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm());469  ARM_AM::AddrOpc Op = ARM_AM::getAM3Op(MO3.getImm());470 471  if (Op == ARM_AM::sub)472    return Addr - ImmOffs;473  return Addr + ImmOffs;474}475 476static std::optional<uint64_t>477evaluateMemOpAddrForAddrMode5(const MCInst &Inst, const MCInstrDesc &Desc,478                              unsigned MemOpIndex, uint64_t Addr) {479  if (MemOpIndex + 1 >= Desc.getNumOperands())480    return std::nullopt;481 482  const MCOperand &MO1 = Inst.getOperand(MemOpIndex);483  const MCOperand &MO2 = Inst.getOperand(MemOpIndex + 1);484  if (!MO1.isReg() || MO1.getReg() != ARM::PC || !MO2.isImm())485    return std::nullopt;486 487  unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm());488  ARM_AM::AddrOpc Op = ARM_AM::getAM5Op(MO2.getImm());489 490  if (Op == ARM_AM::sub)491    return Addr - ImmOffs * 4;492  return Addr + ImmOffs * 4;493}494 495static std::optional<uint64_t>496evaluateMemOpAddrForAddrMode5FP16(const MCInst &Inst, const MCInstrDesc &Desc,497                                  unsigned MemOpIndex, uint64_t Addr) {498  if (MemOpIndex + 1 >= Desc.getNumOperands())499    return std::nullopt;500 501  const MCOperand &MO1 = Inst.getOperand(MemOpIndex);502  const MCOperand &MO2 = Inst.getOperand(MemOpIndex + 1);503  if (!MO1.isReg() || MO1.getReg() != ARM::PC || !MO2.isImm())504    return std::nullopt;505 506  unsigned ImmOffs = ARM_AM::getAM5FP16Offset(MO2.getImm());507  ARM_AM::AddrOpc Op = ARM_AM::getAM5FP16Op(MO2.getImm());508 509  if (Op == ARM_AM::sub)510    return Addr - ImmOffs * 2;511  return Addr + ImmOffs * 2;512}513 514static std::optional<uint64_t>515// NOLINTNEXTLINE(readability-identifier-naming)516evaluateMemOpAddrForAddrModeT2_i8s4(const MCInst &Inst, const MCInstrDesc &Desc,517                                    unsigned MemOpIndex, uint64_t Addr) {518  if (MemOpIndex + 1 >= Desc.getNumOperands())519    return std::nullopt;520 521  const MCOperand &MO1 = Inst.getOperand(MemOpIndex);522  const MCOperand &MO2 = Inst.getOperand(MemOpIndex + 1);523  if (!MO1.isReg() || MO1.getReg() != ARM::PC || !MO2.isImm())524    return std::nullopt;525 526  int32_t OffImm = (int32_t)MO2.getImm();527  assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");528 529  // Special value for #-0. All others are normal.530  if (OffImm == INT32_MIN)531    OffImm = 0;532  return Addr + OffImm;533}534 535static std::optional<uint64_t>536// NOLINTNEXTLINE(readability-identifier-naming)537evaluateMemOpAddrForAddrModeT2_pc(const MCInst &Inst, const MCInstrDesc &Desc,538                                  unsigned MemOpIndex, uint64_t Addr) {539  const MCOperand &MO1 = Inst.getOperand(MemOpIndex);540  if (!MO1.isImm())541    return std::nullopt;542 543  int32_t OffImm = (int32_t)MO1.getImm();544 545  // Special value for #-0. All others are normal.546  if (OffImm == INT32_MIN)547    OffImm = 0;548  return Addr + OffImm;549}550 551static std::optional<uint64_t>552// NOLINTNEXTLINE(readability-identifier-naming)553evaluateMemOpAddrForAddrModeT1_s(const MCInst &Inst, const MCInstrDesc &Desc,554                                 unsigned MemOpIndex, uint64_t Addr) {555  return evaluateMemOpAddrForAddrModeT2_pc(Inst, Desc, MemOpIndex, Addr);556}557 558std::optional<uint64_t> ARMMCInstrAnalysis::evaluateMemoryOperandAddress(559    const MCInst &Inst, const MCSubtargetInfo *STI, uint64_t Addr,560    uint64_t Size) const {561  const MCInstrDesc &Desc = Info->get(Inst.getOpcode());562 563  // Only load instructions can have PC-relative memory addressing.564  if (!Desc.mayLoad())565    return std::nullopt;566 567  // PC-relative addressing does not update the base register.568  uint64_t TSFlags = Desc.TSFlags;569  unsigned IndexMode =570      (TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;571  if (IndexMode != ARMII::IndexModeNone)572    return std::nullopt;573 574  // Find the memory addressing operand in the instruction.575  unsigned OpIndex = Desc.NumDefs;576  while (OpIndex < Desc.getNumOperands() &&577         Desc.operands()[OpIndex].OperandType != MCOI::OPERAND_MEMORY)578    ++OpIndex;579  if (OpIndex == Desc.getNumOperands())580    return std::nullopt;581 582  // Base address for PC-relative addressing is always 32-bit aligned.583  Addr &= ~0x3;584 585  // For ARM instructions the PC offset is 8 bytes, for Thumb instructions it586  // is 4 bytes.587  switch (Desc.TSFlags & ARMII::FormMask) {588  default:589    Addr += 8;590    break;591  case ARMII::ThumbFrm:592    Addr += 4;593    break;594  // VLDR* instructions share the same opcode (and thus the same form) for Arm595  // and Thumb. Use a bit longer route through STI in that case.596  case ARMII::VFPLdStFrm:597    Addr += STI->hasFeature(ARM::ModeThumb) ? 4 : 8;598    break;599  }600 601  // Eveluate the address depending on the addressing mode602  unsigned AddrMode = (TSFlags & ARMII::AddrModeMask);603  switch (AddrMode) {604  default:605    return std::nullopt;606  case ARMII::AddrMode_i12:607    return evaluateMemOpAddrForAddrMode_i12(Inst, Desc, OpIndex, Addr);608  case ARMII::AddrMode3:609    return evaluateMemOpAddrForAddrMode3(Inst, Desc, OpIndex, Addr);610  case ARMII::AddrMode5:611    return evaluateMemOpAddrForAddrMode5(Inst, Desc, OpIndex, Addr);612  case ARMII::AddrMode5FP16:613    return evaluateMemOpAddrForAddrMode5FP16(Inst, Desc, OpIndex, Addr);614  case ARMII::AddrModeT2_i8s4:615    return evaluateMemOpAddrForAddrModeT2_i8s4(Inst, Desc, OpIndex, Addr);616  case ARMII::AddrModeT2_pc:617    return evaluateMemOpAddrForAddrModeT2_pc(Inst, Desc, OpIndex, Addr);618  case ARMII::AddrModeT1_s:619    return evaluateMemOpAddrForAddrModeT1_s(Inst, Desc, OpIndex, Addr);620  }621}622 623template <typename T, size_t N>624static bool instructionsMatch(const T (&Insns)[N], const uint8_t *Buf,625                              llvm::endianness E) {626  for (size_t I = 0; I < N; ++I) {627    T Val = support::endian::read<T>(Buf + I * sizeof(T), E);628    if (Val != Insns[I])629      return false;630  }631  return true;632}633 634std::vector<std::pair<uint64_t, uint64_t>>635ARMMCInstrAnalysis::findPltEntries(uint64_t PltSectionVA,636                                   ArrayRef<uint8_t> PltContents,637                                   const MCSubtargetInfo &STI) const {638  llvm::endianness DataEndianness = STI.getTargetTriple().isLittleEndian()639                                        ? endianness::little640                                        : endianness::big;641  llvm::endianness InstrEndianness =642      STI.checkFeatures("+big-endian-instructions") ? endianness::big643                                                    : endianness::little;644 645  // Do a lightweight parsing of PLT entries.646  std::vector<std::pair<uint64_t, uint64_t>> Result;647  if (STI.checkFeatures("+thumb-mode")) {648    for (uint64_t Byte = 0, End = PltContents.size(); Byte + 12 < End;649         Byte += 16) {650      // Expected instruction sequence:651      //652      // movw ip, #lower16653      // movt ip, #upper16654      // add ip, pc655      // ldr.w pc, [ip]656      // b . -4657 658      uint32_t MovwPart1 =659          support::endian::read16(PltContents.data() + Byte, InstrEndianness);660      if ((MovwPart1 & 0xffb0) != 0xf200)661        continue;662 663      uint32_t MovwPart2 = support::endian::read16(664          PltContents.data() + Byte + 2, InstrEndianness);665      if ((MovwPart2 & 0x8f00) != 0xc00)666        continue;667 668      uint64_t OffsetLower = (MovwPart2 & 0xff) + ((MovwPart2 & 0x7000) >> 4) +669                             ((MovwPart1 & 0x400) << 1) +670                             ((MovwPart1 & 0xf) << 12);671 672      uint32_t MovtPart1 = support::endian::read16(673          PltContents.data() + Byte + 4, InstrEndianness);674      if ((MovtPart1 & 0xfbf0) != 0xf2c0)675        continue;676 677      uint32_t MovtPart2 = support::endian::read16(678          PltContents.data() + Byte + 6, InstrEndianness);679      if ((MovtPart2 & 0x8f00) != 0xc00)680        continue;681 682      uint64_t OffsetHigher =683          ((MovtPart2 & 0xff) << 16) + ((MovtPart2 & 0x7000) << 12) +684          ((MovtPart1 & 0x400) << 17) + ((MovtPart1 & 0xf) << 28);685 686      const uint16_t Insns[] = {687          0x44fc,         // add ip, pc688          0xf8dc, 0xf000, // ldr.w pc, [ip]689          0xe7fc,         // b . -4690      };691 692      if (!instructionsMatch(Insns, PltContents.data() + Byte + 8,693                             InstrEndianness))694        continue;695 696      // add ip, pc at Byte + 8 + thumb-pc-bias = 12697      uint64_t Offset = (PltSectionVA + Byte + 12) + OffsetLower + OffsetHigher;698      Result.emplace_back(PltSectionVA + Byte, Offset);699    }700  } else {701    const uint32_t LongEntryInsns[] = {702        0xe59fc004, //     ldr ip, L2703        0xe08cc00f, // L1: add ip, ip, pc704        0xe59cf000, // ldr pc, [ip]705    };706 707    for (uint64_t Byte = 0, End = PltContents.size(); Byte + 12 < End;708         Byte += 4) {709      // Is it a long entry?710      if (instructionsMatch(LongEntryInsns, PltContents.data() + Byte,711                            InstrEndianness)) {712        // Expected instruction sequence:713        //714        //     ldr ip, L2715        // L1: add ip, ip, pc716        //     ldr pc, [ip]717        // L2: .word   Offset(&(.got.plt) - L1 - 8718 719        uint64_t Offset = (PltSectionVA + Byte + 12) +720                          support::endian::read32(721                              PltContents.data() + Byte + 12, DataEndianness);722        Result.emplace_back(PltSectionVA + Byte, Offset);723        Byte += 12;724      } else {725        // Expected instruction sequence:726        //727        // L1: add ip, pc,  #0x0NN00000  Offset(&(.got.plt) - L1 - 8728        //     add ip, ip,  #0x000NN000  Offset(&(.got.plt) - L1 - 8729        //     ldr pc, [ip, #0x00000NNN] Offset(&(.got.plt) - L1 - 8730 731        uint32_t Add1 =732            support::endian::read32(PltContents.data() + Byte, InstrEndianness);733        if ((Add1 & 0xe28fc600) != 0xe28fc600)734          continue;735        uint32_t Add2 = support::endian::read32(PltContents.data() + Byte + 4,736                                                InstrEndianness);737        if ((Add2 & 0xe28cca00) != 0xe28cca00)738          continue;739        uint32_t Ldr = support::endian::read32(PltContents.data() + Byte + 8,740                                               InstrEndianness);741        if ((Ldr & 0xe5bcf000) != 0xe5bcf000)742          continue;743 744        // add ip, pc, #offset at Byte + 0 + arm-pc-bias = 8745        uint64_t Offset = (PltSectionVA + Byte + 8) + ((Add1 & 0xff) << 20) +746                          ((Add2 & 0xff) << 12) + (Ldr & 0xfff);747        Result.emplace_back(PltSectionVA + Byte, Offset);748        Byte += 8;749      }750    }751  }752  return Result;753}754 755static MCInstrAnalysis *createARMMCInstrAnalysis(const MCInstrInfo *Info) {756  return new ARMMCInstrAnalysis(Info);757}758 759bool ARM::isCDECoproc(size_t Coproc, const MCSubtargetInfo &STI) {760  // Unfortunately we don't have ARMTargetInfo in the disassembler, so we have761  // to rely on feature bits.762  if (Coproc >= 8)763    return false;764  return STI.getFeatureBits()[ARM::FeatureCoprocCDE0 + Coproc];765}766 767// Force static initialization.768extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARMTargetMC() {769  for (Target *T : {&getTheARMLETarget(), &getTheARMBETarget(),770                    &getTheThumbLETarget(), &getTheThumbBETarget()}) {771    // Register the MC asm info.772    RegisterMCAsmInfoFn X(*T, createARMMCAsmInfo);773 774    // Register the MC instruction info.775    TargetRegistry::RegisterMCInstrInfo(*T, createARMMCInstrInfo);776 777    // Register the MC register info.778    TargetRegistry::RegisterMCRegInfo(*T, createARMMCRegisterInfo);779 780    // Register the MC subtarget info.781    TargetRegistry::RegisterMCSubtargetInfo(*T,782                                            ARM_MC::createARMMCSubtargetInfo);783 784    TargetRegistry::RegisterELFStreamer(*T, createELFStreamer);785    TargetRegistry::RegisterCOFFStreamer(*T, createARMWinCOFFStreamer);786    TargetRegistry::RegisterMachOStreamer(*T, createARMMachOStreamer);787 788    // Register the obj target streamer.789    TargetRegistry::RegisterObjectTargetStreamer(*T,790                                                 createARMObjectTargetStreamer);791 792    // Register the asm streamer.793    TargetRegistry::RegisterAsmTargetStreamer(*T, createARMTargetAsmStreamer);794 795    // Register the null TargetStreamer.796    TargetRegistry::RegisterNullTargetStreamer(*T, createARMNullTargetStreamer);797 798    // Register the MCInstPrinter.799    TargetRegistry::RegisterMCInstPrinter(*T, createARMMCInstPrinter);800 801    // Register the MC relocation info.802    TargetRegistry::RegisterMCRelocationInfo(*T, createARMMCRelocationInfo);803  }804 805  // Register the MC instruction analyzer.806  for (Target *T : {&getTheARMLETarget(), &getTheARMBETarget(),807                    &getTheThumbLETarget(), &getTheThumbBETarget()})808    TargetRegistry::RegisterMCInstrAnalysis(*T, createARMMCInstrAnalysis);809 810  for (Target *T : {&getTheARMLETarget(), &getTheThumbLETarget()}) {811    TargetRegistry::RegisterMCCodeEmitter(*T, createARMLEMCCodeEmitter);812    TargetRegistry::RegisterMCAsmBackend(*T, createARMLEAsmBackend);813  }814  for (Target *T : {&getTheARMBETarget(), &getTheThumbBETarget()}) {815    TargetRegistry::RegisterMCCodeEmitter(*T, createARMBEMCCodeEmitter);816    TargetRegistry::RegisterMCAsmBackend(*T, createARMBEAsmBackend);817  }818}819