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