1198090Srdivacky//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===// 2198090Srdivacky// 3198090Srdivacky// The LLVM Compiler Infrastructure 4198090Srdivacky// 5198090Srdivacky// This file is distributed under the University of Illinois Open Source 6198090Srdivacky// License. See LICENSE.TXT for details. 7198090Srdivacky// 8198090Srdivacky//===----------------------------------------------------------------------===// 9198090Srdivacky 10263508Sdim#include "ARMBuildAttrs.h" 11263508Sdim#include "ARMFPUName.h" 12263508Sdim#include "ARMFeatures.h" 13249423Sdim#include "llvm/MC/MCTargetAsmParser.h" 14249423Sdim#include "MCTargetDesc/ARMAddressingModes.h" 15226633Sdim#include "MCTargetDesc/ARMBaseInfo.h" 16226633Sdim#include "MCTargetDesc/ARMMCExpr.h" 17249423Sdim#include "llvm/ADT/BitVector.h" 18249423Sdim#include "llvm/ADT/OwningPtr.h" 19249423Sdim#include "llvm/ADT/STLExtras.h" 20249423Sdim#include "llvm/ADT/SmallVector.h" 21249423Sdim#include "llvm/ADT/StringSwitch.h" 22249423Sdim#include "llvm/ADT/Twine.h" 23223017Sdim#include "llvm/MC/MCAsmInfo.h" 24249423Sdim#include "llvm/MC/MCAssembler.h" 25218893Sdim#include "llvm/MC/MCContext.h" 26249423Sdim#include "llvm/MC/MCELFStreamer.h" 27198090Srdivacky#include "llvm/MC/MCExpr.h" 28198090Srdivacky#include "llvm/MC/MCInst.h" 29226633Sdim#include "llvm/MC/MCInstrDesc.h" 30263508Sdim#include "llvm/MC/MCInstrInfo.h" 31249423Sdim#include "llvm/MC/MCParser/MCAsmLexer.h" 32249423Sdim#include "llvm/MC/MCParser/MCAsmParser.h" 33249423Sdim#include "llvm/MC/MCParser/MCParsedAsmOperand.h" 34226633Sdim#include "llvm/MC/MCRegisterInfo.h" 35249423Sdim#include "llvm/MC/MCStreamer.h" 36224145Sdim#include "llvm/MC/MCSubtargetInfo.h" 37249423Sdim#include "llvm/Support/ELF.h" 38226633Sdim#include "llvm/Support/MathExtras.h" 39198090Srdivacky#include "llvm/Support/SourceMgr.h" 40226633Sdim#include "llvm/Support/TargetRegistry.h" 41212904Sdim#include "llvm/Support/raw_ostream.h" 42224145Sdim 43198090Srdivackyusing namespace llvm; 44198090Srdivacky 45218893Sdimnamespace { 46218893Sdim 47218893Sdimclass ARMOperand; 48218893Sdim 49234353Sdimenum VectorLaneTy { NoLanes, AllLanes, IndexedLane }; 50234353Sdim 51226633Sdimclass ARMAsmParser : public MCTargetAsmParser { 52224145Sdim MCSubtargetInfo &STI; 53198090Srdivacky MCAsmParser &Parser; 54263508Sdim const MCInstrInfo &MII; 55234353Sdim const MCRegisterInfo *MRI; 56198090Srdivacky 57263508Sdim ARMTargetStreamer &getTargetStreamer() { 58263508Sdim MCTargetStreamer &TS = getParser().getStreamer().getTargetStreamer(); 59263508Sdim return static_cast<ARMTargetStreamer &>(TS); 60263508Sdim } 61263508Sdim 62263508Sdim // Unwind directives state 63263508Sdim SMLoc FnStartLoc; 64263508Sdim SMLoc CantUnwindLoc; 65263508Sdim SMLoc PersonalityLoc; 66263508Sdim SMLoc HandlerDataLoc; 67263508Sdim int FPReg; 68263508Sdim void resetUnwindDirectiveParserState() { 69263508Sdim FnStartLoc = SMLoc(); 70263508Sdim CantUnwindLoc = SMLoc(); 71263508Sdim PersonalityLoc = SMLoc(); 72263508Sdim HandlerDataLoc = SMLoc(); 73263508Sdim FPReg = -1; 74263508Sdim } 75263508Sdim 76234353Sdim // Map of register aliases registers via the .req directive. 77234353Sdim StringMap<unsigned> RegisterReqs; 78234353Sdim 79263508Sdim bool NextSymbolIsThumb; 80263508Sdim 81226633Sdim struct { 82226633Sdim ARMCC::CondCodes Cond; // Condition for IT block. 83226633Sdim unsigned Mask:4; // Condition mask for instructions. 84226633Sdim // Starting at first 1 (from lsb). 85226633Sdim // '1' condition as indicated in IT. 86226633Sdim // '0' inverse of condition (else). 87226633Sdim // Count of instructions in IT block is 88226633Sdim // 4 - trailingzeroes(mask) 89226633Sdim 90226633Sdim bool FirstCond; // Explicit flag for when we're parsing the 91226633Sdim // First instruction in the IT block. It's 92226633Sdim // implied in the mask, so needs special 93226633Sdim // handling. 94226633Sdim 95226633Sdim unsigned CurPosition; // Current position in parsing of IT 96226633Sdim // block. In range [0,3]. Initialized 97226633Sdim // according to count of instructions in block. 98226633Sdim // ~0U if no active IT block. 99226633Sdim } ITState; 100226633Sdim bool inITBlock() { return ITState.CurPosition != ~0U;} 101226633Sdim void forwardITPosition() { 102226633Sdim if (!inITBlock()) return; 103226633Sdim // Move to the next instruction in the IT block, if there is one. If not, 104226633Sdim // mark the block as done. 105263508Sdim unsigned TZ = countTrailingZeros(ITState.Mask); 106226633Sdim if (++ITState.CurPosition == 5 - TZ) 107226633Sdim ITState.CurPosition = ~0U; // Done with the IT block after this. 108226633Sdim } 109226633Sdim 110226633Sdim 111198090Srdivacky MCAsmParser &getParser() const { return Parser; } 112198090Srdivacky MCAsmLexer &getLexer() const { return Parser.getLexer(); } 113198090Srdivacky 114234982Sdim bool Warning(SMLoc L, const Twine &Msg, 115251662Sdim ArrayRef<SMRange> Ranges = None) { 116234982Sdim return Parser.Warning(L, Msg, Ranges); 117234982Sdim } 118234982Sdim bool Error(SMLoc L, const Twine &Msg, 119251662Sdim ArrayRef<SMRange> Ranges = None) { 120234982Sdim return Parser.Error(L, Msg, Ranges); 121234982Sdim } 122198090Srdivacky 123226633Sdim int tryParseRegister(); 124226633Sdim bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &); 125226633Sdim int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &); 126226633Sdim bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &); 127226633Sdim bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &); 128226633Sdim bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic); 129226633Sdim bool parsePrefix(ARMMCExpr::VariantKind &RefKind); 130226633Sdim bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType, 131226633Sdim unsigned &ShiftAmount); 132226633Sdim bool parseDirectiveWord(unsigned Size, SMLoc L); 133226633Sdim bool parseDirectiveThumb(SMLoc L); 134234353Sdim bool parseDirectiveARM(SMLoc L); 135226633Sdim bool parseDirectiveThumbFunc(SMLoc L); 136226633Sdim bool parseDirectiveCode(SMLoc L); 137226633Sdim bool parseDirectiveSyntax(SMLoc L); 138234353Sdim bool parseDirectiveReq(StringRef Name, SMLoc L); 139234353Sdim bool parseDirectiveUnreq(SMLoc L); 140234353Sdim bool parseDirectiveArch(SMLoc L); 141234353Sdim bool parseDirectiveEabiAttr(SMLoc L); 142263508Sdim bool parseDirectiveCPU(SMLoc L); 143263508Sdim bool parseDirectiveFPU(SMLoc L); 144263508Sdim bool parseDirectiveFnStart(SMLoc L); 145263508Sdim bool parseDirectiveFnEnd(SMLoc L); 146263508Sdim bool parseDirectiveCantUnwind(SMLoc L); 147263508Sdim bool parseDirectivePersonality(SMLoc L); 148263508Sdim bool parseDirectiveHandlerData(SMLoc L); 149263508Sdim bool parseDirectiveSetFP(SMLoc L); 150263508Sdim bool parseDirectivePad(SMLoc L); 151263508Sdim bool parseDirectiveRegSave(SMLoc L, bool IsVector); 152198090Srdivacky 153226633Sdim StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode, 154226633Sdim bool &CarrySetting, unsigned &ProcessorIMod, 155226633Sdim StringRef &ITMask); 156263508Sdim void getMnemonicAcceptInfo(StringRef Mnemonic, StringRef FullInst, 157263508Sdim bool &CanAcceptCarrySet, 158218893Sdim bool &CanAcceptPredicationCode); 159198090Srdivacky 160224145Sdim bool isThumb() const { 161224145Sdim // FIXME: Can tablegen auto-generate this? 162224145Sdim return (STI.getFeatureBits() & ARM::ModeThumb) != 0; 163224145Sdim } 164224145Sdim bool isThumbOne() const { 165224145Sdim return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0; 166224145Sdim } 167226633Sdim bool isThumbTwo() const { 168226633Sdim return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2); 169226633Sdim } 170263508Sdim bool hasThumb() const { 171263508Sdim return STI.getFeatureBits() & ARM::HasV4TOps; 172263508Sdim } 173226633Sdim bool hasV6Ops() const { 174226633Sdim return STI.getFeatureBits() & ARM::HasV6Ops; 175226633Sdim } 176263508Sdim bool hasV6MOps() const { 177263508Sdim return STI.getFeatureBits() & ARM::HasV6MOps; 178263508Sdim } 179226633Sdim bool hasV7Ops() const { 180226633Sdim return STI.getFeatureBits() & ARM::HasV7Ops; 181226633Sdim } 182263508Sdim bool hasV8Ops() const { 183263508Sdim return STI.getFeatureBits() & ARM::HasV8Ops; 184263508Sdim } 185263508Sdim bool hasARM() const { 186263508Sdim return !(STI.getFeatureBits() & ARM::FeatureNoARM); 187263508Sdim } 188263508Sdim 189224145Sdim void SwitchMode() { 190224145Sdim unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb)); 191224145Sdim setAvailableFeatures(FB); 192224145Sdim } 193226633Sdim bool isMClass() const { 194226633Sdim return STI.getFeatureBits() & ARM::FeatureMClass; 195226633Sdim } 196224145Sdim 197198090Srdivacky /// @name Auto-generated Match Functions 198198090Srdivacky /// { 199198090Srdivacky 200218893Sdim#define GET_ASSEMBLER_HEADER 201218893Sdim#include "ARMGenAsmMatcher.inc" 202198090Srdivacky 203198090Srdivacky /// } 204198090Srdivacky 205226633Sdim OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&); 206226633Sdim OperandMatchResultTy parseCoprocNumOperand( 207218893Sdim SmallVectorImpl<MCParsedAsmOperand*>&); 208226633Sdim OperandMatchResultTy parseCoprocRegOperand( 209218893Sdim SmallVectorImpl<MCParsedAsmOperand*>&); 210226633Sdim OperandMatchResultTy parseCoprocOptionOperand( 211218893Sdim SmallVectorImpl<MCParsedAsmOperand*>&); 212226633Sdim OperandMatchResultTy parseMemBarrierOptOperand( 213218893Sdim SmallVectorImpl<MCParsedAsmOperand*>&); 214263508Sdim OperandMatchResultTy parseInstSyncBarrierOptOperand( 215263508Sdim SmallVectorImpl<MCParsedAsmOperand*>&); 216226633Sdim OperandMatchResultTy parseProcIFlagsOperand( 217218893Sdim SmallVectorImpl<MCParsedAsmOperand*>&); 218226633Sdim OperandMatchResultTy parseMSRMaskOperand( 219221345Sdim SmallVectorImpl<MCParsedAsmOperand*>&); 220226633Sdim OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O, 221226633Sdim StringRef Op, int Low, int High); 222226633Sdim OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) { 223226633Sdim return parsePKHImm(O, "lsl", 0, 31); 224226633Sdim } 225226633Sdim OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) { 226226633Sdim return parsePKHImm(O, "asr", 1, 32); 227226633Sdim } 228226633Sdim OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&); 229226633Sdim OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&); 230226633Sdim OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&); 231226633Sdim OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&); 232226633Sdim OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&); 233226633Sdim OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&); 234226633Sdim OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&); 235234353Sdim OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&); 236249423Sdim OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index, 237249423Sdim SMLoc &EndLoc); 238198090Srdivacky 239221345Sdim // Asm Match Converter Methods 240243830Sdim void cvtThumbMultiply(MCInst &Inst, 241226633Sdim const SmallVectorImpl<MCParsedAsmOperand*> &); 242263508Sdim void cvtThumbBranches(MCInst &Inst, 243234353Sdim const SmallVectorImpl<MCParsedAsmOperand*> &); 244263508Sdim 245226633Sdim bool validateInstruction(MCInst &Inst, 246226633Sdim const SmallVectorImpl<MCParsedAsmOperand*> &Ops); 247234353Sdim bool processInstruction(MCInst &Inst, 248226633Sdim const SmallVectorImpl<MCParsedAsmOperand*> &Ops); 249226633Sdim bool shouldOmitCCOutOperand(StringRef Mnemonic, 250226633Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands); 251263508Sdim bool shouldOmitPredicateOperand(StringRef Mnemonic, 252263508Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands); 253198090Srdivackypublic: 254226633Sdim enum ARMMatchResultTy { 255226633Sdim Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY, 256226633Sdim Match_RequiresNotITBlock, 257226633Sdim Match_RequiresV6, 258239462Sdim Match_RequiresThumb2, 259239462Sdim#define GET_OPERAND_DIAGNOSTIC_TYPES 260239462Sdim#include "ARMGenAsmMatcher.inc" 261239462Sdim 262226633Sdim }; 263226633Sdim 264263508Sdim ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser, 265263508Sdim const MCInstrInfo &MII) 266263508Sdim : MCTargetAsmParser(), STI(_STI), Parser(_Parser), MII(MII), FPReg(-1) { 267224145Sdim MCAsmParserExtension::Initialize(_Parser); 268198090Srdivacky 269234353Sdim // Cache the MCRegisterInfo. 270263508Sdim MRI = getContext().getRegisterInfo(); 271234353Sdim 272224145Sdim // Initialize the set of available features. 273224145Sdim setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); 274226633Sdim 275226633Sdim // Not in an ITBlock to start with. 276226633Sdim ITState.CurPosition = ~0U; 277249423Sdim 278263508Sdim NextSymbolIsThumb = false; 279224145Sdim } 280224145Sdim 281226633Sdim // Implementation of the MCTargetAsmParser interface: 282226633Sdim bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); 283243830Sdim bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 284243830Sdim SMLoc NameLoc, 285226633Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands); 286226633Sdim bool ParseDirective(AsmToken DirectiveID); 287226633Sdim 288249423Sdim unsigned validateTargetOperandClass(MCParsedAsmOperand *Op, unsigned Kind); 289226633Sdim unsigned checkTargetMatchPredicate(MCInst &Inst); 290226633Sdim 291243830Sdim bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 292226633Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands, 293243830Sdim MCStreamer &Out, unsigned &ErrorInfo, 294243830Sdim bool MatchingInlineAsm); 295263508Sdim void onLabelParsed(MCSymbol *Symbol); 296263508Sdim 297198090Srdivacky}; 298218893Sdim} // end anonymous namespace 299218893Sdim 300218893Sdimnamespace { 301218893Sdim 302198090Srdivacky/// ARMOperand - Instances of this class represent a parsed ARM machine 303249423Sdim/// operand. 304218893Sdimclass ARMOperand : public MCParsedAsmOperand { 305206124Srdivacky enum KindTy { 306226633Sdim k_CondCode, 307226633Sdim k_CCOut, 308226633Sdim k_ITCondMask, 309226633Sdim k_CoprocNum, 310226633Sdim k_CoprocReg, 311226633Sdim k_CoprocOption, 312226633Sdim k_Immediate, 313226633Sdim k_MemBarrierOpt, 314263508Sdim k_InstSyncBarrierOpt, 315226633Sdim k_Memory, 316226633Sdim k_PostIndexRegister, 317226633Sdim k_MSRMask, 318226633Sdim k_ProcIFlags, 319226633Sdim k_VectorIndex, 320226633Sdim k_Register, 321226633Sdim k_RegisterList, 322226633Sdim k_DPRRegisterList, 323226633Sdim k_SPRRegisterList, 324234353Sdim k_VectorList, 325234353Sdim k_VectorListAllLanes, 326234353Sdim k_VectorListIndexed, 327226633Sdim k_ShiftedRegister, 328226633Sdim k_ShiftedImmediate, 329226633Sdim k_ShifterImmediate, 330226633Sdim k_RotateImmediate, 331226633Sdim k_BitfieldDescriptor, 332226633Sdim k_Token 333198090Srdivacky } Kind; 334198090Srdivacky 335206124Srdivacky SMLoc StartLoc, EndLoc; 336218893Sdim SmallVector<unsigned, 8> Registers; 337198090Srdivacky 338249423Sdim struct CCOp { 339249423Sdim ARMCC::CondCodes Val; 340249423Sdim }; 341212904Sdim 342249423Sdim struct CopOp { 343249423Sdim unsigned Val; 344249423Sdim }; 345218893Sdim 346249423Sdim struct CoprocOptionOp { 347249423Sdim unsigned Val; 348249423Sdim }; 349218893Sdim 350249423Sdim struct ITMaskOp { 351249423Sdim unsigned Mask:4; 352249423Sdim }; 353226633Sdim 354249423Sdim struct MBOptOp { 355249423Sdim ARM_MB::MemBOpt Val; 356249423Sdim }; 357226633Sdim 358263508Sdim struct ISBOptOp { 359263508Sdim ARM_ISB::InstSyncBOpt Val; 360263508Sdim }; 361263508Sdim 362249423Sdim struct IFlagsOp { 363249423Sdim ARM_PROC::IFlags Val; 364249423Sdim }; 365218893Sdim 366249423Sdim struct MMaskOp { 367249423Sdim unsigned Val; 368249423Sdim }; 369218893Sdim 370249423Sdim struct TokOp { 371249423Sdim const char *Data; 372249423Sdim unsigned Length; 373249423Sdim }; 374198090Srdivacky 375249423Sdim struct RegOp { 376249423Sdim unsigned RegNum; 377249423Sdim }; 378198090Srdivacky 379249423Sdim // A vector register list is a sequential list of 1 to 4 registers. 380249423Sdim struct VectorListOp { 381249423Sdim unsigned RegNum; 382249423Sdim unsigned Count; 383249423Sdim unsigned LaneIndex; 384249423Sdim bool isDoubleSpaced; 385249423Sdim }; 386234353Sdim 387249423Sdim struct VectorIndexOp { 388249423Sdim unsigned Val; 389249423Sdim }; 390226633Sdim 391249423Sdim struct ImmOp { 392249423Sdim const MCExpr *Val; 393249423Sdim }; 394218893Sdim 395249423Sdim /// Combined record for all forms of ARM address expressions. 396249423Sdim struct MemoryOp { 397249423Sdim unsigned BaseRegNum; 398249423Sdim // Offset is in OffsetReg or OffsetImm. If both are zero, no offset 399249423Sdim // was specified. 400249423Sdim const MCConstantExpr *OffsetImm; // Offset immediate value 401249423Sdim unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL 402249423Sdim ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg 403249423Sdim unsigned ShiftImm; // shift for OffsetReg. 404249423Sdim unsigned Alignment; // 0 = no alignment specified 405249423Sdim // n = alignment in bytes (2, 4, 8, 16, or 32) 406249423Sdim unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit) 407249423Sdim }; 408221345Sdim 409249423Sdim struct PostIdxRegOp { 410249423Sdim unsigned RegNum; 411249423Sdim bool isAdd; 412249423Sdim ARM_AM::ShiftOpc ShiftTy; 413249423Sdim unsigned ShiftImm; 414249423Sdim }; 415226633Sdim 416249423Sdim struct ShifterImmOp { 417249423Sdim bool isASR; 418249423Sdim unsigned Imm; 419218893Sdim }; 420198090Srdivacky 421249423Sdim struct RegShiftedRegOp { 422249423Sdim ARM_AM::ShiftOpc ShiftTy; 423249423Sdim unsigned SrcReg; 424249423Sdim unsigned ShiftReg; 425249423Sdim unsigned ShiftImm; 426249423Sdim }; 427249423Sdim 428249423Sdim struct RegShiftedImmOp { 429249423Sdim ARM_AM::ShiftOpc ShiftTy; 430249423Sdim unsigned SrcReg; 431249423Sdim unsigned ShiftImm; 432249423Sdim }; 433249423Sdim 434249423Sdim struct RotImmOp { 435249423Sdim unsigned Imm; 436249423Sdim }; 437249423Sdim 438249423Sdim struct BitfieldOp { 439249423Sdim unsigned LSB; 440249423Sdim unsigned Width; 441249423Sdim }; 442249423Sdim 443249423Sdim union { 444249423Sdim struct CCOp CC; 445249423Sdim struct CopOp Cop; 446249423Sdim struct CoprocOptionOp CoprocOption; 447249423Sdim struct MBOptOp MBOpt; 448263508Sdim struct ISBOptOp ISBOpt; 449249423Sdim struct ITMaskOp ITMask; 450249423Sdim struct IFlagsOp IFlags; 451249423Sdim struct MMaskOp MMask; 452249423Sdim struct TokOp Tok; 453249423Sdim struct RegOp Reg; 454249423Sdim struct VectorListOp VectorList; 455249423Sdim struct VectorIndexOp VectorIndex; 456249423Sdim struct ImmOp Imm; 457249423Sdim struct MemoryOp Memory; 458249423Sdim struct PostIdxRegOp PostIdxReg; 459249423Sdim struct ShifterImmOp ShifterImm; 460249423Sdim struct RegShiftedRegOp RegShiftedReg; 461249423Sdim struct RegShiftedImmOp RegShiftedImm; 462249423Sdim struct RotImmOp RotImm; 463249423Sdim struct BitfieldOp Bitfield; 464249423Sdim }; 465249423Sdim 466218893Sdim ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} 467218893Sdimpublic: 468206124Srdivacky ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() { 469206124Srdivacky Kind = o.Kind; 470206124Srdivacky StartLoc = o.StartLoc; 471206124Srdivacky EndLoc = o.EndLoc; 472206124Srdivacky switch (Kind) { 473226633Sdim case k_CondCode: 474212904Sdim CC = o.CC; 475212904Sdim break; 476226633Sdim case k_ITCondMask: 477226633Sdim ITMask = o.ITMask; 478226633Sdim break; 479226633Sdim case k_Token: 480212904Sdim Tok = o.Tok; 481206124Srdivacky break; 482226633Sdim case k_CCOut: 483226633Sdim case k_Register: 484206124Srdivacky Reg = o.Reg; 485206124Srdivacky break; 486226633Sdim case k_RegisterList: 487226633Sdim case k_DPRRegisterList: 488226633Sdim case k_SPRRegisterList: 489218893Sdim Registers = o.Registers; 490218893Sdim break; 491234353Sdim case k_VectorList: 492234353Sdim case k_VectorListAllLanes: 493234353Sdim case k_VectorListIndexed: 494234353Sdim VectorList = o.VectorList; 495234353Sdim break; 496226633Sdim case k_CoprocNum: 497226633Sdim case k_CoprocReg: 498218893Sdim Cop = o.Cop; 499218893Sdim break; 500226633Sdim case k_CoprocOption: 501226633Sdim CoprocOption = o.CoprocOption; 502226633Sdim break; 503226633Sdim case k_Immediate: 504206124Srdivacky Imm = o.Imm; 505206124Srdivacky break; 506226633Sdim case k_MemBarrierOpt: 507218893Sdim MBOpt = o.MBOpt; 508218893Sdim break; 509263508Sdim case k_InstSyncBarrierOpt: 510263508Sdim ISBOpt = o.ISBOpt; 511226633Sdim case k_Memory: 512226633Sdim Memory = o.Memory; 513206124Srdivacky break; 514226633Sdim case k_PostIndexRegister: 515226633Sdim PostIdxReg = o.PostIdxReg; 516226633Sdim break; 517226633Sdim case k_MSRMask: 518218893Sdim MMask = o.MMask; 519218893Sdim break; 520226633Sdim case k_ProcIFlags: 521218893Sdim IFlags = o.IFlags; 522221345Sdim break; 523226633Sdim case k_ShifterImmediate: 524226633Sdim ShifterImm = o.ShifterImm; 525221345Sdim break; 526226633Sdim case k_ShiftedRegister: 527226633Sdim RegShiftedReg = o.RegShiftedReg; 528224145Sdim break; 529226633Sdim case k_ShiftedImmediate: 530226633Sdim RegShiftedImm = o.RegShiftedImm; 531226633Sdim break; 532226633Sdim case k_RotateImmediate: 533226633Sdim RotImm = o.RotImm; 534226633Sdim break; 535226633Sdim case k_BitfieldDescriptor: 536226633Sdim Bitfield = o.Bitfield; 537226633Sdim break; 538226633Sdim case k_VectorIndex: 539226633Sdim VectorIndex = o.VectorIndex; 540226633Sdim break; 541206124Srdivacky } 542206124Srdivacky } 543218893Sdim 544206124Srdivacky /// getStartLoc - Get the location of the first token of this operand. 545206124Srdivacky SMLoc getStartLoc() const { return StartLoc; } 546206124Srdivacky /// getEndLoc - Get the location of the last token of this operand. 547206124Srdivacky SMLoc getEndLoc() const { return EndLoc; } 548243830Sdim /// getLocRange - Get the range between the first and last token of this 549243830Sdim /// operand. 550234982Sdim SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); } 551234982Sdim 552212904Sdim ARMCC::CondCodes getCondCode() const { 553226633Sdim assert(Kind == k_CondCode && "Invalid access!"); 554212904Sdim return CC.Val; 555212904Sdim } 556212904Sdim 557218893Sdim unsigned getCoproc() const { 558226633Sdim assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!"); 559218893Sdim return Cop.Val; 560218893Sdim } 561218893Sdim 562198090Srdivacky StringRef getToken() const { 563226633Sdim assert(Kind == k_Token && "Invalid access!"); 564198090Srdivacky return StringRef(Tok.Data, Tok.Length); 565198090Srdivacky } 566198090Srdivacky 567198090Srdivacky unsigned getReg() const { 568226633Sdim assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!"); 569198090Srdivacky return Reg.RegNum; 570198090Srdivacky } 571198090Srdivacky 572218893Sdim const SmallVectorImpl<unsigned> &getRegList() const { 573226633Sdim assert((Kind == k_RegisterList || Kind == k_DPRRegisterList || 574226633Sdim Kind == k_SPRRegisterList) && "Invalid access!"); 575218893Sdim return Registers; 576218893Sdim } 577218893Sdim 578198090Srdivacky const MCExpr *getImm() const { 579234353Sdim assert(isImm() && "Invalid access!"); 580198090Srdivacky return Imm.Val; 581198090Srdivacky } 582198090Srdivacky 583226633Sdim unsigned getVectorIndex() const { 584226633Sdim assert(Kind == k_VectorIndex && "Invalid access!"); 585226633Sdim return VectorIndex.Val; 586226633Sdim } 587226633Sdim 588218893Sdim ARM_MB::MemBOpt getMemBarrierOpt() const { 589226633Sdim assert(Kind == k_MemBarrierOpt && "Invalid access!"); 590218893Sdim return MBOpt.Val; 591218893Sdim } 592218893Sdim 593263508Sdim ARM_ISB::InstSyncBOpt getInstSyncBarrierOpt() const { 594263508Sdim assert(Kind == k_InstSyncBarrierOpt && "Invalid access!"); 595263508Sdim return ISBOpt.Val; 596263508Sdim } 597263508Sdim 598218893Sdim ARM_PROC::IFlags getProcIFlags() const { 599226633Sdim assert(Kind == k_ProcIFlags && "Invalid access!"); 600218893Sdim return IFlags.Val; 601218893Sdim } 602218893Sdim 603218893Sdim unsigned getMSRMask() const { 604226633Sdim assert(Kind == k_MSRMask && "Invalid access!"); 605218893Sdim return MMask.Val; 606218893Sdim } 607218893Sdim 608226633Sdim bool isCoprocNum() const { return Kind == k_CoprocNum; } 609226633Sdim bool isCoprocReg() const { return Kind == k_CoprocReg; } 610226633Sdim bool isCoprocOption() const { return Kind == k_CoprocOption; } 611226633Sdim bool isCondCode() const { return Kind == k_CondCode; } 612226633Sdim bool isCCOut() const { return Kind == k_CCOut; } 613226633Sdim bool isITMask() const { return Kind == k_ITCondMask; } 614226633Sdim bool isITCondCode() const { return Kind == k_CondCode; } 615226633Sdim bool isImm() const { return Kind == k_Immediate; } 616263508Sdim // checks whether this operand is an unsigned offset which fits is a field 617263508Sdim // of specified width and scaled by a specific number of bits 618263508Sdim template<unsigned width, unsigned scale> 619263508Sdim bool isUnsignedOffset() const { 620263508Sdim if (!isImm()) return false; 621263508Sdim if (isa<MCSymbolRefExpr>(Imm.Val)) return true; 622263508Sdim if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) { 623263508Sdim int64_t Val = CE->getValue(); 624263508Sdim int64_t Align = 1LL << scale; 625263508Sdim int64_t Max = Align * ((1LL << width) - 1); 626263508Sdim return ((Val % Align) == 0) && (Val >= 0) && (Val <= Max); 627263508Sdim } 628263508Sdim return false; 629263508Sdim } 630263508Sdim // checks whether this operand is an signed offset which fits is a field 631263508Sdim // of specified width and scaled by a specific number of bits 632263508Sdim template<unsigned width, unsigned scale> 633263508Sdim bool isSignedOffset() const { 634263508Sdim if (!isImm()) return false; 635263508Sdim if (isa<MCSymbolRefExpr>(Imm.Val)) return true; 636263508Sdim if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) { 637263508Sdim int64_t Val = CE->getValue(); 638263508Sdim int64_t Align = 1LL << scale; 639263508Sdim int64_t Max = Align * ((1LL << (width-1)) - 1); 640263508Sdim int64_t Min = -Align * (1LL << (width-1)); 641263508Sdim return ((Val % Align) == 0) && (Val >= Min) && (Val <= Max); 642263508Sdim } 643263508Sdim return false; 644263508Sdim } 645263508Sdim 646263508Sdim // checks whether this operand is a memory operand computed as an offset 647263508Sdim // applied to PC. the offset may have 8 bits of magnitude and is represented 648263508Sdim // with two bits of shift. textually it may be either [pc, #imm], #imm or 649263508Sdim // relocable expression... 650263508Sdim bool isThumbMemPC() const { 651263508Sdim int64_t Val = 0; 652263508Sdim if (isImm()) { 653263508Sdim if (isa<MCSymbolRefExpr>(Imm.Val)) return true; 654263508Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val); 655263508Sdim if (!CE) return false; 656263508Sdim Val = CE->getValue(); 657263508Sdim } 658263508Sdim else if (isMem()) { 659263508Sdim if(!Memory.OffsetImm || Memory.OffsetRegNum) return false; 660263508Sdim if(Memory.BaseRegNum != ARM::PC) return false; 661263508Sdim Val = Memory.OffsetImm->getValue(); 662263508Sdim } 663263508Sdim else return false; 664263508Sdim return ((Val % 4) == 0) && (Val >= 0) && (Val <= 1020); 665263508Sdim } 666234353Sdim bool isFPImm() const { 667234353Sdim if (!isImm()) return false; 668234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 669234353Sdim if (!CE) return false; 670234353Sdim int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue())); 671234353Sdim return Val != -1; 672234353Sdim } 673234353Sdim bool isFBits16() const { 674234353Sdim if (!isImm()) return false; 675234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 676234353Sdim if (!CE) return false; 677234353Sdim int64_t Value = CE->getValue(); 678234353Sdim return Value >= 0 && Value <= 16; 679234353Sdim } 680234353Sdim bool isFBits32() const { 681234353Sdim if (!isImm()) return false; 682234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 683234353Sdim if (!CE) return false; 684234353Sdim int64_t Value = CE->getValue(); 685234353Sdim return Value >= 1 && Value <= 32; 686234353Sdim } 687226633Sdim bool isImm8s4() const { 688234353Sdim if (!isImm()) return false; 689226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 690226633Sdim if (!CE) return false; 691226633Sdim int64_t Value = CE->getValue(); 692226633Sdim return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020; 693221345Sdim } 694226633Sdim bool isImm0_1020s4() const { 695234353Sdim if (!isImm()) return false; 696226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 697226633Sdim if (!CE) return false; 698226633Sdim int64_t Value = CE->getValue(); 699226633Sdim return ((Value & 3) == 0) && Value >= 0 && Value <= 1020; 700218893Sdim } 701226633Sdim bool isImm0_508s4() const { 702234353Sdim if (!isImm()) return false; 703226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 704226633Sdim if (!CE) return false; 705226633Sdim int64_t Value = CE->getValue(); 706226633Sdim return ((Value & 3) == 0) && Value >= 0 && Value <= 508; 707218893Sdim } 708234353Sdim bool isImm0_508s4Neg() const { 709234353Sdim if (!isImm()) return false; 710234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 711234353Sdim if (!CE) return false; 712234353Sdim int64_t Value = -CE->getValue(); 713234353Sdim // explicitly exclude zero. we want that to use the normal 0_508 version. 714234353Sdim return ((Value & 3) == 0) && Value > 0 && Value <= 508; 715234353Sdim } 716263508Sdim bool isImm0_239() const { 717263508Sdim if (!isImm()) return false; 718263508Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 719263508Sdim if (!CE) return false; 720263508Sdim int64_t Value = CE->getValue(); 721263508Sdim return Value >= 0 && Value < 240; 722263508Sdim } 723224145Sdim bool isImm0_255() const { 724234353Sdim if (!isImm()) return false; 725224145Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 726224145Sdim if (!CE) return false; 727224145Sdim int64_t Value = CE->getValue(); 728224145Sdim return Value >= 0 && Value < 256; 729224145Sdim } 730234353Sdim bool isImm0_4095() const { 731234353Sdim if (!isImm()) return false; 732234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 733234353Sdim if (!CE) return false; 734234353Sdim int64_t Value = CE->getValue(); 735234353Sdim return Value >= 0 && Value < 4096; 736234353Sdim } 737234353Sdim bool isImm0_4095Neg() const { 738234353Sdim if (!isImm()) return false; 739234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 740234353Sdim if (!CE) return false; 741234353Sdim int64_t Value = -CE->getValue(); 742234353Sdim return Value > 0 && Value < 4096; 743234353Sdim } 744234353Sdim bool isImm0_1() const { 745234353Sdim if (!isImm()) return false; 746234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 747234353Sdim if (!CE) return false; 748234353Sdim int64_t Value = CE->getValue(); 749234353Sdim return Value >= 0 && Value < 2; 750234353Sdim } 751234353Sdim bool isImm0_3() const { 752234353Sdim if (!isImm()) return false; 753234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 754234353Sdim if (!CE) return false; 755234353Sdim int64_t Value = CE->getValue(); 756234353Sdim return Value >= 0 && Value < 4; 757234353Sdim } 758224145Sdim bool isImm0_7() const { 759234353Sdim if (!isImm()) return false; 760224145Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 761224145Sdim if (!CE) return false; 762224145Sdim int64_t Value = CE->getValue(); 763224145Sdim return Value >= 0 && Value < 8; 764224145Sdim } 765224145Sdim bool isImm0_15() const { 766234353Sdim if (!isImm()) return false; 767224145Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 768224145Sdim if (!CE) return false; 769224145Sdim int64_t Value = CE->getValue(); 770224145Sdim return Value >= 0 && Value < 16; 771224145Sdim } 772226633Sdim bool isImm0_31() const { 773234353Sdim if (!isImm()) return false; 774226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 775226633Sdim if (!CE) return false; 776226633Sdim int64_t Value = CE->getValue(); 777226633Sdim return Value >= 0 && Value < 32; 778226633Sdim } 779234353Sdim bool isImm0_63() const { 780234353Sdim if (!isImm()) return false; 781234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 782234353Sdim if (!CE) return false; 783234353Sdim int64_t Value = CE->getValue(); 784234353Sdim return Value >= 0 && Value < 64; 785234353Sdim } 786234353Sdim bool isImm8() const { 787234353Sdim if (!isImm()) return false; 788234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 789234353Sdim if (!CE) return false; 790234353Sdim int64_t Value = CE->getValue(); 791234353Sdim return Value == 8; 792234353Sdim } 793234353Sdim bool isImm16() const { 794234353Sdim if (!isImm()) return false; 795234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 796234353Sdim if (!CE) return false; 797234353Sdim int64_t Value = CE->getValue(); 798234353Sdim return Value == 16; 799234353Sdim } 800234353Sdim bool isImm32() const { 801234353Sdim if (!isImm()) return false; 802234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 803234353Sdim if (!CE) return false; 804234353Sdim int64_t Value = CE->getValue(); 805234353Sdim return Value == 32; 806234353Sdim } 807234353Sdim bool isShrImm8() const { 808234353Sdim if (!isImm()) return false; 809234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 810234353Sdim if (!CE) return false; 811234353Sdim int64_t Value = CE->getValue(); 812234353Sdim return Value > 0 && Value <= 8; 813234353Sdim } 814234353Sdim bool isShrImm16() const { 815234353Sdim if (!isImm()) return false; 816234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 817234353Sdim if (!CE) return false; 818234353Sdim int64_t Value = CE->getValue(); 819234353Sdim return Value > 0 && Value <= 16; 820234353Sdim } 821234353Sdim bool isShrImm32() const { 822234353Sdim if (!isImm()) return false; 823234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 824234353Sdim if (!CE) return false; 825234353Sdim int64_t Value = CE->getValue(); 826234353Sdim return Value > 0 && Value <= 32; 827234353Sdim } 828234353Sdim bool isShrImm64() const { 829234353Sdim if (!isImm()) return false; 830234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 831234353Sdim if (!CE) return false; 832234353Sdim int64_t Value = CE->getValue(); 833234353Sdim return Value > 0 && Value <= 64; 834234353Sdim } 835234353Sdim bool isImm1_7() const { 836234353Sdim if (!isImm()) return false; 837234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 838234353Sdim if (!CE) return false; 839234353Sdim int64_t Value = CE->getValue(); 840234353Sdim return Value > 0 && Value < 8; 841234353Sdim } 842234353Sdim bool isImm1_15() const { 843234353Sdim if (!isImm()) return false; 844234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 845234353Sdim if (!CE) return false; 846234353Sdim int64_t Value = CE->getValue(); 847234353Sdim return Value > 0 && Value < 16; 848234353Sdim } 849234353Sdim bool isImm1_31() const { 850234353Sdim if (!isImm()) return false; 851234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 852234353Sdim if (!CE) return false; 853234353Sdim int64_t Value = CE->getValue(); 854234353Sdim return Value > 0 && Value < 32; 855234353Sdim } 856226633Sdim bool isImm1_16() const { 857234353Sdim if (!isImm()) return false; 858226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 859226633Sdim if (!CE) return false; 860226633Sdim int64_t Value = CE->getValue(); 861226633Sdim return Value > 0 && Value < 17; 862226633Sdim } 863226633Sdim bool isImm1_32() const { 864234353Sdim if (!isImm()) return false; 865226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 866226633Sdim if (!CE) return false; 867226633Sdim int64_t Value = CE->getValue(); 868226633Sdim return Value > 0 && Value < 33; 869226633Sdim } 870234353Sdim bool isImm0_32() const { 871234353Sdim if (!isImm()) return false; 872234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 873234353Sdim if (!CE) return false; 874234353Sdim int64_t Value = CE->getValue(); 875234353Sdim return Value >= 0 && Value < 33; 876234353Sdim } 877224145Sdim bool isImm0_65535() const { 878234353Sdim if (!isImm()) return false; 879224145Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 880224145Sdim if (!CE) return false; 881224145Sdim int64_t Value = CE->getValue(); 882224145Sdim return Value >= 0 && Value < 65536; 883224145Sdim } 884263508Sdim bool isImm256_65535Expr() const { 885263508Sdim if (!isImm()) return false; 886263508Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 887263508Sdim // If it's not a constant expression, it'll generate a fixup and be 888263508Sdim // handled later. 889263508Sdim if (!CE) return true; 890263508Sdim int64_t Value = CE->getValue(); 891263508Sdim return Value >= 256 && Value < 65536; 892263508Sdim } 893226633Sdim bool isImm0_65535Expr() const { 894234353Sdim if (!isImm()) return false; 895224145Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 896226633Sdim // If it's not a constant expression, it'll generate a fixup and be 897226633Sdim // handled later. 898226633Sdim if (!CE) return true; 899226633Sdim int64_t Value = CE->getValue(); 900226633Sdim return Value >= 0 && Value < 65536; 901226633Sdim } 902226633Sdim bool isImm24bit() const { 903234353Sdim if (!isImm()) return false; 904226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 905224145Sdim if (!CE) return false; 906224145Sdim int64_t Value = CE->getValue(); 907226633Sdim return Value >= 0 && Value <= 0xffffff; 908224145Sdim } 909226633Sdim bool isImmThumbSR() const { 910234353Sdim if (!isImm()) return false; 911226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 912226633Sdim if (!CE) return false; 913226633Sdim int64_t Value = CE->getValue(); 914226633Sdim return Value > 0 && Value < 33; 915226633Sdim } 916226633Sdim bool isPKHLSLImm() const { 917234353Sdim if (!isImm()) return false; 918226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 919221345Sdim if (!CE) return false; 920221345Sdim int64_t Value = CE->getValue(); 921226633Sdim return Value >= 0 && Value < 32; 922226633Sdim } 923226633Sdim bool isPKHASRImm() const { 924234353Sdim if (!isImm()) return false; 925226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 926226633Sdim if (!CE) return false; 927226633Sdim int64_t Value = CE->getValue(); 928226633Sdim return Value > 0 && Value <= 32; 929221345Sdim } 930239462Sdim bool isAdrLabel() const { 931239462Sdim // If we have an immediate that's not a constant, treat it as a label 932239462Sdim // reference needing a fixup. If it is a constant, but it can't fit 933239462Sdim // into shift immediate encoding, we reject it. 934239462Sdim if (isImm() && !isa<MCConstantExpr>(getImm())) return true; 935239462Sdim else return (isARMSOImm() || isARMSOImmNeg()); 936239462Sdim } 937226633Sdim bool isARMSOImm() const { 938234353Sdim if (!isImm()) return false; 939226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 940226633Sdim if (!CE) return false; 941226633Sdim int64_t Value = CE->getValue(); 942226633Sdim return ARM_AM::getSOImmVal(Value) != -1; 943226633Sdim } 944234353Sdim bool isARMSOImmNot() const { 945234353Sdim if (!isImm()) return false; 946234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 947234353Sdim if (!CE) return false; 948234353Sdim int64_t Value = CE->getValue(); 949234353Sdim return ARM_AM::getSOImmVal(~Value) != -1; 950234353Sdim } 951234353Sdim bool isARMSOImmNeg() const { 952234353Sdim if (!isImm()) return false; 953234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 954234353Sdim if (!CE) return false; 955234353Sdim int64_t Value = CE->getValue(); 956234353Sdim // Only use this when not representable as a plain so_imm. 957234353Sdim return ARM_AM::getSOImmVal(Value) == -1 && 958234353Sdim ARM_AM::getSOImmVal(-Value) != -1; 959234353Sdim } 960226633Sdim bool isT2SOImm() const { 961234353Sdim if (!isImm()) return false; 962226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 963221345Sdim if (!CE) return false; 964221345Sdim int64_t Value = CE->getValue(); 965226633Sdim return ARM_AM::getT2SOImmVal(Value) != -1; 966221345Sdim } 967234353Sdim bool isT2SOImmNot() const { 968234353Sdim if (!isImm()) return false; 969234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 970234353Sdim if (!CE) return false; 971234353Sdim int64_t Value = CE->getValue(); 972263508Sdim return ARM_AM::getT2SOImmVal(Value) == -1 && 973263508Sdim ARM_AM::getT2SOImmVal(~Value) != -1; 974234353Sdim } 975234353Sdim bool isT2SOImmNeg() const { 976234353Sdim if (!isImm()) return false; 977234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 978234353Sdim if (!CE) return false; 979234353Sdim int64_t Value = CE->getValue(); 980234353Sdim // Only use this when not representable as a plain so_imm. 981234353Sdim return ARM_AM::getT2SOImmVal(Value) == -1 && 982234353Sdim ARM_AM::getT2SOImmVal(-Value) != -1; 983234353Sdim } 984226633Sdim bool isSetEndImm() const { 985234353Sdim if (!isImm()) return false; 986226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 987218893Sdim if (!CE) return false; 988218893Sdim int64_t Value = CE->getValue(); 989226633Sdim return Value == 1 || Value == 0; 990218893Sdim } 991226633Sdim bool isReg() const { return Kind == k_Register; } 992226633Sdim bool isRegList() const { return Kind == k_RegisterList; } 993226633Sdim bool isDPRRegList() const { return Kind == k_DPRRegisterList; } 994226633Sdim bool isSPRRegList() const { return Kind == k_SPRRegisterList; } 995226633Sdim bool isToken() const { return Kind == k_Token; } 996226633Sdim bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; } 997263508Sdim bool isInstSyncBarrierOpt() const { return Kind == k_InstSyncBarrierOpt; } 998243830Sdim bool isMem() const { return Kind == k_Memory; } 999226633Sdim bool isShifterImm() const { return Kind == k_ShifterImmediate; } 1000226633Sdim bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; } 1001226633Sdim bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; } 1002226633Sdim bool isRotImm() const { return Kind == k_RotateImmediate; } 1003226633Sdim bool isBitfield() const { return Kind == k_BitfieldDescriptor; } 1004226633Sdim bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; } 1005226633Sdim bool isPostIdxReg() const { 1006234353Sdim return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift; 1007226633Sdim } 1008226633Sdim bool isMemNoOffset(bool alignOK = false) const { 1009243830Sdim if (!isMem()) 1010221345Sdim return false; 1011226633Sdim // No offset of any kind. 1012226633Sdim return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 && 1013226633Sdim (alignOK || Memory.Alignment == 0); 1014226633Sdim } 1015234353Sdim bool isMemPCRelImm12() const { 1016243830Sdim if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) 1017234353Sdim return false; 1018234353Sdim // Base register must be PC. 1019234353Sdim if (Memory.BaseRegNum != ARM::PC) 1020234353Sdim return false; 1021234353Sdim // Immediate offset in range [-4095, 4095]. 1022234353Sdim if (!Memory.OffsetImm) return true; 1023234353Sdim int64_t Val = Memory.OffsetImm->getValue(); 1024234353Sdim return (Val > -4096 && Val < 4096) || (Val == INT32_MIN); 1025234353Sdim } 1026226633Sdim bool isAlignedMemory() const { 1027226633Sdim return isMemNoOffset(true); 1028226633Sdim } 1029226633Sdim bool isAddrMode2() const { 1030243830Sdim if (!isMem() || Memory.Alignment != 0) return false; 1031226633Sdim // Check for register offset. 1032226633Sdim if (Memory.OffsetRegNum) return true; 1033226633Sdim // Immediate offset in range [-4095, 4095]. 1034226633Sdim if (!Memory.OffsetImm) return true; 1035226633Sdim int64_t Val = Memory.OffsetImm->getValue(); 1036226633Sdim return Val > -4096 && Val < 4096; 1037226633Sdim } 1038226633Sdim bool isAM2OffsetImm() const { 1039234353Sdim if (!isImm()) return false; 1040226633Sdim // Immediate offset in range [-4095, 4095]. 1041226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1042221345Sdim if (!CE) return false; 1043226633Sdim int64_t Val = CE->getValue(); 1044263508Sdim return (Val == INT32_MIN) || (Val > -4096 && Val < 4096); 1045226633Sdim } 1046226633Sdim bool isAddrMode3() const { 1047234353Sdim // If we have an immediate that's not a constant, treat it as a label 1048234353Sdim // reference needing a fixup. If it is a constant, it's something else 1049234353Sdim // and we reject it. 1050234353Sdim if (isImm() && !isa<MCConstantExpr>(getImm())) 1051234353Sdim return true; 1052243830Sdim if (!isMem() || Memory.Alignment != 0) return false; 1053226633Sdim // No shifts are legal for AM3. 1054226633Sdim if (Memory.ShiftType != ARM_AM::no_shift) return false; 1055226633Sdim // Check for register offset. 1056226633Sdim if (Memory.OffsetRegNum) return true; 1057226633Sdim // Immediate offset in range [-255, 255]. 1058226633Sdim if (!Memory.OffsetImm) return true; 1059226633Sdim int64_t Val = Memory.OffsetImm->getValue(); 1060239462Sdim // The #-0 offset is encoded as INT32_MIN, and we have to check 1061239462Sdim // for this too. 1062239462Sdim return (Val > -256 && Val < 256) || Val == INT32_MIN; 1063226633Sdim } 1064226633Sdim bool isAM3Offset() const { 1065226633Sdim if (Kind != k_Immediate && Kind != k_PostIndexRegister) 1066221345Sdim return false; 1067226633Sdim if (Kind == k_PostIndexRegister) 1068226633Sdim return PostIdxReg.ShiftTy == ARM_AM::no_shift; 1069226633Sdim // Immediate offset in range [-255, 255]. 1070226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1071226633Sdim if (!CE) return false; 1072226633Sdim int64_t Val = CE->getValue(); 1073226633Sdim // Special case, #-0 is INT32_MIN. 1074226633Sdim return (Val > -256 && Val < 256) || Val == INT32_MIN; 1075226633Sdim } 1076226633Sdim bool isAddrMode5() const { 1077234353Sdim // If we have an immediate that's not a constant, treat it as a label 1078234353Sdim // reference needing a fixup. If it is a constant, it's something else 1079234353Sdim // and we reject it. 1080234353Sdim if (isImm() && !isa<MCConstantExpr>(getImm())) 1081234353Sdim return true; 1082243830Sdim if (!isMem() || Memory.Alignment != 0) return false; 1083226633Sdim // Check for register offset. 1084226633Sdim if (Memory.OffsetRegNum) return false; 1085226633Sdim // Immediate offset in range [-1020, 1020] and a multiple of 4. 1086226633Sdim if (!Memory.OffsetImm) return true; 1087226633Sdim int64_t Val = Memory.OffsetImm->getValue(); 1088226633Sdim return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) || 1089234353Sdim Val == INT32_MIN; 1090226633Sdim } 1091226633Sdim bool isMemTBB() const { 1092243830Sdim if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative || 1093226633Sdim Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0) 1094226633Sdim return false; 1095221345Sdim return true; 1096221345Sdim } 1097226633Sdim bool isMemTBH() const { 1098243830Sdim if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative || 1099226633Sdim Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 || 1100226633Sdim Memory.Alignment != 0 ) 1101218893Sdim return false; 1102218893Sdim return true; 1103218893Sdim } 1104226633Sdim bool isMemRegOffset() const { 1105243830Sdim if (!isMem() || !Memory.OffsetRegNum || Memory.Alignment != 0) 1106218893Sdim return false; 1107226633Sdim return true; 1108226633Sdim } 1109226633Sdim bool isT2MemRegOffset() const { 1110243830Sdim if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative || 1111226633Sdim Memory.Alignment != 0) 1112226633Sdim return false; 1113226633Sdim // Only lsl #{0, 1, 2, 3} allowed. 1114226633Sdim if (Memory.ShiftType == ARM_AM::no_shift) 1115226633Sdim return true; 1116226633Sdim if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3) 1117226633Sdim return false; 1118226633Sdim return true; 1119226633Sdim } 1120226633Sdim bool isMemThumbRR() const { 1121226633Sdim // Thumb reg+reg addressing is simple. Just two registers, a base and 1122226633Sdim // an offset. No shifts, negations or any other complicating factors. 1123243830Sdim if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative || 1124226633Sdim Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0) 1125226633Sdim return false; 1126226633Sdim return isARMLowRegister(Memory.BaseRegNum) && 1127226633Sdim (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum)); 1128226633Sdim } 1129226633Sdim bool isMemThumbRIs4() const { 1130243830Sdim if (!isMem() || Memory.OffsetRegNum != 0 || 1131226633Sdim !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0) 1132226633Sdim return false; 1133226633Sdim // Immediate offset, multiple of 4 in range [0, 124]. 1134226633Sdim if (!Memory.OffsetImm) return true; 1135226633Sdim int64_t Val = Memory.OffsetImm->getValue(); 1136226633Sdim return Val >= 0 && Val <= 124 && (Val % 4) == 0; 1137226633Sdim } 1138226633Sdim bool isMemThumbRIs2() const { 1139243830Sdim if (!isMem() || Memory.OffsetRegNum != 0 || 1140226633Sdim !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0) 1141226633Sdim return false; 1142226633Sdim // Immediate offset, multiple of 4 in range [0, 62]. 1143226633Sdim if (!Memory.OffsetImm) return true; 1144226633Sdim int64_t Val = Memory.OffsetImm->getValue(); 1145226633Sdim return Val >= 0 && Val <= 62 && (Val % 2) == 0; 1146226633Sdim } 1147226633Sdim bool isMemThumbRIs1() const { 1148243830Sdim if (!isMem() || Memory.OffsetRegNum != 0 || 1149226633Sdim !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0) 1150226633Sdim return false; 1151226633Sdim // Immediate offset in range [0, 31]. 1152226633Sdim if (!Memory.OffsetImm) return true; 1153226633Sdim int64_t Val = Memory.OffsetImm->getValue(); 1154226633Sdim return Val >= 0 && Val <= 31; 1155226633Sdim } 1156226633Sdim bool isMemThumbSPI() const { 1157243830Sdim if (!isMem() || Memory.OffsetRegNum != 0 || 1158226633Sdim Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0) 1159226633Sdim return false; 1160226633Sdim // Immediate offset, multiple of 4 in range [0, 1020]. 1161226633Sdim if (!Memory.OffsetImm) return true; 1162226633Sdim int64_t Val = Memory.OffsetImm->getValue(); 1163226633Sdim return Val >= 0 && Val <= 1020 && (Val % 4) == 0; 1164226633Sdim } 1165226633Sdim bool isMemImm8s4Offset() const { 1166234353Sdim // If we have an immediate that's not a constant, treat it as a label 1167234353Sdim // reference needing a fixup. If it is a constant, it's something else 1168234353Sdim // and we reject it. 1169234353Sdim if (isImm() && !isa<MCConstantExpr>(getImm())) 1170234353Sdim return true; 1171243830Sdim if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) 1172226633Sdim return false; 1173226633Sdim // Immediate offset a multiple of 4 in range [-1020, 1020]. 1174226633Sdim if (!Memory.OffsetImm) return true; 1175226633Sdim int64_t Val = Memory.OffsetImm->getValue(); 1176239462Sdim // Special case, #-0 is INT32_MIN. 1177239462Sdim return (Val >= -1020 && Val <= 1020 && (Val & 3) == 0) || Val == INT32_MIN; 1178226633Sdim } 1179226633Sdim bool isMemImm0_1020s4Offset() const { 1180243830Sdim if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) 1181226633Sdim return false; 1182226633Sdim // Immediate offset a multiple of 4 in range [0, 1020]. 1183226633Sdim if (!Memory.OffsetImm) return true; 1184226633Sdim int64_t Val = Memory.OffsetImm->getValue(); 1185226633Sdim return Val >= 0 && Val <= 1020 && (Val & 3) == 0; 1186226633Sdim } 1187226633Sdim bool isMemImm8Offset() const { 1188243830Sdim if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) 1189226633Sdim return false; 1190234353Sdim // Base reg of PC isn't allowed for these encodings. 1191234353Sdim if (Memory.BaseRegNum == ARM::PC) return false; 1192226633Sdim // Immediate offset in range [-255, 255]. 1193226633Sdim if (!Memory.OffsetImm) return true; 1194226633Sdim int64_t Val = Memory.OffsetImm->getValue(); 1195226633Sdim return (Val == INT32_MIN) || (Val > -256 && Val < 256); 1196226633Sdim } 1197226633Sdim bool isMemPosImm8Offset() const { 1198243830Sdim if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) 1199226633Sdim return false; 1200226633Sdim // Immediate offset in range [0, 255]. 1201226633Sdim if (!Memory.OffsetImm) return true; 1202226633Sdim int64_t Val = Memory.OffsetImm->getValue(); 1203226633Sdim return Val >= 0 && Val < 256; 1204226633Sdim } 1205226633Sdim bool isMemNegImm8Offset() const { 1206243830Sdim if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) 1207226633Sdim return false; 1208234353Sdim // Base reg of PC isn't allowed for these encodings. 1209234353Sdim if (Memory.BaseRegNum == ARM::PC) return false; 1210226633Sdim // Immediate offset in range [-255, -1]. 1211234353Sdim if (!Memory.OffsetImm) return false; 1212226633Sdim int64_t Val = Memory.OffsetImm->getValue(); 1213234353Sdim return (Val == INT32_MIN) || (Val > -256 && Val < 0); 1214226633Sdim } 1215226633Sdim bool isMemUImm12Offset() const { 1216243830Sdim if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) 1217226633Sdim return false; 1218226633Sdim // Immediate offset in range [0, 4095]. 1219226633Sdim if (!Memory.OffsetImm) return true; 1220226633Sdim int64_t Val = Memory.OffsetImm->getValue(); 1221226633Sdim return (Val >= 0 && Val < 4096); 1222226633Sdim } 1223226633Sdim bool isMemImm12Offset() const { 1224226633Sdim // If we have an immediate that's not a constant, treat it as a label 1225226633Sdim // reference needing a fixup. If it is a constant, it's something else 1226226633Sdim // and we reject it. 1227234353Sdim if (isImm() && !isa<MCConstantExpr>(getImm())) 1228226633Sdim return true; 1229226633Sdim 1230243830Sdim if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) 1231226633Sdim return false; 1232226633Sdim // Immediate offset in range [-4095, 4095]. 1233226633Sdim if (!Memory.OffsetImm) return true; 1234226633Sdim int64_t Val = Memory.OffsetImm->getValue(); 1235226633Sdim return (Val > -4096 && Val < 4096) || (Val == INT32_MIN); 1236226633Sdim } 1237226633Sdim bool isPostIdxImm8() const { 1238234353Sdim if (!isImm()) return false; 1239226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1240218893Sdim if (!CE) return false; 1241226633Sdim int64_t Val = CE->getValue(); 1242226633Sdim return (Val > -256 && Val < 256) || (Val == INT32_MIN); 1243226633Sdim } 1244226633Sdim bool isPostIdxImm8s4() const { 1245234353Sdim if (!isImm()) return false; 1246226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1247226633Sdim if (!CE) return false; 1248226633Sdim int64_t Val = CE->getValue(); 1249226633Sdim return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) || 1250226633Sdim (Val == INT32_MIN); 1251226633Sdim } 1252218893Sdim 1253226633Sdim bool isMSRMask() const { return Kind == k_MSRMask; } 1254226633Sdim bool isProcIFlags() const { return Kind == k_ProcIFlags; } 1255226633Sdim 1256234353Sdim // NEON operands. 1257234353Sdim bool isSingleSpacedVectorList() const { 1258234353Sdim return Kind == k_VectorList && !VectorList.isDoubleSpaced; 1259234353Sdim } 1260234353Sdim bool isDoubleSpacedVectorList() const { 1261234353Sdim return Kind == k_VectorList && VectorList.isDoubleSpaced; 1262234353Sdim } 1263234353Sdim bool isVecListOneD() const { 1264234353Sdim if (!isSingleSpacedVectorList()) return false; 1265234353Sdim return VectorList.Count == 1; 1266234353Sdim } 1267234353Sdim 1268234353Sdim bool isVecListDPair() const { 1269234353Sdim if (!isSingleSpacedVectorList()) return false; 1270234353Sdim return (ARMMCRegisterClasses[ARM::DPairRegClassID] 1271234353Sdim .contains(VectorList.RegNum)); 1272234353Sdim } 1273234353Sdim 1274234353Sdim bool isVecListThreeD() const { 1275234353Sdim if (!isSingleSpacedVectorList()) return false; 1276234353Sdim return VectorList.Count == 3; 1277234353Sdim } 1278234353Sdim 1279234353Sdim bool isVecListFourD() const { 1280234353Sdim if (!isSingleSpacedVectorList()) return false; 1281234353Sdim return VectorList.Count == 4; 1282234353Sdim } 1283234353Sdim 1284234353Sdim bool isVecListDPairSpaced() const { 1285234353Sdim if (isSingleSpacedVectorList()) return false; 1286234353Sdim return (ARMMCRegisterClasses[ARM::DPairSpcRegClassID] 1287234353Sdim .contains(VectorList.RegNum)); 1288234353Sdim } 1289234353Sdim 1290234353Sdim bool isVecListThreeQ() const { 1291234353Sdim if (!isDoubleSpacedVectorList()) return false; 1292234353Sdim return VectorList.Count == 3; 1293234353Sdim } 1294234353Sdim 1295234353Sdim bool isVecListFourQ() const { 1296234353Sdim if (!isDoubleSpacedVectorList()) return false; 1297234353Sdim return VectorList.Count == 4; 1298234353Sdim } 1299234353Sdim 1300234353Sdim bool isSingleSpacedVectorAllLanes() const { 1301234353Sdim return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced; 1302234353Sdim } 1303234353Sdim bool isDoubleSpacedVectorAllLanes() const { 1304234353Sdim return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced; 1305234353Sdim } 1306234353Sdim bool isVecListOneDAllLanes() const { 1307234353Sdim if (!isSingleSpacedVectorAllLanes()) return false; 1308234353Sdim return VectorList.Count == 1; 1309234353Sdim } 1310234353Sdim 1311234353Sdim bool isVecListDPairAllLanes() const { 1312234353Sdim if (!isSingleSpacedVectorAllLanes()) return false; 1313234353Sdim return (ARMMCRegisterClasses[ARM::DPairRegClassID] 1314234353Sdim .contains(VectorList.RegNum)); 1315234353Sdim } 1316234353Sdim 1317234353Sdim bool isVecListDPairSpacedAllLanes() const { 1318234353Sdim if (!isDoubleSpacedVectorAllLanes()) return false; 1319234353Sdim return VectorList.Count == 2; 1320234353Sdim } 1321234353Sdim 1322234353Sdim bool isVecListThreeDAllLanes() const { 1323234353Sdim if (!isSingleSpacedVectorAllLanes()) return false; 1324234353Sdim return VectorList.Count == 3; 1325234353Sdim } 1326234353Sdim 1327234353Sdim bool isVecListThreeQAllLanes() const { 1328234353Sdim if (!isDoubleSpacedVectorAllLanes()) return false; 1329234353Sdim return VectorList.Count == 3; 1330234353Sdim } 1331234353Sdim 1332234353Sdim bool isVecListFourDAllLanes() const { 1333234353Sdim if (!isSingleSpacedVectorAllLanes()) return false; 1334234353Sdim return VectorList.Count == 4; 1335234353Sdim } 1336234353Sdim 1337234353Sdim bool isVecListFourQAllLanes() const { 1338234353Sdim if (!isDoubleSpacedVectorAllLanes()) return false; 1339234353Sdim return VectorList.Count == 4; 1340234353Sdim } 1341234353Sdim 1342234353Sdim bool isSingleSpacedVectorIndexed() const { 1343234353Sdim return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced; 1344234353Sdim } 1345234353Sdim bool isDoubleSpacedVectorIndexed() const { 1346234353Sdim return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced; 1347234353Sdim } 1348234353Sdim bool isVecListOneDByteIndexed() const { 1349234353Sdim if (!isSingleSpacedVectorIndexed()) return false; 1350234353Sdim return VectorList.Count == 1 && VectorList.LaneIndex <= 7; 1351234353Sdim } 1352234353Sdim 1353234353Sdim bool isVecListOneDHWordIndexed() const { 1354234353Sdim if (!isSingleSpacedVectorIndexed()) return false; 1355234353Sdim return VectorList.Count == 1 && VectorList.LaneIndex <= 3; 1356234353Sdim } 1357234353Sdim 1358234353Sdim bool isVecListOneDWordIndexed() const { 1359234353Sdim if (!isSingleSpacedVectorIndexed()) return false; 1360234353Sdim return VectorList.Count == 1 && VectorList.LaneIndex <= 1; 1361234353Sdim } 1362234353Sdim 1363234353Sdim bool isVecListTwoDByteIndexed() const { 1364234353Sdim if (!isSingleSpacedVectorIndexed()) return false; 1365234353Sdim return VectorList.Count == 2 && VectorList.LaneIndex <= 7; 1366234353Sdim } 1367234353Sdim 1368234353Sdim bool isVecListTwoDHWordIndexed() const { 1369234353Sdim if (!isSingleSpacedVectorIndexed()) return false; 1370234353Sdim return VectorList.Count == 2 && VectorList.LaneIndex <= 3; 1371234353Sdim } 1372234353Sdim 1373234353Sdim bool isVecListTwoQWordIndexed() const { 1374234353Sdim if (!isDoubleSpacedVectorIndexed()) return false; 1375234353Sdim return VectorList.Count == 2 && VectorList.LaneIndex <= 1; 1376234353Sdim } 1377234353Sdim 1378234353Sdim bool isVecListTwoQHWordIndexed() const { 1379234353Sdim if (!isDoubleSpacedVectorIndexed()) return false; 1380234353Sdim return VectorList.Count == 2 && VectorList.LaneIndex <= 3; 1381234353Sdim } 1382234353Sdim 1383234353Sdim bool isVecListTwoDWordIndexed() const { 1384234353Sdim if (!isSingleSpacedVectorIndexed()) return false; 1385234353Sdim return VectorList.Count == 2 && VectorList.LaneIndex <= 1; 1386234353Sdim } 1387234353Sdim 1388234353Sdim bool isVecListThreeDByteIndexed() const { 1389234353Sdim if (!isSingleSpacedVectorIndexed()) return false; 1390234353Sdim return VectorList.Count == 3 && VectorList.LaneIndex <= 7; 1391234353Sdim } 1392234353Sdim 1393234353Sdim bool isVecListThreeDHWordIndexed() const { 1394234353Sdim if (!isSingleSpacedVectorIndexed()) return false; 1395234353Sdim return VectorList.Count == 3 && VectorList.LaneIndex <= 3; 1396234353Sdim } 1397234353Sdim 1398234353Sdim bool isVecListThreeQWordIndexed() const { 1399234353Sdim if (!isDoubleSpacedVectorIndexed()) return false; 1400234353Sdim return VectorList.Count == 3 && VectorList.LaneIndex <= 1; 1401234353Sdim } 1402234353Sdim 1403234353Sdim bool isVecListThreeQHWordIndexed() const { 1404234353Sdim if (!isDoubleSpacedVectorIndexed()) return false; 1405234353Sdim return VectorList.Count == 3 && VectorList.LaneIndex <= 3; 1406234353Sdim } 1407234353Sdim 1408234353Sdim bool isVecListThreeDWordIndexed() const { 1409234353Sdim if (!isSingleSpacedVectorIndexed()) return false; 1410234353Sdim return VectorList.Count == 3 && VectorList.LaneIndex <= 1; 1411234353Sdim } 1412234353Sdim 1413234353Sdim bool isVecListFourDByteIndexed() const { 1414234353Sdim if (!isSingleSpacedVectorIndexed()) return false; 1415234353Sdim return VectorList.Count == 4 && VectorList.LaneIndex <= 7; 1416234353Sdim } 1417234353Sdim 1418234353Sdim bool isVecListFourDHWordIndexed() const { 1419234353Sdim if (!isSingleSpacedVectorIndexed()) return false; 1420234353Sdim return VectorList.Count == 4 && VectorList.LaneIndex <= 3; 1421234353Sdim } 1422234353Sdim 1423234353Sdim bool isVecListFourQWordIndexed() const { 1424234353Sdim if (!isDoubleSpacedVectorIndexed()) return false; 1425234353Sdim return VectorList.Count == 4 && VectorList.LaneIndex <= 1; 1426234353Sdim } 1427234353Sdim 1428234353Sdim bool isVecListFourQHWordIndexed() const { 1429234353Sdim if (!isDoubleSpacedVectorIndexed()) return false; 1430234353Sdim return VectorList.Count == 4 && VectorList.LaneIndex <= 3; 1431234353Sdim } 1432234353Sdim 1433234353Sdim bool isVecListFourDWordIndexed() const { 1434234353Sdim if (!isSingleSpacedVectorIndexed()) return false; 1435234353Sdim return VectorList.Count == 4 && VectorList.LaneIndex <= 1; 1436234353Sdim } 1437234353Sdim 1438226633Sdim bool isVectorIndex8() const { 1439226633Sdim if (Kind != k_VectorIndex) return false; 1440226633Sdim return VectorIndex.Val < 8; 1441218893Sdim } 1442226633Sdim bool isVectorIndex16() const { 1443226633Sdim if (Kind != k_VectorIndex) return false; 1444226633Sdim return VectorIndex.Val < 4; 1445226633Sdim } 1446226633Sdim bool isVectorIndex32() const { 1447226633Sdim if (Kind != k_VectorIndex) return false; 1448226633Sdim return VectorIndex.Val < 2; 1449226633Sdim } 1450218893Sdim 1451234353Sdim bool isNEONi8splat() const { 1452234353Sdim if (!isImm()) return false; 1453234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1454234353Sdim // Must be a constant. 1455234353Sdim if (!CE) return false; 1456234353Sdim int64_t Value = CE->getValue(); 1457234353Sdim // i8 value splatted across 8 bytes. The immediate is just the 8 byte 1458234353Sdim // value. 1459234353Sdim return Value >= 0 && Value < 256; 1460234353Sdim } 1461226633Sdim 1462234353Sdim bool isNEONi16splat() const { 1463234353Sdim if (!isImm()) return false; 1464234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1465234353Sdim // Must be a constant. 1466234353Sdim if (!CE) return false; 1467234353Sdim int64_t Value = CE->getValue(); 1468234353Sdim // i16 value in the range [0,255] or [0x0100, 0xff00] 1469234353Sdim return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00); 1470234353Sdim } 1471226633Sdim 1472234353Sdim bool isNEONi32splat() const { 1473234353Sdim if (!isImm()) return false; 1474234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1475234353Sdim // Must be a constant. 1476234353Sdim if (!CE) return false; 1477234353Sdim int64_t Value = CE->getValue(); 1478234353Sdim // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X. 1479234353Sdim return (Value >= 0 && Value < 256) || 1480234353Sdim (Value >= 0x0100 && Value <= 0xff00) || 1481234353Sdim (Value >= 0x010000 && Value <= 0xff0000) || 1482234353Sdim (Value >= 0x01000000 && Value <= 0xff000000); 1483234353Sdim } 1484234353Sdim 1485234353Sdim bool isNEONi32vmov() const { 1486234353Sdim if (!isImm()) return false; 1487234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1488234353Sdim // Must be a constant. 1489234353Sdim if (!CE) return false; 1490234353Sdim int64_t Value = CE->getValue(); 1491234353Sdim // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X, 1492234353Sdim // for VMOV/VMVN only, 00Xf or 0Xff are also accepted. 1493234353Sdim return (Value >= 0 && Value < 256) || 1494234353Sdim (Value >= 0x0100 && Value <= 0xff00) || 1495234353Sdim (Value >= 0x010000 && Value <= 0xff0000) || 1496234353Sdim (Value >= 0x01000000 && Value <= 0xff000000) || 1497234353Sdim (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) || 1498234353Sdim (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff); 1499234353Sdim } 1500234353Sdim bool isNEONi32vmovNeg() const { 1501234353Sdim if (!isImm()) return false; 1502234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1503234353Sdim // Must be a constant. 1504234353Sdim if (!CE) return false; 1505234353Sdim int64_t Value = ~CE->getValue(); 1506234353Sdim // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X, 1507234353Sdim // for VMOV/VMVN only, 00Xf or 0Xff are also accepted. 1508234353Sdim return (Value >= 0 && Value < 256) || 1509234353Sdim (Value >= 0x0100 && Value <= 0xff00) || 1510234353Sdim (Value >= 0x010000 && Value <= 0xff0000) || 1511234353Sdim (Value >= 0x01000000 && Value <= 0xff000000) || 1512234353Sdim (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) || 1513234353Sdim (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff); 1514234353Sdim } 1515234353Sdim 1516234353Sdim bool isNEONi64splat() const { 1517234353Sdim if (!isImm()) return false; 1518234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1519234353Sdim // Must be a constant. 1520234353Sdim if (!CE) return false; 1521234353Sdim uint64_t Value = CE->getValue(); 1522234353Sdim // i64 value with each byte being either 0 or 0xff. 1523234353Sdim for (unsigned i = 0; i < 8; ++i) 1524234353Sdim if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false; 1525234353Sdim return true; 1526234353Sdim } 1527234353Sdim 1528212904Sdim void addExpr(MCInst &Inst, const MCExpr *Expr) const { 1529218893Sdim // Add as immediates when possible. Null MCExpr = 0. 1530218893Sdim if (Expr == 0) 1531218893Sdim Inst.addOperand(MCOperand::CreateImm(0)); 1532218893Sdim else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) 1533212904Sdim Inst.addOperand(MCOperand::CreateImm(CE->getValue())); 1534212904Sdim else 1535212904Sdim Inst.addOperand(MCOperand::CreateExpr(Expr)); 1536212904Sdim } 1537212904Sdim 1538212904Sdim void addCondCodeOperands(MCInst &Inst, unsigned N) const { 1539212904Sdim assert(N == 2 && "Invalid number of operands!"); 1540212904Sdim Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode()))); 1541218893Sdim unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR; 1542218893Sdim Inst.addOperand(MCOperand::CreateReg(RegNum)); 1543212904Sdim } 1544212904Sdim 1545218893Sdim void addCoprocNumOperands(MCInst &Inst, unsigned N) const { 1546218893Sdim assert(N == 1 && "Invalid number of operands!"); 1547218893Sdim Inst.addOperand(MCOperand::CreateImm(getCoproc())); 1548218893Sdim } 1549218893Sdim 1550218893Sdim void addCoprocRegOperands(MCInst &Inst, unsigned N) const { 1551218893Sdim assert(N == 1 && "Invalid number of operands!"); 1552218893Sdim Inst.addOperand(MCOperand::CreateImm(getCoproc())); 1553218893Sdim } 1554218893Sdim 1555226633Sdim void addCoprocOptionOperands(MCInst &Inst, unsigned N) const { 1556226633Sdim assert(N == 1 && "Invalid number of operands!"); 1557226633Sdim Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val)); 1558226633Sdim } 1559226633Sdim 1560226633Sdim void addITMaskOperands(MCInst &Inst, unsigned N) const { 1561226633Sdim assert(N == 1 && "Invalid number of operands!"); 1562226633Sdim Inst.addOperand(MCOperand::CreateImm(ITMask.Mask)); 1563226633Sdim } 1564226633Sdim 1565226633Sdim void addITCondCodeOperands(MCInst &Inst, unsigned N) const { 1566226633Sdim assert(N == 1 && "Invalid number of operands!"); 1567226633Sdim Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode()))); 1568226633Sdim } 1569226633Sdim 1570218893Sdim void addCCOutOperands(MCInst &Inst, unsigned N) const { 1571218893Sdim assert(N == 1 && "Invalid number of operands!"); 1572218893Sdim Inst.addOperand(MCOperand::CreateReg(getReg())); 1573218893Sdim } 1574218893Sdim 1575198090Srdivacky void addRegOperands(MCInst &Inst, unsigned N) const { 1576198090Srdivacky assert(N == 1 && "Invalid number of operands!"); 1577198090Srdivacky Inst.addOperand(MCOperand::CreateReg(getReg())); 1578198090Srdivacky } 1579198090Srdivacky 1580226633Sdim void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const { 1581224145Sdim assert(N == 3 && "Invalid number of operands!"); 1582234353Sdim assert(isRegShiftedReg() && 1583234353Sdim "addRegShiftedRegOperands() on non RegShiftedReg!"); 1584226633Sdim Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg)); 1585226633Sdim Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg)); 1586224145Sdim Inst.addOperand(MCOperand::CreateImm( 1587226633Sdim ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm))); 1588224145Sdim } 1589224145Sdim 1590226633Sdim void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const { 1591226633Sdim assert(N == 2 && "Invalid number of operands!"); 1592234353Sdim assert(isRegShiftedImm() && 1593234353Sdim "addRegShiftedImmOperands() on non RegShiftedImm!"); 1594226633Sdim Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg)); 1595239462Sdim // Shift of #32 is encoded as 0 where permitted 1596239462Sdim unsigned Imm = (RegShiftedImm.ShiftImm == 32 ? 0 : RegShiftedImm.ShiftImm); 1597221345Sdim Inst.addOperand(MCOperand::CreateImm( 1598239462Sdim ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, Imm))); 1599221345Sdim } 1600221345Sdim 1601226633Sdim void addShifterImmOperands(MCInst &Inst, unsigned N) const { 1602226633Sdim assert(N == 1 && "Invalid number of operands!"); 1603226633Sdim Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) | 1604226633Sdim ShifterImm.Imm)); 1605226633Sdim } 1606226633Sdim 1607218893Sdim void addRegListOperands(MCInst &Inst, unsigned N) const { 1608218893Sdim assert(N == 1 && "Invalid number of operands!"); 1609218893Sdim const SmallVectorImpl<unsigned> &RegList = getRegList(); 1610218893Sdim for (SmallVectorImpl<unsigned>::const_iterator 1611218893Sdim I = RegList.begin(), E = RegList.end(); I != E; ++I) 1612218893Sdim Inst.addOperand(MCOperand::CreateReg(*I)); 1613218893Sdim } 1614218893Sdim 1615218893Sdim void addDPRRegListOperands(MCInst &Inst, unsigned N) const { 1616218893Sdim addRegListOperands(Inst, N); 1617218893Sdim } 1618218893Sdim 1619218893Sdim void addSPRRegListOperands(MCInst &Inst, unsigned N) const { 1620218893Sdim addRegListOperands(Inst, N); 1621218893Sdim } 1622218893Sdim 1623226633Sdim void addRotImmOperands(MCInst &Inst, unsigned N) const { 1624226633Sdim assert(N == 1 && "Invalid number of operands!"); 1625226633Sdim // Encoded as val>>3. The printer handles display as 8, 16, 24. 1626226633Sdim Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3)); 1627226633Sdim } 1628226633Sdim 1629226633Sdim void addBitfieldOperands(MCInst &Inst, unsigned N) const { 1630226633Sdim assert(N == 1 && "Invalid number of operands!"); 1631226633Sdim // Munge the lsb/width into a bitfield mask. 1632226633Sdim unsigned lsb = Bitfield.LSB; 1633226633Sdim unsigned width = Bitfield.Width; 1634226633Sdim // Make a 32-bit mask w/ the referenced bits clear and all other bits set. 1635226633Sdim uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >> 1636226633Sdim (32 - (lsb + width))); 1637226633Sdim Inst.addOperand(MCOperand::CreateImm(Mask)); 1638226633Sdim } 1639226633Sdim 1640212904Sdim void addImmOperands(MCInst &Inst, unsigned N) const { 1641212904Sdim assert(N == 1 && "Invalid number of operands!"); 1642212904Sdim addExpr(Inst, getImm()); 1643212904Sdim } 1644212904Sdim 1645234353Sdim void addFBits16Operands(MCInst &Inst, unsigned N) const { 1646234353Sdim assert(N == 1 && "Invalid number of operands!"); 1647234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1648234353Sdim Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue())); 1649234353Sdim } 1650234353Sdim 1651234353Sdim void addFBits32Operands(MCInst &Inst, unsigned N) const { 1652234353Sdim assert(N == 1 && "Invalid number of operands!"); 1653234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1654234353Sdim Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue())); 1655234353Sdim } 1656234353Sdim 1657226633Sdim void addFPImmOperands(MCInst &Inst, unsigned N) const { 1658226633Sdim assert(N == 1 && "Invalid number of operands!"); 1659234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1660234353Sdim int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue())); 1661234353Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 1662226633Sdim } 1663226633Sdim 1664226633Sdim void addImm8s4Operands(MCInst &Inst, unsigned N) const { 1665226633Sdim assert(N == 1 && "Invalid number of operands!"); 1666226633Sdim // FIXME: We really want to scale the value here, but the LDRD/STRD 1667226633Sdim // instruction don't encode operands that way yet. 1668226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1669226633Sdim Inst.addOperand(MCOperand::CreateImm(CE->getValue())); 1670226633Sdim } 1671226633Sdim 1672226633Sdim void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const { 1673226633Sdim assert(N == 1 && "Invalid number of operands!"); 1674226633Sdim // The immediate is scaled by four in the encoding and is stored 1675226633Sdim // in the MCInst as such. Lop off the low two bits here. 1676226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1677226633Sdim Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4)); 1678226633Sdim } 1679226633Sdim 1680234353Sdim void addImm0_508s4NegOperands(MCInst &Inst, unsigned N) const { 1681226633Sdim assert(N == 1 && "Invalid number of operands!"); 1682226633Sdim // The immediate is scaled by four in the encoding and is stored 1683226633Sdim // in the MCInst as such. Lop off the low two bits here. 1684226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1685234353Sdim Inst.addOperand(MCOperand::CreateImm(-(CE->getValue() / 4))); 1686226633Sdim } 1687226633Sdim 1688234353Sdim void addImm0_508s4Operands(MCInst &Inst, unsigned N) const { 1689224145Sdim assert(N == 1 && "Invalid number of operands!"); 1690234353Sdim // The immediate is scaled by four in the encoding and is stored 1691234353Sdim // in the MCInst as such. Lop off the low two bits here. 1692234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1693234353Sdim Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4)); 1694224145Sdim } 1695224145Sdim 1696226633Sdim void addImm1_16Operands(MCInst &Inst, unsigned N) const { 1697226633Sdim assert(N == 1 && "Invalid number of operands!"); 1698226633Sdim // The constant encodes as the immediate-1, and we store in the instruction 1699226633Sdim // the bits as encoded, so subtract off one here. 1700226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1701226633Sdim Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1)); 1702226633Sdim } 1703226633Sdim 1704226633Sdim void addImm1_32Operands(MCInst &Inst, unsigned N) const { 1705226633Sdim assert(N == 1 && "Invalid number of operands!"); 1706226633Sdim // The constant encodes as the immediate-1, and we store in the instruction 1707226633Sdim // the bits as encoded, so subtract off one here. 1708226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1709226633Sdim Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1)); 1710226633Sdim } 1711226633Sdim 1712226633Sdim void addImmThumbSROperands(MCInst &Inst, unsigned N) const { 1713226633Sdim assert(N == 1 && "Invalid number of operands!"); 1714226633Sdim // The constant encodes as the immediate, except for 32, which encodes as 1715226633Sdim // zero. 1716226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1717226633Sdim unsigned Imm = CE->getValue(); 1718226633Sdim Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm))); 1719226633Sdim } 1720226633Sdim 1721226633Sdim void addPKHASRImmOperands(MCInst &Inst, unsigned N) const { 1722226633Sdim assert(N == 1 && "Invalid number of operands!"); 1723226633Sdim // An ASR value of 32 encodes as 0, so that's how we want to add it to 1724226633Sdim // the instruction as well. 1725226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1726226633Sdim int Val = CE->getValue(); 1727226633Sdim Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val)); 1728226633Sdim } 1729226633Sdim 1730234353Sdim void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const { 1731226633Sdim assert(N == 1 && "Invalid number of operands!"); 1732234353Sdim // The operand is actually a t2_so_imm, but we have its bitwise 1733234353Sdim // negation in the assembly source, so twiddle it here. 1734234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1735234353Sdim Inst.addOperand(MCOperand::CreateImm(~CE->getValue())); 1736226633Sdim } 1737226633Sdim 1738234353Sdim void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const { 1739224145Sdim assert(N == 1 && "Invalid number of operands!"); 1740234353Sdim // The operand is actually a t2_so_imm, but we have its 1741234353Sdim // negation in the assembly source, so twiddle it here. 1742234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1743234353Sdim Inst.addOperand(MCOperand::CreateImm(-CE->getValue())); 1744224145Sdim } 1745224145Sdim 1746234353Sdim void addImm0_4095NegOperands(MCInst &Inst, unsigned N) const { 1747226633Sdim assert(N == 1 && "Invalid number of operands!"); 1748234353Sdim // The operand is actually an imm0_4095, but we have its 1749234353Sdim // negation in the assembly source, so twiddle it here. 1750234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1751234353Sdim Inst.addOperand(MCOperand::CreateImm(-CE->getValue())); 1752226633Sdim } 1753226633Sdim 1754263508Sdim void addUnsignedOffset_b8s2Operands(MCInst &Inst, unsigned N) const { 1755263508Sdim if(const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm())) { 1756263508Sdim Inst.addOperand(MCOperand::CreateImm(CE->getValue() >> 2)); 1757263508Sdim return; 1758263508Sdim } 1759263508Sdim 1760263508Sdim const MCSymbolRefExpr *SR = dyn_cast<MCSymbolRefExpr>(Imm.Val); 1761263508Sdim assert(SR && "Unknown value type!"); 1762263508Sdim Inst.addOperand(MCOperand::CreateExpr(SR)); 1763263508Sdim } 1764263508Sdim 1765263508Sdim void addThumbMemPCOperands(MCInst &Inst, unsigned N) const { 1766263508Sdim assert(N == 1 && "Invalid number of operands!"); 1767263508Sdim if (isImm()) { 1768263508Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1769263508Sdim if (CE) { 1770263508Sdim Inst.addOperand(MCOperand::CreateImm(CE->getValue())); 1771263508Sdim return; 1772263508Sdim } 1773263508Sdim 1774263508Sdim const MCSymbolRefExpr *SR = dyn_cast<MCSymbolRefExpr>(Imm.Val); 1775263508Sdim assert(SR && "Unknown value type!"); 1776263508Sdim Inst.addOperand(MCOperand::CreateExpr(SR)); 1777263508Sdim return; 1778263508Sdim } 1779263508Sdim 1780263508Sdim assert(isMem() && "Unknown value type!"); 1781263508Sdim assert(isa<MCConstantExpr>(Memory.OffsetImm) && "Unknown value type!"); 1782263508Sdim Inst.addOperand(MCOperand::CreateImm(Memory.OffsetImm->getValue())); 1783263508Sdim } 1784263508Sdim 1785234353Sdim void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const { 1786234353Sdim assert(N == 1 && "Invalid number of operands!"); 1787234353Sdim // The operand is actually a so_imm, but we have its bitwise 1788234353Sdim // negation in the assembly source, so twiddle it here. 1789234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1790234353Sdim Inst.addOperand(MCOperand::CreateImm(~CE->getValue())); 1791234353Sdim } 1792234353Sdim 1793234353Sdim void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const { 1794234353Sdim assert(N == 1 && "Invalid number of operands!"); 1795234353Sdim // The operand is actually a so_imm, but we have its 1796234353Sdim // negation in the assembly source, so twiddle it here. 1797234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1798234353Sdim Inst.addOperand(MCOperand::CreateImm(-CE->getValue())); 1799234353Sdim } 1800234353Sdim 1801218893Sdim void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const { 1802218893Sdim assert(N == 1 && "Invalid number of operands!"); 1803218893Sdim Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt()))); 1804218893Sdim } 1805218893Sdim 1806263508Sdim void addInstSyncBarrierOptOperands(MCInst &Inst, unsigned N) const { 1807263508Sdim assert(N == 1 && "Invalid number of operands!"); 1808263508Sdim Inst.addOperand(MCOperand::CreateImm(unsigned(getInstSyncBarrierOpt()))); 1809263508Sdim } 1810263508Sdim 1811226633Sdim void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const { 1812226633Sdim assert(N == 1 && "Invalid number of operands!"); 1813226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 1814226633Sdim } 1815221345Sdim 1816234353Sdim void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const { 1817234353Sdim assert(N == 1 && "Invalid number of operands!"); 1818234353Sdim int32_t Imm = Memory.OffsetImm->getValue(); 1819234353Sdim Inst.addOperand(MCOperand::CreateImm(Imm)); 1820234353Sdim } 1821234353Sdim 1822239462Sdim void addAdrLabelOperands(MCInst &Inst, unsigned N) const { 1823239462Sdim assert(N == 1 && "Invalid number of operands!"); 1824239462Sdim assert(isImm() && "Not an immediate!"); 1825239462Sdim 1826239462Sdim // If we have an immediate that's not a constant, treat it as a label 1827239462Sdim // reference needing a fixup. 1828239462Sdim if (!isa<MCConstantExpr>(getImm())) { 1829239462Sdim Inst.addOperand(MCOperand::CreateExpr(getImm())); 1830239462Sdim return; 1831239462Sdim } 1832239462Sdim 1833239462Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1834239462Sdim int Val = CE->getValue(); 1835239462Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 1836239462Sdim } 1837239462Sdim 1838226633Sdim void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const { 1839226633Sdim assert(N == 2 && "Invalid number of operands!"); 1840226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 1841226633Sdim Inst.addOperand(MCOperand::CreateImm(Memory.Alignment)); 1842221345Sdim } 1843221345Sdim 1844226633Sdim void addAddrMode2Operands(MCInst &Inst, unsigned N) const { 1845226633Sdim assert(N == 3 && "Invalid number of operands!"); 1846226633Sdim int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; 1847226633Sdim if (!Memory.OffsetRegNum) { 1848226633Sdim ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; 1849226633Sdim // Special case for #-0 1850226633Sdim if (Val == INT32_MIN) Val = 0; 1851226633Sdim if (Val < 0) Val = -Val; 1852226633Sdim Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift); 1853226633Sdim } else { 1854226633Sdim // For register offset, we encode the shift type and negation flag 1855226633Sdim // here. 1856226633Sdim Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 1857226633Sdim Memory.ShiftImm, Memory.ShiftType); 1858226633Sdim } 1859226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 1860226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); 1861226633Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 1862226633Sdim } 1863221345Sdim 1864226633Sdim void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const { 1865226633Sdim assert(N == 2 && "Invalid number of operands!"); 1866226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1867226633Sdim assert(CE && "non-constant AM2OffsetImm operand!"); 1868226633Sdim int32_t Val = CE->getValue(); 1869226633Sdim ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; 1870226633Sdim // Special case for #-0 1871226633Sdim if (Val == INT32_MIN) Val = 0; 1872226633Sdim if (Val < 0) Val = -Val; 1873226633Sdim Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift); 1874226633Sdim Inst.addOperand(MCOperand::CreateReg(0)); 1875226633Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 1876226633Sdim } 1877221345Sdim 1878226633Sdim void addAddrMode3Operands(MCInst &Inst, unsigned N) const { 1879226633Sdim assert(N == 3 && "Invalid number of operands!"); 1880234353Sdim // If we have an immediate that's not a constant, treat it as a label 1881234353Sdim // reference needing a fixup. If it is a constant, it's something else 1882234353Sdim // and we reject it. 1883234353Sdim if (isImm()) { 1884234353Sdim Inst.addOperand(MCOperand::CreateExpr(getImm())); 1885234353Sdim Inst.addOperand(MCOperand::CreateReg(0)); 1886234353Sdim Inst.addOperand(MCOperand::CreateImm(0)); 1887234353Sdim return; 1888234353Sdim } 1889234353Sdim 1890226633Sdim int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; 1891226633Sdim if (!Memory.OffsetRegNum) { 1892226633Sdim ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; 1893226633Sdim // Special case for #-0 1894226633Sdim if (Val == INT32_MIN) Val = 0; 1895226633Sdim if (Val < 0) Val = -Val; 1896226633Sdim Val = ARM_AM::getAM3Opc(AddSub, Val); 1897226633Sdim } else { 1898226633Sdim // For register offset, we encode the shift type and negation flag 1899226633Sdim // here. 1900226633Sdim Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0); 1901226633Sdim } 1902226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 1903226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); 1904226633Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 1905226633Sdim } 1906221345Sdim 1907226633Sdim void addAM3OffsetOperands(MCInst &Inst, unsigned N) const { 1908226633Sdim assert(N == 2 && "Invalid number of operands!"); 1909226633Sdim if (Kind == k_PostIndexRegister) { 1910226633Sdim int32_t Val = 1911226633Sdim ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0); 1912226633Sdim Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum)); 1913226633Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 1914221345Sdim return; 1915221345Sdim } 1916221345Sdim 1917226633Sdim // Constant offset. 1918226633Sdim const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm()); 1919226633Sdim int32_t Val = CE->getValue(); 1920226633Sdim ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; 1921226633Sdim // Special case for #-0 1922226633Sdim if (Val == INT32_MIN) Val = 0; 1923226633Sdim if (Val < 0) Val = -Val; 1924226633Sdim Val = ARM_AM::getAM3Opc(AddSub, Val); 1925221345Sdim Inst.addOperand(MCOperand::CreateReg(0)); 1926226633Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 1927226633Sdim } 1928221345Sdim 1929226633Sdim void addAddrMode5Operands(MCInst &Inst, unsigned N) const { 1930226633Sdim assert(N == 2 && "Invalid number of operands!"); 1931234353Sdim // If we have an immediate that's not a constant, treat it as a label 1932234353Sdim // reference needing a fixup. If it is a constant, it's something else 1933234353Sdim // and we reject it. 1934234353Sdim if (isImm()) { 1935234353Sdim Inst.addOperand(MCOperand::CreateExpr(getImm())); 1936234353Sdim Inst.addOperand(MCOperand::CreateImm(0)); 1937234353Sdim return; 1938234353Sdim } 1939234353Sdim 1940226633Sdim // The lower two bits are always zero and as such are not encoded. 1941226633Sdim int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0; 1942226633Sdim ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; 1943226633Sdim // Special case for #-0 1944226633Sdim if (Val == INT32_MIN) Val = 0; 1945226633Sdim if (Val < 0) Val = -Val; 1946226633Sdim Val = ARM_AM::getAM5Opc(AddSub, Val); 1947226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 1948226633Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 1949226633Sdim } 1950221345Sdim 1951226633Sdim void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const { 1952226633Sdim assert(N == 2 && "Invalid number of operands!"); 1953234353Sdim // If we have an immediate that's not a constant, treat it as a label 1954234353Sdim // reference needing a fixup. If it is a constant, it's something else 1955234353Sdim // and we reject it. 1956234353Sdim if (isImm()) { 1957234353Sdim Inst.addOperand(MCOperand::CreateExpr(getImm())); 1958234353Sdim Inst.addOperand(MCOperand::CreateImm(0)); 1959234353Sdim return; 1960234353Sdim } 1961234353Sdim 1962226633Sdim int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; 1963226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 1964226633Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 1965221345Sdim } 1966221345Sdim 1967226633Sdim void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const { 1968226633Sdim assert(N == 2 && "Invalid number of operands!"); 1969226633Sdim // The lower two bits are always zero and as such are not encoded. 1970226633Sdim int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0; 1971226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 1972226633Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 1973226633Sdim } 1974221345Sdim 1975226633Sdim void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const { 1976226633Sdim assert(N == 2 && "Invalid number of operands!"); 1977226633Sdim int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; 1978226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 1979226633Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 1980226633Sdim } 1981221345Sdim 1982226633Sdim void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const { 1983226633Sdim addMemImm8OffsetOperands(Inst, N); 1984226633Sdim } 1985226633Sdim 1986226633Sdim void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const { 1987226633Sdim addMemImm8OffsetOperands(Inst, N); 1988226633Sdim } 1989226633Sdim 1990226633Sdim void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const { 1991226633Sdim assert(N == 2 && "Invalid number of operands!"); 1992226633Sdim // If this is an immediate, it's a label reference. 1993234353Sdim if (isImm()) { 1994226633Sdim addExpr(Inst, getImm()); 1995226633Sdim Inst.addOperand(MCOperand::CreateImm(0)); 1996221345Sdim return; 1997221345Sdim } 1998221345Sdim 1999226633Sdim // Otherwise, it's a normal memory reg+offset. 2000226633Sdim int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; 2001226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 2002226633Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 2003226633Sdim } 2004221345Sdim 2005226633Sdim void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const { 2006226633Sdim assert(N == 2 && "Invalid number of operands!"); 2007226633Sdim // If this is an immediate, it's a label reference. 2008234353Sdim if (isImm()) { 2009226633Sdim addExpr(Inst, getImm()); 2010226633Sdim Inst.addOperand(MCOperand::CreateImm(0)); 2011226633Sdim return; 2012226633Sdim } 2013221345Sdim 2014226633Sdim // Otherwise, it's a normal memory reg+offset. 2015226633Sdim int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; 2016226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 2017226633Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 2018221345Sdim } 2019221345Sdim 2020226633Sdim void addMemTBBOperands(MCInst &Inst, unsigned N) const { 2021226633Sdim assert(N == 2 && "Invalid number of operands!"); 2022226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 2023226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); 2024226633Sdim } 2025218893Sdim 2026226633Sdim void addMemTBHOperands(MCInst &Inst, unsigned N) const { 2027226633Sdim assert(N == 2 && "Invalid number of operands!"); 2028226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 2029226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); 2030226633Sdim } 2031218893Sdim 2032226633Sdim void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const { 2033226633Sdim assert(N == 3 && "Invalid number of operands!"); 2034234353Sdim unsigned Val = 2035234353Sdim ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 2036234353Sdim Memory.ShiftImm, Memory.ShiftType); 2037226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 2038226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); 2039226633Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 2040226633Sdim } 2041218893Sdim 2042226633Sdim void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const { 2043226633Sdim assert(N == 3 && "Invalid number of operands!"); 2044226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 2045226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); 2046226633Sdim Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm)); 2047218893Sdim } 2048218893Sdim 2049226633Sdim void addMemThumbRROperands(MCInst &Inst, unsigned N) const { 2050226633Sdim assert(N == 2 && "Invalid number of operands!"); 2051226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 2052226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); 2053218893Sdim } 2054218893Sdim 2055226633Sdim void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const { 2056226633Sdim assert(N == 2 && "Invalid number of operands!"); 2057226633Sdim int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0; 2058226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 2059226633Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 2060218893Sdim } 2061218893Sdim 2062226633Sdim void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const { 2063226633Sdim assert(N == 2 && "Invalid number of operands!"); 2064226633Sdim int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0; 2065226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 2066226633Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 2067226633Sdim } 2068226633Sdim 2069226633Sdim void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const { 2070226633Sdim assert(N == 2 && "Invalid number of operands!"); 2071226633Sdim int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0; 2072226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 2073226633Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 2074226633Sdim } 2075226633Sdim 2076226633Sdim void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const { 2077226633Sdim assert(N == 2 && "Invalid number of operands!"); 2078226633Sdim int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0; 2079226633Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 2080226633Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 2081226633Sdim } 2082226633Sdim 2083226633Sdim void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const { 2084226633Sdim assert(N == 1 && "Invalid number of operands!"); 2085226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 2086226633Sdim assert(CE && "non-constant post-idx-imm8 operand!"); 2087226633Sdim int Imm = CE->getValue(); 2088226633Sdim bool isAdd = Imm >= 0; 2089226633Sdim if (Imm == INT32_MIN) Imm = 0; 2090226633Sdim Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8; 2091226633Sdim Inst.addOperand(MCOperand::CreateImm(Imm)); 2092226633Sdim } 2093226633Sdim 2094226633Sdim void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const { 2095226633Sdim assert(N == 1 && "Invalid number of operands!"); 2096226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 2097226633Sdim assert(CE && "non-constant post-idx-imm8s4 operand!"); 2098226633Sdim int Imm = CE->getValue(); 2099226633Sdim bool isAdd = Imm >= 0; 2100226633Sdim if (Imm == INT32_MIN) Imm = 0; 2101226633Sdim // Immediate is scaled by 4. 2102226633Sdim Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8; 2103226633Sdim Inst.addOperand(MCOperand::CreateImm(Imm)); 2104226633Sdim } 2105226633Sdim 2106226633Sdim void addPostIdxRegOperands(MCInst &Inst, unsigned N) const { 2107226633Sdim assert(N == 2 && "Invalid number of operands!"); 2108226633Sdim Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum)); 2109226633Sdim Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd)); 2110226633Sdim } 2111226633Sdim 2112226633Sdim void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const { 2113226633Sdim assert(N == 2 && "Invalid number of operands!"); 2114226633Sdim Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum)); 2115226633Sdim // The sign, shift type, and shift amount are encoded in a single operand 2116226633Sdim // using the AM2 encoding helpers. 2117226633Sdim ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub; 2118226633Sdim unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm, 2119226633Sdim PostIdxReg.ShiftTy); 2120226633Sdim Inst.addOperand(MCOperand::CreateImm(Imm)); 2121226633Sdim } 2122226633Sdim 2123218893Sdim void addMSRMaskOperands(MCInst &Inst, unsigned N) const { 2124218893Sdim assert(N == 1 && "Invalid number of operands!"); 2125218893Sdim Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask()))); 2126218893Sdim } 2127218893Sdim 2128218893Sdim void addProcIFlagsOperands(MCInst &Inst, unsigned N) const { 2129218893Sdim assert(N == 1 && "Invalid number of operands!"); 2130218893Sdim Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags()))); 2131218893Sdim } 2132218893Sdim 2133234353Sdim void addVecListOperands(MCInst &Inst, unsigned N) const { 2134234353Sdim assert(N == 1 && "Invalid number of operands!"); 2135234353Sdim Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum)); 2136234353Sdim } 2137234353Sdim 2138234353Sdim void addVecListIndexedOperands(MCInst &Inst, unsigned N) const { 2139234353Sdim assert(N == 2 && "Invalid number of operands!"); 2140234353Sdim Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum)); 2141234353Sdim Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex)); 2142234353Sdim } 2143234353Sdim 2144226633Sdim void addVectorIndex8Operands(MCInst &Inst, unsigned N) const { 2145226633Sdim assert(N == 1 && "Invalid number of operands!"); 2146226633Sdim Inst.addOperand(MCOperand::CreateImm(getVectorIndex())); 2147226633Sdim } 2148226633Sdim 2149226633Sdim void addVectorIndex16Operands(MCInst &Inst, unsigned N) const { 2150226633Sdim assert(N == 1 && "Invalid number of operands!"); 2151226633Sdim Inst.addOperand(MCOperand::CreateImm(getVectorIndex())); 2152226633Sdim } 2153226633Sdim 2154226633Sdim void addVectorIndex32Operands(MCInst &Inst, unsigned N) const { 2155226633Sdim assert(N == 1 && "Invalid number of operands!"); 2156226633Sdim Inst.addOperand(MCOperand::CreateImm(getVectorIndex())); 2157226633Sdim } 2158226633Sdim 2159234353Sdim void addNEONi8splatOperands(MCInst &Inst, unsigned N) const { 2160234353Sdim assert(N == 1 && "Invalid number of operands!"); 2161234353Sdim // The immediate encodes the type of constant as well as the value. 2162234353Sdim // Mask in that this is an i8 splat. 2163234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 2164234353Sdim Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00)); 2165234353Sdim } 2166234353Sdim 2167234353Sdim void addNEONi16splatOperands(MCInst &Inst, unsigned N) const { 2168234353Sdim assert(N == 1 && "Invalid number of operands!"); 2169234353Sdim // The immediate encodes the type of constant as well as the value. 2170234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 2171234353Sdim unsigned Value = CE->getValue(); 2172234353Sdim if (Value >= 256) 2173234353Sdim Value = (Value >> 8) | 0xa00; 2174234353Sdim else 2175234353Sdim Value |= 0x800; 2176234353Sdim Inst.addOperand(MCOperand::CreateImm(Value)); 2177234353Sdim } 2178234353Sdim 2179234353Sdim void addNEONi32splatOperands(MCInst &Inst, unsigned N) const { 2180234353Sdim assert(N == 1 && "Invalid number of operands!"); 2181234353Sdim // The immediate encodes the type of constant as well as the value. 2182234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 2183234353Sdim unsigned Value = CE->getValue(); 2184234353Sdim if (Value >= 256 && Value <= 0xff00) 2185234353Sdim Value = (Value >> 8) | 0x200; 2186234353Sdim else if (Value > 0xffff && Value <= 0xff0000) 2187234353Sdim Value = (Value >> 16) | 0x400; 2188234353Sdim else if (Value > 0xffffff) 2189234353Sdim Value = (Value >> 24) | 0x600; 2190234353Sdim Inst.addOperand(MCOperand::CreateImm(Value)); 2191234353Sdim } 2192234353Sdim 2193234353Sdim void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const { 2194234353Sdim assert(N == 1 && "Invalid number of operands!"); 2195234353Sdim // The immediate encodes the type of constant as well as the value. 2196234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 2197234353Sdim unsigned Value = CE->getValue(); 2198234353Sdim if (Value >= 256 && Value <= 0xffff) 2199234353Sdim Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200); 2200234353Sdim else if (Value > 0xffff && Value <= 0xffffff) 2201234353Sdim Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400); 2202234353Sdim else if (Value > 0xffffff) 2203234353Sdim Value = (Value >> 24) | 0x600; 2204234353Sdim Inst.addOperand(MCOperand::CreateImm(Value)); 2205234353Sdim } 2206234353Sdim 2207234353Sdim void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const { 2208234353Sdim assert(N == 1 && "Invalid number of operands!"); 2209234353Sdim // The immediate encodes the type of constant as well as the value. 2210234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 2211234353Sdim unsigned Value = ~CE->getValue(); 2212234353Sdim if (Value >= 256 && Value <= 0xffff) 2213234353Sdim Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200); 2214234353Sdim else if (Value > 0xffff && Value <= 0xffffff) 2215234353Sdim Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400); 2216234353Sdim else if (Value > 0xffffff) 2217234353Sdim Value = (Value >> 24) | 0x600; 2218234353Sdim Inst.addOperand(MCOperand::CreateImm(Value)); 2219234353Sdim } 2220234353Sdim 2221234353Sdim void addNEONi64splatOperands(MCInst &Inst, unsigned N) const { 2222234353Sdim assert(N == 1 && "Invalid number of operands!"); 2223234353Sdim // The immediate encodes the type of constant as well as the value. 2224234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 2225234353Sdim uint64_t Value = CE->getValue(); 2226234353Sdim unsigned Imm = 0; 2227234353Sdim for (unsigned i = 0; i < 8; ++i, Value >>= 8) { 2228234353Sdim Imm |= (Value & 1) << i; 2229234353Sdim } 2230234353Sdim Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00)); 2231234353Sdim } 2232234353Sdim 2233224145Sdim virtual void print(raw_ostream &OS) const; 2234212904Sdim 2235226633Sdim static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) { 2236226633Sdim ARMOperand *Op = new ARMOperand(k_ITCondMask); 2237226633Sdim Op->ITMask.Mask = Mask; 2238226633Sdim Op->StartLoc = S; 2239226633Sdim Op->EndLoc = S; 2240226633Sdim return Op; 2241226633Sdim } 2242226633Sdim 2243218893Sdim static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) { 2244226633Sdim ARMOperand *Op = new ARMOperand(k_CondCode); 2245212904Sdim Op->CC.Val = CC; 2246212904Sdim Op->StartLoc = S; 2247212904Sdim Op->EndLoc = S; 2248218893Sdim return Op; 2249212904Sdim } 2250212904Sdim 2251218893Sdim static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) { 2252226633Sdim ARMOperand *Op = new ARMOperand(k_CoprocNum); 2253218893Sdim Op->Cop.Val = CopVal; 2254218893Sdim Op->StartLoc = S; 2255218893Sdim Op->EndLoc = S; 2256218893Sdim return Op; 2257218893Sdim } 2258218893Sdim 2259218893Sdim static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) { 2260226633Sdim ARMOperand *Op = new ARMOperand(k_CoprocReg); 2261218893Sdim Op->Cop.Val = CopVal; 2262218893Sdim Op->StartLoc = S; 2263218893Sdim Op->EndLoc = S; 2264218893Sdim return Op; 2265218893Sdim } 2266218893Sdim 2267226633Sdim static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) { 2268226633Sdim ARMOperand *Op = new ARMOperand(k_CoprocOption); 2269226633Sdim Op->Cop.Val = Val; 2270226633Sdim Op->StartLoc = S; 2271226633Sdim Op->EndLoc = E; 2272226633Sdim return Op; 2273226633Sdim } 2274226633Sdim 2275218893Sdim static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) { 2276226633Sdim ARMOperand *Op = new ARMOperand(k_CCOut); 2277218893Sdim Op->Reg.RegNum = RegNum; 2278218893Sdim Op->StartLoc = S; 2279218893Sdim Op->EndLoc = S; 2280218893Sdim return Op; 2281218893Sdim } 2282218893Sdim 2283218893Sdim static ARMOperand *CreateToken(StringRef Str, SMLoc S) { 2284226633Sdim ARMOperand *Op = new ARMOperand(k_Token); 2285206124Srdivacky Op->Tok.Data = Str.data(); 2286206124Srdivacky Op->Tok.Length = Str.size(); 2287206124Srdivacky Op->StartLoc = S; 2288206124Srdivacky Op->EndLoc = S; 2289218893Sdim return Op; 2290198090Srdivacky } 2291198090Srdivacky 2292218893Sdim static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) { 2293226633Sdim ARMOperand *Op = new ARMOperand(k_Register); 2294206124Srdivacky Op->Reg.RegNum = RegNum; 2295206124Srdivacky Op->StartLoc = S; 2296206124Srdivacky Op->EndLoc = E; 2297218893Sdim return Op; 2298198090Srdivacky } 2299198090Srdivacky 2300224145Sdim static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy, 2301224145Sdim unsigned SrcReg, 2302224145Sdim unsigned ShiftReg, 2303224145Sdim unsigned ShiftImm, 2304224145Sdim SMLoc S, SMLoc E) { 2305226633Sdim ARMOperand *Op = new ARMOperand(k_ShiftedRegister); 2306226633Sdim Op->RegShiftedReg.ShiftTy = ShTy; 2307226633Sdim Op->RegShiftedReg.SrcReg = SrcReg; 2308226633Sdim Op->RegShiftedReg.ShiftReg = ShiftReg; 2309226633Sdim Op->RegShiftedReg.ShiftImm = ShiftImm; 2310224145Sdim Op->StartLoc = S; 2311224145Sdim Op->EndLoc = E; 2312224145Sdim return Op; 2313224145Sdim } 2314224145Sdim 2315226633Sdim static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy, 2316226633Sdim unsigned SrcReg, 2317226633Sdim unsigned ShiftImm, 2318226633Sdim SMLoc S, SMLoc E) { 2319226633Sdim ARMOperand *Op = new ARMOperand(k_ShiftedImmediate); 2320226633Sdim Op->RegShiftedImm.ShiftTy = ShTy; 2321226633Sdim Op->RegShiftedImm.SrcReg = SrcReg; 2322226633Sdim Op->RegShiftedImm.ShiftImm = ShiftImm; 2323226633Sdim Op->StartLoc = S; 2324226633Sdim Op->EndLoc = E; 2325226633Sdim return Op; 2326226633Sdim } 2327226633Sdim 2328226633Sdim static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm, 2329221345Sdim SMLoc S, SMLoc E) { 2330226633Sdim ARMOperand *Op = new ARMOperand(k_ShifterImmediate); 2331226633Sdim Op->ShifterImm.isASR = isASR; 2332226633Sdim Op->ShifterImm.Imm = Imm; 2333221345Sdim Op->StartLoc = S; 2334221345Sdim Op->EndLoc = E; 2335221345Sdim return Op; 2336221345Sdim } 2337221345Sdim 2338226633Sdim static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) { 2339226633Sdim ARMOperand *Op = new ARMOperand(k_RotateImmediate); 2340226633Sdim Op->RotImm.Imm = Imm; 2341226633Sdim Op->StartLoc = S; 2342226633Sdim Op->EndLoc = E; 2343226633Sdim return Op; 2344226633Sdim } 2345226633Sdim 2346226633Sdim static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width, 2347226633Sdim SMLoc S, SMLoc E) { 2348226633Sdim ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor); 2349226633Sdim Op->Bitfield.LSB = LSB; 2350226633Sdim Op->Bitfield.Width = Width; 2351226633Sdim Op->StartLoc = S; 2352226633Sdim Op->EndLoc = E; 2353226633Sdim return Op; 2354226633Sdim } 2355226633Sdim 2356218893Sdim static ARMOperand * 2357263508Sdim CreateRegList(SmallVectorImpl<std::pair<unsigned, unsigned> > &Regs, 2358218893Sdim SMLoc StartLoc, SMLoc EndLoc) { 2359263508Sdim assert (Regs.size() > 0 && "RegList contains no registers?"); 2360226633Sdim KindTy Kind = k_RegisterList; 2361218893Sdim 2362263508Sdim if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().second)) 2363226633Sdim Kind = k_DPRRegisterList; 2364226633Sdim else if (ARMMCRegisterClasses[ARM::SPRRegClassID]. 2365263508Sdim contains(Regs.front().second)) 2366226633Sdim Kind = k_SPRRegisterList; 2367218893Sdim 2368263508Sdim // Sort based on the register encoding values. 2369263508Sdim array_pod_sort(Regs.begin(), Regs.end()); 2370263508Sdim 2371218893Sdim ARMOperand *Op = new ARMOperand(Kind); 2372263508Sdim for (SmallVectorImpl<std::pair<unsigned, unsigned> >::const_iterator 2373218893Sdim I = Regs.begin(), E = Regs.end(); I != E; ++I) 2374263508Sdim Op->Registers.push_back(I->second); 2375218893Sdim Op->StartLoc = StartLoc; 2376218893Sdim Op->EndLoc = EndLoc; 2377218893Sdim return Op; 2378218893Sdim } 2379218893Sdim 2380234353Sdim static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count, 2381234353Sdim bool isDoubleSpaced, SMLoc S, SMLoc E) { 2382234353Sdim ARMOperand *Op = new ARMOperand(k_VectorList); 2383234353Sdim Op->VectorList.RegNum = RegNum; 2384234353Sdim Op->VectorList.Count = Count; 2385234353Sdim Op->VectorList.isDoubleSpaced = isDoubleSpaced; 2386234353Sdim Op->StartLoc = S; 2387234353Sdim Op->EndLoc = E; 2388234353Sdim return Op; 2389234353Sdim } 2390234353Sdim 2391234353Sdim static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count, 2392234353Sdim bool isDoubleSpaced, 2393234353Sdim SMLoc S, SMLoc E) { 2394234353Sdim ARMOperand *Op = new ARMOperand(k_VectorListAllLanes); 2395234353Sdim Op->VectorList.RegNum = RegNum; 2396234353Sdim Op->VectorList.Count = Count; 2397234353Sdim Op->VectorList.isDoubleSpaced = isDoubleSpaced; 2398234353Sdim Op->StartLoc = S; 2399234353Sdim Op->EndLoc = E; 2400234353Sdim return Op; 2401234353Sdim } 2402234353Sdim 2403234353Sdim static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count, 2404234353Sdim unsigned Index, 2405234353Sdim bool isDoubleSpaced, 2406234353Sdim SMLoc S, SMLoc E) { 2407234353Sdim ARMOperand *Op = new ARMOperand(k_VectorListIndexed); 2408234353Sdim Op->VectorList.RegNum = RegNum; 2409234353Sdim Op->VectorList.Count = Count; 2410234353Sdim Op->VectorList.LaneIndex = Index; 2411234353Sdim Op->VectorList.isDoubleSpaced = isDoubleSpaced; 2412234353Sdim Op->StartLoc = S; 2413234353Sdim Op->EndLoc = E; 2414234353Sdim return Op; 2415234353Sdim } 2416234353Sdim 2417226633Sdim static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, 2418226633Sdim MCContext &Ctx) { 2419226633Sdim ARMOperand *Op = new ARMOperand(k_VectorIndex); 2420226633Sdim Op->VectorIndex.Val = Idx; 2421226633Sdim Op->StartLoc = S; 2422226633Sdim Op->EndLoc = E; 2423226633Sdim return Op; 2424226633Sdim } 2425226633Sdim 2426218893Sdim static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) { 2427226633Sdim ARMOperand *Op = new ARMOperand(k_Immediate); 2428206124Srdivacky Op->Imm.Val = Val; 2429206124Srdivacky Op->StartLoc = S; 2430206124Srdivacky Op->EndLoc = E; 2431218893Sdim return Op; 2432198090Srdivacky } 2433198090Srdivacky 2434226633Sdim static ARMOperand *CreateMem(unsigned BaseRegNum, 2435226633Sdim const MCConstantExpr *OffsetImm, 2436226633Sdim unsigned OffsetRegNum, 2437226633Sdim ARM_AM::ShiftOpc ShiftType, 2438226633Sdim unsigned ShiftImm, 2439226633Sdim unsigned Alignment, 2440226633Sdim bool isNegative, 2441218893Sdim SMLoc S, SMLoc E) { 2442226633Sdim ARMOperand *Op = new ARMOperand(k_Memory); 2443226633Sdim Op->Memory.BaseRegNum = BaseRegNum; 2444226633Sdim Op->Memory.OffsetImm = OffsetImm; 2445226633Sdim Op->Memory.OffsetRegNum = OffsetRegNum; 2446226633Sdim Op->Memory.ShiftType = ShiftType; 2447226633Sdim Op->Memory.ShiftImm = ShiftImm; 2448226633Sdim Op->Memory.Alignment = Alignment; 2449226633Sdim Op->Memory.isNegative = isNegative; 2450226633Sdim Op->StartLoc = S; 2451226633Sdim Op->EndLoc = E; 2452226633Sdim return Op; 2453226633Sdim } 2454218893Sdim 2455226633Sdim static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd, 2456226633Sdim ARM_AM::ShiftOpc ShiftTy, 2457226633Sdim unsigned ShiftImm, 2458226633Sdim SMLoc S, SMLoc E) { 2459226633Sdim ARMOperand *Op = new ARMOperand(k_PostIndexRegister); 2460226633Sdim Op->PostIdxReg.RegNum = RegNum; 2461226633Sdim Op->PostIdxReg.isAdd = isAdd; 2462226633Sdim Op->PostIdxReg.ShiftTy = ShiftTy; 2463226633Sdim Op->PostIdxReg.ShiftImm = ShiftImm; 2464206124Srdivacky Op->StartLoc = S; 2465206124Srdivacky Op->EndLoc = E; 2466218893Sdim return Op; 2467198090Srdivacky } 2468218893Sdim 2469218893Sdim static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) { 2470226633Sdim ARMOperand *Op = new ARMOperand(k_MemBarrierOpt); 2471218893Sdim Op->MBOpt.Val = Opt; 2472218893Sdim Op->StartLoc = S; 2473218893Sdim Op->EndLoc = S; 2474218893Sdim return Op; 2475218893Sdim } 2476218893Sdim 2477263508Sdim static ARMOperand *CreateInstSyncBarrierOpt(ARM_ISB::InstSyncBOpt Opt, 2478263508Sdim SMLoc S) { 2479263508Sdim ARMOperand *Op = new ARMOperand(k_InstSyncBarrierOpt); 2480263508Sdim Op->ISBOpt.Val = Opt; 2481263508Sdim Op->StartLoc = S; 2482263508Sdim Op->EndLoc = S; 2483263508Sdim return Op; 2484263508Sdim } 2485263508Sdim 2486218893Sdim static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) { 2487226633Sdim ARMOperand *Op = new ARMOperand(k_ProcIFlags); 2488218893Sdim Op->IFlags.Val = IFlags; 2489218893Sdim Op->StartLoc = S; 2490218893Sdim Op->EndLoc = S; 2491218893Sdim return Op; 2492218893Sdim } 2493218893Sdim 2494218893Sdim static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) { 2495226633Sdim ARMOperand *Op = new ARMOperand(k_MSRMask); 2496218893Sdim Op->MMask.Val = MMask; 2497218893Sdim Op->StartLoc = S; 2498218893Sdim Op->EndLoc = S; 2499218893Sdim return Op; 2500218893Sdim } 2501198090Srdivacky}; 2502198090Srdivacky 2503198090Srdivacky} // end anonymous namespace. 2504198090Srdivacky 2505224145Sdimvoid ARMOperand::print(raw_ostream &OS) const { 2506212904Sdim switch (Kind) { 2507226633Sdim case k_CondCode: 2508218893Sdim OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">"; 2509212904Sdim break; 2510226633Sdim case k_CCOut: 2511218893Sdim OS << "<ccout " << getReg() << ">"; 2512218893Sdim break; 2513226633Sdim case k_ITCondMask: { 2514239462Sdim static const char *const MaskStr[] = { 2515234353Sdim "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)", 2516234353Sdim "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)" 2517234353Sdim }; 2518226633Sdim assert((ITMask.Mask & 0xf) == ITMask.Mask); 2519226633Sdim OS << "<it-mask " << MaskStr[ITMask.Mask] << ">"; 2520226633Sdim break; 2521226633Sdim } 2522226633Sdim case k_CoprocNum: 2523218893Sdim OS << "<coprocessor number: " << getCoproc() << ">"; 2524218893Sdim break; 2525226633Sdim case k_CoprocReg: 2526218893Sdim OS << "<coprocessor register: " << getCoproc() << ">"; 2527218893Sdim break; 2528226633Sdim case k_CoprocOption: 2529226633Sdim OS << "<coprocessor option: " << CoprocOption.Val << ">"; 2530226633Sdim break; 2531226633Sdim case k_MSRMask: 2532218893Sdim OS << "<mask: " << getMSRMask() << ">"; 2533218893Sdim break; 2534226633Sdim case k_Immediate: 2535212904Sdim getImm()->print(OS); 2536212904Sdim break; 2537226633Sdim case k_MemBarrierOpt: 2538263508Sdim OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt(), false) << ">"; 2539218893Sdim break; 2540263508Sdim case k_InstSyncBarrierOpt: 2541263508Sdim OS << "<ARM_ISB::" << InstSyncBOptToString(getInstSyncBarrierOpt()) << ">"; 2542263508Sdim break; 2543226633Sdim case k_Memory: 2544218893Sdim OS << "<memory " 2545226633Sdim << " base:" << Memory.BaseRegNum; 2546218893Sdim OS << ">"; 2547212904Sdim break; 2548226633Sdim case k_PostIndexRegister: 2549226633Sdim OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-") 2550226633Sdim << PostIdxReg.RegNum; 2551226633Sdim if (PostIdxReg.ShiftTy != ARM_AM::no_shift) 2552226633Sdim OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " " 2553226633Sdim << PostIdxReg.ShiftImm; 2554226633Sdim OS << ">"; 2555226633Sdim break; 2556226633Sdim case k_ProcIFlags: { 2557218893Sdim OS << "<ARM_PROC::"; 2558218893Sdim unsigned IFlags = getProcIFlags(); 2559218893Sdim for (int i=2; i >= 0; --i) 2560218893Sdim if (IFlags & (1 << i)) 2561218893Sdim OS << ARM_PROC::IFlagsToString(1 << i); 2562218893Sdim OS << ">"; 2563218893Sdim break; 2564218893Sdim } 2565226633Sdim case k_Register: 2566212904Sdim OS << "<register " << getReg() << ">"; 2567212904Sdim break; 2568226633Sdim case k_ShifterImmediate: 2569226633Sdim OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl") 2570226633Sdim << " #" << ShifterImm.Imm << ">"; 2571221345Sdim break; 2572226633Sdim case k_ShiftedRegister: 2573226633Sdim OS << "<so_reg_reg " 2574234353Sdim << RegShiftedReg.SrcReg << " " 2575234353Sdim << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy) 2576234353Sdim << " " << RegShiftedReg.ShiftReg << ">"; 2577224145Sdim break; 2578226633Sdim case k_ShiftedImmediate: 2579226633Sdim OS << "<so_reg_imm " 2580234353Sdim << RegShiftedImm.SrcReg << " " 2581234353Sdim << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy) 2582234353Sdim << " #" << RegShiftedImm.ShiftImm << ">"; 2583226633Sdim break; 2584226633Sdim case k_RotateImmediate: 2585226633Sdim OS << "<ror " << " #" << (RotImm.Imm * 8) << ">"; 2586226633Sdim break; 2587226633Sdim case k_BitfieldDescriptor: 2588226633Sdim OS << "<bitfield " << "lsb: " << Bitfield.LSB 2589226633Sdim << ", width: " << Bitfield.Width << ">"; 2590226633Sdim break; 2591226633Sdim case k_RegisterList: 2592226633Sdim case k_DPRRegisterList: 2593226633Sdim case k_SPRRegisterList: { 2594218893Sdim OS << "<register_list "; 2595218893Sdim 2596218893Sdim const SmallVectorImpl<unsigned> &RegList = getRegList(); 2597218893Sdim for (SmallVectorImpl<unsigned>::const_iterator 2598218893Sdim I = RegList.begin(), E = RegList.end(); I != E; ) { 2599218893Sdim OS << *I; 2600218893Sdim if (++I < E) OS << ", "; 2601218893Sdim } 2602218893Sdim 2603218893Sdim OS << ">"; 2604218893Sdim break; 2605218893Sdim } 2606234353Sdim case k_VectorList: 2607234353Sdim OS << "<vector_list " << VectorList.Count << " * " 2608234353Sdim << VectorList.RegNum << ">"; 2609234353Sdim break; 2610234353Sdim case k_VectorListAllLanes: 2611234353Sdim OS << "<vector_list(all lanes) " << VectorList.Count << " * " 2612234353Sdim << VectorList.RegNum << ">"; 2613234353Sdim break; 2614234353Sdim case k_VectorListIndexed: 2615234353Sdim OS << "<vector_list(lane " << VectorList.LaneIndex << ") " 2616234353Sdim << VectorList.Count << " * " << VectorList.RegNum << ">"; 2617234353Sdim break; 2618226633Sdim case k_Token: 2619212904Sdim OS << "'" << getToken() << "'"; 2620212904Sdim break; 2621226633Sdim case k_VectorIndex: 2622226633Sdim OS << "<vectorindex " << getVectorIndex() << ">"; 2623226633Sdim break; 2624212904Sdim } 2625212904Sdim} 2626212904Sdim 2627212904Sdim/// @name Auto-generated Match Functions 2628212904Sdim/// { 2629212904Sdim 2630212904Sdimstatic unsigned MatchRegisterName(StringRef Name); 2631212904Sdim 2632212904Sdim/// } 2633212904Sdim 2634218893Sdimbool ARMAsmParser::ParseRegister(unsigned &RegNo, 2635218893Sdim SMLoc &StartLoc, SMLoc &EndLoc) { 2636234353Sdim StartLoc = Parser.getTok().getLoc(); 2637249423Sdim EndLoc = Parser.getTok().getEndLoc(); 2638226633Sdim RegNo = tryParseRegister(); 2639218893Sdim 2640218893Sdim return (RegNo == (unsigned)-1); 2641218893Sdim} 2642218893Sdim 2643198892Srdivacky/// Try to parse a register name. The token must be an Identifier when called, 2644218893Sdim/// and if it is a register name the token is eaten and the register number is 2645218893Sdim/// returned. Otherwise return -1. 2646218893Sdim/// 2647226633Sdimint ARMAsmParser::tryParseRegister() { 2648202878Srdivacky const AsmToken &Tok = Parser.getTok(); 2649226633Sdim if (Tok.isNot(AsmToken::Identifier)) return -1; 2650198090Srdivacky 2651234353Sdim std::string lowerCase = Tok.getString().lower(); 2652218893Sdim unsigned RegNum = MatchRegisterName(lowerCase); 2653218893Sdim if (!RegNum) { 2654218893Sdim RegNum = StringSwitch<unsigned>(lowerCase) 2655218893Sdim .Case("r13", ARM::SP) 2656218893Sdim .Case("r14", ARM::LR) 2657218893Sdim .Case("r15", ARM::PC) 2658218893Sdim .Case("ip", ARM::R12) 2659234353Sdim // Additional register name aliases for 'gas' compatibility. 2660234353Sdim .Case("a1", ARM::R0) 2661234353Sdim .Case("a2", ARM::R1) 2662234353Sdim .Case("a3", ARM::R2) 2663234353Sdim .Case("a4", ARM::R3) 2664234353Sdim .Case("v1", ARM::R4) 2665234353Sdim .Case("v2", ARM::R5) 2666234353Sdim .Case("v3", ARM::R6) 2667234353Sdim .Case("v4", ARM::R7) 2668234353Sdim .Case("v5", ARM::R8) 2669234353Sdim .Case("v6", ARM::R9) 2670234353Sdim .Case("v7", ARM::R10) 2671234353Sdim .Case("v8", ARM::R11) 2672234353Sdim .Case("sb", ARM::R9) 2673234353Sdim .Case("sl", ARM::R10) 2674234353Sdim .Case("fp", ARM::R11) 2675218893Sdim .Default(0); 2676218893Sdim } 2677234353Sdim if (!RegNum) { 2678234353Sdim // Check for aliases registered via .req. Canonicalize to lower case. 2679234353Sdim // That's more consistent since register names are case insensitive, and 2680234353Sdim // it's how the original entry was passed in from MC/MCParser/AsmParser. 2681234353Sdim StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase); 2682234353Sdim // If no match, return failure. 2683234353Sdim if (Entry == RegisterReqs.end()) 2684234353Sdim return -1; 2685234353Sdim Parser.Lex(); // Eat identifier token. 2686234353Sdim return Entry->getValue(); 2687234353Sdim } 2688198090Srdivacky 2689202878Srdivacky Parser.Lex(); // Eat identifier token. 2690226633Sdim 2691218893Sdim return RegNum; 2692218893Sdim} 2693198090Srdivacky 2694224145Sdim// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0. 2695224145Sdim// If a recoverable error occurs, return 1. If an irrecoverable error 2696224145Sdim// occurs, return -1. An irrecoverable error is one where tokens have been 2697224145Sdim// consumed in the process of trying to parse the shifter (i.e., when it is 2698224145Sdim// indeed a shifter operand, but malformed). 2699226633Sdimint ARMAsmParser::tryParseShiftRegister( 2700221345Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 2701221345Sdim SMLoc S = Parser.getTok().getLoc(); 2702221345Sdim const AsmToken &Tok = Parser.getTok(); 2703221345Sdim assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); 2704221345Sdim 2705234353Sdim std::string lowerCase = Tok.getString().lower(); 2706221345Sdim ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase) 2707234353Sdim .Case("asl", ARM_AM::lsl) 2708221345Sdim .Case("lsl", ARM_AM::lsl) 2709221345Sdim .Case("lsr", ARM_AM::lsr) 2710221345Sdim .Case("asr", ARM_AM::asr) 2711221345Sdim .Case("ror", ARM_AM::ror) 2712221345Sdim .Case("rrx", ARM_AM::rrx) 2713221345Sdim .Default(ARM_AM::no_shift); 2714221345Sdim 2715221345Sdim if (ShiftTy == ARM_AM::no_shift) 2716224145Sdim return 1; 2717221345Sdim 2718224145Sdim Parser.Lex(); // Eat the operator. 2719221345Sdim 2720224145Sdim // The source register for the shift has already been added to the 2721224145Sdim // operand list, so we need to pop it off and combine it into the shifted 2722224145Sdim // register operand instead. 2723224145Sdim OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val()); 2724224145Sdim if (!PrevOp->isReg()) 2725224145Sdim return Error(PrevOp->getStartLoc(), "shift must be of a register"); 2726224145Sdim int SrcReg = PrevOp->getReg(); 2727249423Sdim 2728249423Sdim SMLoc EndLoc; 2729224145Sdim int64_t Imm = 0; 2730224145Sdim int ShiftReg = 0; 2731224145Sdim if (ShiftTy == ARM_AM::rrx) { 2732224145Sdim // RRX Doesn't have an explicit shift amount. The encoder expects 2733224145Sdim // the shift register to be the same as the source register. Seems odd, 2734224145Sdim // but OK. 2735224145Sdim ShiftReg = SrcReg; 2736224145Sdim } else { 2737224145Sdim // Figure out if this is shifted by a constant or a register (for non-RRX). 2738234353Sdim if (Parser.getTok().is(AsmToken::Hash) || 2739234353Sdim Parser.getTok().is(AsmToken::Dollar)) { 2740224145Sdim Parser.Lex(); // Eat hash. 2741224145Sdim SMLoc ImmLoc = Parser.getTok().getLoc(); 2742224145Sdim const MCExpr *ShiftExpr = 0; 2743249423Sdim if (getParser().parseExpression(ShiftExpr, EndLoc)) { 2744224145Sdim Error(ImmLoc, "invalid immediate shift value"); 2745224145Sdim return -1; 2746224145Sdim } 2747224145Sdim // The expression must be evaluatable as an immediate. 2748224145Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr); 2749224145Sdim if (!CE) { 2750224145Sdim Error(ImmLoc, "invalid immediate shift value"); 2751224145Sdim return -1; 2752224145Sdim } 2753224145Sdim // Range check the immediate. 2754224145Sdim // lsl, ror: 0 <= imm <= 31 2755224145Sdim // lsr, asr: 0 <= imm <= 32 2756224145Sdim Imm = CE->getValue(); 2757224145Sdim if (Imm < 0 || 2758224145Sdim ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) || 2759224145Sdim ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) { 2760224145Sdim Error(ImmLoc, "immediate shift value out of range"); 2761224145Sdim return -1; 2762224145Sdim } 2763234353Sdim // shift by zero is a nop. Always send it through as lsl. 2764234353Sdim // ('as' compatibility) 2765234353Sdim if (Imm == 0) 2766234353Sdim ShiftTy = ARM_AM::lsl; 2767224145Sdim } else if (Parser.getTok().is(AsmToken::Identifier)) { 2768249423Sdim SMLoc L = Parser.getTok().getLoc(); 2769249423Sdim EndLoc = Parser.getTok().getEndLoc(); 2770226633Sdim ShiftReg = tryParseRegister(); 2771224145Sdim if (ShiftReg == -1) { 2772224145Sdim Error (L, "expected immediate or register in shift operand"); 2773224145Sdim return -1; 2774224145Sdim } 2775224145Sdim } else { 2776224145Sdim Error (Parser.getTok().getLoc(), 2777224145Sdim "expected immediate or register in shift operand"); 2778224145Sdim return -1; 2779224145Sdim } 2780224145Sdim } 2781224145Sdim 2782226633Sdim if (ShiftReg && ShiftTy != ARM_AM::rrx) 2783226633Sdim Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg, 2784226633Sdim ShiftReg, Imm, 2785249423Sdim S, EndLoc)); 2786226633Sdim else 2787226633Sdim Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm, 2788249423Sdim S, EndLoc)); 2789221345Sdim 2790224145Sdim return 0; 2791221345Sdim} 2792221345Sdim 2793221345Sdim 2794218893Sdim/// Try to parse a register name. The token must be an Identifier when called. 2795218893Sdim/// If it's a register, an AsmOperand is created. Another AsmOperand is created 2796218893Sdim/// if there is a "writeback". 'true' if it's not a register. 2797218893Sdim/// 2798218893Sdim/// TODO this is likely to change to allow different register types and or to 2799218893Sdim/// parse for a specific register type. 2800218893Sdimbool ARMAsmParser:: 2801226633SdimtryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 2802249423Sdim const AsmToken &RegTok = Parser.getTok(); 2803226633Sdim int RegNo = tryParseRegister(); 2804218893Sdim if (RegNo == -1) 2805218893Sdim return true; 2806218893Sdim 2807249423Sdim Operands.push_back(ARMOperand::CreateReg(RegNo, RegTok.getLoc(), 2808249423Sdim RegTok.getEndLoc())); 2809218893Sdim 2810218893Sdim const AsmToken &ExclaimTok = Parser.getTok(); 2811218893Sdim if (ExclaimTok.is(AsmToken::Exclaim)) { 2812218893Sdim Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(), 2813218893Sdim ExclaimTok.getLoc())); 2814218893Sdim Parser.Lex(); // Eat exclaim token 2815226633Sdim return false; 2816218893Sdim } 2817218893Sdim 2818226633Sdim // Also check for an index operand. This is only legal for vector registers, 2819226633Sdim // but that'll get caught OK in operand matching, so we don't need to 2820226633Sdim // explicitly filter everything else out here. 2821226633Sdim if (Parser.getTok().is(AsmToken::LBrac)) { 2822226633Sdim SMLoc SIdx = Parser.getTok().getLoc(); 2823226633Sdim Parser.Lex(); // Eat left bracket token. 2824226633Sdim 2825226633Sdim const MCExpr *ImmVal; 2826249423Sdim if (getParser().parseExpression(ImmVal)) 2827234353Sdim return true; 2828226633Sdim const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal); 2829234353Sdim if (!MCE) 2830234353Sdim return TokError("immediate value expected for vector index"); 2831226633Sdim 2832234353Sdim if (Parser.getTok().isNot(AsmToken::RBrac)) 2833249423Sdim return Error(Parser.getTok().getLoc(), "']' expected"); 2834226633Sdim 2835249423Sdim SMLoc E = Parser.getTok().getEndLoc(); 2836226633Sdim Parser.Lex(); // Eat right bracket token. 2837226633Sdim 2838226633Sdim Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(), 2839226633Sdim SIdx, E, 2840226633Sdim getContext())); 2841226633Sdim } 2842226633Sdim 2843218893Sdim return false; 2844218893Sdim} 2845218893Sdim 2846218893Sdim/// MatchCoprocessorOperandName - Try to parse an coprocessor related 2847218893Sdim/// instruction with a symbolic operand name. Example: "p1", "p7", "c3", 2848218893Sdim/// "c5", ... 2849218893Sdimstatic int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) { 2850218893Sdim // Use the same layout as the tablegen'erated register name matcher. Ugly, 2851218893Sdim // but efficient. 2852218893Sdim switch (Name.size()) { 2853234353Sdim default: return -1; 2854218893Sdim case 2: 2855218893Sdim if (Name[0] != CoprocOp) 2856218893Sdim return -1; 2857218893Sdim switch (Name[1]) { 2858218893Sdim default: return -1; 2859218893Sdim case '0': return 0; 2860218893Sdim case '1': return 1; 2861218893Sdim case '2': return 2; 2862218893Sdim case '3': return 3; 2863218893Sdim case '4': return 4; 2864218893Sdim case '5': return 5; 2865218893Sdim case '6': return 6; 2866218893Sdim case '7': return 7; 2867218893Sdim case '8': return 8; 2868218893Sdim case '9': return 9; 2869198892Srdivacky } 2870218893Sdim case 3: 2871218893Sdim if (Name[0] != CoprocOp || Name[1] != '1') 2872218893Sdim return -1; 2873218893Sdim switch (Name[2]) { 2874218893Sdim default: return -1; 2875263508Sdim // p10 and p11 are invalid for coproc instructions (reserved for FP/NEON) 2876263508Sdim case '0': return CoprocOp == 'p'? -1: 10; 2877263508Sdim case '1': return CoprocOp == 'p'? -1: 11; 2878218893Sdim case '2': return 12; 2879218893Sdim case '3': return 13; 2880218893Sdim case '4': return 14; 2881218893Sdim case '5': return 15; 2882218893Sdim } 2883198090Srdivacky } 2884218893Sdim} 2885198090Srdivacky 2886226633Sdim/// parseITCondCode - Try to parse a condition code for an IT instruction. 2887226633SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 2888226633SdimparseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 2889226633Sdim SMLoc S = Parser.getTok().getLoc(); 2890226633Sdim const AsmToken &Tok = Parser.getTok(); 2891226633Sdim if (!Tok.is(AsmToken::Identifier)) 2892226633Sdim return MatchOperand_NoMatch; 2893239462Sdim unsigned CC = StringSwitch<unsigned>(Tok.getString().lower()) 2894226633Sdim .Case("eq", ARMCC::EQ) 2895226633Sdim .Case("ne", ARMCC::NE) 2896226633Sdim .Case("hs", ARMCC::HS) 2897226633Sdim .Case("cs", ARMCC::HS) 2898226633Sdim .Case("lo", ARMCC::LO) 2899226633Sdim .Case("cc", ARMCC::LO) 2900226633Sdim .Case("mi", ARMCC::MI) 2901226633Sdim .Case("pl", ARMCC::PL) 2902226633Sdim .Case("vs", ARMCC::VS) 2903226633Sdim .Case("vc", ARMCC::VC) 2904226633Sdim .Case("hi", ARMCC::HI) 2905226633Sdim .Case("ls", ARMCC::LS) 2906226633Sdim .Case("ge", ARMCC::GE) 2907226633Sdim .Case("lt", ARMCC::LT) 2908226633Sdim .Case("gt", ARMCC::GT) 2909226633Sdim .Case("le", ARMCC::LE) 2910226633Sdim .Case("al", ARMCC::AL) 2911226633Sdim .Default(~0U); 2912226633Sdim if (CC == ~0U) 2913226633Sdim return MatchOperand_NoMatch; 2914226633Sdim Parser.Lex(); // Eat the token. 2915226633Sdim 2916226633Sdim Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S)); 2917226633Sdim 2918226633Sdim return MatchOperand_Success; 2919226633Sdim} 2920226633Sdim 2921226633Sdim/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The 2922218893Sdim/// token must be an Identifier when called, and if it is a coprocessor 2923218893Sdim/// number, the token is eaten and the operand is added to the operand list. 2924218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 2925226633SdimparseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 2926218893Sdim SMLoc S = Parser.getTok().getLoc(); 2927218893Sdim const AsmToken &Tok = Parser.getTok(); 2928226633Sdim if (Tok.isNot(AsmToken::Identifier)) 2929226633Sdim return MatchOperand_NoMatch; 2930218893Sdim 2931218893Sdim int Num = MatchCoprocessorOperandName(Tok.getString(), 'p'); 2932218893Sdim if (Num == -1) 2933218893Sdim return MatchOperand_NoMatch; 2934218893Sdim 2935218893Sdim Parser.Lex(); // Eat identifier token. 2936218893Sdim Operands.push_back(ARMOperand::CreateCoprocNum(Num, S)); 2937218893Sdim return MatchOperand_Success; 2938198090Srdivacky} 2939198090Srdivacky 2940226633Sdim/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The 2941218893Sdim/// token must be an Identifier when called, and if it is a coprocessor 2942218893Sdim/// number, the token is eaten and the operand is added to the operand list. 2943218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 2944226633SdimparseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 2945218893Sdim SMLoc S = Parser.getTok().getLoc(); 2946218893Sdim const AsmToken &Tok = Parser.getTok(); 2947226633Sdim if (Tok.isNot(AsmToken::Identifier)) 2948226633Sdim return MatchOperand_NoMatch; 2949198090Srdivacky 2950218893Sdim int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c'); 2951218893Sdim if (Reg == -1) 2952218893Sdim return MatchOperand_NoMatch; 2953218893Sdim 2954202878Srdivacky Parser.Lex(); // Eat identifier token. 2955218893Sdim Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S)); 2956218893Sdim return MatchOperand_Success; 2957218893Sdim} 2958198090Srdivacky 2959226633Sdim/// parseCoprocOptionOperand - Try to parse an coprocessor option operand. 2960226633Sdim/// coproc_option : '{' imm0_255 '}' 2961226633SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 2962226633SdimparseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 2963218893Sdim SMLoc S = Parser.getTok().getLoc(); 2964198090Srdivacky 2965226633Sdim // If this isn't a '{', this isn't a coprocessor immediate operand. 2966226633Sdim if (Parser.getTok().isNot(AsmToken::LCurly)) 2967226633Sdim return MatchOperand_NoMatch; 2968226633Sdim Parser.Lex(); // Eat the '{' 2969218893Sdim 2970226633Sdim const MCExpr *Expr; 2971226633Sdim SMLoc Loc = Parser.getTok().getLoc(); 2972249423Sdim if (getParser().parseExpression(Expr)) { 2973226633Sdim Error(Loc, "illegal expression"); 2974226633Sdim return MatchOperand_ParseFail; 2975226633Sdim } 2976226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr); 2977226633Sdim if (!CE || CE->getValue() < 0 || CE->getValue() > 255) { 2978226633Sdim Error(Loc, "coprocessor option must be an immediate in range [0, 255]"); 2979226633Sdim return MatchOperand_ParseFail; 2980226633Sdim } 2981226633Sdim int Val = CE->getValue(); 2982218893Sdim 2983226633Sdim // Check for and consume the closing '}' 2984226633Sdim if (Parser.getTok().isNot(AsmToken::RCurly)) 2985226633Sdim return MatchOperand_ParseFail; 2986249423Sdim SMLoc E = Parser.getTok().getEndLoc(); 2987226633Sdim Parser.Lex(); // Eat the '}' 2988198090Srdivacky 2989226633Sdim Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E)); 2990226633Sdim return MatchOperand_Success; 2991226633Sdim} 2992198090Srdivacky 2993226633Sdim// For register list parsing, we need to map from raw GPR register numbering 2994226633Sdim// to the enumeration values. The enumeration values aren't sorted by 2995226633Sdim// register number due to our using "sp", "lr" and "pc" as canonical names. 2996226633Sdimstatic unsigned getNextRegister(unsigned Reg) { 2997226633Sdim // If this is a GPR, we need to do it manually, otherwise we can rely 2998226633Sdim // on the sort ordering of the enumeration since the other reg-classes 2999226633Sdim // are sane. 3000226633Sdim if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg)) 3001226633Sdim return Reg + 1; 3002226633Sdim switch(Reg) { 3003234353Sdim default: llvm_unreachable("Invalid GPR number!"); 3004226633Sdim case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2; 3005226633Sdim case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4; 3006226633Sdim case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6; 3007226633Sdim case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8; 3008226633Sdim case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10; 3009226633Sdim case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12; 3010226633Sdim case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR; 3011226633Sdim case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0; 3012198090Srdivacky } 3013226633Sdim} 3014198090Srdivacky 3015234353Sdim// Return the low-subreg of a given Q register. 3016234353Sdimstatic unsigned getDRegFromQReg(unsigned QReg) { 3017234353Sdim switch (QReg) { 3018234353Sdim default: llvm_unreachable("expected a Q register!"); 3019234353Sdim case ARM::Q0: return ARM::D0; 3020234353Sdim case ARM::Q1: return ARM::D2; 3021234353Sdim case ARM::Q2: return ARM::D4; 3022234353Sdim case ARM::Q3: return ARM::D6; 3023234353Sdim case ARM::Q4: return ARM::D8; 3024234353Sdim case ARM::Q5: return ARM::D10; 3025234353Sdim case ARM::Q6: return ARM::D12; 3026234353Sdim case ARM::Q7: return ARM::D14; 3027234353Sdim case ARM::Q8: return ARM::D16; 3028234353Sdim case ARM::Q9: return ARM::D18; 3029234353Sdim case ARM::Q10: return ARM::D20; 3030234353Sdim case ARM::Q11: return ARM::D22; 3031234353Sdim case ARM::Q12: return ARM::D24; 3032234353Sdim case ARM::Q13: return ARM::D26; 3033234353Sdim case ARM::Q14: return ARM::D28; 3034234353Sdim case ARM::Q15: return ARM::D30; 3035234353Sdim } 3036234353Sdim} 3037234353Sdim 3038226633Sdim/// Parse a register list. 3039226633Sdimbool ARMAsmParser:: 3040226633SdimparseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 3041226633Sdim assert(Parser.getTok().is(AsmToken::LCurly) && 3042226633Sdim "Token is not a Left Curly Brace"); 3043226633Sdim SMLoc S = Parser.getTok().getLoc(); 3044226633Sdim Parser.Lex(); // Eat '{' token. 3045226633Sdim SMLoc RegLoc = Parser.getTok().getLoc(); 3046218893Sdim 3047226633Sdim // Check the first register in the list to see what register class 3048226633Sdim // this is a list of. 3049226633Sdim int Reg = tryParseRegister(); 3050226633Sdim if (Reg == -1) 3051226633Sdim return Error(RegLoc, "register expected"); 3052218893Sdim 3053234353Sdim // The reglist instructions have at most 16 registers, so reserve 3054234353Sdim // space for that many. 3055263508Sdim int EReg = 0; 3056263508Sdim SmallVector<std::pair<unsigned, unsigned>, 16> Registers; 3057234353Sdim 3058234353Sdim // Allow Q regs and just interpret them as the two D sub-registers. 3059234353Sdim if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { 3060234353Sdim Reg = getDRegFromQReg(Reg); 3061263508Sdim EReg = MRI->getEncodingValue(Reg); 3062263508Sdim Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg)); 3063234353Sdim ++Reg; 3064234353Sdim } 3065234353Sdim const MCRegisterClass *RC; 3066226633Sdim if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg)) 3067226633Sdim RC = &ARMMCRegisterClasses[ARM::GPRRegClassID]; 3068226633Sdim else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) 3069226633Sdim RC = &ARMMCRegisterClasses[ARM::DPRRegClassID]; 3070226633Sdim else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg)) 3071226633Sdim RC = &ARMMCRegisterClasses[ARM::SPRRegClassID]; 3072226633Sdim else 3073226633Sdim return Error(RegLoc, "invalid register in register list"); 3074218893Sdim 3075234353Sdim // Store the register. 3076263508Sdim EReg = MRI->getEncodingValue(Reg); 3077263508Sdim Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg)); 3078218893Sdim 3079226633Sdim // This starts immediately after the first register token in the list, 3080226633Sdim // so we can see either a comma or a minus (range separator) as a legal 3081226633Sdim // next token. 3082226633Sdim while (Parser.getTok().is(AsmToken::Comma) || 3083226633Sdim Parser.getTok().is(AsmToken::Minus)) { 3084226633Sdim if (Parser.getTok().is(AsmToken::Minus)) { 3085234353Sdim Parser.Lex(); // Eat the minus. 3086249423Sdim SMLoc AfterMinusLoc = Parser.getTok().getLoc(); 3087226633Sdim int EndReg = tryParseRegister(); 3088226633Sdim if (EndReg == -1) 3089249423Sdim return Error(AfterMinusLoc, "register expected"); 3090234353Sdim // Allow Q regs and just interpret them as the two D sub-registers. 3091234353Sdim if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg)) 3092234353Sdim EndReg = getDRegFromQReg(EndReg) + 1; 3093226633Sdim // If the register is the same as the start reg, there's nothing 3094226633Sdim // more to do. 3095226633Sdim if (Reg == EndReg) 3096226633Sdim continue; 3097226633Sdim // The register must be in the same register class as the first. 3098226633Sdim if (!RC->contains(EndReg)) 3099249423Sdim return Error(AfterMinusLoc, "invalid register in register list"); 3100226633Sdim // Ranges must go from low to high. 3101239462Sdim if (MRI->getEncodingValue(Reg) > MRI->getEncodingValue(EndReg)) 3102249423Sdim return Error(AfterMinusLoc, "bad range in register list"); 3103218893Sdim 3104226633Sdim // Add all the registers in the range to the register list. 3105226633Sdim while (Reg != EndReg) { 3106226633Sdim Reg = getNextRegister(Reg); 3107263508Sdim EReg = MRI->getEncodingValue(Reg); 3108263508Sdim Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg)); 3109226633Sdim } 3110226633Sdim continue; 3111218893Sdim } 3112226633Sdim Parser.Lex(); // Eat the comma. 3113226633Sdim RegLoc = Parser.getTok().getLoc(); 3114226633Sdim int OldReg = Reg; 3115234353Sdim const AsmToken RegTok = Parser.getTok(); 3116226633Sdim Reg = tryParseRegister(); 3117226633Sdim if (Reg == -1) 3118226633Sdim return Error(RegLoc, "register expected"); 3119234353Sdim // Allow Q regs and just interpret them as the two D sub-registers. 3120234353Sdim bool isQReg = false; 3121234353Sdim if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { 3122234353Sdim Reg = getDRegFromQReg(Reg); 3123234353Sdim isQReg = true; 3124234353Sdim } 3125226633Sdim // The register must be in the same register class as the first. 3126226633Sdim if (!RC->contains(Reg)) 3127226633Sdim return Error(RegLoc, "invalid register in register list"); 3128226633Sdim // List must be monotonically increasing. 3129239462Sdim if (MRI->getEncodingValue(Reg) < MRI->getEncodingValue(OldReg)) { 3130234353Sdim if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg)) 3131234353Sdim Warning(RegLoc, "register list not in ascending order"); 3132234353Sdim else 3133234353Sdim return Error(RegLoc, "register list not in ascending order"); 3134234353Sdim } 3135239462Sdim if (MRI->getEncodingValue(Reg) == MRI->getEncodingValue(OldReg)) { 3136234353Sdim Warning(RegLoc, "duplicated register (" + RegTok.getString() + 3137234353Sdim ") in register list"); 3138234353Sdim continue; 3139234353Sdim } 3140226633Sdim // VFP register lists must also be contiguous. 3141226633Sdim if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] && 3142226633Sdim Reg != OldReg + 1) 3143226633Sdim return Error(RegLoc, "non-contiguous register range"); 3144263508Sdim EReg = MRI->getEncodingValue(Reg); 3145263508Sdim Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg)); 3146263508Sdim if (isQReg) { 3147263508Sdim EReg = MRI->getEncodingValue(++Reg); 3148263508Sdim Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg)); 3149263508Sdim } 3150226633Sdim } 3151218893Sdim 3152226633Sdim if (Parser.getTok().isNot(AsmToken::RCurly)) 3153249423Sdim return Error(Parser.getTok().getLoc(), "'}' expected"); 3154249423Sdim SMLoc E = Parser.getTok().getEndLoc(); 3155226633Sdim Parser.Lex(); // Eat '}' token. 3156218893Sdim 3157234353Sdim // Push the register list operand. 3158218893Sdim Operands.push_back(ARMOperand::CreateRegList(Registers, S, E)); 3159234353Sdim 3160234353Sdim // The ARM system instruction variants for LDM/STM have a '^' token here. 3161234353Sdim if (Parser.getTok().is(AsmToken::Caret)) { 3162234353Sdim Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc())); 3163234353Sdim Parser.Lex(); // Eat '^' token. 3164234353Sdim } 3165234353Sdim 3166198090Srdivacky return false; 3167198090Srdivacky} 3168198090Srdivacky 3169234353Sdim// Helper function to parse the lane index for vector lists. 3170234353SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 3171249423SdimparseVectorLane(VectorLaneTy &LaneKind, unsigned &Index, SMLoc &EndLoc) { 3172234353Sdim Index = 0; // Always return a defined index value. 3173234353Sdim if (Parser.getTok().is(AsmToken::LBrac)) { 3174234353Sdim Parser.Lex(); // Eat the '['. 3175234353Sdim if (Parser.getTok().is(AsmToken::RBrac)) { 3176234353Sdim // "Dn[]" is the 'all lanes' syntax. 3177234353Sdim LaneKind = AllLanes; 3178249423Sdim EndLoc = Parser.getTok().getEndLoc(); 3179234353Sdim Parser.Lex(); // Eat the ']'. 3180234353Sdim return MatchOperand_Success; 3181234353Sdim } 3182234353Sdim 3183234353Sdim // There's an optional '#' token here. Normally there wouldn't be, but 3184234353Sdim // inline assemble puts one in, and it's friendly to accept that. 3185234353Sdim if (Parser.getTok().is(AsmToken::Hash)) 3186263508Sdim Parser.Lex(); // Eat '#' or '$'. 3187234353Sdim 3188234353Sdim const MCExpr *LaneIndex; 3189234353Sdim SMLoc Loc = Parser.getTok().getLoc(); 3190249423Sdim if (getParser().parseExpression(LaneIndex)) { 3191234353Sdim Error(Loc, "illegal expression"); 3192234353Sdim return MatchOperand_ParseFail; 3193234353Sdim } 3194234353Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex); 3195234353Sdim if (!CE) { 3196234353Sdim Error(Loc, "lane index must be empty or an integer"); 3197234353Sdim return MatchOperand_ParseFail; 3198234353Sdim } 3199234353Sdim if (Parser.getTok().isNot(AsmToken::RBrac)) { 3200234353Sdim Error(Parser.getTok().getLoc(), "']' expected"); 3201234353Sdim return MatchOperand_ParseFail; 3202234353Sdim } 3203249423Sdim EndLoc = Parser.getTok().getEndLoc(); 3204234353Sdim Parser.Lex(); // Eat the ']'. 3205234353Sdim int64_t Val = CE->getValue(); 3206234353Sdim 3207234353Sdim // FIXME: Make this range check context sensitive for .8, .16, .32. 3208234353Sdim if (Val < 0 || Val > 7) { 3209234353Sdim Error(Parser.getTok().getLoc(), "lane index out of range"); 3210234353Sdim return MatchOperand_ParseFail; 3211234353Sdim } 3212234353Sdim Index = Val; 3213234353Sdim LaneKind = IndexedLane; 3214234353Sdim return MatchOperand_Success; 3215234353Sdim } 3216234353Sdim LaneKind = NoLanes; 3217234353Sdim return MatchOperand_Success; 3218234353Sdim} 3219234353Sdim 3220234353Sdim// parse a vector register list 3221234353SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 3222234353SdimparseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 3223234353Sdim VectorLaneTy LaneKind; 3224234353Sdim unsigned LaneIndex; 3225234353Sdim SMLoc S = Parser.getTok().getLoc(); 3226234353Sdim // As an extension (to match gas), support a plain D register or Q register 3227234353Sdim // (without encosing curly braces) as a single or double entry list, 3228234353Sdim // respectively. 3229234353Sdim if (Parser.getTok().is(AsmToken::Identifier)) { 3230249423Sdim SMLoc E = Parser.getTok().getEndLoc(); 3231234353Sdim int Reg = tryParseRegister(); 3232234353Sdim if (Reg == -1) 3233234353Sdim return MatchOperand_NoMatch; 3234234353Sdim if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) { 3235249423Sdim OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex, E); 3236234353Sdim if (Res != MatchOperand_Success) 3237234353Sdim return Res; 3238234353Sdim switch (LaneKind) { 3239234353Sdim case NoLanes: 3240234353Sdim Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E)); 3241234353Sdim break; 3242234353Sdim case AllLanes: 3243234353Sdim Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false, 3244234353Sdim S, E)); 3245234353Sdim break; 3246234353Sdim case IndexedLane: 3247234353Sdim Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1, 3248234353Sdim LaneIndex, 3249234353Sdim false, S, E)); 3250234353Sdim break; 3251234353Sdim } 3252234353Sdim return MatchOperand_Success; 3253234353Sdim } 3254234353Sdim if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { 3255234353Sdim Reg = getDRegFromQReg(Reg); 3256249423Sdim OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex, E); 3257234353Sdim if (Res != MatchOperand_Success) 3258234353Sdim return Res; 3259234353Sdim switch (LaneKind) { 3260234353Sdim case NoLanes: 3261234353Sdim Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0, 3262234353Sdim &ARMMCRegisterClasses[ARM::DPairRegClassID]); 3263234353Sdim Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E)); 3264234353Sdim break; 3265234353Sdim case AllLanes: 3266234353Sdim Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0, 3267234353Sdim &ARMMCRegisterClasses[ARM::DPairRegClassID]); 3268234353Sdim Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false, 3269234353Sdim S, E)); 3270234353Sdim break; 3271234353Sdim case IndexedLane: 3272234353Sdim Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2, 3273234353Sdim LaneIndex, 3274234353Sdim false, S, E)); 3275234353Sdim break; 3276234353Sdim } 3277234353Sdim return MatchOperand_Success; 3278234353Sdim } 3279234353Sdim Error(S, "vector register expected"); 3280234353Sdim return MatchOperand_ParseFail; 3281234353Sdim } 3282234353Sdim 3283234353Sdim if (Parser.getTok().isNot(AsmToken::LCurly)) 3284234353Sdim return MatchOperand_NoMatch; 3285234353Sdim 3286234353Sdim Parser.Lex(); // Eat '{' token. 3287234353Sdim SMLoc RegLoc = Parser.getTok().getLoc(); 3288234353Sdim 3289234353Sdim int Reg = tryParseRegister(); 3290234353Sdim if (Reg == -1) { 3291234353Sdim Error(RegLoc, "register expected"); 3292234353Sdim return MatchOperand_ParseFail; 3293234353Sdim } 3294234353Sdim unsigned Count = 1; 3295234353Sdim int Spacing = 0; 3296234353Sdim unsigned FirstReg = Reg; 3297234353Sdim // The list is of D registers, but we also allow Q regs and just interpret 3298234353Sdim // them as the two D sub-registers. 3299234353Sdim if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { 3300234353Sdim FirstReg = Reg = getDRegFromQReg(Reg); 3301234353Sdim Spacing = 1; // double-spacing requires explicit D registers, otherwise 3302234353Sdim // it's ambiguous with four-register single spaced. 3303234353Sdim ++Reg; 3304234353Sdim ++Count; 3305234353Sdim } 3306249423Sdim 3307249423Sdim SMLoc E; 3308249423Sdim if (parseVectorLane(LaneKind, LaneIndex, E) != MatchOperand_Success) 3309234353Sdim return MatchOperand_ParseFail; 3310234353Sdim 3311234353Sdim while (Parser.getTok().is(AsmToken::Comma) || 3312234353Sdim Parser.getTok().is(AsmToken::Minus)) { 3313234353Sdim if (Parser.getTok().is(AsmToken::Minus)) { 3314234353Sdim if (!Spacing) 3315234353Sdim Spacing = 1; // Register range implies a single spaced list. 3316234353Sdim else if (Spacing == 2) { 3317234353Sdim Error(Parser.getTok().getLoc(), 3318234353Sdim "sequential registers in double spaced list"); 3319234353Sdim return MatchOperand_ParseFail; 3320234353Sdim } 3321234353Sdim Parser.Lex(); // Eat the minus. 3322249423Sdim SMLoc AfterMinusLoc = Parser.getTok().getLoc(); 3323234353Sdim int EndReg = tryParseRegister(); 3324234353Sdim if (EndReg == -1) { 3325249423Sdim Error(AfterMinusLoc, "register expected"); 3326234353Sdim return MatchOperand_ParseFail; 3327234353Sdim } 3328234353Sdim // Allow Q regs and just interpret them as the two D sub-registers. 3329234353Sdim if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg)) 3330234353Sdim EndReg = getDRegFromQReg(EndReg) + 1; 3331234353Sdim // If the register is the same as the start reg, there's nothing 3332234353Sdim // more to do. 3333234353Sdim if (Reg == EndReg) 3334234353Sdim continue; 3335234353Sdim // The register must be in the same register class as the first. 3336234353Sdim if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) { 3337249423Sdim Error(AfterMinusLoc, "invalid register in register list"); 3338234353Sdim return MatchOperand_ParseFail; 3339234353Sdim } 3340234353Sdim // Ranges must go from low to high. 3341234353Sdim if (Reg > EndReg) { 3342249423Sdim Error(AfterMinusLoc, "bad range in register list"); 3343234353Sdim return MatchOperand_ParseFail; 3344234353Sdim } 3345234353Sdim // Parse the lane specifier if present. 3346234353Sdim VectorLaneTy NextLaneKind; 3347234353Sdim unsigned NextLaneIndex; 3348249423Sdim if (parseVectorLane(NextLaneKind, NextLaneIndex, E) != 3349249423Sdim MatchOperand_Success) 3350234353Sdim return MatchOperand_ParseFail; 3351234353Sdim if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) { 3352249423Sdim Error(AfterMinusLoc, "mismatched lane index in register list"); 3353234353Sdim return MatchOperand_ParseFail; 3354234353Sdim } 3355234353Sdim 3356234353Sdim // Add all the registers in the range to the register list. 3357234353Sdim Count += EndReg - Reg; 3358234353Sdim Reg = EndReg; 3359234353Sdim continue; 3360234353Sdim } 3361234353Sdim Parser.Lex(); // Eat the comma. 3362234353Sdim RegLoc = Parser.getTok().getLoc(); 3363234353Sdim int OldReg = Reg; 3364234353Sdim Reg = tryParseRegister(); 3365234353Sdim if (Reg == -1) { 3366234353Sdim Error(RegLoc, "register expected"); 3367234353Sdim return MatchOperand_ParseFail; 3368234353Sdim } 3369234353Sdim // vector register lists must be contiguous. 3370234353Sdim // It's OK to use the enumeration values directly here rather, as the 3371234353Sdim // VFP register classes have the enum sorted properly. 3372234353Sdim // 3373234353Sdim // The list is of D registers, but we also allow Q regs and just interpret 3374234353Sdim // them as the two D sub-registers. 3375234353Sdim if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { 3376234353Sdim if (!Spacing) 3377234353Sdim Spacing = 1; // Register range implies a single spaced list. 3378234353Sdim else if (Spacing == 2) { 3379234353Sdim Error(RegLoc, 3380234353Sdim "invalid register in double-spaced list (must be 'D' register')"); 3381234353Sdim return MatchOperand_ParseFail; 3382234353Sdim } 3383234353Sdim Reg = getDRegFromQReg(Reg); 3384234353Sdim if (Reg != OldReg + 1) { 3385234353Sdim Error(RegLoc, "non-contiguous register range"); 3386234353Sdim return MatchOperand_ParseFail; 3387234353Sdim } 3388234353Sdim ++Reg; 3389234353Sdim Count += 2; 3390234353Sdim // Parse the lane specifier if present. 3391234353Sdim VectorLaneTy NextLaneKind; 3392234353Sdim unsigned NextLaneIndex; 3393249423Sdim SMLoc LaneLoc = Parser.getTok().getLoc(); 3394249423Sdim if (parseVectorLane(NextLaneKind, NextLaneIndex, E) != 3395249423Sdim MatchOperand_Success) 3396234353Sdim return MatchOperand_ParseFail; 3397234353Sdim if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) { 3398249423Sdim Error(LaneLoc, "mismatched lane index in register list"); 3399234353Sdim return MatchOperand_ParseFail; 3400234353Sdim } 3401234353Sdim continue; 3402234353Sdim } 3403234353Sdim // Normal D register. 3404234353Sdim // Figure out the register spacing (single or double) of the list if 3405234353Sdim // we don't know it already. 3406234353Sdim if (!Spacing) 3407234353Sdim Spacing = 1 + (Reg == OldReg + 2); 3408234353Sdim 3409234353Sdim // Just check that it's contiguous and keep going. 3410234353Sdim if (Reg != OldReg + Spacing) { 3411234353Sdim Error(RegLoc, "non-contiguous register range"); 3412234353Sdim return MatchOperand_ParseFail; 3413234353Sdim } 3414234353Sdim ++Count; 3415234353Sdim // Parse the lane specifier if present. 3416234353Sdim VectorLaneTy NextLaneKind; 3417234353Sdim unsigned NextLaneIndex; 3418234353Sdim SMLoc EndLoc = Parser.getTok().getLoc(); 3419249423Sdim if (parseVectorLane(NextLaneKind, NextLaneIndex, E) != MatchOperand_Success) 3420234353Sdim return MatchOperand_ParseFail; 3421234353Sdim if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) { 3422234353Sdim Error(EndLoc, "mismatched lane index in register list"); 3423234353Sdim return MatchOperand_ParseFail; 3424234353Sdim } 3425234353Sdim } 3426234353Sdim 3427234353Sdim if (Parser.getTok().isNot(AsmToken::RCurly)) { 3428249423Sdim Error(Parser.getTok().getLoc(), "'}' expected"); 3429234353Sdim return MatchOperand_ParseFail; 3430234353Sdim } 3431249423Sdim E = Parser.getTok().getEndLoc(); 3432234353Sdim Parser.Lex(); // Eat '}' token. 3433234353Sdim 3434234353Sdim switch (LaneKind) { 3435234353Sdim case NoLanes: 3436234353Sdim // Two-register operands have been converted to the 3437234353Sdim // composite register classes. 3438234353Sdim if (Count == 2) { 3439234353Sdim const MCRegisterClass *RC = (Spacing == 1) ? 3440234353Sdim &ARMMCRegisterClasses[ARM::DPairRegClassID] : 3441234353Sdim &ARMMCRegisterClasses[ARM::DPairSpcRegClassID]; 3442234353Sdim FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC); 3443234353Sdim } 3444234353Sdim 3445234353Sdim Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, 3446234353Sdim (Spacing == 2), S, E)); 3447234353Sdim break; 3448234353Sdim case AllLanes: 3449234353Sdim // Two-register operands have been converted to the 3450234353Sdim // composite register classes. 3451234353Sdim if (Count == 2) { 3452234353Sdim const MCRegisterClass *RC = (Spacing == 1) ? 3453234353Sdim &ARMMCRegisterClasses[ARM::DPairRegClassID] : 3454234353Sdim &ARMMCRegisterClasses[ARM::DPairSpcRegClassID]; 3455234353Sdim FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC); 3456234353Sdim } 3457234353Sdim Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count, 3458234353Sdim (Spacing == 2), 3459234353Sdim S, E)); 3460234353Sdim break; 3461234353Sdim case IndexedLane: 3462234353Sdim Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count, 3463234353Sdim LaneIndex, 3464234353Sdim (Spacing == 2), 3465234353Sdim S, E)); 3466234353Sdim break; 3467234353Sdim } 3468234353Sdim return MatchOperand_Success; 3469234353Sdim} 3470234353Sdim 3471226633Sdim/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options. 3472218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 3473226633SdimparseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 3474218893Sdim SMLoc S = Parser.getTok().getLoc(); 3475218893Sdim const AsmToken &Tok = Parser.getTok(); 3476239462Sdim unsigned Opt; 3477218893Sdim 3478239462Sdim if (Tok.is(AsmToken::Identifier)) { 3479239462Sdim StringRef OptStr = Tok.getString(); 3480218893Sdim 3481239462Sdim Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()).lower()) 3482239462Sdim .Case("sy", ARM_MB::SY) 3483239462Sdim .Case("st", ARM_MB::ST) 3484263508Sdim .Case("ld", ARM_MB::LD) 3485239462Sdim .Case("sh", ARM_MB::ISH) 3486239462Sdim .Case("ish", ARM_MB::ISH) 3487239462Sdim .Case("shst", ARM_MB::ISHST) 3488239462Sdim .Case("ishst", ARM_MB::ISHST) 3489263508Sdim .Case("ishld", ARM_MB::ISHLD) 3490239462Sdim .Case("nsh", ARM_MB::NSH) 3491239462Sdim .Case("un", ARM_MB::NSH) 3492239462Sdim .Case("nshst", ARM_MB::NSHST) 3493263508Sdim .Case("nshld", ARM_MB::NSHLD) 3494239462Sdim .Case("unst", ARM_MB::NSHST) 3495239462Sdim .Case("osh", ARM_MB::OSH) 3496239462Sdim .Case("oshst", ARM_MB::OSHST) 3497263508Sdim .Case("oshld", ARM_MB::OSHLD) 3498239462Sdim .Default(~0U); 3499218893Sdim 3500263508Sdim // ishld, oshld, nshld and ld are only available from ARMv8. 3501263508Sdim if (!hasV8Ops() && (Opt == ARM_MB::ISHLD || Opt == ARM_MB::OSHLD || 3502263508Sdim Opt == ARM_MB::NSHLD || Opt == ARM_MB::LD)) 3503263508Sdim Opt = ~0U; 3504263508Sdim 3505239462Sdim if (Opt == ~0U) 3506239462Sdim return MatchOperand_NoMatch; 3507239462Sdim 3508239462Sdim Parser.Lex(); // Eat identifier token. 3509239462Sdim } else if (Tok.is(AsmToken::Hash) || 3510239462Sdim Tok.is(AsmToken::Dollar) || 3511239462Sdim Tok.is(AsmToken::Integer)) { 3512239462Sdim if (Parser.getTok().isNot(AsmToken::Integer)) 3513263508Sdim Parser.Lex(); // Eat '#' or '$'. 3514239462Sdim SMLoc Loc = Parser.getTok().getLoc(); 3515239462Sdim 3516239462Sdim const MCExpr *MemBarrierID; 3517249423Sdim if (getParser().parseExpression(MemBarrierID)) { 3518239462Sdim Error(Loc, "illegal expression"); 3519239462Sdim return MatchOperand_ParseFail; 3520239462Sdim } 3521239462Sdim 3522239462Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(MemBarrierID); 3523239462Sdim if (!CE) { 3524239462Sdim Error(Loc, "constant expression expected"); 3525239462Sdim return MatchOperand_ParseFail; 3526239462Sdim } 3527239462Sdim 3528239462Sdim int Val = CE->getValue(); 3529239462Sdim if (Val & ~0xf) { 3530239462Sdim Error(Loc, "immediate value out of range"); 3531239462Sdim return MatchOperand_ParseFail; 3532239462Sdim } 3533239462Sdim 3534239462Sdim Opt = ARM_MB::RESERVED_0 + Val; 3535239462Sdim } else 3536239462Sdim return MatchOperand_ParseFail; 3537239462Sdim 3538218893Sdim Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S)); 3539218893Sdim return MatchOperand_Success; 3540218893Sdim} 3541218893Sdim 3542263508Sdim/// parseInstSyncBarrierOptOperand - Try to parse ISB inst sync barrier options. 3543263508SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 3544263508SdimparseInstSyncBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 3545263508Sdim SMLoc S = Parser.getTok().getLoc(); 3546263508Sdim const AsmToken &Tok = Parser.getTok(); 3547263508Sdim unsigned Opt; 3548263508Sdim 3549263508Sdim if (Tok.is(AsmToken::Identifier)) { 3550263508Sdim StringRef OptStr = Tok.getString(); 3551263508Sdim 3552263508Sdim if (OptStr.equals_lower("sy")) 3553263508Sdim Opt = ARM_ISB::SY; 3554263508Sdim else 3555263508Sdim return MatchOperand_NoMatch; 3556263508Sdim 3557263508Sdim Parser.Lex(); // Eat identifier token. 3558263508Sdim } else if (Tok.is(AsmToken::Hash) || 3559263508Sdim Tok.is(AsmToken::Dollar) || 3560263508Sdim Tok.is(AsmToken::Integer)) { 3561263508Sdim if (Parser.getTok().isNot(AsmToken::Integer)) 3562263508Sdim Parser.Lex(); // Eat '#' or '$'. 3563263508Sdim SMLoc Loc = Parser.getTok().getLoc(); 3564263508Sdim 3565263508Sdim const MCExpr *ISBarrierID; 3566263508Sdim if (getParser().parseExpression(ISBarrierID)) { 3567263508Sdim Error(Loc, "illegal expression"); 3568263508Sdim return MatchOperand_ParseFail; 3569263508Sdim } 3570263508Sdim 3571263508Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ISBarrierID); 3572263508Sdim if (!CE) { 3573263508Sdim Error(Loc, "constant expression expected"); 3574263508Sdim return MatchOperand_ParseFail; 3575263508Sdim } 3576263508Sdim 3577263508Sdim int Val = CE->getValue(); 3578263508Sdim if (Val & ~0xf) { 3579263508Sdim Error(Loc, "immediate value out of range"); 3580263508Sdim return MatchOperand_ParseFail; 3581263508Sdim } 3582263508Sdim 3583263508Sdim Opt = ARM_ISB::RESERVED_0 + Val; 3584263508Sdim } else 3585263508Sdim return MatchOperand_ParseFail; 3586263508Sdim 3587263508Sdim Operands.push_back(ARMOperand::CreateInstSyncBarrierOpt( 3588263508Sdim (ARM_ISB::InstSyncBOpt)Opt, S)); 3589263508Sdim return MatchOperand_Success; 3590263508Sdim} 3591263508Sdim 3592263508Sdim 3593226633Sdim/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction. 3594218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 3595226633SdimparseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 3596218893Sdim SMLoc S = Parser.getTok().getLoc(); 3597218893Sdim const AsmToken &Tok = Parser.getTok(); 3598239462Sdim if (!Tok.is(AsmToken::Identifier)) 3599239462Sdim return MatchOperand_NoMatch; 3600218893Sdim StringRef IFlagsStr = Tok.getString(); 3601218893Sdim 3602226633Sdim // An iflags string of "none" is interpreted to mean that none of the AIF 3603226633Sdim // bits are set. Not a terribly useful instruction, but a valid encoding. 3604218893Sdim unsigned IFlags = 0; 3605226633Sdim if (IFlagsStr != "none") { 3606226633Sdim for (int i = 0, e = IFlagsStr.size(); i != e; ++i) { 3607226633Sdim unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1)) 3608226633Sdim .Case("a", ARM_PROC::A) 3609226633Sdim .Case("i", ARM_PROC::I) 3610226633Sdim .Case("f", ARM_PROC::F) 3611226633Sdim .Default(~0U); 3612218893Sdim 3613226633Sdim // If some specific iflag is already set, it means that some letter is 3614226633Sdim // present more than once, this is not acceptable. 3615226633Sdim if (Flag == ~0U || (IFlags & Flag)) 3616226633Sdim return MatchOperand_NoMatch; 3617218893Sdim 3618226633Sdim IFlags |= Flag; 3619226633Sdim } 3620218893Sdim } 3621218893Sdim 3622218893Sdim Parser.Lex(); // Eat identifier token. 3623218893Sdim Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S)); 3624218893Sdim return MatchOperand_Success; 3625218893Sdim} 3626218893Sdim 3627226633Sdim/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction. 3628218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 3629226633SdimparseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 3630218893Sdim SMLoc S = Parser.getTok().getLoc(); 3631218893Sdim const AsmToken &Tok = Parser.getTok(); 3632243830Sdim if (!Tok.is(AsmToken::Identifier)) 3633243830Sdim return MatchOperand_NoMatch; 3634218893Sdim StringRef Mask = Tok.getString(); 3635218893Sdim 3636226633Sdim if (isMClass()) { 3637226633Sdim // See ARMv6-M 10.1.1 3638234353Sdim std::string Name = Mask.lower(); 3639234353Sdim unsigned FlagsVal = StringSwitch<unsigned>(Name) 3640239462Sdim // Note: in the documentation: 3641239462Sdim // ARM deprecates using MSR APSR without a _<bits> qualifier as an alias 3642239462Sdim // for MSR APSR_nzcvq. 3643239462Sdim // but we do make it an alias here. This is so to get the "mask encoding" 3644239462Sdim // bits correct on MSR APSR writes. 3645239462Sdim // 3646239462Sdim // FIXME: Note the 0xc00 "mask encoding" bits version of the registers 3647239462Sdim // should really only be allowed when writing a special register. Note 3648239462Sdim // they get dropped in the MRS instruction reading a special register as 3649239462Sdim // the SYSm field is only 8 bits. 3650239462Sdim // 3651239462Sdim // FIXME: the _g and _nzcvqg versions are only allowed if the processor 3652239462Sdim // includes the DSP extension but that is not checked. 3653239462Sdim .Case("apsr", 0x800) 3654239462Sdim .Case("apsr_nzcvq", 0x800) 3655239462Sdim .Case("apsr_g", 0x400) 3656239462Sdim .Case("apsr_nzcvqg", 0xc00) 3657239462Sdim .Case("iapsr", 0x801) 3658239462Sdim .Case("iapsr_nzcvq", 0x801) 3659239462Sdim .Case("iapsr_g", 0x401) 3660239462Sdim .Case("iapsr_nzcvqg", 0xc01) 3661239462Sdim .Case("eapsr", 0x802) 3662239462Sdim .Case("eapsr_nzcvq", 0x802) 3663239462Sdim .Case("eapsr_g", 0x402) 3664239462Sdim .Case("eapsr_nzcvqg", 0xc02) 3665239462Sdim .Case("xpsr", 0x803) 3666239462Sdim .Case("xpsr_nzcvq", 0x803) 3667239462Sdim .Case("xpsr_g", 0x403) 3668239462Sdim .Case("xpsr_nzcvqg", 0xc03) 3669239462Sdim .Case("ipsr", 0x805) 3670239462Sdim .Case("epsr", 0x806) 3671239462Sdim .Case("iepsr", 0x807) 3672239462Sdim .Case("msp", 0x808) 3673239462Sdim .Case("psp", 0x809) 3674239462Sdim .Case("primask", 0x810) 3675239462Sdim .Case("basepri", 0x811) 3676239462Sdim .Case("basepri_max", 0x812) 3677239462Sdim .Case("faultmask", 0x813) 3678239462Sdim .Case("control", 0x814) 3679226633Sdim .Default(~0U); 3680234353Sdim 3681226633Sdim if (FlagsVal == ~0U) 3682226633Sdim return MatchOperand_NoMatch; 3683226633Sdim 3684239462Sdim if (!hasV7Ops() && FlagsVal >= 0x811 && FlagsVal <= 0x813) 3685226633Sdim // basepri, basepri_max and faultmask only valid for V7m. 3686226633Sdim return MatchOperand_NoMatch; 3687234353Sdim 3688226633Sdim Parser.Lex(); // Eat identifier token. 3689226633Sdim Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S)); 3690226633Sdim return MatchOperand_Success; 3691226633Sdim } 3692226633Sdim 3693218893Sdim // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf" 3694218893Sdim size_t Start = 0, Next = Mask.find('_'); 3695218893Sdim StringRef Flags = ""; 3696234353Sdim std::string SpecReg = Mask.slice(Start, Next).lower(); 3697218893Sdim if (Next != StringRef::npos) 3698218893Sdim Flags = Mask.slice(Next+1, Mask.size()); 3699218893Sdim 3700218893Sdim // FlagsVal contains the complete mask: 3701218893Sdim // 3-0: Mask 3702218893Sdim // 4: Special Reg (cpsr, apsr => 0; spsr => 1) 3703218893Sdim unsigned FlagsVal = 0; 3704218893Sdim 3705218893Sdim if (SpecReg == "apsr") { 3706218893Sdim FlagsVal = StringSwitch<unsigned>(Flags) 3707226633Sdim .Case("nzcvq", 0x8) // same as CPSR_f 3708218893Sdim .Case("g", 0x4) // same as CPSR_s 3709218893Sdim .Case("nzcvqg", 0xc) // same as CPSR_fs 3710218893Sdim .Default(~0U); 3711218893Sdim 3712218893Sdim if (FlagsVal == ~0U) { 3713218893Sdim if (!Flags.empty()) 3714218893Sdim return MatchOperand_NoMatch; 3715218893Sdim else 3716226633Sdim FlagsVal = 8; // No flag 3717218893Sdim } 3718218893Sdim } else if (SpecReg == "cpsr" || SpecReg == "spsr") { 3719234353Sdim // cpsr_all is an alias for cpsr_fc, as is plain cpsr. 3720234353Sdim if (Flags == "all" || Flags == "") 3721223017Sdim Flags = "fc"; 3722218893Sdim for (int i = 0, e = Flags.size(); i != e; ++i) { 3723218893Sdim unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1)) 3724218893Sdim .Case("c", 1) 3725218893Sdim .Case("x", 2) 3726218893Sdim .Case("s", 4) 3727218893Sdim .Case("f", 8) 3728218893Sdim .Default(~0U); 3729218893Sdim 3730218893Sdim // If some specific flag is already set, it means that some letter is 3731218893Sdim // present more than once, this is not acceptable. 3732218893Sdim if (FlagsVal == ~0U || (FlagsVal & Flag)) 3733218893Sdim return MatchOperand_NoMatch; 3734218893Sdim FlagsVal |= Flag; 3735218893Sdim } 3736218893Sdim } else // No match for special register. 3737218893Sdim return MatchOperand_NoMatch; 3738218893Sdim 3739234353Sdim // Special register without flags is NOT equivalent to "fc" flags. 3740234353Sdim // NOTE: This is a divergence from gas' behavior. Uncommenting the following 3741234353Sdim // two lines would enable gas compatibility at the expense of breaking 3742234353Sdim // round-tripping. 3743234353Sdim // 3744234353Sdim // if (!FlagsVal) 3745234353Sdim // FlagsVal = 0x9; 3746218893Sdim 3747218893Sdim // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1) 3748218893Sdim if (SpecReg == "spsr") 3749218893Sdim FlagsVal |= 16; 3750218893Sdim 3751218893Sdim Parser.Lex(); // Eat identifier token. 3752218893Sdim Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S)); 3753218893Sdim return MatchOperand_Success; 3754218893Sdim} 3755218893Sdim 3756221345SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 3757226633SdimparsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op, 3758226633Sdim int Low, int High) { 3759226633Sdim const AsmToken &Tok = Parser.getTok(); 3760226633Sdim if (Tok.isNot(AsmToken::Identifier)) { 3761226633Sdim Error(Parser.getTok().getLoc(), Op + " operand expected."); 3762226633Sdim return MatchOperand_ParseFail; 3763226633Sdim } 3764226633Sdim StringRef ShiftName = Tok.getString(); 3765234353Sdim std::string LowerOp = Op.lower(); 3766234353Sdim std::string UpperOp = Op.upper(); 3767226633Sdim if (ShiftName != LowerOp && ShiftName != UpperOp) { 3768226633Sdim Error(Parser.getTok().getLoc(), Op + " operand expected."); 3769226633Sdim return MatchOperand_ParseFail; 3770226633Sdim } 3771226633Sdim Parser.Lex(); // Eat shift type token. 3772221345Sdim 3773226633Sdim // There must be a '#' and a shift amount. 3774234353Sdim if (Parser.getTok().isNot(AsmToken::Hash) && 3775234353Sdim Parser.getTok().isNot(AsmToken::Dollar)) { 3776226633Sdim Error(Parser.getTok().getLoc(), "'#' expected"); 3777226633Sdim return MatchOperand_ParseFail; 3778226633Sdim } 3779226633Sdim Parser.Lex(); // Eat hash token. 3780221345Sdim 3781226633Sdim const MCExpr *ShiftAmount; 3782226633Sdim SMLoc Loc = Parser.getTok().getLoc(); 3783249423Sdim SMLoc EndLoc; 3784249423Sdim if (getParser().parseExpression(ShiftAmount, EndLoc)) { 3785226633Sdim Error(Loc, "illegal expression"); 3786226633Sdim return MatchOperand_ParseFail; 3787226633Sdim } 3788226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount); 3789226633Sdim if (!CE) { 3790226633Sdim Error(Loc, "constant expression expected"); 3791226633Sdim return MatchOperand_ParseFail; 3792226633Sdim } 3793226633Sdim int Val = CE->getValue(); 3794226633Sdim if (Val < Low || Val > High) { 3795226633Sdim Error(Loc, "immediate value out of range"); 3796226633Sdim return MatchOperand_ParseFail; 3797226633Sdim } 3798226633Sdim 3799249423Sdim Operands.push_back(ARMOperand::CreateImm(CE, Loc, EndLoc)); 3800226633Sdim 3801221345Sdim return MatchOperand_Success; 3802221345Sdim} 3803221345Sdim 3804221345SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 3805226633SdimparseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 3806226633Sdim const AsmToken &Tok = Parser.getTok(); 3807226633Sdim SMLoc S = Tok.getLoc(); 3808226633Sdim if (Tok.isNot(AsmToken::Identifier)) { 3809249423Sdim Error(S, "'be' or 'le' operand expected"); 3810226633Sdim return MatchOperand_ParseFail; 3811226633Sdim } 3812263508Sdim int Val = StringSwitch<int>(Tok.getString().lower()) 3813226633Sdim .Case("be", 1) 3814226633Sdim .Case("le", 0) 3815226633Sdim .Default(-1); 3816226633Sdim Parser.Lex(); // Eat the token. 3817221345Sdim 3818226633Sdim if (Val == -1) { 3819249423Sdim Error(S, "'be' or 'le' operand expected"); 3820226633Sdim return MatchOperand_ParseFail; 3821226633Sdim } 3822226633Sdim Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val, 3823226633Sdim getContext()), 3824249423Sdim S, Tok.getEndLoc())); 3825226633Sdim return MatchOperand_Success; 3826226633Sdim} 3827226633Sdim 3828226633Sdim/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT 3829226633Sdim/// instructions. Legal values are: 3830226633Sdim/// lsl #n 'n' in [0,31] 3831226633Sdim/// asr #n 'n' in [1,32] 3832226633Sdim/// n == 32 encoded as n == 0. 3833226633SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 3834226633SdimparseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 3835226633Sdim const AsmToken &Tok = Parser.getTok(); 3836226633Sdim SMLoc S = Tok.getLoc(); 3837226633Sdim if (Tok.isNot(AsmToken::Identifier)) { 3838226633Sdim Error(S, "shift operator 'asr' or 'lsl' expected"); 3839226633Sdim return MatchOperand_ParseFail; 3840226633Sdim } 3841226633Sdim StringRef ShiftName = Tok.getString(); 3842226633Sdim bool isASR; 3843226633Sdim if (ShiftName == "lsl" || ShiftName == "LSL") 3844226633Sdim isASR = false; 3845226633Sdim else if (ShiftName == "asr" || ShiftName == "ASR") 3846226633Sdim isASR = true; 3847226633Sdim else { 3848226633Sdim Error(S, "shift operator 'asr' or 'lsl' expected"); 3849226633Sdim return MatchOperand_ParseFail; 3850226633Sdim } 3851226633Sdim Parser.Lex(); // Eat the operator. 3852226633Sdim 3853226633Sdim // A '#' and a shift amount. 3854234353Sdim if (Parser.getTok().isNot(AsmToken::Hash) && 3855234353Sdim Parser.getTok().isNot(AsmToken::Dollar)) { 3856226633Sdim Error(Parser.getTok().getLoc(), "'#' expected"); 3857226633Sdim return MatchOperand_ParseFail; 3858226633Sdim } 3859226633Sdim Parser.Lex(); // Eat hash token. 3860249423Sdim SMLoc ExLoc = Parser.getTok().getLoc(); 3861226633Sdim 3862226633Sdim const MCExpr *ShiftAmount; 3863249423Sdim SMLoc EndLoc; 3864249423Sdim if (getParser().parseExpression(ShiftAmount, EndLoc)) { 3865249423Sdim Error(ExLoc, "malformed shift expression"); 3866226633Sdim return MatchOperand_ParseFail; 3867226633Sdim } 3868226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount); 3869226633Sdim if (!CE) { 3870249423Sdim Error(ExLoc, "shift amount must be an immediate"); 3871226633Sdim return MatchOperand_ParseFail; 3872226633Sdim } 3873226633Sdim 3874226633Sdim int64_t Val = CE->getValue(); 3875226633Sdim if (isASR) { 3876226633Sdim // Shift amount must be in [1,32] 3877226633Sdim if (Val < 1 || Val > 32) { 3878249423Sdim Error(ExLoc, "'asr' shift amount must be in range [1,32]"); 3879226633Sdim return MatchOperand_ParseFail; 3880226633Sdim } 3881226633Sdim // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode. 3882226633Sdim if (isThumb() && Val == 32) { 3883249423Sdim Error(ExLoc, "'asr #32' shift amount not allowed in Thumb mode"); 3884226633Sdim return MatchOperand_ParseFail; 3885226633Sdim } 3886226633Sdim if (Val == 32) Val = 0; 3887226633Sdim } else { 3888226633Sdim // Shift amount must be in [1,32] 3889226633Sdim if (Val < 0 || Val > 31) { 3890249423Sdim Error(ExLoc, "'lsr' shift amount must be in range [0,31]"); 3891226633Sdim return MatchOperand_ParseFail; 3892226633Sdim } 3893226633Sdim } 3894226633Sdim 3895249423Sdim Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, EndLoc)); 3896226633Sdim 3897226633Sdim return MatchOperand_Success; 3898226633Sdim} 3899226633Sdim 3900226633Sdim/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family 3901226633Sdim/// of instructions. Legal values are: 3902226633Sdim/// ror #n 'n' in {0, 8, 16, 24} 3903226633SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 3904226633SdimparseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 3905226633Sdim const AsmToken &Tok = Parser.getTok(); 3906226633Sdim SMLoc S = Tok.getLoc(); 3907226633Sdim if (Tok.isNot(AsmToken::Identifier)) 3908221345Sdim return MatchOperand_NoMatch; 3909226633Sdim StringRef ShiftName = Tok.getString(); 3910226633Sdim if (ShiftName != "ror" && ShiftName != "ROR") 3911226633Sdim return MatchOperand_NoMatch; 3912226633Sdim Parser.Lex(); // Eat the operator. 3913221345Sdim 3914226633Sdim // A '#' and a rotate amount. 3915234353Sdim if (Parser.getTok().isNot(AsmToken::Hash) && 3916234353Sdim Parser.getTok().isNot(AsmToken::Dollar)) { 3917226633Sdim Error(Parser.getTok().getLoc(), "'#' expected"); 3918226633Sdim return MatchOperand_ParseFail; 3919226633Sdim } 3920226633Sdim Parser.Lex(); // Eat hash token. 3921249423Sdim SMLoc ExLoc = Parser.getTok().getLoc(); 3922226633Sdim 3923226633Sdim const MCExpr *ShiftAmount; 3924249423Sdim SMLoc EndLoc; 3925249423Sdim if (getParser().parseExpression(ShiftAmount, EndLoc)) { 3926249423Sdim Error(ExLoc, "malformed rotate expression"); 3927226633Sdim return MatchOperand_ParseFail; 3928226633Sdim } 3929226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount); 3930226633Sdim if (!CE) { 3931249423Sdim Error(ExLoc, "rotate amount must be an immediate"); 3932226633Sdim return MatchOperand_ParseFail; 3933226633Sdim } 3934226633Sdim 3935226633Sdim int64_t Val = CE->getValue(); 3936226633Sdim // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension) 3937226633Sdim // normally, zero is represented in asm by omitting the rotate operand 3938226633Sdim // entirely. 3939226633Sdim if (Val != 8 && Val != 16 && Val != 24 && Val != 0) { 3940249423Sdim Error(ExLoc, "'ror' rotate amount must be 8, 16, or 24"); 3941226633Sdim return MatchOperand_ParseFail; 3942226633Sdim } 3943226633Sdim 3944249423Sdim Operands.push_back(ARMOperand::CreateRotImm(Val, S, EndLoc)); 3945226633Sdim 3946221345Sdim return MatchOperand_Success; 3947221345Sdim} 3948221345Sdim 3949226633SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 3950226633SdimparseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 3951226633Sdim SMLoc S = Parser.getTok().getLoc(); 3952226633Sdim // The bitfield descriptor is really two operands, the LSB and the width. 3953234353Sdim if (Parser.getTok().isNot(AsmToken::Hash) && 3954234353Sdim Parser.getTok().isNot(AsmToken::Dollar)) { 3955226633Sdim Error(Parser.getTok().getLoc(), "'#' expected"); 3956226633Sdim return MatchOperand_ParseFail; 3957226633Sdim } 3958226633Sdim Parser.Lex(); // Eat hash token. 3959226633Sdim 3960226633Sdim const MCExpr *LSBExpr; 3961226633Sdim SMLoc E = Parser.getTok().getLoc(); 3962249423Sdim if (getParser().parseExpression(LSBExpr)) { 3963226633Sdim Error(E, "malformed immediate expression"); 3964226633Sdim return MatchOperand_ParseFail; 3965226633Sdim } 3966226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr); 3967226633Sdim if (!CE) { 3968226633Sdim Error(E, "'lsb' operand must be an immediate"); 3969226633Sdim return MatchOperand_ParseFail; 3970226633Sdim } 3971226633Sdim 3972226633Sdim int64_t LSB = CE->getValue(); 3973226633Sdim // The LSB must be in the range [0,31] 3974226633Sdim if (LSB < 0 || LSB > 31) { 3975226633Sdim Error(E, "'lsb' operand must be in the range [0,31]"); 3976226633Sdim return MatchOperand_ParseFail; 3977226633Sdim } 3978226633Sdim E = Parser.getTok().getLoc(); 3979226633Sdim 3980226633Sdim // Expect another immediate operand. 3981226633Sdim if (Parser.getTok().isNot(AsmToken::Comma)) { 3982226633Sdim Error(Parser.getTok().getLoc(), "too few operands"); 3983226633Sdim return MatchOperand_ParseFail; 3984226633Sdim } 3985226633Sdim Parser.Lex(); // Eat hash token. 3986234353Sdim if (Parser.getTok().isNot(AsmToken::Hash) && 3987234353Sdim Parser.getTok().isNot(AsmToken::Dollar)) { 3988226633Sdim Error(Parser.getTok().getLoc(), "'#' expected"); 3989226633Sdim return MatchOperand_ParseFail; 3990226633Sdim } 3991226633Sdim Parser.Lex(); // Eat hash token. 3992226633Sdim 3993226633Sdim const MCExpr *WidthExpr; 3994249423Sdim SMLoc EndLoc; 3995249423Sdim if (getParser().parseExpression(WidthExpr, EndLoc)) { 3996226633Sdim Error(E, "malformed immediate expression"); 3997226633Sdim return MatchOperand_ParseFail; 3998226633Sdim } 3999226633Sdim CE = dyn_cast<MCConstantExpr>(WidthExpr); 4000226633Sdim if (!CE) { 4001226633Sdim Error(E, "'width' operand must be an immediate"); 4002226633Sdim return MatchOperand_ParseFail; 4003226633Sdim } 4004226633Sdim 4005226633Sdim int64_t Width = CE->getValue(); 4006226633Sdim // The LSB must be in the range [1,32-lsb] 4007226633Sdim if (Width < 1 || Width > 32 - LSB) { 4008226633Sdim Error(E, "'width' operand must be in the range [1,32-lsb]"); 4009226633Sdim return MatchOperand_ParseFail; 4010226633Sdim } 4011226633Sdim 4012249423Sdim Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, EndLoc)); 4013226633Sdim 4014226633Sdim return MatchOperand_Success; 4015226633Sdim} 4016226633Sdim 4017226633SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 4018226633SdimparsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 4019226633Sdim // Check for a post-index addressing register operand. Specifically: 4020226633Sdim // postidx_reg := '+' register {, shift} 4021226633Sdim // | '-' register {, shift} 4022226633Sdim // | register {, shift} 4023226633Sdim 4024226633Sdim // This method must return MatchOperand_NoMatch without consuming any tokens 4025226633Sdim // in the case where there is no match, as other alternatives take other 4026226633Sdim // parse methods. 4027226633Sdim AsmToken Tok = Parser.getTok(); 4028226633Sdim SMLoc S = Tok.getLoc(); 4029226633Sdim bool haveEaten = false; 4030226633Sdim bool isAdd = true; 4031226633Sdim if (Tok.is(AsmToken::Plus)) { 4032226633Sdim Parser.Lex(); // Eat the '+' token. 4033226633Sdim haveEaten = true; 4034226633Sdim } else if (Tok.is(AsmToken::Minus)) { 4035226633Sdim Parser.Lex(); // Eat the '-' token. 4036226633Sdim isAdd = false; 4037226633Sdim haveEaten = true; 4038226633Sdim } 4039249423Sdim 4040249423Sdim SMLoc E = Parser.getTok().getEndLoc(); 4041249423Sdim int Reg = tryParseRegister(); 4042226633Sdim if (Reg == -1) { 4043226633Sdim if (!haveEaten) 4044226633Sdim return MatchOperand_NoMatch; 4045226633Sdim Error(Parser.getTok().getLoc(), "register expected"); 4046226633Sdim return MatchOperand_ParseFail; 4047226633Sdim } 4048226633Sdim 4049226633Sdim ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift; 4050226633Sdim unsigned ShiftImm = 0; 4051226633Sdim if (Parser.getTok().is(AsmToken::Comma)) { 4052226633Sdim Parser.Lex(); // Eat the ','. 4053226633Sdim if (parseMemRegOffsetShift(ShiftTy, ShiftImm)) 4054226633Sdim return MatchOperand_ParseFail; 4055249423Sdim 4056249423Sdim // FIXME: Only approximates end...may include intervening whitespace. 4057249423Sdim E = Parser.getTok().getLoc(); 4058226633Sdim } 4059226633Sdim 4060226633Sdim Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy, 4061226633Sdim ShiftImm, S, E)); 4062226633Sdim 4063226633Sdim return MatchOperand_Success; 4064226633Sdim} 4065226633Sdim 4066226633SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 4067226633SdimparseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 4068226633Sdim // Check for a post-index addressing register operand. Specifically: 4069226633Sdim // am3offset := '+' register 4070226633Sdim // | '-' register 4071226633Sdim // | register 4072226633Sdim // | # imm 4073226633Sdim // | # + imm 4074226633Sdim // | # - imm 4075226633Sdim 4076226633Sdim // This method must return MatchOperand_NoMatch without consuming any tokens 4077226633Sdim // in the case where there is no match, as other alternatives take other 4078226633Sdim // parse methods. 4079226633Sdim AsmToken Tok = Parser.getTok(); 4080226633Sdim SMLoc S = Tok.getLoc(); 4081226633Sdim 4082226633Sdim // Do immediates first, as we always parse those if we have a '#'. 4083234353Sdim if (Parser.getTok().is(AsmToken::Hash) || 4084234353Sdim Parser.getTok().is(AsmToken::Dollar)) { 4085263508Sdim Parser.Lex(); // Eat '#' or '$'. 4086226633Sdim // Explicitly look for a '-', as we need to encode negative zero 4087226633Sdim // differently. 4088226633Sdim bool isNegative = Parser.getTok().is(AsmToken::Minus); 4089226633Sdim const MCExpr *Offset; 4090249423Sdim SMLoc E; 4091249423Sdim if (getParser().parseExpression(Offset, E)) 4092226633Sdim return MatchOperand_ParseFail; 4093226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset); 4094226633Sdim if (!CE) { 4095226633Sdim Error(S, "constant expression expected"); 4096226633Sdim return MatchOperand_ParseFail; 4097226633Sdim } 4098226633Sdim // Negative zero is encoded as the flag value INT32_MIN. 4099226633Sdim int32_t Val = CE->getValue(); 4100226633Sdim if (isNegative && Val == 0) 4101226633Sdim Val = INT32_MIN; 4102226633Sdim 4103226633Sdim Operands.push_back( 4104226633Sdim ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E)); 4105226633Sdim 4106226633Sdim return MatchOperand_Success; 4107226633Sdim } 4108226633Sdim 4109226633Sdim 4110226633Sdim bool haveEaten = false; 4111226633Sdim bool isAdd = true; 4112226633Sdim if (Tok.is(AsmToken::Plus)) { 4113226633Sdim Parser.Lex(); // Eat the '+' token. 4114226633Sdim haveEaten = true; 4115226633Sdim } else if (Tok.is(AsmToken::Minus)) { 4116226633Sdim Parser.Lex(); // Eat the '-' token. 4117226633Sdim isAdd = false; 4118226633Sdim haveEaten = true; 4119226633Sdim } 4120249423Sdim 4121249423Sdim Tok = Parser.getTok(); 4122249423Sdim int Reg = tryParseRegister(); 4123226633Sdim if (Reg == -1) { 4124226633Sdim if (!haveEaten) 4125226633Sdim return MatchOperand_NoMatch; 4126249423Sdim Error(Tok.getLoc(), "register expected"); 4127226633Sdim return MatchOperand_ParseFail; 4128226633Sdim } 4129226633Sdim 4130226633Sdim Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift, 4131249423Sdim 0, S, Tok.getEndLoc())); 4132226633Sdim 4133226633Sdim return MatchOperand_Success; 4134226633Sdim} 4135226633Sdim 4136263508Sdim/// Convert parsed operands to MCInst. Needed here because this instruction 4137263508Sdim/// only has two register operands, but multiplication is commutative so 4138263508Sdim/// assemblers should accept both "mul rD, rN, rD" and "mul rD, rD, rN". 4139243830Sdimvoid ARMAsmParser:: 4140243830SdimcvtThumbMultiply(MCInst &Inst, 4141226633Sdim const SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 4142226633Sdim ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1); 4143226633Sdim ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1); 4144234353Sdim // If we have a three-operand form, make sure to set Rn to be the operand 4145234353Sdim // that isn't the same as Rd. 4146234353Sdim unsigned RegOp = 4; 4147234353Sdim if (Operands.size() == 6 && 4148234353Sdim ((ARMOperand*)Operands[4])->getReg() == 4149234353Sdim ((ARMOperand*)Operands[3])->getReg()) 4150234353Sdim RegOp = 5; 4151234353Sdim ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1); 4152234353Sdim Inst.addOperand(Inst.getOperand(0)); 4153226633Sdim ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2); 4154226633Sdim} 4155226633Sdim 4156243830Sdimvoid ARMAsmParser:: 4157263508SdimcvtThumbBranches(MCInst &Inst, 4158263508Sdim const SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 4159263508Sdim int CondOp = -1, ImmOp = -1; 4160263508Sdim switch(Inst.getOpcode()) { 4161263508Sdim case ARM::tB: 4162263508Sdim case ARM::tBcc: CondOp = 1; ImmOp = 2; break; 4163234353Sdim 4164263508Sdim case ARM::t2B: 4165263508Sdim case ARM::t2Bcc: CondOp = 1; ImmOp = 3; break; 4166234353Sdim 4167263508Sdim default: llvm_unreachable("Unexpected instruction in cvtThumbBranches"); 4168263508Sdim } 4169263508Sdim // first decide whether or not the branch should be conditional 4170263508Sdim // by looking at it's location relative to an IT block 4171263508Sdim if(inITBlock()) { 4172263508Sdim // inside an IT block we cannot have any conditional branches. any 4173263508Sdim // such instructions needs to be converted to unconditional form 4174263508Sdim switch(Inst.getOpcode()) { 4175263508Sdim case ARM::tBcc: Inst.setOpcode(ARM::tB); break; 4176263508Sdim case ARM::t2Bcc: Inst.setOpcode(ARM::t2B); break; 4177263508Sdim } 4178263508Sdim } else { 4179263508Sdim // outside IT blocks we can only have unconditional branches with AL 4180263508Sdim // condition code or conditional branches with non-AL condition code 4181263508Sdim unsigned Cond = static_cast<ARMOperand*>(Operands[CondOp])->getCondCode(); 4182263508Sdim switch(Inst.getOpcode()) { 4183263508Sdim case ARM::tB: 4184263508Sdim case ARM::tBcc: 4185263508Sdim Inst.setOpcode(Cond == ARMCC::AL ? ARM::tB : ARM::tBcc); 4186263508Sdim break; 4187263508Sdim case ARM::t2B: 4188263508Sdim case ARM::t2Bcc: 4189263508Sdim Inst.setOpcode(Cond == ARMCC::AL ? ARM::t2B : ARM::t2Bcc); 4190263508Sdim break; 4191263508Sdim } 4192263508Sdim } 4193263508Sdim 4194263508Sdim // now decide on encoding size based on branch target range 4195263508Sdim switch(Inst.getOpcode()) { 4196263508Sdim // classify tB as either t2B or t1B based on range of immediate operand 4197263508Sdim case ARM::tB: { 4198263508Sdim ARMOperand* op = static_cast<ARMOperand*>(Operands[ImmOp]); 4199263508Sdim if(!op->isSignedOffset<11, 1>() && isThumbTwo()) 4200263508Sdim Inst.setOpcode(ARM::t2B); 4201263508Sdim break; 4202263508Sdim } 4203263508Sdim // classify tBcc as either t2Bcc or t1Bcc based on range of immediate operand 4204263508Sdim case ARM::tBcc: { 4205263508Sdim ARMOperand* op = static_cast<ARMOperand*>(Operands[ImmOp]); 4206263508Sdim if(!op->isSignedOffset<8, 1>() && isThumbTwo()) 4207263508Sdim Inst.setOpcode(ARM::t2Bcc); 4208263508Sdim break; 4209263508Sdim } 4210263508Sdim } 4211263508Sdim ((ARMOperand*)Operands[ImmOp])->addImmOperands(Inst, 1); 4212263508Sdim ((ARMOperand*)Operands[CondOp])->addCondCodeOperands(Inst, 2); 4213234353Sdim} 4214234353Sdim 4215218893Sdim/// Parse an ARM memory expression, return false if successful else return true 4216198892Srdivacky/// or an error. The first token must be a '[' when called. 4217218893Sdimbool ARMAsmParser:: 4218226633SdimparseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 4219206124Srdivacky SMLoc S, E; 4220202878Srdivacky assert(Parser.getTok().is(AsmToken::LBrac) && 4221218893Sdim "Token is not a Left Bracket"); 4222206124Srdivacky S = Parser.getTok().getLoc(); 4223202878Srdivacky Parser.Lex(); // Eat left bracket token. 4224198090Srdivacky 4225202878Srdivacky const AsmToken &BaseRegTok = Parser.getTok(); 4226226633Sdim int BaseRegNum = tryParseRegister(); 4227226633Sdim if (BaseRegNum == -1) 4228226633Sdim return Error(BaseRegTok.getLoc(), "register expected"); 4229198090Srdivacky 4230249423Sdim // The next token must either be a comma, a colon or a closing bracket. 4231218893Sdim const AsmToken &Tok = Parser.getTok(); 4232249423Sdim if (!Tok.is(AsmToken::Colon) && !Tok.is(AsmToken::Comma) && 4233249423Sdim !Tok.is(AsmToken::RBrac)) 4234226633Sdim return Error(Tok.getLoc(), "malformed memory operand"); 4235218893Sdim 4236226633Sdim if (Tok.is(AsmToken::RBrac)) { 4237249423Sdim E = Tok.getEndLoc(); 4238226633Sdim Parser.Lex(); // Eat right bracket token. 4239198090Srdivacky 4240226633Sdim Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift, 4241226633Sdim 0, 0, false, S, E)); 4242218893Sdim 4243226633Sdim // If there's a pre-indexing writeback marker, '!', just add it as a token 4244226633Sdim // operand. It's rather odd, but syntactically valid. 4245226633Sdim if (Parser.getTok().is(AsmToken::Exclaim)) { 4246226633Sdim Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); 4247226633Sdim Parser.Lex(); // Eat the '!'. 4248218893Sdim } 4249198090Srdivacky 4250226633Sdim return false; 4251226633Sdim } 4252221345Sdim 4253249423Sdim assert((Tok.is(AsmToken::Colon) || Tok.is(AsmToken::Comma)) && 4254249423Sdim "Lost colon or comma in memory operand?!"); 4255249423Sdim if (Tok.is(AsmToken::Comma)) { 4256249423Sdim Parser.Lex(); // Eat the comma. 4257249423Sdim } 4258218893Sdim 4259226633Sdim // If we have a ':', it's an alignment specifier. 4260226633Sdim if (Parser.getTok().is(AsmToken::Colon)) { 4261226633Sdim Parser.Lex(); // Eat the ':'. 4262226633Sdim E = Parser.getTok().getLoc(); 4263198090Srdivacky 4264226633Sdim const MCExpr *Expr; 4265249423Sdim if (getParser().parseExpression(Expr)) 4266226633Sdim return true; 4267198090Srdivacky 4268226633Sdim // The expression has to be a constant. Memory references with relocations 4269226633Sdim // don't come through here, as they use the <label> forms of the relevant 4270226633Sdim // instructions. 4271226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr); 4272226633Sdim if (!CE) 4273226633Sdim return Error (E, "constant expression expected"); 4274218893Sdim 4275226633Sdim unsigned Align = 0; 4276226633Sdim switch (CE->getValue()) { 4277226633Sdim default: 4278234353Sdim return Error(E, 4279234353Sdim "alignment specifier must be 16, 32, 64, 128, or 256 bits"); 4280234353Sdim case 16: Align = 2; break; 4281234353Sdim case 32: Align = 4; break; 4282226633Sdim case 64: Align = 8; break; 4283226633Sdim case 128: Align = 16; break; 4284226633Sdim case 256: Align = 32; break; 4285226633Sdim } 4286218893Sdim 4287226633Sdim // Now we should have the closing ']' 4288226633Sdim if (Parser.getTok().isNot(AsmToken::RBrac)) 4289249423Sdim return Error(Parser.getTok().getLoc(), "']' expected"); 4290249423Sdim E = Parser.getTok().getEndLoc(); 4291226633Sdim Parser.Lex(); // Eat right bracket token. 4292218893Sdim 4293226633Sdim // Don't worry about range checking the value here. That's handled by 4294226633Sdim // the is*() predicates. 4295226633Sdim Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, 4296226633Sdim ARM_AM::no_shift, 0, Align, 4297226633Sdim false, S, E)); 4298226633Sdim 4299226633Sdim // If there's a pre-indexing writeback marker, '!', just add it as a token 4300226633Sdim // operand. 4301226633Sdim if (Parser.getTok().is(AsmToken::Exclaim)) { 4302226633Sdim Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); 4303226633Sdim Parser.Lex(); // Eat the '!'. 4304198090Srdivacky } 4305198090Srdivacky 4306226633Sdim return false; 4307198090Srdivacky } 4308198090Srdivacky 4309226633Sdim // If we have a '#', it's an immediate offset, else assume it's a register 4310234353Sdim // offset. Be friendly and also accept a plain integer (without a leading 4311234353Sdim // hash) for gas compatibility. 4312234353Sdim if (Parser.getTok().is(AsmToken::Hash) || 4313234353Sdim Parser.getTok().is(AsmToken::Dollar) || 4314234353Sdim Parser.getTok().is(AsmToken::Integer)) { 4315234353Sdim if (Parser.getTok().isNot(AsmToken::Integer)) 4316263508Sdim Parser.Lex(); // Eat '#' or '$'. 4317226633Sdim E = Parser.getTok().getLoc(); 4318218893Sdim 4319226633Sdim bool isNegative = getParser().getTok().is(AsmToken::Minus); 4320226633Sdim const MCExpr *Offset; 4321249423Sdim if (getParser().parseExpression(Offset)) 4322226633Sdim return true; 4323198090Srdivacky 4324226633Sdim // The expression has to be a constant. Memory references with relocations 4325226633Sdim // don't come through here, as they use the <label> forms of the relevant 4326226633Sdim // instructions. 4327226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset); 4328226633Sdim if (!CE) 4329226633Sdim return Error (E, "constant expression expected"); 4330226633Sdim 4331226633Sdim // If the constant was #-0, represent it as INT32_MIN. 4332226633Sdim int32_t Val = CE->getValue(); 4333226633Sdim if (isNegative && Val == 0) 4334226633Sdim CE = MCConstantExpr::Create(INT32_MIN, getContext()); 4335226633Sdim 4336226633Sdim // Now we should have the closing ']' 4337226633Sdim if (Parser.getTok().isNot(AsmToken::RBrac)) 4338249423Sdim return Error(Parser.getTok().getLoc(), "']' expected"); 4339249423Sdim E = Parser.getTok().getEndLoc(); 4340226633Sdim Parser.Lex(); // Eat right bracket token. 4341226633Sdim 4342226633Sdim // Don't worry about range checking the value here. That's handled by 4343226633Sdim // the is*() predicates. 4344226633Sdim Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0, 4345226633Sdim ARM_AM::no_shift, 0, 0, 4346226633Sdim false, S, E)); 4347226633Sdim 4348226633Sdim // If there's a pre-indexing writeback marker, '!', just add it as a token 4349226633Sdim // operand. 4350226633Sdim if (Parser.getTok().is(AsmToken::Exclaim)) { 4351226633Sdim Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); 4352226633Sdim Parser.Lex(); // Eat the '!'. 4353206124Srdivacky } 4354226633Sdim 4355226633Sdim return false; 4356198892Srdivacky } 4357218893Sdim 4358226633Sdim // The register offset is optionally preceded by a '+' or '-' 4359226633Sdim bool isNegative = false; 4360226633Sdim if (Parser.getTok().is(AsmToken::Minus)) { 4361226633Sdim isNegative = true; 4362226633Sdim Parser.Lex(); // Eat the '-'. 4363226633Sdim } else if (Parser.getTok().is(AsmToken::Plus)) { 4364226633Sdim // Nothing to do. 4365226633Sdim Parser.Lex(); // Eat the '+'. 4366226633Sdim } 4367198892Srdivacky 4368226633Sdim E = Parser.getTok().getLoc(); 4369226633Sdim int OffsetRegNum = tryParseRegister(); 4370226633Sdim if (OffsetRegNum == -1) 4371226633Sdim return Error(E, "register expected"); 4372226633Sdim 4373226633Sdim // If there's a shift operator, handle it. 4374226633Sdim ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift; 4375226633Sdim unsigned ShiftImm = 0; 4376226633Sdim if (Parser.getTok().is(AsmToken::Comma)) { 4377226633Sdim Parser.Lex(); // Eat the ','. 4378226633Sdim if (parseMemRegOffsetShift(ShiftType, ShiftImm)) 4379226633Sdim return true; 4380198892Srdivacky } 4381218893Sdim 4382226633Sdim // Now we should have the closing ']' 4383226633Sdim if (Parser.getTok().isNot(AsmToken::RBrac)) 4384249423Sdim return Error(Parser.getTok().getLoc(), "']' expected"); 4385249423Sdim E = Parser.getTok().getEndLoc(); 4386226633Sdim Parser.Lex(); // Eat right bracket token. 4387198892Srdivacky 4388226633Sdim Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum, 4389226633Sdim ShiftType, ShiftImm, 0, isNegative, 4390226633Sdim S, E)); 4391226633Sdim 4392226633Sdim // If there's a pre-indexing writeback marker, '!', just add it as a token 4393226633Sdim // operand. 4394226633Sdim if (Parser.getTok().is(AsmToken::Exclaim)) { 4395226633Sdim Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); 4396226633Sdim Parser.Lex(); // Eat the '!'. 4397198892Srdivacky } 4398226633Sdim 4399198892Srdivacky return false; 4400198892Srdivacky} 4401198892Srdivacky 4402226633Sdim/// parseMemRegOffsetShift - one of these two: 4403198090Srdivacky/// ( lsl | lsr | asr | ror ) , # shift_amount 4404198090Srdivacky/// rrx 4405226633Sdim/// return true if it parses a shift otherwise it returns false. 4406226633Sdimbool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St, 4407226633Sdim unsigned &Amount) { 4408226633Sdim SMLoc Loc = Parser.getTok().getLoc(); 4409202878Srdivacky const AsmToken &Tok = Parser.getTok(); 4410198090Srdivacky if (Tok.isNot(AsmToken::Identifier)) 4411198090Srdivacky return true; 4412210299Sed StringRef ShiftName = Tok.getString(); 4413234353Sdim if (ShiftName == "lsl" || ShiftName == "LSL" || 4414234353Sdim ShiftName == "asl" || ShiftName == "ASL") 4415221345Sdim St = ARM_AM::lsl; 4416198090Srdivacky else if (ShiftName == "lsr" || ShiftName == "LSR") 4417221345Sdim St = ARM_AM::lsr; 4418198090Srdivacky else if (ShiftName == "asr" || ShiftName == "ASR") 4419221345Sdim St = ARM_AM::asr; 4420198090Srdivacky else if (ShiftName == "ror" || ShiftName == "ROR") 4421221345Sdim St = ARM_AM::ror; 4422198090Srdivacky else if (ShiftName == "rrx" || ShiftName == "RRX") 4423221345Sdim St = ARM_AM::rrx; 4424198090Srdivacky else 4425226633Sdim return Error(Loc, "illegal shift operator"); 4426202878Srdivacky Parser.Lex(); // Eat shift type token. 4427198090Srdivacky 4428226633Sdim // rrx stands alone. 4429226633Sdim Amount = 0; 4430226633Sdim if (St != ARM_AM::rrx) { 4431226633Sdim Loc = Parser.getTok().getLoc(); 4432226633Sdim // A '#' and a shift amount. 4433226633Sdim const AsmToken &HashTok = Parser.getTok(); 4434234353Sdim if (HashTok.isNot(AsmToken::Hash) && 4435234353Sdim HashTok.isNot(AsmToken::Dollar)) 4436226633Sdim return Error(HashTok.getLoc(), "'#' expected"); 4437226633Sdim Parser.Lex(); // Eat hash token. 4438198090Srdivacky 4439226633Sdim const MCExpr *Expr; 4440249423Sdim if (getParser().parseExpression(Expr)) 4441226633Sdim return true; 4442226633Sdim // Range check the immediate. 4443226633Sdim // lsl, ror: 0 <= imm <= 31 4444226633Sdim // lsr, asr: 0 <= imm <= 32 4445226633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr); 4446226633Sdim if (!CE) 4447226633Sdim return Error(Loc, "shift amount must be an immediate"); 4448226633Sdim int64_t Imm = CE->getValue(); 4449226633Sdim if (Imm < 0 || 4450226633Sdim ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) || 4451226633Sdim ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32)) 4452226633Sdim return Error(Loc, "immediate shift value out of range"); 4453243830Sdim // If <ShiftTy> #0, turn it into a no_shift. 4454243830Sdim if (Imm == 0) 4455243830Sdim St = ARM_AM::lsl; 4456243830Sdim // For consistency, treat lsr #32 and asr #32 as having immediate value 0. 4457243830Sdim if (Imm == 32) 4458243830Sdim Imm = 0; 4459226633Sdim Amount = Imm; 4460226633Sdim } 4461198090Srdivacky 4462198090Srdivacky return false; 4463198090Srdivacky} 4464198090Srdivacky 4465226633Sdim/// parseFPImm - A floating point immediate expression operand. 4466226633SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 4467226633SdimparseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 4468234353Sdim // Anything that can accept a floating point constant as an operand 4469249423Sdim // needs to go through here, as the regular parseExpression is 4470234353Sdim // integer only. 4471234353Sdim // 4472234353Sdim // This routine still creates a generic Immediate operand, containing 4473234353Sdim // a bitcast of the 64-bit floating point value. The various operands 4474234353Sdim // that accept floats can check whether the value is valid for them 4475234353Sdim // via the standard is*() predicates. 4476234353Sdim 4477226633Sdim SMLoc S = Parser.getTok().getLoc(); 4478226633Sdim 4479234353Sdim if (Parser.getTok().isNot(AsmToken::Hash) && 4480234353Sdim Parser.getTok().isNot(AsmToken::Dollar)) 4481226633Sdim return MatchOperand_NoMatch; 4482234353Sdim 4483234353Sdim // Disambiguate the VMOV forms that can accept an FP immediate. 4484234353Sdim // vmov.f32 <sreg>, #imm 4485234353Sdim // vmov.f64 <dreg>, #imm 4486234353Sdim // vmov.f32 <dreg>, #imm @ vector f32x2 4487234353Sdim // vmov.f32 <qreg>, #imm @ vector f32x4 4488234353Sdim // 4489234353Sdim // There are also the NEON VMOV instructions which expect an 4490234353Sdim // integer constant. Make sure we don't try to parse an FPImm 4491234353Sdim // for these: 4492234353Sdim // vmov.i{8|16|32|64} <dreg|qreg>, #imm 4493234353Sdim ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]); 4494234353Sdim if (!TyOp->isToken() || (TyOp->getToken() != ".f32" && 4495234353Sdim TyOp->getToken() != ".f64")) 4496234353Sdim return MatchOperand_NoMatch; 4497234353Sdim 4498263508Sdim Parser.Lex(); // Eat '#' or '$'. 4499226633Sdim 4500226633Sdim // Handle negation, as that still comes through as a separate token. 4501226633Sdim bool isNegative = false; 4502226633Sdim if (Parser.getTok().is(AsmToken::Minus)) { 4503226633Sdim isNegative = true; 4504226633Sdim Parser.Lex(); 4505226633Sdim } 4506226633Sdim const AsmToken &Tok = Parser.getTok(); 4507234353Sdim SMLoc Loc = Tok.getLoc(); 4508226633Sdim if (Tok.is(AsmToken::Real)) { 4509234353Sdim APFloat RealVal(APFloat::IEEEsingle, Tok.getString()); 4510226633Sdim uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue(); 4511226633Sdim // If we had a '-' in front, toggle the sign bit. 4512234353Sdim IntVal ^= (uint64_t)isNegative << 31; 4513226633Sdim Parser.Lex(); // Eat the token. 4514234353Sdim Operands.push_back(ARMOperand::CreateImm( 4515234353Sdim MCConstantExpr::Create(IntVal, getContext()), 4516234353Sdim S, Parser.getTok().getLoc())); 4517226633Sdim return MatchOperand_Success; 4518226633Sdim } 4519234353Sdim // Also handle plain integers. Instructions which allow floating point 4520234353Sdim // immediates also allow a raw encoded 8-bit value. 4521226633Sdim if (Tok.is(AsmToken::Integer)) { 4522226633Sdim int64_t Val = Tok.getIntVal(); 4523226633Sdim Parser.Lex(); // Eat the token. 4524226633Sdim if (Val > 255 || Val < 0) { 4525234353Sdim Error(Loc, "encoded floating point value out of range"); 4526226633Sdim return MatchOperand_ParseFail; 4527226633Sdim } 4528234353Sdim double RealVal = ARM_AM::getFPImmFloat(Val); 4529234353Sdim Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue(); 4530234353Sdim Operands.push_back(ARMOperand::CreateImm( 4531234353Sdim MCConstantExpr::Create(Val, getContext()), S, 4532234353Sdim Parser.getTok().getLoc())); 4533226633Sdim return MatchOperand_Success; 4534226633Sdim } 4535226633Sdim 4536234353Sdim Error(Loc, "invalid floating point immediate"); 4537226633Sdim return MatchOperand_ParseFail; 4538226633Sdim} 4539234353Sdim 4540198892Srdivacky/// Parse a arm instruction operand. For now this parses the operand regardless 4541198892Srdivacky/// of the mnemonic. 4542226633Sdimbool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands, 4543218893Sdim StringRef Mnemonic) { 4544206124Srdivacky SMLoc S, E; 4545218893Sdim 4546218893Sdim // Check if the current operand has a custom associated parser, if so, try to 4547218893Sdim // custom parse the operand, or fallback to the general approach. 4548218893Sdim OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); 4549218893Sdim if (ResTy == MatchOperand_Success) 4550218893Sdim return false; 4551218893Sdim // If there wasn't a custom match, try the generic matcher below. Otherwise, 4552218893Sdim // there was a match, but an error occurred, in which case, just return that 4553218893Sdim // the operand parsing failed. 4554218893Sdim if (ResTy == MatchOperand_ParseFail) 4555218893Sdim return true; 4556218893Sdim 4557198090Srdivacky switch (getLexer().getKind()) { 4558218893Sdim default: 4559218893Sdim Error(Parser.getTok().getLoc(), "unexpected token in operand"); 4560218893Sdim return true; 4561224145Sdim case AsmToken::Identifier: { 4562249423Sdim // If we've seen a branch mnemonic, the next operand must be a label. This 4563249423Sdim // is true even if the label is a register name. So "br r1" means branch to 4564249423Sdim // label "r1". 4565249423Sdim bool ExpectLabel = Mnemonic == "b" || Mnemonic == "bl"; 4566249423Sdim if (!ExpectLabel) { 4567249423Sdim if (!tryParseRegisterWithWriteBack(Operands)) 4568249423Sdim return false; 4569249423Sdim int Res = tryParseShiftRegister(Operands); 4570249423Sdim if (Res == 0) // success 4571249423Sdim return false; 4572249423Sdim else if (Res == -1) // irrecoverable error 4573249423Sdim return true; 4574249423Sdim // If this is VMRS, check for the apsr_nzcv operand. 4575249423Sdim if (Mnemonic == "vmrs" && 4576249423Sdim Parser.getTok().getString().equals_lower("apsr_nzcv")) { 4577249423Sdim S = Parser.getTok().getLoc(); 4578249423Sdim Parser.Lex(); 4579249423Sdim Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S)); 4580249423Sdim return false; 4581249423Sdim } 4582226633Sdim } 4583218893Sdim 4584218893Sdim // Fall though for the Identifier case that is not a register or a 4585218893Sdim // special name. 4586224145Sdim } 4587234353Sdim case AsmToken::LParen: // parenthesized expressions like (_strcmp-4) 4588218893Sdim case AsmToken::Integer: // things like 1f and 2b as a branch targets 4589234353Sdim case AsmToken::String: // quoted label names. 4590218893Sdim case AsmToken::Dot: { // . as a branch target 4591198396Srdivacky // This was not a register so parse other operands that start with an 4592198396Srdivacky // identifier (like labels) as expressions and create them as immediates. 4593198396Srdivacky const MCExpr *IdVal; 4594206124Srdivacky S = Parser.getTok().getLoc(); 4595249423Sdim if (getParser().parseExpression(IdVal)) 4596198396Srdivacky return true; 4597206124Srdivacky E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 4598218893Sdim Operands.push_back(ARMOperand::CreateImm(IdVal, S, E)); 4599198396Srdivacky return false; 4600218893Sdim } 4601198090Srdivacky case AsmToken::LBrac: 4602226633Sdim return parseMemory(Operands); 4603198090Srdivacky case AsmToken::LCurly: 4604226633Sdim return parseRegisterList(Operands); 4605234353Sdim case AsmToken::Dollar: 4606226633Sdim case AsmToken::Hash: { 4607198090Srdivacky // #42 -> immediate. 4608206124Srdivacky S = Parser.getTok().getLoc(); 4609202878Srdivacky Parser.Lex(); 4610234982Sdim 4611234982Sdim if (Parser.getTok().isNot(AsmToken::Colon)) { 4612234982Sdim bool isNegative = Parser.getTok().is(AsmToken::Minus); 4613234982Sdim const MCExpr *ImmVal; 4614249423Sdim if (getParser().parseExpression(ImmVal)) 4615234982Sdim return true; 4616234982Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal); 4617234982Sdim if (CE) { 4618234982Sdim int32_t Val = CE->getValue(); 4619234982Sdim if (isNegative && Val == 0) 4620234982Sdim ImmVal = MCConstantExpr::Create(INT32_MIN, getContext()); 4621234982Sdim } 4622234982Sdim E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 4623234982Sdim Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E)); 4624249423Sdim 4625249423Sdim // There can be a trailing '!' on operands that we want as a separate 4626249423Sdim // '!' Token operand. Handle that here. For example, the compatibilty 4627249423Sdim // alias for 'srsdb sp!, #imm' is 'srsdb #imm!'. 4628249423Sdim if (Parser.getTok().is(AsmToken::Exclaim)) { 4629249423Sdim Operands.push_back(ARMOperand::CreateToken(Parser.getTok().getString(), 4630249423Sdim Parser.getTok().getLoc())); 4631249423Sdim Parser.Lex(); // Eat exclaim token 4632249423Sdim } 4633234982Sdim return false; 4634226633Sdim } 4635234982Sdim // w/ a ':' after the '#', it's just like a plain ':'. 4636234982Sdim // FALLTHROUGH 4637226633Sdim } 4638218893Sdim case AsmToken::Colon: { 4639218893Sdim // ":lower16:" and ":upper16:" expression prefixes 4640218893Sdim // FIXME: Check it's an expression prefix, 4641218893Sdim // e.g. (FOO - :lower16:BAR) isn't legal. 4642218893Sdim ARMMCExpr::VariantKind RefKind; 4643226633Sdim if (parsePrefix(RefKind)) 4644218893Sdim return true; 4645218893Sdim 4646218893Sdim const MCExpr *SubExprVal; 4647249423Sdim if (getParser().parseExpression(SubExprVal)) 4648218893Sdim return true; 4649218893Sdim 4650218893Sdim const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal, 4651243830Sdim getContext()); 4652218893Sdim E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 4653218893Sdim Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E)); 4654218893Sdim return false; 4655198090Srdivacky } 4656218893Sdim } 4657198090Srdivacky} 4658198090Srdivacky 4659226633Sdim// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e. 4660218893Sdim// :lower16: and :upper16:. 4661226633Sdimbool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) { 4662218893Sdim RefKind = ARMMCExpr::VK_ARM_None; 4663212904Sdim 4664218893Sdim // :lower16: and :upper16: modifiers 4665218893Sdim assert(getLexer().is(AsmToken::Colon) && "expected a :"); 4666218893Sdim Parser.Lex(); // Eat ':' 4667212904Sdim 4668218893Sdim if (getLexer().isNot(AsmToken::Identifier)) { 4669218893Sdim Error(Parser.getTok().getLoc(), "expected prefix identifier in operand"); 4670218893Sdim return true; 4671218893Sdim } 4672218893Sdim 4673218893Sdim StringRef IDVal = Parser.getTok().getIdentifier(); 4674218893Sdim if (IDVal == "lower16") { 4675218893Sdim RefKind = ARMMCExpr::VK_ARM_LO16; 4676218893Sdim } else if (IDVal == "upper16") { 4677218893Sdim RefKind = ARMMCExpr::VK_ARM_HI16; 4678218893Sdim } else { 4679218893Sdim Error(Parser.getTok().getLoc(), "unexpected prefix in operand"); 4680218893Sdim return true; 4681218893Sdim } 4682218893Sdim Parser.Lex(); 4683218893Sdim 4684218893Sdim if (getLexer().isNot(AsmToken::Colon)) { 4685218893Sdim Error(Parser.getTok().getLoc(), "unexpected token after prefix"); 4686218893Sdim return true; 4687218893Sdim } 4688218893Sdim Parser.Lex(); // Eat the last ':' 4689218893Sdim return false; 4690218893Sdim} 4691218893Sdim 4692218893Sdim/// \brief Given a mnemonic, split out possible predication code and carry 4693218893Sdim/// setting letters to form a canonical mnemonic and flags. 4694218893Sdim// 4695218893Sdim// FIXME: Would be nice to autogen this. 4696226633Sdim// FIXME: This is a bit of a maze of special cases. 4697226633SdimStringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic, 4698226633Sdim unsigned &PredicationCode, 4699226633Sdim bool &CarrySetting, 4700226633Sdim unsigned &ProcessorIMod, 4701226633Sdim StringRef &ITMask) { 4702218893Sdim PredicationCode = ARMCC::AL; 4703218893Sdim CarrySetting = false; 4704218893Sdim ProcessorIMod = 0; 4705218893Sdim 4706218893Sdim // Ignore some mnemonics we know aren't predicated forms. 4707212904Sdim // 4708218893Sdim // FIXME: Would be nice to autogen this. 4709226633Sdim if ((Mnemonic == "movs" && isThumb()) || 4710226633Sdim Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" || 4711226633Sdim Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" || 4712226633Sdim Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" || 4713226633Sdim Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" || 4714263508Sdim Mnemonic == "vaclt" || Mnemonic == "vacle" || Mnemonic == "hlt" || 4715226633Sdim Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" || 4716226633Sdim Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" || 4717234353Sdim Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" || 4718263508Sdim Mnemonic == "fmuls" || Mnemonic == "vmaxnm" || Mnemonic == "vminnm" || 4719263508Sdim Mnemonic == "vcvta" || Mnemonic == "vcvtn" || Mnemonic == "vcvtp" || 4720263508Sdim Mnemonic == "vcvtm" || Mnemonic == "vrinta" || Mnemonic == "vrintn" || 4721263508Sdim Mnemonic == "vrintp" || Mnemonic == "vrintm" || Mnemonic.startswith("vsel")) 4722218893Sdim return Mnemonic; 4723218893Sdim 4724224145Sdim // First, split out any predication code. Ignore mnemonics we know aren't 4725224145Sdim // predicated but do have a carry-set and so weren't caught above. 4726226633Sdim if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" && 4727226633Sdim Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" && 4728226633Sdim Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" && 4729226633Sdim Mnemonic != "sbcs" && Mnemonic != "rscs") { 4730224145Sdim unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2)) 4731224145Sdim .Case("eq", ARMCC::EQ) 4732224145Sdim .Case("ne", ARMCC::NE) 4733224145Sdim .Case("hs", ARMCC::HS) 4734224145Sdim .Case("cs", ARMCC::HS) 4735224145Sdim .Case("lo", ARMCC::LO) 4736224145Sdim .Case("cc", ARMCC::LO) 4737224145Sdim .Case("mi", ARMCC::MI) 4738224145Sdim .Case("pl", ARMCC::PL) 4739224145Sdim .Case("vs", ARMCC::VS) 4740224145Sdim .Case("vc", ARMCC::VC) 4741224145Sdim .Case("hi", ARMCC::HI) 4742224145Sdim .Case("ls", ARMCC::LS) 4743224145Sdim .Case("ge", ARMCC::GE) 4744224145Sdim .Case("lt", ARMCC::LT) 4745224145Sdim .Case("gt", ARMCC::GT) 4746224145Sdim .Case("le", ARMCC::LE) 4747224145Sdim .Case("al", ARMCC::AL) 4748224145Sdim .Default(~0U); 4749224145Sdim if (CC != ~0U) { 4750224145Sdim Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2); 4751224145Sdim PredicationCode = CC; 4752224145Sdim } 4753218893Sdim } 4754212904Sdim 4755218893Sdim // Next, determine if we have a carry setting bit. We explicitly ignore all 4756218893Sdim // the instructions we know end in 's'. 4757218893Sdim if (Mnemonic.endswith("s") && 4758226633Sdim !(Mnemonic == "cps" || Mnemonic == "mls" || 4759226633Sdim Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" || 4760226633Sdim Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" || 4761226633Sdim Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" || 4762234353Sdim Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" || 4763234353Sdim Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" || 4764234353Sdim Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" || 4765234353Sdim Mnemonic == "fmuls" || Mnemonic == "fcmps" || Mnemonic == "fcmpzs" || 4766234353Sdim Mnemonic == "vfms" || Mnemonic == "vfnms" || 4767226633Sdim (Mnemonic == "movs" && isThumb()))) { 4768218893Sdim Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1); 4769218893Sdim CarrySetting = true; 4770218893Sdim } 4771198090Srdivacky 4772218893Sdim // The "cps" instruction can have a interrupt mode operand which is glued into 4773218893Sdim // the mnemonic. Check if this is the case, split it and parse the imod op 4774218893Sdim if (Mnemonic.startswith("cps")) { 4775218893Sdim // Split out any imod code. 4776218893Sdim unsigned IMod = 4777218893Sdim StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2)) 4778218893Sdim .Case("ie", ARM_PROC::IE) 4779218893Sdim .Case("id", ARM_PROC::ID) 4780218893Sdim .Default(~0U); 4781218893Sdim if (IMod != ~0U) { 4782218893Sdim Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2); 4783218893Sdim ProcessorIMod = IMod; 4784218893Sdim } 4785218893Sdim } 4786212904Sdim 4787226633Sdim // The "it" instruction has the condition mask on the end of the mnemonic. 4788226633Sdim if (Mnemonic.startswith("it")) { 4789226633Sdim ITMask = Mnemonic.slice(2, Mnemonic.size()); 4790226633Sdim Mnemonic = Mnemonic.slice(0, 2); 4791226633Sdim } 4792226633Sdim 4793218893Sdim return Mnemonic; 4794218893Sdim} 4795218893Sdim 4796218893Sdim/// \brief Given a canonical mnemonic, determine if the instruction ever allows 4797218893Sdim/// inclusion of carry set or predication code operands. 4798218893Sdim// 4799218893Sdim// FIXME: It would be nice to autogen this. 4800218893Sdimvoid ARMAsmParser:: 4801263508SdimgetMnemonicAcceptInfo(StringRef Mnemonic, StringRef FullInst, 4802263508Sdim bool &CanAcceptCarrySet, bool &CanAcceptPredicationCode) { 4803218893Sdim if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" || 4804218893Sdim Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" || 4805226633Sdim Mnemonic == "add" || Mnemonic == "adc" || 4806218893Sdim Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" || 4807226633Sdim Mnemonic == "orr" || Mnemonic == "mvn" || 4808218893Sdim Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" || 4809226633Sdim Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" || 4810234353Sdim Mnemonic == "vfm" || Mnemonic == "vfnm" || 4811226633Sdim (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" || 4812226633Sdim Mnemonic == "mla" || Mnemonic == "smlal" || 4813226633Sdim Mnemonic == "umlal" || Mnemonic == "umull"))) { 4814218893Sdim CanAcceptCarrySet = true; 4815226633Sdim } else 4816218893Sdim CanAcceptCarrySet = false; 4817218893Sdim 4818263508Sdim if (Mnemonic == "bkpt" || Mnemonic == "cbnz" || Mnemonic == "setend" || 4819263508Sdim Mnemonic == "cps" || Mnemonic == "it" || Mnemonic == "cbz" || 4820263508Sdim Mnemonic == "trap" || Mnemonic == "hlt" || Mnemonic.startswith("crc32") || 4821263508Sdim Mnemonic.startswith("cps") || Mnemonic.startswith("vsel") || 4822263508Sdim Mnemonic == "vmaxnm" || Mnemonic == "vminnm" || Mnemonic == "vcvta" || 4823263508Sdim Mnemonic == "vcvtn" || Mnemonic == "vcvtp" || Mnemonic == "vcvtm" || 4824263508Sdim Mnemonic == "vrinta" || Mnemonic == "vrintn" || Mnemonic == "vrintp" || 4825263508Sdim Mnemonic == "vrintm" || Mnemonic.startswith("aes") || 4826263508Sdim Mnemonic.startswith("sha1") || Mnemonic.startswith("sha256") || 4827263508Sdim (FullInst.startswith("vmull") && FullInst.endswith(".p64"))) { 4828263508Sdim // These mnemonics are never predicable 4829218893Sdim CanAcceptPredicationCode = false; 4830263508Sdim } else if (!isThumb()) { 4831263508Sdim // Some instructions are only predicable in Thumb mode 4832263508Sdim CanAcceptPredicationCode 4833263508Sdim = Mnemonic != "cdp2" && Mnemonic != "clrex" && Mnemonic != "mcr2" && 4834263508Sdim Mnemonic != "mcrr2" && Mnemonic != "mrc2" && Mnemonic != "mrrc2" && 4835263508Sdim Mnemonic != "dmb" && Mnemonic != "dsb" && Mnemonic != "isb" && 4836263508Sdim Mnemonic != "pld" && Mnemonic != "pli" && Mnemonic != "pldw" && 4837263508Sdim Mnemonic != "ldc2" && Mnemonic != "ldc2l" && 4838263508Sdim Mnemonic != "stc2" && Mnemonic != "stc2l" && 4839263508Sdim !Mnemonic.startswith("rfe") && !Mnemonic.startswith("srs"); 4840263508Sdim } else if (isThumbOne()) { 4841263508Sdim if (hasV6MOps()) 4842263508Sdim CanAcceptPredicationCode = Mnemonic != "movs"; 4843263508Sdim else 4844263508Sdim CanAcceptPredicationCode = Mnemonic != "nop" && Mnemonic != "movs"; 4845226633Sdim } else 4846218893Sdim CanAcceptPredicationCode = true; 4847218893Sdim} 4848218893Sdim 4849226633Sdimbool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic, 4850226633Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 4851226633Sdim // FIXME: This is all horribly hacky. We really need a better way to deal 4852226633Sdim // with optional operands like this in the matcher table. 4853226633Sdim 4854226633Sdim // The 'mov' mnemonic is special. One variant has a cc_out operand, while 4855226633Sdim // another does not. Specifically, the MOVW instruction does not. So we 4856226633Sdim // special case it here and remove the defaulted (non-setting) cc_out 4857226633Sdim // operand if that's the instruction we're trying to match. 4858226633Sdim // 4859226633Sdim // We do this as post-processing of the explicit operands rather than just 4860226633Sdim // conditionally adding the cc_out in the first place because we need 4861226633Sdim // to check the type of the parsed immediate operand. 4862226633Sdim if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() && 4863226633Sdim !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() && 4864226633Sdim static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() && 4865226633Sdim static_cast<ARMOperand*>(Operands[1])->getReg() == 0) 4866226633Sdim return true; 4867226633Sdim 4868226633Sdim // Register-register 'add' for thumb does not have a cc_out operand 4869226633Sdim // when there are only two register operands. 4870226633Sdim if (isThumb() && Mnemonic == "add" && Operands.size() == 5 && 4871226633Sdim static_cast<ARMOperand*>(Operands[3])->isReg() && 4872226633Sdim static_cast<ARMOperand*>(Operands[4])->isReg() && 4873226633Sdim static_cast<ARMOperand*>(Operands[1])->getReg() == 0) 4874226633Sdim return true; 4875226633Sdim // Register-register 'add' for thumb does not have a cc_out operand 4876226633Sdim // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do 4877226633Sdim // have to check the immediate range here since Thumb2 has a variant 4878226633Sdim // that can handle a different range and has a cc_out operand. 4879226633Sdim if (((isThumb() && Mnemonic == "add") || 4880226633Sdim (isThumbTwo() && Mnemonic == "sub")) && 4881226633Sdim Operands.size() == 6 && 4882226633Sdim static_cast<ARMOperand*>(Operands[3])->isReg() && 4883226633Sdim static_cast<ARMOperand*>(Operands[4])->isReg() && 4884226633Sdim static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP && 4885226633Sdim static_cast<ARMOperand*>(Operands[1])->getReg() == 0 && 4886234353Sdim ((Mnemonic == "add" &&static_cast<ARMOperand*>(Operands[5])->isReg()) || 4887226633Sdim static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4())) 4888226633Sdim return true; 4889226633Sdim // For Thumb2, add/sub immediate does not have a cc_out operand for the 4890226633Sdim // imm0_4095 variant. That's the least-preferred variant when 4891226633Sdim // selecting via the generic "add" mnemonic, so to know that we 4892226633Sdim // should remove the cc_out operand, we have to explicitly check that 4893226633Sdim // it's not one of the other variants. Ugh. 4894226633Sdim if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") && 4895226633Sdim Operands.size() == 6 && 4896226633Sdim static_cast<ARMOperand*>(Operands[3])->isReg() && 4897226633Sdim static_cast<ARMOperand*>(Operands[4])->isReg() && 4898226633Sdim static_cast<ARMOperand*>(Operands[5])->isImm()) { 4899226633Sdim // Nest conditions rather than one big 'if' statement for readability. 4900226633Sdim // 4901226633Sdim // If both registers are low, we're in an IT block, and the immediate is 4902226633Sdim // in range, we should use encoding T1 instead, which has a cc_out. 4903226633Sdim if (inITBlock() && 4904226633Sdim isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) && 4905226633Sdim isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) && 4906226633Sdim static_cast<ARMOperand*>(Operands[5])->isImm0_7()) 4907226633Sdim return false; 4908263508Sdim // Check against T3. If the second register is the PC, this is an 4909263508Sdim // alternate form of ADR, which uses encoding T4, so check for that too. 4910263508Sdim if (static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC && 4911263508Sdim static_cast<ARMOperand*>(Operands[5])->isT2SOImm()) 4912263508Sdim return false; 4913226633Sdim 4914226633Sdim // Otherwise, we use encoding T4, which does not have a cc_out 4915226633Sdim // operand. 4916226633Sdim return true; 4917226633Sdim } 4918226633Sdim 4919226633Sdim // The thumb2 multiply instruction doesn't have a CCOut register, so 4920226633Sdim // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to 4921226633Sdim // use the 16-bit encoding or not. 4922226633Sdim if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 && 4923226633Sdim static_cast<ARMOperand*>(Operands[1])->getReg() == 0 && 4924226633Sdim static_cast<ARMOperand*>(Operands[3])->isReg() && 4925226633Sdim static_cast<ARMOperand*>(Operands[4])->isReg() && 4926226633Sdim static_cast<ARMOperand*>(Operands[5])->isReg() && 4927226633Sdim // If the registers aren't low regs, the destination reg isn't the 4928226633Sdim // same as one of the source regs, or the cc_out operand is zero 4929226633Sdim // outside of an IT block, we have to use the 32-bit encoding, so 4930226633Sdim // remove the cc_out operand. 4931226633Sdim (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) || 4932226633Sdim !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) || 4933234353Sdim !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) || 4934226633Sdim !inITBlock() || 4935226633Sdim (static_cast<ARMOperand*>(Operands[3])->getReg() != 4936226633Sdim static_cast<ARMOperand*>(Operands[5])->getReg() && 4937226633Sdim static_cast<ARMOperand*>(Operands[3])->getReg() != 4938226633Sdim static_cast<ARMOperand*>(Operands[4])->getReg()))) 4939226633Sdim return true; 4940226633Sdim 4941234353Sdim // Also check the 'mul' syntax variant that doesn't specify an explicit 4942234353Sdim // destination register. 4943234353Sdim if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 && 4944234353Sdim static_cast<ARMOperand*>(Operands[1])->getReg() == 0 && 4945234353Sdim static_cast<ARMOperand*>(Operands[3])->isReg() && 4946234353Sdim static_cast<ARMOperand*>(Operands[4])->isReg() && 4947234353Sdim // If the registers aren't low regs or the cc_out operand is zero 4948234353Sdim // outside of an IT block, we have to use the 32-bit encoding, so 4949234353Sdim // remove the cc_out operand. 4950234353Sdim (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) || 4951234353Sdim !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) || 4952234353Sdim !inITBlock())) 4953234353Sdim return true; 4954226633Sdim 4955226633Sdim 4956234353Sdim 4957226633Sdim // Register-register 'add/sub' for thumb does not have a cc_out operand 4958226633Sdim // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also 4959226633Sdim // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't 4960226633Sdim // right, this will result in better diagnostics (which operand is off) 4961226633Sdim // anyway. 4962226633Sdim if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") && 4963226633Sdim (Operands.size() == 5 || Operands.size() == 6) && 4964226633Sdim static_cast<ARMOperand*>(Operands[3])->isReg() && 4965226633Sdim static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP && 4966234353Sdim static_cast<ARMOperand*>(Operands[1])->getReg() == 0 && 4967234353Sdim (static_cast<ARMOperand*>(Operands[4])->isImm() || 4968234353Sdim (Operands.size() == 6 && 4969234353Sdim static_cast<ARMOperand*>(Operands[5])->isImm()))) 4970226633Sdim return true; 4971226633Sdim 4972226633Sdim return false; 4973226633Sdim} 4974226633Sdim 4975263508Sdimbool ARMAsmParser::shouldOmitPredicateOperand( 4976263508Sdim StringRef Mnemonic, SmallVectorImpl<MCParsedAsmOperand *> &Operands) { 4977263508Sdim // VRINT{Z, R, X} have a predicate operand in VFP, but not in NEON 4978263508Sdim unsigned RegIdx = 3; 4979263508Sdim if ((Mnemonic == "vrintz" || Mnemonic == "vrintx" || Mnemonic == "vrintr") && 4980263508Sdim static_cast<ARMOperand *>(Operands[2])->getToken() == ".f32") { 4981263508Sdim if (static_cast<ARMOperand *>(Operands[3])->isToken() && 4982263508Sdim static_cast<ARMOperand *>(Operands[3])->getToken() == ".f32") 4983263508Sdim RegIdx = 4; 4984263508Sdim 4985263508Sdim if (static_cast<ARMOperand *>(Operands[RegIdx])->isReg() && 4986263508Sdim (ARMMCRegisterClasses[ARM::DPRRegClassID] 4987263508Sdim .contains(static_cast<ARMOperand *>(Operands[RegIdx])->getReg()) || 4988263508Sdim ARMMCRegisterClasses[ARM::QPRRegClassID] 4989263508Sdim .contains(static_cast<ARMOperand *>(Operands[RegIdx])->getReg()))) 4990263508Sdim return true; 4991263508Sdim } 4992263508Sdim return false; 4993263508Sdim} 4994263508Sdim 4995234353Sdimstatic bool isDataTypeToken(StringRef Tok) { 4996234353Sdim return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" || 4997234353Sdim Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" || 4998234353Sdim Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" || 4999234353Sdim Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" || 5000234353Sdim Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" || 5001234353Sdim Tok == ".f" || Tok == ".d"; 5002234353Sdim} 5003234353Sdim 5004234353Sdim// FIXME: This bit should probably be handled via an explicit match class 5005234353Sdim// in the .td files that matches the suffix instead of having it be 5006234353Sdim// a literal string token the way it is now. 5007234353Sdimstatic bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) { 5008234353Sdim return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm"); 5009234353Sdim} 5010251662Sdimstatic void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features, 5011251662Sdim unsigned VariantID); 5012218893Sdim/// Parse an arm instruction mnemonic followed by its operands. 5013243830Sdimbool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 5014243830Sdim SMLoc NameLoc, 5015218893Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 5016234353Sdim // Apply mnemonic aliases before doing anything else, as the destination 5017234353Sdim // mnemnonic may include suffices and we want to handle them normally. 5018234353Sdim // The generic tblgen'erated code does this later, at the start of 5019234353Sdim // MatchInstructionImpl(), but that's too late for aliases that include 5020234353Sdim // any sort of suffix. 5021234353Sdim unsigned AvailableFeatures = getAvailableFeatures(); 5022251662Sdim unsigned AssemblerDialect = getParser().getAssemblerDialect(); 5023251662Sdim applyMnemonicAliases(Name, AvailableFeatures, AssemblerDialect); 5024234353Sdim 5025234353Sdim // First check for the ARM-specific .req directive. 5026234353Sdim if (Parser.getTok().is(AsmToken::Identifier) && 5027234353Sdim Parser.getTok().getIdentifier() == ".req") { 5028234353Sdim parseDirectiveReq(Name, NameLoc); 5029234353Sdim // We always return 'error' for this, as we're done with this 5030234353Sdim // statement and don't need to match the 'instruction." 5031234353Sdim return true; 5032234353Sdim } 5033234353Sdim 5034218893Sdim // Create the leading tokens for the mnemonic, split by '.' characters. 5035218893Sdim size_t Start = 0, Next = Name.find('.'); 5036226633Sdim StringRef Mnemonic = Name.slice(Start, Next); 5037218893Sdim 5038218893Sdim // Split out the predication code and carry setting flag from the mnemonic. 5039218893Sdim unsigned PredicationCode; 5040218893Sdim unsigned ProcessorIMod; 5041218893Sdim bool CarrySetting; 5042226633Sdim StringRef ITMask; 5043226633Sdim Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting, 5044226633Sdim ProcessorIMod, ITMask); 5045218893Sdim 5046226633Sdim // In Thumb1, only the branch (B) instruction can be predicated. 5047226633Sdim if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") { 5048249423Sdim Parser.eatToEndOfStatement(); 5049226633Sdim return Error(NameLoc, "conditional execution not supported in Thumb1"); 5050226633Sdim } 5051218893Sdim 5052226633Sdim Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc)); 5053226633Sdim 5054226633Sdim // Handle the IT instruction ITMask. Convert it to a bitmask. This 5055226633Sdim // is the mask as it will be for the IT encoding if the conditional 5056226633Sdim // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case 5057226633Sdim // where the conditional bit0 is zero, the instruction post-processing 5058226633Sdim // will adjust the mask accordingly. 5059226633Sdim if (Mnemonic == "it") { 5060226633Sdim SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2); 5061226633Sdim if (ITMask.size() > 3) { 5062249423Sdim Parser.eatToEndOfStatement(); 5063226633Sdim return Error(Loc, "too many conditions on IT instruction"); 5064226633Sdim } 5065226633Sdim unsigned Mask = 8; 5066226633Sdim for (unsigned i = ITMask.size(); i != 0; --i) { 5067226633Sdim char pos = ITMask[i - 1]; 5068226633Sdim if (pos != 't' && pos != 'e') { 5069249423Sdim Parser.eatToEndOfStatement(); 5070226633Sdim return Error(Loc, "illegal IT block condition mask '" + ITMask + "'"); 5071226633Sdim } 5072226633Sdim Mask >>= 1; 5073226633Sdim if (ITMask[i - 1] == 't') 5074226633Sdim Mask |= 8; 5075226633Sdim } 5076226633Sdim Operands.push_back(ARMOperand::CreateITMask(Mask, Loc)); 5077226633Sdim } 5078226633Sdim 5079226633Sdim // FIXME: This is all a pretty gross hack. We should automatically handle 5080226633Sdim // optional operands like this via tblgen. 5081226633Sdim 5082218893Sdim // Next, add the CCOut and ConditionCode operands, if needed. 5083218893Sdim // 5084218893Sdim // For mnemonics which can ever incorporate a carry setting bit or predication 5085218893Sdim // code, our matching model involves us always generating CCOut and 5086218893Sdim // ConditionCode operands to match the mnemonic "as written" and then we let 5087218893Sdim // the matcher deal with finding the right instruction or generating an 5088218893Sdim // appropriate error. 5089218893Sdim bool CanAcceptCarrySet, CanAcceptPredicationCode; 5090263508Sdim getMnemonicAcceptInfo(Mnemonic, Name, CanAcceptCarrySet, CanAcceptPredicationCode); 5091218893Sdim 5092224145Sdim // If we had a carry-set on an instruction that can't do that, issue an 5093224145Sdim // error. 5094224145Sdim if (!CanAcceptCarrySet && CarrySetting) { 5095249423Sdim Parser.eatToEndOfStatement(); 5096226633Sdim return Error(NameLoc, "instruction '" + Mnemonic + 5097224145Sdim "' can not set flags, but 's' suffix specified"); 5098224145Sdim } 5099226633Sdim // If we had a predication code on an instruction that can't do that, issue an 5100226633Sdim // error. 5101226633Sdim if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) { 5102249423Sdim Parser.eatToEndOfStatement(); 5103226633Sdim return Error(NameLoc, "instruction '" + Mnemonic + 5104226633Sdim "' is not predicable, but condition code specified"); 5105226633Sdim } 5106224145Sdim 5107218893Sdim // Add the carry setting operand, if necessary. 5108226633Sdim if (CanAcceptCarrySet) { 5109226633Sdim SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size()); 5110218893Sdim Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0, 5111226633Sdim Loc)); 5112226633Sdim } 5113218893Sdim 5114218893Sdim // Add the predication code operand, if necessary. 5115218893Sdim if (CanAcceptPredicationCode) { 5116226633Sdim SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() + 5117226633Sdim CarrySetting); 5118218893Sdim Operands.push_back(ARMOperand::CreateCondCode( 5119226633Sdim ARMCC::CondCodes(PredicationCode), Loc)); 5120218893Sdim } 5121218893Sdim 5122218893Sdim // Add the processor imod operand, if necessary. 5123218893Sdim if (ProcessorIMod) { 5124218893Sdim Operands.push_back(ARMOperand::CreateImm( 5125218893Sdim MCConstantExpr::Create(ProcessorIMod, getContext()), 5126218893Sdim NameLoc, NameLoc)); 5127218893Sdim } 5128218893Sdim 5129212904Sdim // Add the remaining tokens in the mnemonic. 5130212904Sdim while (Next != StringRef::npos) { 5131212904Sdim Start = Next; 5132212904Sdim Next = Name.find('.', Start + 1); 5133218893Sdim StringRef ExtraToken = Name.slice(Start, Next); 5134212904Sdim 5135234353Sdim // Some NEON instructions have an optional datatype suffix that is 5136234353Sdim // completely ignored. Check for that. 5137234353Sdim if (isDataTypeToken(ExtraToken) && 5138234353Sdim doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken)) 5139234353Sdim continue; 5140234353Sdim 5141263508Sdim // For for ARM mode generate an error if the .n qualifier is used. 5142263508Sdim if (ExtraToken == ".n" && !isThumb()) { 5143226633Sdim SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start); 5144263508Sdim return Error(Loc, "instruction with .n (narrow) qualifier not allowed in " 5145263508Sdim "arm mode"); 5146263508Sdim } 5147263508Sdim 5148263508Sdim // The .n qualifier is always discarded as that is what the tables 5149263508Sdim // and matcher expect. In ARM mode the .w qualifier has no effect, 5150263508Sdim // so discard it to avoid errors that can be caused by the matcher. 5151263508Sdim if (ExtraToken != ".n" && (isThumb() || ExtraToken != ".w")) { 5152263508Sdim SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start); 5153226633Sdim Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc)); 5154226633Sdim } 5155212904Sdim } 5156212904Sdim 5157212904Sdim // Read the remaining operands. 5158198090Srdivacky if (getLexer().isNot(AsmToken::EndOfStatement)) { 5159198090Srdivacky // Read the first operand. 5160226633Sdim if (parseOperand(Operands, Mnemonic)) { 5161249423Sdim Parser.eatToEndOfStatement(); 5162218893Sdim return true; 5163218893Sdim } 5164198090Srdivacky 5165198090Srdivacky while (getLexer().is(AsmToken::Comma)) { 5166202878Srdivacky Parser.Lex(); // Eat the comma. 5167198090Srdivacky 5168198090Srdivacky // Parse and remember the operand. 5169226633Sdim if (parseOperand(Operands, Mnemonic)) { 5170249423Sdim Parser.eatToEndOfStatement(); 5171218893Sdim return true; 5172218893Sdim } 5173198090Srdivacky } 5174198090Srdivacky } 5175218893Sdim 5176218893Sdim if (getLexer().isNot(AsmToken::EndOfStatement)) { 5177226633Sdim SMLoc Loc = getLexer().getLoc(); 5178249423Sdim Parser.eatToEndOfStatement(); 5179226633Sdim return Error(Loc, "unexpected token in argument list"); 5180218893Sdim } 5181218893Sdim 5182218893Sdim Parser.Lex(); // Consume the EndOfStatement 5183226633Sdim 5184226633Sdim // Some instructions, mostly Thumb, have forms for the same mnemonic that 5185226633Sdim // do and don't have a cc_out optional-def operand. With some spot-checks 5186226633Sdim // of the operand list, we can figure out which variant we're trying to 5187226633Sdim // parse and adjust accordingly before actually matching. We shouldn't ever 5188226633Sdim // try to remove a cc_out operand that was explicitly set on the the 5189226633Sdim // mnemonic, of course (CarrySetting == true). Reason number #317 the 5190226633Sdim // table driven matcher doesn't fit well with the ARM instruction set. 5191226633Sdim if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) { 5192226633Sdim ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]); 5193226633Sdim Operands.erase(Operands.begin() + 1); 5194226633Sdim delete Op; 5195226633Sdim } 5196226633Sdim 5197263508Sdim // Some instructions have the same mnemonic, but don't always 5198263508Sdim // have a predicate. Distinguish them here and delete the 5199263508Sdim // predicate if needed. 5200263508Sdim if (shouldOmitPredicateOperand(Mnemonic, Operands)) { 5201263508Sdim ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]); 5202263508Sdim Operands.erase(Operands.begin() + 1); 5203263508Sdim delete Op; 5204263508Sdim } 5205263508Sdim 5206226633Sdim // ARM mode 'blx' need special handling, as the register operand version 5207226633Sdim // is predicable, but the label operand version is not. So, we can't rely 5208226633Sdim // on the Mnemonic based checking to correctly figure out when to put 5209226633Sdim // a k_CondCode operand in the list. If we're trying to match the label 5210226633Sdim // version, remove the k_CondCode operand here. 5211226633Sdim if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 && 5212226633Sdim static_cast<ARMOperand*>(Operands[2])->isImm()) { 5213226633Sdim ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]); 5214226633Sdim Operands.erase(Operands.begin() + 1); 5215226633Sdim delete Op; 5216226633Sdim } 5217226633Sdim 5218249423Sdim // Adjust operands of ldrexd/strexd to MCK_GPRPair. 5219249423Sdim // ldrexd/strexd require even/odd GPR pair. To enforce this constraint, 5220249423Sdim // a single GPRPair reg operand is used in the .td file to replace the two 5221249423Sdim // GPRs. However, when parsing from asm, the two GRPs cannot be automatically 5222249423Sdim // expressed as a GPRPair, so we have to manually merge them. 5223249423Sdim // FIXME: We would really like to be able to tablegen'erate this. 5224249423Sdim if (!isThumb() && Operands.size() > 4 && 5225263508Sdim (Mnemonic == "ldrexd" || Mnemonic == "strexd" || Mnemonic == "ldaexd" || 5226263508Sdim Mnemonic == "stlexd")) { 5227263508Sdim bool isLoad = (Mnemonic == "ldrexd" || Mnemonic == "ldaexd"); 5228249423Sdim unsigned Idx = isLoad ? 2 : 3; 5229249423Sdim ARMOperand* Op1 = static_cast<ARMOperand*>(Operands[Idx]); 5230249423Sdim ARMOperand* Op2 = static_cast<ARMOperand*>(Operands[Idx+1]); 5231249423Sdim 5232249423Sdim const MCRegisterClass& MRC = MRI->getRegClass(ARM::GPRRegClassID); 5233249423Sdim // Adjust only if Op1 and Op2 are GPRs. 5234249423Sdim if (Op1->isReg() && Op2->isReg() && MRC.contains(Op1->getReg()) && 5235249423Sdim MRC.contains(Op2->getReg())) { 5236249423Sdim unsigned Reg1 = Op1->getReg(); 5237249423Sdim unsigned Reg2 = Op2->getReg(); 5238249423Sdim unsigned Rt = MRI->getEncodingValue(Reg1); 5239249423Sdim unsigned Rt2 = MRI->getEncodingValue(Reg2); 5240249423Sdim 5241249423Sdim // Rt2 must be Rt + 1 and Rt must be even. 5242249423Sdim if (Rt + 1 != Rt2 || (Rt & 1)) { 5243249423Sdim Error(Op2->getStartLoc(), isLoad ? 5244249423Sdim "destination operands must be sequential" : 5245249423Sdim "source operands must be sequential"); 5246249423Sdim return true; 5247249423Sdim } 5248249423Sdim unsigned NewReg = MRI->getMatchingSuperReg(Reg1, ARM::gsub_0, 5249249423Sdim &(MRI->getRegClass(ARM::GPRPairRegClassID))); 5250249423Sdim Operands.erase(Operands.begin() + Idx, Operands.begin() + Idx + 2); 5251249423Sdim Operands.insert(Operands.begin() + Idx, ARMOperand::CreateReg( 5252249423Sdim NewReg, Op1->getStartLoc(), Op2->getEndLoc())); 5253249423Sdim delete Op1; 5254249423Sdim delete Op2; 5255226633Sdim } 5256226633Sdim } 5257226633Sdim 5258263508Sdim // FIXME: As said above, this is all a pretty gross hack. This instruction 5259263508Sdim // does not fit with other "subs" and tblgen. 5260263508Sdim // Adjust operands of B9.3.19 SUBS PC, LR, #imm (Thumb2) system instruction 5261263508Sdim // so the Mnemonic is the original name "subs" and delete the predicate 5262263508Sdim // operand so it will match the table entry. 5263263508Sdim if (isThumbTwo() && Mnemonic == "sub" && Operands.size() == 6 && 5264263508Sdim static_cast<ARMOperand*>(Operands[3])->isReg() && 5265263508Sdim static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::PC && 5266263508Sdim static_cast<ARMOperand*>(Operands[4])->isReg() && 5267263508Sdim static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::LR && 5268263508Sdim static_cast<ARMOperand*>(Operands[5])->isImm()) { 5269263508Sdim ARMOperand *Op0 = static_cast<ARMOperand*>(Operands[0]); 5270263508Sdim Operands.erase(Operands.begin()); 5271263508Sdim delete Op0; 5272263508Sdim Operands.insert(Operands.begin(), ARMOperand::CreateToken(Name, NameLoc)); 5273263508Sdim 5274263508Sdim ARMOperand *Op1 = static_cast<ARMOperand*>(Operands[1]); 5275263508Sdim Operands.erase(Operands.begin() + 1); 5276263508Sdim delete Op1; 5277263508Sdim } 5278202375Srdivacky return false; 5279198090Srdivacky} 5280198090Srdivacky 5281226633Sdim// Validate context-sensitive operand constraints. 5282226633Sdim 5283226633Sdim// return 'true' if register list contains non-low GPR registers, 5284226633Sdim// 'false' otherwise. If Reg is in the register list or is HiReg, set 5285226633Sdim// 'containsReg' to true. 5286226633Sdimstatic bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg, 5287226633Sdim unsigned HiReg, bool &containsReg) { 5288226633Sdim containsReg = false; 5289226633Sdim for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) { 5290226633Sdim unsigned OpReg = Inst.getOperand(i).getReg(); 5291226633Sdim if (OpReg == Reg) 5292226633Sdim containsReg = true; 5293226633Sdim // Anything other than a low register isn't legal here. 5294226633Sdim if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg)) 5295226633Sdim return true; 5296226633Sdim } 5297226633Sdim return false; 5298226633Sdim} 5299226633Sdim 5300226633Sdim// Check if the specified regisgter is in the register list of the inst, 5301226633Sdim// starting at the indicated operand number. 5302226633Sdimstatic bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) { 5303226633Sdim for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) { 5304226633Sdim unsigned OpReg = Inst.getOperand(i).getReg(); 5305226633Sdim if (OpReg == Reg) 5306226633Sdim return true; 5307226633Sdim } 5308226633Sdim return false; 5309226633Sdim} 5310226633Sdim 5311263508Sdim// Return true if instruction has the interesting property of being 5312263508Sdim// allowed in IT blocks, but not being predicable. 5313263508Sdimstatic bool instIsBreakpoint(const MCInst &Inst) { 5314263508Sdim return Inst.getOpcode() == ARM::tBKPT || 5315263508Sdim Inst.getOpcode() == ARM::BKPT || 5316263508Sdim Inst.getOpcode() == ARM::tHLT || 5317263508Sdim Inst.getOpcode() == ARM::HLT; 5318263508Sdim 5319226633Sdim} 5320226633Sdim 5321226633Sdim// FIXME: We would really like to be able to tablegen'erate this. 5322218893Sdimbool ARMAsmParser:: 5323226633SdimvalidateInstruction(MCInst &Inst, 5324226633Sdim const SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 5325263508Sdim const MCInstrDesc &MCID = MII.get(Inst.getOpcode()); 5326226633Sdim SMLoc Loc = Operands[0]->getStartLoc(); 5327263508Sdim 5328226633Sdim // Check the IT block state first. 5329263508Sdim // NOTE: BKPT and HLT instructions have the interesting property of being 5330263508Sdim // allowed in IT blocks, but not being predicable. They just always execute. 5331263508Sdim if (inITBlock() && !instIsBreakpoint(Inst)) { 5332263508Sdim unsigned Bit = 1; 5333226633Sdim if (ITState.FirstCond) 5334226633Sdim ITState.FirstCond = false; 5335226633Sdim else 5336263508Sdim Bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1; 5337226633Sdim // The instruction must be predicable. 5338226633Sdim if (!MCID.isPredicable()) 5339226633Sdim return Error(Loc, "instructions in IT block must be predicable"); 5340226633Sdim unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm(); 5341263508Sdim unsigned ITCond = Bit ? ITState.Cond : 5342226633Sdim ARMCC::getOppositeCondition(ITState.Cond); 5343226633Sdim if (Cond != ITCond) { 5344226633Sdim // Find the condition code Operand to get its SMLoc information. 5345226633Sdim SMLoc CondLoc; 5346263508Sdim for (unsigned I = 1; I < Operands.size(); ++I) 5347263508Sdim if (static_cast<ARMOperand*>(Operands[I])->isCondCode()) 5348263508Sdim CondLoc = Operands[I]->getStartLoc(); 5349226633Sdim return Error(CondLoc, "incorrect condition in IT block; got '" + 5350226633Sdim StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) + 5351226633Sdim "', but expected '" + 5352226633Sdim ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'"); 5353226633Sdim } 5354226633Sdim // Check for non-'al' condition codes outside of the IT block. 5355226633Sdim } else if (isThumbTwo() && MCID.isPredicable() && 5356226633Sdim Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() != 5357263508Sdim ARMCC::AL && Inst.getOpcode() != ARM::tBcc && 5358263508Sdim Inst.getOpcode() != ARM::t2Bcc) 5359226633Sdim return Error(Loc, "predicated instructions must be in IT block"); 5360226633Sdim 5361263508Sdim const unsigned Opcode = Inst.getOpcode(); 5362263508Sdim switch (Opcode) { 5363226633Sdim case ARM::LDRD: 5364226633Sdim case ARM::LDRD_PRE: 5365249423Sdim case ARM::LDRD_POST: { 5366263508Sdim const unsigned RtReg = Inst.getOperand(0).getReg(); 5367263508Sdim 5368263508Sdim // Rt can't be R14. 5369263508Sdim if (RtReg == ARM::LR) 5370263508Sdim return Error(Operands[3]->getStartLoc(), 5371263508Sdim "Rt can't be R14"); 5372263508Sdim 5373263508Sdim const unsigned Rt = MRI->getEncodingValue(RtReg); 5374263508Sdim // Rt must be even-numbered. 5375263508Sdim if ((Rt & 1) == 1) 5376263508Sdim return Error(Operands[3]->getStartLoc(), 5377263508Sdim "Rt must be even-numbered"); 5378263508Sdim 5379226633Sdim // Rt2 must be Rt + 1. 5380263508Sdim const unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(1).getReg()); 5381226633Sdim if (Rt2 != Rt + 1) 5382226633Sdim return Error(Operands[3]->getStartLoc(), 5383226633Sdim "destination operands must be sequential"); 5384263508Sdim 5385263508Sdim if (Opcode == ARM::LDRD_PRE || Opcode == ARM::LDRD_POST) { 5386263508Sdim const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(3).getReg()); 5387263508Sdim // For addressing modes with writeback, the base register needs to be 5388263508Sdim // different from the destination registers. 5389263508Sdim if (Rn == Rt || Rn == Rt2) 5390263508Sdim return Error(Operands[3]->getStartLoc(), 5391263508Sdim "base register needs to be different from destination " 5392263508Sdim "registers"); 5393263508Sdim } 5394263508Sdim 5395226633Sdim return false; 5396226633Sdim } 5397263508Sdim case ARM::t2LDRDi8: 5398263508Sdim case ARM::t2LDRD_PRE: 5399263508Sdim case ARM::t2LDRD_POST: { 5400263508Sdim // Rt2 must be different from Rt. 5401263508Sdim unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg()); 5402263508Sdim unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(1).getReg()); 5403263508Sdim if (Rt2 == Rt) 5404263508Sdim return Error(Operands[3]->getStartLoc(), 5405263508Sdim "destination operands can't be identical"); 5406263508Sdim return false; 5407263508Sdim } 5408226633Sdim case ARM::STRD: { 5409226633Sdim // Rt2 must be Rt + 1. 5410239462Sdim unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg()); 5411239462Sdim unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(1).getReg()); 5412226633Sdim if (Rt2 != Rt + 1) 5413226633Sdim return Error(Operands[3]->getStartLoc(), 5414226633Sdim "source operands must be sequential"); 5415226633Sdim return false; 5416226633Sdim } 5417226633Sdim case ARM::STRD_PRE: 5418249423Sdim case ARM::STRD_POST: { 5419226633Sdim // Rt2 must be Rt + 1. 5420239462Sdim unsigned Rt = MRI->getEncodingValue(Inst.getOperand(1).getReg()); 5421239462Sdim unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(2).getReg()); 5422226633Sdim if (Rt2 != Rt + 1) 5423226633Sdim return Error(Operands[3]->getStartLoc(), 5424226633Sdim "source operands must be sequential"); 5425226633Sdim return false; 5426226633Sdim } 5427226633Sdim case ARM::SBFX: 5428226633Sdim case ARM::UBFX: { 5429263508Sdim // Width must be in range [1, 32-lsb]. 5430263508Sdim unsigned LSB = Inst.getOperand(2).getImm(); 5431263508Sdim unsigned Widthm1 = Inst.getOperand(3).getImm(); 5432263508Sdim if (Widthm1 >= 32 - LSB) 5433226633Sdim return Error(Operands[5]->getStartLoc(), 5434226633Sdim "bitfield width must be in range [1,32-lsb]"); 5435226633Sdim return false; 5436226633Sdim } 5437263508Sdim // Notionally handles ARM::tLDMIA_UPD too. 5438226633Sdim case ARM::tLDMIA: { 5439226633Sdim // If we're parsing Thumb2, the .w variant is available and handles 5440263508Sdim // most cases that are normally illegal for a Thumb1 LDM instruction. 5441263508Sdim // We'll make the transformation in processInstruction() if necessary. 5442226633Sdim // 5443226633Sdim // Thumb LDM instructions are writeback iff the base register is not 5444226633Sdim // in the register list. 5445226633Sdim unsigned Rn = Inst.getOperand(0).getReg(); 5446263508Sdim bool HasWritebackToken = 5447226633Sdim (static_cast<ARMOperand*>(Operands[3])->isToken() && 5448226633Sdim static_cast<ARMOperand*>(Operands[3])->getToken() == "!"); 5449263508Sdim bool ListContainsBase; 5450263508Sdim if (checkLowRegisterList(Inst, 3, Rn, 0, ListContainsBase) && !isThumbTwo()) 5451263508Sdim return Error(Operands[3 + HasWritebackToken]->getStartLoc(), 5452226633Sdim "registers must be in range r0-r7"); 5453226633Sdim // If we should have writeback, then there should be a '!' token. 5454263508Sdim if (!ListContainsBase && !HasWritebackToken && !isThumbTwo()) 5455226633Sdim return Error(Operands[2]->getStartLoc(), 5456226633Sdim "writeback operator '!' expected"); 5457226633Sdim // If we should not have writeback, there must not be a '!'. This is 5458226633Sdim // true even for the 32-bit wide encodings. 5459263508Sdim if (ListContainsBase && HasWritebackToken) 5460226633Sdim return Error(Operands[3]->getStartLoc(), 5461226633Sdim "writeback operator '!' not allowed when base register " 5462226633Sdim "in register list"); 5463226633Sdim 5464226633Sdim break; 5465226633Sdim } 5466263508Sdim case ARM::LDMIA_UPD: 5467263508Sdim case ARM::LDMDB_UPD: 5468263508Sdim case ARM::LDMIB_UPD: 5469263508Sdim case ARM::LDMDA_UPD: 5470263508Sdim // ARM variants loading and updating the same register are only officially 5471263508Sdim // UNPREDICTABLE on v7 upwards. Goodness knows what they did before. 5472263508Sdim if (!hasV7Ops()) 5473263508Sdim break; 5474263508Sdim // Fallthrough 5475263508Sdim case ARM::t2LDMIA_UPD: 5476263508Sdim case ARM::t2LDMDB_UPD: 5477263508Sdim case ARM::t2STMIA_UPD: 5478263508Sdim case ARM::t2STMDB_UPD: { 5479226633Sdim if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg())) 5480263508Sdim return Error(Operands.back()->getStartLoc(), 5481263508Sdim "writeback register not allowed in register list"); 5482263508Sdim break; 5483263508Sdim } 5484263508Sdim case ARM::sysLDMIA_UPD: 5485263508Sdim case ARM::sysLDMDA_UPD: 5486263508Sdim case ARM::sysLDMDB_UPD: 5487263508Sdim case ARM::sysLDMIB_UPD: 5488263508Sdim if (!listContainsReg(Inst, 3, ARM::PC)) 5489226633Sdim return Error(Operands[4]->getStartLoc(), 5490263508Sdim "writeback register only allowed on system LDM " 5491263508Sdim "if PC in register-list"); 5492226633Sdim break; 5493263508Sdim case ARM::sysSTMIA_UPD: 5494263508Sdim case ARM::sysSTMDA_UPD: 5495263508Sdim case ARM::sysSTMDB_UPD: 5496263508Sdim case ARM::sysSTMIB_UPD: 5497263508Sdim return Error(Operands[2]->getStartLoc(), 5498263508Sdim "system STM cannot have writeback register"); 5499263508Sdim break; 5500243830Sdim case ARM::tMUL: { 5501243830Sdim // The second source operand must be the same register as the destination 5502243830Sdim // operand. 5503243830Sdim // 5504243830Sdim // In this case, we must directly check the parsed operands because the 5505243830Sdim // cvtThumbMultiply() function is written in such a way that it guarantees 5506243830Sdim // this first statement is always true for the new Inst. Essentially, the 5507243830Sdim // destination is unconditionally copied into the second source operand 5508243830Sdim // without checking to see if it matches what we actually parsed. 5509243830Sdim if (Operands.size() == 6 && 5510243830Sdim (((ARMOperand*)Operands[3])->getReg() != 5511243830Sdim ((ARMOperand*)Operands[5])->getReg()) && 5512243830Sdim (((ARMOperand*)Operands[3])->getReg() != 5513243830Sdim ((ARMOperand*)Operands[4])->getReg())) { 5514243830Sdim return Error(Operands[3]->getStartLoc(), 5515243830Sdim "destination register must match source register"); 5516243830Sdim } 5517243830Sdim break; 5518243830Sdim } 5519234353Sdim // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2, 5520234353Sdim // so only issue a diagnostic for thumb1. The instructions will be 5521234353Sdim // switched to the t2 encodings in processInstruction() if necessary. 5522226633Sdim case ARM::tPOP: { 5523263508Sdim bool ListContainsBase; 5524263508Sdim if (checkLowRegisterList(Inst, 2, 0, ARM::PC, ListContainsBase) && 5525234353Sdim !isThumbTwo()) 5526226633Sdim return Error(Operands[2]->getStartLoc(), 5527226633Sdim "registers must be in range r0-r7 or pc"); 5528226633Sdim break; 5529226633Sdim } 5530226633Sdim case ARM::tPUSH: { 5531263508Sdim bool ListContainsBase; 5532263508Sdim if (checkLowRegisterList(Inst, 2, 0, ARM::LR, ListContainsBase) && 5533234353Sdim !isThumbTwo()) 5534226633Sdim return Error(Operands[2]->getStartLoc(), 5535226633Sdim "registers must be in range r0-r7 or lr"); 5536226633Sdim break; 5537226633Sdim } 5538226633Sdim case ARM::tSTMIA_UPD: { 5539263508Sdim bool ListContainsBase, InvalidLowList; 5540263508Sdim InvalidLowList = checkLowRegisterList(Inst, 4, Inst.getOperand(0).getReg(), 5541263508Sdim 0, ListContainsBase); 5542263508Sdim if (InvalidLowList && !isThumbTwo()) 5543226633Sdim return Error(Operands[4]->getStartLoc(), 5544226633Sdim "registers must be in range r0-r7"); 5545263508Sdim 5546263508Sdim // This would be converted to a 32-bit stm, but that's not valid if the 5547263508Sdim // writeback register is in the list. 5548263508Sdim if (InvalidLowList && ListContainsBase) 5549263508Sdim return Error(Operands[4]->getStartLoc(), 5550263508Sdim "writeback operator '!' not allowed when base register " 5551263508Sdim "in register list"); 5552226633Sdim break; 5553226633Sdim } 5554239462Sdim case ARM::tADDrSP: { 5555239462Sdim // If the non-SP source operand and the destination operand are not the 5556239462Sdim // same, we need thumb2 (for the wide encoding), or we have an error. 5557239462Sdim if (!isThumbTwo() && 5558239462Sdim Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) { 5559239462Sdim return Error(Operands[4]->getStartLoc(), 5560239462Sdim "source register must be the same as destination"); 5561239462Sdim } 5562239462Sdim break; 5563226633Sdim } 5564263508Sdim // Final range checking for Thumb unconditional branch instructions. 5565263508Sdim case ARM::tB: 5566263508Sdim if (!(static_cast<ARMOperand*>(Operands[2]))->isSignedOffset<11, 1>()) 5567263508Sdim return Error(Operands[2]->getStartLoc(), "branch target out of range"); 5568263508Sdim break; 5569263508Sdim case ARM::t2B: { 5570263508Sdim int op = (Operands[2]->isImm()) ? 2 : 3; 5571263508Sdim if (!(static_cast<ARMOperand*>(Operands[op]))->isSignedOffset<24, 1>()) 5572263508Sdim return Error(Operands[op]->getStartLoc(), "branch target out of range"); 5573263508Sdim break; 5574239462Sdim } 5575263508Sdim // Final range checking for Thumb conditional branch instructions. 5576263508Sdim case ARM::tBcc: 5577263508Sdim if (!(static_cast<ARMOperand*>(Operands[2]))->isSignedOffset<8, 1>()) 5578263508Sdim return Error(Operands[2]->getStartLoc(), "branch target out of range"); 5579263508Sdim break; 5580263508Sdim case ARM::t2Bcc: { 5581263508Sdim int Op = (Operands[2]->isImm()) ? 2 : 3; 5582263508Sdim if (!(static_cast<ARMOperand*>(Operands[Op]))->isSignedOffset<20, 1>()) 5583263508Sdim return Error(Operands[Op]->getStartLoc(), "branch target out of range"); 5584263508Sdim break; 5585263508Sdim } 5586263508Sdim } 5587226633Sdim 5588226633Sdim return false; 5589226633Sdim} 5590226633Sdim 5591234353Sdimstatic unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) { 5592234353Sdim switch(Opc) { 5593234353Sdim default: llvm_unreachable("unexpected opcode!"); 5594234353Sdim // VST1LN 5595234353Sdim case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD; 5596234353Sdim case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD; 5597234353Sdim case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD; 5598234353Sdim case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD; 5599234353Sdim case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD; 5600234353Sdim case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD; 5601234353Sdim case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8; 5602234353Sdim case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16; 5603234353Sdim case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32; 5604234353Sdim 5605234353Sdim // VST2LN 5606234353Sdim case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD; 5607234353Sdim case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD; 5608234353Sdim case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD; 5609234353Sdim case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD; 5610234353Sdim case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD; 5611234353Sdim 5612234353Sdim case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD; 5613234353Sdim case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD; 5614234353Sdim case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD; 5615234353Sdim case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD; 5616234353Sdim case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD; 5617234353Sdim 5618234353Sdim case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8; 5619234353Sdim case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16; 5620234353Sdim case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32; 5621234353Sdim case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16; 5622234353Sdim case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32; 5623234353Sdim 5624234353Sdim // VST3LN 5625234353Sdim case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD; 5626234353Sdim case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD; 5627234353Sdim case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD; 5628234353Sdim case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD; 5629234353Sdim case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD; 5630234353Sdim case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD; 5631234353Sdim case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD; 5632234353Sdim case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD; 5633234353Sdim case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD; 5634234353Sdim case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD; 5635234353Sdim case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8; 5636234353Sdim case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16; 5637234353Sdim case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32; 5638234353Sdim case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16; 5639234353Sdim case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32; 5640234353Sdim 5641234353Sdim // VST3 5642234353Sdim case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD; 5643234353Sdim case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD; 5644234353Sdim case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD; 5645234353Sdim case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD; 5646234353Sdim case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD; 5647234353Sdim case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD; 5648234353Sdim case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD; 5649234353Sdim case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD; 5650234353Sdim case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD; 5651234353Sdim case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD; 5652234353Sdim case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD; 5653234353Sdim case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD; 5654234353Sdim case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8; 5655234353Sdim case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16; 5656234353Sdim case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32; 5657234353Sdim case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8; 5658234353Sdim case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16; 5659234353Sdim case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32; 5660234353Sdim 5661234353Sdim // VST4LN 5662234353Sdim case ARM::VST4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD; 5663234353Sdim case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD; 5664234353Sdim case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD; 5665234353Sdim case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD; 5666234353Sdim case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD; 5667234353Sdim case ARM::VST4LNdWB_register_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD; 5668234353Sdim case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD; 5669234353Sdim case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD; 5670234353Sdim case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD; 5671234353Sdim case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD; 5672234353Sdim case ARM::VST4LNdAsm_8: Spacing = 1; return ARM::VST4LNd8; 5673234353Sdim case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16; 5674234353Sdim case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32; 5675234353Sdim case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16; 5676234353Sdim case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32; 5677234353Sdim 5678234353Sdim // VST4 5679234353Sdim case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD; 5680234353Sdim case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD; 5681234353Sdim case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD; 5682234353Sdim case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD; 5683234353Sdim case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD; 5684234353Sdim case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD; 5685234353Sdim case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD; 5686234353Sdim case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD; 5687234353Sdim case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD; 5688234353Sdim case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD; 5689234353Sdim case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD; 5690234353Sdim case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD; 5691234353Sdim case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8; 5692234353Sdim case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16; 5693234353Sdim case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32; 5694234353Sdim case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8; 5695234353Sdim case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16; 5696234353Sdim case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32; 5697234353Sdim } 5698234353Sdim} 5699234353Sdim 5700234353Sdimstatic unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) { 5701234353Sdim switch(Opc) { 5702234353Sdim default: llvm_unreachable("unexpected opcode!"); 5703234353Sdim // VLD1LN 5704234353Sdim case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD; 5705234353Sdim case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD; 5706234353Sdim case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD; 5707234353Sdim case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD; 5708234353Sdim case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD; 5709234353Sdim case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD; 5710234353Sdim case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8; 5711234353Sdim case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16; 5712234353Sdim case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32; 5713234353Sdim 5714234353Sdim // VLD2LN 5715234353Sdim case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD; 5716234353Sdim case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD; 5717234353Sdim case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD; 5718234353Sdim case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD; 5719234353Sdim case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD; 5720234353Sdim case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD; 5721234353Sdim case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD; 5722234353Sdim case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD; 5723234353Sdim case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD; 5724234353Sdim case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD; 5725234353Sdim case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8; 5726234353Sdim case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16; 5727234353Sdim case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32; 5728234353Sdim case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16; 5729234353Sdim case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32; 5730234353Sdim 5731234353Sdim // VLD3DUP 5732234353Sdim case ARM::VLD3DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD; 5733234353Sdim case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD; 5734234353Sdim case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD; 5735234353Sdim case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD; 5736234353Sdim case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPq16_UPD; 5737234353Sdim case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD; 5738234353Sdim case ARM::VLD3DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD; 5739234353Sdim case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD; 5740234353Sdim case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD; 5741234353Sdim case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD; 5742234353Sdim case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD; 5743234353Sdim case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD; 5744234353Sdim case ARM::VLD3DUPdAsm_8: Spacing = 1; return ARM::VLD3DUPd8; 5745234353Sdim case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16; 5746234353Sdim case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32; 5747234353Sdim case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8; 5748234353Sdim case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16; 5749234353Sdim case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32; 5750234353Sdim 5751234353Sdim // VLD3LN 5752234353Sdim case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD; 5753234353Sdim case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD; 5754234353Sdim case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD; 5755234353Sdim case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD; 5756234353Sdim case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD; 5757234353Sdim case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD; 5758234353Sdim case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD; 5759234353Sdim case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD; 5760234353Sdim case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD; 5761234353Sdim case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD; 5762234353Sdim case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8; 5763234353Sdim case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16; 5764234353Sdim case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32; 5765234353Sdim case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16; 5766234353Sdim case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32; 5767234353Sdim 5768234353Sdim // VLD3 5769234353Sdim case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD; 5770234353Sdim case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD; 5771234353Sdim case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD; 5772234353Sdim case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD; 5773234353Sdim case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD; 5774234353Sdim case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD; 5775234353Sdim case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD; 5776234353Sdim case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD; 5777234353Sdim case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD; 5778234353Sdim case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD; 5779234353Sdim case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD; 5780234353Sdim case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD; 5781234353Sdim case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8; 5782234353Sdim case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16; 5783234353Sdim case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32; 5784234353Sdim case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8; 5785234353Sdim case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16; 5786234353Sdim case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32; 5787234353Sdim 5788234353Sdim // VLD4LN 5789234353Sdim case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD; 5790234353Sdim case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD; 5791234353Sdim case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD; 5792234353Sdim case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNq16_UPD; 5793234353Sdim case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD; 5794234353Sdim case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD; 5795234353Sdim case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD; 5796234353Sdim case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD; 5797234353Sdim case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD; 5798234353Sdim case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD; 5799234353Sdim case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8; 5800234353Sdim case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16; 5801234353Sdim case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32; 5802234353Sdim case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16; 5803234353Sdim case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32; 5804234353Sdim 5805234353Sdim // VLD4DUP 5806234353Sdim case ARM::VLD4DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD; 5807234353Sdim case ARM::VLD4DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD; 5808234353Sdim case ARM::VLD4DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD; 5809234353Sdim case ARM::VLD4DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPq8_UPD; 5810234353Sdim case ARM::VLD4DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPq16_UPD; 5811234353Sdim case ARM::VLD4DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD; 5812234353Sdim case ARM::VLD4DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD; 5813234353Sdim case ARM::VLD4DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD; 5814234353Sdim case ARM::VLD4DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD; 5815234353Sdim case ARM::VLD4DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD4DUPq8_UPD; 5816234353Sdim case ARM::VLD4DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD4DUPq16_UPD; 5817234353Sdim case ARM::VLD4DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD; 5818234353Sdim case ARM::VLD4DUPdAsm_8: Spacing = 1; return ARM::VLD4DUPd8; 5819234353Sdim case ARM::VLD4DUPdAsm_16: Spacing = 1; return ARM::VLD4DUPd16; 5820234353Sdim case ARM::VLD4DUPdAsm_32: Spacing = 1; return ARM::VLD4DUPd32; 5821234353Sdim case ARM::VLD4DUPqAsm_8: Spacing = 2; return ARM::VLD4DUPq8; 5822234353Sdim case ARM::VLD4DUPqAsm_16: Spacing = 2; return ARM::VLD4DUPq16; 5823234353Sdim case ARM::VLD4DUPqAsm_32: Spacing = 2; return ARM::VLD4DUPq32; 5824234353Sdim 5825234353Sdim // VLD4 5826234353Sdim case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD; 5827234353Sdim case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD; 5828234353Sdim case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD; 5829234353Sdim case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD; 5830234353Sdim case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD; 5831234353Sdim case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD; 5832234353Sdim case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD; 5833234353Sdim case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD; 5834234353Sdim case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD; 5835234353Sdim case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD; 5836234353Sdim case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD; 5837234353Sdim case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD; 5838234353Sdim case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8; 5839234353Sdim case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16; 5840234353Sdim case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32; 5841234353Sdim case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8; 5842234353Sdim case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16; 5843234353Sdim case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32; 5844234353Sdim } 5845234353Sdim} 5846234353Sdim 5847234353Sdimbool ARMAsmParser:: 5848226633SdimprocessInstruction(MCInst &Inst, 5849226633Sdim const SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 5850226633Sdim switch (Inst.getOpcode()) { 5851243830Sdim // Alias for alternate form of 'ADR Rd, #imm' instruction. 5852243830Sdim case ARM::ADDri: { 5853243830Sdim if (Inst.getOperand(1).getReg() != ARM::PC || 5854243830Sdim Inst.getOperand(5).getReg() != 0) 5855243830Sdim return false; 5856243830Sdim MCInst TmpInst; 5857243830Sdim TmpInst.setOpcode(ARM::ADR); 5858243830Sdim TmpInst.addOperand(Inst.getOperand(0)); 5859243830Sdim TmpInst.addOperand(Inst.getOperand(2)); 5860243830Sdim TmpInst.addOperand(Inst.getOperand(3)); 5861243830Sdim TmpInst.addOperand(Inst.getOperand(4)); 5862243830Sdim Inst = TmpInst; 5863243830Sdim return true; 5864243830Sdim } 5865234353Sdim // Aliases for alternate PC+imm syntax of LDR instructions. 5866234353Sdim case ARM::t2LDRpcrel: 5867249423Sdim // Select the narrow version if the immediate will fit. 5868249423Sdim if (Inst.getOperand(1).getImm() > 0 && 5869263508Sdim Inst.getOperand(1).getImm() <= 0xff && 5870263508Sdim !(static_cast<ARMOperand*>(Operands[2])->isToken() && 5871263508Sdim static_cast<ARMOperand*>(Operands[2])->getToken() == ".w")) 5872249423Sdim Inst.setOpcode(ARM::tLDRpci); 5873249423Sdim else 5874249423Sdim Inst.setOpcode(ARM::t2LDRpci); 5875234353Sdim return true; 5876234353Sdim case ARM::t2LDRBpcrel: 5877234353Sdim Inst.setOpcode(ARM::t2LDRBpci); 5878234353Sdim return true; 5879234353Sdim case ARM::t2LDRHpcrel: 5880234353Sdim Inst.setOpcode(ARM::t2LDRHpci); 5881234353Sdim return true; 5882234353Sdim case ARM::t2LDRSBpcrel: 5883234353Sdim Inst.setOpcode(ARM::t2LDRSBpci); 5884234353Sdim return true; 5885234353Sdim case ARM::t2LDRSHpcrel: 5886234353Sdim Inst.setOpcode(ARM::t2LDRSHpci); 5887234353Sdim return true; 5888234353Sdim // Handle NEON VST complex aliases. 5889234353Sdim case ARM::VST1LNdWB_register_Asm_8: 5890234353Sdim case ARM::VST1LNdWB_register_Asm_16: 5891234353Sdim case ARM::VST1LNdWB_register_Asm_32: { 5892234353Sdim MCInst TmpInst; 5893234353Sdim // Shuffle the operands around so the lane index operand is in the 5894234353Sdim // right place. 5895234353Sdim unsigned Spacing; 5896234353Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 5897234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 5898234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 5899234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 5900234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rm 5901234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 5902234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 5903234353Sdim TmpInst.addOperand(Inst.getOperand(5)); // CondCode 5904234353Sdim TmpInst.addOperand(Inst.getOperand(6)); 5905234353Sdim Inst = TmpInst; 5906234353Sdim return true; 5907234353Sdim } 5908234353Sdim 5909234353Sdim case ARM::VST2LNdWB_register_Asm_8: 5910234353Sdim case ARM::VST2LNdWB_register_Asm_16: 5911234353Sdim case ARM::VST2LNdWB_register_Asm_32: 5912234353Sdim case ARM::VST2LNqWB_register_Asm_16: 5913234353Sdim case ARM::VST2LNqWB_register_Asm_32: { 5914234353Sdim MCInst TmpInst; 5915234353Sdim // Shuffle the operands around so the lane index operand is in the 5916234353Sdim // right place. 5917234353Sdim unsigned Spacing; 5918234353Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 5919234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 5920234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 5921234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 5922234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rm 5923234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 5924234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 5925234353Sdim Spacing)); 5926234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 5927234353Sdim TmpInst.addOperand(Inst.getOperand(5)); // CondCode 5928234353Sdim TmpInst.addOperand(Inst.getOperand(6)); 5929234353Sdim Inst = TmpInst; 5930234353Sdim return true; 5931234353Sdim } 5932234353Sdim 5933234353Sdim case ARM::VST3LNdWB_register_Asm_8: 5934234353Sdim case ARM::VST3LNdWB_register_Asm_16: 5935234353Sdim case ARM::VST3LNdWB_register_Asm_32: 5936234353Sdim case ARM::VST3LNqWB_register_Asm_16: 5937234353Sdim case ARM::VST3LNqWB_register_Asm_32: { 5938234353Sdim MCInst TmpInst; 5939234353Sdim // Shuffle the operands around so the lane index operand is in the 5940234353Sdim // right place. 5941234353Sdim unsigned Spacing; 5942234353Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 5943234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 5944234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 5945234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 5946234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rm 5947234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 5948234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 5949234353Sdim Spacing)); 5950234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 5951234353Sdim Spacing * 2)); 5952234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 5953234353Sdim TmpInst.addOperand(Inst.getOperand(5)); // CondCode 5954234353Sdim TmpInst.addOperand(Inst.getOperand(6)); 5955234353Sdim Inst = TmpInst; 5956234353Sdim return true; 5957234353Sdim } 5958234353Sdim 5959234353Sdim case ARM::VST4LNdWB_register_Asm_8: 5960234353Sdim case ARM::VST4LNdWB_register_Asm_16: 5961234353Sdim case ARM::VST4LNdWB_register_Asm_32: 5962234353Sdim case ARM::VST4LNqWB_register_Asm_16: 5963234353Sdim case ARM::VST4LNqWB_register_Asm_32: { 5964234353Sdim MCInst TmpInst; 5965234353Sdim // Shuffle the operands around so the lane index operand is in the 5966234353Sdim // right place. 5967234353Sdim unsigned Spacing; 5968234353Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 5969234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 5970234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 5971234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 5972234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rm 5973234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 5974234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 5975234353Sdim Spacing)); 5976234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 5977234353Sdim Spacing * 2)); 5978234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 5979234353Sdim Spacing * 3)); 5980234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 5981234353Sdim TmpInst.addOperand(Inst.getOperand(5)); // CondCode 5982234353Sdim TmpInst.addOperand(Inst.getOperand(6)); 5983234353Sdim Inst = TmpInst; 5984234353Sdim return true; 5985234353Sdim } 5986234353Sdim 5987234353Sdim case ARM::VST1LNdWB_fixed_Asm_8: 5988234353Sdim case ARM::VST1LNdWB_fixed_Asm_16: 5989234353Sdim case ARM::VST1LNdWB_fixed_Asm_32: { 5990234353Sdim MCInst TmpInst; 5991234353Sdim // Shuffle the operands around so the lane index operand is in the 5992234353Sdim // right place. 5993234353Sdim unsigned Spacing; 5994234353Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 5995234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 5996234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 5997234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 5998234353Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 5999234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6000234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6001234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6002234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6003234353Sdim Inst = TmpInst; 6004234353Sdim return true; 6005234353Sdim } 6006234353Sdim 6007234353Sdim case ARM::VST2LNdWB_fixed_Asm_8: 6008234353Sdim case ARM::VST2LNdWB_fixed_Asm_16: 6009234353Sdim case ARM::VST2LNdWB_fixed_Asm_32: 6010234353Sdim case ARM::VST2LNqWB_fixed_Asm_16: 6011234353Sdim case ARM::VST2LNqWB_fixed_Asm_32: { 6012234353Sdim MCInst TmpInst; 6013234353Sdim // Shuffle the operands around so the lane index operand is in the 6014234353Sdim // right place. 6015234353Sdim unsigned Spacing; 6016234353Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6017234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 6018234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6019234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6020234353Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6021234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6022234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6023234353Sdim Spacing)); 6024234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6025234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6026234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6027234353Sdim Inst = TmpInst; 6028234353Sdim return true; 6029234353Sdim } 6030234353Sdim 6031234353Sdim case ARM::VST3LNdWB_fixed_Asm_8: 6032234353Sdim case ARM::VST3LNdWB_fixed_Asm_16: 6033234353Sdim case ARM::VST3LNdWB_fixed_Asm_32: 6034234353Sdim case ARM::VST3LNqWB_fixed_Asm_16: 6035234353Sdim case ARM::VST3LNqWB_fixed_Asm_32: { 6036234353Sdim MCInst TmpInst; 6037234353Sdim // Shuffle the operands around so the lane index operand is in the 6038234353Sdim // right place. 6039234353Sdim unsigned Spacing; 6040234353Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6041234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 6042234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6043234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6044234353Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6045234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6046234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6047234353Sdim Spacing)); 6048234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6049234353Sdim Spacing * 2)); 6050234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6051234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6052234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6053234353Sdim Inst = TmpInst; 6054234353Sdim return true; 6055234353Sdim } 6056234353Sdim 6057234353Sdim case ARM::VST4LNdWB_fixed_Asm_8: 6058234353Sdim case ARM::VST4LNdWB_fixed_Asm_16: 6059234353Sdim case ARM::VST4LNdWB_fixed_Asm_32: 6060234353Sdim case ARM::VST4LNqWB_fixed_Asm_16: 6061234353Sdim case ARM::VST4LNqWB_fixed_Asm_32: { 6062234353Sdim MCInst TmpInst; 6063234353Sdim // Shuffle the operands around so the lane index operand is in the 6064234353Sdim // right place. 6065234353Sdim unsigned Spacing; 6066234353Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6067234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 6068234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6069234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6070234353Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6071234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6072234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6073234353Sdim Spacing)); 6074234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6075234353Sdim Spacing * 2)); 6076234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6077234353Sdim Spacing * 3)); 6078234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6079234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6080234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6081234353Sdim Inst = TmpInst; 6082234353Sdim return true; 6083234353Sdim } 6084234353Sdim 6085234353Sdim case ARM::VST1LNdAsm_8: 6086234353Sdim case ARM::VST1LNdAsm_16: 6087234353Sdim case ARM::VST1LNdAsm_32: { 6088234353Sdim MCInst TmpInst; 6089234353Sdim // Shuffle the operands around so the lane index operand is in the 6090234353Sdim // right place. 6091234353Sdim unsigned Spacing; 6092234353Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6093234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6094234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6095234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6096234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6097234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6098234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6099234353Sdim Inst = TmpInst; 6100234353Sdim return true; 6101234353Sdim } 6102234353Sdim 6103234353Sdim case ARM::VST2LNdAsm_8: 6104234353Sdim case ARM::VST2LNdAsm_16: 6105234353Sdim case ARM::VST2LNdAsm_32: 6106234353Sdim case ARM::VST2LNqAsm_16: 6107234353Sdim case ARM::VST2LNqAsm_32: { 6108234353Sdim MCInst TmpInst; 6109234353Sdim // Shuffle the operands around so the lane index operand is in the 6110234353Sdim // right place. 6111234353Sdim unsigned Spacing; 6112234353Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6113234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6114234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6115234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6116234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6117234353Sdim Spacing)); 6118234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6119234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6120234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6121234353Sdim Inst = TmpInst; 6122234353Sdim return true; 6123234353Sdim } 6124234353Sdim 6125234353Sdim case ARM::VST3LNdAsm_8: 6126234353Sdim case ARM::VST3LNdAsm_16: 6127234353Sdim case ARM::VST3LNdAsm_32: 6128234353Sdim case ARM::VST3LNqAsm_16: 6129234353Sdim case ARM::VST3LNqAsm_32: { 6130234353Sdim MCInst TmpInst; 6131234353Sdim // Shuffle the operands around so the lane index operand is in the 6132234353Sdim // right place. 6133234353Sdim unsigned Spacing; 6134234353Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6135234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6136234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6137234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6138234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6139234353Sdim Spacing)); 6140234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6141234353Sdim Spacing * 2)); 6142234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6143234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6144234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6145234353Sdim Inst = TmpInst; 6146234353Sdim return true; 6147234353Sdim } 6148234353Sdim 6149234353Sdim case ARM::VST4LNdAsm_8: 6150234353Sdim case ARM::VST4LNdAsm_16: 6151234353Sdim case ARM::VST4LNdAsm_32: 6152234353Sdim case ARM::VST4LNqAsm_16: 6153234353Sdim case ARM::VST4LNqAsm_32: { 6154234353Sdim MCInst TmpInst; 6155234353Sdim // Shuffle the operands around so the lane index operand is in the 6156234353Sdim // right place. 6157234353Sdim unsigned Spacing; 6158234353Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6159234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6160234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6161234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6162234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6163234353Sdim Spacing)); 6164234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6165234353Sdim Spacing * 2)); 6166234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6167234353Sdim Spacing * 3)); 6168234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6169234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6170234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6171234353Sdim Inst = TmpInst; 6172234353Sdim return true; 6173234353Sdim } 6174234353Sdim 6175234353Sdim // Handle NEON VLD complex aliases. 6176234353Sdim case ARM::VLD1LNdWB_register_Asm_8: 6177234353Sdim case ARM::VLD1LNdWB_register_Asm_16: 6178234353Sdim case ARM::VLD1LNdWB_register_Asm_32: { 6179234353Sdim MCInst TmpInst; 6180234353Sdim // Shuffle the operands around so the lane index operand is in the 6181234353Sdim // right place. 6182234353Sdim unsigned Spacing; 6183234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6184234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6185234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 6186234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6187234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6188234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rm 6189234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6190234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6191234353Sdim TmpInst.addOperand(Inst.getOperand(5)); // CondCode 6192234353Sdim TmpInst.addOperand(Inst.getOperand(6)); 6193234353Sdim Inst = TmpInst; 6194234353Sdim return true; 6195234353Sdim } 6196234353Sdim 6197234353Sdim case ARM::VLD2LNdWB_register_Asm_8: 6198234353Sdim case ARM::VLD2LNdWB_register_Asm_16: 6199234353Sdim case ARM::VLD2LNdWB_register_Asm_32: 6200234353Sdim case ARM::VLD2LNqWB_register_Asm_16: 6201234353Sdim case ARM::VLD2LNqWB_register_Asm_32: { 6202234353Sdim MCInst TmpInst; 6203234353Sdim // Shuffle the operands around so the lane index operand is in the 6204234353Sdim // right place. 6205234353Sdim unsigned Spacing; 6206234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6207234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6208234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6209234353Sdim Spacing)); 6210234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 6211234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6212234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6213234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rm 6214234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6215234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6216234353Sdim Spacing)); 6217234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6218234353Sdim TmpInst.addOperand(Inst.getOperand(5)); // CondCode 6219234353Sdim TmpInst.addOperand(Inst.getOperand(6)); 6220234353Sdim Inst = TmpInst; 6221234353Sdim return true; 6222234353Sdim } 6223234353Sdim 6224234353Sdim case ARM::VLD3LNdWB_register_Asm_8: 6225234353Sdim case ARM::VLD3LNdWB_register_Asm_16: 6226234353Sdim case ARM::VLD3LNdWB_register_Asm_32: 6227234353Sdim case ARM::VLD3LNqWB_register_Asm_16: 6228234353Sdim case ARM::VLD3LNqWB_register_Asm_32: { 6229234353Sdim MCInst TmpInst; 6230234353Sdim // Shuffle the operands around so the lane index operand is in the 6231234353Sdim // right place. 6232234353Sdim unsigned Spacing; 6233234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6234234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6235234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6236234353Sdim Spacing)); 6237234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6238234353Sdim Spacing * 2)); 6239234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 6240234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6241234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6242234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rm 6243234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6244234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6245234353Sdim Spacing)); 6246234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6247234353Sdim Spacing * 2)); 6248234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6249234353Sdim TmpInst.addOperand(Inst.getOperand(5)); // CondCode 6250234353Sdim TmpInst.addOperand(Inst.getOperand(6)); 6251234353Sdim Inst = TmpInst; 6252234353Sdim return true; 6253234353Sdim } 6254234353Sdim 6255234353Sdim case ARM::VLD4LNdWB_register_Asm_8: 6256234353Sdim case ARM::VLD4LNdWB_register_Asm_16: 6257234353Sdim case ARM::VLD4LNdWB_register_Asm_32: 6258234353Sdim case ARM::VLD4LNqWB_register_Asm_16: 6259234353Sdim case ARM::VLD4LNqWB_register_Asm_32: { 6260234353Sdim MCInst TmpInst; 6261234353Sdim // Shuffle the operands around so the lane index operand is in the 6262234353Sdim // right place. 6263234353Sdim unsigned Spacing; 6264234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6265234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6266234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6267234353Sdim Spacing)); 6268234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6269234353Sdim Spacing * 2)); 6270234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6271234353Sdim Spacing * 3)); 6272234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 6273234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6274234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6275234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rm 6276234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6277234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6278234353Sdim Spacing)); 6279234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6280234353Sdim Spacing * 2)); 6281234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6282234353Sdim Spacing * 3)); 6283234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6284234353Sdim TmpInst.addOperand(Inst.getOperand(5)); // CondCode 6285234353Sdim TmpInst.addOperand(Inst.getOperand(6)); 6286234353Sdim Inst = TmpInst; 6287234353Sdim return true; 6288234353Sdim } 6289234353Sdim 6290234353Sdim case ARM::VLD1LNdWB_fixed_Asm_8: 6291234353Sdim case ARM::VLD1LNdWB_fixed_Asm_16: 6292234353Sdim case ARM::VLD1LNdWB_fixed_Asm_32: { 6293234353Sdim MCInst TmpInst; 6294234353Sdim // Shuffle the operands around so the lane index operand is in the 6295234353Sdim // right place. 6296234353Sdim unsigned Spacing; 6297234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6298234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6299234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 6300234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6301234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6302234353Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6303234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6304234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6305234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6306234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6307234353Sdim Inst = TmpInst; 6308234353Sdim return true; 6309234353Sdim } 6310234353Sdim 6311234353Sdim case ARM::VLD2LNdWB_fixed_Asm_8: 6312234353Sdim case ARM::VLD2LNdWB_fixed_Asm_16: 6313234353Sdim case ARM::VLD2LNdWB_fixed_Asm_32: 6314234353Sdim case ARM::VLD2LNqWB_fixed_Asm_16: 6315234353Sdim case ARM::VLD2LNqWB_fixed_Asm_32: { 6316234353Sdim MCInst TmpInst; 6317234353Sdim // Shuffle the operands around so the lane index operand is in the 6318234353Sdim // right place. 6319234353Sdim unsigned Spacing; 6320234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6321234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6322234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6323234353Sdim Spacing)); 6324234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 6325234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6326234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6327234353Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6328234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6329234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6330234353Sdim Spacing)); 6331234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6332234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6333234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6334234353Sdim Inst = TmpInst; 6335234353Sdim return true; 6336234353Sdim } 6337234353Sdim 6338234353Sdim case ARM::VLD3LNdWB_fixed_Asm_8: 6339234353Sdim case ARM::VLD3LNdWB_fixed_Asm_16: 6340234353Sdim case ARM::VLD3LNdWB_fixed_Asm_32: 6341234353Sdim case ARM::VLD3LNqWB_fixed_Asm_16: 6342234353Sdim case ARM::VLD3LNqWB_fixed_Asm_32: { 6343234353Sdim MCInst TmpInst; 6344234353Sdim // Shuffle the operands around so the lane index operand is in the 6345234353Sdim // right place. 6346234353Sdim unsigned Spacing; 6347234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6348234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6349234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6350234353Sdim Spacing)); 6351234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6352234353Sdim Spacing * 2)); 6353234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 6354234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6355234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6356234353Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6357234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6358234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6359234353Sdim Spacing)); 6360234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6361234353Sdim Spacing * 2)); 6362234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6363234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6364234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6365234353Sdim Inst = TmpInst; 6366234353Sdim return true; 6367234353Sdim } 6368234353Sdim 6369234353Sdim case ARM::VLD4LNdWB_fixed_Asm_8: 6370234353Sdim case ARM::VLD4LNdWB_fixed_Asm_16: 6371234353Sdim case ARM::VLD4LNdWB_fixed_Asm_32: 6372234353Sdim case ARM::VLD4LNqWB_fixed_Asm_16: 6373234353Sdim case ARM::VLD4LNqWB_fixed_Asm_32: { 6374234353Sdim MCInst TmpInst; 6375234353Sdim // Shuffle the operands around so the lane index operand is in the 6376234353Sdim // right place. 6377234353Sdim unsigned Spacing; 6378234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6379234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6380234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6381234353Sdim Spacing)); 6382234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6383234353Sdim Spacing * 2)); 6384234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6385234353Sdim Spacing * 3)); 6386234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 6387234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6388234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6389234353Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6390234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6391234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6392234353Sdim Spacing)); 6393234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6394234353Sdim Spacing * 2)); 6395234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6396234353Sdim Spacing * 3)); 6397234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6398234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6399234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6400234353Sdim Inst = TmpInst; 6401234353Sdim return true; 6402234353Sdim } 6403234353Sdim 6404234353Sdim case ARM::VLD1LNdAsm_8: 6405234353Sdim case ARM::VLD1LNdAsm_16: 6406234353Sdim case ARM::VLD1LNdAsm_32: { 6407234353Sdim MCInst TmpInst; 6408234353Sdim // Shuffle the operands around so the lane index operand is in the 6409234353Sdim // right place. 6410234353Sdim unsigned Spacing; 6411234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6412234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6413234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6414234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6415234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6416234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6417234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6418234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6419234353Sdim Inst = TmpInst; 6420234353Sdim return true; 6421234353Sdim } 6422234353Sdim 6423234353Sdim case ARM::VLD2LNdAsm_8: 6424234353Sdim case ARM::VLD2LNdAsm_16: 6425234353Sdim case ARM::VLD2LNdAsm_32: 6426234353Sdim case ARM::VLD2LNqAsm_16: 6427234353Sdim case ARM::VLD2LNqAsm_32: { 6428234353Sdim MCInst TmpInst; 6429234353Sdim // Shuffle the operands around so the lane index operand is in the 6430234353Sdim // right place. 6431234353Sdim unsigned Spacing; 6432234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6433234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6434234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6435234353Sdim Spacing)); 6436234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6437234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6438234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6439234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6440234353Sdim Spacing)); 6441234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6442234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6443234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6444234353Sdim Inst = TmpInst; 6445234353Sdim return true; 6446234353Sdim } 6447234353Sdim 6448234353Sdim case ARM::VLD3LNdAsm_8: 6449234353Sdim case ARM::VLD3LNdAsm_16: 6450234353Sdim case ARM::VLD3LNdAsm_32: 6451234353Sdim case ARM::VLD3LNqAsm_16: 6452234353Sdim case ARM::VLD3LNqAsm_32: { 6453234353Sdim MCInst TmpInst; 6454234353Sdim // Shuffle the operands around so the lane index operand is in the 6455234353Sdim // right place. 6456234353Sdim unsigned Spacing; 6457234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6458234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6459234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6460234353Sdim Spacing)); 6461234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6462234353Sdim Spacing * 2)); 6463234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6464234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6465234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6466234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6467234353Sdim Spacing)); 6468234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6469234353Sdim Spacing * 2)); 6470234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6471234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6472234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6473234353Sdim Inst = TmpInst; 6474234353Sdim return true; 6475234353Sdim } 6476234353Sdim 6477234353Sdim case ARM::VLD4LNdAsm_8: 6478234353Sdim case ARM::VLD4LNdAsm_16: 6479234353Sdim case ARM::VLD4LNdAsm_32: 6480234353Sdim case ARM::VLD4LNqAsm_16: 6481234353Sdim case ARM::VLD4LNqAsm_32: { 6482234353Sdim MCInst TmpInst; 6483234353Sdim // Shuffle the operands around so the lane index operand is in the 6484234353Sdim // right place. 6485234353Sdim unsigned Spacing; 6486234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6487234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6488234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6489234353Sdim Spacing)); 6490234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6491234353Sdim Spacing * 2)); 6492234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6493234353Sdim Spacing * 3)); 6494234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6495234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6496234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6497234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6498234353Sdim Spacing)); 6499234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6500234353Sdim Spacing * 2)); 6501234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6502234353Sdim Spacing * 3)); 6503234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6504234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6505234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6506234353Sdim Inst = TmpInst; 6507234353Sdim return true; 6508234353Sdim } 6509234353Sdim 6510234353Sdim // VLD3DUP single 3-element structure to all lanes instructions. 6511234353Sdim case ARM::VLD3DUPdAsm_8: 6512234353Sdim case ARM::VLD3DUPdAsm_16: 6513234353Sdim case ARM::VLD3DUPdAsm_32: 6514234353Sdim case ARM::VLD3DUPqAsm_8: 6515234353Sdim case ARM::VLD3DUPqAsm_16: 6516234353Sdim case ARM::VLD3DUPqAsm_32: { 6517234353Sdim MCInst TmpInst; 6518234353Sdim unsigned Spacing; 6519234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6520234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6521234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6522234353Sdim Spacing)); 6523234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6524234353Sdim Spacing * 2)); 6525234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6526234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6527234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6528234353Sdim TmpInst.addOperand(Inst.getOperand(4)); 6529234353Sdim Inst = TmpInst; 6530234353Sdim return true; 6531234353Sdim } 6532234353Sdim 6533234353Sdim case ARM::VLD3DUPdWB_fixed_Asm_8: 6534234353Sdim case ARM::VLD3DUPdWB_fixed_Asm_16: 6535234353Sdim case ARM::VLD3DUPdWB_fixed_Asm_32: 6536234353Sdim case ARM::VLD3DUPqWB_fixed_Asm_8: 6537234353Sdim case ARM::VLD3DUPqWB_fixed_Asm_16: 6538234353Sdim case ARM::VLD3DUPqWB_fixed_Asm_32: { 6539234353Sdim MCInst TmpInst; 6540234353Sdim unsigned Spacing; 6541234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6542234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6543234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6544234353Sdim Spacing)); 6545234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6546234353Sdim Spacing * 2)); 6547234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6548234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6549234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6550234353Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6551234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6552234353Sdim TmpInst.addOperand(Inst.getOperand(4)); 6553234353Sdim Inst = TmpInst; 6554234353Sdim return true; 6555234353Sdim } 6556234353Sdim 6557234353Sdim case ARM::VLD3DUPdWB_register_Asm_8: 6558234353Sdim case ARM::VLD3DUPdWB_register_Asm_16: 6559234353Sdim case ARM::VLD3DUPdWB_register_Asm_32: 6560234353Sdim case ARM::VLD3DUPqWB_register_Asm_8: 6561234353Sdim case ARM::VLD3DUPqWB_register_Asm_16: 6562234353Sdim case ARM::VLD3DUPqWB_register_Asm_32: { 6563234353Sdim MCInst TmpInst; 6564234353Sdim unsigned Spacing; 6565234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6566234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6567234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6568234353Sdim Spacing)); 6569234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6570234353Sdim Spacing * 2)); 6571234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6572234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6573234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6574234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // Rm 6575234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6576234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6577234353Sdim Inst = TmpInst; 6578234353Sdim return true; 6579234353Sdim } 6580234353Sdim 6581234353Sdim // VLD3 multiple 3-element structure instructions. 6582234353Sdim case ARM::VLD3dAsm_8: 6583234353Sdim case ARM::VLD3dAsm_16: 6584234353Sdim case ARM::VLD3dAsm_32: 6585234353Sdim case ARM::VLD3qAsm_8: 6586234353Sdim case ARM::VLD3qAsm_16: 6587234353Sdim case ARM::VLD3qAsm_32: { 6588234353Sdim MCInst TmpInst; 6589234353Sdim unsigned Spacing; 6590234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6591234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6592234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6593234353Sdim Spacing)); 6594234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6595234353Sdim Spacing * 2)); 6596234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6597234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6598234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6599234353Sdim TmpInst.addOperand(Inst.getOperand(4)); 6600234353Sdim Inst = TmpInst; 6601234353Sdim return true; 6602234353Sdim } 6603234353Sdim 6604234353Sdim case ARM::VLD3dWB_fixed_Asm_8: 6605234353Sdim case ARM::VLD3dWB_fixed_Asm_16: 6606234353Sdim case ARM::VLD3dWB_fixed_Asm_32: 6607234353Sdim case ARM::VLD3qWB_fixed_Asm_8: 6608234353Sdim case ARM::VLD3qWB_fixed_Asm_16: 6609234353Sdim case ARM::VLD3qWB_fixed_Asm_32: { 6610234353Sdim MCInst TmpInst; 6611234353Sdim unsigned Spacing; 6612234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6613234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6614234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6615234353Sdim Spacing)); 6616234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6617234353Sdim Spacing * 2)); 6618234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6619234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6620234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6621234353Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6622234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6623234353Sdim TmpInst.addOperand(Inst.getOperand(4)); 6624234353Sdim Inst = TmpInst; 6625234353Sdim return true; 6626234353Sdim } 6627234353Sdim 6628234353Sdim case ARM::VLD3dWB_register_Asm_8: 6629234353Sdim case ARM::VLD3dWB_register_Asm_16: 6630234353Sdim case ARM::VLD3dWB_register_Asm_32: 6631234353Sdim case ARM::VLD3qWB_register_Asm_8: 6632234353Sdim case ARM::VLD3qWB_register_Asm_16: 6633234353Sdim case ARM::VLD3qWB_register_Asm_32: { 6634234353Sdim MCInst TmpInst; 6635234353Sdim unsigned Spacing; 6636234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6637234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6638234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6639234353Sdim Spacing)); 6640234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6641234353Sdim Spacing * 2)); 6642234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6643234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6644234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6645234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // Rm 6646234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6647234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6648234353Sdim Inst = TmpInst; 6649234353Sdim return true; 6650234353Sdim } 6651234353Sdim 6652234353Sdim // VLD4DUP single 3-element structure to all lanes instructions. 6653234353Sdim case ARM::VLD4DUPdAsm_8: 6654234353Sdim case ARM::VLD4DUPdAsm_16: 6655234353Sdim case ARM::VLD4DUPdAsm_32: 6656234353Sdim case ARM::VLD4DUPqAsm_8: 6657234353Sdim case ARM::VLD4DUPqAsm_16: 6658234353Sdim case ARM::VLD4DUPqAsm_32: { 6659234353Sdim MCInst TmpInst; 6660234353Sdim unsigned Spacing; 6661234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6662234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6663234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6664234353Sdim Spacing)); 6665234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6666234353Sdim Spacing * 2)); 6667234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6668234353Sdim Spacing * 3)); 6669234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6670234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6671234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6672234353Sdim TmpInst.addOperand(Inst.getOperand(4)); 6673234353Sdim Inst = TmpInst; 6674234353Sdim return true; 6675234353Sdim } 6676234353Sdim 6677234353Sdim case ARM::VLD4DUPdWB_fixed_Asm_8: 6678234353Sdim case ARM::VLD4DUPdWB_fixed_Asm_16: 6679234353Sdim case ARM::VLD4DUPdWB_fixed_Asm_32: 6680234353Sdim case ARM::VLD4DUPqWB_fixed_Asm_8: 6681234353Sdim case ARM::VLD4DUPqWB_fixed_Asm_16: 6682234353Sdim case ARM::VLD4DUPqWB_fixed_Asm_32: { 6683234353Sdim MCInst TmpInst; 6684234353Sdim unsigned Spacing; 6685234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6686234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6687234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6688234353Sdim Spacing)); 6689234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6690234353Sdim Spacing * 2)); 6691234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6692234353Sdim Spacing * 3)); 6693234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6694234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6695234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6696234353Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6697234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6698234353Sdim TmpInst.addOperand(Inst.getOperand(4)); 6699234353Sdim Inst = TmpInst; 6700234353Sdim return true; 6701234353Sdim } 6702234353Sdim 6703234353Sdim case ARM::VLD4DUPdWB_register_Asm_8: 6704234353Sdim case ARM::VLD4DUPdWB_register_Asm_16: 6705234353Sdim case ARM::VLD4DUPdWB_register_Asm_32: 6706234353Sdim case ARM::VLD4DUPqWB_register_Asm_8: 6707234353Sdim case ARM::VLD4DUPqWB_register_Asm_16: 6708234353Sdim case ARM::VLD4DUPqWB_register_Asm_32: { 6709234353Sdim MCInst TmpInst; 6710234353Sdim unsigned Spacing; 6711234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6712234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6713234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6714234353Sdim Spacing)); 6715234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6716234353Sdim Spacing * 2)); 6717234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6718234353Sdim Spacing * 3)); 6719234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6720234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6721234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6722234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // Rm 6723234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6724234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6725234353Sdim Inst = TmpInst; 6726234353Sdim return true; 6727234353Sdim } 6728234353Sdim 6729234353Sdim // VLD4 multiple 4-element structure instructions. 6730234353Sdim case ARM::VLD4dAsm_8: 6731234353Sdim case ARM::VLD4dAsm_16: 6732234353Sdim case ARM::VLD4dAsm_32: 6733234353Sdim case ARM::VLD4qAsm_8: 6734234353Sdim case ARM::VLD4qAsm_16: 6735234353Sdim case ARM::VLD4qAsm_32: { 6736234353Sdim MCInst TmpInst; 6737234353Sdim unsigned Spacing; 6738234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6739234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6740234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6741234353Sdim Spacing)); 6742234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6743234353Sdim Spacing * 2)); 6744234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6745234353Sdim Spacing * 3)); 6746234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6747234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6748234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6749234353Sdim TmpInst.addOperand(Inst.getOperand(4)); 6750234353Sdim Inst = TmpInst; 6751234353Sdim return true; 6752234353Sdim } 6753234353Sdim 6754234353Sdim case ARM::VLD4dWB_fixed_Asm_8: 6755234353Sdim case ARM::VLD4dWB_fixed_Asm_16: 6756234353Sdim case ARM::VLD4dWB_fixed_Asm_32: 6757234353Sdim case ARM::VLD4qWB_fixed_Asm_8: 6758234353Sdim case ARM::VLD4qWB_fixed_Asm_16: 6759234353Sdim case ARM::VLD4qWB_fixed_Asm_32: { 6760234353Sdim MCInst TmpInst; 6761234353Sdim unsigned Spacing; 6762234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6763234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6764234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6765234353Sdim Spacing)); 6766234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6767234353Sdim Spacing * 2)); 6768234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6769234353Sdim Spacing * 3)); 6770234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6771234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6772234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6773234353Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6774234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6775234353Sdim TmpInst.addOperand(Inst.getOperand(4)); 6776234353Sdim Inst = TmpInst; 6777234353Sdim return true; 6778234353Sdim } 6779234353Sdim 6780234353Sdim case ARM::VLD4dWB_register_Asm_8: 6781234353Sdim case ARM::VLD4dWB_register_Asm_16: 6782234353Sdim case ARM::VLD4dWB_register_Asm_32: 6783234353Sdim case ARM::VLD4qWB_register_Asm_8: 6784234353Sdim case ARM::VLD4qWB_register_Asm_16: 6785234353Sdim case ARM::VLD4qWB_register_Asm_32: { 6786234353Sdim MCInst TmpInst; 6787234353Sdim unsigned Spacing; 6788234353Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6789234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6790234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6791234353Sdim Spacing)); 6792234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6793234353Sdim Spacing * 2)); 6794234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6795234353Sdim Spacing * 3)); 6796234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6797234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6798234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6799234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // Rm 6800234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6801234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6802234353Sdim Inst = TmpInst; 6803234353Sdim return true; 6804234353Sdim } 6805234353Sdim 6806234353Sdim // VST3 multiple 3-element structure instructions. 6807234353Sdim case ARM::VST3dAsm_8: 6808234353Sdim case ARM::VST3dAsm_16: 6809234353Sdim case ARM::VST3dAsm_32: 6810234353Sdim case ARM::VST3qAsm_8: 6811234353Sdim case ARM::VST3qAsm_16: 6812234353Sdim case ARM::VST3qAsm_32: { 6813234353Sdim MCInst TmpInst; 6814234353Sdim unsigned Spacing; 6815234353Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6816234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6817234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6818234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6819234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6820234353Sdim Spacing)); 6821234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6822234353Sdim Spacing * 2)); 6823234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6824234353Sdim TmpInst.addOperand(Inst.getOperand(4)); 6825234353Sdim Inst = TmpInst; 6826234353Sdim return true; 6827234353Sdim } 6828234353Sdim 6829234353Sdim case ARM::VST3dWB_fixed_Asm_8: 6830234353Sdim case ARM::VST3dWB_fixed_Asm_16: 6831234353Sdim case ARM::VST3dWB_fixed_Asm_32: 6832234353Sdim case ARM::VST3qWB_fixed_Asm_8: 6833234353Sdim case ARM::VST3qWB_fixed_Asm_16: 6834234353Sdim case ARM::VST3qWB_fixed_Asm_32: { 6835234353Sdim MCInst TmpInst; 6836234353Sdim unsigned Spacing; 6837234353Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6838234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6839234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6840234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6841234353Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6842234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6843234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6844234353Sdim Spacing)); 6845234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6846234353Sdim Spacing * 2)); 6847234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6848234353Sdim TmpInst.addOperand(Inst.getOperand(4)); 6849234353Sdim Inst = TmpInst; 6850234353Sdim return true; 6851234353Sdim } 6852234353Sdim 6853234353Sdim case ARM::VST3dWB_register_Asm_8: 6854234353Sdim case ARM::VST3dWB_register_Asm_16: 6855234353Sdim case ARM::VST3dWB_register_Asm_32: 6856234353Sdim case ARM::VST3qWB_register_Asm_8: 6857234353Sdim case ARM::VST3qWB_register_Asm_16: 6858234353Sdim case ARM::VST3qWB_register_Asm_32: { 6859234353Sdim MCInst TmpInst; 6860234353Sdim unsigned Spacing; 6861234353Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6862234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6863234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6864234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6865234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // Rm 6866234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6867234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6868234353Sdim Spacing)); 6869234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6870234353Sdim Spacing * 2)); 6871234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6872234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6873234353Sdim Inst = TmpInst; 6874234353Sdim return true; 6875234353Sdim } 6876234353Sdim 6877234353Sdim // VST4 multiple 3-element structure instructions. 6878234353Sdim case ARM::VST4dAsm_8: 6879234353Sdim case ARM::VST4dAsm_16: 6880234353Sdim case ARM::VST4dAsm_32: 6881234353Sdim case ARM::VST4qAsm_8: 6882234353Sdim case ARM::VST4qAsm_16: 6883234353Sdim case ARM::VST4qAsm_32: { 6884234353Sdim MCInst TmpInst; 6885234353Sdim unsigned Spacing; 6886234353Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6887234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6888234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6889234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6890234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6891234353Sdim Spacing)); 6892234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6893234353Sdim Spacing * 2)); 6894234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6895234353Sdim Spacing * 3)); 6896234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6897234353Sdim TmpInst.addOperand(Inst.getOperand(4)); 6898234353Sdim Inst = TmpInst; 6899234353Sdim return true; 6900234353Sdim } 6901234353Sdim 6902234353Sdim case ARM::VST4dWB_fixed_Asm_8: 6903234353Sdim case ARM::VST4dWB_fixed_Asm_16: 6904234353Sdim case ARM::VST4dWB_fixed_Asm_32: 6905234353Sdim case ARM::VST4qWB_fixed_Asm_8: 6906234353Sdim case ARM::VST4qWB_fixed_Asm_16: 6907234353Sdim case ARM::VST4qWB_fixed_Asm_32: { 6908234353Sdim MCInst TmpInst; 6909234353Sdim unsigned Spacing; 6910234353Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6911234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6912234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6913234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6914234353Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6915234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6916234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6917234353Sdim Spacing)); 6918234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6919234353Sdim Spacing * 2)); 6920234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6921234353Sdim Spacing * 3)); 6922234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6923234353Sdim TmpInst.addOperand(Inst.getOperand(4)); 6924234353Sdim Inst = TmpInst; 6925234353Sdim return true; 6926234353Sdim } 6927234353Sdim 6928234353Sdim case ARM::VST4dWB_register_Asm_8: 6929234353Sdim case ARM::VST4dWB_register_Asm_16: 6930234353Sdim case ARM::VST4dWB_register_Asm_32: 6931234353Sdim case ARM::VST4qWB_register_Asm_8: 6932234353Sdim case ARM::VST4qWB_register_Asm_16: 6933234353Sdim case ARM::VST4qWB_register_Asm_32: { 6934234353Sdim MCInst TmpInst; 6935234353Sdim unsigned Spacing; 6936234353Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6937234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6938234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6939234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6940234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // Rm 6941234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6942234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6943234353Sdim Spacing)); 6944234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6945234353Sdim Spacing * 2)); 6946234353Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6947234353Sdim Spacing * 3)); 6948234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6949234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6950234353Sdim Inst = TmpInst; 6951234353Sdim return true; 6952234353Sdim } 6953234353Sdim 6954234353Sdim // Handle encoding choice for the shift-immediate instructions. 6955234353Sdim case ARM::t2LSLri: 6956234353Sdim case ARM::t2LSRri: 6957234353Sdim case ARM::t2ASRri: { 6958234353Sdim if (isARMLowRegister(Inst.getOperand(0).getReg()) && 6959234353Sdim Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() && 6960234353Sdim Inst.getOperand(5).getReg() == (inITBlock() ? 0 : ARM::CPSR) && 6961234353Sdim !(static_cast<ARMOperand*>(Operands[3])->isToken() && 6962234353Sdim static_cast<ARMOperand*>(Operands[3])->getToken() == ".w")) { 6963234353Sdim unsigned NewOpc; 6964234353Sdim switch (Inst.getOpcode()) { 6965234353Sdim default: llvm_unreachable("unexpected opcode"); 6966234353Sdim case ARM::t2LSLri: NewOpc = ARM::tLSLri; break; 6967234353Sdim case ARM::t2LSRri: NewOpc = ARM::tLSRri; break; 6968234353Sdim case ARM::t2ASRri: NewOpc = ARM::tASRri; break; 6969234353Sdim } 6970234353Sdim // The Thumb1 operands aren't in the same order. Awesome, eh? 6971234353Sdim MCInst TmpInst; 6972234353Sdim TmpInst.setOpcode(NewOpc); 6973234353Sdim TmpInst.addOperand(Inst.getOperand(0)); 6974234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 6975234353Sdim TmpInst.addOperand(Inst.getOperand(1)); 6976234353Sdim TmpInst.addOperand(Inst.getOperand(2)); 6977234353Sdim TmpInst.addOperand(Inst.getOperand(3)); 6978234353Sdim TmpInst.addOperand(Inst.getOperand(4)); 6979234353Sdim Inst = TmpInst; 6980234353Sdim return true; 6981234353Sdim } 6982234353Sdim return false; 6983234353Sdim } 6984234353Sdim 6985234353Sdim // Handle the Thumb2 mode MOV complex aliases. 6986234353Sdim case ARM::t2MOVsr: 6987234353Sdim case ARM::t2MOVSsr: { 6988234353Sdim // Which instruction to expand to depends on the CCOut operand and 6989234353Sdim // whether we're in an IT block if the register operands are low 6990234353Sdim // registers. 6991234353Sdim bool isNarrow = false; 6992234353Sdim if (isARMLowRegister(Inst.getOperand(0).getReg()) && 6993234353Sdim isARMLowRegister(Inst.getOperand(1).getReg()) && 6994234353Sdim isARMLowRegister(Inst.getOperand(2).getReg()) && 6995234353Sdim Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() && 6996234353Sdim inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr)) 6997234353Sdim isNarrow = true; 6998234353Sdim MCInst TmpInst; 6999234353Sdim unsigned newOpc; 7000234353Sdim switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) { 7001234353Sdim default: llvm_unreachable("unexpected opcode!"); 7002234353Sdim case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break; 7003234353Sdim case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break; 7004234353Sdim case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break; 7005234353Sdim case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break; 7006234353Sdim } 7007234353Sdim TmpInst.setOpcode(newOpc); 7008234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Rd 7009234353Sdim if (isNarrow) 7010234353Sdim TmpInst.addOperand(MCOperand::CreateReg( 7011234353Sdim Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0)); 7012234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 7013234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rm 7014234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 7015234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 7016234353Sdim if (!isNarrow) 7017234353Sdim TmpInst.addOperand(MCOperand::CreateReg( 7018234353Sdim Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0)); 7019234353Sdim Inst = TmpInst; 7020234353Sdim return true; 7021234353Sdim } 7022234353Sdim case ARM::t2MOVsi: 7023234353Sdim case ARM::t2MOVSsi: { 7024234353Sdim // Which instruction to expand to depends on the CCOut operand and 7025234353Sdim // whether we're in an IT block if the register operands are low 7026234353Sdim // registers. 7027234353Sdim bool isNarrow = false; 7028234353Sdim if (isARMLowRegister(Inst.getOperand(0).getReg()) && 7029234353Sdim isARMLowRegister(Inst.getOperand(1).getReg()) && 7030234353Sdim inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi)) 7031234353Sdim isNarrow = true; 7032234353Sdim MCInst TmpInst; 7033234353Sdim unsigned newOpc; 7034234353Sdim switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) { 7035234353Sdim default: llvm_unreachable("unexpected opcode!"); 7036234353Sdim case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break; 7037234353Sdim case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break; 7038234353Sdim case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break; 7039234353Sdim case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break; 7040234353Sdim case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break; 7041234353Sdim } 7042239462Sdim unsigned Amount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()); 7043239462Sdim if (Amount == 32) Amount = 0; 7044234353Sdim TmpInst.setOpcode(newOpc); 7045234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Rd 7046234353Sdim if (isNarrow) 7047234353Sdim TmpInst.addOperand(MCOperand::CreateReg( 7048234353Sdim Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0)); 7049234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 7050234353Sdim if (newOpc != ARM::t2RRX) 7051239462Sdim TmpInst.addOperand(MCOperand::CreateImm(Amount)); 7052234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 7053234353Sdim TmpInst.addOperand(Inst.getOperand(4)); 7054234353Sdim if (!isNarrow) 7055234353Sdim TmpInst.addOperand(MCOperand::CreateReg( 7056234353Sdim Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0)); 7057234353Sdim Inst = TmpInst; 7058234353Sdim return true; 7059234353Sdim } 7060234353Sdim // Handle the ARM mode MOV complex aliases. 7061234353Sdim case ARM::ASRr: 7062234353Sdim case ARM::LSRr: 7063234353Sdim case ARM::LSLr: 7064234353Sdim case ARM::RORr: { 7065234353Sdim ARM_AM::ShiftOpc ShiftTy; 7066234353Sdim switch(Inst.getOpcode()) { 7067234353Sdim default: llvm_unreachable("unexpected opcode!"); 7068234353Sdim case ARM::ASRr: ShiftTy = ARM_AM::asr; break; 7069234353Sdim case ARM::LSRr: ShiftTy = ARM_AM::lsr; break; 7070234353Sdim case ARM::LSLr: ShiftTy = ARM_AM::lsl; break; 7071234353Sdim case ARM::RORr: ShiftTy = ARM_AM::ror; break; 7072234353Sdim } 7073234353Sdim unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0); 7074234353Sdim MCInst TmpInst; 7075234353Sdim TmpInst.setOpcode(ARM::MOVsr); 7076234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Rd 7077234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 7078234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rm 7079234353Sdim TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty 7080234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 7081234353Sdim TmpInst.addOperand(Inst.getOperand(4)); 7082234353Sdim TmpInst.addOperand(Inst.getOperand(5)); // cc_out 7083234353Sdim Inst = TmpInst; 7084234353Sdim return true; 7085234353Sdim } 7086234353Sdim case ARM::ASRi: 7087234353Sdim case ARM::LSRi: 7088234353Sdim case ARM::LSLi: 7089234353Sdim case ARM::RORi: { 7090234353Sdim ARM_AM::ShiftOpc ShiftTy; 7091234353Sdim switch(Inst.getOpcode()) { 7092234353Sdim default: llvm_unreachable("unexpected opcode!"); 7093234353Sdim case ARM::ASRi: ShiftTy = ARM_AM::asr; break; 7094234353Sdim case ARM::LSRi: ShiftTy = ARM_AM::lsr; break; 7095234353Sdim case ARM::LSLi: ShiftTy = ARM_AM::lsl; break; 7096234353Sdim case ARM::RORi: ShiftTy = ARM_AM::ror; break; 7097234353Sdim } 7098234353Sdim // A shift by zero is a plain MOVr, not a MOVsi. 7099234353Sdim unsigned Amt = Inst.getOperand(2).getImm(); 7100234353Sdim unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi; 7101239462Sdim // A shift by 32 should be encoded as 0 when permitted 7102239462Sdim if (Amt == 32 && (ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr)) 7103239462Sdim Amt = 0; 7104234353Sdim unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt); 7105234353Sdim MCInst TmpInst; 7106234353Sdim TmpInst.setOpcode(Opc); 7107234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Rd 7108234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 7109234353Sdim if (Opc == ARM::MOVsi) 7110234353Sdim TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty 7111234353Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 7112234353Sdim TmpInst.addOperand(Inst.getOperand(4)); 7113234353Sdim TmpInst.addOperand(Inst.getOperand(5)); // cc_out 7114234353Sdim Inst = TmpInst; 7115234353Sdim return true; 7116234353Sdim } 7117234353Sdim case ARM::RRXi: { 7118234353Sdim unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0); 7119234353Sdim MCInst TmpInst; 7120234353Sdim TmpInst.setOpcode(ARM::MOVsi); 7121234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Rd 7122234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 7123234353Sdim TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty 7124234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // CondCode 7125234353Sdim TmpInst.addOperand(Inst.getOperand(3)); 7126234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // cc_out 7127234353Sdim Inst = TmpInst; 7128234353Sdim return true; 7129234353Sdim } 7130234353Sdim case ARM::t2LDMIA_UPD: { 7131234353Sdim // If this is a load of a single register, then we should use 7132234353Sdim // a post-indexed LDR instruction instead, per the ARM ARM. 7133234353Sdim if (Inst.getNumOperands() != 5) 7134234353Sdim return false; 7135234353Sdim MCInst TmpInst; 7136234353Sdim TmpInst.setOpcode(ARM::t2LDR_POST); 7137234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rt 7138234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb 7139234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 7140234353Sdim TmpInst.addOperand(MCOperand::CreateImm(4)); 7141234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // CondCode 7142234353Sdim TmpInst.addOperand(Inst.getOperand(3)); 7143234353Sdim Inst = TmpInst; 7144234353Sdim return true; 7145234353Sdim } 7146234353Sdim case ARM::t2STMDB_UPD: { 7147234353Sdim // If this is a store of a single register, then we should use 7148234353Sdim // a pre-indexed STR instruction instead, per the ARM ARM. 7149234353Sdim if (Inst.getNumOperands() != 5) 7150234353Sdim return false; 7151234353Sdim MCInst TmpInst; 7152234353Sdim TmpInst.setOpcode(ARM::t2STR_PRE); 7153234353Sdim TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb 7154234353Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rt 7155234353Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 7156234353Sdim TmpInst.addOperand(MCOperand::CreateImm(-4)); 7157234353Sdim TmpInst.addOperand(Inst.getOperand(2)); // CondCode 7158234353Sdim TmpInst.addOperand(Inst.getOperand(3)); 7159234353Sdim Inst = TmpInst; 7160234353Sdim return true; 7161234353Sdim } 7162226633Sdim case ARM::LDMIA_UPD: 7163226633Sdim // If this is a load of a single register via a 'pop', then we should use 7164226633Sdim // a post-indexed LDR instruction instead, per the ARM ARM. 7165226633Sdim if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" && 7166226633Sdim Inst.getNumOperands() == 5) { 7167226633Sdim MCInst TmpInst; 7168226633Sdim TmpInst.setOpcode(ARM::LDR_POST_IMM); 7169226633Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rt 7170226633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb 7171226633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 7172226633Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset 7173226633Sdim TmpInst.addOperand(MCOperand::CreateImm(4)); 7174226633Sdim TmpInst.addOperand(Inst.getOperand(2)); // CondCode 7175226633Sdim TmpInst.addOperand(Inst.getOperand(3)); 7176226633Sdim Inst = TmpInst; 7177234353Sdim return true; 7178226633Sdim } 7179226633Sdim break; 7180226633Sdim case ARM::STMDB_UPD: 7181226633Sdim // If this is a store of a single register via a 'push', then we should use 7182226633Sdim // a pre-indexed STR instruction instead, per the ARM ARM. 7183226633Sdim if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" && 7184226633Sdim Inst.getNumOperands() == 5) { 7185226633Sdim MCInst TmpInst; 7186226633Sdim TmpInst.setOpcode(ARM::STR_PRE_IMM); 7187226633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb 7188226633Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rt 7189226633Sdim TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12 7190226633Sdim TmpInst.addOperand(MCOperand::CreateImm(-4)); 7191226633Sdim TmpInst.addOperand(Inst.getOperand(2)); // CondCode 7192226633Sdim TmpInst.addOperand(Inst.getOperand(3)); 7193226633Sdim Inst = TmpInst; 7194226633Sdim } 7195226633Sdim break; 7196234353Sdim case ARM::t2ADDri12: 7197234353Sdim // If the immediate fits for encoding T3 (t2ADDri) and the generic "add" 7198234353Sdim // mnemonic was used (not "addw"), encoding T3 is preferred. 7199234353Sdim if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" || 7200234353Sdim ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1) 7201234353Sdim break; 7202234353Sdim Inst.setOpcode(ARM::t2ADDri); 7203234353Sdim Inst.addOperand(MCOperand::CreateReg(0)); // cc_out 7204234353Sdim break; 7205234353Sdim case ARM::t2SUBri12: 7206234353Sdim // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub" 7207234353Sdim // mnemonic was used (not "subw"), encoding T3 is preferred. 7208234353Sdim if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" || 7209234353Sdim ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1) 7210234353Sdim break; 7211234353Sdim Inst.setOpcode(ARM::t2SUBri); 7212234353Sdim Inst.addOperand(MCOperand::CreateReg(0)); // cc_out 7213234353Sdim break; 7214226633Sdim case ARM::tADDi8: 7215226633Sdim // If the immediate is in the range 0-7, we want tADDi3 iff Rd was 7216226633Sdim // explicitly specified. From the ARM ARM: "Encoding T1 is preferred 7217226633Sdim // to encoding T2 if <Rd> is specified and encoding T2 is preferred 7218226633Sdim // to encoding T1 if <Rd> is omitted." 7219234353Sdim if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) { 7220226633Sdim Inst.setOpcode(ARM::tADDi3); 7221234353Sdim return true; 7222234353Sdim } 7223226633Sdim break; 7224226633Sdim case ARM::tSUBi8: 7225226633Sdim // If the immediate is in the range 0-7, we want tADDi3 iff Rd was 7226226633Sdim // explicitly specified. From the ARM ARM: "Encoding T1 is preferred 7227226633Sdim // to encoding T2 if <Rd> is specified and encoding T2 is preferred 7228226633Sdim // to encoding T1 if <Rd> is omitted." 7229234353Sdim if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) { 7230226633Sdim Inst.setOpcode(ARM::tSUBi3); 7231234353Sdim return true; 7232234353Sdim } 7233226633Sdim break; 7234234353Sdim case ARM::t2ADDri: 7235234353Sdim case ARM::t2SUBri: { 7236234353Sdim // If the destination and first source operand are the same, and 7237234353Sdim // the flags are compatible with the current IT status, use encoding T2 7238234353Sdim // instead of T3. For compatibility with the system 'as'. Make sure the 7239234353Sdim // wide encoding wasn't explicit. 7240234353Sdim if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() || 7241234353Sdim !isARMLowRegister(Inst.getOperand(0).getReg()) || 7242234353Sdim (unsigned)Inst.getOperand(2).getImm() > 255 || 7243234353Sdim ((!inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR) || 7244234353Sdim (inITBlock() && Inst.getOperand(5).getReg() != 0)) || 7245234353Sdim (static_cast<ARMOperand*>(Operands[3])->isToken() && 7246234353Sdim static_cast<ARMOperand*>(Operands[3])->getToken() == ".w")) 7247234353Sdim break; 7248234353Sdim MCInst TmpInst; 7249234353Sdim TmpInst.setOpcode(Inst.getOpcode() == ARM::t2ADDri ? 7250234353Sdim ARM::tADDi8 : ARM::tSUBi8); 7251234353Sdim TmpInst.addOperand(Inst.getOperand(0)); 7252234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 7253234353Sdim TmpInst.addOperand(Inst.getOperand(0)); 7254234353Sdim TmpInst.addOperand(Inst.getOperand(2)); 7255234353Sdim TmpInst.addOperand(Inst.getOperand(3)); 7256234353Sdim TmpInst.addOperand(Inst.getOperand(4)); 7257234353Sdim Inst = TmpInst; 7258234353Sdim return true; 7259234353Sdim } 7260234353Sdim case ARM::t2ADDrr: { 7261234353Sdim // If the destination and first source operand are the same, and 7262234353Sdim // there's no setting of the flags, use encoding T2 instead of T3. 7263234353Sdim // Note that this is only for ADD, not SUB. This mirrors the system 7264234353Sdim // 'as' behaviour. Make sure the wide encoding wasn't explicit. 7265234353Sdim if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() || 7266234353Sdim Inst.getOperand(5).getReg() != 0 || 7267234353Sdim (static_cast<ARMOperand*>(Operands[3])->isToken() && 7268234353Sdim static_cast<ARMOperand*>(Operands[3])->getToken() == ".w")) 7269234353Sdim break; 7270234353Sdim MCInst TmpInst; 7271234353Sdim TmpInst.setOpcode(ARM::tADDhirr); 7272234353Sdim TmpInst.addOperand(Inst.getOperand(0)); 7273234353Sdim TmpInst.addOperand(Inst.getOperand(0)); 7274234353Sdim TmpInst.addOperand(Inst.getOperand(2)); 7275234353Sdim TmpInst.addOperand(Inst.getOperand(3)); 7276234353Sdim TmpInst.addOperand(Inst.getOperand(4)); 7277234353Sdim Inst = TmpInst; 7278234353Sdim return true; 7279234353Sdim } 7280239462Sdim case ARM::tADDrSP: { 7281239462Sdim // If the non-SP source operand and the destination operand are not the 7282239462Sdim // same, we need to use the 32-bit encoding if it's available. 7283239462Sdim if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) { 7284239462Sdim Inst.setOpcode(ARM::t2ADDrr); 7285239462Sdim Inst.addOperand(MCOperand::CreateReg(0)); // cc_out 7286239462Sdim return true; 7287239462Sdim } 7288239462Sdim break; 7289239462Sdim } 7290226633Sdim case ARM::tB: 7291226633Sdim // A Thumb conditional branch outside of an IT block is a tBcc. 7292234353Sdim if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) { 7293226633Sdim Inst.setOpcode(ARM::tBcc); 7294234353Sdim return true; 7295234353Sdim } 7296226633Sdim break; 7297226633Sdim case ARM::t2B: 7298226633Sdim // A Thumb2 conditional branch outside of an IT block is a t2Bcc. 7299234353Sdim if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){ 7300226633Sdim Inst.setOpcode(ARM::t2Bcc); 7301234353Sdim return true; 7302234353Sdim } 7303226633Sdim break; 7304226633Sdim case ARM::t2Bcc: 7305226633Sdim // If the conditional is AL or we're in an IT block, we really want t2B. 7306234353Sdim if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) { 7307226633Sdim Inst.setOpcode(ARM::t2B); 7308234353Sdim return true; 7309234353Sdim } 7310226633Sdim break; 7311226633Sdim case ARM::tBcc: 7312226633Sdim // If the conditional is AL, we really want tB. 7313234353Sdim if (Inst.getOperand(1).getImm() == ARMCC::AL) { 7314226633Sdim Inst.setOpcode(ARM::tB); 7315234353Sdim return true; 7316234353Sdim } 7317226633Sdim break; 7318226633Sdim case ARM::tLDMIA: { 7319226633Sdim // If the register list contains any high registers, or if the writeback 7320226633Sdim // doesn't match what tLDMIA can do, we need to use the 32-bit encoding 7321226633Sdim // instead if we're in Thumb2. Otherwise, this should have generated 7322226633Sdim // an error in validateInstruction(). 7323226633Sdim unsigned Rn = Inst.getOperand(0).getReg(); 7324226633Sdim bool hasWritebackToken = 7325226633Sdim (static_cast<ARMOperand*>(Operands[3])->isToken() && 7326226633Sdim static_cast<ARMOperand*>(Operands[3])->getToken() == "!"); 7327226633Sdim bool listContainsBase; 7328226633Sdim if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) || 7329226633Sdim (!listContainsBase && !hasWritebackToken) || 7330226633Sdim (listContainsBase && hasWritebackToken)) { 7331226633Sdim // 16-bit encoding isn't sufficient. Switch to the 32-bit version. 7332226633Sdim assert (isThumbTwo()); 7333226633Sdim Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA); 7334226633Sdim // If we're switching to the updating version, we need to insert 7335226633Sdim // the writeback tied operand. 7336226633Sdim if (hasWritebackToken) 7337226633Sdim Inst.insert(Inst.begin(), 7338226633Sdim MCOperand::CreateReg(Inst.getOperand(0).getReg())); 7339234353Sdim return true; 7340226633Sdim } 7341226633Sdim break; 7342226633Sdim } 7343226633Sdim case ARM::tSTMIA_UPD: { 7344226633Sdim // If the register list contains any high registers, we need to use 7345226633Sdim // the 32-bit encoding instead if we're in Thumb2. Otherwise, this 7346226633Sdim // should have generated an error in validateInstruction(). 7347226633Sdim unsigned Rn = Inst.getOperand(0).getReg(); 7348226633Sdim bool listContainsBase; 7349226633Sdim if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) { 7350226633Sdim // 16-bit encoding isn't sufficient. Switch to the 32-bit version. 7351226633Sdim assert (isThumbTwo()); 7352226633Sdim Inst.setOpcode(ARM::t2STMIA_UPD); 7353234353Sdim return true; 7354226633Sdim } 7355226633Sdim break; 7356226633Sdim } 7357234353Sdim case ARM::tPOP: { 7358234353Sdim bool listContainsBase; 7359234353Sdim // If the register list contains any high registers, we need to use 7360234353Sdim // the 32-bit encoding instead if we're in Thumb2. Otherwise, this 7361234353Sdim // should have generated an error in validateInstruction(). 7362234353Sdim if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase)) 7363234353Sdim return false; 7364234353Sdim assert (isThumbTwo()); 7365234353Sdim Inst.setOpcode(ARM::t2LDMIA_UPD); 7366234353Sdim // Add the base register and writeback operands. 7367234353Sdim Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP)); 7368234353Sdim Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP)); 7369234353Sdim return true; 7370234353Sdim } 7371234353Sdim case ARM::tPUSH: { 7372234353Sdim bool listContainsBase; 7373234353Sdim if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase)) 7374234353Sdim return false; 7375234353Sdim assert (isThumbTwo()); 7376234353Sdim Inst.setOpcode(ARM::t2STMDB_UPD); 7377234353Sdim // Add the base register and writeback operands. 7378234353Sdim Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP)); 7379234353Sdim Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP)); 7380234353Sdim return true; 7381234353Sdim } 7382226633Sdim case ARM::t2MOVi: { 7383226633Sdim // If we can use the 16-bit encoding and the user didn't explicitly 7384226633Sdim // request the 32-bit variant, transform it here. 7385226633Sdim if (isARMLowRegister(Inst.getOperand(0).getReg()) && 7386234353Sdim (unsigned)Inst.getOperand(1).getImm() <= 255 && 7387226633Sdim ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL && 7388226633Sdim Inst.getOperand(4).getReg() == ARM::CPSR) || 7389226633Sdim (inITBlock() && Inst.getOperand(4).getReg() == 0)) && 7390226633Sdim (!static_cast<ARMOperand*>(Operands[2])->isToken() || 7391226633Sdim static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) { 7392226633Sdim // The operands aren't in the same order for tMOVi8... 7393226633Sdim MCInst TmpInst; 7394226633Sdim TmpInst.setOpcode(ARM::tMOVi8); 7395226633Sdim TmpInst.addOperand(Inst.getOperand(0)); 7396226633Sdim TmpInst.addOperand(Inst.getOperand(4)); 7397226633Sdim TmpInst.addOperand(Inst.getOperand(1)); 7398226633Sdim TmpInst.addOperand(Inst.getOperand(2)); 7399226633Sdim TmpInst.addOperand(Inst.getOperand(3)); 7400226633Sdim Inst = TmpInst; 7401234353Sdim return true; 7402226633Sdim } 7403226633Sdim break; 7404226633Sdim } 7405226633Sdim case ARM::t2MOVr: { 7406226633Sdim // If we can use the 16-bit encoding and the user didn't explicitly 7407226633Sdim // request the 32-bit variant, transform it here. 7408226633Sdim if (isARMLowRegister(Inst.getOperand(0).getReg()) && 7409226633Sdim isARMLowRegister(Inst.getOperand(1).getReg()) && 7410226633Sdim Inst.getOperand(2).getImm() == ARMCC::AL && 7411226633Sdim Inst.getOperand(4).getReg() == ARM::CPSR && 7412226633Sdim (!static_cast<ARMOperand*>(Operands[2])->isToken() || 7413226633Sdim static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) { 7414226633Sdim // The operands aren't the same for tMOV[S]r... (no cc_out) 7415226633Sdim MCInst TmpInst; 7416226633Sdim TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr); 7417226633Sdim TmpInst.addOperand(Inst.getOperand(0)); 7418226633Sdim TmpInst.addOperand(Inst.getOperand(1)); 7419226633Sdim TmpInst.addOperand(Inst.getOperand(2)); 7420226633Sdim TmpInst.addOperand(Inst.getOperand(3)); 7421226633Sdim Inst = TmpInst; 7422234353Sdim return true; 7423226633Sdim } 7424226633Sdim break; 7425226633Sdim } 7426226633Sdim case ARM::t2SXTH: 7427226633Sdim case ARM::t2SXTB: 7428226633Sdim case ARM::t2UXTH: 7429226633Sdim case ARM::t2UXTB: { 7430226633Sdim // If we can use the 16-bit encoding and the user didn't explicitly 7431226633Sdim // request the 32-bit variant, transform it here. 7432226633Sdim if (isARMLowRegister(Inst.getOperand(0).getReg()) && 7433226633Sdim isARMLowRegister(Inst.getOperand(1).getReg()) && 7434226633Sdim Inst.getOperand(2).getImm() == 0 && 7435226633Sdim (!static_cast<ARMOperand*>(Operands[2])->isToken() || 7436226633Sdim static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) { 7437226633Sdim unsigned NewOpc; 7438226633Sdim switch (Inst.getOpcode()) { 7439226633Sdim default: llvm_unreachable("Illegal opcode!"); 7440226633Sdim case ARM::t2SXTH: NewOpc = ARM::tSXTH; break; 7441226633Sdim case ARM::t2SXTB: NewOpc = ARM::tSXTB; break; 7442226633Sdim case ARM::t2UXTH: NewOpc = ARM::tUXTH; break; 7443226633Sdim case ARM::t2UXTB: NewOpc = ARM::tUXTB; break; 7444226633Sdim } 7445226633Sdim // The operands aren't the same for thumb1 (no rotate operand). 7446226633Sdim MCInst TmpInst; 7447226633Sdim TmpInst.setOpcode(NewOpc); 7448226633Sdim TmpInst.addOperand(Inst.getOperand(0)); 7449226633Sdim TmpInst.addOperand(Inst.getOperand(1)); 7450226633Sdim TmpInst.addOperand(Inst.getOperand(3)); 7451226633Sdim TmpInst.addOperand(Inst.getOperand(4)); 7452226633Sdim Inst = TmpInst; 7453234353Sdim return true; 7454226633Sdim } 7455226633Sdim break; 7456226633Sdim } 7457234353Sdim case ARM::MOVsi: { 7458234353Sdim ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm()); 7459239462Sdim // rrx shifts and asr/lsr of #32 is encoded as 0 7460239462Sdim if (SOpc == ARM_AM::rrx || SOpc == ARM_AM::asr || SOpc == ARM_AM::lsr) 7461239462Sdim return false; 7462234353Sdim if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) { 7463234353Sdim // Shifting by zero is accepted as a vanilla 'MOVr' 7464234353Sdim MCInst TmpInst; 7465234353Sdim TmpInst.setOpcode(ARM::MOVr); 7466234353Sdim TmpInst.addOperand(Inst.getOperand(0)); 7467234353Sdim TmpInst.addOperand(Inst.getOperand(1)); 7468234353Sdim TmpInst.addOperand(Inst.getOperand(3)); 7469234353Sdim TmpInst.addOperand(Inst.getOperand(4)); 7470234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 7471234353Sdim Inst = TmpInst; 7472234353Sdim return true; 7473234353Sdim } 7474234353Sdim return false; 7475234353Sdim } 7476234353Sdim case ARM::ANDrsi: 7477234353Sdim case ARM::ORRrsi: 7478234353Sdim case ARM::EORrsi: 7479234353Sdim case ARM::BICrsi: 7480234353Sdim case ARM::SUBrsi: 7481234353Sdim case ARM::ADDrsi: { 7482234353Sdim unsigned newOpc; 7483234353Sdim ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm()); 7484234353Sdim if (SOpc == ARM_AM::rrx) return false; 7485234353Sdim switch (Inst.getOpcode()) { 7486234353Sdim default: llvm_unreachable("unexpected opcode!"); 7487234353Sdim case ARM::ANDrsi: newOpc = ARM::ANDrr; break; 7488234353Sdim case ARM::ORRrsi: newOpc = ARM::ORRrr; break; 7489234353Sdim case ARM::EORrsi: newOpc = ARM::EORrr; break; 7490234353Sdim case ARM::BICrsi: newOpc = ARM::BICrr; break; 7491234353Sdim case ARM::SUBrsi: newOpc = ARM::SUBrr; break; 7492234353Sdim case ARM::ADDrsi: newOpc = ARM::ADDrr; break; 7493234353Sdim } 7494234353Sdim // If the shift is by zero, use the non-shifted instruction definition. 7495239462Sdim // The exception is for right shifts, where 0 == 32 7496239462Sdim if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0 && 7497239462Sdim !(SOpc == ARM_AM::lsr || SOpc == ARM_AM::asr)) { 7498234353Sdim MCInst TmpInst; 7499234353Sdim TmpInst.setOpcode(newOpc); 7500234353Sdim TmpInst.addOperand(Inst.getOperand(0)); 7501234353Sdim TmpInst.addOperand(Inst.getOperand(1)); 7502234353Sdim TmpInst.addOperand(Inst.getOperand(2)); 7503234353Sdim TmpInst.addOperand(Inst.getOperand(4)); 7504234353Sdim TmpInst.addOperand(Inst.getOperand(5)); 7505234353Sdim TmpInst.addOperand(Inst.getOperand(6)); 7506234353Sdim Inst = TmpInst; 7507234353Sdim return true; 7508234353Sdim } 7509234353Sdim return false; 7510234353Sdim } 7511234353Sdim case ARM::ITasm: 7512226633Sdim case ARM::t2IT: { 7513226633Sdim // The mask bits for all but the first condition are represented as 7514226633Sdim // the low bit of the condition code value implies 't'. We currently 7515226633Sdim // always have 1 implies 't', so XOR toggle the bits if the low bit 7516239462Sdim // of the condition code is zero. 7517226633Sdim MCOperand &MO = Inst.getOperand(1); 7518226633Sdim unsigned Mask = MO.getImm(); 7519226633Sdim unsigned OrigMask = Mask; 7520263508Sdim unsigned TZ = countTrailingZeros(Mask); 7521226633Sdim if ((Inst.getOperand(0).getImm() & 1) == 0) { 7522226633Sdim assert(Mask && TZ <= 3 && "illegal IT mask value!"); 7523263508Sdim Mask ^= (0xE << TZ) & 0xF; 7524239462Sdim } 7525226633Sdim MO.setImm(Mask); 7526226633Sdim 7527226633Sdim // Set up the IT block state according to the IT instruction we just 7528226633Sdim // matched. 7529226633Sdim assert(!inITBlock() && "nested IT blocks?!"); 7530226633Sdim ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm()); 7531226633Sdim ITState.Mask = OrigMask; // Use the original mask, not the updated one. 7532226633Sdim ITState.CurPosition = 0; 7533226633Sdim ITState.FirstCond = true; 7534226633Sdim break; 7535226633Sdim } 7536239462Sdim case ARM::t2LSLrr: 7537239462Sdim case ARM::t2LSRrr: 7538239462Sdim case ARM::t2ASRrr: 7539239462Sdim case ARM::t2SBCrr: 7540239462Sdim case ARM::t2RORrr: 7541239462Sdim case ARM::t2BICrr: 7542239462Sdim { 7543239462Sdim // Assemblers should use the narrow encodings of these instructions when permissible. 7544239462Sdim if ((isARMLowRegister(Inst.getOperand(1).getReg()) && 7545239462Sdim isARMLowRegister(Inst.getOperand(2).getReg())) && 7546239462Sdim Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() && 7547239462Sdim ((!inITBlock() && Inst.getOperand(5).getReg() == ARM::CPSR) || 7548239462Sdim (inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR)) && 7549239462Sdim (!static_cast<ARMOperand*>(Operands[3])->isToken() || 7550239462Sdim !static_cast<ARMOperand*>(Operands[3])->getToken().equals_lower(".w"))) { 7551239462Sdim unsigned NewOpc; 7552239462Sdim switch (Inst.getOpcode()) { 7553239462Sdim default: llvm_unreachable("unexpected opcode"); 7554239462Sdim case ARM::t2LSLrr: NewOpc = ARM::tLSLrr; break; 7555239462Sdim case ARM::t2LSRrr: NewOpc = ARM::tLSRrr; break; 7556239462Sdim case ARM::t2ASRrr: NewOpc = ARM::tASRrr; break; 7557239462Sdim case ARM::t2SBCrr: NewOpc = ARM::tSBC; break; 7558239462Sdim case ARM::t2RORrr: NewOpc = ARM::tROR; break; 7559239462Sdim case ARM::t2BICrr: NewOpc = ARM::tBIC; break; 7560239462Sdim } 7561239462Sdim MCInst TmpInst; 7562239462Sdim TmpInst.setOpcode(NewOpc); 7563239462Sdim TmpInst.addOperand(Inst.getOperand(0)); 7564239462Sdim TmpInst.addOperand(Inst.getOperand(5)); 7565239462Sdim TmpInst.addOperand(Inst.getOperand(1)); 7566239462Sdim TmpInst.addOperand(Inst.getOperand(2)); 7567239462Sdim TmpInst.addOperand(Inst.getOperand(3)); 7568239462Sdim TmpInst.addOperand(Inst.getOperand(4)); 7569239462Sdim Inst = TmpInst; 7570239462Sdim return true; 7571239462Sdim } 7572239462Sdim return false; 7573226633Sdim } 7574239462Sdim case ARM::t2ANDrr: 7575239462Sdim case ARM::t2EORrr: 7576239462Sdim case ARM::t2ADCrr: 7577239462Sdim case ARM::t2ORRrr: 7578239462Sdim { 7579239462Sdim // Assemblers should use the narrow encodings of these instructions when permissible. 7580239462Sdim // These instructions are special in that they are commutable, so shorter encodings 7581239462Sdim // are available more often. 7582239462Sdim if ((isARMLowRegister(Inst.getOperand(1).getReg()) && 7583239462Sdim isARMLowRegister(Inst.getOperand(2).getReg())) && 7584239462Sdim (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() || 7585239462Sdim Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg()) && 7586239462Sdim ((!inITBlock() && Inst.getOperand(5).getReg() == ARM::CPSR) || 7587239462Sdim (inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR)) && 7588239462Sdim (!static_cast<ARMOperand*>(Operands[3])->isToken() || 7589239462Sdim !static_cast<ARMOperand*>(Operands[3])->getToken().equals_lower(".w"))) { 7590239462Sdim unsigned NewOpc; 7591239462Sdim switch (Inst.getOpcode()) { 7592239462Sdim default: llvm_unreachable("unexpected opcode"); 7593239462Sdim case ARM::t2ADCrr: NewOpc = ARM::tADC; break; 7594239462Sdim case ARM::t2ANDrr: NewOpc = ARM::tAND; break; 7595239462Sdim case ARM::t2EORrr: NewOpc = ARM::tEOR; break; 7596239462Sdim case ARM::t2ORRrr: NewOpc = ARM::tORR; break; 7597239462Sdim } 7598239462Sdim MCInst TmpInst; 7599239462Sdim TmpInst.setOpcode(NewOpc); 7600239462Sdim TmpInst.addOperand(Inst.getOperand(0)); 7601239462Sdim TmpInst.addOperand(Inst.getOperand(5)); 7602239462Sdim if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()) { 7603239462Sdim TmpInst.addOperand(Inst.getOperand(1)); 7604239462Sdim TmpInst.addOperand(Inst.getOperand(2)); 7605239462Sdim } else { 7606239462Sdim TmpInst.addOperand(Inst.getOperand(2)); 7607239462Sdim TmpInst.addOperand(Inst.getOperand(1)); 7608239462Sdim } 7609239462Sdim TmpInst.addOperand(Inst.getOperand(3)); 7610239462Sdim TmpInst.addOperand(Inst.getOperand(4)); 7611239462Sdim Inst = TmpInst; 7612239462Sdim return true; 7613239462Sdim } 7614239462Sdim return false; 7615239462Sdim } 7616239462Sdim } 7617234353Sdim return false; 7618226633Sdim} 7619226633Sdim 7620226633Sdimunsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) { 7621226633Sdim // 16-bit thumb arithmetic instructions either require or preclude the 'S' 7622226633Sdim // suffix depending on whether they're in an IT block or not. 7623226633Sdim unsigned Opc = Inst.getOpcode(); 7624263508Sdim const MCInstrDesc &MCID = MII.get(Opc); 7625226633Sdim if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) { 7626226633Sdim assert(MCID.hasOptionalDef() && 7627226633Sdim "optionally flag setting instruction missing optional def operand"); 7628226633Sdim assert(MCID.NumOperands == Inst.getNumOperands() && 7629226633Sdim "operand count mismatch!"); 7630226633Sdim // Find the optional-def operand (cc_out). 7631226633Sdim unsigned OpNo; 7632226633Sdim for (OpNo = 0; 7633226633Sdim !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands; 7634226633Sdim ++OpNo) 7635226633Sdim ; 7636226633Sdim // If we're parsing Thumb1, reject it completely. 7637226633Sdim if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR) 7638226633Sdim return Match_MnemonicFail; 7639226633Sdim // If we're parsing Thumb2, which form is legal depends on whether we're 7640226633Sdim // in an IT block. 7641226633Sdim if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR && 7642226633Sdim !inITBlock()) 7643226633Sdim return Match_RequiresITBlock; 7644226633Sdim if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR && 7645226633Sdim inITBlock()) 7646226633Sdim return Match_RequiresNotITBlock; 7647226633Sdim } 7648226633Sdim // Some high-register supporting Thumb1 encodings only allow both registers 7649226633Sdim // to be from r0-r7 when in Thumb2. 7650226633Sdim else if (Opc == ARM::tADDhirr && isThumbOne() && 7651226633Sdim isARMLowRegister(Inst.getOperand(1).getReg()) && 7652226633Sdim isARMLowRegister(Inst.getOperand(2).getReg())) 7653226633Sdim return Match_RequiresThumb2; 7654226633Sdim // Others only require ARMv6 or later. 7655226633Sdim else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() && 7656226633Sdim isARMLowRegister(Inst.getOperand(0).getReg()) && 7657226633Sdim isARMLowRegister(Inst.getOperand(1).getReg())) 7658226633Sdim return Match_RequiresV6; 7659226633Sdim return Match_Success; 7660226633Sdim} 7661226633Sdim 7662239462Sdimstatic const char *getSubtargetFeatureName(unsigned Val); 7663226633Sdimbool ARMAsmParser:: 7664243830SdimMatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 7665218893Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands, 7666243830Sdim MCStreamer &Out, unsigned &ErrorInfo, 7667243830Sdim bool MatchingInlineAsm) { 7668218893Sdim MCInst Inst; 7669226633Sdim unsigned MatchResult; 7670249423Sdim 7671243830Sdim MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, 7672243830Sdim MatchingInlineAsm); 7673218893Sdim switch (MatchResult) { 7674226633Sdim default: break; 7675218893Sdim case Match_Success: 7676226633Sdim // Context sensitive operand constraints aren't handled by the matcher, 7677226633Sdim // so check them here. 7678226633Sdim if (validateInstruction(Inst, Operands)) { 7679226633Sdim // Still progress the IT block, otherwise one wrong condition causes 7680226633Sdim // nasty cascading errors. 7681226633Sdim forwardITPosition(); 7682226633Sdim return true; 7683226633Sdim } 7684226633Sdim 7685263508Sdim { // processInstruction() updates inITBlock state, we need to save it away 7686263508Sdim bool wasInITBlock = inITBlock(); 7687226633Sdim 7688263508Sdim // Some instructions need post-processing to, for example, tweak which 7689263508Sdim // encoding is selected. Loop on it while changes happen so the 7690263508Sdim // individual transformations can chain off each other. E.g., 7691263508Sdim // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8) 7692263508Sdim while (processInstruction(Inst, Operands)) 7693263508Sdim ; 7694263508Sdim 7695263508Sdim // Only after the instruction is fully processed, we can validate it 7696263508Sdim if (wasInITBlock && hasV8Ops() && isThumb() && 7697263508Sdim !isV8EligibleForIT(&Inst, 2)) { 7698263508Sdim Warning(IDLoc, "deprecated instruction in IT block"); 7699263508Sdim } 7700263508Sdim } 7701263508Sdim 7702226633Sdim // Only move forward at the very end so that everything in validate 7703226633Sdim // and process gets a consistent answer about whether we're in an IT 7704226633Sdim // block. 7705226633Sdim forwardITPosition(); 7706226633Sdim 7707234353Sdim // ITasm is an ARM mode pseudo-instruction that just sets the ITblock and 7708234353Sdim // doesn't actually encode. 7709234353Sdim if (Inst.getOpcode() == ARM::ITasm) 7710234353Sdim return false; 7711234353Sdim 7712234353Sdim Inst.setLoc(IDLoc); 7713218893Sdim Out.EmitInstruction(Inst); 7714218893Sdim return false; 7715239462Sdim case Match_MissingFeature: { 7716239462Sdim assert(ErrorInfo && "Unknown missing feature!"); 7717239462Sdim // Special case the error message for the very common case where only 7718239462Sdim // a single subtarget feature is missing (Thumb vs. ARM, e.g.). 7719239462Sdim std::string Msg = "instruction requires:"; 7720239462Sdim unsigned Mask = 1; 7721239462Sdim for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) { 7722239462Sdim if (ErrorInfo & Mask) { 7723239462Sdim Msg += " "; 7724239462Sdim Msg += getSubtargetFeatureName(ErrorInfo & Mask); 7725239462Sdim } 7726239462Sdim Mask <<= 1; 7727239462Sdim } 7728239462Sdim return Error(IDLoc, Msg); 7729239462Sdim } 7730218893Sdim case Match_InvalidOperand: { 7731218893Sdim SMLoc ErrorLoc = IDLoc; 7732218893Sdim if (ErrorInfo != ~0U) { 7733218893Sdim if (ErrorInfo >= Operands.size()) 7734218893Sdim return Error(IDLoc, "too few operands for instruction"); 7735218893Sdim 7736218893Sdim ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc(); 7737218893Sdim if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc; 7738218893Sdim } 7739218893Sdim 7740218893Sdim return Error(ErrorLoc, "invalid operand for instruction"); 7741218893Sdim } 7742218893Sdim case Match_MnemonicFail: 7743234982Sdim return Error(IDLoc, "invalid instruction", 7744234982Sdim ((ARMOperand*)Operands[0])->getLocRange()); 7745226633Sdim case Match_RequiresNotITBlock: 7746226633Sdim return Error(IDLoc, "flag setting instruction only valid outside IT block"); 7747226633Sdim case Match_RequiresITBlock: 7748226633Sdim return Error(IDLoc, "instruction only valid inside IT block"); 7749226633Sdim case Match_RequiresV6: 7750226633Sdim return Error(IDLoc, "instruction variant requires ARMv6 or later"); 7751226633Sdim case Match_RequiresThumb2: 7752226633Sdim return Error(IDLoc, "instruction variant requires Thumb2"); 7753263508Sdim case Match_ImmRange0_15: { 7754251662Sdim SMLoc ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc(); 7755251662Sdim if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc; 7756263508Sdim return Error(ErrorLoc, "immediate operand must be in the range [0,15]"); 7757251662Sdim } 7758263508Sdim case Match_ImmRange0_239: { 7759239462Sdim SMLoc ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc(); 7760239462Sdim if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc; 7761263508Sdim return Error(ErrorLoc, "immediate operand must be in the range [0,239]"); 7762218893Sdim } 7763239462Sdim } 7764218893Sdim 7765218893Sdim llvm_unreachable("Implement any new match types added!"); 7766218893Sdim} 7767218893Sdim 7768226633Sdim/// parseDirective parses the arm specific directives 7769198090Srdivackybool ARMAsmParser::ParseDirective(AsmToken DirectiveID) { 7770198090Srdivacky StringRef IDVal = DirectiveID.getIdentifier(); 7771198090Srdivacky if (IDVal == ".word") 7772226633Sdim return parseDirectiveWord(4, DirectiveID.getLoc()); 7773198396Srdivacky else if (IDVal == ".thumb") 7774226633Sdim return parseDirectiveThumb(DirectiveID.getLoc()); 7775234353Sdim else if (IDVal == ".arm") 7776234353Sdim return parseDirectiveARM(DirectiveID.getLoc()); 7777198396Srdivacky else if (IDVal == ".thumb_func") 7778226633Sdim return parseDirectiveThumbFunc(DirectiveID.getLoc()); 7779198396Srdivacky else if (IDVal == ".code") 7780226633Sdim return parseDirectiveCode(DirectiveID.getLoc()); 7781198396Srdivacky else if (IDVal == ".syntax") 7782226633Sdim return parseDirectiveSyntax(DirectiveID.getLoc()); 7783234353Sdim else if (IDVal == ".unreq") 7784234353Sdim return parseDirectiveUnreq(DirectiveID.getLoc()); 7785234353Sdim else if (IDVal == ".arch") 7786234353Sdim return parseDirectiveArch(DirectiveID.getLoc()); 7787234353Sdim else if (IDVal == ".eabi_attribute") 7788234353Sdim return parseDirectiveEabiAttr(DirectiveID.getLoc()); 7789263508Sdim else if (IDVal == ".cpu") 7790263508Sdim return parseDirectiveCPU(DirectiveID.getLoc()); 7791263508Sdim else if (IDVal == ".fpu") 7792263508Sdim return parseDirectiveFPU(DirectiveID.getLoc()); 7793263508Sdim else if (IDVal == ".fnstart") 7794263508Sdim return parseDirectiveFnStart(DirectiveID.getLoc()); 7795263508Sdim else if (IDVal == ".fnend") 7796263508Sdim return parseDirectiveFnEnd(DirectiveID.getLoc()); 7797263508Sdim else if (IDVal == ".cantunwind") 7798263508Sdim return parseDirectiveCantUnwind(DirectiveID.getLoc()); 7799263508Sdim else if (IDVal == ".personality") 7800263508Sdim return parseDirectivePersonality(DirectiveID.getLoc()); 7801263508Sdim else if (IDVal == ".handlerdata") 7802263508Sdim return parseDirectiveHandlerData(DirectiveID.getLoc()); 7803263508Sdim else if (IDVal == ".setfp") 7804263508Sdim return parseDirectiveSetFP(DirectiveID.getLoc()); 7805263508Sdim else if (IDVal == ".pad") 7806263508Sdim return parseDirectivePad(DirectiveID.getLoc()); 7807263508Sdim else if (IDVal == ".save") 7808263508Sdim return parseDirectiveRegSave(DirectiveID.getLoc(), false); 7809263508Sdim else if (IDVal == ".vsave") 7810263508Sdim return parseDirectiveRegSave(DirectiveID.getLoc(), true); 7811198090Srdivacky return true; 7812198090Srdivacky} 7813198090Srdivacky 7814226633Sdim/// parseDirectiveWord 7815198090Srdivacky/// ::= .word [ expression (, expression)* ] 7816226633Sdimbool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) { 7817198090Srdivacky if (getLexer().isNot(AsmToken::EndOfStatement)) { 7818198090Srdivacky for (;;) { 7819198090Srdivacky const MCExpr *Value; 7820249423Sdim if (getParser().parseExpression(Value)) 7821198090Srdivacky return true; 7822198090Srdivacky 7823249423Sdim getParser().getStreamer().EmitValue(Value, Size); 7824198090Srdivacky 7825198090Srdivacky if (getLexer().is(AsmToken::EndOfStatement)) 7826198090Srdivacky break; 7827218893Sdim 7828198090Srdivacky // FIXME: Improve diagnostic. 7829198090Srdivacky if (getLexer().isNot(AsmToken::Comma)) 7830198090Srdivacky return Error(L, "unexpected token in directive"); 7831202878Srdivacky Parser.Lex(); 7832198090Srdivacky } 7833198090Srdivacky } 7834198090Srdivacky 7835202878Srdivacky Parser.Lex(); 7836198090Srdivacky return false; 7837198090Srdivacky} 7838198090Srdivacky 7839226633Sdim/// parseDirectiveThumb 7840198396Srdivacky/// ::= .thumb 7841226633Sdimbool ARMAsmParser::parseDirectiveThumb(SMLoc L) { 7842198396Srdivacky if (getLexer().isNot(AsmToken::EndOfStatement)) 7843198396Srdivacky return Error(L, "unexpected token in directive"); 7844202878Srdivacky Parser.Lex(); 7845198396Srdivacky 7846263508Sdim if (!hasThumb()) 7847263508Sdim return Error(L, "target does not support Thumb mode"); 7848263508Sdim 7849234353Sdim if (!isThumb()) 7850234353Sdim SwitchMode(); 7851234353Sdim getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16); 7852198396Srdivacky return false; 7853198396Srdivacky} 7854198396Srdivacky 7855234353Sdim/// parseDirectiveARM 7856234353Sdim/// ::= .arm 7857234353Sdimbool ARMAsmParser::parseDirectiveARM(SMLoc L) { 7858234353Sdim if (getLexer().isNot(AsmToken::EndOfStatement)) 7859234353Sdim return Error(L, "unexpected token in directive"); 7860234353Sdim Parser.Lex(); 7861234353Sdim 7862263508Sdim if (!hasARM()) 7863263508Sdim return Error(L, "target does not support ARM mode"); 7864263508Sdim 7865234353Sdim if (isThumb()) 7866234353Sdim SwitchMode(); 7867234353Sdim getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32); 7868234353Sdim return false; 7869234353Sdim} 7870234353Sdim 7871263508Sdimvoid ARMAsmParser::onLabelParsed(MCSymbol *Symbol) { 7872263508Sdim if (NextSymbolIsThumb) { 7873263508Sdim getParser().getStreamer().EmitThumbFunc(Symbol); 7874263508Sdim NextSymbolIsThumb = false; 7875263508Sdim } 7876263508Sdim} 7877263508Sdim 7878226633Sdim/// parseDirectiveThumbFunc 7879198396Srdivacky/// ::= .thumbfunc symbol_name 7880226633Sdimbool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) { 7881263508Sdim const MCAsmInfo *MAI = getParser().getStreamer().getContext().getAsmInfo(); 7882263508Sdim bool isMachO = MAI->hasSubsectionsViaSymbols(); 7883223017Sdim 7884234353Sdim // Darwin asm has (optionally) function name after .thumb_func direction 7885223017Sdim // ELF doesn't 7886223017Sdim if (isMachO) { 7887223017Sdim const AsmToken &Tok = Parser.getTok(); 7888234353Sdim if (Tok.isNot(AsmToken::EndOfStatement)) { 7889234353Sdim if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String)) 7890234353Sdim return Error(L, "unexpected token in .thumb_func directive"); 7891263508Sdim MCSymbol *Func = 7892263508Sdim getParser().getContext().GetOrCreateSymbol(Tok.getIdentifier()); 7893263508Sdim getParser().getStreamer().EmitThumbFunc(Func); 7894234353Sdim Parser.Lex(); // Consume the identifier token. 7895263508Sdim return false; 7896234353Sdim } 7897223017Sdim } 7898223017Sdim 7899198396Srdivacky if (getLexer().isNot(AsmToken::EndOfStatement)) 7900198396Srdivacky return Error(L, "unexpected token in directive"); 7901198396Srdivacky 7902263508Sdim NextSymbolIsThumb = true; 7903234353Sdim 7904198396Srdivacky return false; 7905198396Srdivacky} 7906198396Srdivacky 7907226633Sdim/// parseDirectiveSyntax 7908198396Srdivacky/// ::= .syntax unified | divided 7909226633Sdimbool ARMAsmParser::parseDirectiveSyntax(SMLoc L) { 7910202878Srdivacky const AsmToken &Tok = Parser.getTok(); 7911198396Srdivacky if (Tok.isNot(AsmToken::Identifier)) 7912198396Srdivacky return Error(L, "unexpected token in .syntax directive"); 7913210299Sed StringRef Mode = Tok.getString(); 7914210299Sed if (Mode == "unified" || Mode == "UNIFIED") 7915202878Srdivacky Parser.Lex(); 7916210299Sed else if (Mode == "divided" || Mode == "DIVIDED") 7917218893Sdim return Error(L, "'.syntax divided' arm asssembly not supported"); 7918198396Srdivacky else 7919198396Srdivacky return Error(L, "unrecognized syntax mode in .syntax directive"); 7920198396Srdivacky 7921198396Srdivacky if (getLexer().isNot(AsmToken::EndOfStatement)) 7922202878Srdivacky return Error(Parser.getTok().getLoc(), "unexpected token in directive"); 7923202878Srdivacky Parser.Lex(); 7924198396Srdivacky 7925198396Srdivacky // TODO tell the MC streamer the mode 7926198396Srdivacky // getParser().getStreamer().Emit???(); 7927198396Srdivacky return false; 7928198396Srdivacky} 7929198396Srdivacky 7930226633Sdim/// parseDirectiveCode 7931198396Srdivacky/// ::= .code 16 | 32 7932226633Sdimbool ARMAsmParser::parseDirectiveCode(SMLoc L) { 7933202878Srdivacky const AsmToken &Tok = Parser.getTok(); 7934198396Srdivacky if (Tok.isNot(AsmToken::Integer)) 7935198396Srdivacky return Error(L, "unexpected token in .code directive"); 7936202878Srdivacky int64_t Val = Parser.getTok().getIntVal(); 7937210299Sed if (Val == 16) 7938202878Srdivacky Parser.Lex(); 7939210299Sed else if (Val == 32) 7940202878Srdivacky Parser.Lex(); 7941198396Srdivacky else 7942198396Srdivacky return Error(L, "invalid operand to .code directive"); 7943198396Srdivacky 7944198396Srdivacky if (getLexer().isNot(AsmToken::EndOfStatement)) 7945202878Srdivacky return Error(Parser.getTok().getLoc(), "unexpected token in directive"); 7946202878Srdivacky Parser.Lex(); 7947198396Srdivacky 7948224145Sdim if (Val == 16) { 7949263508Sdim if (!hasThumb()) 7950263508Sdim return Error(L, "target does not support Thumb mode"); 7951263508Sdim 7952224145Sdim if (!isThumb()) 7953224145Sdim SwitchMode(); 7954218893Sdim getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16); 7955224145Sdim } else { 7956263508Sdim if (!hasARM()) 7957263508Sdim return Error(L, "target does not support ARM mode"); 7958263508Sdim 7959224145Sdim if (isThumb()) 7960224145Sdim SwitchMode(); 7961224145Sdim getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32); 7962218893Sdim } 7963218893Sdim 7964198396Srdivacky return false; 7965198396Srdivacky} 7966198396Srdivacky 7967234353Sdim/// parseDirectiveReq 7968234353Sdim/// ::= name .req registername 7969234353Sdimbool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) { 7970234353Sdim Parser.Lex(); // Eat the '.req' token. 7971234353Sdim unsigned Reg; 7972234353Sdim SMLoc SRegLoc, ERegLoc; 7973234353Sdim if (ParseRegister(Reg, SRegLoc, ERegLoc)) { 7974249423Sdim Parser.eatToEndOfStatement(); 7975234353Sdim return Error(SRegLoc, "register name expected"); 7976234353Sdim } 7977234353Sdim 7978234353Sdim // Shouldn't be anything else. 7979234353Sdim if (Parser.getTok().isNot(AsmToken::EndOfStatement)) { 7980249423Sdim Parser.eatToEndOfStatement(); 7981234353Sdim return Error(Parser.getTok().getLoc(), 7982234353Sdim "unexpected input in .req directive."); 7983234353Sdim } 7984234353Sdim 7985234353Sdim Parser.Lex(); // Consume the EndOfStatement 7986234353Sdim 7987234353Sdim if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg) 7988234353Sdim return Error(SRegLoc, "redefinition of '" + Name + 7989234353Sdim "' does not match original."); 7990234353Sdim 7991234353Sdim return false; 7992234353Sdim} 7993234353Sdim 7994234353Sdim/// parseDirectiveUneq 7995234353Sdim/// ::= .unreq registername 7996234353Sdimbool ARMAsmParser::parseDirectiveUnreq(SMLoc L) { 7997234353Sdim if (Parser.getTok().isNot(AsmToken::Identifier)) { 7998249423Sdim Parser.eatToEndOfStatement(); 7999234353Sdim return Error(L, "unexpected input in .unreq directive."); 8000234353Sdim } 8001234353Sdim RegisterReqs.erase(Parser.getTok().getIdentifier()); 8002234353Sdim Parser.Lex(); // Eat the identifier. 8003234353Sdim return false; 8004234353Sdim} 8005234353Sdim 8006234353Sdim/// parseDirectiveArch 8007234353Sdim/// ::= .arch token 8008234353Sdimbool ARMAsmParser::parseDirectiveArch(SMLoc L) { 8009234353Sdim return true; 8010234353Sdim} 8011234353Sdim 8012234353Sdim/// parseDirectiveEabiAttr 8013234353Sdim/// ::= .eabi_attribute int, int 8014234353Sdimbool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) { 8015263508Sdim if (Parser.getTok().isNot(AsmToken::Integer)) 8016263508Sdim return Error(L, "integer expected"); 8017263508Sdim int64_t Tag = Parser.getTok().getIntVal(); 8018263508Sdim Parser.Lex(); // eat tag integer 8019263508Sdim 8020263508Sdim if (Parser.getTok().isNot(AsmToken::Comma)) 8021263508Sdim return Error(L, "comma expected"); 8022263508Sdim Parser.Lex(); // skip comma 8023263508Sdim 8024263508Sdim L = Parser.getTok().getLoc(); 8025263508Sdim if (Parser.getTok().isNot(AsmToken::Integer)) 8026263508Sdim return Error(L, "integer expected"); 8027263508Sdim int64_t Value = Parser.getTok().getIntVal(); 8028263508Sdim Parser.Lex(); // eat value integer 8029263508Sdim 8030263508Sdim getTargetStreamer().emitAttribute(Tag, Value); 8031263508Sdim return false; 8032234353Sdim} 8033234353Sdim 8034263508Sdim/// parseDirectiveCPU 8035263508Sdim/// ::= .cpu str 8036263508Sdimbool ARMAsmParser::parseDirectiveCPU(SMLoc L) { 8037263508Sdim StringRef CPU = getParser().parseStringToEndOfStatement().trim(); 8038263508Sdim getTargetStreamer().emitTextAttribute(ARMBuildAttrs::CPU_name, CPU); 8039263508Sdim return false; 8040263508Sdim} 8041263508Sdim 8042263508Sdim/// parseDirectiveFPU 8043263508Sdim/// ::= .fpu str 8044263508Sdimbool ARMAsmParser::parseDirectiveFPU(SMLoc L) { 8045263508Sdim StringRef FPU = getParser().parseStringToEndOfStatement().trim(); 8046263508Sdim 8047263508Sdim unsigned ID = StringSwitch<unsigned>(FPU) 8048263508Sdim#define ARM_FPU_NAME(NAME, ID) .Case(NAME, ARM::ID) 8049263508Sdim#include "ARMFPUName.def" 8050263508Sdim .Default(ARM::INVALID_FPU); 8051263508Sdim 8052263508Sdim if (ID == ARM::INVALID_FPU) 8053263508Sdim return Error(L, "Unknown FPU name"); 8054263508Sdim 8055263508Sdim getTargetStreamer().emitFPU(ID); 8056263508Sdim return false; 8057263508Sdim} 8058263508Sdim 8059263508Sdim/// parseDirectiveFnStart 8060263508Sdim/// ::= .fnstart 8061263508Sdimbool ARMAsmParser::parseDirectiveFnStart(SMLoc L) { 8062263508Sdim if (FnStartLoc.isValid()) { 8063263508Sdim Error(L, ".fnstart starts before the end of previous one"); 8064263508Sdim Error(FnStartLoc, "previous .fnstart starts here"); 8065263508Sdim return true; 8066263508Sdim } 8067263508Sdim 8068263508Sdim FnStartLoc = L; 8069263508Sdim getTargetStreamer().emitFnStart(); 8070263508Sdim return false; 8071263508Sdim} 8072263508Sdim 8073263508Sdim/// parseDirectiveFnEnd 8074263508Sdim/// ::= .fnend 8075263508Sdimbool ARMAsmParser::parseDirectiveFnEnd(SMLoc L) { 8076263508Sdim // Check the ordering of unwind directives 8077263508Sdim if (!FnStartLoc.isValid()) 8078263508Sdim return Error(L, ".fnstart must precede .fnend directive"); 8079263508Sdim 8080263508Sdim // Reset the unwind directives parser state 8081263508Sdim resetUnwindDirectiveParserState(); 8082263508Sdim getTargetStreamer().emitFnEnd(); 8083263508Sdim return false; 8084263508Sdim} 8085263508Sdim 8086263508Sdim/// parseDirectiveCantUnwind 8087263508Sdim/// ::= .cantunwind 8088263508Sdimbool ARMAsmParser::parseDirectiveCantUnwind(SMLoc L) { 8089263508Sdim // Check the ordering of unwind directives 8090263508Sdim CantUnwindLoc = L; 8091263508Sdim if (!FnStartLoc.isValid()) 8092263508Sdim return Error(L, ".fnstart must precede .cantunwind directive"); 8093263508Sdim if (HandlerDataLoc.isValid()) { 8094263508Sdim Error(L, ".cantunwind can't be used with .handlerdata directive"); 8095263508Sdim Error(HandlerDataLoc, ".handlerdata was specified here"); 8096263508Sdim return true; 8097263508Sdim } 8098263508Sdim if (PersonalityLoc.isValid()) { 8099263508Sdim Error(L, ".cantunwind can't be used with .personality directive"); 8100263508Sdim Error(PersonalityLoc, ".personality was specified here"); 8101263508Sdim return true; 8102263508Sdim } 8103263508Sdim 8104263508Sdim getTargetStreamer().emitCantUnwind(); 8105263508Sdim return false; 8106263508Sdim} 8107263508Sdim 8108263508Sdim/// parseDirectivePersonality 8109263508Sdim/// ::= .personality name 8110263508Sdimbool ARMAsmParser::parseDirectivePersonality(SMLoc L) { 8111263508Sdim // Check the ordering of unwind directives 8112263508Sdim PersonalityLoc = L; 8113263508Sdim if (!FnStartLoc.isValid()) 8114263508Sdim return Error(L, ".fnstart must precede .personality directive"); 8115263508Sdim if (CantUnwindLoc.isValid()) { 8116263508Sdim Error(L, ".personality can't be used with .cantunwind directive"); 8117263508Sdim Error(CantUnwindLoc, ".cantunwind was specified here"); 8118263508Sdim return true; 8119263508Sdim } 8120263508Sdim if (HandlerDataLoc.isValid()) { 8121263508Sdim Error(L, ".personality must precede .handlerdata directive"); 8122263508Sdim Error(HandlerDataLoc, ".handlerdata was specified here"); 8123263508Sdim return true; 8124263508Sdim } 8125263508Sdim 8126263508Sdim // Parse the name of the personality routine 8127263508Sdim if (Parser.getTok().isNot(AsmToken::Identifier)) { 8128263508Sdim Parser.eatToEndOfStatement(); 8129263508Sdim return Error(L, "unexpected input in .personality directive."); 8130263508Sdim } 8131263508Sdim StringRef Name(Parser.getTok().getIdentifier()); 8132263508Sdim Parser.Lex(); 8133263508Sdim 8134263508Sdim MCSymbol *PR = getParser().getContext().GetOrCreateSymbol(Name); 8135263508Sdim getTargetStreamer().emitPersonality(PR); 8136263508Sdim return false; 8137263508Sdim} 8138263508Sdim 8139263508Sdim/// parseDirectiveHandlerData 8140263508Sdim/// ::= .handlerdata 8141263508Sdimbool ARMAsmParser::parseDirectiveHandlerData(SMLoc L) { 8142263508Sdim // Check the ordering of unwind directives 8143263508Sdim HandlerDataLoc = L; 8144263508Sdim if (!FnStartLoc.isValid()) 8145263508Sdim return Error(L, ".fnstart must precede .personality directive"); 8146263508Sdim if (CantUnwindLoc.isValid()) { 8147263508Sdim Error(L, ".handlerdata can't be used with .cantunwind directive"); 8148263508Sdim Error(CantUnwindLoc, ".cantunwind was specified here"); 8149263508Sdim return true; 8150263508Sdim } 8151263508Sdim 8152263508Sdim getTargetStreamer().emitHandlerData(); 8153263508Sdim return false; 8154263508Sdim} 8155263508Sdim 8156263508Sdim/// parseDirectiveSetFP 8157263508Sdim/// ::= .setfp fpreg, spreg [, offset] 8158263508Sdimbool ARMAsmParser::parseDirectiveSetFP(SMLoc L) { 8159263508Sdim // Check the ordering of unwind directives 8160263508Sdim if (!FnStartLoc.isValid()) 8161263508Sdim return Error(L, ".fnstart must precede .setfp directive"); 8162263508Sdim if (HandlerDataLoc.isValid()) 8163263508Sdim return Error(L, ".setfp must precede .handlerdata directive"); 8164263508Sdim 8165263508Sdim // Parse fpreg 8166263508Sdim SMLoc NewFPRegLoc = Parser.getTok().getLoc(); 8167263508Sdim int NewFPReg = tryParseRegister(); 8168263508Sdim if (NewFPReg == -1) 8169263508Sdim return Error(NewFPRegLoc, "frame pointer register expected"); 8170263508Sdim 8171263508Sdim // Consume comma 8172263508Sdim if (!Parser.getTok().is(AsmToken::Comma)) 8173263508Sdim return Error(Parser.getTok().getLoc(), "comma expected"); 8174263508Sdim Parser.Lex(); // skip comma 8175263508Sdim 8176263508Sdim // Parse spreg 8177263508Sdim SMLoc NewSPRegLoc = Parser.getTok().getLoc(); 8178263508Sdim int NewSPReg = tryParseRegister(); 8179263508Sdim if (NewSPReg == -1) 8180263508Sdim return Error(NewSPRegLoc, "stack pointer register expected"); 8181263508Sdim 8182263508Sdim if (NewSPReg != ARM::SP && NewSPReg != FPReg) 8183263508Sdim return Error(NewSPRegLoc, 8184263508Sdim "register should be either $sp or the latest fp register"); 8185263508Sdim 8186263508Sdim // Update the frame pointer register 8187263508Sdim FPReg = NewFPReg; 8188263508Sdim 8189263508Sdim // Parse offset 8190263508Sdim int64_t Offset = 0; 8191263508Sdim if (Parser.getTok().is(AsmToken::Comma)) { 8192263508Sdim Parser.Lex(); // skip comma 8193263508Sdim 8194263508Sdim if (Parser.getTok().isNot(AsmToken::Hash) && 8195263508Sdim Parser.getTok().isNot(AsmToken::Dollar)) { 8196263508Sdim return Error(Parser.getTok().getLoc(), "'#' expected"); 8197263508Sdim } 8198263508Sdim Parser.Lex(); // skip hash token. 8199263508Sdim 8200263508Sdim const MCExpr *OffsetExpr; 8201263508Sdim SMLoc ExLoc = Parser.getTok().getLoc(); 8202263508Sdim SMLoc EndLoc; 8203263508Sdim if (getParser().parseExpression(OffsetExpr, EndLoc)) 8204263508Sdim return Error(ExLoc, "malformed setfp offset"); 8205263508Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(OffsetExpr); 8206263508Sdim if (!CE) 8207263508Sdim return Error(ExLoc, "setfp offset must be an immediate"); 8208263508Sdim 8209263508Sdim Offset = CE->getValue(); 8210263508Sdim } 8211263508Sdim 8212263508Sdim getTargetStreamer().emitSetFP(static_cast<unsigned>(NewFPReg), 8213263508Sdim static_cast<unsigned>(NewSPReg), Offset); 8214263508Sdim return false; 8215263508Sdim} 8216263508Sdim 8217263508Sdim/// parseDirective 8218263508Sdim/// ::= .pad offset 8219263508Sdimbool ARMAsmParser::parseDirectivePad(SMLoc L) { 8220263508Sdim // Check the ordering of unwind directives 8221263508Sdim if (!FnStartLoc.isValid()) 8222263508Sdim return Error(L, ".fnstart must precede .pad directive"); 8223263508Sdim if (HandlerDataLoc.isValid()) 8224263508Sdim return Error(L, ".pad must precede .handlerdata directive"); 8225263508Sdim 8226263508Sdim // Parse the offset 8227263508Sdim if (Parser.getTok().isNot(AsmToken::Hash) && 8228263508Sdim Parser.getTok().isNot(AsmToken::Dollar)) { 8229263508Sdim return Error(Parser.getTok().getLoc(), "'#' expected"); 8230263508Sdim } 8231263508Sdim Parser.Lex(); // skip hash token. 8232263508Sdim 8233263508Sdim const MCExpr *OffsetExpr; 8234263508Sdim SMLoc ExLoc = Parser.getTok().getLoc(); 8235263508Sdim SMLoc EndLoc; 8236263508Sdim if (getParser().parseExpression(OffsetExpr, EndLoc)) 8237263508Sdim return Error(ExLoc, "malformed pad offset"); 8238263508Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(OffsetExpr); 8239263508Sdim if (!CE) 8240263508Sdim return Error(ExLoc, "pad offset must be an immediate"); 8241263508Sdim 8242263508Sdim getTargetStreamer().emitPad(CE->getValue()); 8243263508Sdim return false; 8244263508Sdim} 8245263508Sdim 8246263508Sdim/// parseDirectiveRegSave 8247263508Sdim/// ::= .save { registers } 8248263508Sdim/// ::= .vsave { registers } 8249263508Sdimbool ARMAsmParser::parseDirectiveRegSave(SMLoc L, bool IsVector) { 8250263508Sdim // Check the ordering of unwind directives 8251263508Sdim if (!FnStartLoc.isValid()) 8252263508Sdim return Error(L, ".fnstart must precede .save or .vsave directives"); 8253263508Sdim if (HandlerDataLoc.isValid()) 8254263508Sdim return Error(L, ".save or .vsave must precede .handlerdata directive"); 8255263508Sdim 8256263508Sdim // RAII object to make sure parsed operands are deleted. 8257263508Sdim struct CleanupObject { 8258263508Sdim SmallVector<MCParsedAsmOperand *, 1> Operands; 8259263508Sdim ~CleanupObject() { 8260263508Sdim for (unsigned I = 0, E = Operands.size(); I != E; ++I) 8261263508Sdim delete Operands[I]; 8262263508Sdim } 8263263508Sdim } CO; 8264263508Sdim 8265263508Sdim // Parse the register list 8266263508Sdim if (parseRegisterList(CO.Operands)) 8267263508Sdim return true; 8268263508Sdim ARMOperand *Op = (ARMOperand*)CO.Operands[0]; 8269263508Sdim if (!IsVector && !Op->isRegList()) 8270263508Sdim return Error(L, ".save expects GPR registers"); 8271263508Sdim if (IsVector && !Op->isDPRRegList()) 8272263508Sdim return Error(L, ".vsave expects DPR registers"); 8273263508Sdim 8274263508Sdim getTargetStreamer().emitRegSave(Op->getRegList(), IsVector); 8275263508Sdim return false; 8276263508Sdim} 8277263508Sdim 8278198892Srdivacky/// Force static initialization. 8279198090Srdivackyextern "C" void LLVMInitializeARMAsmParser() { 8280226633Sdim RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget); 8281226633Sdim RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget); 8282198090Srdivacky} 8283212904Sdim 8284218893Sdim#define GET_REGISTER_MATCHER 8285239462Sdim#define GET_SUBTARGET_FEATURE_NAME 8286218893Sdim#define GET_MATCHER_IMPLEMENTATION 8287212904Sdim#include "ARMGenAsmMatcher.inc" 8288249423Sdim 8289249423Sdim// Define this matcher function after the auto-generated include so we 8290249423Sdim// have the match class enum definitions. 8291249423Sdimunsigned ARMAsmParser::validateTargetOperandClass(MCParsedAsmOperand *AsmOp, 8292249423Sdim unsigned Kind) { 8293249423Sdim ARMOperand *Op = static_cast<ARMOperand*>(AsmOp); 8294249423Sdim // If the kind is a token for a literal immediate, check if our asm 8295249423Sdim // operand matches. This is for InstAliases which have a fixed-value 8296249423Sdim // immediate in the syntax. 8297249423Sdim if (Kind == MCK__35_0 && Op->isImm()) { 8298249423Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm()); 8299249423Sdim if (!CE) 8300249423Sdim return Match_InvalidOperand; 8301249423Sdim if (CE->getValue() == 0) 8302249423Sdim return Match_Success; 8303249423Sdim } 8304249423Sdim return Match_InvalidOperand; 8305249423Sdim} 8306