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-exception 6 // 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/AArch64MCExpr.h" 16 #include "Utils/AArch64BaseInfo.h" 17 #include "llvm/ADT/SmallVector.h" 18 #include "llvm/ADT/Statistic.h" 19 #include "llvm/BinaryFormat/ELF.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 : Ctx(ctx), MCII(mcii) {} 51 AArch64MCCodeEmitter(const AArch64MCCodeEmitter &) = delete; 52 void operator=(const AArch64MCCodeEmitter &) = delete; 53 ~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 uint32_t EncodeMatrixTileListRegisterClass(const MCInst &MI, unsigned OpIdx, 191 SmallVectorImpl<MCFixup> &Fixups, 192 const MCSubtargetInfo &STI) const; 193 uint32_t encodeMatrixIndexGPR32(const MCInst &MI, unsigned OpIdx, 194 SmallVectorImpl<MCFixup> &Fixups, 195 const MCSubtargetInfo &STI) const; 196 197 private: 198 FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const; 199 void 200 verifyInstructionPredicates(const MCInst &MI, 201 const FeatureBitset &AvailableFeatures) const; 202 }; 203 204 } // end anonymous namespace 205 206 /// getMachineOpValue - Return binary encoding of operand. If the machine 207 /// operand requires relocation, record the relocation and return zero. 208 unsigned 209 AArch64MCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, 210 SmallVectorImpl<MCFixup> &Fixups, 211 const MCSubtargetInfo &STI) const { 212 if (MO.isReg()) 213 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 214 215 assert(MO.isImm() && "did not expect relocated expression"); 216 return static_cast<unsigned>(MO.getImm()); 217 } 218 219 template<unsigned FixupKind> uint32_t 220 AArch64MCCodeEmitter::getLdStUImm12OpValue(const MCInst &MI, unsigned OpIdx, 221 SmallVectorImpl<MCFixup> &Fixups, 222 const MCSubtargetInfo &STI) const { 223 const MCOperand &MO = MI.getOperand(OpIdx); 224 uint32_t ImmVal = 0; 225 226 if (MO.isImm()) 227 ImmVal = static_cast<uint32_t>(MO.getImm()); 228 else { 229 assert(MO.isExpr() && "unable to encode load/store imm operand"); 230 MCFixupKind Kind = MCFixupKind(FixupKind); 231 Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc())); 232 ++MCNumFixups; 233 } 234 235 return ImmVal; 236 } 237 238 /// getAdrLabelOpValue - Return encoding info for 21-bit immediate ADR label 239 /// target. 240 uint32_t 241 AArch64MCCodeEmitter::getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, 242 SmallVectorImpl<MCFixup> &Fixups, 243 const MCSubtargetInfo &STI) const { 244 const MCOperand &MO = MI.getOperand(OpIdx); 245 246 // If the destination is an immediate, we have nothing to do. 247 if (MO.isImm()) 248 return MO.getImm(); 249 assert(MO.isExpr() && "Unexpected target type!"); 250 const MCExpr *Expr = MO.getExpr(); 251 252 MCFixupKind Kind = MI.getOpcode() == AArch64::ADR 253 ? MCFixupKind(AArch64::fixup_aarch64_pcrel_adr_imm21) 254 : MCFixupKind(AArch64::fixup_aarch64_pcrel_adrp_imm21); 255 Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc())); 256 257 MCNumFixups += 1; 258 259 // All of the information is in the fixup. 260 return 0; 261 } 262 263 /// getAddSubImmOpValue - Return encoding for the 12-bit immediate value and 264 /// the 2-bit shift field. The shift field is stored in bits 13-14 of the 265 /// return value. 266 uint32_t 267 AArch64MCCodeEmitter::getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx, 268 SmallVectorImpl<MCFixup> &Fixups, 269 const MCSubtargetInfo &STI) const { 270 // Suboperands are [imm, shifter]. 271 const MCOperand &MO = MI.getOperand(OpIdx); 272 const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 273 assert(AArch64_AM::getShiftType(MO1.getImm()) == AArch64_AM::LSL && 274 "unexpected shift type for add/sub immediate"); 275 unsigned ShiftVal = AArch64_AM::getShiftValue(MO1.getImm()); 276 assert((ShiftVal == 0 || ShiftVal == 12) && 277 "unexpected shift value for add/sub immediate"); 278 if (MO.isImm()) 279 return MO.getImm() | (ShiftVal == 0 ? 0 : (1 << ShiftVal)); 280 assert(MO.isExpr() && "Unable to encode MCOperand!"); 281 const MCExpr *Expr = MO.getExpr(); 282 283 // Encode the 12 bits of the fixup. 284 MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_add_imm12); 285 Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc())); 286 287 ++MCNumFixups; 288 289 // Set the shift bit of the add instruction for relocation types 290 // R_AARCH64_TLSLE_ADD_TPREL_HI12 and R_AARCH64_TLSLD_ADD_DTPREL_HI12. 291 if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) { 292 AArch64MCExpr::VariantKind RefKind = A64E->getKind(); 293 if (RefKind == AArch64MCExpr::VK_TPREL_HI12 || 294 RefKind == AArch64MCExpr::VK_DTPREL_HI12 || 295 RefKind == AArch64MCExpr::VK_SECREL_HI12) 296 ShiftVal = 12; 297 } 298 return ShiftVal == 0 ? 0 : (1 << ShiftVal); 299 } 300 301 /// getCondBranchTargetOpValue - Return the encoded value for a conditional 302 /// branch target. 303 uint32_t AArch64MCCodeEmitter::getCondBranchTargetOpValue( 304 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups, 305 const MCSubtargetInfo &STI) const { 306 const MCOperand &MO = MI.getOperand(OpIdx); 307 308 // If the destination is an immediate, we have nothing to do. 309 if (MO.isImm()) 310 return MO.getImm(); 311 assert(MO.isExpr() && "Unexpected target type!"); 312 313 MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_pcrel_branch19); 314 Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc())); 315 316 ++MCNumFixups; 317 318 // All of the information is in the fixup. 319 return 0; 320 } 321 322 /// getLoadLiteralOpValue - Return the encoded value for a load-literal 323 /// pc-relative address. 324 uint32_t 325 AArch64MCCodeEmitter::getLoadLiteralOpValue(const MCInst &MI, unsigned OpIdx, 326 SmallVectorImpl<MCFixup> &Fixups, 327 const MCSubtargetInfo &STI) const { 328 const MCOperand &MO = MI.getOperand(OpIdx); 329 330 // If the destination is an immediate, we have nothing to do. 331 if (MO.isImm()) 332 return MO.getImm(); 333 assert(MO.isExpr() && "Unexpected target type!"); 334 335 MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_ldr_pcrel_imm19); 336 Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc())); 337 338 ++MCNumFixups; 339 340 // All of the information is in the fixup. 341 return 0; 342 } 343 344 uint32_t 345 AArch64MCCodeEmitter::getMemExtendOpValue(const MCInst &MI, unsigned OpIdx, 346 SmallVectorImpl<MCFixup> &Fixups, 347 const MCSubtargetInfo &STI) const { 348 unsigned SignExtend = MI.getOperand(OpIdx).getImm(); 349 unsigned DoShift = MI.getOperand(OpIdx + 1).getImm(); 350 return (SignExtend << 1) | DoShift; 351 } 352 353 uint32_t 354 AArch64MCCodeEmitter::getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx, 355 SmallVectorImpl<MCFixup> &Fixups, 356 const MCSubtargetInfo &STI) const { 357 const MCOperand &MO = MI.getOperand(OpIdx); 358 359 if (MO.isImm()) 360 return MO.getImm(); 361 assert(MO.isExpr() && "Unexpected movz/movk immediate"); 362 363 Fixups.push_back(MCFixup::create( 364 0, MO.getExpr(), MCFixupKind(AArch64::fixup_aarch64_movw), MI.getLoc())); 365 366 ++MCNumFixups; 367 368 return 0; 369 } 370 371 /// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and- 372 /// branch target. 373 uint32_t AArch64MCCodeEmitter::getTestBranchTargetOpValue( 374 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups, 375 const MCSubtargetInfo &STI) const { 376 const MCOperand &MO = MI.getOperand(OpIdx); 377 378 // If the destination is an immediate, we have nothing to do. 379 if (MO.isImm()) 380 return MO.getImm(); 381 assert(MO.isExpr() && "Unexpected ADR target type!"); 382 383 MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_pcrel_branch14); 384 Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc())); 385 386 ++MCNumFixups; 387 388 // All of the information is in the fixup. 389 return 0; 390 } 391 392 /// getBranchTargetOpValue - Return the encoded value for an unconditional 393 /// branch target. 394 uint32_t 395 AArch64MCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 396 SmallVectorImpl<MCFixup> &Fixups, 397 const MCSubtargetInfo &STI) const { 398 const MCOperand &MO = MI.getOperand(OpIdx); 399 400 // If the destination is an immediate, we have nothing to do. 401 if (MO.isImm()) 402 return MO.getImm(); 403 assert(MO.isExpr() && "Unexpected ADR target type!"); 404 405 MCFixupKind Kind = MI.getOpcode() == AArch64::BL 406 ? MCFixupKind(AArch64::fixup_aarch64_pcrel_call26) 407 : MCFixupKind(AArch64::fixup_aarch64_pcrel_branch26); 408 Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc())); 409 410 ++MCNumFixups; 411 412 // All of the information is in the fixup. 413 return 0; 414 } 415 416 /// getVecShifterOpValue - Return the encoded value for the vector shifter: 417 /// 418 /// 00 -> 0 419 /// 01 -> 8 420 /// 10 -> 16 421 /// 11 -> 24 422 uint32_t 423 AArch64MCCodeEmitter::getVecShifterOpValue(const MCInst &MI, unsigned OpIdx, 424 SmallVectorImpl<MCFixup> &Fixups, 425 const MCSubtargetInfo &STI) const { 426 const MCOperand &MO = MI.getOperand(OpIdx); 427 assert(MO.isImm() && "Expected an immediate value for the shift amount!"); 428 429 switch (MO.getImm()) { 430 default: 431 break; 432 case 0: 433 return 0; 434 case 8: 435 return 1; 436 case 16: 437 return 2; 438 case 24: 439 return 3; 440 } 441 442 llvm_unreachable("Invalid value for vector shift amount!"); 443 } 444 445 /// getFixedPointScaleOpValue - Return the encoded value for the 446 // FP-to-fixed-point scale factor. 447 uint32_t AArch64MCCodeEmitter::getFixedPointScaleOpValue( 448 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups, 449 const MCSubtargetInfo &STI) const { 450 const MCOperand &MO = MI.getOperand(OpIdx); 451 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 452 return 64 - MO.getImm(); 453 } 454 455 uint32_t 456 AArch64MCCodeEmitter::getVecShiftR64OpValue(const MCInst &MI, unsigned OpIdx, 457 SmallVectorImpl<MCFixup> &Fixups, 458 const MCSubtargetInfo &STI) const { 459 const MCOperand &MO = MI.getOperand(OpIdx); 460 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 461 return 64 - MO.getImm(); 462 } 463 464 uint32_t 465 AArch64MCCodeEmitter::getVecShiftR32OpValue(const MCInst &MI, unsigned OpIdx, 466 SmallVectorImpl<MCFixup> &Fixups, 467 const MCSubtargetInfo &STI) const { 468 const MCOperand &MO = MI.getOperand(OpIdx); 469 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 470 return 32 - MO.getImm(); 471 } 472 473 uint32_t 474 AArch64MCCodeEmitter::getVecShiftR16OpValue(const MCInst &MI, unsigned OpIdx, 475 SmallVectorImpl<MCFixup> &Fixups, 476 const MCSubtargetInfo &STI) const { 477 const MCOperand &MO = MI.getOperand(OpIdx); 478 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 479 return 16 - MO.getImm(); 480 } 481 482 uint32_t 483 AArch64MCCodeEmitter::getVecShiftR8OpValue(const MCInst &MI, unsigned OpIdx, 484 SmallVectorImpl<MCFixup> &Fixups, 485 const MCSubtargetInfo &STI) const { 486 const MCOperand &MO = MI.getOperand(OpIdx); 487 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 488 return 8 - MO.getImm(); 489 } 490 491 uint32_t 492 AArch64MCCodeEmitter::getVecShiftL64OpValue(const MCInst &MI, unsigned OpIdx, 493 SmallVectorImpl<MCFixup> &Fixups, 494 const MCSubtargetInfo &STI) const { 495 const MCOperand &MO = MI.getOperand(OpIdx); 496 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 497 return MO.getImm() - 64; 498 } 499 500 uint32_t 501 AArch64MCCodeEmitter::getVecShiftL32OpValue(const MCInst &MI, unsigned OpIdx, 502 SmallVectorImpl<MCFixup> &Fixups, 503 const MCSubtargetInfo &STI) const { 504 const MCOperand &MO = MI.getOperand(OpIdx); 505 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 506 return MO.getImm() - 32; 507 } 508 509 uint32_t 510 AArch64MCCodeEmitter::getVecShiftL16OpValue(const MCInst &MI, unsigned OpIdx, 511 SmallVectorImpl<MCFixup> &Fixups, 512 const MCSubtargetInfo &STI) const { 513 const MCOperand &MO = MI.getOperand(OpIdx); 514 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 515 return MO.getImm() - 16; 516 } 517 518 uint32_t 519 AArch64MCCodeEmitter::getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx, 520 SmallVectorImpl<MCFixup> &Fixups, 521 const MCSubtargetInfo &STI) const { 522 const MCOperand &MO = MI.getOperand(OpIdx); 523 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 524 return MO.getImm() - 8; 525 } 526 527 uint32_t AArch64MCCodeEmitter::EncodeMatrixTileListRegisterClass( 528 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups, 529 const MCSubtargetInfo &STI) const { 530 unsigned RegMask = MI.getOperand(OpIdx).getImm(); 531 assert(RegMask <= 0xFF && "Invalid register mask!"); 532 return RegMask; 533 } 534 535 uint32_t 536 AArch64MCCodeEmitter::encodeMatrixIndexGPR32(const MCInst &MI, unsigned OpIdx, 537 SmallVectorImpl<MCFixup> &Fixups, 538 const MCSubtargetInfo &STI) const { 539 auto RegOpnd = MI.getOperand(OpIdx).getReg(); 540 assert(RegOpnd >= AArch64::W12 && RegOpnd <= AArch64::W15 && 541 "Expected register in the range w12-w15!"); 542 return RegOpnd - AArch64::W12; 543 } 544 545 uint32_t 546 AArch64MCCodeEmitter::getImm8OptLsl(const MCInst &MI, unsigned OpIdx, 547 SmallVectorImpl<MCFixup> &Fixups, 548 const MCSubtargetInfo &STI) const { 549 // Test shift 550 auto ShiftOpnd = MI.getOperand(OpIdx + 1).getImm(); 551 assert(AArch64_AM::getShiftType(ShiftOpnd) == AArch64_AM::LSL && 552 "Unexpected shift type for imm8_opt_lsl immediate."); 553 554 unsigned ShiftVal = AArch64_AM::getShiftValue(ShiftOpnd); 555 assert((ShiftVal == 0 || ShiftVal == 8) && 556 "Unexpected shift value for imm8_opt_lsl immediate."); 557 558 // Test immediate 559 auto Immediate = MI.getOperand(OpIdx).getImm(); 560 return (Immediate & 0xff) | (ShiftVal == 0 ? 0 : (1 << ShiftVal)); 561 } 562 563 uint32_t 564 AArch64MCCodeEmitter::getSVEIncDecImm(const MCInst &MI, unsigned OpIdx, 565 SmallVectorImpl<MCFixup> &Fixups, 566 const MCSubtargetInfo &STI) const { 567 const MCOperand &MO = MI.getOperand(OpIdx); 568 assert(MO.isImm() && "Expected an immediate value!"); 569 // Normalize 1-16 range to 0-15. 570 return MO.getImm() - 1; 571 } 572 573 /// getMoveVecShifterOpValue - Return the encoded value for the vector move 574 /// shifter (MSL). 575 uint32_t AArch64MCCodeEmitter::getMoveVecShifterOpValue( 576 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups, 577 const MCSubtargetInfo &STI) const { 578 const MCOperand &MO = MI.getOperand(OpIdx); 579 assert(MO.isImm() && 580 "Expected an immediate value for the move shift amount!"); 581 unsigned ShiftVal = AArch64_AM::getShiftValue(MO.getImm()); 582 assert((ShiftVal == 8 || ShiftVal == 16) && "Invalid shift amount!"); 583 return ShiftVal == 8 ? 0 : 1; 584 } 585 586 unsigned AArch64MCCodeEmitter::fixMOVZ(const MCInst &MI, unsigned EncodedValue, 587 const MCSubtargetInfo &STI) const { 588 // If one of the signed fixup kinds is applied to a MOVZ instruction, the 589 // eventual result could be either a MOVZ or a MOVN. It's the MCCodeEmitter's 590 // job to ensure that any bits possibly affected by this are 0. This means we 591 // must zero out bit 30 (essentially emitting a MOVN). 592 MCOperand UImm16MO = MI.getOperand(1); 593 594 // Nothing to do if there's no fixup. 595 if (UImm16MO.isImm()) 596 return EncodedValue; 597 598 const MCExpr *E = UImm16MO.getExpr(); 599 if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(E)) { 600 switch (A64E->getKind()) { 601 case AArch64MCExpr::VK_DTPREL_G2: 602 case AArch64MCExpr::VK_DTPREL_G1: 603 case AArch64MCExpr::VK_DTPREL_G0: 604 case AArch64MCExpr::VK_GOTTPREL_G1: 605 case AArch64MCExpr::VK_TPREL_G2: 606 case AArch64MCExpr::VK_TPREL_G1: 607 case AArch64MCExpr::VK_TPREL_G0: 608 return EncodedValue & ~(1u << 30); 609 default: 610 // Nothing to do for an unsigned fixup. 611 return EncodedValue; 612 } 613 } 614 615 return EncodedValue; 616 } 617 618 void AArch64MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, 619 SmallVectorImpl<MCFixup> &Fixups, 620 const MCSubtargetInfo &STI) const { 621 verifyInstructionPredicates(MI, 622 computeAvailableFeatures(STI.getFeatureBits())); 623 624 if (MI.getOpcode() == AArch64::TLSDESCCALL) { 625 // This is a directive which applies an R_AARCH64_TLSDESC_CALL to the 626 // following (BLR) instruction. It doesn't emit any code itself so it 627 // doesn't go through the normal TableGenerated channels. 628 auto Reloc = STI.getTargetTriple().getEnvironment() == Triple::GNUILP32 629 ? ELF::R_AARCH64_P32_TLSDESC_CALL 630 : ELF::R_AARCH64_TLSDESC_CALL; 631 Fixups.push_back( 632 MCFixup::create(0, MI.getOperand(0).getExpr(), 633 MCFixupKind(FirstLiteralRelocationKind + Reloc))); 634 return; 635 } 636 637 if (MI.getOpcode() == AArch64::CompilerBarrier || 638 MI.getOpcode() == AArch64::SPACE) { 639 // CompilerBarrier just prevents the compiler from reordering accesses, and 640 // SPACE just increases basic block size, in both cases no actual code. 641 return; 642 } 643 644 uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI); 645 support::endian::write<uint32_t>(OS, Binary, support::little); 646 ++MCNumEmitted; // Keep track of the # of mi's emitted. 647 } 648 649 unsigned 650 AArch64MCCodeEmitter::fixMulHigh(const MCInst &MI, 651 unsigned EncodedValue, 652 const MCSubtargetInfo &STI) const { 653 // The Ra field of SMULH and UMULH is unused: it should be assembled as 31 654 // (i.e. all bits 1) but is ignored by the processor. 655 EncodedValue |= 0x1f << 10; 656 return EncodedValue; 657 } 658 659 template<int hasRs, int hasRt2> unsigned 660 AArch64MCCodeEmitter::fixLoadStoreExclusive(const MCInst &MI, 661 unsigned EncodedValue, 662 const MCSubtargetInfo &STI) const { 663 if (!hasRs) EncodedValue |= 0x001F0000; 664 if (!hasRt2) EncodedValue |= 0x00007C00; 665 666 return EncodedValue; 667 } 668 669 unsigned AArch64MCCodeEmitter::fixOneOperandFPComparison( 670 const MCInst &MI, unsigned EncodedValue, const MCSubtargetInfo &STI) const { 671 // The Rm field of FCMP and friends is unused - it should be assembled 672 // as 0, but is ignored by the processor. 673 EncodedValue &= ~(0x1f << 16); 674 return EncodedValue; 675 } 676 677 #define ENABLE_INSTR_PREDICATE_VERIFIER 678 #include "AArch64GenMCCodeEmitter.inc" 679 680 MCCodeEmitter *llvm::createAArch64MCCodeEmitter(const MCInstrInfo &MCII, 681 MCContext &Ctx) { 682 return new AArch64MCCodeEmitter(MCII, Ctx); 683 } 684