Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp
Line
Count
Source (jump to first uncovered line)
1
//=- AArch64/AArch64MCCodeEmitter.cpp - Convert AArch64 code to machine code-=//
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-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file implements the AArch64MCCodeEmitter class.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "MCTargetDesc/AArch64AddressingModes.h"
14
#include "MCTargetDesc/AArch64FixupKinds.h"
15
#include "MCTargetDesc/AArch64MCExpr.h"
16
#include "Utils/AArch64BaseInfo.h"
17
#include "llvm/ADT/SmallVector.h"
18
#include "llvm/ADT/Statistic.h"
19
#include "llvm/MC/MCCodeEmitter.h"
20
#include "llvm/MC/MCContext.h"
21
#include "llvm/MC/MCFixup.h"
22
#include "llvm/MC/MCInst.h"
23
#include "llvm/MC/MCInstrInfo.h"
24
#include "llvm/MC/MCRegisterInfo.h"
25
#include "llvm/MC/MCSubtargetInfo.h"
26
#include "llvm/Support/Casting.h"
27
#include "llvm/Support/Endian.h"
28
#include "llvm/Support/EndianStream.h"
29
#include "llvm/Support/ErrorHandling.h"
30
#include "llvm/Support/raw_ostream.h"
31
#include <cassert>
32
#include <cstdint>
33
34
using namespace llvm;
35
36
#define DEBUG_TYPE "mccodeemitter"
37
38
STATISTIC(MCNumEmitted, "Number of MC instructions emitted.");
39
STATISTIC(MCNumFixups, "Number of MC fixups created.");
40
41
namespace {
42
43
class AArch64MCCodeEmitter : public MCCodeEmitter {
44
  MCContext &Ctx;
45
  const MCInstrInfo &MCII;
46
47
public:
48
  AArch64MCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
49
10.4k
      : Ctx(ctx), MCII(mcii) {}
50
  AArch64MCCodeEmitter(const AArch64MCCodeEmitter &) = delete;
51
  void operator=(const AArch64MCCodeEmitter &) = delete;
52
10.4k
  ~AArch64MCCodeEmitter() override = default;
53
54
  // getBinaryCodeForInstr - TableGen'erated function for getting the
55
  // binary encoding for an instruction.
56
  uint64_t getBinaryCodeForInstr(const MCInst &MI,
57
                                 SmallVectorImpl<MCFixup> &Fixups,
58
                                 const MCSubtargetInfo &STI) const;
59
60
  /// getMachineOpValue - Return binary encoding of operand. If the machine
61
  /// operand requires relocation, record the relocation and return zero.
62
  unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
63
                             SmallVectorImpl<MCFixup> &Fixups,
64
                             const MCSubtargetInfo &STI) const;
65
66
  /// getLdStUImm12OpValue - Return encoding info for 12-bit unsigned immediate
67
  /// attached to a load, store or prfm instruction. If operand requires a
68
  /// relocation, record it and return zero in that part of the encoding.
69
  template <uint32_t FixupKind>
70
  uint32_t getLdStUImm12OpValue(const MCInst &MI, unsigned OpIdx,
71
                                SmallVectorImpl<MCFixup> &Fixups,
72
                                const MCSubtargetInfo &STI) const;
73
74
  /// getAdrLabelOpValue - Return encoding info for 21-bit immediate ADR label
75
  /// target.
76
  uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
77
                              SmallVectorImpl<MCFixup> &Fixups,
78
                              const MCSubtargetInfo &STI) const;
79
80
  /// getAddSubImmOpValue - Return encoding for the 12-bit immediate value and
81
  /// the 2-bit shift field.
82
  uint32_t getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx,
83
                               SmallVectorImpl<MCFixup> &Fixups,
84
                               const MCSubtargetInfo &STI) const;
85
86
  /// getCondBranchTargetOpValue - Return the encoded value for a conditional
87
  /// branch target.
88
  uint32_t getCondBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
89
                                      SmallVectorImpl<MCFixup> &Fixups,
90
                                      const MCSubtargetInfo &STI) const;
91
92
  /// getLoadLiteralOpValue - Return the encoded value for a load-literal
93
  /// pc-relative address.
94
  uint32_t getLoadLiteralOpValue(const MCInst &MI, unsigned OpIdx,
95
                                 SmallVectorImpl<MCFixup> &Fixups,
96
                                 const MCSubtargetInfo &STI) const;
97
98
  /// getMemExtendOpValue - Return the encoded value for a reg-extend load/store
99
  /// instruction: bit 0 is whether a shift is present, bit 1 is whether the
100
  /// operation is a sign extend (as opposed to a zero extend).
101
  uint32_t getMemExtendOpValue(const MCInst &MI, unsigned OpIdx,
102
                               SmallVectorImpl<MCFixup> &Fixups,
103
                               const MCSubtargetInfo &STI) const;
104
105
  /// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and-
106
  /// branch target.
107
  uint32_t getTestBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
108
                                      SmallVectorImpl<MCFixup> &Fixups,
109
                                      const MCSubtargetInfo &STI) const;
110
111
  /// getBranchTargetOpValue - Return the encoded value for an unconditional
112
  /// branch target.
113
  uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
114
                                  SmallVectorImpl<MCFixup> &Fixups,
115
                                  const MCSubtargetInfo &STI) const;
116
117
  /// getMoveWideImmOpValue - Return the encoded value for the immediate operand
118
  /// of a MOVZ or MOVK instruction.
119
  uint32_t getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx,
120
                                 SmallVectorImpl<MCFixup> &Fixups,
121
                                 const MCSubtargetInfo &STI) const;
122
123
  /// getVecShifterOpValue - Return the encoded value for the vector shifter.
124
  uint32_t getVecShifterOpValue(const MCInst &MI, unsigned OpIdx,
125
                                SmallVectorImpl<MCFixup> &Fixups,
126
                                const MCSubtargetInfo &STI) const;
127
128
  /// getMoveVecShifterOpValue - Return the encoded value for the vector move
129
  /// shifter (MSL).
130
  uint32_t getMoveVecShifterOpValue(const MCInst &MI, unsigned OpIdx,
131
                                    SmallVectorImpl<MCFixup> &Fixups,
132
                                    const MCSubtargetInfo &STI) const;
133
134
  /// getFixedPointScaleOpValue - Return the encoded value for the
135
  // FP-to-fixed-point scale factor.
136
  uint32_t getFixedPointScaleOpValue(const MCInst &MI, unsigned OpIdx,
137
                                     SmallVectorImpl<MCFixup> &Fixups,
138
                                     const MCSubtargetInfo &STI) const;
139
140
  uint32_t getVecShiftR64OpValue(const MCInst &MI, unsigned OpIdx,
141
                                 SmallVectorImpl<MCFixup> &Fixups,
142
                                 const MCSubtargetInfo &STI) const;
143
  uint32_t getVecShiftR32OpValue(const MCInst &MI, unsigned OpIdx,
144
                                 SmallVectorImpl<MCFixup> &Fixups,
145
                                 const MCSubtargetInfo &STI) const;
146
  uint32_t getVecShiftR16OpValue(const MCInst &MI, unsigned OpIdx,
147
                                 SmallVectorImpl<MCFixup> &Fixups,
148
                                 const MCSubtargetInfo &STI) const;
149
  uint32_t getVecShiftR8OpValue(const MCInst &MI, unsigned OpIdx,
150
                                SmallVectorImpl<MCFixup> &Fixups,
151
                                const MCSubtargetInfo &STI) const;
152
  uint32_t getVecShiftL64OpValue(const MCInst &MI, unsigned OpIdx,
153
                                 SmallVectorImpl<MCFixup> &Fixups,
154
                                 const MCSubtargetInfo &STI) const;
155
  uint32_t getVecShiftL32OpValue(const MCInst &MI, unsigned OpIdx,
156
                                 SmallVectorImpl<MCFixup> &Fixups,
157
                                 const MCSubtargetInfo &STI) const;
158
  uint32_t getVecShiftL16OpValue(const MCInst &MI, unsigned OpIdx,
159
                                 SmallVectorImpl<MCFixup> &Fixups,
160
                                 const MCSubtargetInfo &STI) const;
161
  uint32_t getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx,
162
                                SmallVectorImpl<MCFixup> &Fixups,
163
                                const MCSubtargetInfo &STI) const;
164
165
  uint32_t getImm8OptLsl(const MCInst &MI, unsigned OpIdx,
166
                         SmallVectorImpl<MCFixup> &Fixups,
167
                         const MCSubtargetInfo &STI) const;
168
  uint32_t getSVEIncDecImm(const MCInst &MI, unsigned OpIdx,
169
                           SmallVectorImpl<MCFixup> &Fixups,
170
                           const MCSubtargetInfo &STI) const;
171
172
  unsigned fixMOVZ(const MCInst &MI, unsigned EncodedValue,
173
                   const MCSubtargetInfo &STI) const;
174
175
  void encodeInstruction(const MCInst &MI, raw_ostream &OS,
176
                         SmallVectorImpl<MCFixup> &Fixups,
177
                         const MCSubtargetInfo &STI) const override;
178
179
  unsigned fixMulHigh(const MCInst &MI, unsigned EncodedValue,
180
                      const MCSubtargetInfo &STI) const;
181
182
  template<int hasRs, int hasRt2> unsigned
183
  fixLoadStoreExclusive(const MCInst &MI, unsigned EncodedValue,
184
                        const MCSubtargetInfo &STI) const;
185
186
  unsigned fixOneOperandFPComparison(const MCInst &MI, unsigned EncodedValue,
187
                                     const MCSubtargetInfo &STI) const;
188
189
private:
190
  FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const;
191
  void
192
  verifyInstructionPredicates(const MCInst &MI,
193
                              const FeatureBitset &AvailableFeatures) const;
194
};
195
196
} // end anonymous namespace
197
198
/// getMachineOpValue - Return binary encoding of operand. If the machine
199
/// operand requires relocation, record the relocation and return zero.
200
unsigned
201
AArch64MCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
202
                                        SmallVectorImpl<MCFixup> &Fixups,
203
34.8M
                                        const MCSubtargetInfo &STI) const {
204
34.8M
  if (MO.isReg())
205
27.2M
    return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
206
7.60M
207
7.60M
  assert(MO.isImm() && "did not expect relocated expression");
208
7.60M
  return static_cast<unsigned>(MO.getImm());
209
7.60M
}
210
211
template<unsigned FixupKind> uint32_t
212
AArch64MCCodeEmitter::getLdStUImm12OpValue(const MCInst &MI, unsigned OpIdx,
213
                                           SmallVectorImpl<MCFixup> &Fixups,
214
2.13M
                                           const MCSubtargetInfo &STI) const {
215
2.13M
  const MCOperand &MO = MI.getOperand(OpIdx);
216
2.13M
  uint32_t ImmVal = 0;
217
2.13M
218
2.13M
  if (MO.isImm())
219
1.92M
    ImmVal = static_cast<uint32_t>(MO.getImm());
220
209k
  else {
221
209k
    assert(MO.isExpr() && "unable to encode load/store imm operand");
222
209k
    MCFixupKind Kind = MCFixupKind(FixupKind);
223
209k
    Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
224
209k
    ++MCNumFixups;
225
209k
  }
226
2.13M
227
2.13M
  return ImmVal;
228
2.13M
}
AArch64MCCodeEmitter.cpp:unsigned int (anonymous namespace)::AArch64MCCodeEmitter::getLdStUImm12OpValue<135u>(llvm::MCInst const&, unsigned int, llvm::SmallVectorImpl<llvm::MCFixup>&, llvm::MCSubtargetInfo const&) const
Line
Count
Source
214
123k
                                           const MCSubtargetInfo &STI) const {
215
123k
  const MCOperand &MO = MI.getOperand(OpIdx);
216
123k
  uint32_t ImmVal = 0;
217
123k
218
123k
  if (MO.isImm())
219
103k
    ImmVal = static_cast<uint32_t>(MO.getImm());
220
19.4k
  else {
221
19.4k
    assert(MO.isExpr() && "unable to encode load/store imm operand");
222
19.4k
    MCFixupKind Kind = MCFixupKind(FixupKind);
223
19.4k
    Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
224
19.4k
    ++MCNumFixups;
225
19.4k
  }
226
123k
227
123k
  return ImmVal;
228
123k
}
AArch64MCCodeEmitter.cpp:unsigned int (anonymous namespace)::AArch64MCCodeEmitter::getLdStUImm12OpValue<131u>(llvm::MCInst const&, unsigned int, llvm::SmallVectorImpl<llvm::MCFixup>&, llvm::MCSubtargetInfo const&) const
Line
Count
Source
214
341k
                                           const MCSubtargetInfo &STI) const {
215
341k
  const MCOperand &MO = MI.getOperand(OpIdx);
216
341k
  uint32_t ImmVal = 0;
217
341k
218
341k
  if (MO.isImm())
219
333k
    ImmVal = static_cast<uint32_t>(MO.getImm());
220
8.68k
  else {
221
8.68k
    assert(MO.isExpr() && "unable to encode load/store imm operand");
222
8.68k
    MCFixupKind Kind = MCFixupKind(FixupKind);
223
8.68k
    Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
224
8.68k
    ++MCNumFixups;
225
8.68k
  }
226
341k
227
341k
  return ImmVal;
228
341k
}
AArch64MCCodeEmitter.cpp:unsigned int (anonymous namespace)::AArch64MCCodeEmitter::getLdStUImm12OpValue<132u>(llvm::MCInst const&, unsigned int, llvm::SmallVectorImpl<llvm::MCFixup>&, llvm::MCSubtargetInfo const&) const
Line
Count
Source
214
95.0k
                                           const MCSubtargetInfo &STI) const {
215
95.0k
  const MCOperand &MO = MI.getOperand(OpIdx);
216
95.0k
  uint32_t ImmVal = 0;
217
95.0k
218
95.0k
  if (MO.isImm())
219
94.9k
    ImmVal = static_cast<uint32_t>(MO.getImm());
220
100
  else {
221
100
    assert(MO.isExpr() && "unable to encode load/store imm operand");
222
100
    MCFixupKind Kind = MCFixupKind(FixupKind);
223
100
    Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
224
100
    ++MCNumFixups;
225
100
  }
226
95.0k
227
95.0k
  return ImmVal;
228
95.0k
}
AArch64MCCodeEmitter.cpp:unsigned int (anonymous namespace)::AArch64MCCodeEmitter::getLdStUImm12OpValue<133u>(llvm::MCInst const&, unsigned int, llvm::SmallVectorImpl<llvm::MCFixup>&, llvm::MCSubtargetInfo const&) const
Line
Count
Source
214
490k
                                           const MCSubtargetInfo &STI) const {
215
490k
  const MCOperand &MO = MI.getOperand(OpIdx);
216
490k
  uint32_t ImmVal = 0;
217
490k
218
490k
  if (MO.isImm())
219
484k
    ImmVal = static_cast<uint32_t>(MO.getImm());
220
6.30k
  else {
221
6.30k
    assert(MO.isExpr() && "unable to encode load/store imm operand");
222
6.30k
    MCFixupKind Kind = MCFixupKind(FixupKind);
223
6.30k
    Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
224
6.30k
    ++MCNumFixups;
225
6.30k
  }
226
490k
227
490k
  return ImmVal;
228
490k
}
AArch64MCCodeEmitter.cpp:unsigned int (anonymous namespace)::AArch64MCCodeEmitter::getLdStUImm12OpValue<134u>(llvm::MCInst const&, unsigned int, llvm::SmallVectorImpl<llvm::MCFixup>&, llvm::MCSubtargetInfo const&) const
Line
Count
Source
214
1.08M
                                           const MCSubtargetInfo &STI) const {
215
1.08M
  const MCOperand &MO = MI.getOperand(OpIdx);
216
1.08M
  uint32_t ImmVal = 0;
217
1.08M
218
1.08M
  if (MO.isImm())
219
906k
    ImmVal = static_cast<uint32_t>(MO.getImm());
220
174k
  else {
221
174k
    assert(MO.isExpr() && "unable to encode load/store imm operand");
222
174k
    MCFixupKind Kind = MCFixupKind(FixupKind);
223
174k
    Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
224
174k
    ++MCNumFixups;
225
174k
  }
226
1.08M
227
1.08M
  return ImmVal;
228
1.08M
}
229
230
/// getAdrLabelOpValue - Return encoding info for 21-bit immediate ADR label
231
/// target.
232
uint32_t
233
AArch64MCCodeEmitter::getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
234
                                         SmallVectorImpl<MCFixup> &Fixups,
235
638k
                                         const MCSubtargetInfo &STI) const {
236
638k
  const MCOperand &MO = MI.getOperand(OpIdx);
237
638k
238
638k
  // If the destination is an immediate, we have nothing to do.
239
638k
  if (MO.isImm())
240
15
    return MO.getImm();
241
638k
  assert(MO.isExpr() && "Unexpected target type!");
242
638k
  const MCExpr *Expr = MO.getExpr();
243
638k
244
638k
  MCFixupKind Kind = MI.getOpcode() == AArch64::ADR
245
638k
                         ? 
MCFixupKind(AArch64::fixup_aarch64_pcrel_adr_imm21)2.37k
246
638k
                         : 
MCFixupKind(AArch64::fixup_aarch64_pcrel_adrp_imm21)636k
;
247
638k
  Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc()));
248
638k
249
638k
  MCNumFixups += 1;
250
638k
251
638k
  // All of the information is in the fixup.
252
638k
  return 0;
253
638k
}
254
255
/// getAddSubImmOpValue - Return encoding for the 12-bit immediate value and
256
/// the 2-bit shift field.  The shift field is stored in bits 13-14 of the
257
/// return value.
258
uint32_t
259
AArch64MCCodeEmitter::getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx,
260
                                          SmallVectorImpl<MCFixup> &Fixups,
261
1.39M
                                          const MCSubtargetInfo &STI) const {
262
1.39M
  // Suboperands are [imm, shifter].
263
1.39M
  const MCOperand &MO = MI.getOperand(OpIdx);
264
1.39M
  const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
265
1.39M
  assert(AArch64_AM::getShiftType(MO1.getImm()) == AArch64_AM::LSL &&
266
1.39M
         "unexpected shift type for add/sub immediate");
267
1.39M
  unsigned ShiftVal = AArch64_AM::getShiftValue(MO1.getImm());
268
1.39M
  assert((ShiftVal == 0 || ShiftVal == 12) &&
269
1.39M
         "unexpected shift value for add/sub immediate");
270
1.39M
  if (MO.isImm())
271
946k
    return MO.getImm() | (ShiftVal == 0 ? 
0923k
:
(1 << ShiftVal)23.0k
);
272
445k
  assert(MO.isExpr() && "Unable to encode MCOperand!");
273
445k
  const MCExpr *Expr = MO.getExpr();
274
445k
275
445k
  // Encode the 12 bits of the fixup.
276
445k
  MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_add_imm12);
277
445k
  Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc()));
278
445k
279
445k
  ++MCNumFixups;
280
445k
281
445k
  // Set the shift bit of the add instruction for relocation types
282
445k
  // R_AARCH64_TLSLE_ADD_TPREL_HI12 and R_AARCH64_TLSLD_ADD_DTPREL_HI12.
283
445k
  if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) {
284
186
    AArch64MCExpr::VariantKind RefKind = A64E->getKind();
285
186
    if (RefKind == AArch64MCExpr::VK_TPREL_HI12 ||
286
186
        
RefKind == AArch64MCExpr::VK_DTPREL_HI12164
||
287
186
        
RefKind == AArch64MCExpr::VK_SECREL_HI12154
)
288
33
      ShiftVal = 12;
289
186
  }
290
445k
  return ShiftVal == 0 ? 
0445k
:
(1 << ShiftVal)41
;
291
445k
}
292
293
/// getCondBranchTargetOpValue - Return the encoded value for a conditional
294
/// branch target.
295
uint32_t AArch64MCCodeEmitter::getCondBranchTargetOpValue(
296
    const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
297
1.03M
    const MCSubtargetInfo &STI) const {
298
1.03M
  const MCOperand &MO = MI.getOperand(OpIdx);
299
1.03M
300
1.03M
  // If the destination is an immediate, we have nothing to do.
301
1.03M
  if (MO.isImm())
302
13
    return MO.getImm();
303
1.03M
  assert(MO.isExpr() && "Unexpected target type!");
304
1.03M
305
1.03M
  MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_pcrel_branch19);
306
1.03M
  Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
307
1.03M
308
1.03M
  ++MCNumFixups;
309
1.03M
310
1.03M
  // All of the information is in the fixup.
311
1.03M
  return 0;
312
1.03M
}
313
314
/// getLoadLiteralOpValue - Return the encoded value for a load-literal
315
/// pc-relative address.
316
uint32_t
317
AArch64MCCodeEmitter::getLoadLiteralOpValue(const MCInst &MI, unsigned OpIdx,
318
                                            SmallVectorImpl<MCFixup> &Fixups,
319
49
                                            const MCSubtargetInfo &STI) const {
320
49
  const MCOperand &MO = MI.getOperand(OpIdx);
321
49
322
49
  // If the destination is an immediate, we have nothing to do.
323
49
  if (MO.isImm())
324
2
    return MO.getImm();
325
47
  assert(MO.isExpr() && "Unexpected target type!");
326
47
327
47
  MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_ldr_pcrel_imm19);
328
47
  Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
329
47
330
47
  ++MCNumFixups;
331
47
332
47
  // All of the information is in the fixup.
333
47
  return 0;
334
47
}
335
336
uint32_t
337
AArch64MCCodeEmitter::getMemExtendOpValue(const MCInst &MI, unsigned OpIdx,
338
                                          SmallVectorImpl<MCFixup> &Fixups,
339
91.8k
                                          const MCSubtargetInfo &STI) const {
340
91.8k
  unsigned SignExtend = MI.getOperand(OpIdx).getImm();
341
91.8k
  unsigned DoShift = MI.getOperand(OpIdx + 1).getImm();
342
91.8k
  return (SignExtend << 1) | DoShift;
343
91.8k
}
344
345
uint32_t
346
AArch64MCCodeEmitter::getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx,
347
                                            SmallVectorImpl<MCFixup> &Fixups,
348
1.48M
                                            const MCSubtargetInfo &STI) const {
349
1.48M
  const MCOperand &MO = MI.getOperand(OpIdx);
350
1.48M
351
1.48M
  if (MO.isImm())
352
1.48M
    return MO.getImm();
353
297
  assert(MO.isExpr() && "Unexpected movz/movk immediate");
354
297
355
297
  Fixups.push_back(MCFixup::create(
356
297
      0, MO.getExpr(), MCFixupKind(AArch64::fixup_aarch64_movw), MI.getLoc()));
357
297
358
297
  ++MCNumFixups;
359
297
360
297
  return 0;
361
297
}
362
363
/// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and-
364
/// branch target.
365
uint32_t AArch64MCCodeEmitter::getTestBranchTargetOpValue(
366
    const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
367
86.8k
    const MCSubtargetInfo &STI) const {
368
86.8k
  const MCOperand &MO = MI.getOperand(OpIdx);
369
86.8k
370
86.8k
  // If the destination is an immediate, we have nothing to do.
371
86.8k
  if (MO.isImm())
372
3
    return MO.getImm();
373
86.8k
  assert(MO.isExpr() && "Unexpected ADR target type!");
374
86.8k
375
86.8k
  MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_pcrel_branch14);
376
86.8k
  Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
377
86.8k
378
86.8k
  ++MCNumFixups;
379
86.8k
380
86.8k
  // All of the information is in the fixup.
381
86.8k
  return 0;
382
86.8k
}
383
384
/// getBranchTargetOpValue - Return the encoded value for an unconditional
385
/// branch target.
386
uint32_t
387
AArch64MCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
388
                                             SmallVectorImpl<MCFixup> &Fixups,
389
1.45M
                                             const MCSubtargetInfo &STI) const {
390
1.45M
  const MCOperand &MO = MI.getOperand(OpIdx);
391
1.45M
392
1.45M
  // If the destination is an immediate, we have nothing to do.
393
1.45M
  if (MO.isImm())
394
7
    return MO.getImm();
395
1.45M
  assert(MO.isExpr() && "Unexpected ADR target type!");
396
1.45M
397
1.45M
  MCFixupKind Kind = MI.getOpcode() == AArch64::BL
398
1.45M
                         ? 
MCFixupKind(AArch64::fixup_aarch64_pcrel_call26)1.11M
399
1.45M
                         : 
MCFixupKind(AArch64::fixup_aarch64_pcrel_branch26)340k
;
400
1.45M
  Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
401
1.45M
402
1.45M
  ++MCNumFixups;
403
1.45M
404
1.45M
  // All of the information is in the fixup.
405
1.45M
  return 0;
406
1.45M
}
407
408
/// getVecShifterOpValue - Return the encoded value for the vector shifter:
409
///
410
///   00 -> 0
411
///   01 -> 8
412
///   10 -> 16
413
///   11 -> 24
414
uint32_t
415
AArch64MCCodeEmitter::getVecShifterOpValue(const MCInst &MI, unsigned OpIdx,
416
                                           SmallVectorImpl<MCFixup> &Fixups,
417
17.7k
                                           const MCSubtargetInfo &STI) const {
418
17.7k
  const MCOperand &MO = MI.getOperand(OpIdx);
419
17.7k
  assert(MO.isImm() && "Expected an immediate value for the shift amount!");
420
17.7k
421
17.7k
  switch (MO.getImm()) {
422
17.7k
  default:
423
0
    break;
424
17.7k
  case 0:
425
17.4k
    return 0;
426
17.7k
  case 8:
427
199
    return 1;
428
17.7k
  case 16:
429
54
    return 2;
430
17.7k
  case 24:
431
75
    return 3;
432
0
  }
433
0
434
0
  llvm_unreachable("Invalid value for vector shift amount!");
435
0
}
436
437
/// getFixedPointScaleOpValue - Return the encoded value for the
438
// FP-to-fixed-point scale factor.
439
uint32_t AArch64MCCodeEmitter::getFixedPointScaleOpValue(
440
    const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
441
104
    const MCSubtargetInfo &STI) const {
442
104
  const MCOperand &MO = MI.getOperand(OpIdx);
443
104
  assert(MO.isImm() && "Expected an immediate value for the scale amount!");
444
104
  return 64 - MO.getImm();
445
104
}
446
447
uint32_t
448
AArch64MCCodeEmitter::getVecShiftR64OpValue(const MCInst &MI, unsigned OpIdx,
449
                                            SmallVectorImpl<MCFixup> &Fixups,
450
1.34k
                                            const MCSubtargetInfo &STI) const {
451
1.34k
  const MCOperand &MO = MI.getOperand(OpIdx);
452
1.34k
  assert(MO.isImm() && "Expected an immediate value for the scale amount!");
453
1.34k
  return 64 - MO.getImm();
454
1.34k
}
455
456
uint32_t
457
AArch64MCCodeEmitter::getVecShiftR32OpValue(const MCInst &MI, unsigned OpIdx,
458
                                            SmallVectorImpl<MCFixup> &Fixups,
459
6.32k
                                            const MCSubtargetInfo &STI) const {
460
6.32k
  const MCOperand &MO = MI.getOperand(OpIdx);
461
6.32k
  assert(MO.isImm() && "Expected an immediate value for the scale amount!");
462
6.32k
  return 32 - MO.getImm();
463
6.32k
}
464
465
uint32_t
466
AArch64MCCodeEmitter::getVecShiftR16OpValue(const MCInst &MI, unsigned OpIdx,
467
                                            SmallVectorImpl<MCFixup> &Fixups,
468
537
                                            const MCSubtargetInfo &STI) const {
469
537
  const MCOperand &MO = MI.getOperand(OpIdx);
470
537
  assert(MO.isImm() && "Expected an immediate value for the scale amount!");
471
537
  return 16 - MO.getImm();
472
537
}
473
474
uint32_t
475
AArch64MCCodeEmitter::getVecShiftR8OpValue(const MCInst &MI, unsigned OpIdx,
476
                                           SmallVectorImpl<MCFixup> &Fixups,
477
360
                                           const MCSubtargetInfo &STI) const {
478
360
  const MCOperand &MO = MI.getOperand(OpIdx);
479
360
  assert(MO.isImm() && "Expected an immediate value for the scale amount!");
480
360
  return 8 - MO.getImm();
481
360
}
482
483
uint32_t
484
AArch64MCCodeEmitter::getVecShiftL64OpValue(const MCInst &MI, unsigned OpIdx,
485
                                            SmallVectorImpl<MCFixup> &Fixups,
486
216
                                            const MCSubtargetInfo &STI) const {
487
216
  const MCOperand &MO = MI.getOperand(OpIdx);
488
216
  assert(MO.isImm() && "Expected an immediate value for the scale amount!");
489
216
  return MO.getImm() - 64;
490
216
}
491
492
uint32_t
493
AArch64MCCodeEmitter::getVecShiftL32OpValue(const MCInst &MI, unsigned OpIdx,
494
                                            SmallVectorImpl<MCFixup> &Fixups,
495
30.5k
                                            const MCSubtargetInfo &STI) const {
496
30.5k
  const MCOperand &MO = MI.getOperand(OpIdx);
497
30.5k
  assert(MO.isImm() && "Expected an immediate value for the scale amount!");
498
30.5k
  return MO.getImm() - 32;
499
30.5k
}
500
501
uint32_t
502
AArch64MCCodeEmitter::getVecShiftL16OpValue(const MCInst &MI, unsigned OpIdx,
503
                                            SmallVectorImpl<MCFixup> &Fixups,
504
1.33k
                                            const MCSubtargetInfo &STI) const {
505
1.33k
  const MCOperand &MO = MI.getOperand(OpIdx);
506
1.33k
  assert(MO.isImm() && "Expected an immediate value for the scale amount!");
507
1.33k
  return MO.getImm() - 16;
508
1.33k
}
509
510
uint32_t
511
AArch64MCCodeEmitter::getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx,
512
                                           SmallVectorImpl<MCFixup> &Fixups,
513
437
                                           const MCSubtargetInfo &STI) const {
514
437
  const MCOperand &MO = MI.getOperand(OpIdx);
515
437
  assert(MO.isImm() && "Expected an immediate value for the scale amount!");
516
437
  return MO.getImm() - 8;
517
437
}
518
519
uint32_t
520
AArch64MCCodeEmitter::getImm8OptLsl(const MCInst &MI, unsigned OpIdx,
521
                                    SmallVectorImpl<MCFixup> &Fixups,
522
636
                                    const MCSubtargetInfo &STI) const {
523
636
  // Test shift
524
636
  auto ShiftOpnd = MI.getOperand(OpIdx + 1).getImm();
525
636
  assert(AArch64_AM::getShiftType(ShiftOpnd) == AArch64_AM::LSL &&
526
636
         "Unexpected shift type for imm8_opt_lsl immediate.");
527
636
528
636
  unsigned ShiftVal = AArch64_AM::getShiftValue(ShiftOpnd);
529
636
  assert((ShiftVal == 0 || ShiftVal == 8) &&
530
636
         "Unexpected shift value for imm8_opt_lsl immediate.");
531
636
532
636
  // Test immediate
533
636
  auto Immediate = MI.getOperand(OpIdx).getImm();
534
636
  return (Immediate & 0xff) | (ShiftVal == 0 ? 
0246
:
(1 << ShiftVal)390
);
535
636
}
536
537
uint32_t
538
AArch64MCCodeEmitter::getSVEIncDecImm(const MCInst &MI, unsigned OpIdx,
539
                                           SmallVectorImpl<MCFixup> &Fixups,
540
2.85k
                                           const MCSubtargetInfo &STI) const {
541
2.85k
  const MCOperand &MO = MI.getOperand(OpIdx);
542
2.85k
  assert(MO.isImm() && "Expected an immediate value!");
543
2.85k
  // Normalize 1-16 range to 0-15.
544
2.85k
  return MO.getImm() - 1;
545
2.85k
}
546
547
/// getMoveVecShifterOpValue - Return the encoded value for the vector move
548
/// shifter (MSL).
549
uint32_t AArch64MCCodeEmitter::getMoveVecShifterOpValue(
550
    const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
551
69
    const MCSubtargetInfo &STI) const {
552
69
  const MCOperand &MO = MI.getOperand(OpIdx);
553
69
  assert(MO.isImm() &&
554
69
         "Expected an immediate value for the move shift amount!");
555
69
  unsigned ShiftVal = AArch64_AM::getShiftValue(MO.getImm());
556
69
  assert((ShiftVal == 8 || ShiftVal == 16) && "Invalid shift amount!");
557
69
  return ShiftVal == 8 ? 
057
:
112
;
558
69
}
559
560
unsigned AArch64MCCodeEmitter::fixMOVZ(const MCInst &MI, unsigned EncodedValue,
561
1.23M
                                       const MCSubtargetInfo &STI) const {
562
1.23M
  // If one of the signed fixup kinds is applied to a MOVZ instruction, the
563
1.23M
  // eventual result could be either a MOVZ or a MOVN. It's the MCCodeEmitter's
564
1.23M
  // job to ensure that any bits possibly affected by this are 0. This means we
565
1.23M
  // must zero out bit 30 (essentially emitting a MOVN).
566
1.23M
  MCOperand UImm16MO = MI.getOperand(1);
567
1.23M
568
1.23M
  // Nothing to do if there's no fixup.
569
1.23M
  if (UImm16MO.isImm())
570
1.23M
    return EncodedValue;
571
133
572
133
  const AArch64MCExpr *A64E = cast<AArch64MCExpr>(UImm16MO.getExpr());
573
133
  switch (A64E->getKind()) {
574
133
  case AArch64MCExpr::VK_DTPREL_G2:
575
53
  case AArch64MCExpr::VK_DTPREL_G1:
576
53
  case AArch64MCExpr::VK_DTPREL_G0:
577
53
  case AArch64MCExpr::VK_GOTTPREL_G1:
578
53
  case AArch64MCExpr::VK_TPREL_G2:
579
53
  case AArch64MCExpr::VK_TPREL_G1:
580
53
  case AArch64MCExpr::VK_TPREL_G0:
581
53
    return EncodedValue & ~(1u << 30);
582
80
  default:
583
80
    // Nothing to do for an unsigned fixup.
584
80
    return EncodedValue;
585
0
  }
586
0
587
0
588
0
  return EncodedValue & ~(1u << 30);
589
0
}
590
591
void AArch64MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
592
                                             SmallVectorImpl<MCFixup> &Fixups,
593
14.5M
                                             const MCSubtargetInfo &STI) const {
594
14.5M
  verifyInstructionPredicates(MI,
595
14.5M
                              computeAvailableFeatures(STI.getFeatureBits()));
596
14.5M
597
14.5M
  if (MI.getOpcode() == AArch64::TLSDESCCALL) {
598
21
    // This is a directive which applies an R_AARCH64_TLSDESC_CALL to the
599
21
    // following (BLR) instruction. It doesn't emit any code itself so it
600
21
    // doesn't go through the normal TableGenerated channels.
601
21
    MCFixupKind Fixup = MCFixupKind(AArch64::fixup_aarch64_tlsdesc_call);
602
21
    Fixups.push_back(MCFixup::create(0, MI.getOperand(0).getExpr(), Fixup));
603
21
    return;
604
14.5M
  } else if (MI.getOpcode() == AArch64::CompilerBarrier) {
605
9
    // This just prevents the compiler from reordering accesses, no actual code.
606
9
    return;
607
9
  }
608
14.5M
609
14.5M
  uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI);
610
14.5M
  support::endian::write<uint32_t>(OS, Binary, support::little);
611
14.5M
  ++MCNumEmitted; // Keep track of the # of mi's emitted.
612
14.5M
}
613
614
unsigned
615
AArch64MCCodeEmitter::fixMulHigh(const MCInst &MI,
616
                                 unsigned EncodedValue,
617
529
                                 const MCSubtargetInfo &STI) const {
618
529
  // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
619
529
  // (i.e. all bits 1) but is ignored by the processor.
620
529
  EncodedValue |= 0x1f << 10;
621
529
  return EncodedValue;
622
529
}
623
624
template<int hasRs, int hasRt2> unsigned
625
AArch64MCCodeEmitter::fixLoadStoreExclusive(const MCInst &MI,
626
                                            unsigned EncodedValue,
627
54.7k
                                            const MCSubtargetInfo &STI) const {
628
54.7k
  if (!hasRs) 
EncodedValue |= 0x001F000031.0k
;
629
54.7k
  if (!hasRt2) 
EncodedValue |= 0x00007C0054.6k
;
630
54.7k
631
54.7k
  return EncodedValue;
632
54.7k
}
AArch64MCCodeEmitter.cpp:unsigned int (anonymous namespace)::AArch64MCCodeEmitter::fixLoadStoreExclusive<0, 0>(llvm::MCInst const&, unsigned int, llvm::MCSubtargetInfo const&) const
Line
Count
Source
627
31.0k
                                            const MCSubtargetInfo &STI) const {
628
31.0k
  if (!hasRs) EncodedValue |= 0x001F0000;
629
31.0k
  if (!hasRt2) EncodedValue |= 0x00007C00;
630
31.0k
631
31.0k
  return EncodedValue;
632
31.0k
}
AArch64MCCodeEmitter.cpp:unsigned int (anonymous namespace)::AArch64MCCodeEmitter::fixLoadStoreExclusive<0, 1>(llvm::MCInst const&, unsigned int, llvm::MCSubtargetInfo const&) const
Line
Count
Source
627
8
                                            const MCSubtargetInfo &STI) const {
628
8
  if (!hasRs) EncodedValue |= 0x001F0000;
629
8
  if (!hasRt2) 
EncodedValue |= 0x00007C000
;
630
8
631
8
  return EncodedValue;
632
8
}
AArch64MCCodeEmitter.cpp:unsigned int (anonymous namespace)::AArch64MCCodeEmitter::fixLoadStoreExclusive<1, 0>(llvm::MCInst const&, unsigned int, llvm::MCSubtargetInfo const&) const
Line
Count
Source
627
23.6k
                                            const MCSubtargetInfo &STI) const {
628
23.6k
  if (!hasRs) 
EncodedValue |= 0x001F00000
;
629
23.6k
  if (!hasRt2) EncodedValue |= 0x00007C00;
630
23.6k
631
23.6k
  return EncodedValue;
632
23.6k
}
633
634
unsigned AArch64MCCodeEmitter::fixOneOperandFPComparison(
635
2.15k
    const MCInst &MI, unsigned EncodedValue, const MCSubtargetInfo &STI) const {
636
2.15k
  // The Rm field of FCMP and friends is unused - it should be assembled
637
2.15k
  // as 0, but is ignored by the processor.
638
2.15k
  EncodedValue &= ~(0x1f << 16);
639
2.15k
  return EncodedValue;
640
2.15k
}
641
642
#define ENABLE_INSTR_PREDICATE_VERIFIER
643
#include "AArch64GenMCCodeEmitter.inc"
644
645
MCCodeEmitter *llvm::createAArch64MCCodeEmitter(const MCInstrInfo &MCII,
646
                                                const MCRegisterInfo &MRI,
647
10.4k
                                                MCContext &Ctx) {
648
10.4k
  return new AArch64MCCodeEmitter(MCII, Ctx);
649
10.4k
}