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