AArch64MCCodeEmitter.cpp revision dce4a407a24b04eebc6a376f8e62b41aaa7b071f
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  else {
222    assert(MO.isImm() && "did not expect relocated expression");
223    return static_cast<unsigned>(MO.getImm());
224  }
225
226  assert(0 && "Unable to encode MCOperand!");
227  return 0;
228}
229
230template<unsigned FixupKind> uint32_t
231AArch64MCCodeEmitter::getLdStUImm12OpValue(const MCInst &MI, unsigned OpIdx,
232                                           SmallVectorImpl<MCFixup> &Fixups,
233                                           const MCSubtargetInfo &STI) const {
234  const MCOperand &MO = MI.getOperand(OpIdx);
235  uint32_t ImmVal = 0;
236
237  if (MO.isImm())
238    ImmVal = static_cast<uint32_t>(MO.getImm());
239  else {
240    assert(MO.isExpr() && "unable to encode load/store imm operand");
241    MCFixupKind Kind = MCFixupKind(FixupKind);
242    Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc()));
243    ++MCNumFixups;
244  }
245
246  return ImmVal;
247}
248
249/// getAdrLabelOpValue - Return encoding info for 21-bit immediate ADR label
250/// target.
251uint32_t
252AArch64MCCodeEmitter::getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
253                                         SmallVectorImpl<MCFixup> &Fixups,
254                                         const MCSubtargetInfo &STI) const {
255  const MCOperand &MO = MI.getOperand(OpIdx);
256
257  // If the destination is an immediate, we have nothing to do.
258  if (MO.isImm())
259    return MO.getImm();
260  assert(MO.isExpr() && "Unexpected target type!");
261  const MCExpr *Expr = MO.getExpr();
262
263  MCFixupKind Kind = MI.getOpcode() == AArch64::ADR
264                         ? MCFixupKind(AArch64::fixup_aarch64_pcrel_adr_imm21)
265                         : MCFixupKind(AArch64::fixup_aarch64_pcrel_adrp_imm21);
266  Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc()));
267
268  MCNumFixups += 1;
269
270  // All of the information is in the fixup.
271  return 0;
272}
273
274/// getAddSubImmOpValue - Return encoding for the 12-bit immediate value and
275/// the 2-bit shift field.  The shift field is stored in bits 13-14 of the
276/// return value.
277uint32_t
278AArch64MCCodeEmitter::getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx,
279                                          SmallVectorImpl<MCFixup> &Fixups,
280                                          const MCSubtargetInfo &STI) const {
281  // Suboperands are [imm, shifter].
282  const MCOperand &MO = MI.getOperand(OpIdx);
283  const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
284  assert(AArch64_AM::getShiftType(MO1.getImm()) == AArch64_AM::LSL &&
285         "unexpected shift type for add/sub immediate");
286  unsigned ShiftVal = AArch64_AM::getShiftValue(MO1.getImm());
287  assert((ShiftVal == 0 || ShiftVal == 12) &&
288         "unexpected shift value for add/sub immediate");
289  if (MO.isImm())
290    return MO.getImm() | (ShiftVal == 0 ? 0 : (1 << 12));
291  assert(MO.isExpr() && "Unable to encode MCOperand!");
292  const MCExpr *Expr = MO.getExpr();
293
294  // Encode the 12 bits of the fixup.
295  MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_add_imm12);
296  Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc()));
297
298  ++MCNumFixups;
299
300  return 0;
301}
302
303/// getCondBranchTargetOpValue - Return the encoded value for a conditional
304/// branch target.
305uint32_t AArch64MCCodeEmitter::getCondBranchTargetOpValue(
306    const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
307    const MCSubtargetInfo &STI) const {
308  const MCOperand &MO = MI.getOperand(OpIdx);
309
310  // If the destination is an immediate, we have nothing to do.
311  if (MO.isImm())
312    return MO.getImm();
313  assert(MO.isExpr() && "Unexpected target type!");
314
315  MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_pcrel_branch19);
316  Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc()));
317
318  ++MCNumFixups;
319
320  // All of the information is in the fixup.
321  return 0;
322}
323
324/// getLoadLiteralOpValue - Return the encoded value for a load-literal
325/// pc-relative address.
326uint32_t
327AArch64MCCodeEmitter::getLoadLiteralOpValue(const MCInst &MI, unsigned OpIdx,
328                                            SmallVectorImpl<MCFixup> &Fixups,
329                                            const MCSubtargetInfo &STI) const {
330  const MCOperand &MO = MI.getOperand(OpIdx);
331
332  // If the destination is an immediate, we have nothing to do.
333  if (MO.isImm())
334    return MO.getImm();
335  assert(MO.isExpr() && "Unexpected target type!");
336
337  MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_ldr_pcrel_imm19);
338  Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc()));
339
340  ++MCNumFixups;
341
342  // All of the information is in the fixup.
343  return 0;
344}
345
346uint32_t
347AArch64MCCodeEmitter::getMemExtendOpValue(const MCInst &MI, unsigned OpIdx,
348                                          SmallVectorImpl<MCFixup> &Fixups,
349                                          const MCSubtargetInfo &STI) const {
350  unsigned SignExtend = MI.getOperand(OpIdx).getImm();
351  unsigned DoShift = MI.getOperand(OpIdx + 1).getImm();
352  return (SignExtend << 1) | DoShift;
353}
354
355uint32_t
356AArch64MCCodeEmitter::getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx,
357                                            SmallVectorImpl<MCFixup> &Fixups,
358                                            const MCSubtargetInfo &STI) const {
359  const MCOperand &MO = MI.getOperand(OpIdx);
360
361  if (MO.isImm())
362    return MO.getImm();
363  assert(MO.isExpr() && "Unexpected movz/movk immediate");
364
365  Fixups.push_back(MCFixup::Create(
366      0, MO.getExpr(), MCFixupKind(AArch64::fixup_aarch64_movw), MI.getLoc()));
367
368  ++MCNumFixups;
369
370  return 0;
371}
372
373/// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and-
374/// branch target.
375uint32_t AArch64MCCodeEmitter::getTestBranchTargetOpValue(
376    const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
377    const MCSubtargetInfo &STI) const {
378  const MCOperand &MO = MI.getOperand(OpIdx);
379
380  // If the destination is an immediate, we have nothing to do.
381  if (MO.isImm())
382    return MO.getImm();
383  assert(MO.isExpr() && "Unexpected ADR target type!");
384
385  MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_pcrel_branch14);
386  Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc()));
387
388  ++MCNumFixups;
389
390  // All of the information is in the fixup.
391  return 0;
392}
393
394/// getBranchTargetOpValue - Return the encoded value for an unconditional
395/// branch target.
396uint32_t
397AArch64MCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
398                                             SmallVectorImpl<MCFixup> &Fixups,
399                                             const MCSubtargetInfo &STI) const {
400  const MCOperand &MO = MI.getOperand(OpIdx);
401
402  // If the destination is an immediate, we have nothing to do.
403  if (MO.isImm())
404    return MO.getImm();
405  assert(MO.isExpr() && "Unexpected ADR target type!");
406
407  MCFixupKind Kind = MI.getOpcode() == AArch64::BL
408                         ? MCFixupKind(AArch64::fixup_aarch64_pcrel_call26)
409                         : MCFixupKind(AArch64::fixup_aarch64_pcrel_branch26);
410  Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc()));
411
412  ++MCNumFixups;
413
414  // All of the information is in the fixup.
415  return 0;
416}
417
418/// getVecShifterOpValue - Return the encoded value for the vector shifter:
419///
420///   00 -> 0
421///   01 -> 8
422///   10 -> 16
423///   11 -> 24
424uint32_t
425AArch64MCCodeEmitter::getVecShifterOpValue(const MCInst &MI, unsigned OpIdx,
426                                           SmallVectorImpl<MCFixup> &Fixups,
427                                           const MCSubtargetInfo &STI) const {
428  const MCOperand &MO = MI.getOperand(OpIdx);
429  assert(MO.isImm() && "Expected an immediate value for the shift amount!");
430
431  switch (MO.getImm()) {
432  default:
433    break;
434  case 0:
435    return 0;
436  case 8:
437    return 1;
438  case 16:
439    return 2;
440  case 24:
441    return 3;
442  }
443
444  assert(false && "Invalid value for vector shift amount!");
445  return 0;
446}
447
448uint32_t
449AArch64MCCodeEmitter::getSIMDShift64OpValue(const MCInst &MI, unsigned OpIdx,
450                                            SmallVectorImpl<MCFixup> &Fixups,
451                                            const MCSubtargetInfo &STI) const {
452  const MCOperand &MO = MI.getOperand(OpIdx);
453  assert(MO.isImm() && "Expected an immediate value for the shift amount!");
454  return 64 - (MO.getImm());
455}
456
457uint32_t AArch64MCCodeEmitter::getSIMDShift64_32OpValue(
458    const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
459    const MCSubtargetInfo &STI) const {
460  const MCOperand &MO = MI.getOperand(OpIdx);
461  assert(MO.isImm() && "Expected an immediate value for the shift amount!");
462  return 64 - (MO.getImm() | 32);
463}
464
465uint32_t
466AArch64MCCodeEmitter::getSIMDShift32OpValue(const MCInst &MI, unsigned OpIdx,
467                                            SmallVectorImpl<MCFixup> &Fixups,
468                                            const MCSubtargetInfo &STI) const {
469  const MCOperand &MO = MI.getOperand(OpIdx);
470  assert(MO.isImm() && "Expected an immediate value for the shift amount!");
471  return 32 - (MO.getImm() | 16);
472}
473
474uint32_t
475AArch64MCCodeEmitter::getSIMDShift16OpValue(const MCInst &MI, unsigned OpIdx,
476                                            SmallVectorImpl<MCFixup> &Fixups,
477                                            const MCSubtargetInfo &STI) const {
478  const MCOperand &MO = MI.getOperand(OpIdx);
479  assert(MO.isImm() && "Expected an immediate value for the shift amount!");
480  return 16 - (MO.getImm() | 8);
481}
482
483/// getFixedPointScaleOpValue - Return the encoded value for the
484// FP-to-fixed-point scale factor.
485uint32_t AArch64MCCodeEmitter::getFixedPointScaleOpValue(
486    const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
487    const MCSubtargetInfo &STI) const {
488  const MCOperand &MO = MI.getOperand(OpIdx);
489  assert(MO.isImm() && "Expected an immediate value for the scale amount!");
490  return 64 - MO.getImm();
491}
492
493uint32_t
494AArch64MCCodeEmitter::getVecShiftR64OpValue(const MCInst &MI, unsigned OpIdx,
495                                            SmallVectorImpl<MCFixup> &Fixups,
496                                            const MCSubtargetInfo &STI) const {
497  const MCOperand &MO = MI.getOperand(OpIdx);
498  assert(MO.isImm() && "Expected an immediate value for the scale amount!");
499  return 64 - MO.getImm();
500}
501
502uint32_t
503AArch64MCCodeEmitter::getVecShiftR32OpValue(const MCInst &MI, unsigned OpIdx,
504                                            SmallVectorImpl<MCFixup> &Fixups,
505                                            const MCSubtargetInfo &STI) const {
506  const MCOperand &MO = MI.getOperand(OpIdx);
507  assert(MO.isImm() && "Expected an immediate value for the scale amount!");
508  return 32 - MO.getImm();
509}
510
511uint32_t
512AArch64MCCodeEmitter::getVecShiftR16OpValue(const MCInst &MI, unsigned OpIdx,
513                                            SmallVectorImpl<MCFixup> &Fixups,
514                                            const MCSubtargetInfo &STI) const {
515  const MCOperand &MO = MI.getOperand(OpIdx);
516  assert(MO.isImm() && "Expected an immediate value for the scale amount!");
517  return 16 - MO.getImm();
518}
519
520uint32_t
521AArch64MCCodeEmitter::getVecShiftR8OpValue(const MCInst &MI, unsigned OpIdx,
522                                           SmallVectorImpl<MCFixup> &Fixups,
523                                           const MCSubtargetInfo &STI) const {
524  const MCOperand &MO = MI.getOperand(OpIdx);
525  assert(MO.isImm() && "Expected an immediate value for the scale amount!");
526  return 8 - MO.getImm();
527}
528
529uint32_t
530AArch64MCCodeEmitter::getVecShiftL64OpValue(const MCInst &MI, unsigned OpIdx,
531                                            SmallVectorImpl<MCFixup> &Fixups,
532                                            const MCSubtargetInfo &STI) const {
533  const MCOperand &MO = MI.getOperand(OpIdx);
534  assert(MO.isImm() && "Expected an immediate value for the scale amount!");
535  return MO.getImm() - 64;
536}
537
538uint32_t
539AArch64MCCodeEmitter::getVecShiftL32OpValue(const MCInst &MI, unsigned OpIdx,
540                                            SmallVectorImpl<MCFixup> &Fixups,
541                                            const MCSubtargetInfo &STI) const {
542  const MCOperand &MO = MI.getOperand(OpIdx);
543  assert(MO.isImm() && "Expected an immediate value for the scale amount!");
544  return MO.getImm() - 32;
545}
546
547uint32_t
548AArch64MCCodeEmitter::getVecShiftL16OpValue(const MCInst &MI, unsigned OpIdx,
549                                            SmallVectorImpl<MCFixup> &Fixups,
550                                            const MCSubtargetInfo &STI) const {
551  const MCOperand &MO = MI.getOperand(OpIdx);
552  assert(MO.isImm() && "Expected an immediate value for the scale amount!");
553  return MO.getImm() - 16;
554}
555
556uint32_t
557AArch64MCCodeEmitter::getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx,
558                                           SmallVectorImpl<MCFixup> &Fixups,
559                                           const MCSubtargetInfo &STI) const {
560  const MCOperand &MO = MI.getOperand(OpIdx);
561  assert(MO.isImm() && "Expected an immediate value for the scale amount!");
562  return MO.getImm() - 8;
563}
564
565/// getMoveVecShifterOpValue - Return the encoded value for the vector move
566/// shifter (MSL).
567uint32_t AArch64MCCodeEmitter::getMoveVecShifterOpValue(
568    const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
569    const MCSubtargetInfo &STI) const {
570  const MCOperand &MO = MI.getOperand(OpIdx);
571  assert(MO.isImm() &&
572         "Expected an immediate value for the move shift amount!");
573  unsigned ShiftVal = AArch64_AM::getShiftValue(MO.getImm());
574  assert((ShiftVal == 8 || ShiftVal == 16) && "Invalid shift amount!");
575  return ShiftVal == 8 ? 0 : 1;
576}
577
578unsigned AArch64MCCodeEmitter::fixMOVZ(const MCInst &MI, unsigned EncodedValue,
579                                       const MCSubtargetInfo &STI) const {
580  // If one of the signed fixup kinds is applied to a MOVZ instruction, the
581  // eventual result could be either a MOVZ or a MOVN. It's the MCCodeEmitter's
582  // job to ensure that any bits possibly affected by this are 0. This means we
583  // must zero out bit 30 (essentially emitting a MOVN).
584  MCOperand UImm16MO = MI.getOperand(1);
585
586  // Nothing to do if there's no fixup.
587  if (UImm16MO.isImm())
588    return EncodedValue;
589
590  const AArch64MCExpr *A64E = cast<AArch64MCExpr>(UImm16MO.getExpr());
591  switch (A64E->getKind()) {
592  case AArch64MCExpr::VK_DTPREL_G2:
593  case AArch64MCExpr::VK_DTPREL_G1:
594  case AArch64MCExpr::VK_DTPREL_G0:
595  case AArch64MCExpr::VK_GOTTPREL_G1:
596  case AArch64MCExpr::VK_TPREL_G2:
597  case AArch64MCExpr::VK_TPREL_G1:
598  case AArch64MCExpr::VK_TPREL_G0:
599    return EncodedValue & ~(1u << 30);
600  default:
601    // Nothing to do for an unsigned fixup.
602    return EncodedValue;
603  }
604
605
606  return EncodedValue & ~(1u << 30);
607}
608
609void AArch64MCCodeEmitter::EncodeInstruction(const MCInst &MI, raw_ostream &OS,
610                                             SmallVectorImpl<MCFixup> &Fixups,
611                                             const MCSubtargetInfo &STI) const {
612  if (MI.getOpcode() == AArch64::TLSDESCCALL) {
613    // This is a directive which applies an R_AARCH64_TLSDESC_CALL to the
614    // following (BLR) instruction. It doesn't emit any code itself so it
615    // doesn't go through the normal TableGenerated channels.
616    MCFixupKind Fixup = MCFixupKind(AArch64::fixup_aarch64_tlsdesc_call);
617    Fixups.push_back(MCFixup::Create(0, MI.getOperand(0).getExpr(), Fixup));
618    return;
619  }
620
621  uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI);
622  EmitConstant(Binary, 4, OS);
623  ++MCNumEmitted; // Keep track of the # of mi's emitted.
624}
625
626unsigned
627AArch64MCCodeEmitter::fixMulHigh(const MCInst &MI,
628                                 unsigned EncodedValue,
629                                 const MCSubtargetInfo &STI) const {
630  // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
631  // (i.e. all bits 1) but is ignored by the processor.
632  EncodedValue |= 0x1f << 10;
633  return EncodedValue;
634}
635
636template<int hasRs, int hasRt2> unsigned
637AArch64MCCodeEmitter::fixLoadStoreExclusive(const MCInst &MI,
638                                            unsigned EncodedValue,
639                                            const MCSubtargetInfo &STI) const {
640  if (!hasRs) EncodedValue |= 0x001F0000;
641  if (!hasRt2) EncodedValue |= 0x00007C00;
642
643  return EncodedValue;
644}
645
646unsigned AArch64MCCodeEmitter::fixOneOperandFPComparison(
647    const MCInst &MI, unsigned EncodedValue, const MCSubtargetInfo &STI) const {
648  // The Rm field of FCMP and friends is unused - it should be assembled
649  // as 0, but is ignored by the processor.
650  EncodedValue &= ~(0x1f << 16);
651  return EncodedValue;
652}
653
654#include "AArch64GenMCCodeEmitter.inc"
655