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