LLVM API Documentation

AArch64MCCodeEmitter.cpp
Go to the documentation of this file.
00001 //=- AArch64/AArch64MCCodeEmitter.cpp - Convert AArch64 code to machine code-=//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements the AArch64MCCodeEmitter class.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "MCTargetDesc/AArch64AddressingModes.h"
00015 #include "MCTargetDesc/AArch64FixupKinds.h"
00016 #include "MCTargetDesc/AArch64MCExpr.h"
00017 #include "Utils/AArch64BaseInfo.h"
00018 #include "llvm/ADT/Statistic.h"
00019 #include "llvm/MC/MCCodeEmitter.h"
00020 #include "llvm/MC/MCContext.h"
00021 #include "llvm/MC/MCInst.h"
00022 #include "llvm/MC/MCInstrInfo.h"
00023 #include "llvm/MC/MCRegisterInfo.h"
00024 #include "llvm/MC/MCSubtargetInfo.h"
00025 #include "llvm/Support/raw_ostream.h"
00026 using namespace llvm;
00027 
00028 #define DEBUG_TYPE "mccodeemitter"
00029 
00030 STATISTIC(MCNumEmitted, "Number of MC instructions emitted.");
00031 STATISTIC(MCNumFixups, "Number of MC fixups created.");
00032 
00033 namespace {
00034 
00035 class AArch64MCCodeEmitter : public MCCodeEmitter {
00036   MCContext &Ctx;
00037 
00038   AArch64MCCodeEmitter(const AArch64MCCodeEmitter &); // DO NOT IMPLEMENT
00039   void operator=(const AArch64MCCodeEmitter &);     // DO NOT IMPLEMENT
00040 public:
00041   AArch64MCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
00042                      MCContext &ctx)
00043       : Ctx(ctx) {}
00044 
00045   ~AArch64MCCodeEmitter() {}
00046 
00047   // getBinaryCodeForInstr - TableGen'erated function for getting the
00048   // binary encoding for an instruction.
00049   uint64_t getBinaryCodeForInstr(const MCInst &MI,
00050                                  SmallVectorImpl<MCFixup> &Fixups,
00051                                  const MCSubtargetInfo &STI) const;
00052 
00053   /// getMachineOpValue - Return binary encoding of operand. If the machine
00054   /// operand requires relocation, record the relocation and return zero.
00055   unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
00056                              SmallVectorImpl<MCFixup> &Fixups,
00057                              const MCSubtargetInfo &STI) const;
00058 
00059   /// getLdStUImm12OpValue - Return encoding info for 12-bit unsigned immediate
00060   /// attached to a load, store or prfm instruction. If operand requires a
00061   /// relocation, record it and return zero in that part of the encoding.
00062   template <uint32_t FixupKind>
00063   uint32_t getLdStUImm12OpValue(const MCInst &MI, unsigned OpIdx,
00064                                 SmallVectorImpl<MCFixup> &Fixups,
00065                                 const MCSubtargetInfo &STI) const;
00066 
00067   /// getAdrLabelOpValue - Return encoding info for 21-bit immediate ADR label
00068   /// target.
00069   uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
00070                               SmallVectorImpl<MCFixup> &Fixups,
00071                               const MCSubtargetInfo &STI) const;
00072 
00073   /// getAddSubImmOpValue - Return encoding for the 12-bit immediate value and
00074   /// the 2-bit shift field.
00075   uint32_t getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx,
00076                                SmallVectorImpl<MCFixup> &Fixups,
00077                                const MCSubtargetInfo &STI) const;
00078 
00079   /// getCondBranchTargetOpValue - Return the encoded value for a conditional
00080   /// branch target.
00081   uint32_t getCondBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
00082                                       SmallVectorImpl<MCFixup> &Fixups,
00083                                       const MCSubtargetInfo &STI) const;
00084 
00085   /// getLoadLiteralOpValue - Return the encoded value for a load-literal
00086   /// pc-relative address.
00087   uint32_t getLoadLiteralOpValue(const MCInst &MI, unsigned OpIdx,
00088                                  SmallVectorImpl<MCFixup> &Fixups,
00089                                  const MCSubtargetInfo &STI) const;
00090 
00091   /// getMemExtendOpValue - Return the encoded value for a reg-extend load/store
00092   /// instruction: bit 0 is whether a shift is present, bit 1 is whether the
00093   /// operation is a sign extend (as opposed to a zero extend).
00094   uint32_t getMemExtendOpValue(const MCInst &MI, unsigned OpIdx,
00095                                SmallVectorImpl<MCFixup> &Fixups,
00096                                const MCSubtargetInfo &STI) const;
00097 
00098   /// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and-
00099   /// branch target.
00100   uint32_t getTestBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
00101                                       SmallVectorImpl<MCFixup> &Fixups,
00102                                       const MCSubtargetInfo &STI) const;
00103 
00104   /// getBranchTargetOpValue - Return the encoded value for an unconditional
00105   /// branch target.
00106   uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
00107                                   SmallVectorImpl<MCFixup> &Fixups,
00108                                   const MCSubtargetInfo &STI) const;
00109 
00110   /// getMoveWideImmOpValue - Return the encoded value for the immediate operand
00111   /// of a MOVZ or MOVK instruction.
00112   uint32_t getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx,
00113                                  SmallVectorImpl<MCFixup> &Fixups,
00114                                  const MCSubtargetInfo &STI) const;
00115 
00116   /// getVecShifterOpValue - Return the encoded value for the vector shifter.
00117   uint32_t getVecShifterOpValue(const MCInst &MI, unsigned OpIdx,
00118                                 SmallVectorImpl<MCFixup> &Fixups,
00119                                 const MCSubtargetInfo &STI) const;
00120 
00121   /// getMoveVecShifterOpValue - Return the encoded value for the vector move
00122   /// shifter (MSL).
00123   uint32_t getMoveVecShifterOpValue(const MCInst &MI, unsigned OpIdx,
00124                                     SmallVectorImpl<MCFixup> &Fixups,
00125                                     const MCSubtargetInfo &STI) const;
00126 
00127   /// getFixedPointScaleOpValue - Return the encoded value for the
00128   // FP-to-fixed-point scale factor.
00129   uint32_t getFixedPointScaleOpValue(const MCInst &MI, unsigned OpIdx,
00130                                      SmallVectorImpl<MCFixup> &Fixups,
00131                                      const MCSubtargetInfo &STI) const;
00132 
00133   uint32_t getVecShiftR64OpValue(const MCInst &MI, unsigned OpIdx,
00134                                  SmallVectorImpl<MCFixup> &Fixups,
00135                                  const MCSubtargetInfo &STI) const;
00136   uint32_t getVecShiftR32OpValue(const MCInst &MI, unsigned OpIdx,
00137                                  SmallVectorImpl<MCFixup> &Fixups,
00138                                  const MCSubtargetInfo &STI) const;
00139   uint32_t getVecShiftR16OpValue(const MCInst &MI, unsigned OpIdx,
00140                                  SmallVectorImpl<MCFixup> &Fixups,
00141                                  const MCSubtargetInfo &STI) const;
00142   uint32_t getVecShiftR8OpValue(const MCInst &MI, unsigned OpIdx,
00143                                 SmallVectorImpl<MCFixup> &Fixups,
00144                                 const MCSubtargetInfo &STI) const;
00145   uint32_t getVecShiftL64OpValue(const MCInst &MI, unsigned OpIdx,
00146                                  SmallVectorImpl<MCFixup> &Fixups,
00147                                  const MCSubtargetInfo &STI) const;
00148   uint32_t getVecShiftL32OpValue(const MCInst &MI, unsigned OpIdx,
00149                                  SmallVectorImpl<MCFixup> &Fixups,
00150                                  const MCSubtargetInfo &STI) const;
00151   uint32_t getVecShiftL16OpValue(const MCInst &MI, unsigned OpIdx,
00152                                  SmallVectorImpl<MCFixup> &Fixups,
00153                                  const MCSubtargetInfo &STI) const;
00154   uint32_t getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx,
00155                                 SmallVectorImpl<MCFixup> &Fixups,
00156                                 const MCSubtargetInfo &STI) const;
00157 
00158   /// getSIMDShift64OpValue - Return the encoded value for the
00159   // shift-by-immediate AdvSIMD instructions.
00160   uint32_t getSIMDShift64OpValue(const MCInst &MI, unsigned OpIdx,
00161                                  SmallVectorImpl<MCFixup> &Fixups,
00162                                  const MCSubtargetInfo &STI) const;
00163 
00164   uint32_t getSIMDShift64_32OpValue(const MCInst &MI, unsigned OpIdx,
00165                                     SmallVectorImpl<MCFixup> &Fixups,
00166                                     const MCSubtargetInfo &STI) const;
00167 
00168   uint32_t getSIMDShift32OpValue(const MCInst &MI, unsigned OpIdx,
00169                                  SmallVectorImpl<MCFixup> &Fixups,
00170                                  const MCSubtargetInfo &STI) const;
00171 
00172   uint32_t getSIMDShift16OpValue(const MCInst &MI, unsigned OpIdx,
00173                                  SmallVectorImpl<MCFixup> &Fixups,
00174                                  const MCSubtargetInfo &STI) const;
00175 
00176   unsigned fixMOVZ(const MCInst &MI, unsigned EncodedValue,
00177                    const MCSubtargetInfo &STI) const;
00178 
00179   void EmitByte(unsigned char C, raw_ostream &OS) const { OS << (char)C; }
00180 
00181   void EmitConstant(uint64_t Val, unsigned Size, raw_ostream &OS) const {
00182     // Output the constant in little endian byte order.
00183     for (unsigned i = 0; i != Size; ++i) {
00184       EmitByte(Val & 255, OS);
00185       Val >>= 8;
00186     }
00187   }
00188 
00189   void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
00190                          SmallVectorImpl<MCFixup> &Fixups,
00191                          const MCSubtargetInfo &STI) const override;
00192 
00193   unsigned fixMulHigh(const MCInst &MI, unsigned EncodedValue,
00194                       const MCSubtargetInfo &STI) const;
00195 
00196   template<int hasRs, int hasRt2> unsigned
00197   fixLoadStoreExclusive(const MCInst &MI, unsigned EncodedValue,
00198                         const MCSubtargetInfo &STI) const;
00199 
00200   unsigned fixOneOperandFPComparison(const MCInst &MI, unsigned EncodedValue,
00201                                      const MCSubtargetInfo &STI) const;
00202 };
00203 
00204 } // end anonymous namespace
00205 
00206 MCCodeEmitter *llvm::createAArch64MCCodeEmitter(const MCInstrInfo &MCII,
00207                                                 const MCRegisterInfo &MRI,
00208                                                 const MCSubtargetInfo &STI,
00209                                                 MCContext &Ctx) {
00210   return new AArch64MCCodeEmitter(MCII, STI, Ctx);
00211 }
00212 
00213 /// getMachineOpValue - Return binary encoding of operand. If the machine
00214 /// operand requires relocation, record the relocation and return zero.
00215 unsigned
00216 AArch64MCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
00217                                         SmallVectorImpl<MCFixup> &Fixups,
00218                                         const MCSubtargetInfo &STI) const {
00219   if (MO.isReg())
00220     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
00221 
00222   assert(MO.isImm() && "did not expect relocated expression");
00223   return static_cast<unsigned>(MO.getImm());
00224 }
00225 
00226 template<unsigned FixupKind> uint32_t
00227 AArch64MCCodeEmitter::getLdStUImm12OpValue(const MCInst &MI, unsigned OpIdx,
00228                                            SmallVectorImpl<MCFixup> &Fixups,
00229                                            const MCSubtargetInfo &STI) const {
00230   const MCOperand &MO = MI.getOperand(OpIdx);
00231   uint32_t ImmVal = 0;
00232 
00233   if (MO.isImm())
00234     ImmVal = static_cast<uint32_t>(MO.getImm());
00235   else {
00236     assert(MO.isExpr() && "unable to encode load/store imm operand");
00237     MCFixupKind Kind = MCFixupKind(FixupKind);
00238     Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc()));
00239     ++MCNumFixups;
00240   }
00241 
00242   return ImmVal;
00243 }
00244 
00245 /// getAdrLabelOpValue - Return encoding info for 21-bit immediate ADR label
00246 /// target.
00247 uint32_t
00248 AArch64MCCodeEmitter::getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
00249                                          SmallVectorImpl<MCFixup> &Fixups,
00250                                          const MCSubtargetInfo &STI) const {
00251   const MCOperand &MO = MI.getOperand(OpIdx);
00252 
00253   // If the destination is an immediate, we have nothing to do.
00254   if (MO.isImm())
00255     return MO.getImm();
00256   assert(MO.isExpr() && "Unexpected target type!");
00257   const MCExpr *Expr = MO.getExpr();
00258 
00259   MCFixupKind Kind = MI.getOpcode() == AArch64::ADR
00260                          ? MCFixupKind(AArch64::fixup_aarch64_pcrel_adr_imm21)
00261                          : MCFixupKind(AArch64::fixup_aarch64_pcrel_adrp_imm21);
00262   Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc()));
00263 
00264   MCNumFixups += 1;
00265 
00266   // All of the information is in the fixup.
00267   return 0;
00268 }
00269 
00270 /// getAddSubImmOpValue - Return encoding for the 12-bit immediate value and
00271 /// the 2-bit shift field.  The shift field is stored in bits 13-14 of the
00272 /// return value.
00273 uint32_t
00274 AArch64MCCodeEmitter::getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx,
00275                                           SmallVectorImpl<MCFixup> &Fixups,
00276                                           const MCSubtargetInfo &STI) const {
00277   // Suboperands are [imm, shifter].
00278   const MCOperand &MO = MI.getOperand(OpIdx);
00279   const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
00280   assert(AArch64_AM::getShiftType(MO1.getImm()) == AArch64_AM::LSL &&
00281          "unexpected shift type for add/sub immediate");
00282   unsigned ShiftVal = AArch64_AM::getShiftValue(MO1.getImm());
00283   assert((ShiftVal == 0 || ShiftVal == 12) &&
00284          "unexpected shift value for add/sub immediate");
00285   if (MO.isImm())
00286     return MO.getImm() | (ShiftVal == 0 ? 0 : (1 << 12));
00287   assert(MO.isExpr() && "Unable to encode MCOperand!");
00288   const MCExpr *Expr = MO.getExpr();
00289 
00290   // Encode the 12 bits of the fixup.
00291   MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_add_imm12);
00292   Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc()));
00293 
00294   ++MCNumFixups;
00295 
00296   return 0;
00297 }
00298 
00299 /// getCondBranchTargetOpValue - Return the encoded value for a conditional
00300 /// branch target.
00301 uint32_t AArch64MCCodeEmitter::getCondBranchTargetOpValue(
00302     const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
00303     const MCSubtargetInfo &STI) const {
00304   const MCOperand &MO = MI.getOperand(OpIdx);
00305 
00306   // If the destination is an immediate, we have nothing to do.
00307   if (MO.isImm())
00308     return MO.getImm();
00309   assert(MO.isExpr() && "Unexpected target type!");
00310 
00311   MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_pcrel_branch19);
00312   Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc()));
00313 
00314   ++MCNumFixups;
00315 
00316   // All of the information is in the fixup.
00317   return 0;
00318 }
00319 
00320 /// getLoadLiteralOpValue - Return the encoded value for a load-literal
00321 /// pc-relative address.
00322 uint32_t
00323 AArch64MCCodeEmitter::getLoadLiteralOpValue(const MCInst &MI, unsigned OpIdx,
00324                                             SmallVectorImpl<MCFixup> &Fixups,
00325                                             const MCSubtargetInfo &STI) const {
00326   const MCOperand &MO = MI.getOperand(OpIdx);
00327 
00328   // If the destination is an immediate, we have nothing to do.
00329   if (MO.isImm())
00330     return MO.getImm();
00331   assert(MO.isExpr() && "Unexpected target type!");
00332 
00333   MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_ldr_pcrel_imm19);
00334   Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc()));
00335 
00336   ++MCNumFixups;
00337 
00338   // All of the information is in the fixup.
00339   return 0;
00340 }
00341 
00342 uint32_t
00343 AArch64MCCodeEmitter::getMemExtendOpValue(const MCInst &MI, unsigned OpIdx,
00344                                           SmallVectorImpl<MCFixup> &Fixups,
00345                                           const MCSubtargetInfo &STI) const {
00346   unsigned SignExtend = MI.getOperand(OpIdx).getImm();
00347   unsigned DoShift = MI.getOperand(OpIdx + 1).getImm();
00348   return (SignExtend << 1) | DoShift;
00349 }
00350 
00351 uint32_t
00352 AArch64MCCodeEmitter::getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx,
00353                                             SmallVectorImpl<MCFixup> &Fixups,
00354                                             const MCSubtargetInfo &STI) const {
00355   const MCOperand &MO = MI.getOperand(OpIdx);
00356 
00357   if (MO.isImm())
00358     return MO.getImm();
00359   assert(MO.isExpr() && "Unexpected movz/movk immediate");
00360 
00361   Fixups.push_back(MCFixup::Create(
00362       0, MO.getExpr(), MCFixupKind(AArch64::fixup_aarch64_movw), MI.getLoc()));
00363 
00364   ++MCNumFixups;
00365 
00366   return 0;
00367 }
00368 
00369 /// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and-
00370 /// branch target.
00371 uint32_t AArch64MCCodeEmitter::getTestBranchTargetOpValue(
00372     const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
00373     const MCSubtargetInfo &STI) const {
00374   const MCOperand &MO = MI.getOperand(OpIdx);
00375 
00376   // If the destination is an immediate, we have nothing to do.
00377   if (MO.isImm())
00378     return MO.getImm();
00379   assert(MO.isExpr() && "Unexpected ADR target type!");
00380 
00381   MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_pcrel_branch14);
00382   Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc()));
00383 
00384   ++MCNumFixups;
00385 
00386   // All of the information is in the fixup.
00387   return 0;
00388 }
00389 
00390 /// getBranchTargetOpValue - Return the encoded value for an unconditional
00391 /// branch target.
00392 uint32_t
00393 AArch64MCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
00394                                              SmallVectorImpl<MCFixup> &Fixups,
00395                                              const MCSubtargetInfo &STI) const {
00396   const MCOperand &MO = MI.getOperand(OpIdx);
00397 
00398   // If the destination is an immediate, we have nothing to do.
00399   if (MO.isImm())
00400     return MO.getImm();
00401   assert(MO.isExpr() && "Unexpected ADR target type!");
00402 
00403   MCFixupKind Kind = MI.getOpcode() == AArch64::BL
00404                          ? MCFixupKind(AArch64::fixup_aarch64_pcrel_call26)
00405                          : MCFixupKind(AArch64::fixup_aarch64_pcrel_branch26);
00406   Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc()));
00407 
00408   ++MCNumFixups;
00409 
00410   // All of the information is in the fixup.
00411   return 0;
00412 }
00413 
00414 /// getVecShifterOpValue - Return the encoded value for the vector shifter:
00415 ///
00416 ///   00 -> 0
00417 ///   01 -> 8
00418 ///   10 -> 16
00419 ///   11 -> 24
00420 uint32_t
00421 AArch64MCCodeEmitter::getVecShifterOpValue(const MCInst &MI, unsigned OpIdx,
00422                                            SmallVectorImpl<MCFixup> &Fixups,
00423                                            const MCSubtargetInfo &STI) const {
00424   const MCOperand &MO = MI.getOperand(OpIdx);
00425   assert(MO.isImm() && "Expected an immediate value for the shift amount!");
00426 
00427   switch (MO.getImm()) {
00428   default:
00429     break;
00430   case 0:
00431     return 0;
00432   case 8:
00433     return 1;
00434   case 16:
00435     return 2;
00436   case 24:
00437     return 3;
00438   }
00439 
00440   assert(false && "Invalid value for vector shift amount!");
00441   return 0;
00442 }
00443 
00444 uint32_t
00445 AArch64MCCodeEmitter::getSIMDShift64OpValue(const MCInst &MI, unsigned OpIdx,
00446                                             SmallVectorImpl<MCFixup> &Fixups,
00447                                             const MCSubtargetInfo &STI) const {
00448   const MCOperand &MO = MI.getOperand(OpIdx);
00449   assert(MO.isImm() && "Expected an immediate value for the shift amount!");
00450   return 64 - (MO.getImm());
00451 }
00452 
00453 uint32_t AArch64MCCodeEmitter::getSIMDShift64_32OpValue(
00454     const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
00455     const MCSubtargetInfo &STI) const {
00456   const MCOperand &MO = MI.getOperand(OpIdx);
00457   assert(MO.isImm() && "Expected an immediate value for the shift amount!");
00458   return 64 - (MO.getImm() | 32);
00459 }
00460 
00461 uint32_t
00462 AArch64MCCodeEmitter::getSIMDShift32OpValue(const MCInst &MI, unsigned OpIdx,
00463                                             SmallVectorImpl<MCFixup> &Fixups,
00464                                             const MCSubtargetInfo &STI) const {
00465   const MCOperand &MO = MI.getOperand(OpIdx);
00466   assert(MO.isImm() && "Expected an immediate value for the shift amount!");
00467   return 32 - (MO.getImm() | 16);
00468 }
00469 
00470 uint32_t
00471 AArch64MCCodeEmitter::getSIMDShift16OpValue(const MCInst &MI, unsigned OpIdx,
00472                                             SmallVectorImpl<MCFixup> &Fixups,
00473                                             const MCSubtargetInfo &STI) const {
00474   const MCOperand &MO = MI.getOperand(OpIdx);
00475   assert(MO.isImm() && "Expected an immediate value for the shift amount!");
00476   return 16 - (MO.getImm() | 8);
00477 }
00478 
00479 /// getFixedPointScaleOpValue - Return the encoded value for the
00480 // FP-to-fixed-point scale factor.
00481 uint32_t AArch64MCCodeEmitter::getFixedPointScaleOpValue(
00482     const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
00483     const MCSubtargetInfo &STI) const {
00484   const MCOperand &MO = MI.getOperand(OpIdx);
00485   assert(MO.isImm() && "Expected an immediate value for the scale amount!");
00486   return 64 - MO.getImm();
00487 }
00488 
00489 uint32_t
00490 AArch64MCCodeEmitter::getVecShiftR64OpValue(const MCInst &MI, unsigned OpIdx,
00491                                             SmallVectorImpl<MCFixup> &Fixups,
00492                                             const MCSubtargetInfo &STI) const {
00493   const MCOperand &MO = MI.getOperand(OpIdx);
00494   assert(MO.isImm() && "Expected an immediate value for the scale amount!");
00495   return 64 - MO.getImm();
00496 }
00497 
00498 uint32_t
00499 AArch64MCCodeEmitter::getVecShiftR32OpValue(const MCInst &MI, unsigned OpIdx,
00500                                             SmallVectorImpl<MCFixup> &Fixups,
00501                                             const MCSubtargetInfo &STI) const {
00502   const MCOperand &MO = MI.getOperand(OpIdx);
00503   assert(MO.isImm() && "Expected an immediate value for the scale amount!");
00504   return 32 - MO.getImm();
00505 }
00506 
00507 uint32_t
00508 AArch64MCCodeEmitter::getVecShiftR16OpValue(const MCInst &MI, unsigned OpIdx,
00509                                             SmallVectorImpl<MCFixup> &Fixups,
00510                                             const MCSubtargetInfo &STI) const {
00511   const MCOperand &MO = MI.getOperand(OpIdx);
00512   assert(MO.isImm() && "Expected an immediate value for the scale amount!");
00513   return 16 - MO.getImm();
00514 }
00515 
00516 uint32_t
00517 AArch64MCCodeEmitter::getVecShiftR8OpValue(const MCInst &MI, unsigned OpIdx,
00518                                            SmallVectorImpl<MCFixup> &Fixups,
00519                                            const MCSubtargetInfo &STI) const {
00520   const MCOperand &MO = MI.getOperand(OpIdx);
00521   assert(MO.isImm() && "Expected an immediate value for the scale amount!");
00522   return 8 - MO.getImm();
00523 }
00524 
00525 uint32_t
00526 AArch64MCCodeEmitter::getVecShiftL64OpValue(const MCInst &MI, unsigned OpIdx,
00527                                             SmallVectorImpl<MCFixup> &Fixups,
00528                                             const MCSubtargetInfo &STI) const {
00529   const MCOperand &MO = MI.getOperand(OpIdx);
00530   assert(MO.isImm() && "Expected an immediate value for the scale amount!");
00531   return MO.getImm() - 64;
00532 }
00533 
00534 uint32_t
00535 AArch64MCCodeEmitter::getVecShiftL32OpValue(const MCInst &MI, unsigned OpIdx,
00536                                             SmallVectorImpl<MCFixup> &Fixups,
00537                                             const MCSubtargetInfo &STI) const {
00538   const MCOperand &MO = MI.getOperand(OpIdx);
00539   assert(MO.isImm() && "Expected an immediate value for the scale amount!");
00540   return MO.getImm() - 32;
00541 }
00542 
00543 uint32_t
00544 AArch64MCCodeEmitter::getVecShiftL16OpValue(const MCInst &MI, unsigned OpIdx,
00545                                             SmallVectorImpl<MCFixup> &Fixups,
00546                                             const MCSubtargetInfo &STI) const {
00547   const MCOperand &MO = MI.getOperand(OpIdx);
00548   assert(MO.isImm() && "Expected an immediate value for the scale amount!");
00549   return MO.getImm() - 16;
00550 }
00551 
00552 uint32_t
00553 AArch64MCCodeEmitter::getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx,
00554                                            SmallVectorImpl<MCFixup> &Fixups,
00555                                            const MCSubtargetInfo &STI) const {
00556   const MCOperand &MO = MI.getOperand(OpIdx);
00557   assert(MO.isImm() && "Expected an immediate value for the scale amount!");
00558   return MO.getImm() - 8;
00559 }
00560 
00561 /// getMoveVecShifterOpValue - Return the encoded value for the vector move
00562 /// shifter (MSL).
00563 uint32_t AArch64MCCodeEmitter::getMoveVecShifterOpValue(
00564     const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
00565     const MCSubtargetInfo &STI) const {
00566   const MCOperand &MO = MI.getOperand(OpIdx);
00567   assert(MO.isImm() &&
00568          "Expected an immediate value for the move shift amount!");
00569   unsigned ShiftVal = AArch64_AM::getShiftValue(MO.getImm());
00570   assert((ShiftVal == 8 || ShiftVal == 16) && "Invalid shift amount!");
00571   return ShiftVal == 8 ? 0 : 1;
00572 }
00573 
00574 unsigned AArch64MCCodeEmitter::fixMOVZ(const MCInst &MI, unsigned EncodedValue,
00575                                        const MCSubtargetInfo &STI) const {
00576   // If one of the signed fixup kinds is applied to a MOVZ instruction, the
00577   // eventual result could be either a MOVZ or a MOVN. It's the MCCodeEmitter's
00578   // job to ensure that any bits possibly affected by this are 0. This means we
00579   // must zero out bit 30 (essentially emitting a MOVN).
00580   MCOperand UImm16MO = MI.getOperand(1);
00581 
00582   // Nothing to do if there's no fixup.
00583   if (UImm16MO.isImm())
00584     return EncodedValue;
00585 
00586   const AArch64MCExpr *A64E = cast<AArch64MCExpr>(UImm16MO.getExpr());
00587   switch (A64E->getKind()) {
00588   case AArch64MCExpr::VK_DTPREL_G2:
00589   case AArch64MCExpr::VK_DTPREL_G1:
00590   case AArch64MCExpr::VK_DTPREL_G0:
00591   case AArch64MCExpr::VK_GOTTPREL_G1:
00592   case AArch64MCExpr::VK_TPREL_G2:
00593   case AArch64MCExpr::VK_TPREL_G1:
00594   case AArch64MCExpr::VK_TPREL_G0:
00595     return EncodedValue & ~(1u << 30);
00596   default:
00597     // Nothing to do for an unsigned fixup.
00598     return EncodedValue;
00599   }
00600 
00601 
00602   return EncodedValue & ~(1u << 30);
00603 }
00604 
00605 void AArch64MCCodeEmitter::EncodeInstruction(const MCInst &MI, raw_ostream &OS,
00606                                              SmallVectorImpl<MCFixup> &Fixups,
00607                                              const MCSubtargetInfo &STI) const {
00608   if (MI.getOpcode() == AArch64::TLSDESCCALL) {
00609     // This is a directive which applies an R_AARCH64_TLSDESC_CALL to the
00610     // following (BLR) instruction. It doesn't emit any code itself so it
00611     // doesn't go through the normal TableGenerated channels.
00612     MCFixupKind Fixup = MCFixupKind(AArch64::fixup_aarch64_tlsdesc_call);
00613     Fixups.push_back(MCFixup::Create(0, MI.getOperand(0).getExpr(), Fixup));
00614     return;
00615   }
00616 
00617   uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI);
00618   EmitConstant(Binary, 4, OS);
00619   ++MCNumEmitted; // Keep track of the # of mi's emitted.
00620 }
00621 
00622 unsigned
00623 AArch64MCCodeEmitter::fixMulHigh(const MCInst &MI,
00624                                  unsigned EncodedValue,
00625                                  const MCSubtargetInfo &STI) const {
00626   // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
00627   // (i.e. all bits 1) but is ignored by the processor.
00628   EncodedValue |= 0x1f << 10;
00629   return EncodedValue;
00630 }
00631 
00632 template<int hasRs, int hasRt2> unsigned
00633 AArch64MCCodeEmitter::fixLoadStoreExclusive(const MCInst &MI,
00634                                             unsigned EncodedValue,
00635                                             const MCSubtargetInfo &STI) const {
00636   if (!hasRs) EncodedValue |= 0x001F0000;
00637   if (!hasRt2) EncodedValue |= 0x00007C00;
00638 
00639   return EncodedValue;
00640 }
00641 
00642 unsigned AArch64MCCodeEmitter::fixOneOperandFPComparison(
00643     const MCInst &MI, unsigned EncodedValue, const MCSubtargetInfo &STI) const {
00644   // The Rm field of FCMP and friends is unused - it should be assembled
00645   // as 0, but is ignored by the processor.
00646   EncodedValue &= ~(0x1f << 16);
00647   return EncodedValue;
00648 }
00649 
00650 #include "AArch64GenMCCodeEmitter.inc"