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 222 assert(MO.isImm() && "did not expect relocated expression"); 223 return static_cast<unsigned>(MO.getImm()); 224} 225 226template<unsigned FixupKind> uint32_t 227AArch64MCCodeEmitter::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. 247uint32_t 248AArch64MCCodeEmitter::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. 273uint32_t 274AArch64MCCodeEmitter::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. 301uint32_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. 322uint32_t 323AArch64MCCodeEmitter::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 342uint32_t 343AArch64MCCodeEmitter::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 351uint32_t 352AArch64MCCodeEmitter::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. 371uint32_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. 392uint32_t 393AArch64MCCodeEmitter::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 420uint32_t 421AArch64MCCodeEmitter::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 assert(false && "Invalid value for vector shift amount!"); 441 return 0; 442} 443 444uint32_t 445AArch64MCCodeEmitter::getSIMDShift64OpValue(const MCInst &MI, unsigned OpIdx, 446 SmallVectorImpl<MCFixup> &Fixups, 447 const MCSubtargetInfo &STI) const { 448 const MCOperand &MO = MI.getOperand(OpIdx); 449 assert(MO.isImm() && "Expected an immediate value for the shift amount!"); 450 return 64 - (MO.getImm()); 451} 452 453uint32_t AArch64MCCodeEmitter::getSIMDShift64_32OpValue( 454 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups, 455 const MCSubtargetInfo &STI) const { 456 const MCOperand &MO = MI.getOperand(OpIdx); 457 assert(MO.isImm() && "Expected an immediate value for the shift amount!"); 458 return 64 - (MO.getImm() | 32); 459} 460 461uint32_t 462AArch64MCCodeEmitter::getSIMDShift32OpValue(const MCInst &MI, unsigned OpIdx, 463 SmallVectorImpl<MCFixup> &Fixups, 464 const MCSubtargetInfo &STI) const { 465 const MCOperand &MO = MI.getOperand(OpIdx); 466 assert(MO.isImm() && "Expected an immediate value for the shift amount!"); 467 return 32 - (MO.getImm() | 16); 468} 469 470uint32_t 471AArch64MCCodeEmitter::getSIMDShift16OpValue(const MCInst &MI, unsigned OpIdx, 472 SmallVectorImpl<MCFixup> &Fixups, 473 const MCSubtargetInfo &STI) const { 474 const MCOperand &MO = MI.getOperand(OpIdx); 475 assert(MO.isImm() && "Expected an immediate value for the shift amount!"); 476 return 16 - (MO.getImm() | 8); 477} 478 479/// getFixedPointScaleOpValue - Return the encoded value for the 480// FP-to-fixed-point scale factor. 481uint32_t AArch64MCCodeEmitter::getFixedPointScaleOpValue( 482 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups, 483 const MCSubtargetInfo &STI) const { 484 const MCOperand &MO = MI.getOperand(OpIdx); 485 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 486 return 64 - MO.getImm(); 487} 488 489uint32_t 490AArch64MCCodeEmitter::getVecShiftR64OpValue(const MCInst &MI, unsigned OpIdx, 491 SmallVectorImpl<MCFixup> &Fixups, 492 const MCSubtargetInfo &STI) const { 493 const MCOperand &MO = MI.getOperand(OpIdx); 494 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 495 return 64 - MO.getImm(); 496} 497 498uint32_t 499AArch64MCCodeEmitter::getVecShiftR32OpValue(const MCInst &MI, unsigned OpIdx, 500 SmallVectorImpl<MCFixup> &Fixups, 501 const MCSubtargetInfo &STI) const { 502 const MCOperand &MO = MI.getOperand(OpIdx); 503 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 504 return 32 - MO.getImm(); 505} 506 507uint32_t 508AArch64MCCodeEmitter::getVecShiftR16OpValue(const MCInst &MI, unsigned OpIdx, 509 SmallVectorImpl<MCFixup> &Fixups, 510 const MCSubtargetInfo &STI) const { 511 const MCOperand &MO = MI.getOperand(OpIdx); 512 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 513 return 16 - MO.getImm(); 514} 515 516uint32_t 517AArch64MCCodeEmitter::getVecShiftR8OpValue(const MCInst &MI, unsigned OpIdx, 518 SmallVectorImpl<MCFixup> &Fixups, 519 const MCSubtargetInfo &STI) const { 520 const MCOperand &MO = MI.getOperand(OpIdx); 521 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 522 return 8 - MO.getImm(); 523} 524 525uint32_t 526AArch64MCCodeEmitter::getVecShiftL64OpValue(const MCInst &MI, unsigned OpIdx, 527 SmallVectorImpl<MCFixup> &Fixups, 528 const MCSubtargetInfo &STI) const { 529 const MCOperand &MO = MI.getOperand(OpIdx); 530 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 531 return MO.getImm() - 64; 532} 533 534uint32_t 535AArch64MCCodeEmitter::getVecShiftL32OpValue(const MCInst &MI, unsigned OpIdx, 536 SmallVectorImpl<MCFixup> &Fixups, 537 const MCSubtargetInfo &STI) const { 538 const MCOperand &MO = MI.getOperand(OpIdx); 539 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 540 return MO.getImm() - 32; 541} 542 543uint32_t 544AArch64MCCodeEmitter::getVecShiftL16OpValue(const MCInst &MI, unsigned OpIdx, 545 SmallVectorImpl<MCFixup> &Fixups, 546 const MCSubtargetInfo &STI) const { 547 const MCOperand &MO = MI.getOperand(OpIdx); 548 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 549 return MO.getImm() - 16; 550} 551 552uint32_t 553AArch64MCCodeEmitter::getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx, 554 SmallVectorImpl<MCFixup> &Fixups, 555 const MCSubtargetInfo &STI) const { 556 const MCOperand &MO = MI.getOperand(OpIdx); 557 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 558 return MO.getImm() - 8; 559} 560 561/// getMoveVecShifterOpValue - Return the encoded value for the vector move 562/// shifter (MSL). 563uint32_t AArch64MCCodeEmitter::getMoveVecShifterOpValue( 564 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups, 565 const MCSubtargetInfo &STI) const { 566 const MCOperand &MO = MI.getOperand(OpIdx); 567 assert(MO.isImm() && 568 "Expected an immediate value for the move shift amount!"); 569 unsigned ShiftVal = AArch64_AM::getShiftValue(MO.getImm()); 570 assert((ShiftVal == 8 || ShiftVal == 16) && "Invalid shift amount!"); 571 return ShiftVal == 8 ? 0 : 1; 572} 573 574unsigned AArch64MCCodeEmitter::fixMOVZ(const MCInst &MI, unsigned EncodedValue, 575 const MCSubtargetInfo &STI) const { 576 // If one of the signed fixup kinds is applied to a MOVZ instruction, the 577 // eventual result could be either a MOVZ or a MOVN. It's the MCCodeEmitter's 578 // job to ensure that any bits possibly affected by this are 0. This means we 579 // must zero out bit 30 (essentially emitting a MOVN). 580 MCOperand UImm16MO = MI.getOperand(1); 581 582 // Nothing to do if there's no fixup. 583 if (UImm16MO.isImm()) 584 return EncodedValue; 585 586 const AArch64MCExpr *A64E = cast<AArch64MCExpr>(UImm16MO.getExpr()); 587 switch (A64E->getKind()) { 588 case AArch64MCExpr::VK_DTPREL_G2: 589 case AArch64MCExpr::VK_DTPREL_G1: 590 case AArch64MCExpr::VK_DTPREL_G0: 591 case AArch64MCExpr::VK_GOTTPREL_G1: 592 case AArch64MCExpr::VK_TPREL_G2: 593 case AArch64MCExpr::VK_TPREL_G1: 594 case AArch64MCExpr::VK_TPREL_G0: 595 return EncodedValue & ~(1u << 30); 596 default: 597 // Nothing to do for an unsigned fixup. 598 return EncodedValue; 599 } 600 601 602 return EncodedValue & ~(1u << 30); 603} 604 605void AArch64MCCodeEmitter::EncodeInstruction(const MCInst &MI, raw_ostream &OS, 606 SmallVectorImpl<MCFixup> &Fixups, 607 const MCSubtargetInfo &STI) const { 608 if (MI.getOpcode() == AArch64::TLSDESCCALL) { 609 // This is a directive which applies an R_AARCH64_TLSDESC_CALL to the 610 // following (BLR) instruction. It doesn't emit any code itself so it 611 // doesn't go through the normal TableGenerated channels. 612 MCFixupKind Fixup = MCFixupKind(AArch64::fixup_aarch64_tlsdesc_call); 613 Fixups.push_back(MCFixup::Create(0, MI.getOperand(0).getExpr(), Fixup)); 614 return; 615 } 616 617 uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI); 618 EmitConstant(Binary, 4, OS); 619 ++MCNumEmitted; // Keep track of the # of mi's emitted. 620} 621 622unsigned 623AArch64MCCodeEmitter::fixMulHigh(const MCInst &MI, 624 unsigned EncodedValue, 625 const MCSubtargetInfo &STI) const { 626 // The Ra field of SMULH and UMULH is unused: it should be assembled as 31 627 // (i.e. all bits 1) but is ignored by the processor. 628 EncodedValue |= 0x1f << 10; 629 return EncodedValue; 630} 631 632template<int hasRs, int hasRt2> unsigned 633AArch64MCCodeEmitter::fixLoadStoreExclusive(const MCInst &MI, 634 unsigned EncodedValue, 635 const MCSubtargetInfo &STI) const { 636 if (!hasRs) EncodedValue |= 0x001F0000; 637 if (!hasRt2) EncodedValue |= 0x00007C00; 638 639 return EncodedValue; 640} 641 642unsigned AArch64MCCodeEmitter::fixOneOperandFPComparison( 643 const MCInst &MI, unsigned EncodedValue, const MCSubtargetInfo &STI) const { 644 // The Rm field of FCMP and friends is unused - it should be assembled 645 // as 0, but is ignored by the processor. 646 EncodedValue &= ~(0x1f << 16); 647 return EncodedValue; 648} 649 650#include "AArch64GenMCCodeEmitter.inc" 651