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