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