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