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