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