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