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" 15252723Sdim#include "MCTargetDesc/ARMMCTargetDesc.h" 16226584Sdim#include "MCTargetDesc/ARMAddressingModes.h" 17226584Sdim#include "MCTargetDesc/ARMBaseInfo.h" 18226584Sdim#include "MCTargetDesc/ARMFixupKinds.h" 19226584Sdim#include "MCTargetDesc/ARMMCExpr.h" 20252723Sdim#include "llvm/ADT/APFloat.h" 21252723Sdim#include "llvm/ADT/Statistic.h" 22226584Sdim#include "llvm/MC/MCCodeEmitter.h" 23245431Sdim#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 { 38245431Sdim ARMMCCodeEmitter(const ARMMCCodeEmitter &) LLVM_DELETED_FUNCTION; 39245431Sdim void operator=(const ARMMCCodeEmitter &) LLVM_DELETED_FUNCTION; 40226584Sdim const MCInstrInfo &MCII; 41226584Sdim const MCSubtargetInfo &STI; 42245431Sdim const MCContext &CTX; 43226584Sdim 44226584Sdimpublic: 45226584Sdim ARMMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti, 46226584Sdim MCContext &ctx) 47245431Sdim : 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()); 61263509Sdim return TT.isOSDarwin(); 62226584Sdim } 63226584Sdim 64226584Sdim unsigned getMachineSoImmOpValue(unsigned SoImm) const; 65226584Sdim 66226584Sdim // getBinaryCodeForInstr - TableGen'erated function for getting the 67226584Sdim // binary encoding for an instruction. 68235633Sdim uint64_t getBinaryCodeForInstr(const MCInst &MI, 69226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 70226584Sdim 71226584Sdim /// getMachineOpValue - Return binary encoding of operand. If the machine 72226584Sdim /// operand requires relocation, record the relocation and return zero. 73226584Sdim unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO, 74226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 75226584Sdim 76226584Sdim /// getHiLo16ImmOpValue - Return the encoding for the hi / low 16-bit of 77226584Sdim /// the specified operand. This is used for operands with :lower16: and 78226584Sdim /// :upper16: prefixes. 79226584Sdim uint32_t getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx, 80226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 81226584Sdim 82226584Sdim bool EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx, 83226584Sdim unsigned &Reg, unsigned &Imm, 84226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 85226584Sdim 86226584Sdim /// getThumbBLTargetOpValue - Return encoding info for Thumb immediate 87226584Sdim /// BL branch target. 88226584Sdim uint32_t getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx, 89226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 90226584Sdim 91226584Sdim /// getThumbBLXTargetOpValue - Return encoding info for Thumb immediate 92226584Sdim /// BLX branch target. 93226584Sdim uint32_t getThumbBLXTargetOpValue(const MCInst &MI, unsigned OpIdx, 94226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 95226584Sdim 96226584Sdim /// getThumbBRTargetOpValue - Return encoding info for Thumb branch target. 97226584Sdim uint32_t getThumbBRTargetOpValue(const MCInst &MI, unsigned OpIdx, 98226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 99226584Sdim 100226584Sdim /// getThumbBCCTargetOpValue - Return encoding info for Thumb branch target. 101226584Sdim uint32_t getThumbBCCTargetOpValue(const MCInst &MI, unsigned OpIdx, 102226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 103226584Sdim 104226584Sdim /// getThumbCBTargetOpValue - Return encoding info for Thumb branch target. 105226584Sdim uint32_t getThumbCBTargetOpValue(const MCInst &MI, unsigned OpIdx, 106226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 107226584Sdim 108226584Sdim /// getBranchTargetOpValue - Return encoding info for 24-bit immediate 109226584Sdim /// branch target. 110226584Sdim uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 111226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 112226584Sdim 113226584Sdim /// getUnconditionalBranchTargetOpValue - Return encoding info for 24-bit 114226584Sdim /// immediate Thumb2 direct branch target. 115226584Sdim uint32_t getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 116226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 117226584Sdim 118226584Sdim /// getARMBranchTargetOpValue - Return encoding info for 24-bit immediate 119226584Sdim /// branch target. 120226584Sdim uint32_t getARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 121226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 122235633Sdim uint32_t getARMBLTargetOpValue(const MCInst &MI, unsigned OpIdx, 123235633Sdim SmallVectorImpl<MCFixup> &Fixups) const; 124226584Sdim uint32_t getARMBLXTargetOpValue(const MCInst &MI, unsigned OpIdx, 125235633Sdim SmallVectorImpl<MCFixup> &Fixups) const; 126226584Sdim 127226584Sdim /// getAdrLabelOpValue - Return encoding info for 12-bit immediate 128226584Sdim /// ADR label target. 129226584Sdim uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, 130226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 131226584Sdim uint32_t getThumbAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, 132226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 133226584Sdim uint32_t getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx, 134226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 135226584Sdim 136226584Sdim 137226584Sdim /// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12' 138226584Sdim /// operand. 139226584Sdim uint32_t getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx, 140226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 141226584Sdim 142226584Sdim /// getThumbAddrModeRegRegOpValue - Return encoding for 'reg + reg' operand. 143226584Sdim uint32_t getThumbAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx, 144226584Sdim SmallVectorImpl<MCFixup> &Fixups)const; 145226584Sdim 146226584Sdim /// getT2AddrModeImm8s4OpValue - Return encoding info for 'reg +/- imm8<<2' 147226584Sdim /// operand. 148226584Sdim uint32_t getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx, 149226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 150226584Sdim 151226584Sdim /// getT2AddrModeImm0_1020s4OpValue - Return encoding info for 'reg + imm8<<2' 152226584Sdim /// operand. 153226584Sdim uint32_t getT2AddrModeImm0_1020s4OpValue(const MCInst &MI, unsigned OpIdx, 154226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 155226584Sdim 156226584Sdim /// getT2Imm8s4OpValue - Return encoding info for '+/- imm8<<2' 157226584Sdim /// operand. 158226584Sdim uint32_t getT2Imm8s4OpValue(const MCInst &MI, unsigned OpIdx, 159226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 160226584Sdim 161226584Sdim 162226584Sdim /// getLdStSORegOpValue - Return encoding info for 'reg +/- reg shop imm' 163226584Sdim /// operand as needed by load/store instructions. 164226584Sdim uint32_t getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx, 165226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 166226584Sdim 167226584Sdim /// getLdStmModeOpValue - Return encoding for load/store multiple mode. 168226584Sdim uint32_t getLdStmModeOpValue(const MCInst &MI, unsigned OpIdx, 169226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 170226584Sdim ARM_AM::AMSubMode Mode = (ARM_AM::AMSubMode)MI.getOperand(OpIdx).getImm(); 171226584Sdim switch (Mode) { 172235633Sdim default: llvm_unreachable("Unknown addressing sub-mode!"); 173226584Sdim case ARM_AM::da: return 0; 174226584Sdim case ARM_AM::ia: return 1; 175226584Sdim case ARM_AM::db: return 2; 176226584Sdim case ARM_AM::ib: return 3; 177226584Sdim } 178226584Sdim } 179226584Sdim /// getShiftOp - Return the shift opcode (bit[6:5]) of the immediate value. 180226584Sdim /// 181226584Sdim unsigned getShiftOp(ARM_AM::ShiftOpc ShOpc) const { 182226584Sdim switch (ShOpc) { 183226584Sdim case ARM_AM::no_shift: 184226584Sdim case ARM_AM::lsl: return 0; 185226584Sdim case ARM_AM::lsr: return 1; 186226584Sdim case ARM_AM::asr: return 2; 187226584Sdim case ARM_AM::ror: 188226584Sdim case ARM_AM::rrx: return 3; 189226584Sdim } 190235633Sdim llvm_unreachable("Invalid ShiftOpc!"); 191226584Sdim } 192226584Sdim 193226584Sdim /// getAddrMode2OpValue - Return encoding for addrmode2 operands. 194226584Sdim uint32_t getAddrMode2OpValue(const MCInst &MI, unsigned OpIdx, 195226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 196226584Sdim 197226584Sdim /// getAddrMode2OffsetOpValue - Return encoding for am2offset operands. 198226584Sdim uint32_t getAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx, 199226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 200226584Sdim 201226584Sdim /// getPostIdxRegOpValue - Return encoding for postidx_reg operands. 202226584Sdim uint32_t getPostIdxRegOpValue(const MCInst &MI, unsigned OpIdx, 203226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 204226584Sdim 205226584Sdim /// getAddrMode3OffsetOpValue - Return encoding for am3offset operands. 206226584Sdim uint32_t getAddrMode3OffsetOpValue(const MCInst &MI, unsigned OpIdx, 207226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 208226584Sdim 209226584Sdim /// getAddrMode3OpValue - Return encoding for addrmode3 operands. 210226584Sdim uint32_t getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx, 211226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 212226584Sdim 213226584Sdim /// getAddrModeThumbSPOpValue - Return encoding info for 'reg +/- imm12' 214226584Sdim /// operand. 215226584Sdim uint32_t getAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx, 216226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 217226584Sdim 218226584Sdim /// getAddrModeISOpValue - Encode the t_addrmode_is# operands. 219226584Sdim uint32_t getAddrModeISOpValue(const MCInst &MI, unsigned OpIdx, 220226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 221226584Sdim 222226584Sdim /// getAddrModePCOpValue - Return encoding for t_addrmode_pc operands. 223226584Sdim uint32_t getAddrModePCOpValue(const MCInst &MI, unsigned OpIdx, 224226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 225226584Sdim 226226584Sdim /// getAddrMode5OpValue - Return encoding info for 'reg +/- imm8' operand. 227226584Sdim uint32_t getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx, 228226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 229226584Sdim 230226584Sdim /// getCCOutOpValue - Return encoding of the 's' bit. 231226584Sdim unsigned getCCOutOpValue(const MCInst &MI, unsigned Op, 232226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 233226584Sdim // The operand is either reg0 or CPSR. The 's' bit is encoded as '0' or 234226584Sdim // '1' respectively. 235226584Sdim return MI.getOperand(Op).getReg() == ARM::CPSR; 236226584Sdim } 237226584Sdim 238226584Sdim /// getSOImmOpValue - Return an encoded 12-bit shifted-immediate value. 239226584Sdim unsigned getSOImmOpValue(const MCInst &MI, unsigned Op, 240226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 241226584Sdim unsigned SoImm = MI.getOperand(Op).getImm(); 242226584Sdim int SoImmVal = ARM_AM::getSOImmVal(SoImm); 243226584Sdim assert(SoImmVal != -1 && "Not a valid so_imm value!"); 244226584Sdim 245226584Sdim // Encode rotate_imm. 246226584Sdim unsigned Binary = (ARM_AM::getSOImmValRot((unsigned)SoImmVal) >> 1) 247226584Sdim << ARMII::SoRotImmShift; 248226584Sdim 249226584Sdim // Encode immed_8. 250226584Sdim Binary |= ARM_AM::getSOImmValImm((unsigned)SoImmVal); 251226584Sdim return Binary; 252226584Sdim } 253226584Sdim 254226584Sdim /// getT2SOImmOpValue - Return an encoded 12-bit shifted-immediate value. 255226584Sdim unsigned getT2SOImmOpValue(const MCInst &MI, unsigned Op, 256226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 257226584Sdim unsigned SoImm = MI.getOperand(Op).getImm(); 258226584Sdim unsigned Encoded = ARM_AM::getT2SOImmVal(SoImm); 259226584Sdim assert(Encoded != ~0U && "Not a Thumb2 so_imm value?"); 260226584Sdim return Encoded; 261226584Sdim } 262226584Sdim 263226584Sdim unsigned getT2AddrModeSORegOpValue(const MCInst &MI, unsigned OpNum, 264226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 265226584Sdim unsigned getT2AddrModeImm8OpValue(const MCInst &MI, unsigned OpNum, 266226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 267226584Sdim unsigned getT2AddrModeImm8OffsetOpValue(const MCInst &MI, unsigned OpNum, 268226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 269226584Sdim unsigned getT2AddrModeImm12OffsetOpValue(const MCInst &MI, unsigned OpNum, 270226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 271226584Sdim 272226584Sdim /// getSORegOpValue - Return an encoded so_reg shifted register value. 273226584Sdim unsigned getSORegRegOpValue(const MCInst &MI, unsigned Op, 274226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 275226584Sdim unsigned getSORegImmOpValue(const MCInst &MI, unsigned Op, 276226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 277226584Sdim unsigned getT2SORegOpValue(const MCInst &MI, unsigned Op, 278226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 279226584Sdim 280226584Sdim unsigned getNEONVcvtImm32OpValue(const MCInst &MI, unsigned Op, 281226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 282226584Sdim return 64 - MI.getOperand(Op).getImm(); 283226584Sdim } 284226584Sdim 285226584Sdim unsigned getBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op, 286226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 287226584Sdim 288226584Sdim unsigned getRegisterListOpValue(const MCInst &MI, unsigned Op, 289226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 290226584Sdim unsigned getAddrMode6AddressOpValue(const MCInst &MI, unsigned Op, 291226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 292226584Sdim unsigned getAddrMode6OneLane32AddressOpValue(const MCInst &MI, unsigned Op, 293226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 294226584Sdim unsigned getAddrMode6DupAddressOpValue(const MCInst &MI, unsigned Op, 295226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 296226584Sdim unsigned getAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op, 297226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 298226584Sdim 299226584Sdim unsigned getShiftRight8Imm(const MCInst &MI, unsigned Op, 300226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 301226584Sdim unsigned getShiftRight16Imm(const MCInst &MI, unsigned Op, 302226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 303226584Sdim unsigned getShiftRight32Imm(const MCInst &MI, unsigned Op, 304226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 305226584Sdim unsigned getShiftRight64Imm(const MCInst &MI, unsigned Op, 306226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 307226584Sdim 308226584Sdim unsigned getThumbSRImmOpValue(const MCInst &MI, unsigned Op, 309226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 310226584Sdim 311226584Sdim unsigned NEONThumb2DataIPostEncoder(const MCInst &MI, 312226584Sdim unsigned EncodedValue) const; 313226584Sdim unsigned NEONThumb2LoadStorePostEncoder(const MCInst &MI, 314226584Sdim unsigned EncodedValue) const; 315226584Sdim unsigned NEONThumb2DupPostEncoder(const MCInst &MI, 316226584Sdim unsigned EncodedValue) const; 317263509Sdim unsigned NEONThumb2V8PostEncoder(const MCInst &MI, 318263509Sdim unsigned EncodedValue) const; 319226584Sdim 320226584Sdim unsigned VFPThumb2PostEncoder(const MCInst &MI, 321226584Sdim unsigned EncodedValue) const; 322226584Sdim 323226584Sdim void EmitByte(unsigned char C, raw_ostream &OS) const { 324226584Sdim OS << (char)C; 325226584Sdim } 326226584Sdim 327226584Sdim void EmitConstant(uint64_t Val, unsigned Size, raw_ostream &OS) const { 328226584Sdim // Output the constant in little endian byte order. 329226584Sdim for (unsigned i = 0; i != Size; ++i) { 330226584Sdim EmitByte(Val & 255, OS); 331226584Sdim Val >>= 8; 332226584Sdim } 333226584Sdim } 334226584Sdim 335226584Sdim void EncodeInstruction(const MCInst &MI, raw_ostream &OS, 336226584Sdim SmallVectorImpl<MCFixup> &Fixups) const; 337226584Sdim}; 338226584Sdim 339226584Sdim} // end anonymous namespace 340226584Sdim 341226584SdimMCCodeEmitter *llvm::createARMMCCodeEmitter(const MCInstrInfo &MCII, 342245431Sdim const MCRegisterInfo &MRI, 343226584Sdim const MCSubtargetInfo &STI, 344226584Sdim MCContext &Ctx) { 345226584Sdim return new ARMMCCodeEmitter(MCII, STI, Ctx); 346226584Sdim} 347226584Sdim 348226584Sdim/// NEONThumb2DataIPostEncoder - Post-process encoded NEON data-processing 349226584Sdim/// instructions, and rewrite them to their Thumb2 form if we are currently in 350226584Sdim/// Thumb2 mode. 351226584Sdimunsigned ARMMCCodeEmitter::NEONThumb2DataIPostEncoder(const MCInst &MI, 352226584Sdim unsigned EncodedValue) const { 353226584Sdim if (isThumb2()) { 354226584Sdim // NEON Thumb2 data-processsing encodings are very simple: bit 24 is moved 355226584Sdim // to bit 12 of the high half-word (i.e. bit 28), and bits 27-24 are 356226584Sdim // set to 1111. 357226584Sdim unsigned Bit24 = EncodedValue & 0x01000000; 358226584Sdim unsigned Bit28 = Bit24 << 4; 359226584Sdim EncodedValue &= 0xEFFFFFFF; 360226584Sdim EncodedValue |= Bit28; 361226584Sdim EncodedValue |= 0x0F000000; 362226584Sdim } 363226584Sdim 364226584Sdim return EncodedValue; 365226584Sdim} 366226584Sdim 367226584Sdim/// NEONThumb2LoadStorePostEncoder - Post-process encoded NEON load/store 368226584Sdim/// instructions, and rewrite them to their Thumb2 form if we are currently in 369226584Sdim/// Thumb2 mode. 370226584Sdimunsigned ARMMCCodeEmitter::NEONThumb2LoadStorePostEncoder(const MCInst &MI, 371226584Sdim unsigned EncodedValue) const { 372226584Sdim if (isThumb2()) { 373226584Sdim EncodedValue &= 0xF0FFFFFF; 374226584Sdim EncodedValue |= 0x09000000; 375226584Sdim } 376226584Sdim 377226584Sdim return EncodedValue; 378226584Sdim} 379226584Sdim 380226584Sdim/// NEONThumb2DupPostEncoder - Post-process encoded NEON vdup 381226584Sdim/// instructions, and rewrite them to their Thumb2 form if we are currently in 382226584Sdim/// Thumb2 mode. 383226584Sdimunsigned ARMMCCodeEmitter::NEONThumb2DupPostEncoder(const MCInst &MI, 384226584Sdim unsigned EncodedValue) const { 385226584Sdim if (isThumb2()) { 386226584Sdim EncodedValue &= 0x00FFFFFF; 387226584Sdim EncodedValue |= 0xEE000000; 388226584Sdim } 389226584Sdim 390226584Sdim return EncodedValue; 391226584Sdim} 392226584Sdim 393263509Sdim/// Post-process encoded NEON v8 instructions, and rewrite them to Thumb2 form 394263509Sdim/// if we are in Thumb2. 395263509Sdimunsigned ARMMCCodeEmitter::NEONThumb2V8PostEncoder(const MCInst &MI, 396263509Sdim unsigned EncodedValue) const { 397263509Sdim if (isThumb2()) { 398263509Sdim EncodedValue |= 0xC000000; // Set bits 27-26 399263509Sdim } 400263509Sdim 401263509Sdim return EncodedValue; 402263509Sdim} 403263509Sdim 404226584Sdim/// VFPThumb2PostEncoder - Post-process encoded VFP instructions and rewrite 405226584Sdim/// them to their Thumb2 form if we are currently in Thumb2 mode. 406226584Sdimunsigned ARMMCCodeEmitter:: 407226584SdimVFPThumb2PostEncoder(const MCInst &MI, unsigned EncodedValue) const { 408226584Sdim if (isThumb2()) { 409226584Sdim EncodedValue &= 0x0FFFFFFF; 410226584Sdim EncodedValue |= 0xE0000000; 411226584Sdim } 412226584Sdim return EncodedValue; 413226584Sdim} 414226584Sdim 415226584Sdim/// getMachineOpValue - Return binary encoding of operand. If the machine 416226584Sdim/// operand requires relocation, record the relocation and return zero. 417226584Sdimunsigned ARMMCCodeEmitter:: 418226584SdimgetMachineOpValue(const MCInst &MI, const MCOperand &MO, 419226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 420226584Sdim if (MO.isReg()) { 421226584Sdim unsigned Reg = MO.getReg(); 422263509Sdim unsigned RegNo = CTX.getRegisterInfo()->getEncodingValue(Reg); 423226584Sdim 424226584Sdim // Q registers are encoded as 2x their register number. 425226584Sdim switch (Reg) { 426226584Sdim default: 427226584Sdim return RegNo; 428226584Sdim case ARM::Q0: case ARM::Q1: case ARM::Q2: case ARM::Q3: 429226584Sdim case ARM::Q4: case ARM::Q5: case ARM::Q6: case ARM::Q7: 430226584Sdim case ARM::Q8: case ARM::Q9: case ARM::Q10: case ARM::Q11: 431226584Sdim case ARM::Q12: case ARM::Q13: case ARM::Q14: case ARM::Q15: 432226584Sdim return 2 * RegNo; 433226584Sdim } 434226584Sdim } else if (MO.isImm()) { 435226584Sdim return static_cast<unsigned>(MO.getImm()); 436226584Sdim } else if (MO.isFPImm()) { 437226584Sdim return static_cast<unsigned>(APFloat(MO.getFPImm()) 438226584Sdim .bitcastToAPInt().getHiBits(32).getLimitedValue()); 439226584Sdim } 440226584Sdim 441226584Sdim llvm_unreachable("Unable to encode MCOperand!"); 442226584Sdim} 443226584Sdim 444226584Sdim/// getAddrModeImmOpValue - Return encoding info for 'reg +/- imm' operand. 445226584Sdimbool ARMMCCodeEmitter:: 446226584SdimEncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx, unsigned &Reg, 447226584Sdim unsigned &Imm, SmallVectorImpl<MCFixup> &Fixups) const { 448226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 449226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 450226584Sdim 451263509Sdim Reg = CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 452226584Sdim 453226584Sdim int32_t SImm = MO1.getImm(); 454226584Sdim bool isAdd = true; 455226584Sdim 456226584Sdim // Special value for #-0 457226584Sdim if (SImm == INT32_MIN) { 458226584Sdim SImm = 0; 459226584Sdim isAdd = false; 460226584Sdim } 461226584Sdim 462226584Sdim // Immediate is always encoded as positive. The 'U' bit controls add vs sub. 463226584Sdim if (SImm < 0) { 464226584Sdim SImm = -SImm; 465226584Sdim isAdd = false; 466226584Sdim } 467226584Sdim 468226584Sdim Imm = SImm; 469226584Sdim return isAdd; 470226584Sdim} 471226584Sdim 472226584Sdim/// getBranchTargetOpValue - Helper function to get the branch target operand, 473226584Sdim/// which is either an immediate or requires a fixup. 474226584Sdimstatic uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 475226584Sdim unsigned FixupKind, 476226584Sdim SmallVectorImpl<MCFixup> &Fixups) { 477226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 478226584Sdim 479226584Sdim // If the destination is an immediate, we have nothing to do. 480226584Sdim if (MO.isImm()) return MO.getImm(); 481226584Sdim assert(MO.isExpr() && "Unexpected branch target type!"); 482226584Sdim const MCExpr *Expr = MO.getExpr(); 483226584Sdim MCFixupKind Kind = MCFixupKind(FixupKind); 484235633Sdim Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); 485226584Sdim 486226584Sdim // All of the information is in the fixup. 487226584Sdim return 0; 488226584Sdim} 489226584Sdim 490226584Sdim// Thumb BL and BLX use a strange offset encoding where bits 22 and 21 are 491226584Sdim// determined by negating them and XOR'ing them with bit 23. 492226584Sdimstatic int32_t encodeThumbBLOffset(int32_t offset) { 493226584Sdim offset >>= 1; 494226584Sdim uint32_t S = (offset & 0x800000) >> 23; 495226584Sdim uint32_t J1 = (offset & 0x400000) >> 22; 496226584Sdim uint32_t J2 = (offset & 0x200000) >> 21; 497226584Sdim J1 = (~J1 & 0x1); 498226584Sdim J2 = (~J2 & 0x1); 499226584Sdim J1 ^= S; 500226584Sdim J2 ^= S; 501226584Sdim 502226584Sdim offset &= ~0x600000; 503226584Sdim offset |= J1 << 22; 504226584Sdim offset |= J2 << 21; 505226584Sdim 506226584Sdim return offset; 507226584Sdim} 508226584Sdim 509226584Sdim/// getThumbBLTargetOpValue - Return encoding info for immediate branch target. 510226584Sdimuint32_t ARMMCCodeEmitter:: 511226584SdimgetThumbBLTargetOpValue(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_bl, 516226584Sdim Fixups); 517226584Sdim return encodeThumbBLOffset(MO.getImm()); 518226584Sdim} 519226584Sdim 520226584Sdim/// getThumbBLXTargetOpValue - Return encoding info for Thumb immediate 521226584Sdim/// BLX branch target. 522226584Sdimuint32_t ARMMCCodeEmitter:: 523226584SdimgetThumbBLXTargetOpValue(const MCInst &MI, unsigned OpIdx, 524226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 525226584Sdim const MCOperand MO = MI.getOperand(OpIdx); 526226584Sdim if (MO.isExpr()) 527226584Sdim return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_blx, 528226584Sdim Fixups); 529226584Sdim return encodeThumbBLOffset(MO.getImm()); 530226584Sdim} 531226584Sdim 532226584Sdim/// getThumbBRTargetOpValue - Return encoding info for Thumb branch target. 533226584Sdimuint32_t ARMMCCodeEmitter:: 534226584SdimgetThumbBRTargetOpValue(const MCInst &MI, unsigned OpIdx, 535226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 536226584Sdim const MCOperand MO = MI.getOperand(OpIdx); 537226584Sdim if (MO.isExpr()) 538226584Sdim return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_br, 539226584Sdim Fixups); 540226584Sdim return (MO.getImm() >> 1); 541226584Sdim} 542226584Sdim 543226584Sdim/// getThumbBCCTargetOpValue - Return encoding info for Thumb branch target. 544226584Sdimuint32_t ARMMCCodeEmitter:: 545226584SdimgetThumbBCCTargetOpValue(const MCInst &MI, unsigned OpIdx, 546226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 547226584Sdim const MCOperand MO = MI.getOperand(OpIdx); 548226584Sdim if (MO.isExpr()) 549226584Sdim return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_bcc, 550226584Sdim Fixups); 551226584Sdim return (MO.getImm() >> 1); 552226584Sdim} 553226584Sdim 554226584Sdim/// getThumbCBTargetOpValue - Return encoding info for Thumb branch target. 555226584Sdimuint32_t ARMMCCodeEmitter:: 556226584SdimgetThumbCBTargetOpValue(const MCInst &MI, unsigned OpIdx, 557226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 558226584Sdim const MCOperand MO = MI.getOperand(OpIdx); 559226584Sdim if (MO.isExpr()) 560226584Sdim return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_cb, Fixups); 561226584Sdim return (MO.getImm() >> 1); 562226584Sdim} 563226584Sdim 564226584Sdim/// Return true if this branch has a non-always predication 565226584Sdimstatic bool HasConditionalBranch(const MCInst &MI) { 566226584Sdim int NumOp = MI.getNumOperands(); 567226584Sdim if (NumOp >= 2) { 568226584Sdim for (int i = 0; i < NumOp-1; ++i) { 569226584Sdim const MCOperand &MCOp1 = MI.getOperand(i); 570226584Sdim const MCOperand &MCOp2 = MI.getOperand(i + 1); 571226584Sdim if (MCOp1.isImm() && MCOp2.isReg() && 572226584Sdim (MCOp2.getReg() == 0 || MCOp2.getReg() == ARM::CPSR)) { 573226584Sdim if (ARMCC::CondCodes(MCOp1.getImm()) != ARMCC::AL) 574226584Sdim return true; 575226584Sdim } 576226584Sdim } 577226584Sdim } 578226584Sdim return false; 579226584Sdim} 580226584Sdim 581226584Sdim/// getBranchTargetOpValue - Return encoding info for 24-bit immediate branch 582226584Sdim/// target. 583226584Sdimuint32_t ARMMCCodeEmitter:: 584226584SdimgetBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 585226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 586226584Sdim // FIXME: This really, really shouldn't use TargetMachine. We don't want 587226584Sdim // coupling between MC and TM anywhere we can help it. 588226584Sdim if (isThumb2()) 589226584Sdim return 590226584Sdim ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_condbranch, Fixups); 591226584Sdim return getARMBranchTargetOpValue(MI, OpIdx, Fixups); 592226584Sdim} 593226584Sdim 594226584Sdim/// getBranchTargetOpValue - Return encoding info for 24-bit immediate branch 595226584Sdim/// target. 596226584Sdimuint32_t ARMMCCodeEmitter:: 597226584SdimgetARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 598226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 599226584Sdim const MCOperand MO = MI.getOperand(OpIdx); 600226584Sdim if (MO.isExpr()) { 601226584Sdim if (HasConditionalBranch(MI)) 602226584Sdim return ::getBranchTargetOpValue(MI, OpIdx, 603226584Sdim ARM::fixup_arm_condbranch, Fixups); 604226584Sdim return ::getBranchTargetOpValue(MI, OpIdx, 605226584Sdim ARM::fixup_arm_uncondbranch, Fixups); 606226584Sdim } 607226584Sdim 608226584Sdim return MO.getImm() >> 2; 609226584Sdim} 610226584Sdim 611226584Sdimuint32_t ARMMCCodeEmitter:: 612235633SdimgetARMBLTargetOpValue(const MCInst &MI, unsigned OpIdx, 613226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 614226584Sdim const MCOperand MO = MI.getOperand(OpIdx); 615226584Sdim if (MO.isExpr()) { 616226584Sdim if (HasConditionalBranch(MI)) 617235633Sdim return ::getBranchTargetOpValue(MI, OpIdx, 618235633Sdim ARM::fixup_arm_condbl, Fixups); 619235633Sdim return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_uncondbl, Fixups); 620226584Sdim } 621226584Sdim 622235633Sdim return MO.getImm() >> 2; 623235633Sdim} 624235633Sdim 625235633Sdimuint32_t ARMMCCodeEmitter:: 626235633SdimgetARMBLXTargetOpValue(const MCInst &MI, unsigned OpIdx, 627235633Sdim SmallVectorImpl<MCFixup> &Fixups) const { 628235633Sdim const MCOperand MO = MI.getOperand(OpIdx); 629235633Sdim if (MO.isExpr()) 630235633Sdim return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_blx, Fixups); 631235633Sdim 632226584Sdim return MO.getImm() >> 1; 633226584Sdim} 634226584Sdim 635226584Sdim/// getUnconditionalBranchTargetOpValue - Return encoding info for 24-bit 636226584Sdim/// immediate branch target. 637226584Sdimuint32_t ARMMCCodeEmitter:: 638226584SdimgetUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 639226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 640263509Sdim unsigned Val = 0; 641263509Sdim const MCOperand MO = MI.getOperand(OpIdx); 642263509Sdim 643263509Sdim if(MO.isExpr()) 644263509Sdim return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_uncondbranch, Fixups); 645263509Sdim else 646263509Sdim Val = MO.getImm() >> 1; 647263509Sdim 648226584Sdim bool I = (Val & 0x800000); 649226584Sdim bool J1 = (Val & 0x400000); 650226584Sdim bool J2 = (Val & 0x200000); 651226584Sdim if (I ^ J1) 652226584Sdim Val &= ~0x400000; 653226584Sdim else 654226584Sdim Val |= 0x400000; 655226584Sdim 656226584Sdim if (I ^ J2) 657226584Sdim Val &= ~0x200000; 658226584Sdim else 659226584Sdim Val |= 0x200000; 660226584Sdim 661226584Sdim return Val; 662226584Sdim} 663226584Sdim 664245431Sdim/// getAdrLabelOpValue - Return encoding info for 12-bit shifted-immediate 665245431Sdim/// ADR label target. 666226584Sdimuint32_t ARMMCCodeEmitter:: 667226584SdimgetAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, 668226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 669226584Sdim const MCOperand MO = MI.getOperand(OpIdx); 670226584Sdim if (MO.isExpr()) 671226584Sdim return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_adr_pcrel_12, 672226584Sdim Fixups); 673263509Sdim int64_t offset = MO.getImm(); 674226584Sdim uint32_t Val = 0x2000; 675245431Sdim 676252723Sdim int SoImmVal; 677245431Sdim if (offset == INT32_MIN) { 678226584Sdim Val = 0x1000; 679252723Sdim SoImmVal = 0; 680245431Sdim } else if (offset < 0) { 681245431Sdim Val = 0x1000; 682226584Sdim offset *= -1; 683252723Sdim SoImmVal = ARM_AM::getSOImmVal(offset); 684252723Sdim if(SoImmVal == -1) { 685252723Sdim Val = 0x2000; 686252723Sdim offset *= -1; 687252723Sdim SoImmVal = ARM_AM::getSOImmVal(offset); 688252723Sdim } 689252723Sdim } else { 690252723Sdim SoImmVal = ARM_AM::getSOImmVal(offset); 691252723Sdim if(SoImmVal == -1) { 692252723Sdim Val = 0x1000; 693252723Sdim offset *= -1; 694252723Sdim SoImmVal = ARM_AM::getSOImmVal(offset); 695252723Sdim } 696226584Sdim } 697245431Sdim 698245431Sdim assert(SoImmVal != -1 && "Not a valid so_imm value!"); 699245431Sdim 700245431Sdim Val |= SoImmVal; 701226584Sdim return Val; 702226584Sdim} 703226584Sdim 704245431Sdim/// getT2AdrLabelOpValue - Return encoding info for 12-bit immediate ADR label 705226584Sdim/// target. 706226584Sdimuint32_t ARMMCCodeEmitter:: 707226584SdimgetT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx, 708226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 709226584Sdim const MCOperand MO = MI.getOperand(OpIdx); 710226584Sdim if (MO.isExpr()) 711226584Sdim return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_adr_pcrel_12, 712226584Sdim Fixups); 713226584Sdim int32_t Val = MO.getImm(); 714245431Sdim if (Val == INT32_MIN) 715245431Sdim Val = 0x1000; 716245431Sdim else if (Val < 0) { 717226584Sdim Val *= -1; 718226584Sdim Val |= 0x1000; 719226584Sdim } 720226584Sdim return Val; 721226584Sdim} 722226584Sdim 723245431Sdim/// getThumbAdrLabelOpValue - Return encoding info for 8-bit immediate ADR label 724226584Sdim/// target. 725226584Sdimuint32_t ARMMCCodeEmitter:: 726226584SdimgetThumbAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, 727226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 728226584Sdim const MCOperand MO = MI.getOperand(OpIdx); 729226584Sdim if (MO.isExpr()) 730226584Sdim return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_thumb_adr_pcrel_10, 731226584Sdim Fixups); 732226584Sdim return MO.getImm(); 733226584Sdim} 734226584Sdim 735226584Sdim/// getThumbAddrModeRegRegOpValue - Return encoding info for 'reg + reg' 736226584Sdim/// operand. 737226584Sdimuint32_t ARMMCCodeEmitter:: 738226584SdimgetThumbAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx, 739226584Sdim SmallVectorImpl<MCFixup> &) const { 740226584Sdim // [Rn, Rm] 741226584Sdim // {5-3} = Rm 742226584Sdim // {2-0} = Rn 743226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx); 744226584Sdim const MCOperand &MO2 = MI.getOperand(OpIdx + 1); 745263509Sdim unsigned Rn = CTX.getRegisterInfo()->getEncodingValue(MO1.getReg()); 746263509Sdim unsigned Rm = CTX.getRegisterInfo()->getEncodingValue(MO2.getReg()); 747226584Sdim return (Rm << 3) | Rn; 748226584Sdim} 749226584Sdim 750226584Sdim/// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12' operand. 751226584Sdimuint32_t ARMMCCodeEmitter:: 752226584SdimgetAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx, 753226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 754226584Sdim // {17-13} = reg 755226584Sdim // {12} = (U)nsigned (add == '1', sub == '0') 756226584Sdim // {11-0} = imm12 757226584Sdim unsigned Reg, Imm12; 758226584Sdim bool isAdd = true; 759226584Sdim // If The first operand isn't a register, we have a label reference. 760226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 761226584Sdim if (!MO.isReg()) { 762263509Sdim Reg = CTX.getRegisterInfo()->getEncodingValue(ARM::PC); // Rn is PC. 763226584Sdim Imm12 = 0; 764226584Sdim 765226584Sdim if (MO.isExpr()) { 766226584Sdim const MCExpr *Expr = MO.getExpr(); 767263509Sdim isAdd = false ; // 'U' bit is set as part of the fixup. 768226584Sdim 769226584Sdim MCFixupKind Kind; 770226584Sdim if (isThumb2()) 771226584Sdim Kind = MCFixupKind(ARM::fixup_t2_ldst_pcrel_12); 772226584Sdim else 773226584Sdim Kind = MCFixupKind(ARM::fixup_arm_ldst_pcrel_12); 774235633Sdim Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); 775226584Sdim 776226584Sdim ++MCNumCPRelocations; 777226584Sdim } else { 778226584Sdim Reg = ARM::PC; 779226584Sdim int32_t Offset = MO.getImm(); 780263509Sdim if (Offset == INT32_MIN) { 781263509Sdim Offset = 0; 782263509Sdim isAdd = false; 783263509Sdim } else if (Offset < 0) { 784226584Sdim Offset *= -1; 785226584Sdim isAdd = false; 786226584Sdim } 787226584Sdim Imm12 = Offset; 788226584Sdim } 789226584Sdim } else 790226584Sdim isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm12, Fixups); 791226584Sdim 792226584Sdim uint32_t Binary = Imm12 & 0xfff; 793226584Sdim // Immediate is always encoded as positive. The 'U' bit controls add vs sub. 794226584Sdim if (isAdd) 795226584Sdim Binary |= (1 << 12); 796226584Sdim Binary |= (Reg << 13); 797226584Sdim return Binary; 798226584Sdim} 799226584Sdim 800226584Sdim/// getT2Imm8s4OpValue - Return encoding info for 801226584Sdim/// '+/- imm8<<2' operand. 802226584Sdimuint32_t ARMMCCodeEmitter:: 803226584SdimgetT2Imm8s4OpValue(const MCInst &MI, unsigned OpIdx, 804226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 805226584Sdim // FIXME: The immediate operand should have already been encoded like this 806226584Sdim // before ever getting here. The encoder method should just need to combine 807226584Sdim // the MI operands for the register and the offset into a single 808226584Sdim // representation for the complex operand in the .td file. This isn't just 809226584Sdim // style, unfortunately. As-is, we can't represent the distinct encoding 810226584Sdim // for #-0. 811226584Sdim 812226584Sdim // {8} = (U)nsigned (add == '1', sub == '0') 813226584Sdim // {7-0} = imm8 814226584Sdim int32_t Imm8 = MI.getOperand(OpIdx).getImm(); 815226584Sdim bool isAdd = Imm8 >= 0; 816226584Sdim 817226584Sdim // Immediate is always encoded as positive. The 'U' bit controls add vs sub. 818226584Sdim if (Imm8 < 0) 819245431Sdim Imm8 = -(uint32_t)Imm8; 820226584Sdim 821226584Sdim // Scaled by 4. 822226584Sdim Imm8 /= 4; 823226584Sdim 824226584Sdim uint32_t Binary = Imm8 & 0xff; 825226584Sdim // Immediate is always encoded as positive. The 'U' bit controls add vs sub. 826226584Sdim if (isAdd) 827226584Sdim Binary |= (1 << 8); 828226584Sdim return Binary; 829226584Sdim} 830226584Sdim 831226584Sdim/// getT2AddrModeImm8s4OpValue - Return encoding info for 832226584Sdim/// 'reg +/- imm8<<2' operand. 833226584Sdimuint32_t ARMMCCodeEmitter:: 834226584SdimgetT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx, 835226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 836226584Sdim // {12-9} = reg 837226584Sdim // {8} = (U)nsigned (add == '1', sub == '0') 838226584Sdim // {7-0} = imm8 839226584Sdim unsigned Reg, Imm8; 840226584Sdim bool isAdd = true; 841226584Sdim // If The first operand isn't a register, we have a label reference. 842226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 843226584Sdim if (!MO.isReg()) { 844263509Sdim Reg = CTX.getRegisterInfo()->getEncodingValue(ARM::PC); // Rn is PC. 845226584Sdim Imm8 = 0; 846226584Sdim isAdd = false ; // 'U' bit is set as part of the fixup. 847226584Sdim 848226584Sdim assert(MO.isExpr() && "Unexpected machine operand type!"); 849226584Sdim const MCExpr *Expr = MO.getExpr(); 850235633Sdim MCFixupKind Kind = MCFixupKind(ARM::fixup_t2_pcrel_10); 851235633Sdim Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); 852226584Sdim 853226584Sdim ++MCNumCPRelocations; 854226584Sdim } else 855226584Sdim isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups); 856226584Sdim 857226584Sdim // FIXME: The immediate operand should have already been encoded like this 858226584Sdim // before ever getting here. The encoder method should just need to combine 859226584Sdim // the MI operands for the register and the offset into a single 860226584Sdim // representation for the complex operand in the .td file. This isn't just 861226584Sdim // style, unfortunately. As-is, we can't represent the distinct encoding 862226584Sdim // for #-0. 863226584Sdim uint32_t Binary = (Imm8 >> 2) & 0xff; 864226584Sdim // Immediate is always encoded as positive. The 'U' bit controls add vs sub. 865226584Sdim if (isAdd) 866226584Sdim Binary |= (1 << 8); 867226584Sdim Binary |= (Reg << 9); 868226584Sdim return Binary; 869226584Sdim} 870226584Sdim 871226584Sdim/// getT2AddrModeImm0_1020s4OpValue - Return encoding info for 872226584Sdim/// 'reg + imm8<<2' operand. 873226584Sdimuint32_t ARMMCCodeEmitter:: 874226584SdimgetT2AddrModeImm0_1020s4OpValue(const MCInst &MI, unsigned OpIdx, 875226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 876226584Sdim // {11-8} = reg 877226584Sdim // {7-0} = imm8 878226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 879226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 880263509Sdim unsigned Reg = CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 881226584Sdim unsigned Imm8 = MO1.getImm(); 882226584Sdim return (Reg << 8) | Imm8; 883226584Sdim} 884226584Sdim 885226584Sdim// FIXME: This routine assumes that a binary 886226584Sdim// expression will always result in a PCRel expression 887226584Sdim// In reality, its only true if one or more subexpressions 888226584Sdim// is itself a PCRel (i.e. "." in asm or some other pcrel construct) 889226584Sdim// but this is good enough for now. 890226584Sdimstatic bool EvaluateAsPCRel(const MCExpr *Expr) { 891226584Sdim switch (Expr->getKind()) { 892235633Sdim default: llvm_unreachable("Unexpected expression type"); 893226584Sdim case MCExpr::SymbolRef: return false; 894226584Sdim case MCExpr::Binary: return true; 895226584Sdim } 896226584Sdim} 897226584Sdim 898226584Sdimuint32_t 899226584SdimARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx, 900226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 901226584Sdim // {20-16} = imm{15-12} 902226584Sdim // {11-0} = imm{11-0} 903226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 904226584Sdim if (MO.isImm()) 905226584Sdim // Hi / lo 16 bits already extracted during earlier passes. 906226584Sdim return static_cast<unsigned>(MO.getImm()); 907226584Sdim 908226584Sdim // Handle :upper16: and :lower16: assembly prefixes. 909226584Sdim const MCExpr *E = MO.getExpr(); 910245431Sdim MCFixupKind Kind; 911226584Sdim if (E->getKind() == MCExpr::Target) { 912226584Sdim const ARMMCExpr *ARM16Expr = cast<ARMMCExpr>(E); 913226584Sdim E = ARM16Expr->getSubExpr(); 914226584Sdim 915226584Sdim switch (ARM16Expr->getKind()) { 916235633Sdim default: llvm_unreachable("Unsupported ARMFixup"); 917226584Sdim case ARMMCExpr::VK_ARM_HI16: 918226584Sdim if (!isTargetDarwin() && EvaluateAsPCRel(E)) 919226584Sdim Kind = MCFixupKind(isThumb2() 920226584Sdim ? ARM::fixup_t2_movt_hi16_pcrel 921226584Sdim : ARM::fixup_arm_movt_hi16_pcrel); 922226584Sdim else 923226584Sdim Kind = MCFixupKind(isThumb2() 924226584Sdim ? ARM::fixup_t2_movt_hi16 925226584Sdim : ARM::fixup_arm_movt_hi16); 926226584Sdim break; 927226584Sdim case ARMMCExpr::VK_ARM_LO16: 928226584Sdim if (!isTargetDarwin() && EvaluateAsPCRel(E)) 929226584Sdim Kind = MCFixupKind(isThumb2() 930226584Sdim ? ARM::fixup_t2_movw_lo16_pcrel 931226584Sdim : ARM::fixup_arm_movw_lo16_pcrel); 932226584Sdim else 933226584Sdim Kind = MCFixupKind(isThumb2() 934226584Sdim ? ARM::fixup_t2_movw_lo16 935226584Sdim : ARM::fixup_arm_movw_lo16); 936226584Sdim break; 937226584Sdim } 938235633Sdim Fixups.push_back(MCFixup::Create(0, E, Kind, MI.getLoc())); 939226584Sdim return 0; 940245431Sdim } 941245431Sdim // If the expression doesn't have :upper16: or :lower16: on it, 942245431Sdim // it's just a plain immediate expression, and those evaluate to 943245431Sdim // the lower 16 bits of the expression regardless of whether 944245431Sdim // we have a movt or a movw. 945245431Sdim if (!isTargetDarwin() && EvaluateAsPCRel(E)) 946245431Sdim Kind = MCFixupKind(isThumb2() 947245431Sdim ? ARM::fixup_t2_movw_lo16_pcrel 948245431Sdim : ARM::fixup_arm_movw_lo16_pcrel); 949245431Sdim else 950245431Sdim Kind = MCFixupKind(isThumb2() 951245431Sdim ? ARM::fixup_t2_movw_lo16 952245431Sdim : ARM::fixup_arm_movw_lo16); 953245431Sdim Fixups.push_back(MCFixup::Create(0, E, Kind, MI.getLoc())); 954245431Sdim return 0; 955226584Sdim} 956226584Sdim 957226584Sdimuint32_t ARMMCCodeEmitter:: 958226584SdimgetLdStSORegOpValue(const MCInst &MI, unsigned OpIdx, 959226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 960226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 961226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx+1); 962226584Sdim const MCOperand &MO2 = MI.getOperand(OpIdx+2); 963263509Sdim unsigned Rn = CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 964263509Sdim unsigned Rm = CTX.getRegisterInfo()->getEncodingValue(MO1.getReg()); 965226584Sdim unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()); 966226584Sdim bool isAdd = ARM_AM::getAM2Op(MO2.getImm()) == ARM_AM::add; 967226584Sdim ARM_AM::ShiftOpc ShOp = ARM_AM::getAM2ShiftOpc(MO2.getImm()); 968226584Sdim unsigned SBits = getShiftOp(ShOp); 969226584Sdim 970245431Sdim // While "lsr #32" and "asr #32" exist, they are encoded with a 0 in the shift 971245431Sdim // amount. However, it would be an easy mistake to make so check here. 972245431Sdim assert((ShImm & ~0x1f) == 0 && "Out of range shift amount"); 973245431Sdim 974226584Sdim // {16-13} = Rn 975226584Sdim // {12} = isAdd 976226584Sdim // {11-0} = shifter 977226584Sdim // {3-0} = Rm 978226584Sdim // {4} = 0 979226584Sdim // {6-5} = type 980226584Sdim // {11-7} = imm 981226584Sdim uint32_t Binary = Rm; 982226584Sdim Binary |= Rn << 13; 983226584Sdim Binary |= SBits << 5; 984226584Sdim Binary |= ShImm << 7; 985226584Sdim if (isAdd) 986226584Sdim Binary |= 1 << 12; 987226584Sdim return Binary; 988226584Sdim} 989226584Sdim 990226584Sdimuint32_t ARMMCCodeEmitter:: 991226584SdimgetAddrMode2OpValue(const MCInst &MI, unsigned OpIdx, 992226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 993226584Sdim // {17-14} Rn 994226584Sdim // {13} 1 == imm12, 0 == Rm 995226584Sdim // {12} isAdd 996226584Sdim // {11-0} imm12/Rm 997226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 998263509Sdim unsigned Rn = CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 999226584Sdim uint32_t Binary = getAddrMode2OffsetOpValue(MI, OpIdx + 1, Fixups); 1000226584Sdim Binary |= Rn << 14; 1001226584Sdim return Binary; 1002226584Sdim} 1003226584Sdim 1004226584Sdimuint32_t ARMMCCodeEmitter:: 1005226584SdimgetAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx, 1006226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1007226584Sdim // {13} 1 == imm12, 0 == Rm 1008226584Sdim // {12} isAdd 1009226584Sdim // {11-0} imm12/Rm 1010226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 1011226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx+1); 1012226584Sdim unsigned Imm = MO1.getImm(); 1013226584Sdim bool isAdd = ARM_AM::getAM2Op(Imm) == ARM_AM::add; 1014226584Sdim bool isReg = MO.getReg() != 0; 1015226584Sdim uint32_t Binary = ARM_AM::getAM2Offset(Imm); 1016226584Sdim // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm12 1017226584Sdim if (isReg) { 1018226584Sdim ARM_AM::ShiftOpc ShOp = ARM_AM::getAM2ShiftOpc(Imm); 1019226584Sdim Binary <<= 7; // Shift amount is bits [11:7] 1020226584Sdim Binary |= getShiftOp(ShOp) << 5; // Shift type is bits [6:5] 1021263509Sdim Binary |= CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); // Rm is bits [3:0] 1022226584Sdim } 1023226584Sdim return Binary | (isAdd << 12) | (isReg << 13); 1024226584Sdim} 1025226584Sdim 1026226584Sdimuint32_t ARMMCCodeEmitter:: 1027226584SdimgetPostIdxRegOpValue(const MCInst &MI, unsigned OpIdx, 1028226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1029226584Sdim // {4} isAdd 1030226584Sdim // {3-0} Rm 1031226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 1032226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx+1); 1033226584Sdim bool isAdd = MO1.getImm() != 0; 1034263509Sdim return CTX.getRegisterInfo()->getEncodingValue(MO.getReg()) | (isAdd << 4); 1035226584Sdim} 1036226584Sdim 1037226584Sdimuint32_t ARMMCCodeEmitter:: 1038226584SdimgetAddrMode3OffsetOpValue(const MCInst &MI, unsigned OpIdx, 1039226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1040226584Sdim // {9} 1 == imm8, 0 == Rm 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 unsigned Imm = MO1.getImm(); 1047226584Sdim bool isAdd = ARM_AM::getAM3Op(Imm) == ARM_AM::add; 1048226584Sdim bool isImm = MO.getReg() == 0; 1049226584Sdim uint32_t Imm8 = ARM_AM::getAM3Offset(Imm); 1050226584Sdim // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm8 1051226584Sdim if (!isImm) 1052263509Sdim Imm8 = CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 1053226584Sdim return Imm8 | (isAdd << 8) | (isImm << 9); 1054226584Sdim} 1055226584Sdim 1056226584Sdimuint32_t ARMMCCodeEmitter:: 1057226584SdimgetAddrMode3OpValue(const MCInst &MI, unsigned OpIdx, 1058226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1059226584Sdim // {13} 1 == imm8, 0 == Rm 1060226584Sdim // {12-9} Rn 1061226584Sdim // {8} isAdd 1062226584Sdim // {7-4} imm7_4/zero 1063226584Sdim // {3-0} imm3_0/Rm 1064226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 1065226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx+1); 1066226584Sdim const MCOperand &MO2 = MI.getOperand(OpIdx+2); 1067235633Sdim 1068235633Sdim // If The first operand isn't a register, we have a label reference. 1069235633Sdim if (!MO.isReg()) { 1070263509Sdim unsigned Rn = CTX.getRegisterInfo()->getEncodingValue(ARM::PC); // Rn is PC. 1071235633Sdim 1072235633Sdim assert(MO.isExpr() && "Unexpected machine operand type!"); 1073235633Sdim const MCExpr *Expr = MO.getExpr(); 1074235633Sdim MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_pcrel_10_unscaled); 1075235633Sdim Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); 1076235633Sdim 1077235633Sdim ++MCNumCPRelocations; 1078235633Sdim return (Rn << 9) | (1 << 13); 1079235633Sdim } 1080263509Sdim unsigned Rn = CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 1081226584Sdim unsigned Imm = MO2.getImm(); 1082226584Sdim bool isAdd = ARM_AM::getAM3Op(Imm) == ARM_AM::add; 1083226584Sdim bool isImm = MO1.getReg() == 0; 1084226584Sdim uint32_t Imm8 = ARM_AM::getAM3Offset(Imm); 1085226584Sdim // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm8 1086226584Sdim if (!isImm) 1087263509Sdim Imm8 = CTX.getRegisterInfo()->getEncodingValue(MO1.getReg()); 1088226584Sdim return (Rn << 9) | Imm8 | (isAdd << 8) | (isImm << 13); 1089226584Sdim} 1090226584Sdim 1091226584Sdim/// getAddrModeThumbSPOpValue - Encode the t_addrmode_sp operands. 1092226584Sdimuint32_t ARMMCCodeEmitter:: 1093226584SdimgetAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx, 1094226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1095226584Sdim // [SP, #imm] 1096226584Sdim // {7-0} = imm8 1097226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 1098226584Sdim assert(MI.getOperand(OpIdx).getReg() == ARM::SP && 1099226584Sdim "Unexpected base register!"); 1100226584Sdim 1101226584Sdim // The immediate is already shifted for the implicit zeroes, so no change 1102226584Sdim // here. 1103226584Sdim return MO1.getImm() & 0xff; 1104226584Sdim} 1105226584Sdim 1106226584Sdim/// getAddrModeISOpValue - Encode the t_addrmode_is# operands. 1107226584Sdimuint32_t ARMMCCodeEmitter:: 1108226584SdimgetAddrModeISOpValue(const MCInst &MI, unsigned OpIdx, 1109226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1110226584Sdim // [Rn, #imm] 1111226584Sdim // {7-3} = imm5 1112226584Sdim // {2-0} = Rn 1113226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 1114226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 1115263509Sdim unsigned Rn = CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 1116226584Sdim unsigned Imm5 = MO1.getImm(); 1117226584Sdim return ((Imm5 & 0x1f) << 3) | Rn; 1118226584Sdim} 1119226584Sdim 1120226584Sdim/// getAddrModePCOpValue - Return encoding for t_addrmode_pc operands. 1121226584Sdimuint32_t ARMMCCodeEmitter:: 1122226584SdimgetAddrModePCOpValue(const MCInst &MI, unsigned OpIdx, 1123226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1124226584Sdim const MCOperand MO = MI.getOperand(OpIdx); 1125226584Sdim if (MO.isExpr()) 1126226584Sdim return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_cp, Fixups); 1127226584Sdim return (MO.getImm() >> 2); 1128226584Sdim} 1129226584Sdim 1130226584Sdim/// getAddrMode5OpValue - Return encoding info for 'reg +/- imm10' operand. 1131226584Sdimuint32_t ARMMCCodeEmitter:: 1132226584SdimgetAddrMode5OpValue(const MCInst &MI, unsigned OpIdx, 1133226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1134226584Sdim // {12-9} = reg 1135226584Sdim // {8} = (U)nsigned (add == '1', sub == '0') 1136226584Sdim // {7-0} = imm8 1137226584Sdim unsigned Reg, Imm8; 1138226584Sdim bool isAdd; 1139226584Sdim // If The first operand isn't a register, we have a label reference. 1140226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 1141226584Sdim if (!MO.isReg()) { 1142263509Sdim Reg = CTX.getRegisterInfo()->getEncodingValue(ARM::PC); // Rn is PC. 1143226584Sdim Imm8 = 0; 1144226584Sdim isAdd = false; // 'U' bit is handled as part of the fixup. 1145226584Sdim 1146226584Sdim assert(MO.isExpr() && "Unexpected machine operand type!"); 1147226584Sdim const MCExpr *Expr = MO.getExpr(); 1148226584Sdim MCFixupKind Kind; 1149226584Sdim if (isThumb2()) 1150226584Sdim Kind = MCFixupKind(ARM::fixup_t2_pcrel_10); 1151226584Sdim else 1152226584Sdim Kind = MCFixupKind(ARM::fixup_arm_pcrel_10); 1153235633Sdim Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); 1154226584Sdim 1155226584Sdim ++MCNumCPRelocations; 1156226584Sdim } else { 1157226584Sdim EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups); 1158226584Sdim isAdd = ARM_AM::getAM5Op(Imm8) == ARM_AM::add; 1159226584Sdim } 1160226584Sdim 1161226584Sdim uint32_t Binary = ARM_AM::getAM5Offset(Imm8); 1162226584Sdim // Immediate is always encoded as positive. The 'U' bit controls add vs sub. 1163226584Sdim if (isAdd) 1164226584Sdim Binary |= (1 << 8); 1165226584Sdim Binary |= (Reg << 9); 1166226584Sdim return Binary; 1167226584Sdim} 1168226584Sdim 1169226584Sdimunsigned ARMMCCodeEmitter:: 1170226584SdimgetSORegRegOpValue(const MCInst &MI, unsigned OpIdx, 1171226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1172226584Sdim // Sub-operands are [reg, reg, imm]. The first register is Rm, the reg to be 1173226584Sdim // shifted. The second is Rs, the amount to shift by, and the third specifies 1174226584Sdim // the type of the shift. 1175226584Sdim // 1176226584Sdim // {3-0} = Rm. 1177226584Sdim // {4} = 1 1178226584Sdim // {6-5} = type 1179226584Sdim // {11-8} = Rs 1180226584Sdim // {7} = 0 1181226584Sdim 1182226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 1183226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 1184226584Sdim const MCOperand &MO2 = MI.getOperand(OpIdx + 2); 1185226584Sdim ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO2.getImm()); 1186226584Sdim 1187226584Sdim // Encode Rm. 1188263509Sdim unsigned Binary = CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 1189226584Sdim 1190226584Sdim // Encode the shift opcode. 1191226584Sdim unsigned SBits = 0; 1192226584Sdim unsigned Rs = MO1.getReg(); 1193226584Sdim if (Rs) { 1194226584Sdim // Set shift operand (bit[7:4]). 1195226584Sdim // LSL - 0001 1196226584Sdim // LSR - 0011 1197226584Sdim // ASR - 0101 1198226584Sdim // ROR - 0111 1199226584Sdim switch (SOpc) { 1200226584Sdim default: llvm_unreachable("Unknown shift opc!"); 1201226584Sdim case ARM_AM::lsl: SBits = 0x1; break; 1202226584Sdim case ARM_AM::lsr: SBits = 0x3; break; 1203226584Sdim case ARM_AM::asr: SBits = 0x5; break; 1204226584Sdim case ARM_AM::ror: SBits = 0x7; break; 1205226584Sdim } 1206226584Sdim } 1207226584Sdim 1208226584Sdim Binary |= SBits << 4; 1209226584Sdim 1210226584Sdim // Encode the shift operation Rs. 1211226584Sdim // Encode Rs bit[11:8]. 1212226584Sdim assert(ARM_AM::getSORegOffset(MO2.getImm()) == 0); 1213263509Sdim return Binary | (CTX.getRegisterInfo()->getEncodingValue(Rs) << ARMII::RegRsShift); 1214226584Sdim} 1215226584Sdim 1216226584Sdimunsigned ARMMCCodeEmitter:: 1217226584SdimgetSORegImmOpValue(const MCInst &MI, unsigned OpIdx, 1218226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1219226584Sdim // Sub-operands are [reg, imm]. The first register is Rm, the reg to be 1220226584Sdim // shifted. The second is the amount to shift by. 1221226584Sdim // 1222226584Sdim // {3-0} = Rm. 1223226584Sdim // {4} = 0 1224226584Sdim // {6-5} = type 1225226584Sdim // {11-7} = imm 1226226584Sdim 1227226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 1228226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 1229226584Sdim ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO1.getImm()); 1230226584Sdim 1231226584Sdim // Encode Rm. 1232263509Sdim unsigned Binary = CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 1233226584Sdim 1234226584Sdim // Encode the shift opcode. 1235226584Sdim unsigned SBits = 0; 1236226584Sdim 1237226584Sdim // Set shift operand (bit[6:4]). 1238226584Sdim // LSL - 000 1239226584Sdim // LSR - 010 1240226584Sdim // ASR - 100 1241226584Sdim // ROR - 110 1242226584Sdim // RRX - 110 and bit[11:8] clear. 1243226584Sdim switch (SOpc) { 1244226584Sdim default: llvm_unreachable("Unknown shift opc!"); 1245226584Sdim case ARM_AM::lsl: SBits = 0x0; break; 1246226584Sdim case ARM_AM::lsr: SBits = 0x2; break; 1247226584Sdim case ARM_AM::asr: SBits = 0x4; break; 1248226584Sdim case ARM_AM::ror: SBits = 0x6; break; 1249226584Sdim case ARM_AM::rrx: 1250226584Sdim Binary |= 0x60; 1251226584Sdim return Binary; 1252226584Sdim } 1253226584Sdim 1254226584Sdim // Encode shift_imm bit[11:7]. 1255226584Sdim Binary |= SBits << 4; 1256226584Sdim unsigned Offset = ARM_AM::getSORegOffset(MO1.getImm()); 1257245431Sdim assert(Offset < 32 && "Offset must be in range 0-31!"); 1258226584Sdim return Binary | (Offset << 7); 1259226584Sdim} 1260226584Sdim 1261226584Sdim 1262226584Sdimunsigned ARMMCCodeEmitter:: 1263226584SdimgetT2AddrModeSORegOpValue(const MCInst &MI, unsigned OpNum, 1264226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1265226584Sdim const MCOperand &MO1 = MI.getOperand(OpNum); 1266226584Sdim const MCOperand &MO2 = MI.getOperand(OpNum+1); 1267226584Sdim const MCOperand &MO3 = MI.getOperand(OpNum+2); 1268226584Sdim 1269226584Sdim // Encoded as [Rn, Rm, imm]. 1270226584Sdim // FIXME: Needs fixup support. 1271263509Sdim unsigned Value = CTX.getRegisterInfo()->getEncodingValue(MO1.getReg()); 1272226584Sdim Value <<= 4; 1273263509Sdim Value |= CTX.getRegisterInfo()->getEncodingValue(MO2.getReg()); 1274226584Sdim Value <<= 2; 1275226584Sdim Value |= MO3.getImm(); 1276226584Sdim 1277226584Sdim return Value; 1278226584Sdim} 1279226584Sdim 1280226584Sdimunsigned ARMMCCodeEmitter:: 1281226584SdimgetT2AddrModeImm8OpValue(const MCInst &MI, unsigned OpNum, 1282226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1283226584Sdim const MCOperand &MO1 = MI.getOperand(OpNum); 1284226584Sdim const MCOperand &MO2 = MI.getOperand(OpNum+1); 1285226584Sdim 1286226584Sdim // FIXME: Needs fixup support. 1287263509Sdim unsigned Value = CTX.getRegisterInfo()->getEncodingValue(MO1.getReg()); 1288226584Sdim 1289226584Sdim // Even though the immediate is 8 bits long, we need 9 bits in order 1290226584Sdim // to represent the (inverse of the) sign bit. 1291226584Sdim Value <<= 9; 1292226584Sdim int32_t tmp = (int32_t)MO2.getImm(); 1293226584Sdim if (tmp < 0) 1294226584Sdim tmp = abs(tmp); 1295226584Sdim else 1296226584Sdim Value |= 256; // Set the ADD bit 1297226584Sdim Value |= tmp & 255; 1298226584Sdim return Value; 1299226584Sdim} 1300226584Sdim 1301226584Sdimunsigned ARMMCCodeEmitter:: 1302226584SdimgetT2AddrModeImm8OffsetOpValue(const MCInst &MI, unsigned OpNum, 1303226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1304226584Sdim const MCOperand &MO1 = MI.getOperand(OpNum); 1305226584Sdim 1306226584Sdim // FIXME: Needs fixup support. 1307226584Sdim unsigned Value = 0; 1308226584Sdim int32_t tmp = (int32_t)MO1.getImm(); 1309226584Sdim if (tmp < 0) 1310226584Sdim tmp = abs(tmp); 1311226584Sdim else 1312226584Sdim Value |= 256; // Set the ADD bit 1313226584Sdim Value |= tmp & 255; 1314226584Sdim return Value; 1315226584Sdim} 1316226584Sdim 1317226584Sdimunsigned ARMMCCodeEmitter:: 1318226584SdimgetT2AddrModeImm12OffsetOpValue(const MCInst &MI, unsigned OpNum, 1319226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1320226584Sdim const MCOperand &MO1 = MI.getOperand(OpNum); 1321226584Sdim 1322226584Sdim // FIXME: Needs fixup support. 1323226584Sdim unsigned Value = 0; 1324226584Sdim int32_t tmp = (int32_t)MO1.getImm(); 1325226584Sdim if (tmp < 0) 1326226584Sdim tmp = abs(tmp); 1327226584Sdim else 1328226584Sdim Value |= 4096; // Set the ADD bit 1329226584Sdim Value |= tmp & 4095; 1330226584Sdim return Value; 1331226584Sdim} 1332226584Sdim 1333226584Sdimunsigned ARMMCCodeEmitter:: 1334226584SdimgetT2SORegOpValue(const MCInst &MI, unsigned OpIdx, 1335226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1336226584Sdim // Sub-operands are [reg, imm]. The first register is Rm, the reg to be 1337226584Sdim // shifted. The second is the amount to shift by. 1338226584Sdim // 1339226584Sdim // {3-0} = Rm. 1340226584Sdim // {4} = 0 1341226584Sdim // {6-5} = type 1342226584Sdim // {11-7} = imm 1343226584Sdim 1344226584Sdim const MCOperand &MO = MI.getOperand(OpIdx); 1345226584Sdim const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 1346226584Sdim ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO1.getImm()); 1347226584Sdim 1348226584Sdim // Encode Rm. 1349263509Sdim unsigned Binary = CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 1350226584Sdim 1351226584Sdim // Encode the shift opcode. 1352226584Sdim unsigned SBits = 0; 1353226584Sdim // Set shift operand (bit[6:4]). 1354226584Sdim // LSL - 000 1355226584Sdim // LSR - 010 1356226584Sdim // ASR - 100 1357226584Sdim // ROR - 110 1358226584Sdim switch (SOpc) { 1359226584Sdim default: llvm_unreachable("Unknown shift opc!"); 1360226584Sdim case ARM_AM::lsl: SBits = 0x0; break; 1361226584Sdim case ARM_AM::lsr: SBits = 0x2; break; 1362226584Sdim case ARM_AM::asr: SBits = 0x4; break; 1363226584Sdim case ARM_AM::rrx: // FALLTHROUGH 1364226584Sdim case ARM_AM::ror: SBits = 0x6; break; 1365226584Sdim } 1366226584Sdim 1367226584Sdim Binary |= SBits << 4; 1368226584Sdim if (SOpc == ARM_AM::rrx) 1369226584Sdim return Binary; 1370226584Sdim 1371226584Sdim // Encode shift_imm bit[11:7]. 1372226584Sdim return Binary | ARM_AM::getSORegOffset(MO1.getImm()) << 7; 1373226584Sdim} 1374226584Sdim 1375226584Sdimunsigned ARMMCCodeEmitter:: 1376226584SdimgetBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op, 1377226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1378226584Sdim // 10 bits. lower 5 bits are are the lsb of the mask, high five bits are the 1379226584Sdim // msb of the mask. 1380226584Sdim const MCOperand &MO = MI.getOperand(Op); 1381226584Sdim uint32_t v = ~MO.getImm(); 1382263509Sdim uint32_t lsb = countTrailingZeros(v); 1383263509Sdim uint32_t msb = (32 - countLeadingZeros (v)) - 1; 1384226584Sdim assert (v != 0 && lsb < 32 && msb < 32 && "Illegal bitfield mask!"); 1385226584Sdim return lsb | (msb << 5); 1386226584Sdim} 1387226584Sdim 1388226584Sdimunsigned ARMMCCodeEmitter:: 1389226584SdimgetRegisterListOpValue(const MCInst &MI, unsigned Op, 1390226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1391226584Sdim // VLDM/VSTM: 1392226584Sdim // {12-8} = Vd 1393226584Sdim // {7-0} = Number of registers 1394226584Sdim // 1395226584Sdim // LDM/STM: 1396226584Sdim // {15-0} = Bitfield of GPRs. 1397226584Sdim unsigned Reg = MI.getOperand(Op).getReg(); 1398235633Sdim bool SPRRegs = ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg); 1399235633Sdim bool DPRRegs = ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg); 1400226584Sdim 1401226584Sdim unsigned Binary = 0; 1402226584Sdim 1403226584Sdim if (SPRRegs || DPRRegs) { 1404226584Sdim // VLDM/VSTM 1405263509Sdim unsigned RegNo = CTX.getRegisterInfo()->getEncodingValue(Reg); 1406226584Sdim unsigned NumRegs = (MI.getNumOperands() - Op) & 0xff; 1407226584Sdim Binary |= (RegNo & 0x1f) << 8; 1408226584Sdim if (SPRRegs) 1409226584Sdim Binary |= NumRegs; 1410226584Sdim else 1411226584Sdim Binary |= NumRegs * 2; 1412226584Sdim } else { 1413226584Sdim for (unsigned I = Op, E = MI.getNumOperands(); I < E; ++I) { 1414263509Sdim unsigned RegNo = CTX.getRegisterInfo()->getEncodingValue(MI.getOperand(I).getReg()); 1415226584Sdim Binary |= 1 << RegNo; 1416226584Sdim } 1417226584Sdim } 1418226584Sdim 1419226584Sdim return Binary; 1420226584Sdim} 1421226584Sdim 1422226584Sdim/// getAddrMode6AddressOpValue - Encode an addrmode6 register number along 1423226584Sdim/// with the alignment operand. 1424226584Sdimunsigned ARMMCCodeEmitter:: 1425226584SdimgetAddrMode6AddressOpValue(const MCInst &MI, unsigned Op, 1426226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1427226584Sdim const MCOperand &Reg = MI.getOperand(Op); 1428226584Sdim const MCOperand &Imm = MI.getOperand(Op + 1); 1429226584Sdim 1430263509Sdim unsigned RegNo = CTX.getRegisterInfo()->getEncodingValue(Reg.getReg()); 1431226584Sdim unsigned Align = 0; 1432226584Sdim 1433226584Sdim switch (Imm.getImm()) { 1434226584Sdim default: break; 1435226584Sdim case 2: 1436226584Sdim case 4: 1437226584Sdim case 8: Align = 0x01; break; 1438226584Sdim case 16: Align = 0x02; break; 1439226584Sdim case 32: Align = 0x03; break; 1440226584Sdim } 1441226584Sdim 1442226584Sdim return RegNo | (Align << 4); 1443226584Sdim} 1444226584Sdim 1445226584Sdim/// getAddrMode6OneLane32AddressOpValue - Encode an addrmode6 register number 1446226584Sdim/// along with the alignment operand for use in VST1 and VLD1 with size 32. 1447226584Sdimunsigned ARMMCCodeEmitter:: 1448226584SdimgetAddrMode6OneLane32AddressOpValue(const MCInst &MI, unsigned Op, 1449226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1450226584Sdim const MCOperand &Reg = MI.getOperand(Op); 1451226584Sdim const MCOperand &Imm = MI.getOperand(Op + 1); 1452226584Sdim 1453263509Sdim unsigned RegNo = CTX.getRegisterInfo()->getEncodingValue(Reg.getReg()); 1454226584Sdim unsigned Align = 0; 1455226584Sdim 1456226584Sdim switch (Imm.getImm()) { 1457226584Sdim default: break; 1458226584Sdim case 8: 1459235633Sdim case 16: 1460235633Sdim case 32: // Default '0' value for invalid alignments of 8, 16, 32 bytes. 1461235633Sdim case 2: Align = 0x00; break; 1462235633Sdim case 4: Align = 0x03; break; 1463226584Sdim } 1464226584Sdim 1465226584Sdim return RegNo | (Align << 4); 1466226584Sdim} 1467226584Sdim 1468226584Sdim 1469226584Sdim/// getAddrMode6DupAddressOpValue - Encode an addrmode6 register number and 1470226584Sdim/// alignment operand for use in VLD-dup instructions. This is the same as 1471226584Sdim/// getAddrMode6AddressOpValue except for the alignment encoding, which is 1472226584Sdim/// different for VLD4-dup. 1473226584Sdimunsigned ARMMCCodeEmitter:: 1474226584SdimgetAddrMode6DupAddressOpValue(const MCInst &MI, unsigned Op, 1475226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1476226584Sdim const MCOperand &Reg = MI.getOperand(Op); 1477226584Sdim const MCOperand &Imm = MI.getOperand(Op + 1); 1478226584Sdim 1479263509Sdim unsigned RegNo = CTX.getRegisterInfo()->getEncodingValue(Reg.getReg()); 1480226584Sdim unsigned Align = 0; 1481226584Sdim 1482226584Sdim switch (Imm.getImm()) { 1483226584Sdim default: break; 1484226584Sdim case 2: 1485226584Sdim case 4: 1486226584Sdim case 8: Align = 0x01; break; 1487226584Sdim case 16: Align = 0x03; break; 1488226584Sdim } 1489226584Sdim 1490226584Sdim return RegNo | (Align << 4); 1491226584Sdim} 1492226584Sdim 1493226584Sdimunsigned ARMMCCodeEmitter:: 1494226584SdimgetAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op, 1495226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1496226584Sdim const MCOperand &MO = MI.getOperand(Op); 1497226584Sdim if (MO.getReg() == 0) return 0x0D; 1498263509Sdim return CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 1499226584Sdim} 1500226584Sdim 1501226584Sdimunsigned ARMMCCodeEmitter:: 1502226584SdimgetShiftRight8Imm(const MCInst &MI, unsigned Op, 1503226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1504226584Sdim return 8 - MI.getOperand(Op).getImm(); 1505226584Sdim} 1506226584Sdim 1507226584Sdimunsigned ARMMCCodeEmitter:: 1508226584SdimgetShiftRight16Imm(const MCInst &MI, unsigned Op, 1509226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1510226584Sdim return 16 - MI.getOperand(Op).getImm(); 1511226584Sdim} 1512226584Sdim 1513226584Sdimunsigned ARMMCCodeEmitter:: 1514226584SdimgetShiftRight32Imm(const MCInst &MI, unsigned Op, 1515226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1516226584Sdim return 32 - MI.getOperand(Op).getImm(); 1517226584Sdim} 1518226584Sdim 1519226584Sdimunsigned ARMMCCodeEmitter:: 1520226584SdimgetShiftRight64Imm(const MCInst &MI, unsigned Op, 1521226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1522226584Sdim return 64 - MI.getOperand(Op).getImm(); 1523226584Sdim} 1524226584Sdim 1525226584Sdimvoid ARMMCCodeEmitter:: 1526226584SdimEncodeInstruction(const MCInst &MI, raw_ostream &OS, 1527226584Sdim SmallVectorImpl<MCFixup> &Fixups) const { 1528226584Sdim // Pseudo instructions don't get encoded. 1529226584Sdim const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); 1530226584Sdim uint64_t TSFlags = Desc.TSFlags; 1531226584Sdim if ((TSFlags & ARMII::FormMask) == ARMII::Pseudo) 1532226584Sdim return; 1533226584Sdim 1534226584Sdim int Size; 1535226584Sdim if (Desc.getSize() == 2 || Desc.getSize() == 4) 1536226584Sdim Size = Desc.getSize(); 1537226584Sdim else 1538226584Sdim llvm_unreachable("Unexpected instruction size!"); 1539226584Sdim 1540226584Sdim uint32_t Binary = getBinaryCodeForInstr(MI, Fixups); 1541226584Sdim // Thumb 32-bit wide instructions need to emit the high order halfword 1542226584Sdim // first. 1543226584Sdim if (isThumb() && Size == 4) { 1544226584Sdim EmitConstant(Binary >> 16, 2, OS); 1545226584Sdim EmitConstant(Binary & 0xffff, 2, OS); 1546226584Sdim } else 1547226584Sdim EmitConstant(Binary, Size, OS); 1548226584Sdim ++MCNumEmitted; // Keep track of the # of mi's emitted. 1549226584Sdim} 1550226584Sdim 1551226584Sdim#include "ARMGenMCCodeEmitter.inc" 1552