1249259Sdim//=- AArch64/AArch64MCCodeEmitter.cpp - Convert AArch64 code to machine code =// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim// 10249259Sdim// This file implements the AArch64MCCodeEmitter class. 11249259Sdim// 12249259Sdim//===----------------------------------------------------------------------===// 13249259Sdim 14249259Sdim#define DEBUG_TYPE "mccodeemitter" 15249259Sdim#include "MCTargetDesc/AArch64FixupKinds.h" 16249259Sdim#include "MCTargetDesc/AArch64MCExpr.h" 17249259Sdim#include "MCTargetDesc/AArch64MCTargetDesc.h" 18249259Sdim#include "Utils/AArch64BaseInfo.h" 19249259Sdim#include "llvm/MC/MCCodeEmitter.h" 20249259Sdim#include "llvm/MC/MCContext.h" 21249259Sdim#include "llvm/MC/MCInst.h" 22249259Sdim#include "llvm/MC/MCInstrInfo.h" 23249259Sdim#include "llvm/MC/MCRegisterInfo.h" 24249259Sdim#include "llvm/MC/MCSubtargetInfo.h" 25249259Sdim#include "llvm/Support/ErrorHandling.h" 26249259Sdim#include "llvm/Support/raw_ostream.h" 27249259Sdim 28249259Sdimusing namespace llvm; 29249259Sdim 30249259Sdimnamespace { 31249259Sdimclass AArch64MCCodeEmitter : public MCCodeEmitter { 32249259Sdim AArch64MCCodeEmitter(const AArch64MCCodeEmitter &) LLVM_DELETED_FUNCTION; 33249259Sdim void operator=(const AArch64MCCodeEmitter &) LLVM_DELETED_FUNCTION; 34249259Sdim MCContext &Ctx; 35249259Sdim 36249259Sdimpublic: 37249259Sdim AArch64MCCodeEmitter(MCContext &ctx) : Ctx(ctx) {} 38249259Sdim 39249259Sdim ~AArch64MCCodeEmitter() {} 40249259Sdim 41249259Sdim unsigned getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx, 42249259Sdim SmallVectorImpl<MCFixup> &Fixups) const; 43249259Sdim 44249259Sdim unsigned getAdrpLabelOpValue(const MCInst &MI, unsigned OpIdx, 45249259Sdim SmallVectorImpl<MCFixup> &Fixups) const; 46249259Sdim 47249259Sdim template<int MemSize> 48249259Sdim unsigned getOffsetUImm12OpValue(const MCInst &MI, unsigned OpIdx, 49249259Sdim SmallVectorImpl<MCFixup> &Fixups) const { 50249259Sdim return getOffsetUImm12OpValue(MI, OpIdx, Fixups, MemSize); 51249259Sdim } 52249259Sdim 53249259Sdim unsigned getOffsetUImm12OpValue(const MCInst &MI, unsigned OpIdx, 54249259Sdim SmallVectorImpl<MCFixup> &Fixups, 55249259Sdim int MemSize) const; 56249259Sdim 57249259Sdim unsigned getBitfield32LSLOpValue(const MCInst &MI, unsigned OpIdx, 58249259Sdim SmallVectorImpl<MCFixup> &Fixups) const; 59249259Sdim unsigned getBitfield64LSLOpValue(const MCInst &MI, unsigned OpIdx, 60249259Sdim SmallVectorImpl<MCFixup> &Fixups) const; 61249259Sdim 62263508Sdim unsigned getShiftRightImm8(const MCInst &MI, unsigned Op, 63263508Sdim SmallVectorImpl<MCFixup> &Fixups) const; 64263508Sdim unsigned getShiftRightImm16(const MCInst &MI, unsigned Op, 65263508Sdim SmallVectorImpl<MCFixup> &Fixups) const; 66263508Sdim unsigned getShiftRightImm32(const MCInst &MI, unsigned Op, 67263508Sdim SmallVectorImpl<MCFixup> &Fixups) const; 68263508Sdim unsigned getShiftRightImm64(const MCInst &MI, unsigned Op, 69263508Sdim SmallVectorImpl<MCFixup> &Fixups) const; 70249259Sdim 71263508Sdim unsigned getShiftLeftImm8(const MCInst &MI, unsigned Op, 72263508Sdim SmallVectorImpl<MCFixup> &Fixups) const; 73263508Sdim unsigned getShiftLeftImm16(const MCInst &MI, unsigned Op, 74263508Sdim SmallVectorImpl<MCFixup> &Fixups) const; 75263508Sdim unsigned getShiftLeftImm32(const MCInst &MI, unsigned Op, 76263508Sdim SmallVectorImpl<MCFixup> &Fixups) const; 77263508Sdim unsigned getShiftLeftImm64(const MCInst &MI, unsigned Op, 78263508Sdim SmallVectorImpl<MCFixup> &Fixups) const; 79263508Sdim 80249259Sdim // Labels are handled mostly the same way: a symbol is needed, and 81249259Sdim // just gets some fixup attached. 82249259Sdim template<AArch64::Fixups fixupDesired> 83249259Sdim unsigned getLabelOpValue(const MCInst &MI, unsigned OpIdx, 84249259Sdim SmallVectorImpl<MCFixup> &Fixups) const; 85249259Sdim 86249259Sdim unsigned getLoadLitLabelOpValue(const MCInst &MI, unsigned OpIdx, 87249259Sdim SmallVectorImpl<MCFixup> &Fixups) const; 88249259Sdim 89249259Sdim 90249259Sdim unsigned getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx, 91249259Sdim SmallVectorImpl<MCFixup> &Fixups) const; 92249259Sdim 93249259Sdim 94249259Sdim unsigned getAddressWithFixup(const MCOperand &MO, 95249259Sdim unsigned FixupKind, 96249259Sdim SmallVectorImpl<MCFixup> &Fixups) const; 97249259Sdim 98249259Sdim 99249259Sdim // getBinaryCodeForInstr - TableGen'erated function for getting the 100249259Sdim // binary encoding for an instruction. 101249259Sdim uint64_t getBinaryCodeForInstr(const MCInst &MI, 102249259Sdim SmallVectorImpl<MCFixup> &Fixups) const; 103249259Sdim 104249259Sdim /// getMachineOpValue - Return binary encoding of operand. If the machine 105249259Sdim /// operand requires relocation, record the relocation and return zero. 106249259Sdim unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO, 107249259Sdim SmallVectorImpl<MCFixup> &Fixups) const; 108249259Sdim 109249259Sdim 110249259Sdim void EmitByte(unsigned char C, raw_ostream &OS) const { 111249259Sdim OS << (char)C; 112249259Sdim } 113249259Sdim 114249259Sdim void EmitInstruction(uint32_t Val, raw_ostream &OS) const { 115249259Sdim // Output the constant in little endian byte order. 116249259Sdim for (unsigned i = 0; i != 4; ++i) { 117249259Sdim EmitByte(Val & 0xff, OS); 118249259Sdim Val >>= 8; 119249259Sdim } 120249259Sdim } 121249259Sdim 122249259Sdim 123249259Sdim void EncodeInstruction(const MCInst &MI, raw_ostream &OS, 124249259Sdim SmallVectorImpl<MCFixup> &Fixups) const; 125249259Sdim 126249259Sdim template<int hasRs, int hasRt2> unsigned 127249259Sdim fixLoadStoreExclusive(const MCInst &MI, unsigned EncodedValue) const; 128249259Sdim 129249259Sdim unsigned fixMOVZ(const MCInst &MI, unsigned EncodedValue) const; 130249259Sdim 131249259Sdim unsigned fixMulHigh(const MCInst &MI, unsigned EncodedValue) const; 132249259Sdim 133249259Sdim 134249259Sdim}; 135249259Sdim 136249259Sdim} // end anonymous namespace 137249259Sdim 138249259Sdimunsigned AArch64MCCodeEmitter::getAddressWithFixup(const MCOperand &MO, 139249259Sdim unsigned FixupKind, 140249259Sdim SmallVectorImpl<MCFixup> &Fixups) const { 141249259Sdim if (!MO.isExpr()) { 142249259Sdim // This can occur for manually decoded or constructed MCInsts, but neither 143249259Sdim // the assembly-parser nor instruction selection will currently produce an 144249259Sdim // MCInst that's not a symbol reference. 145249259Sdim assert(MO.isImm() && "Unexpected address requested"); 146249259Sdim return MO.getImm(); 147249259Sdim } 148249259Sdim 149249259Sdim const MCExpr *Expr = MO.getExpr(); 150249259Sdim MCFixupKind Kind = MCFixupKind(FixupKind); 151249259Sdim Fixups.push_back(MCFixup::Create(0, Expr, Kind)); 152249259Sdim 153249259Sdim return 0; 154249259Sdim} 155249259Sdim 156249259Sdimunsigned AArch64MCCodeEmitter:: 157249259SdimgetOffsetUImm12OpValue(const MCInst &MI, unsigned OpIdx, 158249259Sdim SmallVectorImpl<MCFixup> &Fixups, 159249259Sdim int MemSize) const { 160249259Sdim const MCOperand &ImmOp = MI.getOperand(OpIdx); 161249259Sdim if (ImmOp.isImm()) 162249259Sdim return ImmOp.getImm(); 163249259Sdim 164249259Sdim assert(ImmOp.isExpr() && "Unexpected operand type"); 165249259Sdim const AArch64MCExpr *Expr = cast<AArch64MCExpr>(ImmOp.getExpr()); 166249259Sdim unsigned FixupKind; 167249259Sdim 168249259Sdim 169249259Sdim switch (Expr->getKind()) { 170249259Sdim default: llvm_unreachable("Unexpected operand modifier"); 171249259Sdim case AArch64MCExpr::VK_AARCH64_LO12: { 172263508Sdim static const unsigned FixupsBySize[] = { AArch64::fixup_a64_ldst8_lo12, 173263508Sdim AArch64::fixup_a64_ldst16_lo12, 174263508Sdim AArch64::fixup_a64_ldst32_lo12, 175263508Sdim AArch64::fixup_a64_ldst64_lo12, 176249259Sdim AArch64::fixup_a64_ldst128_lo12 }; 177249259Sdim assert(MemSize <= 16 && "Invalid fixup for operation"); 178249259Sdim FixupKind = FixupsBySize[Log2_32(MemSize)]; 179249259Sdim break; 180249259Sdim } 181249259Sdim case AArch64MCExpr::VK_AARCH64_GOT_LO12: 182249259Sdim assert(MemSize == 8 && "Invalid fixup for operation"); 183249259Sdim FixupKind = AArch64::fixup_a64_ld64_got_lo12_nc; 184249259Sdim break; 185249259Sdim case AArch64MCExpr::VK_AARCH64_DTPREL_LO12: { 186263508Sdim static const unsigned FixupsBySize[] = { 187263508Sdim AArch64::fixup_a64_ldst8_dtprel_lo12, 188263508Sdim AArch64::fixup_a64_ldst16_dtprel_lo12, 189263508Sdim AArch64::fixup_a64_ldst32_dtprel_lo12, 190263508Sdim AArch64::fixup_a64_ldst64_dtprel_lo12 191263508Sdim }; 192249259Sdim assert(MemSize <= 8 && "Invalid fixup for operation"); 193249259Sdim FixupKind = FixupsBySize[Log2_32(MemSize)]; 194249259Sdim break; 195249259Sdim } 196249259Sdim case AArch64MCExpr::VK_AARCH64_DTPREL_LO12_NC: { 197263508Sdim static const unsigned FixupsBySize[] = { 198263508Sdim AArch64::fixup_a64_ldst8_dtprel_lo12_nc, 199263508Sdim AArch64::fixup_a64_ldst16_dtprel_lo12_nc, 200263508Sdim AArch64::fixup_a64_ldst32_dtprel_lo12_nc, 201263508Sdim AArch64::fixup_a64_ldst64_dtprel_lo12_nc 202263508Sdim }; 203249259Sdim assert(MemSize <= 8 && "Invalid fixup for operation"); 204249259Sdim FixupKind = FixupsBySize[Log2_32(MemSize)]; 205249259Sdim break; 206249259Sdim } 207249259Sdim case AArch64MCExpr::VK_AARCH64_GOTTPREL_LO12: 208249259Sdim assert(MemSize == 8 && "Invalid fixup for operation"); 209249259Sdim FixupKind = AArch64::fixup_a64_ld64_gottprel_lo12_nc; 210249259Sdim break; 211249259Sdim case AArch64MCExpr::VK_AARCH64_TPREL_LO12:{ 212263508Sdim static const unsigned FixupsBySize[] = { 213263508Sdim AArch64::fixup_a64_ldst8_tprel_lo12, 214263508Sdim AArch64::fixup_a64_ldst16_tprel_lo12, 215263508Sdim AArch64::fixup_a64_ldst32_tprel_lo12, 216263508Sdim AArch64::fixup_a64_ldst64_tprel_lo12 217263508Sdim }; 218249259Sdim assert(MemSize <= 8 && "Invalid fixup for operation"); 219249259Sdim FixupKind = FixupsBySize[Log2_32(MemSize)]; 220249259Sdim break; 221249259Sdim } 222249259Sdim case AArch64MCExpr::VK_AARCH64_TPREL_LO12_NC: { 223263508Sdim static const unsigned FixupsBySize[] = { 224263508Sdim AArch64::fixup_a64_ldst8_tprel_lo12_nc, 225263508Sdim AArch64::fixup_a64_ldst16_tprel_lo12_nc, 226263508Sdim AArch64::fixup_a64_ldst32_tprel_lo12_nc, 227263508Sdim AArch64::fixup_a64_ldst64_tprel_lo12_nc 228263508Sdim }; 229249259Sdim assert(MemSize <= 8 && "Invalid fixup for operation"); 230249259Sdim FixupKind = FixupsBySize[Log2_32(MemSize)]; 231249259Sdim break; 232249259Sdim } 233249259Sdim case AArch64MCExpr::VK_AARCH64_TLSDESC_LO12: 234249259Sdim assert(MemSize == 8 && "Invalid fixup for operation"); 235249259Sdim FixupKind = AArch64::fixup_a64_tlsdesc_ld64_lo12_nc; 236249259Sdim break; 237249259Sdim } 238249259Sdim 239249259Sdim return getAddressWithFixup(ImmOp, FixupKind, Fixups); 240249259Sdim} 241249259Sdim 242249259Sdimunsigned 243249259SdimAArch64MCCodeEmitter::getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx, 244249259Sdim SmallVectorImpl<MCFixup> &Fixups) const { 245249259Sdim const MCOperand &MO = MI.getOperand(OpIdx); 246249259Sdim if (MO.isImm()) 247249259Sdim return static_cast<unsigned>(MO.getImm()); 248249259Sdim 249249259Sdim assert(MO.isExpr()); 250249259Sdim 251249259Sdim unsigned FixupKind = 0; 252249259Sdim switch(cast<AArch64MCExpr>(MO.getExpr())->getKind()) { 253249259Sdim default: llvm_unreachable("Invalid expression modifier"); 254249259Sdim case AArch64MCExpr::VK_AARCH64_LO12: 255249259Sdim FixupKind = AArch64::fixup_a64_add_lo12; break; 256249259Sdim case AArch64MCExpr::VK_AARCH64_DTPREL_HI12: 257249259Sdim FixupKind = AArch64::fixup_a64_add_dtprel_hi12; break; 258249259Sdim case AArch64MCExpr::VK_AARCH64_DTPREL_LO12: 259249259Sdim FixupKind = AArch64::fixup_a64_add_dtprel_lo12; break; 260249259Sdim case AArch64MCExpr::VK_AARCH64_DTPREL_LO12_NC: 261249259Sdim FixupKind = AArch64::fixup_a64_add_dtprel_lo12_nc; break; 262249259Sdim case AArch64MCExpr::VK_AARCH64_TPREL_HI12: 263249259Sdim FixupKind = AArch64::fixup_a64_add_tprel_hi12; break; 264249259Sdim case AArch64MCExpr::VK_AARCH64_TPREL_LO12: 265249259Sdim FixupKind = AArch64::fixup_a64_add_tprel_lo12; break; 266249259Sdim case AArch64MCExpr::VK_AARCH64_TPREL_LO12_NC: 267249259Sdim FixupKind = AArch64::fixup_a64_add_tprel_lo12_nc; break; 268249259Sdim case AArch64MCExpr::VK_AARCH64_TLSDESC_LO12: 269249259Sdim FixupKind = AArch64::fixup_a64_tlsdesc_add_lo12_nc; break; 270249259Sdim } 271249259Sdim 272249259Sdim return getAddressWithFixup(MO, FixupKind, Fixups); 273249259Sdim} 274249259Sdim 275249259Sdimunsigned 276249259SdimAArch64MCCodeEmitter::getAdrpLabelOpValue(const MCInst &MI, unsigned OpIdx, 277249259Sdim SmallVectorImpl<MCFixup> &Fixups) const { 278249259Sdim 279249259Sdim const MCOperand &MO = MI.getOperand(OpIdx); 280249259Sdim if (MO.isImm()) 281249259Sdim return static_cast<unsigned>(MO.getImm()); 282249259Sdim 283249259Sdim assert(MO.isExpr()); 284249259Sdim 285249259Sdim unsigned Modifier = AArch64MCExpr::VK_AARCH64_None; 286249259Sdim if (const AArch64MCExpr *Expr = dyn_cast<AArch64MCExpr>(MO.getExpr())) 287249259Sdim Modifier = Expr->getKind(); 288249259Sdim 289249259Sdim unsigned FixupKind = 0; 290249259Sdim switch(Modifier) { 291249259Sdim case AArch64MCExpr::VK_AARCH64_None: 292249259Sdim FixupKind = AArch64::fixup_a64_adr_prel_page; 293249259Sdim break; 294249259Sdim case AArch64MCExpr::VK_AARCH64_GOT: 295249259Sdim FixupKind = AArch64::fixup_a64_adr_prel_got_page; 296249259Sdim break; 297249259Sdim case AArch64MCExpr::VK_AARCH64_GOTTPREL: 298249259Sdim FixupKind = AArch64::fixup_a64_adr_gottprel_page; 299249259Sdim break; 300249259Sdim case AArch64MCExpr::VK_AARCH64_TLSDESC: 301249259Sdim FixupKind = AArch64::fixup_a64_tlsdesc_adr_page; 302249259Sdim break; 303249259Sdim default: 304249259Sdim llvm_unreachable("Unknown symbol reference kind for ADRP instruction"); 305249259Sdim } 306249259Sdim 307249259Sdim return getAddressWithFixup(MO, FixupKind, Fixups); 308249259Sdim} 309249259Sdim 310249259Sdimunsigned 311249259SdimAArch64MCCodeEmitter::getBitfield32LSLOpValue(const MCInst &MI, unsigned OpIdx, 312249259Sdim SmallVectorImpl<MCFixup> &Fixups) const { 313249259Sdim 314249259Sdim const MCOperand &MO = MI.getOperand(OpIdx); 315249259Sdim assert(MO.isImm() && "Only immediate expected for shift"); 316249259Sdim 317249259Sdim return ((32 - MO.getImm()) & 0x1f) | (31 - MO.getImm()) << 6; 318249259Sdim} 319249259Sdim 320249259Sdimunsigned 321249259SdimAArch64MCCodeEmitter::getBitfield64LSLOpValue(const MCInst &MI, unsigned OpIdx, 322249259Sdim SmallVectorImpl<MCFixup> &Fixups) const { 323249259Sdim 324249259Sdim const MCOperand &MO = MI.getOperand(OpIdx); 325249259Sdim assert(MO.isImm() && "Only immediate expected for shift"); 326249259Sdim 327249259Sdim return ((64 - MO.getImm()) & 0x3f) | (63 - MO.getImm()) << 6; 328249259Sdim} 329249259Sdim 330263508Sdimunsigned AArch64MCCodeEmitter::getShiftRightImm8( 331263508Sdim const MCInst &MI, unsigned Op, SmallVectorImpl<MCFixup> &Fixups) const { 332263508Sdim return 8 - MI.getOperand(Op).getImm(); 333263508Sdim} 334249259Sdim 335263508Sdimunsigned AArch64MCCodeEmitter::getShiftRightImm16( 336263508Sdim const MCInst &MI, unsigned Op, SmallVectorImpl<MCFixup> &Fixups) const { 337263508Sdim return 16 - MI.getOperand(Op).getImm(); 338263508Sdim} 339263508Sdim 340263508Sdimunsigned AArch64MCCodeEmitter::getShiftRightImm32( 341263508Sdim const MCInst &MI, unsigned Op, SmallVectorImpl<MCFixup> &Fixups) const { 342263508Sdim return 32 - MI.getOperand(Op).getImm(); 343263508Sdim} 344263508Sdim 345263508Sdimunsigned AArch64MCCodeEmitter::getShiftRightImm64( 346263508Sdim const MCInst &MI, unsigned Op, SmallVectorImpl<MCFixup> &Fixups) const { 347263508Sdim return 64 - MI.getOperand(Op).getImm(); 348263508Sdim} 349263508Sdim 350263508Sdimunsigned AArch64MCCodeEmitter::getShiftLeftImm8( 351263508Sdim const MCInst &MI, unsigned Op, SmallVectorImpl<MCFixup> &Fixups) const { 352263508Sdim return MI.getOperand(Op).getImm() - 8; 353263508Sdim} 354263508Sdim 355263508Sdimunsigned AArch64MCCodeEmitter::getShiftLeftImm16( 356263508Sdim const MCInst &MI, unsigned Op, SmallVectorImpl<MCFixup> &Fixups) const { 357263508Sdim return MI.getOperand(Op).getImm() - 16; 358263508Sdim} 359263508Sdim 360263508Sdimunsigned AArch64MCCodeEmitter::getShiftLeftImm32( 361263508Sdim const MCInst &MI, unsigned Op, SmallVectorImpl<MCFixup> &Fixups) const { 362263508Sdim return MI.getOperand(Op).getImm() - 32; 363263508Sdim} 364263508Sdim 365263508Sdimunsigned AArch64MCCodeEmitter::getShiftLeftImm64( 366263508Sdim const MCInst &MI, unsigned Op, SmallVectorImpl<MCFixup> &Fixups) const { 367263508Sdim return MI.getOperand(Op).getImm() - 64; 368263508Sdim} 369263508Sdim 370249259Sdimtemplate<AArch64::Fixups fixupDesired> unsigned 371249259SdimAArch64MCCodeEmitter::getLabelOpValue(const MCInst &MI, 372249259Sdim unsigned OpIdx, 373249259Sdim SmallVectorImpl<MCFixup> &Fixups) const { 374249259Sdim const MCOperand &MO = MI.getOperand(OpIdx); 375249259Sdim 376249259Sdim if (MO.isExpr()) 377249259Sdim return getAddressWithFixup(MO, fixupDesired, Fixups); 378249259Sdim 379249259Sdim assert(MO.isImm()); 380249259Sdim return MO.getImm(); 381249259Sdim} 382249259Sdim 383249259Sdimunsigned 384249259SdimAArch64MCCodeEmitter::getLoadLitLabelOpValue(const MCInst &MI, 385249259Sdim unsigned OpIdx, 386249259Sdim SmallVectorImpl<MCFixup> &Fixups) const { 387249259Sdim const MCOperand &MO = MI.getOperand(OpIdx); 388249259Sdim 389249259Sdim if (MO.isImm()) 390249259Sdim return MO.getImm(); 391249259Sdim 392249259Sdim assert(MO.isExpr()); 393249259Sdim 394249259Sdim unsigned FixupKind; 395249259Sdim if (isa<AArch64MCExpr>(MO.getExpr())) { 396249259Sdim assert(dyn_cast<AArch64MCExpr>(MO.getExpr())->getKind() 397249259Sdim == AArch64MCExpr::VK_AARCH64_GOTTPREL 398249259Sdim && "Invalid symbol modifier for literal load"); 399249259Sdim FixupKind = AArch64::fixup_a64_ld_gottprel_prel19; 400249259Sdim } else { 401249259Sdim FixupKind = AArch64::fixup_a64_ld_prel; 402249259Sdim } 403249259Sdim 404249259Sdim return getAddressWithFixup(MO, FixupKind, Fixups); 405249259Sdim} 406249259Sdim 407249259Sdim 408249259Sdimunsigned 409249259SdimAArch64MCCodeEmitter::getMachineOpValue(const MCInst &MI, 410249259Sdim const MCOperand &MO, 411249259Sdim SmallVectorImpl<MCFixup> &Fixups) const { 412249259Sdim if (MO.isReg()) { 413263508Sdim return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 414249259Sdim } else if (MO.isImm()) { 415249259Sdim return static_cast<unsigned>(MO.getImm()); 416249259Sdim } 417249259Sdim 418249259Sdim llvm_unreachable("Unable to encode MCOperand!"); 419249259Sdim return 0; 420249259Sdim} 421249259Sdim 422249259Sdimunsigned 423249259SdimAArch64MCCodeEmitter::getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx, 424249259Sdim SmallVectorImpl<MCFixup> &Fixups) const { 425249259Sdim const MCOperand &UImm16MO = MI.getOperand(OpIdx); 426249259Sdim const MCOperand &ShiftMO = MI.getOperand(OpIdx + 1); 427249259Sdim 428249259Sdim unsigned Result = static_cast<unsigned>(ShiftMO.getImm()) << 16; 429249259Sdim 430249259Sdim if (UImm16MO.isImm()) { 431249259Sdim Result |= UImm16MO.getImm(); 432249259Sdim return Result; 433249259Sdim } 434249259Sdim 435249259Sdim const AArch64MCExpr *A64E = cast<AArch64MCExpr>(UImm16MO.getExpr()); 436249259Sdim AArch64::Fixups requestedFixup; 437249259Sdim switch (A64E->getKind()) { 438249259Sdim default: llvm_unreachable("unexpected expression modifier"); 439249259Sdim case AArch64MCExpr::VK_AARCH64_ABS_G0: 440249259Sdim requestedFixup = AArch64::fixup_a64_movw_uabs_g0; break; 441249259Sdim case AArch64MCExpr::VK_AARCH64_ABS_G0_NC: 442249259Sdim requestedFixup = AArch64::fixup_a64_movw_uabs_g0_nc; break; 443249259Sdim case AArch64MCExpr::VK_AARCH64_ABS_G1: 444249259Sdim requestedFixup = AArch64::fixup_a64_movw_uabs_g1; break; 445249259Sdim case AArch64MCExpr::VK_AARCH64_ABS_G1_NC: 446249259Sdim requestedFixup = AArch64::fixup_a64_movw_uabs_g1_nc; break; 447249259Sdim case AArch64MCExpr::VK_AARCH64_ABS_G2: 448249259Sdim requestedFixup = AArch64::fixup_a64_movw_uabs_g2; break; 449249259Sdim case AArch64MCExpr::VK_AARCH64_ABS_G2_NC: 450249259Sdim requestedFixup = AArch64::fixup_a64_movw_uabs_g2_nc; break; 451249259Sdim case AArch64MCExpr::VK_AARCH64_ABS_G3: 452249259Sdim requestedFixup = AArch64::fixup_a64_movw_uabs_g3; break; 453249259Sdim case AArch64MCExpr::VK_AARCH64_SABS_G0: 454249259Sdim requestedFixup = AArch64::fixup_a64_movw_sabs_g0; break; 455249259Sdim case AArch64MCExpr::VK_AARCH64_SABS_G1: 456249259Sdim requestedFixup = AArch64::fixup_a64_movw_sabs_g1; break; 457249259Sdim case AArch64MCExpr::VK_AARCH64_SABS_G2: 458249259Sdim requestedFixup = AArch64::fixup_a64_movw_sabs_g2; break; 459249259Sdim case AArch64MCExpr::VK_AARCH64_DTPREL_G2: 460249259Sdim requestedFixup = AArch64::fixup_a64_movw_dtprel_g2; break; 461249259Sdim case AArch64MCExpr::VK_AARCH64_DTPREL_G1: 462249259Sdim requestedFixup = AArch64::fixup_a64_movw_dtprel_g1; break; 463249259Sdim case AArch64MCExpr::VK_AARCH64_DTPREL_G1_NC: 464249259Sdim requestedFixup = AArch64::fixup_a64_movw_dtprel_g1_nc; break; 465249259Sdim case AArch64MCExpr::VK_AARCH64_DTPREL_G0: 466249259Sdim requestedFixup = AArch64::fixup_a64_movw_dtprel_g0; break; 467249259Sdim case AArch64MCExpr::VK_AARCH64_DTPREL_G0_NC: 468249259Sdim requestedFixup = AArch64::fixup_a64_movw_dtprel_g0_nc; break; 469249259Sdim case AArch64MCExpr::VK_AARCH64_GOTTPREL_G1: 470249259Sdim requestedFixup = AArch64::fixup_a64_movw_gottprel_g1; break; 471249259Sdim case AArch64MCExpr::VK_AARCH64_GOTTPREL_G0_NC: 472249259Sdim requestedFixup = AArch64::fixup_a64_movw_gottprel_g0_nc; break; 473249259Sdim case AArch64MCExpr::VK_AARCH64_TPREL_G2: 474249259Sdim requestedFixup = AArch64::fixup_a64_movw_tprel_g2; break; 475249259Sdim case AArch64MCExpr::VK_AARCH64_TPREL_G1: 476249259Sdim requestedFixup = AArch64::fixup_a64_movw_tprel_g1; break; 477249259Sdim case AArch64MCExpr::VK_AARCH64_TPREL_G1_NC: 478249259Sdim requestedFixup = AArch64::fixup_a64_movw_tprel_g1_nc; break; 479249259Sdim case AArch64MCExpr::VK_AARCH64_TPREL_G0: 480249259Sdim requestedFixup = AArch64::fixup_a64_movw_tprel_g0; break; 481249259Sdim case AArch64MCExpr::VK_AARCH64_TPREL_G0_NC: 482249259Sdim requestedFixup = AArch64::fixup_a64_movw_tprel_g0_nc; break; 483249259Sdim } 484249259Sdim 485249259Sdim return Result | getAddressWithFixup(UImm16MO, requestedFixup, Fixups); 486249259Sdim} 487249259Sdim 488249259Sdimtemplate<int hasRs, int hasRt2> unsigned 489249259SdimAArch64MCCodeEmitter::fixLoadStoreExclusive(const MCInst &MI, 490249259Sdim unsigned EncodedValue) const { 491249259Sdim if (!hasRs) EncodedValue |= 0x001F0000; 492249259Sdim if (!hasRt2) EncodedValue |= 0x00007C00; 493249259Sdim 494249259Sdim return EncodedValue; 495249259Sdim} 496249259Sdim 497249259Sdimunsigned 498249259SdimAArch64MCCodeEmitter::fixMOVZ(const MCInst &MI, unsigned EncodedValue) const { 499249259Sdim // If one of the signed fixup kinds is applied to a MOVZ instruction, the 500249259Sdim // eventual result could be either a MOVZ or a MOVN. It's the MCCodeEmitter's 501249259Sdim // job to ensure that any bits possibly affected by this are 0. This means we 502249259Sdim // must zero out bit 30 (essentially emitting a MOVN). 503249259Sdim MCOperand UImm16MO = MI.getOperand(1); 504249259Sdim 505249259Sdim // Nothing to do if there's no fixup. 506249259Sdim if (UImm16MO.isImm()) 507249259Sdim return EncodedValue; 508249259Sdim 509249259Sdim const AArch64MCExpr *A64E = cast<AArch64MCExpr>(UImm16MO.getExpr()); 510249259Sdim switch (A64E->getKind()) { 511249259Sdim case AArch64MCExpr::VK_AARCH64_SABS_G0: 512249259Sdim case AArch64MCExpr::VK_AARCH64_SABS_G1: 513249259Sdim case AArch64MCExpr::VK_AARCH64_SABS_G2: 514249259Sdim case AArch64MCExpr::VK_AARCH64_DTPREL_G2: 515249259Sdim case AArch64MCExpr::VK_AARCH64_DTPREL_G1: 516249259Sdim case AArch64MCExpr::VK_AARCH64_DTPREL_G0: 517249259Sdim case AArch64MCExpr::VK_AARCH64_GOTTPREL_G1: 518249259Sdim case AArch64MCExpr::VK_AARCH64_TPREL_G2: 519249259Sdim case AArch64MCExpr::VK_AARCH64_TPREL_G1: 520249259Sdim case AArch64MCExpr::VK_AARCH64_TPREL_G0: 521249259Sdim return EncodedValue & ~(1u << 30); 522249259Sdim default: 523249259Sdim // Nothing to do for an unsigned fixup. 524249259Sdim return EncodedValue; 525249259Sdim } 526249259Sdim 527249259Sdim llvm_unreachable("Should have returned by now"); 528249259Sdim} 529249259Sdim 530249259Sdimunsigned 531249259SdimAArch64MCCodeEmitter::fixMulHigh(const MCInst &MI, 532249259Sdim unsigned EncodedValue) const { 533249259Sdim // The Ra field of SMULH and UMULH is unused: it should be assembled as 31 534249259Sdim // (i.e. all bits 1) but is ignored by the processor. 535249259Sdim EncodedValue |= 0x1f << 10; 536249259Sdim return EncodedValue; 537249259Sdim} 538249259Sdim 539249259SdimMCCodeEmitter *llvm::createAArch64MCCodeEmitter(const MCInstrInfo &MCII, 540249259Sdim const MCRegisterInfo &MRI, 541249259Sdim const MCSubtargetInfo &STI, 542249259Sdim MCContext &Ctx) { 543249259Sdim return new AArch64MCCodeEmitter(Ctx); 544249259Sdim} 545249259Sdim 546249259Sdimvoid AArch64MCCodeEmitter:: 547249259SdimEncodeInstruction(const MCInst &MI, raw_ostream &OS, 548249259Sdim SmallVectorImpl<MCFixup> &Fixups) const { 549249259Sdim if (MI.getOpcode() == AArch64::TLSDESCCALL) { 550249259Sdim // This is a directive which applies an R_AARCH64_TLSDESC_CALL to the 551249259Sdim // following (BLR) instruction. It doesn't emit any code itself so it 552249259Sdim // doesn't go through the normal TableGenerated channels. 553249259Sdim MCFixupKind Fixup = MCFixupKind(AArch64::fixup_a64_tlsdesc_call); 554249259Sdim const MCExpr *Expr; 555249259Sdim Expr = AArch64MCExpr::CreateTLSDesc(MI.getOperand(0).getExpr(), Ctx); 556249259Sdim Fixups.push_back(MCFixup::Create(0, Expr, Fixup)); 557249259Sdim return; 558249259Sdim } 559249259Sdim 560249259Sdim uint32_t Binary = getBinaryCodeForInstr(MI, Fixups); 561249259Sdim 562249259Sdim EmitInstruction(Binary, OS); 563249259Sdim} 564249259Sdim 565249259Sdim 566249259Sdim#include "AArch64GenMCCodeEmitter.inc" 567