brintos

brintos / llvm-project-archived public Read only

0
0
Text · 31.9 KiB · 21ff55e Raw
785 lines · cpp
1//=- AArch64/AArch64MCCodeEmitter.cpp - Convert AArch64 code to machine code-=//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the AArch64MCCodeEmitter class.10//11//===----------------------------------------------------------------------===//12 13#include "MCTargetDesc/AArch64AddressingModes.h"14#include "MCTargetDesc/AArch64FixupKinds.h"15#include "MCTargetDesc/AArch64MCAsmInfo.h"16#include "llvm/ADT/SmallVector.h"17#include "llvm/ADT/Statistic.h"18#include "llvm/BinaryFormat/ELF.h"19#include "llvm/MC/MCCodeEmitter.h"20#include "llvm/MC/MCContext.h"21#include "llvm/MC/MCFixup.h"22#include "llvm/MC/MCInst.h"23#include "llvm/MC/MCInstrInfo.h"24#include "llvm/MC/MCRegisterInfo.h"25#include "llvm/MC/MCSubtargetInfo.h"26#include "llvm/Support/Casting.h"27#include "llvm/Support/EndianStream.h"28#include <cassert>29#include <cstdint>30 31using namespace llvm;32 33#define DEBUG_TYPE "mccodeemitter"34 35STATISTIC(MCNumEmitted, "Number of MC instructions emitted.");36STATISTIC(MCNumFixups, "Number of MC fixups created.");37 38namespace {39 40class AArch64MCCodeEmitter : public MCCodeEmitter {41  MCContext &Ctx;42 43public:44  AArch64MCCodeEmitter(const MCInstrInfo &, MCContext &ctx) : Ctx(ctx) {}45  AArch64MCCodeEmitter(const AArch64MCCodeEmitter &) = delete;46  void operator=(const AArch64MCCodeEmitter &) = delete;47  ~AArch64MCCodeEmitter() override = default;48 49  // getBinaryCodeForInstr - TableGen'erated function for getting the50  // binary encoding for an instruction.51  uint64_t getBinaryCodeForInstr(const MCInst &MI,52                                 SmallVectorImpl<MCFixup> &Fixups,53                                 const MCSubtargetInfo &STI) const;54 55  /// getMachineOpValue - Return binary encoding of operand. If the machine56  /// operand requires relocation, record the relocation and return zero.57  unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,58                             SmallVectorImpl<MCFixup> &Fixups,59                             const MCSubtargetInfo &STI) const;60 61  /// getLdStUImm12OpValue - Return encoding info for 12-bit unsigned immediate62  /// attached to a load, store or prfm instruction. If operand requires a63  /// relocation, record it and return zero in that part of the encoding.64  template <uint32_t FixupKind>65  uint32_t getLdStUImm12OpValue(const MCInst &MI, unsigned OpIdx,66                                SmallVectorImpl<MCFixup> &Fixups,67                                const MCSubtargetInfo &STI) const;68 69  /// getAdrLabelOpValue - Return encoding info for 21-bit immediate ADR label70  /// target.71  uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,72                              SmallVectorImpl<MCFixup> &Fixups,73                              const MCSubtargetInfo &STI) const;74 75  /// getAddSubImmOpValue - Return encoding for the 12-bit immediate value and76  /// the 2-bit shift field.77  uint32_t getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx,78                               SmallVectorImpl<MCFixup> &Fixups,79                               const MCSubtargetInfo &STI) const;80 81  /// getCondBranchTargetOpValue - Return the encoded value for a conditional82  /// branch target.83  uint32_t getCondBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,84                                      SmallVectorImpl<MCFixup> &Fixups,85                                      const MCSubtargetInfo &STI) const;86 87  /// getCondCompBranchTargetOpValue - Return the encoded value for a88  /// conditional compare-and-branch target.89  uint32_t getCondCompBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,90                                          SmallVectorImpl<MCFixup> &Fixups,91                                          const MCSubtargetInfo &STI) const;92 93  /// getPAuthPCRelOpValue - Return the encoded value for a pointer94  /// authentication pc-relative operand.95  uint32_t getPAuthPCRelOpValue(const MCInst &MI, unsigned OpIdx,96                                SmallVectorImpl<MCFixup> &Fixups,97                                const MCSubtargetInfo &STI) const;98 99  /// getLoadLiteralOpValue - Return the encoded value for a load-literal100  /// pc-relative address.101  uint32_t getLoadLiteralOpValue(const MCInst &MI, unsigned OpIdx,102                                 SmallVectorImpl<MCFixup> &Fixups,103                                 const MCSubtargetInfo &STI) const;104 105  /// getMemExtendOpValue - Return the encoded value for a reg-extend load/store106  /// instruction: bit 0 is whether a shift is present, bit 1 is whether the107  /// operation is a sign extend (as opposed to a zero extend).108  uint32_t getMemExtendOpValue(const MCInst &MI, unsigned OpIdx,109                               SmallVectorImpl<MCFixup> &Fixups,110                               const MCSubtargetInfo &STI) const;111 112  /// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and-113  /// branch target.114  uint32_t getTestBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,115                                      SmallVectorImpl<MCFixup> &Fixups,116                                      const MCSubtargetInfo &STI) const;117 118  /// getBranchTargetOpValue - Return the encoded value for an unconditional119  /// branch target.120  uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,121                                  SmallVectorImpl<MCFixup> &Fixups,122                                  const MCSubtargetInfo &STI) const;123 124  /// getMoveWideImmOpValue - Return the encoded value for the immediate operand125  /// of a MOVZ or MOVK instruction.126  uint32_t getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx,127                                 SmallVectorImpl<MCFixup> &Fixups,128                                 const MCSubtargetInfo &STI) const;129 130  /// getVecShifterOpValue - Return the encoded value for the vector shifter.131  uint32_t getVecShifterOpValue(const MCInst &MI, unsigned OpIdx,132                                SmallVectorImpl<MCFixup> &Fixups,133                                const MCSubtargetInfo &STI) const;134 135  /// getMoveVecShifterOpValue - Return the encoded value for the vector move136  /// shifter (MSL).137  uint32_t getMoveVecShifterOpValue(const MCInst &MI, unsigned OpIdx,138                                    SmallVectorImpl<MCFixup> &Fixups,139                                    const MCSubtargetInfo &STI) const;140 141  /// getFixedPointScaleOpValue - Return the encoded value for the142  // FP-to-fixed-point scale factor.143  uint32_t getFixedPointScaleOpValue(const MCInst &MI, unsigned OpIdx,144                                     SmallVectorImpl<MCFixup> &Fixups,145                                     const MCSubtargetInfo &STI) const;146 147  uint32_t getVecShiftR64OpValue(const MCInst &MI, unsigned OpIdx,148                                 SmallVectorImpl<MCFixup> &Fixups,149                                 const MCSubtargetInfo &STI) const;150  uint32_t getVecShiftR32OpValue(const MCInst &MI, unsigned OpIdx,151                                 SmallVectorImpl<MCFixup> &Fixups,152                                 const MCSubtargetInfo &STI) const;153  uint32_t getVecShiftR16OpValue(const MCInst &MI, unsigned OpIdx,154                                 SmallVectorImpl<MCFixup> &Fixups,155                                 const MCSubtargetInfo &STI) const;156  uint32_t getVecShiftR8OpValue(const MCInst &MI, unsigned OpIdx,157                                SmallVectorImpl<MCFixup> &Fixups,158                                const MCSubtargetInfo &STI) const;159  uint32_t getVecShiftL64OpValue(const MCInst &MI, unsigned OpIdx,160                                 SmallVectorImpl<MCFixup> &Fixups,161                                 const MCSubtargetInfo &STI) const;162  uint32_t getVecShiftL32OpValue(const MCInst &MI, unsigned OpIdx,163                                 SmallVectorImpl<MCFixup> &Fixups,164                                 const MCSubtargetInfo &STI) const;165  uint32_t getVecShiftL16OpValue(const MCInst &MI, unsigned OpIdx,166                                 SmallVectorImpl<MCFixup> &Fixups,167                                 const MCSubtargetInfo &STI) const;168  uint32_t getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx,169                                SmallVectorImpl<MCFixup> &Fixups,170                                const MCSubtargetInfo &STI) const;171 172  uint32_t getImm8OptLsl(const MCInst &MI, unsigned OpIdx,173                         SmallVectorImpl<MCFixup> &Fixups,174                         const MCSubtargetInfo &STI) const;175  uint32_t getSVEIncDecImm(const MCInst &MI, unsigned OpIdx,176                           SmallVectorImpl<MCFixup> &Fixups,177                           const MCSubtargetInfo &STI) const;178 179  unsigned fixMOVZ(const MCInst &MI, unsigned EncodedValue,180                   const MCSubtargetInfo &STI) const;181 182  void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,183                         SmallVectorImpl<MCFixup> &Fixups,184                         const MCSubtargetInfo &STI) const override;185 186  unsigned fixMulHigh(const MCInst &MI, unsigned EncodedValue,187                      const MCSubtargetInfo &STI) const;188 189  template<int hasRs, int hasRt2> unsigned190  fixLoadStoreExclusive(const MCInst &MI, unsigned EncodedValue,191                        const MCSubtargetInfo &STI) const;192 193  unsigned fixOneOperandFPComparison(const MCInst &MI, unsigned EncodedValue,194                                     const MCSubtargetInfo &STI) const;195 196  template <unsigned Multiple, unsigned Min, unsigned Max>197  uint32_t EncodeRegMul_MinMax(const MCInst &MI, unsigned OpIdx,198                               SmallVectorImpl<MCFixup> &Fixups,199                               const MCSubtargetInfo &STI) const;200  uint32_t EncodeZK(const MCInst &MI, unsigned OpIdx,201                    SmallVectorImpl<MCFixup> &Fixups,202                    const MCSubtargetInfo &STI) const;203  uint32_t EncodePNR_p8to15(const MCInst &MI, unsigned OpIdx,204                            SmallVectorImpl<MCFixup> &Fixups,205                            const MCSubtargetInfo &STI) const;206 207  uint32_t EncodeZPR2StridedRegisterClass(const MCInst &MI, unsigned OpIdx,208                                          SmallVectorImpl<MCFixup> &Fixups,209                                          const MCSubtargetInfo &STI) const;210  uint32_t EncodeZPR4StridedRegisterClass(const MCInst &MI, unsigned OpIdx,211                                          SmallVectorImpl<MCFixup> &Fixups,212                                          const MCSubtargetInfo &STI) const;213 214  uint32_t EncodeMatrixTileListRegisterClass(const MCInst &MI, unsigned OpIdx,215                                             SmallVectorImpl<MCFixup> &Fixups,216                                             const MCSubtargetInfo &STI) const;217  template <unsigned BaseReg>218  uint32_t encodeMatrixIndexGPR32(const MCInst &MI, unsigned OpIdx,219                                  SmallVectorImpl<MCFixup> &Fixups,220                                  const MCSubtargetInfo &STI) const;221};222 223} // end anonymous namespace224 225static void addFixup(SmallVectorImpl<MCFixup> &Fixups, uint32_t Offset,226                     const MCExpr *Value, uint16_t Kind, bool PCRel = false) {227  Fixups.push_back(MCFixup::create(Offset, Value, Kind, PCRel));228}229 230/// getMachineOpValue - Return binary encoding of operand. If the machine231/// operand requires relocation, record the relocation and return zero.232unsigned233AArch64MCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,234                                        SmallVectorImpl<MCFixup> &Fixups,235                                        const MCSubtargetInfo &STI) const {236  if (MO.isReg())237    return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());238 239  assert(MO.isImm() && "did not expect relocated expression");240  return static_cast<unsigned>(MO.getImm());241}242 243template<unsigned FixupKind> uint32_t244AArch64MCCodeEmitter::getLdStUImm12OpValue(const MCInst &MI, unsigned OpIdx,245                                           SmallVectorImpl<MCFixup> &Fixups,246                                           const MCSubtargetInfo &STI) const {247  const MCOperand &MO = MI.getOperand(OpIdx);248  uint32_t ImmVal = 0;249 250  if (MO.isImm())251    ImmVal = static_cast<uint32_t>(MO.getImm());252  else {253    assert(MO.isExpr() && "unable to encode load/store imm operand");254    MCFixupKind Kind = MCFixupKind(FixupKind);255    addFixup(Fixups, 0, MO.getExpr(), Kind);256    ++MCNumFixups;257  }258 259  return ImmVal;260}261 262/// getAdrLabelOpValue - Return encoding info for 21-bit immediate ADR label263/// target.264uint32_t265AArch64MCCodeEmitter::getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,266                                         SmallVectorImpl<MCFixup> &Fixups,267                                         const MCSubtargetInfo &STI) const {268  const MCOperand &MO = MI.getOperand(OpIdx);269 270  // If the destination is an immediate, we have nothing to do.271  if (MO.isImm())272    return MO.getImm();273  assert(MO.isExpr() && "Unexpected target type!");274  const MCExpr *Expr = MO.getExpr();275 276  unsigned Kind = MI.getOpcode() == AArch64::ADR277                      ? AArch64::fixup_aarch64_pcrel_adr_imm21278                      : AArch64::fixup_aarch64_pcrel_adrp_imm21;279  addFixup(Fixups, 0, Expr, Kind, true);280  MCNumFixups += 1;281  return 0;282}283 284/// getAddSubImmOpValue - Return encoding for the 12-bit immediate value and285/// the 2-bit shift field.  The shift field is stored in bits 13-14 of the286/// return value.287uint32_t288AArch64MCCodeEmitter::getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx,289                                          SmallVectorImpl<MCFixup> &Fixups,290                                          const MCSubtargetInfo &STI) const {291  // Suboperands are [imm, shifter].292  const MCOperand &MO = MI.getOperand(OpIdx);293  const MCOperand &MO1 = MI.getOperand(OpIdx + 1);294  assert(AArch64_AM::getShiftType(MO1.getImm()) == AArch64_AM::LSL &&295         "unexpected shift type for add/sub immediate");296  unsigned ShiftVal = AArch64_AM::getShiftValue(MO1.getImm());297  assert((ShiftVal == 0 || ShiftVal == 12) &&298         "unexpected shift value for add/sub immediate");299  if (MO.isImm())300    return MO.getImm() | (ShiftVal == 0 ? 0 : (1 << ShiftVal));301  assert(MO.isExpr() && "Unable to encode MCOperand!");302  const MCExpr *Expr = MO.getExpr();303 304  // Encode the 12 bits of the fixup.305  MCFixupKind Kind = AArch64::fixup_aarch64_add_imm12;306  addFixup(Fixups, 0, Expr, Kind);307 308  ++MCNumFixups;309 310  // Set the shift bit of the add instruction for relocation types311  // R_AARCH64_TLSLE_ADD_TPREL_HI12 and R_AARCH64_TLSLD_ADD_DTPREL_HI12.312  if (auto *A64E = dyn_cast<MCSpecifierExpr>(Expr)) {313    AArch64::Specifier RefKind = A64E->getSpecifier();314    if (RefKind == AArch64::S_TPREL_HI12 || RefKind == AArch64::S_DTPREL_HI12 ||315        RefKind == AArch64::S_SECREL_HI12)316      ShiftVal = 12;317  }318  return ShiftVal == 0 ? 0 : (1 << ShiftVal);319}320 321/// getCondBranchTargetOpValue - Return the encoded value for a conditional322/// branch target.323uint32_t AArch64MCCodeEmitter::getCondBranchTargetOpValue(324    const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,325    const MCSubtargetInfo &STI) const {326  const MCOperand &MO = MI.getOperand(OpIdx);327 328  // If the destination is an immediate, we have nothing to do.329  if (MO.isImm())330    return MO.getImm();331  assert(MO.isExpr() && "Unexpected target type!");332 333  addFixup(Fixups, 0, MO.getExpr(), AArch64::fixup_aarch64_pcrel_branch19,334           true);335  ++MCNumFixups;336  return 0;337}338 339/// getCondCompBranchTargetOpValue - Return the encoded value for a conditional340/// compare-and-branch target.341uint32_t AArch64MCCodeEmitter::getCondCompBranchTargetOpValue(342    const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,343    const MCSubtargetInfo &STI) const {344  const MCOperand &MO = MI.getOperand(OpIdx);345 346  // If the destination is an immediate, we have nothing to do.347  if (MO.isImm())348    return MO.getImm();349  assert(MO.isExpr() && "Unexpected target type!");350 351  Fixups.push_back(MCFixup::create(0, MO.getExpr(),352                                   AArch64::fixup_aarch64_pcrel_branch9, true));353  ++MCNumFixups;354  return 0;355}356 357/// getPAuthPCRelOpValue - Return the encoded value for a pointer358/// authentication pc-relative operand.359uint32_t360AArch64MCCodeEmitter::getPAuthPCRelOpValue(const MCInst &MI, unsigned OpIdx,361                                           SmallVectorImpl<MCFixup> &Fixups,362                                           const MCSubtargetInfo &STI) const {363  const MCOperand &MO = MI.getOperand(OpIdx);364 365  // If the destination is an immediate, invert sign as it's a negative value366  // that should be encoded as unsigned367  if (MO.isImm())368    return -(MO.getImm());369  assert(MO.isExpr() && "Unexpected target type!");370 371  addFixup(Fixups, 0, MO.getExpr(), AArch64::fixup_aarch64_pcrel_branch16,372           true);373  ++MCNumFixups;374  return 0;375}376 377/// getLoadLiteralOpValue - Return the encoded value for a load-literal378/// pc-relative address.379uint32_t380AArch64MCCodeEmitter::getLoadLiteralOpValue(const MCInst &MI, unsigned OpIdx,381                                            SmallVectorImpl<MCFixup> &Fixups,382                                            const MCSubtargetInfo &STI) const {383  const MCOperand &MO = MI.getOperand(OpIdx);384 385  // If the destination is an immediate, we have nothing to do.386  if (MO.isImm())387    return MO.getImm();388  assert(MO.isExpr() && "Unexpected target type!");389 390  addFixup(Fixups, 0, MO.getExpr(), AArch64::fixup_aarch64_ldr_pcrel_imm19,391           true);392  ++MCNumFixups;393  return 0;394}395 396uint32_t397AArch64MCCodeEmitter::getMemExtendOpValue(const MCInst &MI, unsigned OpIdx,398                                          SmallVectorImpl<MCFixup> &Fixups,399                                          const MCSubtargetInfo &STI) const {400  unsigned SignExtend = MI.getOperand(OpIdx).getImm();401  unsigned DoShift = MI.getOperand(OpIdx + 1).getImm();402  return (SignExtend << 1) | DoShift;403}404 405uint32_t406AArch64MCCodeEmitter::getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx,407                                            SmallVectorImpl<MCFixup> &Fixups,408                                            const MCSubtargetInfo &STI) const {409  const MCOperand &MO = MI.getOperand(OpIdx);410 411  if (MO.isImm())412    return MO.getImm();413  assert(MO.isExpr() && "Unexpected movz/movk immediate");414 415  Fixups.push_back(416      MCFixup::create(0, MO.getExpr(), AArch64::fixup_aarch64_movw));417 418  ++MCNumFixups;419 420  return 0;421}422 423/// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and-424/// branch target.425uint32_t AArch64MCCodeEmitter::getTestBranchTargetOpValue(426    const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,427    const MCSubtargetInfo &STI) const {428  const MCOperand &MO = MI.getOperand(OpIdx);429 430  // If the destination is an immediate, we have nothing to do.431  if (MO.isImm())432    return MO.getImm();433  assert(MO.isExpr() && "Unexpected ADR target type!");434 435  addFixup(Fixups, 0, MO.getExpr(), AArch64::fixup_aarch64_pcrel_branch14,436           true);437  ++MCNumFixups;438  return 0;439}440 441/// getBranchTargetOpValue - Return the encoded value for an unconditional442/// branch target.443uint32_t444AArch64MCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,445                                             SmallVectorImpl<MCFixup> &Fixups,446                                             const MCSubtargetInfo &STI) const {447  const MCOperand &MO = MI.getOperand(OpIdx);448 449  // If the destination is an immediate, we have nothing to do.450  if (MO.isImm())451    return MO.getImm();452  assert(MO.isExpr() && "Unexpected ADR target type!");453 454  unsigned Kind = MI.getOpcode() == AArch64::BL455                      ? AArch64::fixup_aarch64_pcrel_call26456                      : AArch64::fixup_aarch64_pcrel_branch26;457  addFixup(Fixups, 0, MO.getExpr(), Kind, true);458 459  ++MCNumFixups;460 461  // All of the information is in the fixup.462  return 0;463}464 465/// getVecShifterOpValue - Return the encoded value for the vector shifter:466///467///   00 -> 0468///   01 -> 8469///   10 -> 16470///   11 -> 24471uint32_t472AArch64MCCodeEmitter::getVecShifterOpValue(const MCInst &MI, unsigned OpIdx,473                                           SmallVectorImpl<MCFixup> &Fixups,474                                           const MCSubtargetInfo &STI) const {475  const MCOperand &MO = MI.getOperand(OpIdx);476  assert(MO.isImm() && "Expected an immediate value for the shift amount!");477 478  switch (MO.getImm()) {479  default:480    break;481  case 0:482    return 0;483  case 8:484    return 1;485  case 16:486    return 2;487  case 24:488    return 3;489  }490 491  llvm_unreachable("Invalid value for vector shift amount!");492}493 494/// getFixedPointScaleOpValue - Return the encoded value for the495// FP-to-fixed-point scale factor.496uint32_t AArch64MCCodeEmitter::getFixedPointScaleOpValue(497    const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,498    const MCSubtargetInfo &STI) const {499  const MCOperand &MO = MI.getOperand(OpIdx);500  assert(MO.isImm() && "Expected an immediate value for the scale amount!");501  return 64 - MO.getImm();502}503 504uint32_t505AArch64MCCodeEmitter::getVecShiftR64OpValue(const MCInst &MI, unsigned OpIdx,506                                            SmallVectorImpl<MCFixup> &Fixups,507                                            const MCSubtargetInfo &STI) const {508  const MCOperand &MO = MI.getOperand(OpIdx);509  assert(MO.isImm() && "Expected an immediate value for the scale amount!");510  return 64 - MO.getImm();511}512 513uint32_t514AArch64MCCodeEmitter::getVecShiftR32OpValue(const MCInst &MI, unsigned OpIdx,515                                            SmallVectorImpl<MCFixup> &Fixups,516                                            const MCSubtargetInfo &STI) const {517  const MCOperand &MO = MI.getOperand(OpIdx);518  assert(MO.isImm() && "Expected an immediate value for the scale amount!");519  return 32 - MO.getImm();520}521 522uint32_t523AArch64MCCodeEmitter::getVecShiftR16OpValue(const MCInst &MI, unsigned OpIdx,524                                            SmallVectorImpl<MCFixup> &Fixups,525                                            const MCSubtargetInfo &STI) const {526  const MCOperand &MO = MI.getOperand(OpIdx);527  assert(MO.isImm() && "Expected an immediate value for the scale amount!");528  return 16 - MO.getImm();529}530 531uint32_t532AArch64MCCodeEmitter::getVecShiftR8OpValue(const MCInst &MI, unsigned OpIdx,533                                           SmallVectorImpl<MCFixup> &Fixups,534                                           const MCSubtargetInfo &STI) const {535  const MCOperand &MO = MI.getOperand(OpIdx);536  assert(MO.isImm() && "Expected an immediate value for the scale amount!");537  return 8 - MO.getImm();538}539 540uint32_t541AArch64MCCodeEmitter::getVecShiftL64OpValue(const MCInst &MI, unsigned OpIdx,542                                            SmallVectorImpl<MCFixup> &Fixups,543                                            const MCSubtargetInfo &STI) const {544  const MCOperand &MO = MI.getOperand(OpIdx);545  assert(MO.isImm() && "Expected an immediate value for the scale amount!");546  return MO.getImm() - 64;547}548 549uint32_t550AArch64MCCodeEmitter::getVecShiftL32OpValue(const MCInst &MI, unsigned OpIdx,551                                            SmallVectorImpl<MCFixup> &Fixups,552                                            const MCSubtargetInfo &STI) const {553  const MCOperand &MO = MI.getOperand(OpIdx);554  assert(MO.isImm() && "Expected an immediate value for the scale amount!");555  return MO.getImm() - 32;556}557 558uint32_t559AArch64MCCodeEmitter::getVecShiftL16OpValue(const MCInst &MI, unsigned OpIdx,560                                            SmallVectorImpl<MCFixup> &Fixups,561                                            const MCSubtargetInfo &STI) const {562  const MCOperand &MO = MI.getOperand(OpIdx);563  assert(MO.isImm() && "Expected an immediate value for the scale amount!");564  return MO.getImm() - 16;565}566 567uint32_t568AArch64MCCodeEmitter::getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx,569                                           SmallVectorImpl<MCFixup> &Fixups,570                                           const MCSubtargetInfo &STI) const {571  const MCOperand &MO = MI.getOperand(OpIdx);572  assert(MO.isImm() && "Expected an immediate value for the scale amount!");573  return MO.getImm() - 8;574}575 576template <unsigned Multiple, unsigned Min, unsigned Max>577uint32_t578AArch64MCCodeEmitter::EncodeRegMul_MinMax(const MCInst &MI, unsigned OpIdx,579                                          SmallVectorImpl<MCFixup> &Fixups,580                                          const MCSubtargetInfo &STI) const {581  assert(llvm::isPowerOf2_32(Multiple) && "Multiple is not a power of 2");582  auto RegOpnd = MI.getOperand(OpIdx).getReg();583  unsigned RegVal = Ctx.getRegisterInfo()->getEncodingValue(RegOpnd);584  assert(RegVal >= Min && RegVal <= Max && (RegVal & (Multiple - 1)) == 0);585  return (RegVal - Min) / Multiple;586}587 588// Zk Is the name of the control vector register Z20-Z23 or Z28-Z31, encoded in589// the "K:Zk" fields. Z20-Z23 = 000, 001,010, 011  and Z28-Z31 = 100, 101, 110,590// 111591uint32_t AArch64MCCodeEmitter::EncodeZK(const MCInst &MI, unsigned OpIdx,592                                        SmallVectorImpl<MCFixup> &Fixups,593                                        const MCSubtargetInfo &STI) const {594  auto RegOpnd = MI.getOperand(OpIdx).getReg();595  unsigned RegVal = Ctx.getRegisterInfo()->getEncodingValue(RegOpnd);596 597  // ZZ8-Z31 => Reg is in 3..7 (offset 24)598  if (RegOpnd > AArch64::Z27)599    return (RegVal - 24);600 601  assert((RegOpnd > AArch64::Z19 && RegOpnd < AArch64::Z24) &&602         "Expected ZK in Z20..Z23 or Z28..Z31");603  // Z20-Z23 => Reg is in 0..3 (offset 20)604  return (RegVal - 20);605}606 607uint32_t608AArch64MCCodeEmitter::EncodePNR_p8to15(const MCInst &MI, unsigned OpIdx,609                                       SmallVectorImpl<MCFixup> &Fixups,610                                       const MCSubtargetInfo &STI) const {611  auto RegOpnd = MI.getOperand(OpIdx).getReg();612  return RegOpnd - AArch64::PN8;613}614 615uint32_t AArch64MCCodeEmitter::EncodeZPR2StridedRegisterClass(616    const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,617    const MCSubtargetInfo &STI) const {618  auto RegOpnd = MI.getOperand(OpIdx).getReg();619  unsigned RegVal = Ctx.getRegisterInfo()->getEncodingValue(RegOpnd);620  unsigned T = (RegVal & 0x10) >> 1;621  unsigned Zt = RegVal & 0x7;622  return T | Zt;623}624 625uint32_t AArch64MCCodeEmitter::EncodeZPR4StridedRegisterClass(626    const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,627    const MCSubtargetInfo &STI) const {628  auto RegOpnd = MI.getOperand(OpIdx).getReg();629  unsigned RegVal = Ctx.getRegisterInfo()->getEncodingValue(RegOpnd);630  unsigned T = (RegVal & 0x10) >> 2;631  unsigned Zt = RegVal & 0x3;632  return T | Zt;633}634 635uint32_t AArch64MCCodeEmitter::EncodeMatrixTileListRegisterClass(636    const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,637    const MCSubtargetInfo &STI) const {638  unsigned RegMask = MI.getOperand(OpIdx).getImm();639  assert(RegMask <= 0xFF && "Invalid register mask!");640  return RegMask;641}642 643template <unsigned BaseReg>644uint32_t645AArch64MCCodeEmitter::encodeMatrixIndexGPR32(const MCInst &MI, unsigned OpIdx,646                                             SmallVectorImpl<MCFixup> &Fixups,647                                             const MCSubtargetInfo &STI) const {648  auto RegOpnd = MI.getOperand(OpIdx).getReg();649  return RegOpnd - BaseReg;650}651 652uint32_t653AArch64MCCodeEmitter::getImm8OptLsl(const MCInst &MI, unsigned OpIdx,654                                    SmallVectorImpl<MCFixup> &Fixups,655                                    const MCSubtargetInfo &STI) const {656  // Test shift657  auto ShiftOpnd = MI.getOperand(OpIdx + 1).getImm();658  assert(AArch64_AM::getShiftType(ShiftOpnd) == AArch64_AM::LSL &&659         "Unexpected shift type for imm8_opt_lsl immediate.");660 661  unsigned ShiftVal = AArch64_AM::getShiftValue(ShiftOpnd);662  assert((ShiftVal == 0 || ShiftVal == 8) &&663         "Unexpected shift value for imm8_opt_lsl immediate.");664 665  // Test immediate666  auto Immediate = MI.getOperand(OpIdx).getImm();667  return (Immediate & 0xff) | (ShiftVal == 0 ? 0 : (1 << ShiftVal));668}669 670uint32_t671AArch64MCCodeEmitter::getSVEIncDecImm(const MCInst &MI, unsigned OpIdx,672                                           SmallVectorImpl<MCFixup> &Fixups,673                                           const MCSubtargetInfo &STI) const {674  const MCOperand &MO = MI.getOperand(OpIdx);675  assert(MO.isImm() && "Expected an immediate value!");676  // Normalize 1-16 range to 0-15.677  return MO.getImm() - 1;678}679 680/// getMoveVecShifterOpValue - Return the encoded value for the vector move681/// shifter (MSL).682uint32_t AArch64MCCodeEmitter::getMoveVecShifterOpValue(683    const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,684    const MCSubtargetInfo &STI) const {685  const MCOperand &MO = MI.getOperand(OpIdx);686  assert(MO.isImm() &&687         "Expected an immediate value for the move shift amount!");688  unsigned ShiftVal = AArch64_AM::getShiftValue(MO.getImm());689  assert((ShiftVal == 8 || ShiftVal == 16) && "Invalid shift amount!");690  return ShiftVal == 8 ? 0 : 1;691}692 693unsigned AArch64MCCodeEmitter::fixMOVZ(const MCInst &MI, unsigned EncodedValue,694                                       const MCSubtargetInfo &STI) const {695  // If one of the signed fixup kinds is applied to a MOVZ instruction, the696  // eventual result could be either a MOVZ or a MOVN. It's the MCCodeEmitter's697  // job to ensure that any bits possibly affected by this are 0. This means we698  // must zero out bit 30 (essentially emitting a MOVN).699  MCOperand UImm16MO = MI.getOperand(1);700 701  // Nothing to do if there's no fixup.702  if (UImm16MO.isImm())703    return EncodedValue;704 705  const MCExpr *E = UImm16MO.getExpr();706  if (auto *A64E = dyn_cast<MCSpecifierExpr>(E)) {707    switch (A64E->getSpecifier()) {708    case AArch64::S_DTPREL_G2:709    case AArch64::S_DTPREL_G1:710    case AArch64::S_DTPREL_G0:711    case AArch64::S_GOTTPREL_G1:712    case AArch64::S_TPREL_G2:713    case AArch64::S_TPREL_G1:714    case AArch64::S_TPREL_G0:715      return EncodedValue & ~(1u << 30);716    default:717      // Nothing to do for an unsigned fixup.718      return EncodedValue;719    }720  }721 722  return EncodedValue;723}724 725void AArch64MCCodeEmitter::encodeInstruction(const MCInst &MI,726                                             SmallVectorImpl<char> &CB,727 728                                             SmallVectorImpl<MCFixup> &Fixups,729                                             const MCSubtargetInfo &STI) const {730  if (MI.getOpcode() == AArch64::TLSDESCCALL) {731    // This is a directive which applies an R_AARCH64_TLSDESC_CALL to the732    // following (BLR) instruction. It doesn't emit any code itself so it733    // doesn't go through the normal TableGenerated channels.734    auto Reloc = STI.getTargetTriple().getEnvironment() == Triple::GNUILP32735                     ? ELF::R_AARCH64_P32_TLSDESC_CALL736                     : ELF::R_AARCH64_TLSDESC_CALL;737    addFixup(Fixups, 0, MI.getOperand(0).getExpr(), Reloc);738    return;739  }740 741  if (MI.getOpcode() == AArch64::SPACE) {742    // SPACE just increases basic block size, in both cases no actual code.743    return;744  }745 746  uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI);747  support::endian::write<uint32_t>(CB, Binary, llvm::endianness::little);748  ++MCNumEmitted; // Keep track of the # of mi's emitted.749}750 751unsigned752AArch64MCCodeEmitter::fixMulHigh(const MCInst &MI,753                                 unsigned EncodedValue,754                                 const MCSubtargetInfo &STI) const {755  // The Ra field of SMULH and UMULH is unused: it should be assembled as 31756  // (i.e. all bits 1) but is ignored by the processor.757  EncodedValue |= 0x1f << 10;758  return EncodedValue;759}760 761template<int hasRs, int hasRt2> unsigned762AArch64MCCodeEmitter::fixLoadStoreExclusive(const MCInst &MI,763                                            unsigned EncodedValue,764                                            const MCSubtargetInfo &STI) const {765  if (!hasRs) EncodedValue |= 0x001F0000;766  if (!hasRt2) EncodedValue |= 0x00007C00;767 768  return EncodedValue;769}770 771unsigned AArch64MCCodeEmitter::fixOneOperandFPComparison(772    const MCInst &MI, unsigned EncodedValue, const MCSubtargetInfo &STI) const {773  // The Rm field of FCMP and friends is unused - it should be assembled774  // as 0, but is ignored by the processor.775  EncodedValue &= ~(0x1f << 16);776  return EncodedValue;777}778 779#include "AArch64GenMCCodeEmitter.inc"780 781MCCodeEmitter *llvm::createAArch64MCCodeEmitter(const MCInstrInfo &MCII,782                                                MCContext &Ctx) {783  return new AArch64MCCodeEmitter(MCII, Ctx);784}785