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