LCOV - code coverage report
Current view: top level - lib/Target/AArch64/MCTargetDesc - AArch64MCCodeEmitter.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 94 95 98.9 %
Date: 2018-07-13 00:08:38 Functions: 16 17 94.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13