ARMMCCodeEmitter.cpp revision 249423
1226584Sdim//===-- ARM/ARMMCCodeEmitter.cpp - Convert ARM code to machine code -------===// 2226584Sdim// 3226584Sdim// The LLVM Compiler Infrastructure 4226584Sdim// 5226584Sdim// This file is distributed under the University of Illinois Open Source 6226584Sdim// License. See LICENSE.TXT for details. 7226584Sdim// 8226584Sdim//===----------------------------------------------------------------------===// 9226584Sdim// 10226584Sdim// This file implements the ARMMCCodeEmitter class. 11226584Sdim// 12226584Sdim//===----------------------------------------------------------------------===// 13226584Sdim 14226584Sdim#define DEBUG_TYPE "mccodeemitter" 15249423Sdim#include "MCTargetDesc/ARMMCTargetDesc.h" 16226584Sdim#include "MCTargetDesc/ARMAddressingModes.h" 17226584Sdim#include "MCTargetDesc/ARMBaseInfo.h" 18226584Sdim#include "MCTargetDesc/ARMFixupKinds.h" 19226584Sdim#include "MCTargetDesc/ARMMCExpr.h" 20249423Sdim#include "llvm/ADT/APFloat.h" 21249423Sdim#include "llvm/ADT/Statistic.h" 22226584Sdim#include "llvm/MC/MCCodeEmitter.h" 23239462Sdim#include "llvm/MC/MCContext.h" 24226584Sdim#include "llvm/MC/MCExpr.h" 25226584Sdim#include "llvm/MC/MCInst.h" 26226584Sdim#include "llvm/MC/MCInstrInfo.h" 27226584Sdim#include "llvm/MC/MCRegisterInfo.h" 28226584Sdim#include "llvm/MC/MCSubtargetInfo.h" 29226584Sdim#include "llvm/Support/raw_ostream.h" 30226584Sdim 31226584Sdimusing namespace llvm; 32226584Sdim 33226584SdimSTATISTIC(MCNumEmitted, "Number of MC instructions emitted."); 34226584SdimSTATISTIC(MCNumCPRelocations, "Number of constant pool relocations created."); 35226584Sdim 36226584Sdimnamespace { 37226584Sdimclass ARMMCCodeEmitter : public MCCodeEmitter { 38243830Sdim ARMMCCodeEmitter(const ARMMCCodeEmitter &) LLVM_DELETED_FUNCTION; 39243830Sdim void operator=(const ARMMCCodeEmitter &) LLVM_DELETED_FUNCTION; 40226584Sdim const MCInstrInfo &MCII; 41226584Sdim const MCSubtargetInfo &STI; 42239462Sdim const MCContext &CTX; 43226584Sdim 44226584Sdimpublic: 45226584Sdim ARMMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti, 46226584Sdim MCContext &ctx) 47239462Sdim : MCII(mcii), STI(sti), CTX(ctx) { 48226584Sdim } 49226584Sdim 50226584Sdim ~ARMMCCodeEmitter() {} 51226584Sdim 52226584Sdim bool isThumb() const { 53226584Sdim // FIXME: Can tablegen auto-generate this? 54226584Sdim return (STI.getFeatureBits() & ARM::ModeThumb) != 0; 55226584Sdim } 56226584Sdim bool isThumb2() const { 57226584Sdim return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) != 0; 58226584Sdim } 59226584Sdim bool isTargetDarwin() const { 60226584Sdim Triple TT(STI.getTargetTriple()); 61226584Sdim Triple::OSType OS = TT.getOS(); 62226584Sdim return OS == Triple::Darwin || OS == Triple::MacOSX || OS == Triple::IOS; 63226584Sdim } 64226584Sdim 65226584Sdim unsigned getMachineSoImmOpValue(unsigned SoImm) const; 66226584Sdim 67226584Sdim // getBinaryCodeForInstr - TableGen'erated function for getting the 68226584Sdim // binary encoding for an instruction. 69234353Sdim uint64_t getBinaryCodeForInstr(const MCInst &MI, 70226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 71226584Sdim 72226584Sdim /// getMachineOpValue - Return binary encoding of operand. If the machine 73226584Sdim /// operand requires relocation, record the relocation and return zero. 74226584Sdim unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO, 75226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 76226584Sdim 77226584Sdim /// getHiLo16ImmOpValue - Return the encoding for the hi / low 16-bit of 78226584Sdim /// the specified operand. This is used for operands with :lower16: and 79226584Sdim /// :upper16: prefixes. 80226584Sdim uint32_t getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx, 81226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 82226584Sdim 83226584Sdim bool EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx, 84226584Sdim unsigned &Reg, unsigned &Imm, 85226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 86226584Sdim 87226584Sdim /// getThumbBLTargetOpValue - Return encoding info for Thumb immediate 88226584Sdim /// BL branch target. 89226584Sdim uint32_t getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx, 90226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 91226584Sdim 92226584Sdim /// getThumbBLXTargetOpValue - Return encoding info for Thumb immediate 93226584Sdim /// BLX branch target. 94226584Sdim uint32_t getThumbBLXTargetOpValue(const MCInst &MI, unsigned OpIdx, 95226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 96226584Sdim 97226584Sdim /// getThumbBRTargetOpValue - Return encoding info for Thumb branch target. 98226584Sdim uint32_t getThumbBRTargetOpValue(const MCInst &MI, unsigned OpIdx, 99226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 100226584Sdim 101226584Sdim /// getThumbBCCTargetOpValue - Return encoding info for Thumb branch target. 102226584Sdim uint32_t getThumbBCCTargetOpValue(const MCInst &MI, unsigned OpIdx, 103226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 104226584Sdim 105226584Sdim /// getThumbCBTargetOpValue - Return encoding info for Thumb branch target. 106226584Sdim uint32_t getThumbCBTargetOpValue(const MCInst &MI, unsigned OpIdx, 107226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 108226584Sdim 109226584Sdim /// getBranchTargetOpValue - Return encoding info for 24-bit immediate 110226584Sdim /// branch target. 111226584Sdim uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 112226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 113226584Sdim 114226584Sdim /// getUnconditionalBranchTargetOpValue - Return encoding info for 24-bit 115226584Sdim /// immediate Thumb2 direct branch target. 116226584Sdim uint32_t getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 117226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 118226584Sdim 119226584Sdim /// getARMBranchTargetOpValue - Return encoding info for 24-bit immediate 120226584Sdim /// branch target. 121226584Sdim uint32_t getARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 122226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 123234353Sdim uint32_t getARMBLTargetOpValue(const MCInst &MI, unsigned OpIdx, 124234353Sdim SmallVectorImpl<MCFixup> &Fixups) const; 125226584Sdim uint32_t getARMBLXTargetOpValue(const MCInst &MI, unsigned OpIdx, 126234353Sdim SmallVectorImpl<MCFixup> &Fixups) const; 127226584Sdim 128226584Sdim /// getAdrLabelOpValue - Return encoding info for 12-bit immediate 129226584Sdim /// ADR label target. 130226584Sdim uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, 131226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 132226584Sdim uint32_t getThumbAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, 133226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 134226584Sdim uint32_t getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx, 135226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 136226584Sdim 137226584Sdim 138226584Sdim /// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12' 139226584Sdim /// operand. 140226584Sdim uint32_t getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx, 141226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 142226584Sdim 143226584Sdim /// getThumbAddrModeRegRegOpValue - Return encoding for 'reg + reg' operand. 144226584Sdim uint32_t getThumbAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx, 145226584Sdim SmallVectorImpl<MCFixup> &Fixups)const; 146226584Sdim 147226584Sdim /// getT2AddrModeImm8s4OpValue - Return encoding info for 'reg +/- imm8<<2' 148226584Sdim /// operand. 149226584Sdim uint32_t getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx, 150226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 151226584Sdim 152226584Sdim /// getT2AddrModeImm0_1020s4OpValue - Return encoding info for 'reg + imm8<<2' 153226584Sdim /// operand. 154226584Sdim uint32_t getT2AddrModeImm0_1020s4OpValue(const MCInst &MI, unsigned OpIdx, 155226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 156226584Sdim 157226584Sdim /// getT2Imm8s4OpValue - Return encoding info for '+/- imm8<<2' 158226584Sdim /// operand. 159226584Sdim uint32_t getT2Imm8s4OpValue(const MCInst &MI, unsigned OpIdx, 160226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 161226584Sdim 162226584Sdim 163226584Sdim /// getLdStSORegOpValue - Return encoding info for 'reg +/- reg shop imm' 164226584Sdim /// operand as needed by load/store instructions. 165226584Sdim uint32_t getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx, 166226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 167226584Sdim 168226584Sdim /// getLdStmModeOpValue - Return encoding for load/store multiple mode. 169226584Sdim uint32_t getLdStmModeOpValue(const MCInst &MI, unsigned OpIdx, 170226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 171226584Sdim ARM_AM::AMSubMode Mode = (ARM_AM::AMSubMode)MI.getOperand(OpIdx).getImm(); 172226584Sdim switch (Mode) { 173234353Sdim default: llvm_unreachable("Unknown addressing sub-mode!"); 174226584Sdim case ARM_AM::da: return 0; 175226584Sdim case ARM_AM::ia: return 1; 176226584Sdim case ARM_AM::db: return 2; 177226584Sdim case ARM_AM::ib: return 3; 178226584Sdim } 179226584Sdim } 180226584Sdim /// getShiftOp - Return the shift opcode (bit[6:5]) of the immediate value. 181226584Sdim /// 182226584Sdim unsigned getShiftOp(ARM_AM::ShiftOpc ShOpc) const { 183226584Sdim switch (ShOpc) { 184226584Sdim case ARM_AM::no_shift: 185226584Sdim case ARM_AM::lsl: return 0; 186226584Sdim case ARM_AM::lsr: return 1; 187226584Sdim case ARM_AM::asr: return 2; 188226584Sdim case ARM_AM::ror: 189226584Sdim case ARM_AM::rrx: return 3; 190226584Sdim } 191234353Sdim llvm_unreachable("Invalid ShiftOpc!"); 192226584Sdim } 193226584Sdim 194226584Sdim /// getAddrMode2OpValue - Return encoding for addrmode2 operands. 195226584Sdim uint32_t getAddrMode2OpValue(const MCInst &MI, unsigned OpIdx, 196226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 197226584Sdim 198226584Sdim /// getAddrMode2OffsetOpValue - Return encoding for am2offset operands. 199226584Sdim uint32_t getAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx, 200226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 201226584Sdim 202226584Sdim /// getPostIdxRegOpValue - Return encoding for postidx_reg operands. 203226584Sdim uint32_t getPostIdxRegOpValue(const MCInst &MI, unsigned OpIdx, 204226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 205226584Sdim 206226584Sdim /// getAddrMode3OffsetOpValue - Return encoding for am3offset operands. 207226584Sdim uint32_t getAddrMode3OffsetOpValue(const MCInst &MI, unsigned OpIdx, 208226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 209226584Sdim 210226584Sdim /// getAddrMode3OpValue - Return encoding for addrmode3 operands. 211226584Sdim uint32_t getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx, 212226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 213226584Sdim 214226584Sdim /// getAddrModeThumbSPOpValue - Return encoding info for 'reg +/- imm12' 215226584Sdim /// operand. 216226584Sdim uint32_t getAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx, 217226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 218226584Sdim 219226584Sdim /// getAddrModeISOpValue - Encode the t_addrmode_is# operands. 220226584Sdim uint32_t getAddrModeISOpValue(const MCInst &MI, unsigned OpIdx, 221226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 222226584Sdim 223226584Sdim /// getAddrModePCOpValue - Return encoding for t_addrmode_pc operands. 224226584Sdim uint32_t getAddrModePCOpValue(const MCInst &MI, unsigned OpIdx, 225226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 226226584Sdim 227226584Sdim /// getAddrMode5OpValue - Return encoding info for 'reg +/- imm8' operand. 228226584Sdim uint32_t getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx, 229226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 230226584Sdim 231226584Sdim /// getCCOutOpValue - Return encoding of the 's' bit. 232226584Sdim unsigned getCCOutOpValue(const MCInst &MI, unsigned Op, 233226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 234226584Sdim // The operand is either reg0 or CPSR. The 's' bit is encoded as '0' or 235226584Sdim // '1' respectively. 236226584Sdim return MI.getOperand(Op).getReg() == ARM::CPSR; 237226584Sdim } 238226584Sdim 239226584Sdim /// getSOImmOpValue - Return an encoded 12-bit shifted-immediate value. 240226584Sdim unsigned getSOImmOpValue(const MCInst &MI, unsigned Op, 241226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 242226584Sdim unsigned SoImm = MI.getOperand(Op).getImm(); 243226584Sdim int SoImmVal = ARM_AM::getSOImmVal(SoImm); 244226584Sdim assert(SoImmVal != -1 && "Not a valid so_imm value!"); 245226584Sdim 246226584Sdim // Encode rotate_imm. 247226584Sdim unsigned Binary = (ARM_AM::getSOImmValRot((unsigned)SoImmVal) >> 1) 248226584Sdim << ARMII::SoRotImmShift; 249226584Sdim 250226584Sdim // Encode immed_8. 251226584Sdim Binary |= ARM_AM::getSOImmValImm((unsigned)SoImmVal); 252226584Sdim return Binary; 253226584Sdim } 254226584Sdim 255226584Sdim /// getT2SOImmOpValue - Return an encoded 12-bit shifted-immediate value. 256226584Sdim unsigned getT2SOImmOpValue(const MCInst &MI, unsigned Op, 257226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 258226584Sdim unsigned SoImm = MI.getOperand(Op).getImm(); 259226584Sdim unsigned Encoded = ARM_AM::getT2SOImmVal(SoImm); 260226584Sdim assert(Encoded != ~0U && "Not a Thumb2 so_imm value?"); 261226584Sdim return Encoded; 262226584Sdim } 263226584Sdim 264226584Sdim unsigned getT2AddrModeSORegOpValue(const MCInst &MI, unsigned OpNum, 265226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 266226584Sdim unsigned getT2AddrModeImm8OpValue(const MCInst &MI, unsigned OpNum, 267226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 268226584Sdim unsigned getT2AddrModeImm8OffsetOpValue(const MCInst &MI, unsigned OpNum, 269226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 270226584Sdim unsigned getT2AddrModeImm12OffsetOpValue(const MCInst &MI, unsigned OpNum, 271226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 272226584Sdim 273226584Sdim /// getSORegOpValue - Return an encoded so_reg shifted register value. 274226584Sdim unsigned getSORegRegOpValue(const MCInst &MI, unsigned Op, 275226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 276226584Sdim unsigned getSORegImmOpValue(const MCInst &MI, unsigned Op, 277226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 278226584Sdim unsigned getT2SORegOpValue(const MCInst &MI, unsigned Op, 279226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 280226584Sdim 281226584Sdim unsigned getNEONVcvtImm32OpValue(const MCInst &MI, unsigned Op, 282226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 283226584Sdim return 64 - MI.getOperand(Op).getImm(); 284226584Sdim } 285226584Sdim 286226584Sdim unsigned getBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op, 287226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 288226584Sdim 289226584Sdim unsigned getRegisterListOpValue(const MCInst &MI, unsigned Op, 290226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 291226584Sdim unsigned getAddrMode6AddressOpValue(const MCInst &MI, unsigned Op, 292226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 293226584Sdim unsigned getAddrMode6OneLane32AddressOpValue(const MCInst &MI, unsigned Op, 294226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 295226584Sdim unsigned getAddrMode6DupAddressOpValue(const MCInst &MI, unsigned Op, 296226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 297226584Sdim unsigned getAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op, 298226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 299226584Sdim 300226584Sdim unsigned getShiftRight8Imm(const MCInst &MI, unsigned Op, 301226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 302226584Sdim unsigned getShiftRight16Imm(const MCInst &MI, unsigned Op, 303226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 304226584Sdim unsigned getShiftRight32Imm(const MCInst &MI, unsigned Op, 305226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 306226584Sdim unsigned getShiftRight64Imm(const MCInst &MI, unsigned Op, 307226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 308226584Sdim 309226584Sdim unsigned getThumbSRImmOpValue(const MCInst &MI, unsigned Op, 310226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 311226584Sdim 312226584Sdim unsigned NEONThumb2DataIPostEncoder(const MCInst &MI, 313226584Sdim unsigned EncodedValue) const; 314226584Sdim unsigned NEONThumb2LoadStorePostEncoder(const MCInst &MI, 315226584Sdim unsigned EncodedValue) const; 316226584Sdim unsigned NEONThumb2DupPostEncoder(const MCInst &MI, 317226584Sdim unsigned EncodedValue) const; 318226584Sdim 319226584Sdim unsigned VFPThumb2PostEncoder(const MCInst &MI, 320226584Sdim unsigned EncodedValue) const; 321226584Sdim 322226584Sdim void EmitByte(unsigned char C, raw_ostream &OS) const { 323226584Sdim OS << (char)C; 324226584Sdim } 325226584Sdim 326226584Sdim void EmitConstant(uint64_t Val, unsigned Size, raw_ostream &OS) const { 327226584Sdim // Output the constant in little endian byte order. 328226584Sdim for (unsigned i = 0; i != Size; ++i) { 329226584Sdim EmitByte(Val & 255, OS); 330226584Sdim Val >>= 8; 331226584Sdim } 332226584Sdim } 333226584Sdim 334226584Sdim void EncodeInstruction(const MCInst &MI, raw_ostream &OS, 335226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 336226584Sdim}; 337226584Sdim 338226584Sdim} // end anonymous namespace 339226584Sdim 340226584SdimMCCodeEmitter *llvm::createARMMCCodeEmitter(const MCInstrInfo &MCII, 341239462Sdim const MCRegisterInfo &MRI, 342226584Sdim const MCSubtargetInfo &STI, 343226584Sdim MCContext &Ctx) { 344226584Sdim return new ARMMCCodeEmitter(MCII, STI, Ctx); 345226584Sdim} 346226584Sdim 347226584Sdim/// NEONThumb2DataIPostEncoder - Post-process encoded NEON data-processing 348226584Sdim/// instructions, and rewrite them to their Thumb2 form if we are currently in 349226584Sdim/// Thumb2 mode. 350226584Sdimunsigned ARMMCCodeEmitter::NEONThumb2DataIPostEncoder(const MCInst &MI, 351226584Sdim unsigned EncodedValue) const { 352226584Sdim if (isThumb2()) { 353226584Sdim // NEON Thumb2 data-processsing encodings are very simple: bit 24 is moved 354226584Sdim // to bit 12 of the high half-word (i.e. bit 28), and bits 27-24 are 355226584Sdim // set to 1111. 356226584Sdim unsigned Bit24 = EncodedValue & 0x01000000; 357226584Sdim unsigned Bit28 = Bit24 << 4; 358226584Sdim EncodedValue &= 0xEFFFFFFF; 359226584Sdim EncodedValue |= Bit28; 360226584Sdim EncodedValue |= 0x0F000000; 361226584Sdim } 362226584Sdim 363226584Sdim return EncodedValue; 364226584Sdim} 365226584Sdim 366226584Sdim/// NEONThumb2LoadStorePostEncoder - Post-process encoded NEON load/store 367226584Sdim/// instructions, and rewrite them to their Thumb2 form if we are currently in 368226584Sdim/// Thumb2 mode. 369226584Sdimunsigned ARMMCCodeEmitter::NEONThumb2LoadStorePostEncoder(const MCInst &MI, 370226584Sdim unsigned EncodedValue) const { 371226584Sdim if (isThumb2()) { 372226584Sdim EncodedValue &= 0xF0FFFFFF; 373226584Sdim EncodedValue |= 0x09000000; 374226584Sdim } 375226584Sdim 376226584Sdim return EncodedValue; 377226584Sdim} 378226584Sdim 379226584Sdim/// NEONThumb2DupPostEncoder - Post-process encoded NEON vdup 380226584Sdim/// instructions, and rewrite them to their Thumb2 form if we are currently in 381226584Sdim/// Thumb2 mode. 382226584Sdimunsigned ARMMCCodeEmitter::NEONThumb2DupPostEncoder(const MCInst &MI, 383226584Sdim unsigned EncodedValue) const { 384226584Sdim if (isThumb2()) { 385226584Sdim EncodedValue &= 0x00FFFFFF; 386226584Sdim EncodedValue |= 0xEE000000; 387226584Sdim } 388226584Sdim 389226584Sdim return EncodedValue; 390226584Sdim} 391226584Sdim 392226584Sdim/// VFPThumb2PostEncoder - Post-process encoded VFP instructions and rewrite 393226584Sdim/// them to their Thumb2 form if we are currently in Thumb2 mode. 394226584Sdimunsigned ARMMCCodeEmitter:: 395226584SdimVFPThumb2PostEncoder(const MCInst &MI, unsigned EncodedValue) const { 396226584Sdim if (isThumb2()) { 397226584Sdim EncodedValue &= 0x0FFFFFFF; 398226584Sdim EncodedValue |= 0xE0000000; 399226584Sdim } 400226584Sdim return EncodedValue; 401226584Sdim} 402226584Sdim 403226584Sdim/// getMachineOpValue - Return binary encoding of operand. If the machine 404226584Sdim/// operand requires relocation, record the relocation and return zero. 405226584Sdimunsigned ARMMCCodeEmitter:: 406226584SdimgetMachineOpValue(const MCInst &MI, const MCOperand &MO, 407226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 408226584Sdim if (MO.isReg()) { 409226584Sdim unsigned Reg = MO.getReg(); 410239462Sdim unsigned RegNo = CTX.getRegisterInfo().getEncodingValue(Reg); 411226584Sdim 412226584Sdim // Q registers are encoded as 2x their register number. 413226584Sdim switch (Reg) { 414226584Sdim default: 415226584Sdim return RegNo; 416226584Sdim case ARM::Q0: case ARM::Q1: case ARM::Q2: case ARM::Q3: 417226584Sdim case ARM::Q4: case ARM::Q5: case ARM::Q6: case ARM::Q7: 418226584Sdim case ARM::Q8: case ARM::Q9: case ARM::Q10: case ARM::Q11: 419226584Sdim case ARM::Q12: case ARM::Q13: case ARM::Q14: case ARM::Q15: 420226584Sdim return 2 * RegNo; 421226584Sdim } 422226584Sdim } else if (MO.isImm()) { 423226584Sdim return static_cast<unsigned>(MO.getImm()); 424226584Sdim } else if (MO.isFPImm()) { 425226584Sdim return static_cast<unsigned>(APFloat(MO.getFPImm()) 426226584Sdim .bitcastToAPInt().getHiBits(32).getLimitedValue()); 427226584Sdim } 428226584Sdim 429226584Sdim llvm_unreachable("Unable to encode MCOperand!"); 430226584Sdim} 431226584Sdim 432226584Sdim/// getAddrModeImmOpValue - Return encoding info for 'reg +/- imm' operand. 433226584Sdimbool ARMMCCodeEmitter:: 434226584SdimEncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx, unsigned &Reg, 435226584Sdim unsigned &Imm, SmallVectorImpl<MCFixup> &Fixups) const { 436226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 437226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 438226584Sdim 439239462Sdim Reg = CTX.getRegisterInfo().getEncodingValue(MO.getReg()); 440226584Sdim 441226584Sdim int32_t SImm = MO1.getImm(); 442226584Sdim bool isAdd = true; 443226584Sdim 444226584Sdim // Special value for #-0 445226584Sdim if (SImm == INT32_MIN) { 446226584Sdim SImm = 0; 447226584Sdim isAdd = false; 448226584Sdim } 449226584Sdim 450226584Sdim // Immediate is always encoded as positive. The 'U' bit controls add vs sub. 451226584Sdim if (SImm < 0) { 452226584Sdim SImm = -SImm; 453226584Sdim isAdd = false; 454226584Sdim } 455226584Sdim 456226584Sdim Imm = SImm; 457226584Sdim return isAdd; 458226584Sdim} 459226584Sdim 460226584Sdim/// getBranchTargetOpValue - Helper function to get the branch target operand, 461226584Sdim/// which is either an immediate or requires a fixup. 462226584Sdimstatic uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 463226584Sdim unsigned FixupKind, 464226584Sdim SmallVectorImpl<MCFixup> &Fixups) { 465226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 466226584Sdim 467226584Sdim // If the destination is an immediate, we have nothing to do. 468226584Sdim if (MO.isImm()) return MO.getImm(); 469226584Sdim assert(MO.isExpr() && "Unexpected branch target type!"); 470226584Sdim const MCExpr *Expr = MO.getExpr(); 471226584Sdim MCFixupKind Kind = MCFixupKind(FixupKind); 472234353Sdim Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); 473226584Sdim 474226584Sdim // All of the information is in the fixup. 475226584Sdim return 0; 476226584Sdim} 477226584Sdim 478226584Sdim// Thumb BL and BLX use a strange offset encoding where bits 22 and 21 are 479226584Sdim// determined by negating them and XOR'ing them with bit 23. 480226584Sdimstatic int32_t encodeThumbBLOffset(int32_t offset) { 481226584Sdim offset >>= 1; 482226584Sdim uint32_t S = (offset & 0x800000) >> 23; 483226584Sdim uint32_t J1 = (offset & 0x400000) >> 22; 484226584Sdim uint32_t J2 = (offset & 0x200000) >> 21; 485226584Sdim J1 = (~J1 & 0x1); 486226584Sdim J2 = (~J2 & 0x1); 487226584Sdim J1 ^= S; 488226584Sdim J2 ^= S; 489226584Sdim 490226584Sdim offset &= ~0x600000; 491226584Sdim offset |= J1 << 22; 492226584Sdim offset |= J2 << 21; 493226584Sdim 494226584Sdim return offset; 495226584Sdim} 496226584Sdim 497226584Sdim/// getThumbBLTargetOpValue - Return encoding info for immediate branch target. 498226584Sdimuint32_t ARMMCCodeEmitter:: 499226584SdimgetThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx, 500226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 501226584Sdim const MCOperand MO = MI.getOperand(OpIdx); 502226584Sdim if (MO.isExpr()) 503226584Sdim return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_bl, 504226584Sdim Fixups); 505226584Sdim return encodeThumbBLOffset(MO.getImm()); 506226584Sdim} 507226584Sdim 508226584Sdim/// getThumbBLXTargetOpValue - Return encoding info for Thumb immediate 509226584Sdim/// BLX branch target. 510226584Sdimuint32_t ARMMCCodeEmitter:: 511226584SdimgetThumbBLXTargetOpValue(const MCInst &MI, unsigned OpIdx, 512226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 513226584Sdim const MCOperand MO = MI.getOperand(OpIdx); 514226584Sdim if (MO.isExpr()) 515226584Sdim return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_blx, 516226584Sdim Fixups); 517226584Sdim return encodeThumbBLOffset(MO.getImm()); 518226584Sdim} 519226584Sdim 520226584Sdim/// getThumbBRTargetOpValue - Return encoding info for Thumb branch target. 521226584Sdimuint32_t ARMMCCodeEmitter:: 522226584SdimgetThumbBRTargetOpValue(const MCInst &MI, unsigned OpIdx, 523226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 524226584Sdim const MCOperand MO = MI.getOperand(OpIdx); 525226584Sdim if (MO.isExpr()) 526226584Sdim return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_br, 527226584Sdim Fixups); 528226584Sdim return (MO.getImm() >> 1); 529226584Sdim} 530226584Sdim 531226584Sdim/// getThumbBCCTargetOpValue - Return encoding info for Thumb branch target. 532226584Sdimuint32_t ARMMCCodeEmitter:: 533226584SdimgetThumbBCCTargetOpValue(const MCInst &MI, unsigned OpIdx, 534226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 535226584Sdim const MCOperand MO = MI.getOperand(OpIdx); 536226584Sdim if (MO.isExpr()) 537226584Sdim return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_bcc, 538226584Sdim Fixups); 539226584Sdim return (MO.getImm() >> 1); 540226584Sdim} 541226584Sdim 542226584Sdim/// getThumbCBTargetOpValue - Return encoding info for Thumb branch target. 543226584Sdimuint32_t ARMMCCodeEmitter:: 544226584SdimgetThumbCBTargetOpValue(const MCInst &MI, unsigned OpIdx, 545226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 546226584Sdim const MCOperand MO = MI.getOperand(OpIdx); 547226584Sdim if (MO.isExpr()) 548226584Sdim return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_cb, Fixups); 549226584Sdim return (MO.getImm() >> 1); 550226584Sdim} 551226584Sdim 552226584Sdim/// Return true if this branch has a non-always predication 553226584Sdimstatic bool HasConditionalBranch(const MCInst &MI) { 554226584Sdim int NumOp = MI.getNumOperands(); 555226584Sdim if (NumOp >= 2) { 556226584Sdim for (int i = 0; i < NumOp-1; ++i) { 557226584Sdim const MCOperand &MCOp1 = MI.getOperand(i); 558226584Sdim const MCOperand &MCOp2 = MI.getOperand(i + 1); 559226584Sdim if (MCOp1.isImm() && MCOp2.isReg() && 560226584Sdim (MCOp2.getReg() == 0 || MCOp2.getReg() == ARM::CPSR)) { 561226584Sdim if (ARMCC::CondCodes(MCOp1.getImm()) != ARMCC::AL) 562226584Sdim return true; 563226584Sdim } 564226584Sdim } 565226584Sdim } 566226584Sdim return false; 567226584Sdim} 568226584Sdim 569226584Sdim/// getBranchTargetOpValue - Return encoding info for 24-bit immediate branch 570226584Sdim/// target. 571226584Sdimuint32_t ARMMCCodeEmitter:: 572226584SdimgetBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 573226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 574226584Sdim // FIXME: This really, really shouldn't use TargetMachine. We don't want 575226584Sdim // coupling between MC and TM anywhere we can help it. 576226584Sdim if (isThumb2()) 577226584Sdim return 578226584Sdim ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_condbranch, Fixups); 579226584Sdim return getARMBranchTargetOpValue(MI, OpIdx, Fixups); 580226584Sdim} 581226584Sdim 582226584Sdim/// getBranchTargetOpValue - Return encoding info for 24-bit immediate branch 583226584Sdim/// target. 584226584Sdimuint32_t ARMMCCodeEmitter:: 585226584SdimgetARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 586226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 587226584Sdim const MCOperand MO = MI.getOperand(OpIdx); 588226584Sdim if (MO.isExpr()) { 589226584Sdim if (HasConditionalBranch(MI)) 590226584Sdim return ::getBranchTargetOpValue(MI, OpIdx, 591226584Sdim ARM::fixup_arm_condbranch, Fixups); 592226584Sdim return ::getBranchTargetOpValue(MI, OpIdx, 593226584Sdim ARM::fixup_arm_uncondbranch, Fixups); 594226584Sdim } 595226584Sdim 596226584Sdim return MO.getImm() >> 2; 597226584Sdim} 598226584Sdim 599226584Sdimuint32_t ARMMCCodeEmitter:: 600234353SdimgetARMBLTargetOpValue(const MCInst &MI, unsigned OpIdx, 601226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 602226584Sdim const MCOperand MO = MI.getOperand(OpIdx); 603226584Sdim if (MO.isExpr()) { 604226584Sdim if (HasConditionalBranch(MI)) 605234353Sdim return ::getBranchTargetOpValue(MI, OpIdx, 606234353Sdim ARM::fixup_arm_condbl, Fixups); 607234353Sdim return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_uncondbl, Fixups); 608226584Sdim } 609226584Sdim 610234353Sdim return MO.getImm() >> 2; 611234353Sdim} 612234353Sdim 613234353Sdimuint32_t ARMMCCodeEmitter:: 614234353SdimgetARMBLXTargetOpValue(const MCInst &MI, unsigned OpIdx, 615234353Sdim SmallVectorImpl<MCFixup> &Fixups) const { 616234353Sdim const MCOperand MO = MI.getOperand(OpIdx); 617234353Sdim if (MO.isExpr()) 618234353Sdim return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_blx, Fixups); 619234353Sdim 620226584Sdim return MO.getImm() >> 1; 621226584Sdim} 622226584Sdim 623226584Sdim/// getUnconditionalBranchTargetOpValue - Return encoding info for 24-bit 624226584Sdim/// immediate branch target. 625226584Sdimuint32_t ARMMCCodeEmitter:: 626226584SdimgetUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 627226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 628226584Sdim unsigned Val = 629226584Sdim ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_uncondbranch, Fixups); 630226584Sdim bool I = (Val & 0x800000); 631226584Sdim bool J1 = (Val & 0x400000); 632226584Sdim bool J2 = (Val & 0x200000); 633226584Sdim if (I ^ J1) 634226584Sdim Val &= ~0x400000; 635226584Sdim else 636226584Sdim Val |= 0x400000; 637226584Sdim 638226584Sdim if (I ^ J2) 639226584Sdim Val &= ~0x200000; 640226584Sdim else 641226584Sdim Val |= 0x200000; 642226584Sdim 643226584Sdim return Val; 644226584Sdim} 645226584Sdim 646239462Sdim/// getAdrLabelOpValue - Return encoding info for 12-bit shifted-immediate 647239462Sdim/// ADR label target. 648226584Sdimuint32_t ARMMCCodeEmitter:: 649226584SdimgetAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, 650226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 651226584Sdim const MCOperand MO = MI.getOperand(OpIdx); 652226584Sdim if (MO.isExpr()) 653226584Sdim return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_adr_pcrel_12, 654226584Sdim Fixups); 655226584Sdim int32_t offset = MO.getImm(); 656226584Sdim uint32_t Val = 0x2000; 657239462Sdim 658249423Sdim int SoImmVal; 659239462Sdim if (offset == INT32_MIN) { 660226584Sdim Val = 0x1000; 661249423Sdim SoImmVal = 0; 662239462Sdim } else if (offset < 0) { 663239462Sdim Val = 0x1000; 664226584Sdim offset *= -1; 665249423Sdim SoImmVal = ARM_AM::getSOImmVal(offset); 666249423Sdim if(SoImmVal == -1) { 667249423Sdim Val = 0x2000; 668249423Sdim offset *= -1; 669249423Sdim SoImmVal = ARM_AM::getSOImmVal(offset); 670249423Sdim } 671249423Sdim } else { 672249423Sdim SoImmVal = ARM_AM::getSOImmVal(offset); 673249423Sdim if(SoImmVal == -1) { 674249423Sdim Val = 0x1000; 675249423Sdim offset *= -1; 676249423Sdim SoImmVal = ARM_AM::getSOImmVal(offset); 677249423Sdim } 678226584Sdim } 679239462Sdim 680239462Sdim assert(SoImmVal != -1 && "Not a valid so_imm value!"); 681239462Sdim 682239462Sdim Val |= SoImmVal; 683226584Sdim return Val; 684226584Sdim} 685226584Sdim 686239462Sdim/// getT2AdrLabelOpValue - Return encoding info for 12-bit immediate ADR label 687226584Sdim/// target. 688226584Sdimuint32_t ARMMCCodeEmitter:: 689226584SdimgetT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx, 690226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 691226584Sdim const MCOperand MO = MI.getOperand(OpIdx); 692226584Sdim if (MO.isExpr()) 693226584Sdim return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_adr_pcrel_12, 694226584Sdim Fixups); 695226584Sdim int32_t Val = MO.getImm(); 696239462Sdim if (Val == INT32_MIN) 697239462Sdim Val = 0x1000; 698239462Sdim else if (Val < 0) { 699226584Sdim Val *= -1; 700226584Sdim Val |= 0x1000; 701226584Sdim } 702226584Sdim return Val; 703226584Sdim} 704226584Sdim 705239462Sdim/// getThumbAdrLabelOpValue - Return encoding info for 8-bit immediate ADR label 706226584Sdim/// target. 707226584Sdimuint32_t ARMMCCodeEmitter:: 708226584SdimgetThumbAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, 709226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 710226584Sdim const MCOperand MO = MI.getOperand(OpIdx); 711226584Sdim if (MO.isExpr()) 712226584Sdim return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_thumb_adr_pcrel_10, 713226584Sdim Fixups); 714226584Sdim return MO.getImm(); 715226584Sdim} 716226584Sdim 717226584Sdim/// getThumbAddrModeRegRegOpValue - Return encoding info for 'reg + reg' 718226584Sdim/// operand. 719226584Sdimuint32_t ARMMCCodeEmitter:: 720226584SdimgetThumbAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx, 721226584Sdim SmallVectorImpl<MCFixup> &) const { 722226584Sdim // [Rn, Rm] 723226584Sdim // {5-3} = Rm 724226584Sdim // {2-0} = Rn 725226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx); 726226584Sdim const MCOperand &MO2 = MI.getOperand(OpIdx + 1); 727239462Sdim unsigned Rn = CTX.getRegisterInfo().getEncodingValue(MO1.getReg()); 728239462Sdim unsigned Rm = CTX.getRegisterInfo().getEncodingValue(MO2.getReg()); 729226584Sdim return (Rm << 3) | Rn; 730226584Sdim} 731226584Sdim 732226584Sdim/// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12' operand. 733226584Sdimuint32_t ARMMCCodeEmitter:: 734226584SdimgetAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx, 735226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 736226584Sdim // {17-13} = reg 737226584Sdim // {12} = (U)nsigned (add == '1', sub == '0') 738226584Sdim // {11-0} = imm12 739226584Sdim unsigned Reg, Imm12; 740226584Sdim bool isAdd = true; 741226584Sdim // If The first operand isn't a register, we have a label reference. 742226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 743226584Sdim if (!MO.isReg()) { 744239462Sdim Reg = CTX.getRegisterInfo().getEncodingValue(ARM::PC); // Rn is PC. 745226584Sdim Imm12 = 0; 746226584Sdim isAdd = false ; // 'U' bit is set as part of the fixup. 747226584Sdim 748226584Sdim if (MO.isExpr()) { 749226584Sdim const MCExpr *Expr = MO.getExpr(); 750226584Sdim 751226584Sdim MCFixupKind Kind; 752226584Sdim if (isThumb2()) 753226584Sdim Kind = MCFixupKind(ARM::fixup_t2_ldst_pcrel_12); 754226584Sdim else 755226584Sdim Kind = MCFixupKind(ARM::fixup_arm_ldst_pcrel_12); 756234353Sdim Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); 757226584Sdim 758226584Sdim ++MCNumCPRelocations; 759226584Sdim } else { 760226584Sdim Reg = ARM::PC; 761226584Sdim int32_t Offset = MO.getImm(); 762234353Sdim // FIXME: Handle #-0. 763226584Sdim if (Offset < 0) { 764226584Sdim Offset *= -1; 765226584Sdim isAdd = false; 766226584Sdim } 767226584Sdim Imm12 = Offset; 768226584Sdim } 769226584Sdim } else 770226584Sdim isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm12, Fixups); 771226584Sdim 772226584Sdim uint32_t Binary = Imm12 & 0xfff; 773226584Sdim // Immediate is always encoded as positive. The 'U' bit controls add vs sub. 774226584Sdim if (isAdd) 775226584Sdim Binary |= (1 << 12); 776226584Sdim Binary |= (Reg << 13); 777226584Sdim return Binary; 778226584Sdim} 779226584Sdim 780226584Sdim/// getT2Imm8s4OpValue - Return encoding info for 781226584Sdim/// '+/- imm8<<2' operand. 782226584Sdimuint32_t ARMMCCodeEmitter:: 783226584SdimgetT2Imm8s4OpValue(const MCInst &MI, unsigned OpIdx, 784226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 785226584Sdim // FIXME: The immediate operand should have already been encoded like this 786226584Sdim // before ever getting here. The encoder method should just need to combine 787226584Sdim // the MI operands for the register and the offset into a single 788226584Sdim // representation for the complex operand in the .td file. This isn't just 789226584Sdim // style, unfortunately. As-is, we can't represent the distinct encoding 790226584Sdim // for #-0. 791226584Sdim 792226584Sdim // {8} = (U)nsigned (add == '1', sub == '0') 793226584Sdim // {7-0} = imm8 794226584Sdim int32_t Imm8 = MI.getOperand(OpIdx).getImm(); 795226584Sdim bool isAdd = Imm8 >= 0; 796226584Sdim 797226584Sdim // Immediate is always encoded as positive. The 'U' bit controls add vs sub. 798226584Sdim if (Imm8 < 0) 799243830Sdim Imm8 = -(uint32_t)Imm8; 800226584Sdim 801226584Sdim // Scaled by 4. 802226584Sdim Imm8 /= 4; 803226584Sdim 804226584Sdim uint32_t Binary = Imm8 & 0xff; 805226584Sdim // Immediate is always encoded as positive. The 'U' bit controls add vs sub. 806226584Sdim if (isAdd) 807226584Sdim Binary |= (1 << 8); 808226584Sdim return Binary; 809226584Sdim} 810226584Sdim 811226584Sdim/// getT2AddrModeImm8s4OpValue - Return encoding info for 812226584Sdim/// 'reg +/- imm8<<2' operand. 813226584Sdimuint32_t ARMMCCodeEmitter:: 814226584SdimgetT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx, 815226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 816226584Sdim // {12-9} = reg 817226584Sdim // {8} = (U)nsigned (add == '1', sub == '0') 818226584Sdim // {7-0} = imm8 819226584Sdim unsigned Reg, Imm8; 820226584Sdim bool isAdd = true; 821226584Sdim // If The first operand isn't a register, we have a label reference. 822226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 823226584Sdim if (!MO.isReg()) { 824239462Sdim Reg = CTX.getRegisterInfo().getEncodingValue(ARM::PC); // Rn is PC. 825226584Sdim Imm8 = 0; 826226584Sdim isAdd = false ; // 'U' bit is set as part of the fixup. 827226584Sdim 828226584Sdim assert(MO.isExpr() && "Unexpected machine operand type!"); 829226584Sdim const MCExpr *Expr = MO.getExpr(); 830234353Sdim MCFixupKind Kind = MCFixupKind(ARM::fixup_t2_pcrel_10); 831234353Sdim Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); 832226584Sdim 833226584Sdim ++MCNumCPRelocations; 834226584Sdim } else 835226584Sdim isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups); 836226584Sdim 837226584Sdim // FIXME: The immediate operand should have already been encoded like this 838226584Sdim // before ever getting here. The encoder method should just need to combine 839226584Sdim // the MI operands for the register and the offset into a single 840226584Sdim // representation for the complex operand in the .td file. This isn't just 841226584Sdim // style, unfortunately. As-is, we can't represent the distinct encoding 842226584Sdim // for #-0. 843226584Sdim uint32_t Binary = (Imm8 >> 2) & 0xff; 844226584Sdim // Immediate is always encoded as positive. The 'U' bit controls add vs sub. 845226584Sdim if (isAdd) 846226584Sdim Binary |= (1 << 8); 847226584Sdim Binary |= (Reg << 9); 848226584Sdim return Binary; 849226584Sdim} 850226584Sdim 851226584Sdim/// getT2AddrModeImm0_1020s4OpValue - Return encoding info for 852226584Sdim/// 'reg + imm8<<2' operand. 853226584Sdimuint32_t ARMMCCodeEmitter:: 854226584SdimgetT2AddrModeImm0_1020s4OpValue(const MCInst &MI, unsigned OpIdx, 855226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 856226584Sdim // {11-8} = reg 857226584Sdim // {7-0} = imm8 858226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 859226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 860239462Sdim unsigned Reg = CTX.getRegisterInfo().getEncodingValue(MO.getReg()); 861226584Sdim unsigned Imm8 = MO1.getImm(); 862226584Sdim return (Reg << 8) | Imm8; 863226584Sdim} 864226584Sdim 865226584Sdim// FIXME: This routine assumes that a binary 866226584Sdim// expression will always result in a PCRel expression 867226584Sdim// In reality, its only true if one or more subexpressions 868226584Sdim// is itself a PCRel (i.e. "." in asm or some other pcrel construct) 869226584Sdim// but this is good enough for now. 870226584Sdimstatic bool EvaluateAsPCRel(const MCExpr *Expr) { 871226584Sdim switch (Expr->getKind()) { 872234353Sdim default: llvm_unreachable("Unexpected expression type"); 873226584Sdim case MCExpr::SymbolRef: return false; 874226584Sdim case MCExpr::Binary: return true; 875226584Sdim } 876226584Sdim} 877226584Sdim 878226584Sdimuint32_t 879226584SdimARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx, 880226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 881226584Sdim // {20-16} = imm{15-12} 882226584Sdim // {11-0} = imm{11-0} 883226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 884226584Sdim if (MO.isImm()) 885226584Sdim // Hi / lo 16 bits already extracted during earlier passes. 886226584Sdim return static_cast<unsigned>(MO.getImm()); 887226584Sdim 888226584Sdim // Handle :upper16: and :lower16: assembly prefixes. 889226584Sdim const MCExpr *E = MO.getExpr(); 890239462Sdim MCFixupKind Kind; 891226584Sdim if (E->getKind() == MCExpr::Target) { 892226584Sdim const ARMMCExpr *ARM16Expr = cast<ARMMCExpr>(E); 893226584Sdim E = ARM16Expr->getSubExpr(); 894226584Sdim 895226584Sdim switch (ARM16Expr->getKind()) { 896234353Sdim default: llvm_unreachable("Unsupported ARMFixup"); 897226584Sdim case ARMMCExpr::VK_ARM_HI16: 898226584Sdim if (!isTargetDarwin() && EvaluateAsPCRel(E)) 899226584Sdim Kind = MCFixupKind(isThumb2() 900226584Sdim ? ARM::fixup_t2_movt_hi16_pcrel 901226584Sdim : ARM::fixup_arm_movt_hi16_pcrel); 902226584Sdim else 903226584Sdim Kind = MCFixupKind(isThumb2() 904226584Sdim ? ARM::fixup_t2_movt_hi16 905226584Sdim : ARM::fixup_arm_movt_hi16); 906226584Sdim break; 907226584Sdim case ARMMCExpr::VK_ARM_LO16: 908226584Sdim if (!isTargetDarwin() && EvaluateAsPCRel(E)) 909226584Sdim Kind = MCFixupKind(isThumb2() 910226584Sdim ? ARM::fixup_t2_movw_lo16_pcrel 911226584Sdim : ARM::fixup_arm_movw_lo16_pcrel); 912226584Sdim else 913226584Sdim Kind = MCFixupKind(isThumb2() 914226584Sdim ? ARM::fixup_t2_movw_lo16 915226584Sdim : ARM::fixup_arm_movw_lo16); 916226584Sdim break; 917226584Sdim } 918234353Sdim Fixups.push_back(MCFixup::Create(0, E, Kind, MI.getLoc())); 919226584Sdim return 0; 920239462Sdim } 921239462Sdim // If the expression doesn't have :upper16: or :lower16: on it, 922239462Sdim // it's just a plain immediate expression, and those evaluate to 923239462Sdim // the lower 16 bits of the expression regardless of whether 924239462Sdim // we have a movt or a movw. 925239462Sdim if (!isTargetDarwin() && EvaluateAsPCRel(E)) 926239462Sdim Kind = MCFixupKind(isThumb2() 927239462Sdim ? ARM::fixup_t2_movw_lo16_pcrel 928239462Sdim : ARM::fixup_arm_movw_lo16_pcrel); 929239462Sdim else 930239462Sdim Kind = MCFixupKind(isThumb2() 931239462Sdim ? ARM::fixup_t2_movw_lo16 932239462Sdim : ARM::fixup_arm_movw_lo16); 933239462Sdim Fixups.push_back(MCFixup::Create(0, E, Kind, MI.getLoc())); 934239462Sdim return 0; 935226584Sdim} 936226584Sdim 937226584Sdimuint32_t ARMMCCodeEmitter:: 938226584SdimgetLdStSORegOpValue(const MCInst &MI, unsigned OpIdx, 939226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 940226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 941226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx+1); 942226584Sdim const MCOperand &MO2 = MI.getOperand(OpIdx+2); 943239462Sdim unsigned Rn = CTX.getRegisterInfo().getEncodingValue(MO.getReg()); 944239462Sdim unsigned Rm = CTX.getRegisterInfo().getEncodingValue(MO1.getReg()); 945226584Sdim unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()); 946226584Sdim bool isAdd = ARM_AM::getAM2Op(MO2.getImm()) == ARM_AM::add; 947226584Sdim ARM_AM::ShiftOpc ShOp = ARM_AM::getAM2ShiftOpc(MO2.getImm()); 948226584Sdim unsigned SBits = getShiftOp(ShOp); 949226584Sdim 950243830Sdim // While "lsr #32" and "asr #32" exist, they are encoded with a 0 in the shift 951243830Sdim // amount. However, it would be an easy mistake to make so check here. 952243830Sdim assert((ShImm & ~0x1f) == 0 && "Out of range shift amount"); 953243830Sdim 954226584Sdim // {16-13} = Rn 955226584Sdim // {12} = isAdd 956226584Sdim // {11-0} = shifter 957226584Sdim // {3-0} = Rm 958226584Sdim // {4} = 0 959226584Sdim // {6-5} = type 960226584Sdim // {11-7} = imm 961226584Sdim uint32_t Binary = Rm; 962226584Sdim Binary |= Rn << 13; 963226584Sdim Binary |= SBits << 5; 964226584Sdim Binary |= ShImm << 7; 965226584Sdim if (isAdd) 966226584Sdim Binary |= 1 << 12; 967226584Sdim return Binary; 968226584Sdim} 969226584Sdim 970226584Sdimuint32_t ARMMCCodeEmitter:: 971226584SdimgetAddrMode2OpValue(const MCInst &MI, unsigned OpIdx, 972226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 973226584Sdim // {17-14} Rn 974226584Sdim // {13} 1 == imm12, 0 == Rm 975226584Sdim // {12} isAdd 976226584Sdim // {11-0} imm12/Rm 977226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 978239462Sdim unsigned Rn = CTX.getRegisterInfo().getEncodingValue(MO.getReg()); 979226584Sdim uint32_t Binary = getAddrMode2OffsetOpValue(MI, OpIdx + 1, Fixups); 980226584Sdim Binary |= Rn << 14; 981226584Sdim return Binary; 982226584Sdim} 983226584Sdim 984226584Sdimuint32_t ARMMCCodeEmitter:: 985226584SdimgetAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx, 986226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 987226584Sdim // {13} 1 == imm12, 0 == Rm 988226584Sdim // {12} isAdd 989226584Sdim // {11-0} imm12/Rm 990226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 991226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx+1); 992226584Sdim unsigned Imm = MO1.getImm(); 993226584Sdim bool isAdd = ARM_AM::getAM2Op(Imm) == ARM_AM::add; 994226584Sdim bool isReg = MO.getReg() != 0; 995226584Sdim uint32_t Binary = ARM_AM::getAM2Offset(Imm); 996226584Sdim // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm12 997226584Sdim if (isReg) { 998226584Sdim ARM_AM::ShiftOpc ShOp = ARM_AM::getAM2ShiftOpc(Imm); 999226584Sdim Binary <<= 7; // Shift amount is bits [11:7] 1000226584Sdim Binary |= getShiftOp(ShOp) << 5; // Shift type is bits [6:5] 1001239462Sdim Binary |= CTX.getRegisterInfo().getEncodingValue(MO.getReg()); // Rm is bits [3:0] 1002226584Sdim } 1003226584Sdim return Binary | (isAdd << 12) | (isReg << 13); 1004226584Sdim} 1005226584Sdim 1006226584Sdimuint32_t ARMMCCodeEmitter:: 1007226584SdimgetPostIdxRegOpValue(const MCInst &MI, unsigned OpIdx, 1008226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1009226584Sdim // {4} isAdd 1010226584Sdim // {3-0} Rm 1011226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 1012226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx+1); 1013226584Sdim bool isAdd = MO1.getImm() != 0; 1014239462Sdim return CTX.getRegisterInfo().getEncodingValue(MO.getReg()) | (isAdd << 4); 1015226584Sdim} 1016226584Sdim 1017226584Sdimuint32_t ARMMCCodeEmitter:: 1018226584SdimgetAddrMode3OffsetOpValue(const MCInst &MI, unsigned OpIdx, 1019226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1020226584Sdim // {9} 1 == imm8, 0 == Rm 1021226584Sdim // {8} isAdd 1022226584Sdim // {7-4} imm7_4/zero 1023226584Sdim // {3-0} imm3_0/Rm 1024226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 1025226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx+1); 1026226584Sdim unsigned Imm = MO1.getImm(); 1027226584Sdim bool isAdd = ARM_AM::getAM3Op(Imm) == ARM_AM::add; 1028226584Sdim bool isImm = MO.getReg() == 0; 1029226584Sdim uint32_t Imm8 = ARM_AM::getAM3Offset(Imm); 1030226584Sdim // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm8 1031226584Sdim if (!isImm) 1032239462Sdim Imm8 = CTX.getRegisterInfo().getEncodingValue(MO.getReg()); 1033226584Sdim return Imm8 | (isAdd << 8) | (isImm << 9); 1034226584Sdim} 1035226584Sdim 1036226584Sdimuint32_t ARMMCCodeEmitter:: 1037226584SdimgetAddrMode3OpValue(const MCInst &MI, unsigned OpIdx, 1038226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1039226584Sdim // {13} 1 == imm8, 0 == Rm 1040226584Sdim // {12-9} Rn 1041226584Sdim // {8} isAdd 1042226584Sdim // {7-4} imm7_4/zero 1043226584Sdim // {3-0} imm3_0/Rm 1044226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 1045226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx+1); 1046226584Sdim const MCOperand &MO2 = MI.getOperand(OpIdx+2); 1047234353Sdim 1048234353Sdim // If The first operand isn't a register, we have a label reference. 1049234353Sdim if (!MO.isReg()) { 1050239462Sdim unsigned Rn = CTX.getRegisterInfo().getEncodingValue(ARM::PC); // Rn is PC. 1051234353Sdim 1052234353Sdim assert(MO.isExpr() && "Unexpected machine operand type!"); 1053234353Sdim const MCExpr *Expr = MO.getExpr(); 1054234353Sdim MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_pcrel_10_unscaled); 1055234353Sdim Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); 1056234353Sdim 1057234353Sdim ++MCNumCPRelocations; 1058234353Sdim return (Rn << 9) | (1 << 13); 1059234353Sdim } 1060239462Sdim unsigned Rn = CTX.getRegisterInfo().getEncodingValue(MO.getReg()); 1061226584Sdim unsigned Imm = MO2.getImm(); 1062226584Sdim bool isAdd = ARM_AM::getAM3Op(Imm) == ARM_AM::add; 1063226584Sdim bool isImm = MO1.getReg() == 0; 1064226584Sdim uint32_t Imm8 = ARM_AM::getAM3Offset(Imm); 1065226584Sdim // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm8 1066226584Sdim if (!isImm) 1067239462Sdim Imm8 = CTX.getRegisterInfo().getEncodingValue(MO1.getReg()); 1068226584Sdim return (Rn << 9) | Imm8 | (isAdd << 8) | (isImm << 13); 1069226584Sdim} 1070226584Sdim 1071226584Sdim/// getAddrModeThumbSPOpValue - Encode the t_addrmode_sp operands. 1072226584Sdimuint32_t ARMMCCodeEmitter:: 1073226584SdimgetAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx, 1074226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1075226584Sdim // [SP, #imm] 1076226584Sdim // {7-0} = imm8 1077226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 1078226584Sdim assert(MI.getOperand(OpIdx).getReg() == ARM::SP && 1079226584Sdim "Unexpected base register!"); 1080226584Sdim 1081226584Sdim // The immediate is already shifted for the implicit zeroes, so no change 1082226584Sdim // here. 1083226584Sdim return MO1.getImm() & 0xff; 1084226584Sdim} 1085226584Sdim 1086226584Sdim/// getAddrModeISOpValue - Encode the t_addrmode_is# operands. 1087226584Sdimuint32_t ARMMCCodeEmitter:: 1088226584SdimgetAddrModeISOpValue(const MCInst &MI, unsigned OpIdx, 1089226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1090226584Sdim // [Rn, #imm] 1091226584Sdim // {7-3} = imm5 1092226584Sdim // {2-0} = Rn 1093226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 1094226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 1095239462Sdim unsigned Rn = CTX.getRegisterInfo().getEncodingValue(MO.getReg()); 1096226584Sdim unsigned Imm5 = MO1.getImm(); 1097226584Sdim return ((Imm5 & 0x1f) << 3) | Rn; 1098226584Sdim} 1099226584Sdim 1100226584Sdim/// getAddrModePCOpValue - Return encoding for t_addrmode_pc operands. 1101226584Sdimuint32_t ARMMCCodeEmitter:: 1102226584SdimgetAddrModePCOpValue(const MCInst &MI, unsigned OpIdx, 1103226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1104226584Sdim const MCOperand MO = MI.getOperand(OpIdx); 1105226584Sdim if (MO.isExpr()) 1106226584Sdim return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_cp, Fixups); 1107226584Sdim return (MO.getImm() >> 2); 1108226584Sdim} 1109226584Sdim 1110226584Sdim/// getAddrMode5OpValue - Return encoding info for 'reg +/- imm10' operand. 1111226584Sdimuint32_t ARMMCCodeEmitter:: 1112226584SdimgetAddrMode5OpValue(const MCInst &MI, unsigned OpIdx, 1113226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1114226584Sdim // {12-9} = reg 1115226584Sdim // {8} = (U)nsigned (add == '1', sub == '0') 1116226584Sdim // {7-0} = imm8 1117226584Sdim unsigned Reg, Imm8; 1118226584Sdim bool isAdd; 1119226584Sdim // If The first operand isn't a register, we have a label reference. 1120226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 1121226584Sdim if (!MO.isReg()) { 1122239462Sdim Reg = CTX.getRegisterInfo().getEncodingValue(ARM::PC); // Rn is PC. 1123226584Sdim Imm8 = 0; 1124226584Sdim isAdd = false; // 'U' bit is handled as part of the fixup. 1125226584Sdim 1126226584Sdim assert(MO.isExpr() && "Unexpected machine operand type!"); 1127226584Sdim const MCExpr *Expr = MO.getExpr(); 1128226584Sdim MCFixupKind Kind; 1129226584Sdim if (isThumb2()) 1130226584Sdim Kind = MCFixupKind(ARM::fixup_t2_pcrel_10); 1131226584Sdim else 1132226584Sdim Kind = MCFixupKind(ARM::fixup_arm_pcrel_10); 1133234353Sdim Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); 1134226584Sdim 1135226584Sdim ++MCNumCPRelocations; 1136226584Sdim } else { 1137226584Sdim EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups); 1138226584Sdim isAdd = ARM_AM::getAM5Op(Imm8) == ARM_AM::add; 1139226584Sdim } 1140226584Sdim 1141226584Sdim uint32_t Binary = ARM_AM::getAM5Offset(Imm8); 1142226584Sdim // Immediate is always encoded as positive. The 'U' bit controls add vs sub. 1143226584Sdim if (isAdd) 1144226584Sdim Binary |= (1 << 8); 1145226584Sdim Binary |= (Reg << 9); 1146226584Sdim return Binary; 1147226584Sdim} 1148226584Sdim 1149226584Sdimunsigned ARMMCCodeEmitter:: 1150226584SdimgetSORegRegOpValue(const MCInst &MI, unsigned OpIdx, 1151226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1152226584Sdim // Sub-operands are [reg, reg, imm]. The first register is Rm, the reg to be 1153226584Sdim // shifted. The second is Rs, the amount to shift by, and the third specifies 1154226584Sdim // the type of the shift. 1155226584Sdim // 1156226584Sdim // {3-0} = Rm. 1157226584Sdim // {4} = 1 1158226584Sdim // {6-5} = type 1159226584Sdim // {11-8} = Rs 1160226584Sdim // {7} = 0 1161226584Sdim 1162226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 1163226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 1164226584Sdim const MCOperand &MO2 = MI.getOperand(OpIdx + 2); 1165226584Sdim ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO2.getImm()); 1166226584Sdim 1167226584Sdim // Encode Rm. 1168239462Sdim unsigned Binary = CTX.getRegisterInfo().getEncodingValue(MO.getReg()); 1169226584Sdim 1170226584Sdim // Encode the shift opcode. 1171226584Sdim unsigned SBits = 0; 1172226584Sdim unsigned Rs = MO1.getReg(); 1173226584Sdim if (Rs) { 1174226584Sdim // Set shift operand (bit[7:4]). 1175226584Sdim // LSL - 0001 1176226584Sdim // LSR - 0011 1177226584Sdim // ASR - 0101 1178226584Sdim // ROR - 0111 1179226584Sdim switch (SOpc) { 1180226584Sdim default: llvm_unreachable("Unknown shift opc!"); 1181226584Sdim case ARM_AM::lsl: SBits = 0x1; break; 1182226584Sdim case ARM_AM::lsr: SBits = 0x3; break; 1183226584Sdim case ARM_AM::asr: SBits = 0x5; break; 1184226584Sdim case ARM_AM::ror: SBits = 0x7; break; 1185226584Sdim } 1186226584Sdim } 1187226584Sdim 1188226584Sdim Binary |= SBits << 4; 1189226584Sdim 1190226584Sdim // Encode the shift operation Rs. 1191226584Sdim // Encode Rs bit[11:8]. 1192226584Sdim assert(ARM_AM::getSORegOffset(MO2.getImm()) == 0); 1193239462Sdim return Binary | (CTX.getRegisterInfo().getEncodingValue(Rs) << ARMII::RegRsShift); 1194226584Sdim} 1195226584Sdim 1196226584Sdimunsigned ARMMCCodeEmitter:: 1197226584SdimgetSORegImmOpValue(const MCInst &MI, unsigned OpIdx, 1198226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1199226584Sdim // Sub-operands are [reg, imm]. The first register is Rm, the reg to be 1200226584Sdim // shifted. The second is the amount to shift by. 1201226584Sdim // 1202226584Sdim // {3-0} = Rm. 1203226584Sdim // {4} = 0 1204226584Sdim // {6-5} = type 1205226584Sdim // {11-7} = imm 1206226584Sdim 1207226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 1208226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 1209226584Sdim ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO1.getImm()); 1210226584Sdim 1211226584Sdim // Encode Rm. 1212239462Sdim unsigned Binary = CTX.getRegisterInfo().getEncodingValue(MO.getReg()); 1213226584Sdim 1214226584Sdim // Encode the shift opcode. 1215226584Sdim unsigned SBits = 0; 1216226584Sdim 1217226584Sdim // Set shift operand (bit[6:4]). 1218226584Sdim // LSL - 000 1219226584Sdim // LSR - 010 1220226584Sdim // ASR - 100 1221226584Sdim // ROR - 110 1222226584Sdim // RRX - 110 and bit[11:8] clear. 1223226584Sdim switch (SOpc) { 1224226584Sdim default: llvm_unreachable("Unknown shift opc!"); 1225226584Sdim case ARM_AM::lsl: SBits = 0x0; break; 1226226584Sdim case ARM_AM::lsr: SBits = 0x2; break; 1227226584Sdim case ARM_AM::asr: SBits = 0x4; break; 1228226584Sdim case ARM_AM::ror: SBits = 0x6; break; 1229226584Sdim case ARM_AM::rrx: 1230226584Sdim Binary |= 0x60; 1231226584Sdim return Binary; 1232226584Sdim } 1233226584Sdim 1234226584Sdim // Encode shift_imm bit[11:7]. 1235226584Sdim Binary |= SBits << 4; 1236226584Sdim unsigned Offset = ARM_AM::getSORegOffset(MO1.getImm()); 1237239462Sdim assert(Offset < 32 && "Offset must be in range 0-31!"); 1238226584Sdim return Binary | (Offset << 7); 1239226584Sdim} 1240226584Sdim 1241226584Sdim 1242226584Sdimunsigned ARMMCCodeEmitter:: 1243226584SdimgetT2AddrModeSORegOpValue(const MCInst &MI, unsigned OpNum, 1244226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1245226584Sdim const MCOperand &MO1 = MI.getOperand(OpNum); 1246226584Sdim const MCOperand &MO2 = MI.getOperand(OpNum+1); 1247226584Sdim const MCOperand &MO3 = MI.getOperand(OpNum+2); 1248226584Sdim 1249226584Sdim // Encoded as [Rn, Rm, imm]. 1250226584Sdim // FIXME: Needs fixup support. 1251239462Sdim unsigned Value = CTX.getRegisterInfo().getEncodingValue(MO1.getReg()); 1252226584Sdim Value <<= 4; 1253239462Sdim Value |= CTX.getRegisterInfo().getEncodingValue(MO2.getReg()); 1254226584Sdim Value <<= 2; 1255226584Sdim Value |= MO3.getImm(); 1256226584Sdim 1257226584Sdim return Value; 1258226584Sdim} 1259226584Sdim 1260226584Sdimunsigned ARMMCCodeEmitter:: 1261226584SdimgetT2AddrModeImm8OpValue(const MCInst &MI, unsigned OpNum, 1262226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1263226584Sdim const MCOperand &MO1 = MI.getOperand(OpNum); 1264226584Sdim const MCOperand &MO2 = MI.getOperand(OpNum+1); 1265226584Sdim 1266226584Sdim // FIXME: Needs fixup support. 1267239462Sdim unsigned Value = CTX.getRegisterInfo().getEncodingValue(MO1.getReg()); 1268226584Sdim 1269226584Sdim // Even though the immediate is 8 bits long, we need 9 bits in order 1270226584Sdim // to represent the (inverse of the) sign bit. 1271226584Sdim Value <<= 9; 1272226584Sdim int32_t tmp = (int32_t)MO2.getImm(); 1273226584Sdim if (tmp < 0) 1274226584Sdim tmp = abs(tmp); 1275226584Sdim else 1276226584Sdim Value |= 256; // Set the ADD bit 1277226584Sdim Value |= tmp & 255; 1278226584Sdim return Value; 1279226584Sdim} 1280226584Sdim 1281226584Sdimunsigned ARMMCCodeEmitter:: 1282226584SdimgetT2AddrModeImm8OffsetOpValue(const MCInst &MI, unsigned OpNum, 1283226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1284226584Sdim const MCOperand &MO1 = MI.getOperand(OpNum); 1285226584Sdim 1286226584Sdim // FIXME: Needs fixup support. 1287226584Sdim unsigned Value = 0; 1288226584Sdim int32_t tmp = (int32_t)MO1.getImm(); 1289226584Sdim if (tmp < 0) 1290226584Sdim tmp = abs(tmp); 1291226584Sdim else 1292226584Sdim Value |= 256; // Set the ADD bit 1293226584Sdim Value |= tmp & 255; 1294226584Sdim return Value; 1295226584Sdim} 1296226584Sdim 1297226584Sdimunsigned ARMMCCodeEmitter:: 1298226584SdimgetT2AddrModeImm12OffsetOpValue(const MCInst &MI, unsigned OpNum, 1299226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1300226584Sdim const MCOperand &MO1 = MI.getOperand(OpNum); 1301226584Sdim 1302226584Sdim // FIXME: Needs fixup support. 1303226584Sdim unsigned Value = 0; 1304226584Sdim int32_t tmp = (int32_t)MO1.getImm(); 1305226584Sdim if (tmp < 0) 1306226584Sdim tmp = abs(tmp); 1307226584Sdim else 1308226584Sdim Value |= 4096; // Set the ADD bit 1309226584Sdim Value |= tmp & 4095; 1310226584Sdim return Value; 1311226584Sdim} 1312226584Sdim 1313226584Sdimunsigned ARMMCCodeEmitter:: 1314226584SdimgetT2SORegOpValue(const MCInst &MI, unsigned OpIdx, 1315226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1316226584Sdim // Sub-operands are [reg, imm]. The first register is Rm, the reg to be 1317226584Sdim // shifted. The second is the amount to shift by. 1318226584Sdim // 1319226584Sdim // {3-0} = Rm. 1320226584Sdim // {4} = 0 1321226584Sdim // {6-5} = type 1322226584Sdim // {11-7} = imm 1323226584Sdim 1324226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 1325226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 1326226584Sdim ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO1.getImm()); 1327226584Sdim 1328226584Sdim // Encode Rm. 1329239462Sdim unsigned Binary = CTX.getRegisterInfo().getEncodingValue(MO.getReg()); 1330226584Sdim 1331226584Sdim // Encode the shift opcode. 1332226584Sdim unsigned SBits = 0; 1333226584Sdim // Set shift operand (bit[6:4]). 1334226584Sdim // LSL - 000 1335226584Sdim // LSR - 010 1336226584Sdim // ASR - 100 1337226584Sdim // ROR - 110 1338226584Sdim switch (SOpc) { 1339226584Sdim default: llvm_unreachable("Unknown shift opc!"); 1340226584Sdim case ARM_AM::lsl: SBits = 0x0; break; 1341226584Sdim case ARM_AM::lsr: SBits = 0x2; break; 1342226584Sdim case ARM_AM::asr: SBits = 0x4; break; 1343226584Sdim case ARM_AM::rrx: // FALLTHROUGH 1344226584Sdim case ARM_AM::ror: SBits = 0x6; break; 1345226584Sdim } 1346226584Sdim 1347226584Sdim Binary |= SBits << 4; 1348226584Sdim if (SOpc == ARM_AM::rrx) 1349226584Sdim return Binary; 1350226584Sdim 1351226584Sdim // Encode shift_imm bit[11:7]. 1352226584Sdim return Binary | ARM_AM::getSORegOffset(MO1.getImm()) << 7; 1353226584Sdim} 1354226584Sdim 1355226584Sdimunsigned ARMMCCodeEmitter:: 1356226584SdimgetBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op, 1357226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1358226584Sdim // 10 bits. lower 5 bits are are the lsb of the mask, high five bits are the 1359226584Sdim // msb of the mask. 1360226584Sdim const MCOperand &MO = MI.getOperand(Op); 1361226584Sdim uint32_t v = ~MO.getImm(); 1362226584Sdim uint32_t lsb = CountTrailingZeros_32(v); 1363226584Sdim uint32_t msb = (32 - CountLeadingZeros_32 (v)) - 1; 1364226584Sdim assert (v != 0 && lsb < 32 && msb < 32 && "Illegal bitfield mask!"); 1365226584Sdim return lsb | (msb << 5); 1366226584Sdim} 1367226584Sdim 1368226584Sdimunsigned ARMMCCodeEmitter:: 1369226584SdimgetRegisterListOpValue(const MCInst &MI, unsigned Op, 1370226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1371226584Sdim // VLDM/VSTM: 1372226584Sdim // {12-8} = Vd 1373226584Sdim // {7-0} = Number of registers 1374226584Sdim // 1375226584Sdim // LDM/STM: 1376226584Sdim // {15-0} = Bitfield of GPRs. 1377226584Sdim unsigned Reg = MI.getOperand(Op).getReg(); 1378234353Sdim bool SPRRegs = ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg); 1379234353Sdim bool DPRRegs = ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg); 1380226584Sdim 1381226584Sdim unsigned Binary = 0; 1382226584Sdim 1383226584Sdim if (SPRRegs || DPRRegs) { 1384226584Sdim // VLDM/VSTM 1385239462Sdim unsigned RegNo = CTX.getRegisterInfo().getEncodingValue(Reg); 1386226584Sdim unsigned NumRegs = (MI.getNumOperands() - Op) & 0xff; 1387226584Sdim Binary |= (RegNo & 0x1f) << 8; 1388226584Sdim if (SPRRegs) 1389226584Sdim Binary |= NumRegs; 1390226584Sdim else 1391226584Sdim Binary |= NumRegs * 2; 1392226584Sdim } else { 1393226584Sdim for (unsigned I = Op, E = MI.getNumOperands(); I < E; ++I) { 1394239462Sdim unsigned RegNo = CTX.getRegisterInfo().getEncodingValue(MI.getOperand(I).getReg()); 1395226584Sdim Binary |= 1 << RegNo; 1396226584Sdim } 1397226584Sdim } 1398226584Sdim 1399226584Sdim return Binary; 1400226584Sdim} 1401226584Sdim 1402226584Sdim/// getAddrMode6AddressOpValue - Encode an addrmode6 register number along 1403226584Sdim/// with the alignment operand. 1404226584Sdimunsigned ARMMCCodeEmitter:: 1405226584SdimgetAddrMode6AddressOpValue(const MCInst &MI, unsigned Op, 1406226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1407226584Sdim const MCOperand &Reg = MI.getOperand(Op); 1408226584Sdim const MCOperand &Imm = MI.getOperand(Op + 1); 1409226584Sdim 1410239462Sdim unsigned RegNo = CTX.getRegisterInfo().getEncodingValue(Reg.getReg()); 1411226584Sdim unsigned Align = 0; 1412226584Sdim 1413226584Sdim switch (Imm.getImm()) { 1414226584Sdim default: break; 1415226584Sdim case 2: 1416226584Sdim case 4: 1417226584Sdim case 8: Align = 0x01; break; 1418226584Sdim case 16: Align = 0x02; break; 1419226584Sdim case 32: Align = 0x03; break; 1420226584Sdim } 1421226584Sdim 1422226584Sdim return RegNo | (Align << 4); 1423226584Sdim} 1424226584Sdim 1425226584Sdim/// getAddrMode6OneLane32AddressOpValue - Encode an addrmode6 register number 1426226584Sdim/// along with the alignment operand for use in VST1 and VLD1 with size 32. 1427226584Sdimunsigned ARMMCCodeEmitter:: 1428226584SdimgetAddrMode6OneLane32AddressOpValue(const MCInst &MI, unsigned Op, 1429226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1430226584Sdim const MCOperand &Reg = MI.getOperand(Op); 1431226584Sdim const MCOperand &Imm = MI.getOperand(Op + 1); 1432226584Sdim 1433239462Sdim unsigned RegNo = CTX.getRegisterInfo().getEncodingValue(Reg.getReg()); 1434226584Sdim unsigned Align = 0; 1435226584Sdim 1436226584Sdim switch (Imm.getImm()) { 1437226584Sdim default: break; 1438226584Sdim case 8: 1439234353Sdim case 16: 1440234353Sdim case 32: // Default '0' value for invalid alignments of 8, 16, 32 bytes. 1441234353Sdim case 2: Align = 0x00; break; 1442234353Sdim case 4: Align = 0x03; break; 1443226584Sdim } 1444226584Sdim 1445226584Sdim return RegNo | (Align << 4); 1446226584Sdim} 1447226584Sdim 1448226584Sdim 1449226584Sdim/// getAddrMode6DupAddressOpValue - Encode an addrmode6 register number and 1450226584Sdim/// alignment operand for use in VLD-dup instructions. This is the same as 1451226584Sdim/// getAddrMode6AddressOpValue except for the alignment encoding, which is 1452226584Sdim/// different for VLD4-dup. 1453226584Sdimunsigned ARMMCCodeEmitter:: 1454226584SdimgetAddrMode6DupAddressOpValue(const MCInst &MI, unsigned Op, 1455226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1456226584Sdim const MCOperand &Reg = MI.getOperand(Op); 1457226584Sdim const MCOperand &Imm = MI.getOperand(Op + 1); 1458226584Sdim 1459239462Sdim unsigned RegNo = CTX.getRegisterInfo().getEncodingValue(Reg.getReg()); 1460226584Sdim unsigned Align = 0; 1461226584Sdim 1462226584Sdim switch (Imm.getImm()) { 1463226584Sdim default: break; 1464226584Sdim case 2: 1465226584Sdim case 4: 1466226584Sdim case 8: Align = 0x01; break; 1467226584Sdim case 16: Align = 0x03; break; 1468226584Sdim } 1469226584Sdim 1470226584Sdim return RegNo | (Align << 4); 1471226584Sdim} 1472226584Sdim 1473226584Sdimunsigned ARMMCCodeEmitter:: 1474226584SdimgetAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op, 1475226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1476226584Sdim const MCOperand &MO = MI.getOperand(Op); 1477226584Sdim if (MO.getReg() == 0) return 0x0D; 1478239462Sdim return CTX.getRegisterInfo().getEncodingValue(MO.getReg()); 1479226584Sdim} 1480226584Sdim 1481226584Sdimunsigned ARMMCCodeEmitter:: 1482226584SdimgetShiftRight8Imm(const MCInst &MI, unsigned Op, 1483226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1484226584Sdim return 8 - MI.getOperand(Op).getImm(); 1485226584Sdim} 1486226584Sdim 1487226584Sdimunsigned ARMMCCodeEmitter:: 1488226584SdimgetShiftRight16Imm(const MCInst &MI, unsigned Op, 1489226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1490226584Sdim return 16 - MI.getOperand(Op).getImm(); 1491226584Sdim} 1492226584Sdim 1493226584Sdimunsigned ARMMCCodeEmitter:: 1494226584SdimgetShiftRight32Imm(const MCInst &MI, unsigned Op, 1495226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1496226584Sdim return 32 - MI.getOperand(Op).getImm(); 1497226584Sdim} 1498226584Sdim 1499226584Sdimunsigned ARMMCCodeEmitter:: 1500226584SdimgetShiftRight64Imm(const MCInst &MI, unsigned Op, 1501226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1502226584Sdim return 64 - MI.getOperand(Op).getImm(); 1503226584Sdim} 1504226584Sdim 1505226584Sdimvoid ARMMCCodeEmitter:: 1506226584SdimEncodeInstruction(const MCInst &MI, raw_ostream &OS, 1507226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1508226584Sdim // Pseudo instructions don't get encoded. 1509226584Sdim const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); 1510226584Sdim uint64_t TSFlags = Desc.TSFlags; 1511226584Sdim if ((TSFlags & ARMII::FormMask) == ARMII::Pseudo) 1512226584Sdim return; 1513226584Sdim 1514226584Sdim int Size; 1515226584Sdim if (Desc.getSize() == 2 || Desc.getSize() == 4) 1516226584Sdim Size = Desc.getSize(); 1517226584Sdim else 1518226584Sdim llvm_unreachable("Unexpected instruction size!"); 1519226584Sdim 1520226584Sdim uint32_t Binary = getBinaryCodeForInstr(MI, Fixups); 1521226584Sdim // Thumb 32-bit wide instructions need to emit the high order halfword 1522226584Sdim // first. 1523226584Sdim if (isThumb() && Size == 4) { 1524226584Sdim EmitConstant(Binary >> 16, 2, OS); 1525226584Sdim EmitConstant(Binary & 0xffff, 2, OS); 1526226584Sdim } else 1527226584Sdim EmitConstant(Binary, Size, OS); 1528226584Sdim ++MCNumEmitted; // Keep track of the # of mi's emitted. 1529226584Sdim} 1530226584Sdim 1531226584Sdim#include "ARMGenMCCodeEmitter.inc" 1532