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