AArch64MCCodeEmitter.cpp revision dce4a407a24b04eebc6a376f8e62b41aaa7b071f
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/MC/MCCodeEmitter.h" 19#include "llvm/MC/MCContext.h" 20#include "llvm/MC/MCInst.h" 21#include "llvm/MC/MCInstrInfo.h" 22#include "llvm/MC/MCRegisterInfo.h" 23#include "llvm/MC/MCSubtargetInfo.h" 24#include "llvm/ADT/Statistic.h" 25#include "llvm/Support/raw_ostream.h" 26using namespace llvm; 27 28#define DEBUG_TYPE "mccodeemitter" 29 30STATISTIC(MCNumEmitted, "Number of MC instructions emitted."); 31STATISTIC(MCNumFixups, "Number of MC fixups created."); 32 33namespace { 34 35class AArch64MCCodeEmitter : public MCCodeEmitter { 36 MCContext &Ctx; 37 38 AArch64MCCodeEmitter(const AArch64MCCodeEmitter &); // DO NOT IMPLEMENT 39 void operator=(const AArch64MCCodeEmitter &); // DO NOT IMPLEMENT 40public: 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 206MCCodeEmitter *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. 215unsigned 216AArch64MCCodeEmitter::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 else { 222 assert(MO.isImm() && "did not expect relocated expression"); 223 return static_cast<unsigned>(MO.getImm()); 224 } 225 226 assert(0 && "Unable to encode MCOperand!"); 227 return 0; 228} 229 230template<unsigned FixupKind> uint32_t 231AArch64MCCodeEmitter::getLdStUImm12OpValue(const MCInst &MI, unsigned OpIdx, 232 SmallVectorImpl<MCFixup> &Fixups, 233 const MCSubtargetInfo &STI) const { 234 const MCOperand &MO = MI.getOperand(OpIdx); 235 uint32_t ImmVal = 0; 236 237 if (MO.isImm()) 238 ImmVal = static_cast<uint32_t>(MO.getImm()); 239 else { 240 assert(MO.isExpr() && "unable to encode load/store imm operand"); 241 MCFixupKind Kind = MCFixupKind(FixupKind); 242 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc())); 243 ++MCNumFixups; 244 } 245 246 return ImmVal; 247} 248 249/// getAdrLabelOpValue - Return encoding info for 21-bit immediate ADR label 250/// target. 251uint32_t 252AArch64MCCodeEmitter::getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, 253 SmallVectorImpl<MCFixup> &Fixups, 254 const MCSubtargetInfo &STI) const { 255 const MCOperand &MO = MI.getOperand(OpIdx); 256 257 // If the destination is an immediate, we have nothing to do. 258 if (MO.isImm()) 259 return MO.getImm(); 260 assert(MO.isExpr() && "Unexpected target type!"); 261 const MCExpr *Expr = MO.getExpr(); 262 263 MCFixupKind Kind = MI.getOpcode() == AArch64::ADR 264 ? MCFixupKind(AArch64::fixup_aarch64_pcrel_adr_imm21) 265 : MCFixupKind(AArch64::fixup_aarch64_pcrel_adrp_imm21); 266 Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); 267 268 MCNumFixups += 1; 269 270 // All of the information is in the fixup. 271 return 0; 272} 273 274/// getAddSubImmOpValue - Return encoding for the 12-bit immediate value and 275/// the 2-bit shift field. The shift field is stored in bits 13-14 of the 276/// return value. 277uint32_t 278AArch64MCCodeEmitter::getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx, 279 SmallVectorImpl<MCFixup> &Fixups, 280 const MCSubtargetInfo &STI) const { 281 // Suboperands are [imm, shifter]. 282 const MCOperand &MO = MI.getOperand(OpIdx); 283 const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 284 assert(AArch64_AM::getShiftType(MO1.getImm()) == AArch64_AM::LSL && 285 "unexpected shift type for add/sub immediate"); 286 unsigned ShiftVal = AArch64_AM::getShiftValue(MO1.getImm()); 287 assert((ShiftVal == 0 || ShiftVal == 12) && 288 "unexpected shift value for add/sub immediate"); 289 if (MO.isImm()) 290 return MO.getImm() | (ShiftVal == 0 ? 0 : (1 << 12)); 291 assert(MO.isExpr() && "Unable to encode MCOperand!"); 292 const MCExpr *Expr = MO.getExpr(); 293 294 // Encode the 12 bits of the fixup. 295 MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_add_imm12); 296 Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); 297 298 ++MCNumFixups; 299 300 return 0; 301} 302 303/// getCondBranchTargetOpValue - Return the encoded value for a conditional 304/// branch target. 305uint32_t AArch64MCCodeEmitter::getCondBranchTargetOpValue( 306 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups, 307 const MCSubtargetInfo &STI) const { 308 const MCOperand &MO = MI.getOperand(OpIdx); 309 310 // If the destination is an immediate, we have nothing to do. 311 if (MO.isImm()) 312 return MO.getImm(); 313 assert(MO.isExpr() && "Unexpected target type!"); 314 315 MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_pcrel_branch19); 316 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc())); 317 318 ++MCNumFixups; 319 320 // All of the information is in the fixup. 321 return 0; 322} 323 324/// getLoadLiteralOpValue - Return the encoded value for a load-literal 325/// pc-relative address. 326uint32_t 327AArch64MCCodeEmitter::getLoadLiteralOpValue(const MCInst &MI, unsigned OpIdx, 328 SmallVectorImpl<MCFixup> &Fixups, 329 const MCSubtargetInfo &STI) const { 330 const MCOperand &MO = MI.getOperand(OpIdx); 331 332 // If the destination is an immediate, we have nothing to do. 333 if (MO.isImm()) 334 return MO.getImm(); 335 assert(MO.isExpr() && "Unexpected target type!"); 336 337 MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_ldr_pcrel_imm19); 338 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc())); 339 340 ++MCNumFixups; 341 342 // All of the information is in the fixup. 343 return 0; 344} 345 346uint32_t 347AArch64MCCodeEmitter::getMemExtendOpValue(const MCInst &MI, unsigned OpIdx, 348 SmallVectorImpl<MCFixup> &Fixups, 349 const MCSubtargetInfo &STI) const { 350 unsigned SignExtend = MI.getOperand(OpIdx).getImm(); 351 unsigned DoShift = MI.getOperand(OpIdx + 1).getImm(); 352 return (SignExtend << 1) | DoShift; 353} 354 355uint32_t 356AArch64MCCodeEmitter::getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx, 357 SmallVectorImpl<MCFixup> &Fixups, 358 const MCSubtargetInfo &STI) const { 359 const MCOperand &MO = MI.getOperand(OpIdx); 360 361 if (MO.isImm()) 362 return MO.getImm(); 363 assert(MO.isExpr() && "Unexpected movz/movk immediate"); 364 365 Fixups.push_back(MCFixup::Create( 366 0, MO.getExpr(), MCFixupKind(AArch64::fixup_aarch64_movw), MI.getLoc())); 367 368 ++MCNumFixups; 369 370 return 0; 371} 372 373/// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and- 374/// branch target. 375uint32_t AArch64MCCodeEmitter::getTestBranchTargetOpValue( 376 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups, 377 const MCSubtargetInfo &STI) const { 378 const MCOperand &MO = MI.getOperand(OpIdx); 379 380 // If the destination is an immediate, we have nothing to do. 381 if (MO.isImm()) 382 return MO.getImm(); 383 assert(MO.isExpr() && "Unexpected ADR target type!"); 384 385 MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_pcrel_branch14); 386 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc())); 387 388 ++MCNumFixups; 389 390 // All of the information is in the fixup. 391 return 0; 392} 393 394/// getBranchTargetOpValue - Return the encoded value for an unconditional 395/// branch target. 396uint32_t 397AArch64MCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 398 SmallVectorImpl<MCFixup> &Fixups, 399 const MCSubtargetInfo &STI) const { 400 const MCOperand &MO = MI.getOperand(OpIdx); 401 402 // If the destination is an immediate, we have nothing to do. 403 if (MO.isImm()) 404 return MO.getImm(); 405 assert(MO.isExpr() && "Unexpected ADR target type!"); 406 407 MCFixupKind Kind = MI.getOpcode() == AArch64::BL 408 ? MCFixupKind(AArch64::fixup_aarch64_pcrel_call26) 409 : MCFixupKind(AArch64::fixup_aarch64_pcrel_branch26); 410 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc())); 411 412 ++MCNumFixups; 413 414 // All of the information is in the fixup. 415 return 0; 416} 417 418/// getVecShifterOpValue - Return the encoded value for the vector shifter: 419/// 420/// 00 -> 0 421/// 01 -> 8 422/// 10 -> 16 423/// 11 -> 24 424uint32_t 425AArch64MCCodeEmitter::getVecShifterOpValue(const MCInst &MI, unsigned OpIdx, 426 SmallVectorImpl<MCFixup> &Fixups, 427 const MCSubtargetInfo &STI) const { 428 const MCOperand &MO = MI.getOperand(OpIdx); 429 assert(MO.isImm() && "Expected an immediate value for the shift amount!"); 430 431 switch (MO.getImm()) { 432 default: 433 break; 434 case 0: 435 return 0; 436 case 8: 437 return 1; 438 case 16: 439 return 2; 440 case 24: 441 return 3; 442 } 443 444 assert(false && "Invalid value for vector shift amount!"); 445 return 0; 446} 447 448uint32_t 449AArch64MCCodeEmitter::getSIMDShift64OpValue(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 shift amount!"); 454 return 64 - (MO.getImm()); 455} 456 457uint32_t AArch64MCCodeEmitter::getSIMDShift64_32OpValue( 458 const MCInst &MI, unsigned OpIdx, 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 shift amount!"); 462 return 64 - (MO.getImm() | 32); 463} 464 465uint32_t 466AArch64MCCodeEmitter::getSIMDShift32OpValue(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 shift amount!"); 471 return 32 - (MO.getImm() | 16); 472} 473 474uint32_t 475AArch64MCCodeEmitter::getSIMDShift16OpValue(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 shift amount!"); 480 return 16 - (MO.getImm() | 8); 481} 482 483/// getFixedPointScaleOpValue - Return the encoded value for the 484// FP-to-fixed-point scale factor. 485uint32_t AArch64MCCodeEmitter::getFixedPointScaleOpValue( 486 const MCInst &MI, unsigned OpIdx, 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 64 - MO.getImm(); 491} 492 493uint32_t 494AArch64MCCodeEmitter::getVecShiftR64OpValue(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 64 - MO.getImm(); 500} 501 502uint32_t 503AArch64MCCodeEmitter::getVecShiftR32OpValue(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 32 - MO.getImm(); 509} 510 511uint32_t 512AArch64MCCodeEmitter::getVecShiftR16OpValue(const MCInst &MI, unsigned OpIdx, 513 SmallVectorImpl<MCFixup> &Fixups, 514 const MCSubtargetInfo &STI) const { 515 const MCOperand &MO = MI.getOperand(OpIdx); 516 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 517 return 16 - MO.getImm(); 518} 519 520uint32_t 521AArch64MCCodeEmitter::getVecShiftR8OpValue(const MCInst &MI, unsigned OpIdx, 522 SmallVectorImpl<MCFixup> &Fixups, 523 const MCSubtargetInfo &STI) const { 524 const MCOperand &MO = MI.getOperand(OpIdx); 525 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 526 return 8 - MO.getImm(); 527} 528 529uint32_t 530AArch64MCCodeEmitter::getVecShiftL64OpValue(const MCInst &MI, unsigned OpIdx, 531 SmallVectorImpl<MCFixup> &Fixups, 532 const MCSubtargetInfo &STI) const { 533 const MCOperand &MO = MI.getOperand(OpIdx); 534 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 535 return MO.getImm() - 64; 536} 537 538uint32_t 539AArch64MCCodeEmitter::getVecShiftL32OpValue(const MCInst &MI, unsigned OpIdx, 540 SmallVectorImpl<MCFixup> &Fixups, 541 const MCSubtargetInfo &STI) const { 542 const MCOperand &MO = MI.getOperand(OpIdx); 543 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 544 return MO.getImm() - 32; 545} 546 547uint32_t 548AArch64MCCodeEmitter::getVecShiftL16OpValue(const MCInst &MI, unsigned OpIdx, 549 SmallVectorImpl<MCFixup> &Fixups, 550 const MCSubtargetInfo &STI) const { 551 const MCOperand &MO = MI.getOperand(OpIdx); 552 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 553 return MO.getImm() - 16; 554} 555 556uint32_t 557AArch64MCCodeEmitter::getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx, 558 SmallVectorImpl<MCFixup> &Fixups, 559 const MCSubtargetInfo &STI) const { 560 const MCOperand &MO = MI.getOperand(OpIdx); 561 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 562 return MO.getImm() - 8; 563} 564 565/// getMoveVecShifterOpValue - Return the encoded value for the vector move 566/// shifter (MSL). 567uint32_t AArch64MCCodeEmitter::getMoveVecShifterOpValue( 568 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups, 569 const MCSubtargetInfo &STI) const { 570 const MCOperand &MO = MI.getOperand(OpIdx); 571 assert(MO.isImm() && 572 "Expected an immediate value for the move shift amount!"); 573 unsigned ShiftVal = AArch64_AM::getShiftValue(MO.getImm()); 574 assert((ShiftVal == 8 || ShiftVal == 16) && "Invalid shift amount!"); 575 return ShiftVal == 8 ? 0 : 1; 576} 577 578unsigned AArch64MCCodeEmitter::fixMOVZ(const MCInst &MI, unsigned EncodedValue, 579 const MCSubtargetInfo &STI) const { 580 // If one of the signed fixup kinds is applied to a MOVZ instruction, the 581 // eventual result could be either a MOVZ or a MOVN. It's the MCCodeEmitter's 582 // job to ensure that any bits possibly affected by this are 0. This means we 583 // must zero out bit 30 (essentially emitting a MOVN). 584 MCOperand UImm16MO = MI.getOperand(1); 585 586 // Nothing to do if there's no fixup. 587 if (UImm16MO.isImm()) 588 return EncodedValue; 589 590 const AArch64MCExpr *A64E = cast<AArch64MCExpr>(UImm16MO.getExpr()); 591 switch (A64E->getKind()) { 592 case AArch64MCExpr::VK_DTPREL_G2: 593 case AArch64MCExpr::VK_DTPREL_G1: 594 case AArch64MCExpr::VK_DTPREL_G0: 595 case AArch64MCExpr::VK_GOTTPREL_G1: 596 case AArch64MCExpr::VK_TPREL_G2: 597 case AArch64MCExpr::VK_TPREL_G1: 598 case AArch64MCExpr::VK_TPREL_G0: 599 return EncodedValue & ~(1u << 30); 600 default: 601 // Nothing to do for an unsigned fixup. 602 return EncodedValue; 603 } 604 605 606 return EncodedValue & ~(1u << 30); 607} 608 609void AArch64MCCodeEmitter::EncodeInstruction(const MCInst &MI, raw_ostream &OS, 610 SmallVectorImpl<MCFixup> &Fixups, 611 const MCSubtargetInfo &STI) const { 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 MCFixupKind Fixup = MCFixupKind(AArch64::fixup_aarch64_tlsdesc_call); 617 Fixups.push_back(MCFixup::Create(0, MI.getOperand(0).getExpr(), Fixup)); 618 return; 619 } 620 621 uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI); 622 EmitConstant(Binary, 4, OS); 623 ++MCNumEmitted; // Keep track of the # of mi's emitted. 624} 625 626unsigned 627AArch64MCCodeEmitter::fixMulHigh(const MCInst &MI, 628 unsigned EncodedValue, 629 const MCSubtargetInfo &STI) const { 630 // The Ra field of SMULH and UMULH is unused: it should be assembled as 31 631 // (i.e. all bits 1) but is ignored by the processor. 632 EncodedValue |= 0x1f << 10; 633 return EncodedValue; 634} 635 636template<int hasRs, int hasRt2> unsigned 637AArch64MCCodeEmitter::fixLoadStoreExclusive(const MCInst &MI, 638 unsigned EncodedValue, 639 const MCSubtargetInfo &STI) const { 640 if (!hasRs) EncodedValue |= 0x001F0000; 641 if (!hasRt2) EncodedValue |= 0x00007C00; 642 643 return EncodedValue; 644} 645 646unsigned AArch64MCCodeEmitter::fixOneOperandFPComparison( 647 const MCInst &MI, unsigned EncodedValue, const MCSubtargetInfo &STI) const { 648 // The Rm field of FCMP and friends is unused - it should be assembled 649 // as 0, but is ignored by the processor. 650 EncodedValue &= ~(0x1f << 16); 651 return EncodedValue; 652} 653 654#include "AArch64GenMCCodeEmitter.inc" 655