1249259Sdim//===-- AArch64AsmBackend.cpp - AArch64 Assembler Backend -----------------===// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim// 10249259Sdim// This file contains the AArch64 implementation of the MCAsmBackend class, 11249259Sdim// which is principally concerned with relaxation of the various fixup kinds. 12249259Sdim// 13249259Sdim//===----------------------------------------------------------------------===// 14249259Sdim 15249259Sdim#include "MCTargetDesc/AArch64FixupKinds.h" 16249259Sdim#include "MCTargetDesc/AArch64MCTargetDesc.h" 17249259Sdim#include "llvm/MC/MCAsmBackend.h" 18249259Sdim#include "llvm/MC/MCSubtargetInfo.h" 19249259Sdim#include "llvm/MC/MCELFObjectWriter.h" 20249259Sdim#include "llvm/MC/MCFixupKindInfo.h" 21249259Sdim#include "llvm/MC/MCObjectWriter.h" 22249259Sdim#include "llvm/Support/ELF.h" 23249259Sdim#include "llvm/Support/ErrorHandling.h" 24249259Sdim#include "llvm/Support/raw_ostream.h" 25249259Sdimusing namespace llvm; 26249259Sdim 27249259Sdimnamespace { 28249259Sdimclass AArch64AsmBackend : public MCAsmBackend { 29249259Sdim const MCSubtargetInfo* STI; 30249259Sdimpublic: 31249259Sdim AArch64AsmBackend(const Target &T, const StringRef TT) 32249259Sdim : MCAsmBackend(), 33249259Sdim STI(AArch64_MC::createAArch64MCSubtargetInfo(TT, "", "")) 34249259Sdim {} 35249259Sdim 36249259Sdim 37249259Sdim ~AArch64AsmBackend() { 38249259Sdim delete STI; 39249259Sdim } 40249259Sdim 41249259Sdim bool writeNopData(uint64_t Count, MCObjectWriter *OW) const; 42249259Sdim 43249259Sdim virtual void processFixupValue(const MCAssembler &Asm, 44249259Sdim const MCAsmLayout &Layout, 45249259Sdim const MCFixup &Fixup, const MCFragment *DF, 46249259Sdim MCValue &Target, uint64_t &Value, 47249259Sdim bool &IsResolved); 48249259Sdim}; 49249259Sdim} // end anonymous namespace 50249259Sdim 51249259Sdimvoid AArch64AsmBackend::processFixupValue(const MCAssembler &Asm, 52249259Sdim const MCAsmLayout &Layout, 53249259Sdim const MCFixup &Fixup, 54249259Sdim const MCFragment *DF, 55249259Sdim MCValue &Target, uint64_t &Value, 56249259Sdim bool &IsResolved) { 57249259Sdim // The ADRP instruction adds some multiple of 0x1000 to the current PC & 58249259Sdim // ~0xfff. This means that the required offset to reach a symbol can vary by 59249259Sdim // up to one step depending on where the ADRP is in memory. For example: 60249259Sdim // 61249259Sdim // ADRP x0, there 62249259Sdim // there: 63249259Sdim // 64249259Sdim // If the ADRP occurs at address 0xffc then "there" will be at 0x1000 and 65249259Sdim // we'll need that as an offset. At any other address "there" will be in the 66249259Sdim // same page as the ADRP and the instruction should encode 0x0. Assuming the 67249259Sdim // section isn't 0x1000-aligned, we therefore need to delegate this decision 68249259Sdim // to the linker -- a relocation! 69249259Sdim if ((uint32_t)Fixup.getKind() == AArch64::fixup_a64_adr_prel_page || 70249259Sdim (uint32_t)Fixup.getKind() == AArch64::fixup_a64_adr_prel_got_page || 71249259Sdim (uint32_t)Fixup.getKind() == AArch64::fixup_a64_adr_gottprel_page || 72249259Sdim (uint32_t)Fixup.getKind() == AArch64::fixup_a64_tlsdesc_adr_page) 73249259Sdim IsResolved = false; 74249259Sdim} 75249259Sdim 76249259Sdim 77249259Sdimstatic uint64_t adjustFixupValue(unsigned Kind, uint64_t Value); 78249259Sdim 79249259Sdimnamespace { 80249259Sdim 81249259Sdimclass ELFAArch64AsmBackend : public AArch64AsmBackend { 82249259Sdimpublic: 83249259Sdim uint8_t OSABI; 84249259Sdim ELFAArch64AsmBackend(const Target &T, const StringRef TT, 85249259Sdim uint8_t _OSABI) 86249259Sdim : AArch64AsmBackend(T, TT), OSABI(_OSABI) { } 87249259Sdim 88249259Sdim bool fixupNeedsRelaxation(const MCFixup &Fixup, 89249259Sdim uint64_t Value, 90249259Sdim const MCRelaxableFragment *DF, 91249259Sdim const MCAsmLayout &Layout) const; 92249259Sdim 93249259Sdim unsigned int getNumFixupKinds() const { 94249259Sdim return AArch64::NumTargetFixupKinds; 95249259Sdim } 96249259Sdim 97249259Sdim const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { 98249259Sdim const static MCFixupKindInfo Infos[AArch64::NumTargetFixupKinds] = { 99249259Sdim// This table *must* be in the order that the fixup_* kinds are defined in 100249259Sdim// AArch64FixupKinds.h. 101249259Sdim// 102249259Sdim// Name Offset (bits) Size (bits) Flags 103249259Sdim{ "fixup_a64_ld_prel", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 104249259Sdim{ "fixup_a64_adr_prel", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 105249259Sdim{ "fixup_a64_adr_prel_page", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 106249259Sdim{ "fixup_a64_add_lo12", 0, 32, 0 }, 107249259Sdim{ "fixup_a64_ldst8_lo12", 0, 32, 0 }, 108249259Sdim{ "fixup_a64_ldst16_lo12", 0, 32, 0 }, 109249259Sdim{ "fixup_a64_ldst32_lo12", 0, 32, 0 }, 110249259Sdim{ "fixup_a64_ldst64_lo12", 0, 32, 0 }, 111249259Sdim{ "fixup_a64_ldst128_lo12", 0, 32, 0 }, 112249259Sdim{ "fixup_a64_tstbr", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 113249259Sdim{ "fixup_a64_condbr", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 114249259Sdim{ "fixup_a64_uncondbr", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 115249259Sdim{ "fixup_a64_call", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 116249259Sdim{ "fixup_a64_movw_uabs_g0", 0, 32, 0 }, 117249259Sdim{ "fixup_a64_movw_uabs_g0_nc", 0, 32, 0 }, 118249259Sdim{ "fixup_a64_movw_uabs_g1", 0, 32, 0 }, 119249259Sdim{ "fixup_a64_movw_uabs_g1_nc", 0, 32, 0 }, 120249259Sdim{ "fixup_a64_movw_uabs_g2", 0, 32, 0 }, 121249259Sdim{ "fixup_a64_movw_uabs_g2_nc", 0, 32, 0 }, 122249259Sdim{ "fixup_a64_movw_uabs_g3", 0, 32, 0 }, 123249259Sdim{ "fixup_a64_movw_sabs_g0", 0, 32, 0 }, 124249259Sdim{ "fixup_a64_movw_sabs_g1", 0, 32, 0 }, 125249259Sdim{ "fixup_a64_movw_sabs_g2", 0, 32, 0 }, 126249259Sdim{ "fixup_a64_adr_prel_got_page", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 127249259Sdim{ "fixup_a64_ld64_got_lo12_nc", 0, 32, 0 }, 128249259Sdim{ "fixup_a64_movw_dtprel_g2", 0, 32, 0 }, 129249259Sdim{ "fixup_a64_movw_dtprel_g1", 0, 32, 0 }, 130249259Sdim{ "fixup_a64_movw_dtprel_g1_nc", 0, 32, 0 }, 131249259Sdim{ "fixup_a64_movw_dtprel_g0", 0, 32, 0 }, 132249259Sdim{ "fixup_a64_movw_dtprel_g0_nc", 0, 32, 0 }, 133249259Sdim{ "fixup_a64_add_dtprel_hi12", 0, 32, 0 }, 134249259Sdim{ "fixup_a64_add_dtprel_lo12", 0, 32, 0 }, 135249259Sdim{ "fixup_a64_add_dtprel_lo12_nc", 0, 32, 0 }, 136249259Sdim{ "fixup_a64_ldst8_dtprel_lo12", 0, 32, 0 }, 137249259Sdim{ "fixup_a64_ldst8_dtprel_lo12_nc", 0, 32, 0 }, 138249259Sdim{ "fixup_a64_ldst16_dtprel_lo12", 0, 32, 0 }, 139249259Sdim{ "fixup_a64_ldst16_dtprel_lo12_nc", 0, 32, 0 }, 140249259Sdim{ "fixup_a64_ldst32_dtprel_lo12", 0, 32, 0 }, 141249259Sdim{ "fixup_a64_ldst32_dtprel_lo12_nc", 0, 32, 0 }, 142249259Sdim{ "fixup_a64_ldst64_dtprel_lo12", 0, 32, 0 }, 143249259Sdim{ "fixup_a64_ldst64_dtprel_lo12_nc", 0, 32, 0 }, 144249259Sdim{ "fixup_a64_movw_gottprel_g1", 0, 32, 0 }, 145249259Sdim{ "fixup_a64_movw_gottprel_g0_nc", 0, 32, 0 }, 146249259Sdim{ "fixup_a64_adr_gottprel_page", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 147249259Sdim{ "fixup_a64_ld64_gottprel_lo12_nc", 0, 32, 0 }, 148249259Sdim{ "fixup_a64_ld_gottprel_prel19", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 149249259Sdim{ "fixup_a64_movw_tprel_g2", 0, 32, 0 }, 150249259Sdim{ "fixup_a64_movw_tprel_g1", 0, 32, 0 }, 151249259Sdim{ "fixup_a64_movw_tprel_g1_nc", 0, 32, 0 }, 152249259Sdim{ "fixup_a64_movw_tprel_g0", 0, 32, 0 }, 153249259Sdim{ "fixup_a64_movw_tprel_g0_nc", 0, 32, 0 }, 154249259Sdim{ "fixup_a64_add_tprel_hi12", 0, 32, 0 }, 155249259Sdim{ "fixup_a64_add_tprel_lo12", 0, 32, 0 }, 156249259Sdim{ "fixup_a64_add_tprel_lo12_nc", 0, 32, 0 }, 157249259Sdim{ "fixup_a64_ldst8_tprel_lo12", 0, 32, 0 }, 158249259Sdim{ "fixup_a64_ldst8_tprel_lo12_nc", 0, 32, 0 }, 159249259Sdim{ "fixup_a64_ldst16_tprel_lo12", 0, 32, 0 }, 160249259Sdim{ "fixup_a64_ldst16_tprel_lo12_nc", 0, 32, 0 }, 161249259Sdim{ "fixup_a64_ldst32_tprel_lo12", 0, 32, 0 }, 162249259Sdim{ "fixup_a64_ldst32_tprel_lo12_nc", 0, 32, 0 }, 163249259Sdim{ "fixup_a64_ldst64_tprel_lo12", 0, 32, 0 }, 164249259Sdim{ "fixup_a64_ldst64_tprel_lo12_nc", 0, 32, 0 }, 165249259Sdim{ "fixup_a64_tlsdesc_adr_page", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 166249259Sdim{ "fixup_a64_tlsdesc_ld64_lo12_nc", 0, 32, 0 }, 167249259Sdim{ "fixup_a64_tlsdesc_add_lo12_nc", 0, 32, 0 }, 168249259Sdim{ "fixup_a64_tlsdesc_call", 0, 0, 0 } 169249259Sdim }; 170249259Sdim if (Kind < FirstTargetFixupKind) 171249259Sdim return MCAsmBackend::getFixupKindInfo(Kind); 172249259Sdim 173249259Sdim assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && 174249259Sdim "Invalid kind!"); 175249259Sdim return Infos[Kind - FirstTargetFixupKind]; 176249259Sdim } 177249259Sdim 178249259Sdim void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, 179249259Sdim uint64_t Value) const { 180249259Sdim unsigned NumBytes = getFixupKindInfo(Fixup.getKind()).TargetSize / 8; 181249259Sdim Value = adjustFixupValue(Fixup.getKind(), Value); 182249259Sdim if (!Value) return; // Doesn't change encoding. 183249259Sdim 184249259Sdim unsigned Offset = Fixup.getOffset(); 185249259Sdim assert(Offset + NumBytes <= DataSize && "Invalid fixup offset!"); 186249259Sdim 187249259Sdim // For each byte of the fragment that the fixup touches, mask in the bits 188249259Sdim // from the fixup value. 189249259Sdim for (unsigned i = 0; i != NumBytes; ++i) { 190249259Sdim Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); 191249259Sdim } 192249259Sdim } 193249259Sdim 194249259Sdim bool mayNeedRelaxation(const MCInst&) const { 195249259Sdim return false; 196249259Sdim } 197249259Sdim 198249259Sdim void relaxInstruction(const MCInst&, llvm::MCInst&) const { 199249259Sdim llvm_unreachable("Cannot relax instructions"); 200249259Sdim } 201249259Sdim 202249259Sdim MCObjectWriter *createObjectWriter(raw_ostream &OS) const { 203249259Sdim return createAArch64ELFObjectWriter(OS, OSABI); 204249259Sdim } 205249259Sdim}; 206249259Sdim 207249259Sdim} // end anonymous namespace 208249259Sdim 209249259Sdimbool 210249259SdimELFAArch64AsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, 211249259Sdim uint64_t Value, 212249259Sdim const MCRelaxableFragment *DF, 213249259Sdim const MCAsmLayout &Layout) const { 214249259Sdim // Correct for now. With all instructions 32-bit only very low-level 215249259Sdim // considerations could make you select something which may fail. 216249259Sdim return false; 217249259Sdim} 218249259Sdim 219249259Sdim 220249259Sdimbool AArch64AsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { 221249259Sdim // Can't emit NOP with size not multiple of 32-bits 222249259Sdim if (Count % 4 != 0) 223249259Sdim return false; 224249259Sdim 225249259Sdim uint64_t NumNops = Count / 4; 226249259Sdim for (uint64_t i = 0; i != NumNops; ++i) 227249259Sdim OW->Write32(0xd503201f); 228249259Sdim 229249259Sdim return true; 230249259Sdim} 231249259Sdim 232249259Sdimstatic unsigned ADRImmBits(unsigned Value) { 233249259Sdim unsigned lo2 = Value & 0x3; 234249259Sdim unsigned hi19 = (Value & 0x1fffff) >> 2; 235249259Sdim 236249259Sdim return (hi19 << 5) | (lo2 << 29); 237249259Sdim} 238249259Sdim 239249259Sdimstatic uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) { 240249259Sdim switch (Kind) { 241249259Sdim default: 242249259Sdim llvm_unreachable("Unknown fixup kind!"); 243249259Sdim case FK_Data_2: 244249259Sdim assert((int64_t)Value >= -32768 && 245249259Sdim (int64_t)Value <= 65536 && 246249259Sdim "Out of range ABS16 fixup"); 247249259Sdim return Value; 248249259Sdim case FK_Data_4: 249249259Sdim assert((int64_t)Value >= -(1LL << 31) && 250249259Sdim (int64_t)Value <= (1LL << 32) - 1 && 251249259Sdim "Out of range ABS32 fixup"); 252249259Sdim return Value; 253249259Sdim case FK_Data_8: 254249259Sdim return Value; 255249259Sdim 256249259Sdim case AArch64::fixup_a64_ld_gottprel_prel19: 257249259Sdim // R_AARCH64_LD_GOTTPREL_PREL19: Set a load-literal immediate to bits 1F 258249259Sdim // FFFC of G(TPREL(S+A)) - P; check -2^20 <= X < 2^20. 259249259Sdim case AArch64::fixup_a64_ld_prel: 260249259Sdim // R_AARCH64_LD_PREL_LO19: Sets a load-literal (immediate) value to bits 261249259Sdim // 1F FFFC of S+A-P, checking that -2^20 <= S+A-P < 2^20. 262249259Sdim assert((int64_t)Value >= -(1LL << 20) && 263249259Sdim (int64_t)Value < (1LL << 20) && "Out of range LDR (lit) fixup"); 264249259Sdim return (Value & 0x1ffffc) << 3; 265249259Sdim 266249259Sdim case AArch64::fixup_a64_adr_prel: 267249259Sdim // R_AARCH64_ADR_PREL_LO21: Sets an ADR immediate value to bits 1F FFFF of 268249259Sdim // the result of S+A-P, checking that -2^20 <= S+A-P < 2^20. 269249259Sdim assert((int64_t)Value >= -(1LL << 20) && 270249259Sdim (int64_t)Value < (1LL << 20) && "Out of range ADR fixup"); 271249259Sdim return ADRImmBits(Value & 0x1fffff); 272249259Sdim 273249259Sdim case AArch64::fixup_a64_adr_prel_page: 274249259Sdim // R_AARCH64_ADR_PREL_PG_HI21: Sets an ADRP immediate value to bits 1 FFFF 275249259Sdim // F000 of the result of the operation, checking that -2^32 <= result < 276249259Sdim // 2^32. 277249259Sdim assert((int64_t)Value >= -(1LL << 32) && 278249259Sdim (int64_t)Value < (1LL << 32) && "Out of range ADRP fixup"); 279249259Sdim return ADRImmBits((Value & 0x1fffff000ULL) >> 12); 280249259Sdim 281249259Sdim case AArch64::fixup_a64_add_dtprel_hi12: 282249259Sdim // R_AARCH64_TLSLD_ADD_DTPREL_LO12: Set an ADD immediate field to bits 283249259Sdim // FF F000 of DTPREL(S+A), check 0 <= X < 2^24. 284249259Sdim case AArch64::fixup_a64_add_tprel_hi12: 285249259Sdim // R_AARCH64_TLSLD_ADD_TPREL_LO12: Set an ADD immediate field to bits 286249259Sdim // FF F000 of TPREL(S+A), check 0 <= X < 2^24. 287249259Sdim assert((int64_t)Value >= 0 && 288249259Sdim (int64_t)Value < (1LL << 24) && "Out of range ADD fixup"); 289249259Sdim return (Value & 0xfff000) >> 2; 290249259Sdim 291249259Sdim case AArch64::fixup_a64_add_dtprel_lo12: 292249259Sdim // R_AARCH64_TLSLD_ADD_DTPREL_LO12: Set an ADD immediate field to bits 293249259Sdim // FFF of DTPREL(S+A), check 0 <= X < 2^12. 294249259Sdim case AArch64::fixup_a64_add_tprel_lo12: 295249259Sdim // R_AARCH64_TLSLD_ADD_TPREL_LO12: Set an ADD immediate field to bits 296249259Sdim // FFF of TPREL(S+A), check 0 <= X < 2^12. 297249259Sdim assert((int64_t)Value >= 0 && 298249259Sdim (int64_t)Value < (1LL << 12) && "Out of range ADD fixup"); 299249259Sdim // ... fallthrough to no-checking versions ... 300249259Sdim case AArch64::fixup_a64_add_dtprel_lo12_nc: 301249259Sdim // R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC: Set an ADD immediate field to bits 302249259Sdim // FFF of DTPREL(S+A) with no overflow check. 303249259Sdim case AArch64::fixup_a64_add_tprel_lo12_nc: 304249259Sdim // R_AARCH64_TLSLD_ADD_TPREL_LO12_NC: Set an ADD immediate field to bits 305249259Sdim // FFF of TPREL(S+A) with no overflow check. 306249259Sdim case AArch64::fixup_a64_tlsdesc_add_lo12_nc: 307249259Sdim // R_AARCH64_TLSDESC_ADD_LO12_NC: Set an ADD immediate field to bits 308249259Sdim // FFF of G(TLSDESC(S+A)), with no overflow check. 309249259Sdim case AArch64::fixup_a64_add_lo12: 310249259Sdim // R_AARCH64_ADD_ABS_LO12_NC: Sets an ADD immediate value to bits FFF of 311249259Sdim // S+A, with no overflow check. 312249259Sdim return (Value & 0xfff) << 10; 313249259Sdim 314249259Sdim case AArch64::fixup_a64_ldst8_dtprel_lo12: 315249259Sdim // R_AARCH64_TLSLD_LDST8_DTPREL_LO12: Set an LD/ST offset field to bits FFF 316249259Sdim // of DTPREL(S+A), check 0 <= X < 2^12. 317249259Sdim case AArch64::fixup_a64_ldst8_tprel_lo12: 318249259Sdim // R_AARCH64_TLSLE_LDST8_TPREL_LO12: Set an LD/ST offset field to bits FFF 319249259Sdim // of DTPREL(S+A), check 0 <= X < 2^12. 320249259Sdim assert((int64_t) Value >= 0 && 321249259Sdim (int64_t) Value < (1LL << 12) && "Out of range LD/ST fixup"); 322249259Sdim // ... fallthrough to no-checking versions ... 323249259Sdim case AArch64::fixup_a64_ldst8_dtprel_lo12_nc: 324249259Sdim // R_AARCH64_TLSLD_LDST8_DTPREL_LO12: Set an LD/ST offset field to bits FFF 325249259Sdim // of DTPREL(S+A), with no overflow check. 326249259Sdim case AArch64::fixup_a64_ldst8_tprel_lo12_nc: 327249259Sdim // R_AARCH64_TLSLD_LDST8_TPREL_LO12: Set an LD/ST offset field to bits FFF 328249259Sdim // of TPREL(S+A), with no overflow check. 329249259Sdim case AArch64::fixup_a64_ldst8_lo12: 330249259Sdim // R_AARCH64_LDST8_ABS_LO12_NC: Sets an LD/ST immediate value to bits FFF 331249259Sdim // of S+A, with no overflow check. 332249259Sdim return (Value & 0xfff) << 10; 333249259Sdim 334249259Sdim case AArch64::fixup_a64_ldst16_dtprel_lo12: 335249259Sdim // R_AARCH64_TLSLD_LDST16_DTPREL_LO12: Set an LD/ST offset field to bits FFE 336249259Sdim // of DTPREL(S+A), check 0 <= X < 2^12. 337249259Sdim case AArch64::fixup_a64_ldst16_tprel_lo12: 338249259Sdim // R_AARCH64_TLSLE_LDST16_TPREL_LO12: Set an LD/ST offset field to bits FFE 339249259Sdim // of DTPREL(S+A), check 0 <= X < 2^12. 340249259Sdim assert((int64_t) Value >= 0 && 341249259Sdim (int64_t) Value < (1LL << 12) && "Out of range LD/ST fixup"); 342249259Sdim // ... fallthrough to no-checking versions ... 343249259Sdim case AArch64::fixup_a64_ldst16_dtprel_lo12_nc: 344249259Sdim // R_AARCH64_TLSLD_LDST16_DTPREL_LO12: Set an LD/ST offset field to bits FFE 345249259Sdim // of DTPREL(S+A), with no overflow check. 346249259Sdim case AArch64::fixup_a64_ldst16_tprel_lo12_nc: 347249259Sdim // R_AARCH64_TLSLD_LDST16_TPREL_LO12: Set an LD/ST offset field to bits FFE 348249259Sdim // of TPREL(S+A), with no overflow check. 349249259Sdim case AArch64::fixup_a64_ldst16_lo12: 350249259Sdim // R_AARCH64_LDST16_ABS_LO12_NC: Sets an LD/ST immediate value to bits FFE 351249259Sdim // of S+A, with no overflow check. 352249259Sdim return (Value & 0xffe) << 9; 353249259Sdim 354249259Sdim case AArch64::fixup_a64_ldst32_dtprel_lo12: 355249259Sdim // R_AARCH64_TLSLD_LDST32_DTPREL_LO12: Set an LD/ST offset field to bits FFC 356249259Sdim // of DTPREL(S+A), check 0 <= X < 2^12. 357249259Sdim case AArch64::fixup_a64_ldst32_tprel_lo12: 358249259Sdim // R_AARCH64_TLSLE_LDST32_TPREL_LO12: Set an LD/ST offset field to bits FFC 359249259Sdim // of DTPREL(S+A), check 0 <= X < 2^12. 360249259Sdim assert((int64_t) Value >= 0 && 361249259Sdim (int64_t) Value < (1LL << 12) && "Out of range LD/ST fixup"); 362249259Sdim // ... fallthrough to no-checking versions ... 363249259Sdim case AArch64::fixup_a64_ldst32_dtprel_lo12_nc: 364249259Sdim // R_AARCH64_TLSLD_LDST32_DTPREL_LO12: Set an LD/ST offset field to bits FFC 365249259Sdim // of DTPREL(S+A), with no overflow check. 366249259Sdim case AArch64::fixup_a64_ldst32_tprel_lo12_nc: 367249259Sdim // R_AARCH64_TLSLD_LDST32_TPREL_LO12: Set an LD/ST offset field to bits FFC 368249259Sdim // of TPREL(S+A), with no overflow check. 369249259Sdim case AArch64::fixup_a64_ldst32_lo12: 370249259Sdim // R_AARCH64_LDST32_ABS_LO12_NC: Sets an LD/ST immediate value to bits FFC 371249259Sdim // of S+A, with no overflow check. 372249259Sdim return (Value & 0xffc) << 8; 373249259Sdim 374249259Sdim case AArch64::fixup_a64_ldst64_dtprel_lo12: 375249259Sdim // R_AARCH64_TLSLD_LDST64_DTPREL_LO12: Set an LD/ST offset field to bits FF8 376249259Sdim // of DTPREL(S+A), check 0 <= X < 2^12. 377249259Sdim case AArch64::fixup_a64_ldst64_tprel_lo12: 378249259Sdim // R_AARCH64_TLSLE_LDST64_TPREL_LO12: Set an LD/ST offset field to bits FF8 379249259Sdim // of DTPREL(S+A), check 0 <= X < 2^12. 380249259Sdim assert((int64_t) Value >= 0 && 381249259Sdim (int64_t) Value < (1LL << 12) && "Out of range LD/ST fixup"); 382249259Sdim // ... fallthrough to no-checking versions ... 383249259Sdim case AArch64::fixup_a64_ldst64_dtprel_lo12_nc: 384249259Sdim // R_AARCH64_TLSLD_LDST64_DTPREL_LO12: Set an LD/ST offset field to bits FF8 385249259Sdim // of DTPREL(S+A), with no overflow check. 386249259Sdim case AArch64::fixup_a64_ldst64_tprel_lo12_nc: 387249259Sdim // R_AARCH64_TLSLD_LDST64_TPREL_LO12: Set an LD/ST offset field to bits FF8 388249259Sdim // of TPREL(S+A), with no overflow check. 389249259Sdim case AArch64::fixup_a64_ldst64_lo12: 390249259Sdim // R_AARCH64_LDST64_ABS_LO12_NC: Sets an LD/ST immediate value to bits FF8 391249259Sdim // of S+A, with no overflow check. 392249259Sdim return (Value & 0xff8) << 7; 393249259Sdim 394249259Sdim case AArch64::fixup_a64_ldst128_lo12: 395249259Sdim // R_AARCH64_LDST128_ABS_LO12_NC: Sets an LD/ST immediate value to bits FF0 396249259Sdim // of S+A, with no overflow check. 397249259Sdim return (Value & 0xff0) << 6; 398249259Sdim 399249259Sdim case AArch64::fixup_a64_movw_uabs_g0: 400249259Sdim // R_AARCH64_MOVW_UABS_G0: Sets a MOVZ immediate field to bits FFFF of S+A 401249259Sdim // with a check that S+A < 2^16 402249259Sdim assert(Value <= 0xffff && "Out of range move wide fixup"); 403249259Sdim return (Value & 0xffff) << 5; 404249259Sdim 405249259Sdim case AArch64::fixup_a64_movw_dtprel_g0_nc: 406249259Sdim // R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC: Sets a MOVK immediate field to bits 407249259Sdim // FFFF of DTPREL(S+A) with no overflow check. 408249259Sdim case AArch64::fixup_a64_movw_gottprel_g0_nc: 409249259Sdim // R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC: Sets a MOVK immediate field to bits 410249259Sdim // FFFF of G(TPREL(S+A)) - GOT with no overflow check. 411249259Sdim case AArch64::fixup_a64_movw_tprel_g0_nc: 412249259Sdim // R_AARCH64_TLSLE_MOVW_TPREL_G0_NC: Sets a MOVK immediate field to bits 413249259Sdim // FFFF of TPREL(S+A) with no overflow check. 414249259Sdim case AArch64::fixup_a64_movw_uabs_g0_nc: 415249259Sdim // R_AARCH64_MOVW_UABS_G0_NC: Sets a MOVK immediate field to bits FFFF of 416249259Sdim // S+A with no overflow check. 417249259Sdim return (Value & 0xffff) << 5; 418249259Sdim 419249259Sdim case AArch64::fixup_a64_movw_uabs_g1: 420249259Sdim // R_AARCH64_MOVW_UABS_G1: Sets a MOVZ immediate field to bits FFFF0000 of 421249259Sdim // S+A with a check that S+A < 2^32 422249259Sdim assert(Value <= 0xffffffffull && "Out of range move wide fixup"); 423249259Sdim return ((Value >> 16) & 0xffff) << 5; 424249259Sdim 425249259Sdim case AArch64::fixup_a64_movw_dtprel_g1_nc: 426249259Sdim // R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC: Set a MOVK immediate field 427249259Sdim // to bits FFFF0000 of DTPREL(S+A), with no overflow check. 428249259Sdim case AArch64::fixup_a64_movw_tprel_g1_nc: 429249259Sdim // R_AARCH64_TLSLD_MOVW_TPREL_G1_NC: Set a MOVK immediate field 430249259Sdim // to bits FFFF0000 of TPREL(S+A), with no overflow check. 431249259Sdim case AArch64::fixup_a64_movw_uabs_g1_nc: 432249259Sdim // R_AARCH64_MOVW_UABS_G1_NC: Sets a MOVK immediate field to bits 433249259Sdim // FFFF0000 of S+A with no overflow check. 434249259Sdim return ((Value >> 16) & 0xffff) << 5; 435249259Sdim 436249259Sdim case AArch64::fixup_a64_movw_uabs_g2: 437249259Sdim // R_AARCH64_MOVW_UABS_G2: Sets a MOVZ immediate field to bits FFFF 0000 438249259Sdim // 0000 of S+A with a check that S+A < 2^48 439249259Sdim assert(Value <= 0xffffffffffffull && "Out of range move wide fixup"); 440249259Sdim return ((Value >> 32) & 0xffff) << 5; 441249259Sdim 442249259Sdim case AArch64::fixup_a64_movw_uabs_g2_nc: 443249259Sdim // R_AARCH64_MOVW_UABS_G2: Sets a MOVK immediate field to bits FFFF 0000 444249259Sdim // 0000 of S+A with no overflow check. 445249259Sdim return ((Value >> 32) & 0xffff) << 5; 446249259Sdim 447249259Sdim case AArch64::fixup_a64_movw_uabs_g3: 448249259Sdim // R_AARCH64_MOVW_UABS_G3: Sets a MOVZ immediate field to bits FFFF 0000 449249259Sdim // 0000 0000 of S+A (no overflow check needed) 450249259Sdim return ((Value >> 48) & 0xffff) << 5; 451249259Sdim 452249259Sdim case AArch64::fixup_a64_movw_dtprel_g0: 453249259Sdim // R_AARCH64_TLSLD_MOVW_DTPREL_G0: Set a MOV[NZ] immediate field 454249259Sdim // to bits FFFF of DTPREL(S+A). 455249259Sdim case AArch64::fixup_a64_movw_tprel_g0: 456249259Sdim // R_AARCH64_TLSLE_MOVW_TPREL_G0: Set a MOV[NZ] immediate field to 457249259Sdim // bits FFFF of TPREL(S+A). 458249259Sdim case AArch64::fixup_a64_movw_sabs_g0: { 459249259Sdim // R_AARCH64_MOVW_SABS_G0: Sets MOV[NZ] immediate field using bits FFFF of 460249259Sdim // S+A (see notes below); check -2^16 <= S+A < 2^16. (notes say that we 461249259Sdim // should convert between MOVN and MOVZ to achieve our goals). 462249259Sdim int64_t Signed = Value; 463249259Sdim assert(Signed >= -(1LL << 16) && Signed < (1LL << 16) 464249259Sdim && "Out of range move wide fixup"); 465249259Sdim if (Signed >= 0) { 466249259Sdim Value = (Value & 0xffff) << 5; 467249259Sdim // Bit 30 converts the MOVN encoding into a MOVZ 468249259Sdim Value |= 1 << 30; 469249259Sdim } else { 470249259Sdim // MCCodeEmitter should have encoded a MOVN, which is fine. 471249259Sdim Value = (~Value & 0xffff) << 5; 472249259Sdim } 473249259Sdim return Value; 474249259Sdim } 475249259Sdim 476249259Sdim case AArch64::fixup_a64_movw_dtprel_g1: 477249259Sdim // R_AARCH64_TLSLD_MOVW_DTPREL_G1: Set a MOV[NZ] immediate field 478249259Sdim // to bits FFFF0000 of DTPREL(S+A). 479249259Sdim case AArch64::fixup_a64_movw_gottprel_g1: 480249259Sdim // R_AARCH64_TLSIE_MOVW_GOTTPREL_G1: Set a MOV[NZ] immediate field 481249259Sdim // to bits FFFF0000 of G(TPREL(S+A)) - GOT. 482249259Sdim case AArch64::fixup_a64_movw_tprel_g1: 483249259Sdim // R_AARCH64_TLSLE_MOVW_TPREL_G1: Set a MOV[NZ] immediate field to 484249259Sdim // bits FFFF0000 of TPREL(S+A). 485249259Sdim case AArch64::fixup_a64_movw_sabs_g1: { 486249259Sdim // R_AARCH64_MOVW_SABS_G1: Sets MOV[NZ] immediate field using bits FFFF 0000 487249259Sdim // of S+A (see notes below); check -2^32 <= S+A < 2^32. (notes say that we 488249259Sdim // should convert between MOVN and MOVZ to achieve our goals). 489249259Sdim int64_t Signed = Value; 490249259Sdim assert(Signed >= -(1LL << 32) && Signed < (1LL << 32) 491249259Sdim && "Out of range move wide fixup"); 492249259Sdim if (Signed >= 0) { 493249259Sdim Value = ((Value >> 16) & 0xffff) << 5; 494249259Sdim // Bit 30 converts the MOVN encoding into a MOVZ 495249259Sdim Value |= 1 << 30; 496249259Sdim } else { 497249259Sdim Value = ((~Value >> 16) & 0xffff) << 5; 498249259Sdim } 499249259Sdim return Value; 500249259Sdim } 501249259Sdim 502249259Sdim case AArch64::fixup_a64_movw_dtprel_g2: 503249259Sdim // R_AARCH64_TLSLD_MOVW_DTPREL_G2: Set a MOV[NZ] immediate field 504249259Sdim // to bits FFFF 0000 0000 of DTPREL(S+A). 505249259Sdim case AArch64::fixup_a64_movw_tprel_g2: 506249259Sdim // R_AARCH64_TLSLE_MOVW_TPREL_G2: Set a MOV[NZ] immediate field to 507249259Sdim // bits FFFF 0000 0000 of TPREL(S+A). 508249259Sdim case AArch64::fixup_a64_movw_sabs_g2: { 509249259Sdim // R_AARCH64_MOVW_SABS_G2: Sets MOV[NZ] immediate field using bits FFFF 0000 510249259Sdim // 0000 of S+A (see notes below); check -2^48 <= S+A < 2^48. (notes say that 511249259Sdim // we should convert between MOVN and MOVZ to achieve our goals). 512249259Sdim int64_t Signed = Value; 513249259Sdim assert(Signed >= -(1LL << 48) && Signed < (1LL << 48) 514249259Sdim && "Out of range move wide fixup"); 515249259Sdim if (Signed >= 0) { 516249259Sdim Value = ((Value >> 32) & 0xffff) << 5; 517249259Sdim // Bit 30 converts the MOVN encoding into a MOVZ 518249259Sdim Value |= 1 << 30; 519249259Sdim } else { 520249259Sdim Value = ((~Value >> 32) & 0xffff) << 5; 521249259Sdim } 522249259Sdim return Value; 523249259Sdim } 524249259Sdim 525249259Sdim case AArch64::fixup_a64_tstbr: 526249259Sdim // R_AARCH64_TSTBR14: Sets the immediate field of a TBZ/TBNZ instruction to 527249259Sdim // bits FFFC of S+A-P, checking -2^15 <= S+A-P < 2^15. 528249259Sdim assert((int64_t)Value >= -(1LL << 15) && 529249259Sdim (int64_t)Value < (1LL << 15) && "Out of range TBZ/TBNZ fixup"); 530249259Sdim return (Value & 0xfffc) << (5 - 2); 531249259Sdim 532249259Sdim case AArch64::fixup_a64_condbr: 533249259Sdim // R_AARCH64_CONDBR19: Sets the immediate field of a conditional branch 534249259Sdim // instruction to bits 1FFFFC of S+A-P, checking -2^20 <= S+A-P < 2^20. 535249259Sdim assert((int64_t)Value >= -(1LL << 20) && 536249259Sdim (int64_t)Value < (1LL << 20) && "Out of range B.cond fixup"); 537249259Sdim return (Value & 0x1ffffc) << (5 - 2); 538249259Sdim 539249259Sdim case AArch64::fixup_a64_uncondbr: 540249259Sdim // R_AARCH64_JUMP26 same as below (except to a linker, possibly). 541249259Sdim case AArch64::fixup_a64_call: 542249259Sdim // R_AARCH64_CALL26: Sets a CALL immediate field to bits FFFFFFC of S+A-P, 543249259Sdim // checking that -2^27 <= S+A-P < 2^27. 544249259Sdim assert((int64_t)Value >= -(1LL << 27) && 545249259Sdim (int64_t)Value < (1LL << 27) && "Out of range branch fixup"); 546249259Sdim return (Value & 0xffffffc) >> 2; 547249259Sdim 548249259Sdim case AArch64::fixup_a64_adr_gottprel_page: 549249259Sdim // R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: Set an ADRP immediate field to bits 550249259Sdim // 1FFFFF000 of Page(G(TPREL(S+A))) - Page(P); check -2^32 <= X < 2^32. 551249259Sdim case AArch64::fixup_a64_tlsdesc_adr_page: 552249259Sdim // R_AARCH64_TLSDESC_ADR_PAGE: Set an ADRP immediate field to bits 1FFFFF000 553249259Sdim // of Page(G(TLSDESC(S+A))) - Page(P); check -2^32 <= X < 2^32. 554249259Sdim case AArch64::fixup_a64_adr_prel_got_page: 555249259Sdim // R_AARCH64_ADR_GOT_PAGE: Sets the immediate value of an ADRP to bits 556249259Sdim // 1FFFFF000 of the operation, checking that -2^32 < Page(G(S))-Page(GOT) < 557249259Sdim // 2^32. 558249259Sdim assert((int64_t)Value >= -(1LL << 32) && 559249259Sdim (int64_t)Value < (1LL << 32) && "Out of range ADRP fixup"); 560249259Sdim return ADRImmBits((Value & 0x1fffff000ULL) >> 12); 561249259Sdim 562249259Sdim case AArch64::fixup_a64_ld64_gottprel_lo12_nc: 563249259Sdim // R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: Set an LD offset field to bits FF8 564249259Sdim // of X, with no overflow check. Check that X & 7 == 0. 565249259Sdim case AArch64::fixup_a64_tlsdesc_ld64_lo12_nc: 566249259Sdim // R_AARCH64_TLSDESC_LD64_LO12_NC: Set an LD offset field to bits FF8 of 567249259Sdim // G(TLSDESC(S+A)), with no overflow check. Check that X & 7 == 0. 568249259Sdim case AArch64::fixup_a64_ld64_got_lo12_nc: 569249259Sdim // R_AARCH64_LD64_GOT_LO12_NC: Sets the LD/ST immediate field to bits FF8 of 570249259Sdim // G(S) with no overflow check. Check X & 7 == 0 571249259Sdim assert(((int64_t)Value & 7) == 0 && "Misaligned fixup"); 572249259Sdim return (Value & 0xff8) << 7; 573249259Sdim 574249259Sdim case AArch64::fixup_a64_tlsdesc_call: 575249259Sdim // R_AARCH64_TLSDESC_CALL: For relaxation only. 576249259Sdim return 0; 577249259Sdim } 578249259Sdim} 579249259Sdim 580249259SdimMCAsmBackend * 581263508Sdimllvm::createAArch64AsmBackend(const Target &T, const MCRegisterInfo &MRI, 582263508Sdim StringRef TT, StringRef CPU) { 583249259Sdim Triple TheTriple(TT); 584249259Sdim return new ELFAArch64AsmBackend(T, TT, TheTriple.getOS()); 585249259Sdim} 586