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