Home | History | Annotate | Download | only in MCTargetDesc
      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"
     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 AArch64MCCodeEmitter : public MCCodeEmitter {
     36   MCContext &Ctx;
     37 
     38   AArch64MCCodeEmitter(const AArch64MCCodeEmitter &); // DO NOT IMPLEMENT
     39   void operator=(const AArch64MCCodeEmitter &);     // DO NOT IMPLEMENT
     40 public:
     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 
    206 MCCodeEmitter *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.
    215 unsigned
    216 AArch64MCCodeEmitter::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 
    226 template<unsigned FixupKind> uint32_t
    227 AArch64MCCodeEmitter::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.
    247 uint32_t
    248 AArch64MCCodeEmitter::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.
    273 uint32_t
    274 AArch64MCCodeEmitter::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.
    301 uint32_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.
    322 uint32_t
    323 AArch64MCCodeEmitter::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 
    342 uint32_t
    343 AArch64MCCodeEmitter::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 
    351 uint32_t
    352 AArch64MCCodeEmitter::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.
    371 uint32_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.
    392 uint32_t
    393 AArch64MCCodeEmitter::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
    420 uint32_t
    421 AArch64MCCodeEmitter::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 
    444 uint32_t
    445 AArch64MCCodeEmitter::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 
    453 uint32_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 
    461 uint32_t
    462 AArch64MCCodeEmitter::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 
    470 uint32_t
    471 AArch64MCCodeEmitter::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.
    481 uint32_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 
    489 uint32_t
    490 AArch64MCCodeEmitter::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 
    498 uint32_t
    499 AArch64MCCodeEmitter::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 
    507 uint32_t
    508 AArch64MCCodeEmitter::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 
    516 uint32_t
    517 AArch64MCCodeEmitter::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 
    525 uint32_t
    526 AArch64MCCodeEmitter::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 
    534 uint32_t
    535 AArch64MCCodeEmitter::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 
    543 uint32_t
    544 AArch64MCCodeEmitter::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 
    552 uint32_t
    553 AArch64MCCodeEmitter::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).
    563 uint32_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 
    574 unsigned 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 
    605 void 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 
    622 unsigned
    623 AArch64MCCodeEmitter::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 
    632 template<int hasRs, int hasRt2> unsigned
    633 AArch64MCCodeEmitter::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 
    642 unsigned 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