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 10263509Sdim#include "ARMBuildAttrs.h" 11263509Sdim#include "ARMFPUName.h" 12263509Sdim#include "ARMFeatures.h" 13252723Sdim#include "llvm/MC/MCTargetAsmParser.h" 14252723Sdim#include "MCTargetDesc/ARMAddressingModes.h" 15226890Sdim#include "MCTargetDesc/ARMBaseInfo.h" 16226890Sdim#include "MCTargetDesc/ARMMCExpr.h" 17252723Sdim#include "llvm/ADT/BitVector.h" 18252723Sdim#include "llvm/ADT/OwningPtr.h" 19252723Sdim#include "llvm/ADT/STLExtras.h" 20252723Sdim#include "llvm/ADT/SmallVector.h" 21252723Sdim#include "llvm/ADT/StringSwitch.h" 22252723Sdim#include "llvm/ADT/Twine.h" 23223017Sdim#include "llvm/MC/MCAsmInfo.h" 24252723Sdim#include "llvm/MC/MCAssembler.h" 25218893Sdim#include "llvm/MC/MCContext.h" 26252723Sdim#include "llvm/MC/MCELFStreamer.h" 27198090Srdivacky#include "llvm/MC/MCExpr.h" 28198090Srdivacky#include "llvm/MC/MCInst.h" 29226890Sdim#include "llvm/MC/MCInstrDesc.h" 30263509Sdim#include "llvm/MC/MCInstrInfo.h" 31252723Sdim#include "llvm/MC/MCParser/MCAsmLexer.h" 32252723Sdim#include "llvm/MC/MCParser/MCAsmParser.h" 33252723Sdim#include "llvm/MC/MCParser/MCParsedAsmOperand.h" 34226890Sdim#include "llvm/MC/MCRegisterInfo.h" 35252723Sdim#include "llvm/MC/MCStreamer.h" 36224145Sdim#include "llvm/MC/MCSubtargetInfo.h" 37252723Sdim#include "llvm/Support/ELF.h" 38226890Sdim#include "llvm/Support/MathExtras.h" 39198090Srdivacky#include "llvm/Support/SourceMgr.h" 40226890Sdim#include "llvm/Support/TargetRegistry.h" 41212904Sdim#include "llvm/Support/raw_ostream.h" 42224145Sdim 43198090Srdivackyusing namespace llvm; 44198090Srdivacky 45218893Sdimnamespace { 46218893Sdim 47218893Sdimclass ARMOperand; 48218893Sdim 49235633Sdimenum VectorLaneTy { NoLanes, AllLanes, IndexedLane }; 50235633Sdim 51226890Sdimclass ARMAsmParser : public MCTargetAsmParser { 52224145Sdim MCSubtargetInfo &STI; 53198090Srdivacky MCAsmParser &Parser; 54263509Sdim const MCInstrInfo &MII; 55235633Sdim const MCRegisterInfo *MRI; 56198090Srdivacky 57263509Sdim ARMTargetStreamer &getTargetStreamer() { 58263509Sdim MCTargetStreamer &TS = getParser().getStreamer().getTargetStreamer(); 59263509Sdim return static_cast<ARMTargetStreamer &>(TS); 60263509Sdim } 61263509Sdim 62263509Sdim // Unwind directives state 63263509Sdim SMLoc FnStartLoc; 64263509Sdim SMLoc CantUnwindLoc; 65263509Sdim SMLoc PersonalityLoc; 66263509Sdim SMLoc HandlerDataLoc; 67263509Sdim int FPReg; 68263509Sdim void resetUnwindDirectiveParserState() { 69263509Sdim FnStartLoc = SMLoc(); 70263509Sdim CantUnwindLoc = SMLoc(); 71263509Sdim PersonalityLoc = SMLoc(); 72263509Sdim HandlerDataLoc = SMLoc(); 73263509Sdim FPReg = -1; 74263509Sdim } 75263509Sdim 76235633Sdim // Map of register aliases registers via the .req directive. 77235633Sdim StringMap<unsigned> RegisterReqs; 78235633Sdim 79263509Sdim bool NextSymbolIsThumb; 80263509Sdim 81226890Sdim struct { 82226890Sdim ARMCC::CondCodes Cond; // Condition for IT block. 83226890Sdim unsigned Mask:4; // Condition mask for instructions. 84226890Sdim // Starting at first 1 (from lsb). 85226890Sdim // '1' condition as indicated in IT. 86226890Sdim // '0' inverse of condition (else). 87226890Sdim // Count of instructions in IT block is 88226890Sdim // 4 - trailingzeroes(mask) 89226890Sdim 90226890Sdim bool FirstCond; // Explicit flag for when we're parsing the 91226890Sdim // First instruction in the IT block. It's 92226890Sdim // implied in the mask, so needs special 93226890Sdim // handling. 94226890Sdim 95226890Sdim unsigned CurPosition; // Current position in parsing of IT 96226890Sdim // block. In range [0,3]. Initialized 97226890Sdim // according to count of instructions in block. 98226890Sdim // ~0U if no active IT block. 99226890Sdim } ITState; 100226890Sdim bool inITBlock() { return ITState.CurPosition != ~0U;} 101226890Sdim void forwardITPosition() { 102226890Sdim if (!inITBlock()) return; 103226890Sdim // Move to the next instruction in the IT block, if there is one. If not, 104226890Sdim // mark the block as done. 105263509Sdim unsigned TZ = countTrailingZeros(ITState.Mask); 106226890Sdim if (++ITState.CurPosition == 5 - TZ) 107226890Sdim ITState.CurPosition = ~0U; // Done with the IT block after this. 108226890Sdim } 109226890Sdim 110226890Sdim 111198090Srdivacky MCAsmParser &getParser() const { return Parser; } 112198090Srdivacky MCAsmLexer &getLexer() const { return Parser.getLexer(); } 113198090Srdivacky 114235633Sdim bool Warning(SMLoc L, const Twine &Msg, 115252723Sdim ArrayRef<SMRange> Ranges = None) { 116235633Sdim return Parser.Warning(L, Msg, Ranges); 117235633Sdim } 118235633Sdim bool Error(SMLoc L, const Twine &Msg, 119252723Sdim ArrayRef<SMRange> Ranges = None) { 120235633Sdim return Parser.Error(L, Msg, Ranges); 121235633Sdim } 122198090Srdivacky 123226890Sdim int tryParseRegister(); 124226890Sdim bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &); 125226890Sdim int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &); 126226890Sdim bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &); 127226890Sdim bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &); 128226890Sdim bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic); 129226890Sdim bool parsePrefix(ARMMCExpr::VariantKind &RefKind); 130226890Sdim bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType, 131226890Sdim unsigned &ShiftAmount); 132226890Sdim bool parseDirectiveWord(unsigned Size, SMLoc L); 133226890Sdim bool parseDirectiveThumb(SMLoc L); 134235633Sdim bool parseDirectiveARM(SMLoc L); 135226890Sdim bool parseDirectiveThumbFunc(SMLoc L); 136226890Sdim bool parseDirectiveCode(SMLoc L); 137226890Sdim bool parseDirectiveSyntax(SMLoc L); 138235633Sdim bool parseDirectiveReq(StringRef Name, SMLoc L); 139235633Sdim bool parseDirectiveUnreq(SMLoc L); 140235633Sdim bool parseDirectiveArch(SMLoc L); 141235633Sdim bool parseDirectiveEabiAttr(SMLoc L); 142263509Sdim bool parseDirectiveCPU(SMLoc L); 143263509Sdim bool parseDirectiveFPU(SMLoc L); 144263509Sdim bool parseDirectiveFnStart(SMLoc L); 145263509Sdim bool parseDirectiveFnEnd(SMLoc L); 146263509Sdim bool parseDirectiveCantUnwind(SMLoc L); 147263509Sdim bool parseDirectivePersonality(SMLoc L); 148263509Sdim bool parseDirectiveHandlerData(SMLoc L); 149263509Sdim bool parseDirectiveSetFP(SMLoc L); 150263509Sdim bool parseDirectivePad(SMLoc L); 151263509Sdim bool parseDirectiveRegSave(SMLoc L, bool IsVector); 152198090Srdivacky 153226890Sdim StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode, 154226890Sdim bool &CarrySetting, unsigned &ProcessorIMod, 155226890Sdim StringRef &ITMask); 156263509Sdim void getMnemonicAcceptInfo(StringRef Mnemonic, StringRef FullInst, 157263509Sdim 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 } 167226890Sdim bool isThumbTwo() const { 168226890Sdim return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2); 169226890Sdim } 170263509Sdim bool hasThumb() const { 171263509Sdim return STI.getFeatureBits() & ARM::HasV4TOps; 172263509Sdim } 173226890Sdim bool hasV6Ops() const { 174226890Sdim return STI.getFeatureBits() & ARM::HasV6Ops; 175226890Sdim } 176263509Sdim bool hasV6MOps() const { 177263509Sdim return STI.getFeatureBits() & ARM::HasV6MOps; 178263509Sdim } 179226890Sdim bool hasV7Ops() const { 180226890Sdim return STI.getFeatureBits() & ARM::HasV7Ops; 181226890Sdim } 182263509Sdim bool hasV8Ops() const { 183263509Sdim return STI.getFeatureBits() & ARM::HasV8Ops; 184263509Sdim } 185263509Sdim bool hasARM() const { 186263509Sdim return !(STI.getFeatureBits() & ARM::FeatureNoARM); 187263509Sdim } 188263509Sdim 189224145Sdim void SwitchMode() { 190224145Sdim unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb)); 191224145Sdim setAvailableFeatures(FB); 192224145Sdim } 193226890Sdim bool isMClass() const { 194226890Sdim return STI.getFeatureBits() & ARM::FeatureMClass; 195226890Sdim } 196224145Sdim 197198090Srdivacky /// @name Auto-generated Match Functions 198198090Srdivacky /// { 199198090Srdivacky 200218893Sdim#define GET_ASSEMBLER_HEADER 201218893Sdim#include "ARMGenAsmMatcher.inc" 202198090Srdivacky 203198090Srdivacky /// } 204198090Srdivacky 205226890Sdim OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&); 206226890Sdim OperandMatchResultTy parseCoprocNumOperand( 207218893Sdim SmallVectorImpl<MCParsedAsmOperand*>&); 208226890Sdim OperandMatchResultTy parseCoprocRegOperand( 209218893Sdim SmallVectorImpl<MCParsedAsmOperand*>&); 210226890Sdim OperandMatchResultTy parseCoprocOptionOperand( 211218893Sdim SmallVectorImpl<MCParsedAsmOperand*>&); 212226890Sdim OperandMatchResultTy parseMemBarrierOptOperand( 213218893Sdim SmallVectorImpl<MCParsedAsmOperand*>&); 214263509Sdim OperandMatchResultTy parseInstSyncBarrierOptOperand( 215263509Sdim SmallVectorImpl<MCParsedAsmOperand*>&); 216226890Sdim OperandMatchResultTy parseProcIFlagsOperand( 217218893Sdim SmallVectorImpl<MCParsedAsmOperand*>&); 218226890Sdim OperandMatchResultTy parseMSRMaskOperand( 219221345Sdim SmallVectorImpl<MCParsedAsmOperand*>&); 220226890Sdim OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O, 221226890Sdim StringRef Op, int Low, int High); 222226890Sdim OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) { 223226890Sdim return parsePKHImm(O, "lsl", 0, 31); 224226890Sdim } 225226890Sdim OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) { 226226890Sdim return parsePKHImm(O, "asr", 1, 32); 227226890Sdim } 228226890Sdim OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&); 229226890Sdim OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&); 230226890Sdim OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&); 231226890Sdim OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&); 232226890Sdim OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&); 233226890Sdim OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&); 234226890Sdim OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&); 235235633Sdim OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&); 236252723Sdim OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index, 237252723Sdim SMLoc &EndLoc); 238198090Srdivacky 239221345Sdim // Asm Match Converter Methods 240245431Sdim void cvtThumbMultiply(MCInst &Inst, 241226890Sdim const SmallVectorImpl<MCParsedAsmOperand*> &); 242263509Sdim void cvtThumbBranches(MCInst &Inst, 243235633Sdim const SmallVectorImpl<MCParsedAsmOperand*> &); 244263509Sdim 245226890Sdim bool validateInstruction(MCInst &Inst, 246226890Sdim const SmallVectorImpl<MCParsedAsmOperand*> &Ops); 247235633Sdim bool processInstruction(MCInst &Inst, 248226890Sdim const SmallVectorImpl<MCParsedAsmOperand*> &Ops); 249226890Sdim bool shouldOmitCCOutOperand(StringRef Mnemonic, 250226890Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands); 251263509Sdim bool shouldOmitPredicateOperand(StringRef Mnemonic, 252263509Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands); 253198090Srdivackypublic: 254226890Sdim enum ARMMatchResultTy { 255226890Sdim Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY, 256226890Sdim Match_RequiresNotITBlock, 257226890Sdim Match_RequiresV6, 258245431Sdim Match_RequiresThumb2, 259245431Sdim#define GET_OPERAND_DIAGNOSTIC_TYPES 260245431Sdim#include "ARMGenAsmMatcher.inc" 261245431Sdim 262226890Sdim }; 263226890Sdim 264263509Sdim ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser, 265263509Sdim const MCInstrInfo &MII) 266263509Sdim : MCTargetAsmParser(), STI(_STI), Parser(_Parser), MII(MII), FPReg(-1) { 267224145Sdim MCAsmParserExtension::Initialize(_Parser); 268198090Srdivacky 269235633Sdim // Cache the MCRegisterInfo. 270263509Sdim MRI = getContext().getRegisterInfo(); 271235633Sdim 272224145Sdim // Initialize the set of available features. 273224145Sdim setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); 274226890Sdim 275226890Sdim // Not in an ITBlock to start with. 276226890Sdim ITState.CurPosition = ~0U; 277252723Sdim 278263509Sdim NextSymbolIsThumb = false; 279224145Sdim } 280224145Sdim 281226890Sdim // Implementation of the MCTargetAsmParser interface: 282226890Sdim bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); 283245431Sdim bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 284245431Sdim SMLoc NameLoc, 285226890Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands); 286226890Sdim bool ParseDirective(AsmToken DirectiveID); 287226890Sdim 288252723Sdim unsigned validateTargetOperandClass(MCParsedAsmOperand *Op, unsigned Kind); 289226890Sdim unsigned checkTargetMatchPredicate(MCInst &Inst); 290226890Sdim 291245431Sdim bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 292226890Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands, 293245431Sdim MCStreamer &Out, unsigned &ErrorInfo, 294245431Sdim bool MatchingInlineAsm); 295263509Sdim void onLabelParsed(MCSymbol *Symbol); 296263509Sdim 297198090Srdivacky}; 298218893Sdim} // end anonymous namespace 299218893Sdim 300218893Sdimnamespace { 301218893Sdim 302198090Srdivacky/// ARMOperand - Instances of this class represent a parsed ARM machine 303252723Sdim/// operand. 304218893Sdimclass ARMOperand : public MCParsedAsmOperand { 305206124Srdivacky enum KindTy { 306226890Sdim k_CondCode, 307226890Sdim k_CCOut, 308226890Sdim k_ITCondMask, 309226890Sdim k_CoprocNum, 310226890Sdim k_CoprocReg, 311226890Sdim k_CoprocOption, 312226890Sdim k_Immediate, 313226890Sdim k_MemBarrierOpt, 314263509Sdim k_InstSyncBarrierOpt, 315226890Sdim k_Memory, 316226890Sdim k_PostIndexRegister, 317226890Sdim k_MSRMask, 318226890Sdim k_ProcIFlags, 319226890Sdim k_VectorIndex, 320226890Sdim k_Register, 321226890Sdim k_RegisterList, 322226890Sdim k_DPRRegisterList, 323226890Sdim k_SPRRegisterList, 324235633Sdim k_VectorList, 325235633Sdim k_VectorListAllLanes, 326235633Sdim k_VectorListIndexed, 327226890Sdim k_ShiftedRegister, 328226890Sdim k_ShiftedImmediate, 329226890Sdim k_ShifterImmediate, 330226890Sdim k_RotateImmediate, 331226890Sdim k_BitfieldDescriptor, 332226890Sdim k_Token 333198090Srdivacky } Kind; 334198090Srdivacky 335206124Srdivacky SMLoc StartLoc, EndLoc; 336218893Sdim SmallVector<unsigned, 8> Registers; 337198090Srdivacky 338252723Sdim struct CCOp { 339252723Sdim ARMCC::CondCodes Val; 340252723Sdim }; 341212904Sdim 342252723Sdim struct CopOp { 343252723Sdim unsigned Val; 344252723Sdim }; 345218893Sdim 346252723Sdim struct CoprocOptionOp { 347252723Sdim unsigned Val; 348252723Sdim }; 349218893Sdim 350252723Sdim struct ITMaskOp { 351252723Sdim unsigned Mask:4; 352252723Sdim }; 353226890Sdim 354252723Sdim struct MBOptOp { 355252723Sdim ARM_MB::MemBOpt Val; 356252723Sdim }; 357226890Sdim 358263509Sdim struct ISBOptOp { 359263509Sdim ARM_ISB::InstSyncBOpt Val; 360263509Sdim }; 361263509Sdim 362252723Sdim struct IFlagsOp { 363252723Sdim ARM_PROC::IFlags Val; 364252723Sdim }; 365218893Sdim 366252723Sdim struct MMaskOp { 367252723Sdim unsigned Val; 368252723Sdim }; 369218893Sdim 370252723Sdim struct TokOp { 371252723Sdim const char *Data; 372252723Sdim unsigned Length; 373252723Sdim }; 374198090Srdivacky 375252723Sdim struct RegOp { 376252723Sdim unsigned RegNum; 377252723Sdim }; 378198090Srdivacky 379252723Sdim // A vector register list is a sequential list of 1 to 4 registers. 380252723Sdim struct VectorListOp { 381252723Sdim unsigned RegNum; 382252723Sdim unsigned Count; 383252723Sdim unsigned LaneIndex; 384252723Sdim bool isDoubleSpaced; 385252723Sdim }; 386235633Sdim 387252723Sdim struct VectorIndexOp { 388252723Sdim unsigned Val; 389252723Sdim }; 390226890Sdim 391252723Sdim struct ImmOp { 392252723Sdim const MCExpr *Val; 393252723Sdim }; 394218893Sdim 395252723Sdim /// Combined record for all forms of ARM address expressions. 396252723Sdim struct MemoryOp { 397252723Sdim unsigned BaseRegNum; 398252723Sdim // Offset is in OffsetReg or OffsetImm. If both are zero, no offset 399252723Sdim // was specified. 400252723Sdim const MCConstantExpr *OffsetImm; // Offset immediate value 401252723Sdim unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL 402252723Sdim ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg 403252723Sdim unsigned ShiftImm; // shift for OffsetReg. 404252723Sdim unsigned Alignment; // 0 = no alignment specified 405252723Sdim // n = alignment in bytes (2, 4, 8, 16, or 32) 406252723Sdim unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit) 407252723Sdim }; 408221345Sdim 409252723Sdim struct PostIdxRegOp { 410252723Sdim unsigned RegNum; 411252723Sdim bool isAdd; 412252723Sdim ARM_AM::ShiftOpc ShiftTy; 413252723Sdim unsigned ShiftImm; 414252723Sdim }; 415226890Sdim 416252723Sdim struct ShifterImmOp { 417252723Sdim bool isASR; 418252723Sdim unsigned Imm; 419218893Sdim }; 420198090Srdivacky 421252723Sdim struct RegShiftedRegOp { 422252723Sdim ARM_AM::ShiftOpc ShiftTy; 423252723Sdim unsigned SrcReg; 424252723Sdim unsigned ShiftReg; 425252723Sdim unsigned ShiftImm; 426252723Sdim }; 427252723Sdim 428252723Sdim struct RegShiftedImmOp { 429252723Sdim ARM_AM::ShiftOpc ShiftTy; 430252723Sdim unsigned SrcReg; 431252723Sdim unsigned ShiftImm; 432252723Sdim }; 433252723Sdim 434252723Sdim struct RotImmOp { 435252723Sdim unsigned Imm; 436252723Sdim }; 437252723Sdim 438252723Sdim struct BitfieldOp { 439252723Sdim unsigned LSB; 440252723Sdim unsigned Width; 441252723Sdim }; 442252723Sdim 443252723Sdim union { 444252723Sdim struct CCOp CC; 445252723Sdim struct CopOp Cop; 446252723Sdim struct CoprocOptionOp CoprocOption; 447252723Sdim struct MBOptOp MBOpt; 448263509Sdim struct ISBOptOp ISBOpt; 449252723Sdim struct ITMaskOp ITMask; 450252723Sdim struct IFlagsOp IFlags; 451252723Sdim struct MMaskOp MMask; 452252723Sdim struct TokOp Tok; 453252723Sdim struct RegOp Reg; 454252723Sdim struct VectorListOp VectorList; 455252723Sdim struct VectorIndexOp VectorIndex; 456252723Sdim struct ImmOp Imm; 457252723Sdim struct MemoryOp Memory; 458252723Sdim struct PostIdxRegOp PostIdxReg; 459252723Sdim struct ShifterImmOp ShifterImm; 460252723Sdim struct RegShiftedRegOp RegShiftedReg; 461252723Sdim struct RegShiftedImmOp RegShiftedImm; 462252723Sdim struct RotImmOp RotImm; 463252723Sdim struct BitfieldOp Bitfield; 464252723Sdim }; 465252723Sdim 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) { 473226890Sdim case k_CondCode: 474212904Sdim CC = o.CC; 475212904Sdim break; 476226890Sdim case k_ITCondMask: 477226890Sdim ITMask = o.ITMask; 478226890Sdim break; 479226890Sdim case k_Token: 480212904Sdim Tok = o.Tok; 481206124Srdivacky break; 482226890Sdim case k_CCOut: 483226890Sdim case k_Register: 484206124Srdivacky Reg = o.Reg; 485206124Srdivacky break; 486226890Sdim case k_RegisterList: 487226890Sdim case k_DPRRegisterList: 488226890Sdim case k_SPRRegisterList: 489218893Sdim Registers = o.Registers; 490218893Sdim break; 491235633Sdim case k_VectorList: 492235633Sdim case k_VectorListAllLanes: 493235633Sdim case k_VectorListIndexed: 494235633Sdim VectorList = o.VectorList; 495235633Sdim break; 496226890Sdim case k_CoprocNum: 497226890Sdim case k_CoprocReg: 498218893Sdim Cop = o.Cop; 499218893Sdim break; 500226890Sdim case k_CoprocOption: 501226890Sdim CoprocOption = o.CoprocOption; 502226890Sdim break; 503226890Sdim case k_Immediate: 504206124Srdivacky Imm = o.Imm; 505206124Srdivacky break; 506226890Sdim case k_MemBarrierOpt: 507218893Sdim MBOpt = o.MBOpt; 508218893Sdim break; 509263509Sdim case k_InstSyncBarrierOpt: 510263509Sdim ISBOpt = o.ISBOpt; 511226890Sdim case k_Memory: 512226890Sdim Memory = o.Memory; 513206124Srdivacky break; 514226890Sdim case k_PostIndexRegister: 515226890Sdim PostIdxReg = o.PostIdxReg; 516226890Sdim break; 517226890Sdim case k_MSRMask: 518218893Sdim MMask = o.MMask; 519218893Sdim break; 520226890Sdim case k_ProcIFlags: 521218893Sdim IFlags = o.IFlags; 522221345Sdim break; 523226890Sdim case k_ShifterImmediate: 524226890Sdim ShifterImm = o.ShifterImm; 525221345Sdim break; 526226890Sdim case k_ShiftedRegister: 527226890Sdim RegShiftedReg = o.RegShiftedReg; 528224145Sdim break; 529226890Sdim case k_ShiftedImmediate: 530226890Sdim RegShiftedImm = o.RegShiftedImm; 531226890Sdim break; 532226890Sdim case k_RotateImmediate: 533226890Sdim RotImm = o.RotImm; 534226890Sdim break; 535226890Sdim case k_BitfieldDescriptor: 536226890Sdim Bitfield = o.Bitfield; 537226890Sdim break; 538226890Sdim case k_VectorIndex: 539226890Sdim VectorIndex = o.VectorIndex; 540226890Sdim 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; } 548245431Sdim /// getLocRange - Get the range between the first and last token of this 549245431Sdim /// operand. 550235633Sdim SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); } 551235633Sdim 552212904Sdim ARMCC::CondCodes getCondCode() const { 553226890Sdim assert(Kind == k_CondCode && "Invalid access!"); 554212904Sdim return CC.Val; 555212904Sdim } 556212904Sdim 557218893Sdim unsigned getCoproc() const { 558226890Sdim assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!"); 559218893Sdim return Cop.Val; 560218893Sdim } 561218893Sdim 562198090Srdivacky StringRef getToken() const { 563226890Sdim assert(Kind == k_Token && "Invalid access!"); 564198090Srdivacky return StringRef(Tok.Data, Tok.Length); 565198090Srdivacky } 566198090Srdivacky 567198090Srdivacky unsigned getReg() const { 568226890Sdim assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!"); 569198090Srdivacky return Reg.RegNum; 570198090Srdivacky } 571198090Srdivacky 572218893Sdim const SmallVectorImpl<unsigned> &getRegList() const { 573226890Sdim assert((Kind == k_RegisterList || Kind == k_DPRRegisterList || 574226890Sdim Kind == k_SPRRegisterList) && "Invalid access!"); 575218893Sdim return Registers; 576218893Sdim } 577218893Sdim 578198090Srdivacky const MCExpr *getImm() const { 579235633Sdim assert(isImm() && "Invalid access!"); 580198090Srdivacky return Imm.Val; 581198090Srdivacky } 582198090Srdivacky 583226890Sdim unsigned getVectorIndex() const { 584226890Sdim assert(Kind == k_VectorIndex && "Invalid access!"); 585226890Sdim return VectorIndex.Val; 586226890Sdim } 587226890Sdim 588218893Sdim ARM_MB::MemBOpt getMemBarrierOpt() const { 589226890Sdim assert(Kind == k_MemBarrierOpt && "Invalid access!"); 590218893Sdim return MBOpt.Val; 591218893Sdim } 592218893Sdim 593263509Sdim ARM_ISB::InstSyncBOpt getInstSyncBarrierOpt() const { 594263509Sdim assert(Kind == k_InstSyncBarrierOpt && "Invalid access!"); 595263509Sdim return ISBOpt.Val; 596263509Sdim } 597263509Sdim 598218893Sdim ARM_PROC::IFlags getProcIFlags() const { 599226890Sdim assert(Kind == k_ProcIFlags && "Invalid access!"); 600218893Sdim return IFlags.Val; 601218893Sdim } 602218893Sdim 603218893Sdim unsigned getMSRMask() const { 604226890Sdim assert(Kind == k_MSRMask && "Invalid access!"); 605218893Sdim return MMask.Val; 606218893Sdim } 607218893Sdim 608226890Sdim bool isCoprocNum() const { return Kind == k_CoprocNum; } 609226890Sdim bool isCoprocReg() const { return Kind == k_CoprocReg; } 610226890Sdim bool isCoprocOption() const { return Kind == k_CoprocOption; } 611226890Sdim bool isCondCode() const { return Kind == k_CondCode; } 612226890Sdim bool isCCOut() const { return Kind == k_CCOut; } 613226890Sdim bool isITMask() const { return Kind == k_ITCondMask; } 614226890Sdim bool isITCondCode() const { return Kind == k_CondCode; } 615226890Sdim bool isImm() const { return Kind == k_Immediate; } 616263509Sdim // checks whether this operand is an unsigned offset which fits is a field 617263509Sdim // of specified width and scaled by a specific number of bits 618263509Sdim template<unsigned width, unsigned scale> 619263509Sdim bool isUnsignedOffset() const { 620263509Sdim if (!isImm()) return false; 621263509Sdim if (isa<MCSymbolRefExpr>(Imm.Val)) return true; 622263509Sdim if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) { 623263509Sdim int64_t Val = CE->getValue(); 624263509Sdim int64_t Align = 1LL << scale; 625263509Sdim int64_t Max = Align * ((1LL << width) - 1); 626263509Sdim return ((Val % Align) == 0) && (Val >= 0) && (Val <= Max); 627263509Sdim } 628263509Sdim return false; 629263509Sdim } 630263509Sdim // checks whether this operand is an signed offset which fits is a field 631263509Sdim // of specified width and scaled by a specific number of bits 632263509Sdim template<unsigned width, unsigned scale> 633263509Sdim bool isSignedOffset() const { 634263509Sdim if (!isImm()) return false; 635263509Sdim if (isa<MCSymbolRefExpr>(Imm.Val)) return true; 636263509Sdim if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) { 637263509Sdim int64_t Val = CE->getValue(); 638263509Sdim int64_t Align = 1LL << scale; 639263509Sdim int64_t Max = Align * ((1LL << (width-1)) - 1); 640263509Sdim int64_t Min = -Align * (1LL << (width-1)); 641263509Sdim return ((Val % Align) == 0) && (Val >= Min) && (Val <= Max); 642263509Sdim } 643263509Sdim return false; 644263509Sdim } 645263509Sdim 646263509Sdim // checks whether this operand is a memory operand computed as an offset 647263509Sdim // applied to PC. the offset may have 8 bits of magnitude and is represented 648263509Sdim // with two bits of shift. textually it may be either [pc, #imm], #imm or 649263509Sdim // relocable expression... 650263509Sdim bool isThumbMemPC() const { 651263509Sdim int64_t Val = 0; 652263509Sdim if (isImm()) { 653263509Sdim if (isa<MCSymbolRefExpr>(Imm.Val)) return true; 654263509Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val); 655263509Sdim if (!CE) return false; 656263509Sdim Val = CE->getValue(); 657263509Sdim } 658263509Sdim else if (isMem()) { 659263509Sdim if(!Memory.OffsetImm || Memory.OffsetRegNum) return false; 660263509Sdim if(Memory.BaseRegNum != ARM::PC) return false; 661263509Sdim Val = Memory.OffsetImm->getValue(); 662263509Sdim } 663263509Sdim else return false; 664263509Sdim return ((Val % 4) == 0) && (Val >= 0) && (Val <= 1020); 665263509Sdim } 666235633Sdim bool isFPImm() const { 667235633Sdim if (!isImm()) return false; 668235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 669235633Sdim if (!CE) return false; 670235633Sdim int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue())); 671235633Sdim return Val != -1; 672235633Sdim } 673235633Sdim bool isFBits16() const { 674235633Sdim if (!isImm()) return false; 675235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 676235633Sdim if (!CE) return false; 677235633Sdim int64_t Value = CE->getValue(); 678235633Sdim return Value >= 0 && Value <= 16; 679235633Sdim } 680235633Sdim bool isFBits32() const { 681235633Sdim if (!isImm()) return false; 682235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 683235633Sdim if (!CE) return false; 684235633Sdim int64_t Value = CE->getValue(); 685235633Sdim return Value >= 1 && Value <= 32; 686235633Sdim } 687226890Sdim bool isImm8s4() const { 688235633Sdim if (!isImm()) return false; 689226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 690226890Sdim if (!CE) return false; 691226890Sdim int64_t Value = CE->getValue(); 692226890Sdim return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020; 693221345Sdim } 694226890Sdim bool isImm0_1020s4() const { 695235633Sdim if (!isImm()) return false; 696226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 697226890Sdim if (!CE) return false; 698226890Sdim int64_t Value = CE->getValue(); 699226890Sdim return ((Value & 3) == 0) && Value >= 0 && Value <= 1020; 700218893Sdim } 701226890Sdim bool isImm0_508s4() const { 702235633Sdim if (!isImm()) return false; 703226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 704226890Sdim if (!CE) return false; 705226890Sdim int64_t Value = CE->getValue(); 706226890Sdim return ((Value & 3) == 0) && Value >= 0 && Value <= 508; 707218893Sdim } 708235633Sdim bool isImm0_508s4Neg() const { 709235633Sdim if (!isImm()) return false; 710235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 711235633Sdim if (!CE) return false; 712235633Sdim int64_t Value = -CE->getValue(); 713235633Sdim // explicitly exclude zero. we want that to use the normal 0_508 version. 714235633Sdim return ((Value & 3) == 0) && Value > 0 && Value <= 508; 715235633Sdim } 716263509Sdim bool isImm0_239() const { 717263509Sdim if (!isImm()) return false; 718263509Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 719263509Sdim if (!CE) return false; 720263509Sdim int64_t Value = CE->getValue(); 721263509Sdim return Value >= 0 && Value < 240; 722263509Sdim } 723224145Sdim bool isImm0_255() const { 724235633Sdim 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 } 730235633Sdim bool isImm0_4095() const { 731235633Sdim if (!isImm()) return false; 732235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 733235633Sdim if (!CE) return false; 734235633Sdim int64_t Value = CE->getValue(); 735235633Sdim return Value >= 0 && Value < 4096; 736235633Sdim } 737235633Sdim bool isImm0_4095Neg() const { 738235633Sdim if (!isImm()) return false; 739235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 740235633Sdim if (!CE) return false; 741235633Sdim int64_t Value = -CE->getValue(); 742235633Sdim return Value > 0 && Value < 4096; 743235633Sdim } 744235633Sdim bool isImm0_1() const { 745235633Sdim if (!isImm()) return false; 746235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 747235633Sdim if (!CE) return false; 748235633Sdim int64_t Value = CE->getValue(); 749235633Sdim return Value >= 0 && Value < 2; 750235633Sdim } 751235633Sdim bool isImm0_3() const { 752235633Sdim if (!isImm()) return false; 753235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 754235633Sdim if (!CE) return false; 755235633Sdim int64_t Value = CE->getValue(); 756235633Sdim return Value >= 0 && Value < 4; 757235633Sdim } 758224145Sdim bool isImm0_7() const { 759235633Sdim 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 { 766235633Sdim 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 } 772226890Sdim bool isImm0_31() const { 773235633Sdim if (!isImm()) return false; 774226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 775226890Sdim if (!CE) return false; 776226890Sdim int64_t Value = CE->getValue(); 777226890Sdim return Value >= 0 && Value < 32; 778226890Sdim } 779235633Sdim bool isImm0_63() const { 780235633Sdim if (!isImm()) return false; 781235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 782235633Sdim if (!CE) return false; 783235633Sdim int64_t Value = CE->getValue(); 784235633Sdim return Value >= 0 && Value < 64; 785235633Sdim } 786235633Sdim bool isImm8() const { 787235633Sdim if (!isImm()) return false; 788235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 789235633Sdim if (!CE) return false; 790235633Sdim int64_t Value = CE->getValue(); 791235633Sdim return Value == 8; 792235633Sdim } 793235633Sdim bool isImm16() const { 794235633Sdim if (!isImm()) return false; 795235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 796235633Sdim if (!CE) return false; 797235633Sdim int64_t Value = CE->getValue(); 798235633Sdim return Value == 16; 799235633Sdim } 800235633Sdim bool isImm32() const { 801235633Sdim if (!isImm()) return false; 802235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 803235633Sdim if (!CE) return false; 804235633Sdim int64_t Value = CE->getValue(); 805235633Sdim return Value == 32; 806235633Sdim } 807235633Sdim bool isShrImm8() const { 808235633Sdim if (!isImm()) return false; 809235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 810235633Sdim if (!CE) return false; 811235633Sdim int64_t Value = CE->getValue(); 812235633Sdim return Value > 0 && Value <= 8; 813235633Sdim } 814235633Sdim bool isShrImm16() const { 815235633Sdim if (!isImm()) return false; 816235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 817235633Sdim if (!CE) return false; 818235633Sdim int64_t Value = CE->getValue(); 819235633Sdim return Value > 0 && Value <= 16; 820235633Sdim } 821235633Sdim bool isShrImm32() const { 822235633Sdim if (!isImm()) return false; 823235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 824235633Sdim if (!CE) return false; 825235633Sdim int64_t Value = CE->getValue(); 826235633Sdim return Value > 0 && Value <= 32; 827235633Sdim } 828235633Sdim bool isShrImm64() const { 829235633Sdim if (!isImm()) return false; 830235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 831235633Sdim if (!CE) return false; 832235633Sdim int64_t Value = CE->getValue(); 833235633Sdim return Value > 0 && Value <= 64; 834235633Sdim } 835235633Sdim bool isImm1_7() const { 836235633Sdim if (!isImm()) return false; 837235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 838235633Sdim if (!CE) return false; 839235633Sdim int64_t Value = CE->getValue(); 840235633Sdim return Value > 0 && Value < 8; 841235633Sdim } 842235633Sdim bool isImm1_15() const { 843235633Sdim if (!isImm()) return false; 844235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 845235633Sdim if (!CE) return false; 846235633Sdim int64_t Value = CE->getValue(); 847235633Sdim return Value > 0 && Value < 16; 848235633Sdim } 849235633Sdim bool isImm1_31() const { 850235633Sdim if (!isImm()) return false; 851235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 852235633Sdim if (!CE) return false; 853235633Sdim int64_t Value = CE->getValue(); 854235633Sdim return Value > 0 && Value < 32; 855235633Sdim } 856226890Sdim bool isImm1_16() const { 857235633Sdim if (!isImm()) return false; 858226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 859226890Sdim if (!CE) return false; 860226890Sdim int64_t Value = CE->getValue(); 861226890Sdim return Value > 0 && Value < 17; 862226890Sdim } 863226890Sdim bool isImm1_32() const { 864235633Sdim if (!isImm()) return false; 865226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 866226890Sdim if (!CE) return false; 867226890Sdim int64_t Value = CE->getValue(); 868226890Sdim return Value > 0 && Value < 33; 869226890Sdim } 870235633Sdim bool isImm0_32() const { 871235633Sdim if (!isImm()) return false; 872235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 873235633Sdim if (!CE) return false; 874235633Sdim int64_t Value = CE->getValue(); 875235633Sdim return Value >= 0 && Value < 33; 876235633Sdim } 877224145Sdim bool isImm0_65535() const { 878235633Sdim 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 } 884263509Sdim bool isImm256_65535Expr() const { 885263509Sdim if (!isImm()) return false; 886263509Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 887263509Sdim // If it's not a constant expression, it'll generate a fixup and be 888263509Sdim // handled later. 889263509Sdim if (!CE) return true; 890263509Sdim int64_t Value = CE->getValue(); 891263509Sdim return Value >= 256 && Value < 65536; 892263509Sdim } 893226890Sdim bool isImm0_65535Expr() const { 894235633Sdim if (!isImm()) return false; 895224145Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 896226890Sdim // If it's not a constant expression, it'll generate a fixup and be 897226890Sdim // handled later. 898226890Sdim if (!CE) return true; 899226890Sdim int64_t Value = CE->getValue(); 900226890Sdim return Value >= 0 && Value < 65536; 901226890Sdim } 902226890Sdim bool isImm24bit() const { 903235633Sdim if (!isImm()) return false; 904226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 905224145Sdim if (!CE) return false; 906224145Sdim int64_t Value = CE->getValue(); 907226890Sdim return Value >= 0 && Value <= 0xffffff; 908224145Sdim } 909226890Sdim bool isImmThumbSR() const { 910235633Sdim if (!isImm()) return false; 911226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 912226890Sdim if (!CE) return false; 913226890Sdim int64_t Value = CE->getValue(); 914226890Sdim return Value > 0 && Value < 33; 915226890Sdim } 916226890Sdim bool isPKHLSLImm() const { 917235633Sdim if (!isImm()) return false; 918226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 919221345Sdim if (!CE) return false; 920221345Sdim int64_t Value = CE->getValue(); 921226890Sdim return Value >= 0 && Value < 32; 922226890Sdim } 923226890Sdim bool isPKHASRImm() const { 924235633Sdim if (!isImm()) return false; 925226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 926226890Sdim if (!CE) return false; 927226890Sdim int64_t Value = CE->getValue(); 928226890Sdim return Value > 0 && Value <= 32; 929221345Sdim } 930245431Sdim bool isAdrLabel() const { 931245431Sdim // If we have an immediate that's not a constant, treat it as a label 932245431Sdim // reference needing a fixup. If it is a constant, but it can't fit 933245431Sdim // into shift immediate encoding, we reject it. 934245431Sdim if (isImm() && !isa<MCConstantExpr>(getImm())) return true; 935245431Sdim else return (isARMSOImm() || isARMSOImmNeg()); 936245431Sdim } 937226890Sdim bool isARMSOImm() const { 938235633Sdim if (!isImm()) return false; 939226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 940226890Sdim if (!CE) return false; 941226890Sdim int64_t Value = CE->getValue(); 942226890Sdim return ARM_AM::getSOImmVal(Value) != -1; 943226890Sdim } 944235633Sdim bool isARMSOImmNot() const { 945235633Sdim if (!isImm()) return false; 946235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 947235633Sdim if (!CE) return false; 948235633Sdim int64_t Value = CE->getValue(); 949235633Sdim return ARM_AM::getSOImmVal(~Value) != -1; 950235633Sdim } 951235633Sdim bool isARMSOImmNeg() const { 952235633Sdim if (!isImm()) return false; 953235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 954235633Sdim if (!CE) return false; 955235633Sdim int64_t Value = CE->getValue(); 956235633Sdim // Only use this when not representable as a plain so_imm. 957235633Sdim return ARM_AM::getSOImmVal(Value) == -1 && 958235633Sdim ARM_AM::getSOImmVal(-Value) != -1; 959235633Sdim } 960226890Sdim bool isT2SOImm() const { 961235633Sdim if (!isImm()) return false; 962226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 963221345Sdim if (!CE) return false; 964221345Sdim int64_t Value = CE->getValue(); 965226890Sdim return ARM_AM::getT2SOImmVal(Value) != -1; 966221345Sdim } 967235633Sdim bool isT2SOImmNot() const { 968235633Sdim if (!isImm()) return false; 969235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 970235633Sdim if (!CE) return false; 971235633Sdim int64_t Value = CE->getValue(); 972263509Sdim return ARM_AM::getT2SOImmVal(Value) == -1 && 973263509Sdim ARM_AM::getT2SOImmVal(~Value) != -1; 974235633Sdim } 975235633Sdim bool isT2SOImmNeg() const { 976235633Sdim if (!isImm()) return false; 977235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 978235633Sdim if (!CE) return false; 979235633Sdim int64_t Value = CE->getValue(); 980235633Sdim // Only use this when not representable as a plain so_imm. 981235633Sdim return ARM_AM::getT2SOImmVal(Value) == -1 && 982235633Sdim ARM_AM::getT2SOImmVal(-Value) != -1; 983235633Sdim } 984226890Sdim bool isSetEndImm() const { 985235633Sdim if (!isImm()) return false; 986226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 987218893Sdim if (!CE) return false; 988218893Sdim int64_t Value = CE->getValue(); 989226890Sdim return Value == 1 || Value == 0; 990218893Sdim } 991226890Sdim bool isReg() const { return Kind == k_Register; } 992226890Sdim bool isRegList() const { return Kind == k_RegisterList; } 993226890Sdim bool isDPRRegList() const { return Kind == k_DPRRegisterList; } 994226890Sdim bool isSPRRegList() const { return Kind == k_SPRRegisterList; } 995226890Sdim bool isToken() const { return Kind == k_Token; } 996226890Sdim bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; } 997263509Sdim bool isInstSyncBarrierOpt() const { return Kind == k_InstSyncBarrierOpt; } 998245431Sdim bool isMem() const { return Kind == k_Memory; } 999226890Sdim bool isShifterImm() const { return Kind == k_ShifterImmediate; } 1000226890Sdim bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; } 1001226890Sdim bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; } 1002226890Sdim bool isRotImm() const { return Kind == k_RotateImmediate; } 1003226890Sdim bool isBitfield() const { return Kind == k_BitfieldDescriptor; } 1004226890Sdim bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; } 1005226890Sdim bool isPostIdxReg() const { 1006235633Sdim return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift; 1007226890Sdim } 1008226890Sdim bool isMemNoOffset(bool alignOK = false) const { 1009245431Sdim if (!isMem()) 1010221345Sdim return false; 1011226890Sdim // No offset of any kind. 1012226890Sdim return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 && 1013226890Sdim (alignOK || Memory.Alignment == 0); 1014226890Sdim } 1015235633Sdim bool isMemPCRelImm12() const { 1016245431Sdim if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) 1017235633Sdim return false; 1018235633Sdim // Base register must be PC. 1019235633Sdim if (Memory.BaseRegNum != ARM::PC) 1020235633Sdim return false; 1021235633Sdim // Immediate offset in range [-4095, 4095]. 1022235633Sdim if (!Memory.OffsetImm) return true; 1023235633Sdim int64_t Val = Memory.OffsetImm->getValue(); 1024235633Sdim return (Val > -4096 && Val < 4096) || (Val == INT32_MIN); 1025235633Sdim } 1026226890Sdim bool isAlignedMemory() const { 1027226890Sdim return isMemNoOffset(true); 1028226890Sdim } 1029226890Sdim bool isAddrMode2() const { 1030245431Sdim if (!isMem() || Memory.Alignment != 0) return false; 1031226890Sdim // Check for register offset. 1032226890Sdim if (Memory.OffsetRegNum) return true; 1033226890Sdim // Immediate offset in range [-4095, 4095]. 1034226890Sdim if (!Memory.OffsetImm) return true; 1035226890Sdim int64_t Val = Memory.OffsetImm->getValue(); 1036226890Sdim return Val > -4096 && Val < 4096; 1037226890Sdim } 1038226890Sdim bool isAM2OffsetImm() const { 1039235633Sdim if (!isImm()) return false; 1040226890Sdim // Immediate offset in range [-4095, 4095]. 1041226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1042221345Sdim if (!CE) return false; 1043226890Sdim int64_t Val = CE->getValue(); 1044263509Sdim return (Val == INT32_MIN) || (Val > -4096 && Val < 4096); 1045226890Sdim } 1046226890Sdim bool isAddrMode3() const { 1047235633Sdim // If we have an immediate that's not a constant, treat it as a label 1048235633Sdim // reference needing a fixup. If it is a constant, it's something else 1049235633Sdim // and we reject it. 1050235633Sdim if (isImm() && !isa<MCConstantExpr>(getImm())) 1051235633Sdim return true; 1052245431Sdim if (!isMem() || Memory.Alignment != 0) return false; 1053226890Sdim // No shifts are legal for AM3. 1054226890Sdim if (Memory.ShiftType != ARM_AM::no_shift) return false; 1055226890Sdim // Check for register offset. 1056226890Sdim if (Memory.OffsetRegNum) return true; 1057226890Sdim // Immediate offset in range [-255, 255]. 1058226890Sdim if (!Memory.OffsetImm) return true; 1059226890Sdim int64_t Val = Memory.OffsetImm->getValue(); 1060245431Sdim // The #-0 offset is encoded as INT32_MIN, and we have to check 1061245431Sdim // for this too. 1062245431Sdim return (Val > -256 && Val < 256) || Val == INT32_MIN; 1063226890Sdim } 1064226890Sdim bool isAM3Offset() const { 1065226890Sdim if (Kind != k_Immediate && Kind != k_PostIndexRegister) 1066221345Sdim return false; 1067226890Sdim if (Kind == k_PostIndexRegister) 1068226890Sdim return PostIdxReg.ShiftTy == ARM_AM::no_shift; 1069226890Sdim // Immediate offset in range [-255, 255]. 1070226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1071226890Sdim if (!CE) return false; 1072226890Sdim int64_t Val = CE->getValue(); 1073226890Sdim // Special case, #-0 is INT32_MIN. 1074226890Sdim return (Val > -256 && Val < 256) || Val == INT32_MIN; 1075226890Sdim } 1076226890Sdim bool isAddrMode5() const { 1077235633Sdim // If we have an immediate that's not a constant, treat it as a label 1078235633Sdim // reference needing a fixup. If it is a constant, it's something else 1079235633Sdim // and we reject it. 1080235633Sdim if (isImm() && !isa<MCConstantExpr>(getImm())) 1081235633Sdim return true; 1082245431Sdim if (!isMem() || Memory.Alignment != 0) return false; 1083226890Sdim // Check for register offset. 1084226890Sdim if (Memory.OffsetRegNum) return false; 1085226890Sdim // Immediate offset in range [-1020, 1020] and a multiple of 4. 1086226890Sdim if (!Memory.OffsetImm) return true; 1087226890Sdim int64_t Val = Memory.OffsetImm->getValue(); 1088226890Sdim return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) || 1089235633Sdim Val == INT32_MIN; 1090226890Sdim } 1091226890Sdim bool isMemTBB() const { 1092245431Sdim if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative || 1093226890Sdim Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0) 1094226890Sdim return false; 1095221345Sdim return true; 1096221345Sdim } 1097226890Sdim bool isMemTBH() const { 1098245431Sdim if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative || 1099226890Sdim Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 || 1100226890Sdim Memory.Alignment != 0 ) 1101218893Sdim return false; 1102218893Sdim return true; 1103218893Sdim } 1104226890Sdim bool isMemRegOffset() const { 1105245431Sdim if (!isMem() || !Memory.OffsetRegNum || Memory.Alignment != 0) 1106218893Sdim return false; 1107226890Sdim return true; 1108226890Sdim } 1109226890Sdim bool isT2MemRegOffset() const { 1110245431Sdim if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative || 1111226890Sdim Memory.Alignment != 0) 1112226890Sdim return false; 1113226890Sdim // Only lsl #{0, 1, 2, 3} allowed. 1114226890Sdim if (Memory.ShiftType == ARM_AM::no_shift) 1115226890Sdim return true; 1116226890Sdim if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3) 1117226890Sdim return false; 1118226890Sdim return true; 1119226890Sdim } 1120226890Sdim bool isMemThumbRR() const { 1121226890Sdim // Thumb reg+reg addressing is simple. Just two registers, a base and 1122226890Sdim // an offset. No shifts, negations or any other complicating factors. 1123245431Sdim if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative || 1124226890Sdim Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0) 1125226890Sdim return false; 1126226890Sdim return isARMLowRegister(Memory.BaseRegNum) && 1127226890Sdim (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum)); 1128226890Sdim } 1129226890Sdim bool isMemThumbRIs4() const { 1130245431Sdim if (!isMem() || Memory.OffsetRegNum != 0 || 1131226890Sdim !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0) 1132226890Sdim return false; 1133226890Sdim // Immediate offset, multiple of 4 in range [0, 124]. 1134226890Sdim if (!Memory.OffsetImm) return true; 1135226890Sdim int64_t Val = Memory.OffsetImm->getValue(); 1136226890Sdim return Val >= 0 && Val <= 124 && (Val % 4) == 0; 1137226890Sdim } 1138226890Sdim bool isMemThumbRIs2() const { 1139245431Sdim if (!isMem() || Memory.OffsetRegNum != 0 || 1140226890Sdim !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0) 1141226890Sdim return false; 1142226890Sdim // Immediate offset, multiple of 4 in range [0, 62]. 1143226890Sdim if (!Memory.OffsetImm) return true; 1144226890Sdim int64_t Val = Memory.OffsetImm->getValue(); 1145226890Sdim return Val >= 0 && Val <= 62 && (Val % 2) == 0; 1146226890Sdim } 1147226890Sdim bool isMemThumbRIs1() const { 1148245431Sdim if (!isMem() || Memory.OffsetRegNum != 0 || 1149226890Sdim !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0) 1150226890Sdim return false; 1151226890Sdim // Immediate offset in range [0, 31]. 1152226890Sdim if (!Memory.OffsetImm) return true; 1153226890Sdim int64_t Val = Memory.OffsetImm->getValue(); 1154226890Sdim return Val >= 0 && Val <= 31; 1155226890Sdim } 1156226890Sdim bool isMemThumbSPI() const { 1157245431Sdim if (!isMem() || Memory.OffsetRegNum != 0 || 1158226890Sdim Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0) 1159226890Sdim return false; 1160226890Sdim // Immediate offset, multiple of 4 in range [0, 1020]. 1161226890Sdim if (!Memory.OffsetImm) return true; 1162226890Sdim int64_t Val = Memory.OffsetImm->getValue(); 1163226890Sdim return Val >= 0 && Val <= 1020 && (Val % 4) == 0; 1164226890Sdim } 1165226890Sdim bool isMemImm8s4Offset() const { 1166235633Sdim // If we have an immediate that's not a constant, treat it as a label 1167235633Sdim // reference needing a fixup. If it is a constant, it's something else 1168235633Sdim // and we reject it. 1169235633Sdim if (isImm() && !isa<MCConstantExpr>(getImm())) 1170235633Sdim return true; 1171245431Sdim if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) 1172226890Sdim return false; 1173226890Sdim // Immediate offset a multiple of 4 in range [-1020, 1020]. 1174226890Sdim if (!Memory.OffsetImm) return true; 1175226890Sdim int64_t Val = Memory.OffsetImm->getValue(); 1176245431Sdim // Special case, #-0 is INT32_MIN. 1177245431Sdim return (Val >= -1020 && Val <= 1020 && (Val & 3) == 0) || Val == INT32_MIN; 1178226890Sdim } 1179226890Sdim bool isMemImm0_1020s4Offset() const { 1180245431Sdim if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) 1181226890Sdim return false; 1182226890Sdim // Immediate offset a multiple of 4 in range [0, 1020]. 1183226890Sdim if (!Memory.OffsetImm) return true; 1184226890Sdim int64_t Val = Memory.OffsetImm->getValue(); 1185226890Sdim return Val >= 0 && Val <= 1020 && (Val & 3) == 0; 1186226890Sdim } 1187226890Sdim bool isMemImm8Offset() const { 1188245431Sdim if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) 1189226890Sdim return false; 1190235633Sdim // Base reg of PC isn't allowed for these encodings. 1191235633Sdim if (Memory.BaseRegNum == ARM::PC) return false; 1192226890Sdim // Immediate offset in range [-255, 255]. 1193226890Sdim if (!Memory.OffsetImm) return true; 1194226890Sdim int64_t Val = Memory.OffsetImm->getValue(); 1195226890Sdim return (Val == INT32_MIN) || (Val > -256 && Val < 256); 1196226890Sdim } 1197226890Sdim bool isMemPosImm8Offset() const { 1198245431Sdim if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) 1199226890Sdim return false; 1200226890Sdim // Immediate offset in range [0, 255]. 1201226890Sdim if (!Memory.OffsetImm) return true; 1202226890Sdim int64_t Val = Memory.OffsetImm->getValue(); 1203226890Sdim return Val >= 0 && Val < 256; 1204226890Sdim } 1205226890Sdim bool isMemNegImm8Offset() const { 1206245431Sdim if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) 1207226890Sdim return false; 1208235633Sdim // Base reg of PC isn't allowed for these encodings. 1209235633Sdim if (Memory.BaseRegNum == ARM::PC) return false; 1210226890Sdim // Immediate offset in range [-255, -1]. 1211235633Sdim if (!Memory.OffsetImm) return false; 1212226890Sdim int64_t Val = Memory.OffsetImm->getValue(); 1213235633Sdim return (Val == INT32_MIN) || (Val > -256 && Val < 0); 1214226890Sdim } 1215226890Sdim bool isMemUImm12Offset() const { 1216245431Sdim if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) 1217226890Sdim return false; 1218226890Sdim // Immediate offset in range [0, 4095]. 1219226890Sdim if (!Memory.OffsetImm) return true; 1220226890Sdim int64_t Val = Memory.OffsetImm->getValue(); 1221226890Sdim return (Val >= 0 && Val < 4096); 1222226890Sdim } 1223226890Sdim bool isMemImm12Offset() const { 1224226890Sdim // If we have an immediate that's not a constant, treat it as a label 1225226890Sdim // reference needing a fixup. If it is a constant, it's something else 1226226890Sdim // and we reject it. 1227235633Sdim if (isImm() && !isa<MCConstantExpr>(getImm())) 1228226890Sdim return true; 1229226890Sdim 1230245431Sdim if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) 1231226890Sdim return false; 1232226890Sdim // Immediate offset in range [-4095, 4095]. 1233226890Sdim if (!Memory.OffsetImm) return true; 1234226890Sdim int64_t Val = Memory.OffsetImm->getValue(); 1235226890Sdim return (Val > -4096 && Val < 4096) || (Val == INT32_MIN); 1236226890Sdim } 1237226890Sdim bool isPostIdxImm8() const { 1238235633Sdim if (!isImm()) return false; 1239226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1240218893Sdim if (!CE) return false; 1241226890Sdim int64_t Val = CE->getValue(); 1242226890Sdim return (Val > -256 && Val < 256) || (Val == INT32_MIN); 1243226890Sdim } 1244226890Sdim bool isPostIdxImm8s4() const { 1245235633Sdim if (!isImm()) return false; 1246226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1247226890Sdim if (!CE) return false; 1248226890Sdim int64_t Val = CE->getValue(); 1249226890Sdim return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) || 1250226890Sdim (Val == INT32_MIN); 1251226890Sdim } 1252218893Sdim 1253226890Sdim bool isMSRMask() const { return Kind == k_MSRMask; } 1254226890Sdim bool isProcIFlags() const { return Kind == k_ProcIFlags; } 1255226890Sdim 1256235633Sdim // NEON operands. 1257235633Sdim bool isSingleSpacedVectorList() const { 1258235633Sdim return Kind == k_VectorList && !VectorList.isDoubleSpaced; 1259235633Sdim } 1260235633Sdim bool isDoubleSpacedVectorList() const { 1261235633Sdim return Kind == k_VectorList && VectorList.isDoubleSpaced; 1262235633Sdim } 1263235633Sdim bool isVecListOneD() const { 1264235633Sdim if (!isSingleSpacedVectorList()) return false; 1265235633Sdim return VectorList.Count == 1; 1266235633Sdim } 1267235633Sdim 1268235633Sdim bool isVecListDPair() const { 1269235633Sdim if (!isSingleSpacedVectorList()) return false; 1270235633Sdim return (ARMMCRegisterClasses[ARM::DPairRegClassID] 1271235633Sdim .contains(VectorList.RegNum)); 1272235633Sdim } 1273235633Sdim 1274235633Sdim bool isVecListThreeD() const { 1275235633Sdim if (!isSingleSpacedVectorList()) return false; 1276235633Sdim return VectorList.Count == 3; 1277235633Sdim } 1278235633Sdim 1279235633Sdim bool isVecListFourD() const { 1280235633Sdim if (!isSingleSpacedVectorList()) return false; 1281235633Sdim return VectorList.Count == 4; 1282235633Sdim } 1283235633Sdim 1284235633Sdim bool isVecListDPairSpaced() const { 1285235633Sdim if (isSingleSpacedVectorList()) return false; 1286235633Sdim return (ARMMCRegisterClasses[ARM::DPairSpcRegClassID] 1287235633Sdim .contains(VectorList.RegNum)); 1288235633Sdim } 1289235633Sdim 1290235633Sdim bool isVecListThreeQ() const { 1291235633Sdim if (!isDoubleSpacedVectorList()) return false; 1292235633Sdim return VectorList.Count == 3; 1293235633Sdim } 1294235633Sdim 1295235633Sdim bool isVecListFourQ() const { 1296235633Sdim if (!isDoubleSpacedVectorList()) return false; 1297235633Sdim return VectorList.Count == 4; 1298235633Sdim } 1299235633Sdim 1300235633Sdim bool isSingleSpacedVectorAllLanes() const { 1301235633Sdim return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced; 1302235633Sdim } 1303235633Sdim bool isDoubleSpacedVectorAllLanes() const { 1304235633Sdim return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced; 1305235633Sdim } 1306235633Sdim bool isVecListOneDAllLanes() const { 1307235633Sdim if (!isSingleSpacedVectorAllLanes()) return false; 1308235633Sdim return VectorList.Count == 1; 1309235633Sdim } 1310235633Sdim 1311235633Sdim bool isVecListDPairAllLanes() const { 1312235633Sdim if (!isSingleSpacedVectorAllLanes()) return false; 1313235633Sdim return (ARMMCRegisterClasses[ARM::DPairRegClassID] 1314235633Sdim .contains(VectorList.RegNum)); 1315235633Sdim } 1316235633Sdim 1317235633Sdim bool isVecListDPairSpacedAllLanes() const { 1318235633Sdim if (!isDoubleSpacedVectorAllLanes()) return false; 1319235633Sdim return VectorList.Count == 2; 1320235633Sdim } 1321235633Sdim 1322235633Sdim bool isVecListThreeDAllLanes() const { 1323235633Sdim if (!isSingleSpacedVectorAllLanes()) return false; 1324235633Sdim return VectorList.Count == 3; 1325235633Sdim } 1326235633Sdim 1327235633Sdim bool isVecListThreeQAllLanes() const { 1328235633Sdim if (!isDoubleSpacedVectorAllLanes()) return false; 1329235633Sdim return VectorList.Count == 3; 1330235633Sdim } 1331235633Sdim 1332235633Sdim bool isVecListFourDAllLanes() const { 1333235633Sdim if (!isSingleSpacedVectorAllLanes()) return false; 1334235633Sdim return VectorList.Count == 4; 1335235633Sdim } 1336235633Sdim 1337235633Sdim bool isVecListFourQAllLanes() const { 1338235633Sdim if (!isDoubleSpacedVectorAllLanes()) return false; 1339235633Sdim return VectorList.Count == 4; 1340235633Sdim } 1341235633Sdim 1342235633Sdim bool isSingleSpacedVectorIndexed() const { 1343235633Sdim return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced; 1344235633Sdim } 1345235633Sdim bool isDoubleSpacedVectorIndexed() const { 1346235633Sdim return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced; 1347235633Sdim } 1348235633Sdim bool isVecListOneDByteIndexed() const { 1349235633Sdim if (!isSingleSpacedVectorIndexed()) return false; 1350235633Sdim return VectorList.Count == 1 && VectorList.LaneIndex <= 7; 1351235633Sdim } 1352235633Sdim 1353235633Sdim bool isVecListOneDHWordIndexed() const { 1354235633Sdim if (!isSingleSpacedVectorIndexed()) return false; 1355235633Sdim return VectorList.Count == 1 && VectorList.LaneIndex <= 3; 1356235633Sdim } 1357235633Sdim 1358235633Sdim bool isVecListOneDWordIndexed() const { 1359235633Sdim if (!isSingleSpacedVectorIndexed()) return false; 1360235633Sdim return VectorList.Count == 1 && VectorList.LaneIndex <= 1; 1361235633Sdim } 1362235633Sdim 1363235633Sdim bool isVecListTwoDByteIndexed() const { 1364235633Sdim if (!isSingleSpacedVectorIndexed()) return false; 1365235633Sdim return VectorList.Count == 2 && VectorList.LaneIndex <= 7; 1366235633Sdim } 1367235633Sdim 1368235633Sdim bool isVecListTwoDHWordIndexed() const { 1369235633Sdim if (!isSingleSpacedVectorIndexed()) return false; 1370235633Sdim return VectorList.Count == 2 && VectorList.LaneIndex <= 3; 1371235633Sdim } 1372235633Sdim 1373235633Sdim bool isVecListTwoQWordIndexed() const { 1374235633Sdim if (!isDoubleSpacedVectorIndexed()) return false; 1375235633Sdim return VectorList.Count == 2 && VectorList.LaneIndex <= 1; 1376235633Sdim } 1377235633Sdim 1378235633Sdim bool isVecListTwoQHWordIndexed() const { 1379235633Sdim if (!isDoubleSpacedVectorIndexed()) return false; 1380235633Sdim return VectorList.Count == 2 && VectorList.LaneIndex <= 3; 1381235633Sdim } 1382235633Sdim 1383235633Sdim bool isVecListTwoDWordIndexed() const { 1384235633Sdim if (!isSingleSpacedVectorIndexed()) return false; 1385235633Sdim return VectorList.Count == 2 && VectorList.LaneIndex <= 1; 1386235633Sdim } 1387235633Sdim 1388235633Sdim bool isVecListThreeDByteIndexed() const { 1389235633Sdim if (!isSingleSpacedVectorIndexed()) return false; 1390235633Sdim return VectorList.Count == 3 && VectorList.LaneIndex <= 7; 1391235633Sdim } 1392235633Sdim 1393235633Sdim bool isVecListThreeDHWordIndexed() const { 1394235633Sdim if (!isSingleSpacedVectorIndexed()) return false; 1395235633Sdim return VectorList.Count == 3 && VectorList.LaneIndex <= 3; 1396235633Sdim } 1397235633Sdim 1398235633Sdim bool isVecListThreeQWordIndexed() const { 1399235633Sdim if (!isDoubleSpacedVectorIndexed()) return false; 1400235633Sdim return VectorList.Count == 3 && VectorList.LaneIndex <= 1; 1401235633Sdim } 1402235633Sdim 1403235633Sdim bool isVecListThreeQHWordIndexed() const { 1404235633Sdim if (!isDoubleSpacedVectorIndexed()) return false; 1405235633Sdim return VectorList.Count == 3 && VectorList.LaneIndex <= 3; 1406235633Sdim } 1407235633Sdim 1408235633Sdim bool isVecListThreeDWordIndexed() const { 1409235633Sdim if (!isSingleSpacedVectorIndexed()) return false; 1410235633Sdim return VectorList.Count == 3 && VectorList.LaneIndex <= 1; 1411235633Sdim } 1412235633Sdim 1413235633Sdim bool isVecListFourDByteIndexed() const { 1414235633Sdim if (!isSingleSpacedVectorIndexed()) return false; 1415235633Sdim return VectorList.Count == 4 && VectorList.LaneIndex <= 7; 1416235633Sdim } 1417235633Sdim 1418235633Sdim bool isVecListFourDHWordIndexed() const { 1419235633Sdim if (!isSingleSpacedVectorIndexed()) return false; 1420235633Sdim return VectorList.Count == 4 && VectorList.LaneIndex <= 3; 1421235633Sdim } 1422235633Sdim 1423235633Sdim bool isVecListFourQWordIndexed() const { 1424235633Sdim if (!isDoubleSpacedVectorIndexed()) return false; 1425235633Sdim return VectorList.Count == 4 && VectorList.LaneIndex <= 1; 1426235633Sdim } 1427235633Sdim 1428235633Sdim bool isVecListFourQHWordIndexed() const { 1429235633Sdim if (!isDoubleSpacedVectorIndexed()) return false; 1430235633Sdim return VectorList.Count == 4 && VectorList.LaneIndex <= 3; 1431235633Sdim } 1432235633Sdim 1433235633Sdim bool isVecListFourDWordIndexed() const { 1434235633Sdim if (!isSingleSpacedVectorIndexed()) return false; 1435235633Sdim return VectorList.Count == 4 && VectorList.LaneIndex <= 1; 1436235633Sdim } 1437235633Sdim 1438226890Sdim bool isVectorIndex8() const { 1439226890Sdim if (Kind != k_VectorIndex) return false; 1440226890Sdim return VectorIndex.Val < 8; 1441218893Sdim } 1442226890Sdim bool isVectorIndex16() const { 1443226890Sdim if (Kind != k_VectorIndex) return false; 1444226890Sdim return VectorIndex.Val < 4; 1445226890Sdim } 1446226890Sdim bool isVectorIndex32() const { 1447226890Sdim if (Kind != k_VectorIndex) return false; 1448226890Sdim return VectorIndex.Val < 2; 1449226890Sdim } 1450218893Sdim 1451235633Sdim bool isNEONi8splat() const { 1452235633Sdim if (!isImm()) return false; 1453235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1454235633Sdim // Must be a constant. 1455235633Sdim if (!CE) return false; 1456235633Sdim int64_t Value = CE->getValue(); 1457235633Sdim // i8 value splatted across 8 bytes. The immediate is just the 8 byte 1458235633Sdim // value. 1459235633Sdim return Value >= 0 && Value < 256; 1460235633Sdim } 1461226890Sdim 1462235633Sdim bool isNEONi16splat() const { 1463235633Sdim if (!isImm()) return false; 1464235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1465235633Sdim // Must be a constant. 1466235633Sdim if (!CE) return false; 1467235633Sdim int64_t Value = CE->getValue(); 1468235633Sdim // i16 value in the range [0,255] or [0x0100, 0xff00] 1469235633Sdim return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00); 1470235633Sdim } 1471226890Sdim 1472235633Sdim bool isNEONi32splat() const { 1473235633Sdim if (!isImm()) return false; 1474235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1475235633Sdim // Must be a constant. 1476235633Sdim if (!CE) return false; 1477235633Sdim int64_t Value = CE->getValue(); 1478235633Sdim // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X. 1479235633Sdim return (Value >= 0 && Value < 256) || 1480235633Sdim (Value >= 0x0100 && Value <= 0xff00) || 1481235633Sdim (Value >= 0x010000 && Value <= 0xff0000) || 1482235633Sdim (Value >= 0x01000000 && Value <= 0xff000000); 1483235633Sdim } 1484235633Sdim 1485235633Sdim bool isNEONi32vmov() const { 1486235633Sdim if (!isImm()) return false; 1487235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1488235633Sdim // Must be a constant. 1489235633Sdim if (!CE) return false; 1490235633Sdim int64_t Value = CE->getValue(); 1491235633Sdim // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X, 1492235633Sdim // for VMOV/VMVN only, 00Xf or 0Xff are also accepted. 1493235633Sdim return (Value >= 0 && Value < 256) || 1494235633Sdim (Value >= 0x0100 && Value <= 0xff00) || 1495235633Sdim (Value >= 0x010000 && Value <= 0xff0000) || 1496235633Sdim (Value >= 0x01000000 && Value <= 0xff000000) || 1497235633Sdim (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) || 1498235633Sdim (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff); 1499235633Sdim } 1500235633Sdim bool isNEONi32vmovNeg() const { 1501235633Sdim if (!isImm()) return false; 1502235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1503235633Sdim // Must be a constant. 1504235633Sdim if (!CE) return false; 1505235633Sdim int64_t Value = ~CE->getValue(); 1506235633Sdim // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X, 1507235633Sdim // for VMOV/VMVN only, 00Xf or 0Xff are also accepted. 1508235633Sdim return (Value >= 0 && Value < 256) || 1509235633Sdim (Value >= 0x0100 && Value <= 0xff00) || 1510235633Sdim (Value >= 0x010000 && Value <= 0xff0000) || 1511235633Sdim (Value >= 0x01000000 && Value <= 0xff000000) || 1512235633Sdim (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) || 1513235633Sdim (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff); 1514235633Sdim } 1515235633Sdim 1516235633Sdim bool isNEONi64splat() const { 1517235633Sdim if (!isImm()) return false; 1518235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1519235633Sdim // Must be a constant. 1520235633Sdim if (!CE) return false; 1521235633Sdim uint64_t Value = CE->getValue(); 1522235633Sdim // i64 value with each byte being either 0 or 0xff. 1523235633Sdim for (unsigned i = 0; i < 8; ++i) 1524235633Sdim if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false; 1525235633Sdim return true; 1526235633Sdim } 1527235633Sdim 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 1555226890Sdim void addCoprocOptionOperands(MCInst &Inst, unsigned N) const { 1556226890Sdim assert(N == 1 && "Invalid number of operands!"); 1557226890Sdim Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val)); 1558226890Sdim } 1559226890Sdim 1560226890Sdim void addITMaskOperands(MCInst &Inst, unsigned N) const { 1561226890Sdim assert(N == 1 && "Invalid number of operands!"); 1562226890Sdim Inst.addOperand(MCOperand::CreateImm(ITMask.Mask)); 1563226890Sdim } 1564226890Sdim 1565226890Sdim void addITCondCodeOperands(MCInst &Inst, unsigned N) const { 1566226890Sdim assert(N == 1 && "Invalid number of operands!"); 1567226890Sdim Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode()))); 1568226890Sdim } 1569226890Sdim 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 1580226890Sdim void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const { 1581224145Sdim assert(N == 3 && "Invalid number of operands!"); 1582235633Sdim assert(isRegShiftedReg() && 1583235633Sdim "addRegShiftedRegOperands() on non RegShiftedReg!"); 1584226890Sdim Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg)); 1585226890Sdim Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg)); 1586224145Sdim Inst.addOperand(MCOperand::CreateImm( 1587226890Sdim ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm))); 1588224145Sdim } 1589224145Sdim 1590226890Sdim void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const { 1591226890Sdim assert(N == 2 && "Invalid number of operands!"); 1592235633Sdim assert(isRegShiftedImm() && 1593235633Sdim "addRegShiftedImmOperands() on non RegShiftedImm!"); 1594226890Sdim Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg)); 1595245431Sdim // Shift of #32 is encoded as 0 where permitted 1596245431Sdim unsigned Imm = (RegShiftedImm.ShiftImm == 32 ? 0 : RegShiftedImm.ShiftImm); 1597221345Sdim Inst.addOperand(MCOperand::CreateImm( 1598245431Sdim ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, Imm))); 1599221345Sdim } 1600221345Sdim 1601226890Sdim void addShifterImmOperands(MCInst &Inst, unsigned N) const { 1602226890Sdim assert(N == 1 && "Invalid number of operands!"); 1603226890Sdim Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) | 1604226890Sdim ShifterImm.Imm)); 1605226890Sdim } 1606226890Sdim 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 1623226890Sdim void addRotImmOperands(MCInst &Inst, unsigned N) const { 1624226890Sdim assert(N == 1 && "Invalid number of operands!"); 1625226890Sdim // Encoded as val>>3. The printer handles display as 8, 16, 24. 1626226890Sdim Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3)); 1627226890Sdim } 1628226890Sdim 1629226890Sdim void addBitfieldOperands(MCInst &Inst, unsigned N) const { 1630226890Sdim assert(N == 1 && "Invalid number of operands!"); 1631226890Sdim // Munge the lsb/width into a bitfield mask. 1632226890Sdim unsigned lsb = Bitfield.LSB; 1633226890Sdim unsigned width = Bitfield.Width; 1634226890Sdim // Make a 32-bit mask w/ the referenced bits clear and all other bits set. 1635226890Sdim uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >> 1636226890Sdim (32 - (lsb + width))); 1637226890Sdim Inst.addOperand(MCOperand::CreateImm(Mask)); 1638226890Sdim } 1639226890Sdim 1640212904Sdim void addImmOperands(MCInst &Inst, unsigned N) const { 1641212904Sdim assert(N == 1 && "Invalid number of operands!"); 1642212904Sdim addExpr(Inst, getImm()); 1643212904Sdim } 1644212904Sdim 1645235633Sdim void addFBits16Operands(MCInst &Inst, unsigned N) const { 1646235633Sdim assert(N == 1 && "Invalid number of operands!"); 1647235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1648235633Sdim Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue())); 1649235633Sdim } 1650235633Sdim 1651235633Sdim void addFBits32Operands(MCInst &Inst, unsigned N) const { 1652235633Sdim assert(N == 1 && "Invalid number of operands!"); 1653235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1654235633Sdim Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue())); 1655235633Sdim } 1656235633Sdim 1657226890Sdim void addFPImmOperands(MCInst &Inst, unsigned N) const { 1658226890Sdim assert(N == 1 && "Invalid number of operands!"); 1659235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1660235633Sdim int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue())); 1661235633Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 1662226890Sdim } 1663226890Sdim 1664226890Sdim void addImm8s4Operands(MCInst &Inst, unsigned N) const { 1665226890Sdim assert(N == 1 && "Invalid number of operands!"); 1666226890Sdim // FIXME: We really want to scale the value here, but the LDRD/STRD 1667226890Sdim // instruction don't encode operands that way yet. 1668226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1669226890Sdim Inst.addOperand(MCOperand::CreateImm(CE->getValue())); 1670226890Sdim } 1671226890Sdim 1672226890Sdim void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const { 1673226890Sdim assert(N == 1 && "Invalid number of operands!"); 1674226890Sdim // The immediate is scaled by four in the encoding and is stored 1675226890Sdim // in the MCInst as such. Lop off the low two bits here. 1676226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1677226890Sdim Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4)); 1678226890Sdim } 1679226890Sdim 1680235633Sdim void addImm0_508s4NegOperands(MCInst &Inst, unsigned N) const { 1681226890Sdim assert(N == 1 && "Invalid number of operands!"); 1682226890Sdim // The immediate is scaled by four in the encoding and is stored 1683226890Sdim // in the MCInst as such. Lop off the low two bits here. 1684226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1685235633Sdim Inst.addOperand(MCOperand::CreateImm(-(CE->getValue() / 4))); 1686226890Sdim } 1687226890Sdim 1688235633Sdim void addImm0_508s4Operands(MCInst &Inst, unsigned N) const { 1689224145Sdim assert(N == 1 && "Invalid number of operands!"); 1690235633Sdim // The immediate is scaled by four in the encoding and is stored 1691235633Sdim // in the MCInst as such. Lop off the low two bits here. 1692235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1693235633Sdim Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4)); 1694224145Sdim } 1695224145Sdim 1696226890Sdim void addImm1_16Operands(MCInst &Inst, unsigned N) const { 1697226890Sdim assert(N == 1 && "Invalid number of operands!"); 1698226890Sdim // The constant encodes as the immediate-1, and we store in the instruction 1699226890Sdim // the bits as encoded, so subtract off one here. 1700226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1701226890Sdim Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1)); 1702226890Sdim } 1703226890Sdim 1704226890Sdim void addImm1_32Operands(MCInst &Inst, unsigned N) const { 1705226890Sdim assert(N == 1 && "Invalid number of operands!"); 1706226890Sdim // The constant encodes as the immediate-1, and we store in the instruction 1707226890Sdim // the bits as encoded, so subtract off one here. 1708226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1709226890Sdim Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1)); 1710226890Sdim } 1711226890Sdim 1712226890Sdim void addImmThumbSROperands(MCInst &Inst, unsigned N) const { 1713226890Sdim assert(N == 1 && "Invalid number of operands!"); 1714226890Sdim // The constant encodes as the immediate, except for 32, which encodes as 1715226890Sdim // zero. 1716226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1717226890Sdim unsigned Imm = CE->getValue(); 1718226890Sdim Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm))); 1719226890Sdim } 1720226890Sdim 1721226890Sdim void addPKHASRImmOperands(MCInst &Inst, unsigned N) const { 1722226890Sdim assert(N == 1 && "Invalid number of operands!"); 1723226890Sdim // An ASR value of 32 encodes as 0, so that's how we want to add it to 1724226890Sdim // the instruction as well. 1725226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1726226890Sdim int Val = CE->getValue(); 1727226890Sdim Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val)); 1728226890Sdim } 1729226890Sdim 1730235633Sdim void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const { 1731226890Sdim assert(N == 1 && "Invalid number of operands!"); 1732235633Sdim // The operand is actually a t2_so_imm, but we have its bitwise 1733235633Sdim // negation in the assembly source, so twiddle it here. 1734235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1735235633Sdim Inst.addOperand(MCOperand::CreateImm(~CE->getValue())); 1736226890Sdim } 1737226890Sdim 1738235633Sdim void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const { 1739224145Sdim assert(N == 1 && "Invalid number of operands!"); 1740235633Sdim // The operand is actually a t2_so_imm, but we have its 1741235633Sdim // negation in the assembly source, so twiddle it here. 1742235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1743235633Sdim Inst.addOperand(MCOperand::CreateImm(-CE->getValue())); 1744224145Sdim } 1745224145Sdim 1746235633Sdim void addImm0_4095NegOperands(MCInst &Inst, unsigned N) const { 1747226890Sdim assert(N == 1 && "Invalid number of operands!"); 1748235633Sdim // The operand is actually an imm0_4095, but we have its 1749235633Sdim // negation in the assembly source, so twiddle it here. 1750235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1751235633Sdim Inst.addOperand(MCOperand::CreateImm(-CE->getValue())); 1752226890Sdim } 1753226890Sdim 1754263509Sdim void addUnsignedOffset_b8s2Operands(MCInst &Inst, unsigned N) const { 1755263509Sdim if(const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm())) { 1756263509Sdim Inst.addOperand(MCOperand::CreateImm(CE->getValue() >> 2)); 1757263509Sdim return; 1758263509Sdim } 1759263509Sdim 1760263509Sdim const MCSymbolRefExpr *SR = dyn_cast<MCSymbolRefExpr>(Imm.Val); 1761263509Sdim assert(SR && "Unknown value type!"); 1762263509Sdim Inst.addOperand(MCOperand::CreateExpr(SR)); 1763263509Sdim } 1764263509Sdim 1765263509Sdim void addThumbMemPCOperands(MCInst &Inst, unsigned N) const { 1766263509Sdim assert(N == 1 && "Invalid number of operands!"); 1767263509Sdim if (isImm()) { 1768263509Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1769263509Sdim if (CE) { 1770263509Sdim Inst.addOperand(MCOperand::CreateImm(CE->getValue())); 1771263509Sdim return; 1772263509Sdim } 1773263509Sdim 1774263509Sdim const MCSymbolRefExpr *SR = dyn_cast<MCSymbolRefExpr>(Imm.Val); 1775263509Sdim assert(SR && "Unknown value type!"); 1776263509Sdim Inst.addOperand(MCOperand::CreateExpr(SR)); 1777263509Sdim return; 1778263509Sdim } 1779263509Sdim 1780263509Sdim assert(isMem() && "Unknown value type!"); 1781263509Sdim assert(isa<MCConstantExpr>(Memory.OffsetImm) && "Unknown value type!"); 1782263509Sdim Inst.addOperand(MCOperand::CreateImm(Memory.OffsetImm->getValue())); 1783263509Sdim } 1784263509Sdim 1785235633Sdim void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const { 1786235633Sdim assert(N == 1 && "Invalid number of operands!"); 1787235633Sdim // The operand is actually a so_imm, but we have its bitwise 1788235633Sdim // negation in the assembly source, so twiddle it here. 1789235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1790235633Sdim Inst.addOperand(MCOperand::CreateImm(~CE->getValue())); 1791235633Sdim } 1792235633Sdim 1793235633Sdim void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const { 1794235633Sdim assert(N == 1 && "Invalid number of operands!"); 1795235633Sdim // The operand is actually a so_imm, but we have its 1796235633Sdim // negation in the assembly source, so twiddle it here. 1797235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1798235633Sdim Inst.addOperand(MCOperand::CreateImm(-CE->getValue())); 1799235633Sdim } 1800235633Sdim 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 1806263509Sdim void addInstSyncBarrierOptOperands(MCInst &Inst, unsigned N) const { 1807263509Sdim assert(N == 1 && "Invalid number of operands!"); 1808263509Sdim Inst.addOperand(MCOperand::CreateImm(unsigned(getInstSyncBarrierOpt()))); 1809263509Sdim } 1810263509Sdim 1811226890Sdim void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const { 1812226890Sdim assert(N == 1 && "Invalid number of operands!"); 1813226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 1814226890Sdim } 1815221345Sdim 1816235633Sdim void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const { 1817235633Sdim assert(N == 1 && "Invalid number of operands!"); 1818235633Sdim int32_t Imm = Memory.OffsetImm->getValue(); 1819235633Sdim Inst.addOperand(MCOperand::CreateImm(Imm)); 1820235633Sdim } 1821235633Sdim 1822245431Sdim void addAdrLabelOperands(MCInst &Inst, unsigned N) const { 1823245431Sdim assert(N == 1 && "Invalid number of operands!"); 1824245431Sdim assert(isImm() && "Not an immediate!"); 1825245431Sdim 1826245431Sdim // If we have an immediate that's not a constant, treat it as a label 1827245431Sdim // reference needing a fixup. 1828245431Sdim if (!isa<MCConstantExpr>(getImm())) { 1829245431Sdim Inst.addOperand(MCOperand::CreateExpr(getImm())); 1830245431Sdim return; 1831245431Sdim } 1832245431Sdim 1833245431Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1834245431Sdim int Val = CE->getValue(); 1835245431Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 1836245431Sdim } 1837245431Sdim 1838226890Sdim void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const { 1839226890Sdim assert(N == 2 && "Invalid number of operands!"); 1840226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 1841226890Sdim Inst.addOperand(MCOperand::CreateImm(Memory.Alignment)); 1842221345Sdim } 1843221345Sdim 1844226890Sdim void addAddrMode2Operands(MCInst &Inst, unsigned N) const { 1845226890Sdim assert(N == 3 && "Invalid number of operands!"); 1846226890Sdim int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; 1847226890Sdim if (!Memory.OffsetRegNum) { 1848226890Sdim ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; 1849226890Sdim // Special case for #-0 1850226890Sdim if (Val == INT32_MIN) Val = 0; 1851226890Sdim if (Val < 0) Val = -Val; 1852226890Sdim Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift); 1853226890Sdim } else { 1854226890Sdim // For register offset, we encode the shift type and negation flag 1855226890Sdim // here. 1856226890Sdim Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 1857226890Sdim Memory.ShiftImm, Memory.ShiftType); 1858226890Sdim } 1859226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 1860226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); 1861226890Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 1862226890Sdim } 1863221345Sdim 1864226890Sdim void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const { 1865226890Sdim assert(N == 2 && "Invalid number of operands!"); 1866226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 1867226890Sdim assert(CE && "non-constant AM2OffsetImm operand!"); 1868226890Sdim int32_t Val = CE->getValue(); 1869226890Sdim ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; 1870226890Sdim // Special case for #-0 1871226890Sdim if (Val == INT32_MIN) Val = 0; 1872226890Sdim if (Val < 0) Val = -Val; 1873226890Sdim Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift); 1874226890Sdim Inst.addOperand(MCOperand::CreateReg(0)); 1875226890Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 1876226890Sdim } 1877221345Sdim 1878226890Sdim void addAddrMode3Operands(MCInst &Inst, unsigned N) const { 1879226890Sdim assert(N == 3 && "Invalid number of operands!"); 1880235633Sdim // If we have an immediate that's not a constant, treat it as a label 1881235633Sdim // reference needing a fixup. If it is a constant, it's something else 1882235633Sdim // and we reject it. 1883235633Sdim if (isImm()) { 1884235633Sdim Inst.addOperand(MCOperand::CreateExpr(getImm())); 1885235633Sdim Inst.addOperand(MCOperand::CreateReg(0)); 1886235633Sdim Inst.addOperand(MCOperand::CreateImm(0)); 1887235633Sdim return; 1888235633Sdim } 1889235633Sdim 1890226890Sdim int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; 1891226890Sdim if (!Memory.OffsetRegNum) { 1892226890Sdim ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; 1893226890Sdim // Special case for #-0 1894226890Sdim if (Val == INT32_MIN) Val = 0; 1895226890Sdim if (Val < 0) Val = -Val; 1896226890Sdim Val = ARM_AM::getAM3Opc(AddSub, Val); 1897226890Sdim } else { 1898226890Sdim // For register offset, we encode the shift type and negation flag 1899226890Sdim // here. 1900226890Sdim Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0); 1901226890Sdim } 1902226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 1903226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); 1904226890Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 1905226890Sdim } 1906221345Sdim 1907226890Sdim void addAM3OffsetOperands(MCInst &Inst, unsigned N) const { 1908226890Sdim assert(N == 2 && "Invalid number of operands!"); 1909226890Sdim if (Kind == k_PostIndexRegister) { 1910226890Sdim int32_t Val = 1911226890Sdim ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0); 1912226890Sdim Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum)); 1913226890Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 1914221345Sdim return; 1915221345Sdim } 1916221345Sdim 1917226890Sdim // Constant offset. 1918226890Sdim const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm()); 1919226890Sdim int32_t Val = CE->getValue(); 1920226890Sdim ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; 1921226890Sdim // Special case for #-0 1922226890Sdim if (Val == INT32_MIN) Val = 0; 1923226890Sdim if (Val < 0) Val = -Val; 1924226890Sdim Val = ARM_AM::getAM3Opc(AddSub, Val); 1925221345Sdim Inst.addOperand(MCOperand::CreateReg(0)); 1926226890Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 1927226890Sdim } 1928221345Sdim 1929226890Sdim void addAddrMode5Operands(MCInst &Inst, unsigned N) const { 1930226890Sdim assert(N == 2 && "Invalid number of operands!"); 1931235633Sdim // If we have an immediate that's not a constant, treat it as a label 1932235633Sdim // reference needing a fixup. If it is a constant, it's something else 1933235633Sdim // and we reject it. 1934235633Sdim if (isImm()) { 1935235633Sdim Inst.addOperand(MCOperand::CreateExpr(getImm())); 1936235633Sdim Inst.addOperand(MCOperand::CreateImm(0)); 1937235633Sdim return; 1938235633Sdim } 1939235633Sdim 1940226890Sdim // The lower two bits are always zero and as such are not encoded. 1941226890Sdim int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0; 1942226890Sdim ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; 1943226890Sdim // Special case for #-0 1944226890Sdim if (Val == INT32_MIN) Val = 0; 1945226890Sdim if (Val < 0) Val = -Val; 1946226890Sdim Val = ARM_AM::getAM5Opc(AddSub, Val); 1947226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 1948226890Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 1949226890Sdim } 1950221345Sdim 1951226890Sdim void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const { 1952226890Sdim assert(N == 2 && "Invalid number of operands!"); 1953235633Sdim // If we have an immediate that's not a constant, treat it as a label 1954235633Sdim // reference needing a fixup. If it is a constant, it's something else 1955235633Sdim // and we reject it. 1956235633Sdim if (isImm()) { 1957235633Sdim Inst.addOperand(MCOperand::CreateExpr(getImm())); 1958235633Sdim Inst.addOperand(MCOperand::CreateImm(0)); 1959235633Sdim return; 1960235633Sdim } 1961235633Sdim 1962226890Sdim int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; 1963226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 1964226890Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 1965221345Sdim } 1966221345Sdim 1967226890Sdim void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const { 1968226890Sdim assert(N == 2 && "Invalid number of operands!"); 1969226890Sdim // The lower two bits are always zero and as such are not encoded. 1970226890Sdim int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0; 1971226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 1972226890Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 1973226890Sdim } 1974221345Sdim 1975226890Sdim void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const { 1976226890Sdim assert(N == 2 && "Invalid number of operands!"); 1977226890Sdim int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; 1978226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 1979226890Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 1980226890Sdim } 1981221345Sdim 1982226890Sdim void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const { 1983226890Sdim addMemImm8OffsetOperands(Inst, N); 1984226890Sdim } 1985226890Sdim 1986226890Sdim void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const { 1987226890Sdim addMemImm8OffsetOperands(Inst, N); 1988226890Sdim } 1989226890Sdim 1990226890Sdim void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const { 1991226890Sdim assert(N == 2 && "Invalid number of operands!"); 1992226890Sdim // If this is an immediate, it's a label reference. 1993235633Sdim if (isImm()) { 1994226890Sdim addExpr(Inst, getImm()); 1995226890Sdim Inst.addOperand(MCOperand::CreateImm(0)); 1996221345Sdim return; 1997221345Sdim } 1998221345Sdim 1999226890Sdim // Otherwise, it's a normal memory reg+offset. 2000226890Sdim int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; 2001226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 2002226890Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 2003226890Sdim } 2004221345Sdim 2005226890Sdim void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const { 2006226890Sdim assert(N == 2 && "Invalid number of operands!"); 2007226890Sdim // If this is an immediate, it's a label reference. 2008235633Sdim if (isImm()) { 2009226890Sdim addExpr(Inst, getImm()); 2010226890Sdim Inst.addOperand(MCOperand::CreateImm(0)); 2011226890Sdim return; 2012226890Sdim } 2013221345Sdim 2014226890Sdim // Otherwise, it's a normal memory reg+offset. 2015226890Sdim int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; 2016226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 2017226890Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 2018221345Sdim } 2019221345Sdim 2020226890Sdim void addMemTBBOperands(MCInst &Inst, unsigned N) const { 2021226890Sdim assert(N == 2 && "Invalid number of operands!"); 2022226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 2023226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); 2024226890Sdim } 2025218893Sdim 2026226890Sdim void addMemTBHOperands(MCInst &Inst, unsigned N) const { 2027226890Sdim assert(N == 2 && "Invalid number of operands!"); 2028226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 2029226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); 2030226890Sdim } 2031218893Sdim 2032226890Sdim void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const { 2033226890Sdim assert(N == 3 && "Invalid number of operands!"); 2034235633Sdim unsigned Val = 2035235633Sdim ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 2036235633Sdim Memory.ShiftImm, Memory.ShiftType); 2037226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 2038226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); 2039226890Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 2040226890Sdim } 2041218893Sdim 2042226890Sdim void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const { 2043226890Sdim assert(N == 3 && "Invalid number of operands!"); 2044226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 2045226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); 2046226890Sdim Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm)); 2047218893Sdim } 2048218893Sdim 2049226890Sdim void addMemThumbRROperands(MCInst &Inst, unsigned N) const { 2050226890Sdim assert(N == 2 && "Invalid number of operands!"); 2051226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 2052226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); 2053218893Sdim } 2054218893Sdim 2055226890Sdim void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const { 2056226890Sdim assert(N == 2 && "Invalid number of operands!"); 2057226890Sdim int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0; 2058226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 2059226890Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 2060218893Sdim } 2061218893Sdim 2062226890Sdim void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const { 2063226890Sdim assert(N == 2 && "Invalid number of operands!"); 2064226890Sdim int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0; 2065226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 2066226890Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 2067226890Sdim } 2068226890Sdim 2069226890Sdim void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const { 2070226890Sdim assert(N == 2 && "Invalid number of operands!"); 2071226890Sdim int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0; 2072226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 2073226890Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 2074226890Sdim } 2075226890Sdim 2076226890Sdim void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const { 2077226890Sdim assert(N == 2 && "Invalid number of operands!"); 2078226890Sdim int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0; 2079226890Sdim Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); 2080226890Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 2081226890Sdim } 2082226890Sdim 2083226890Sdim void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const { 2084226890Sdim assert(N == 1 && "Invalid number of operands!"); 2085226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 2086226890Sdim assert(CE && "non-constant post-idx-imm8 operand!"); 2087226890Sdim int Imm = CE->getValue(); 2088226890Sdim bool isAdd = Imm >= 0; 2089226890Sdim if (Imm == INT32_MIN) Imm = 0; 2090226890Sdim Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8; 2091226890Sdim Inst.addOperand(MCOperand::CreateImm(Imm)); 2092226890Sdim } 2093226890Sdim 2094226890Sdim void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const { 2095226890Sdim assert(N == 1 && "Invalid number of operands!"); 2096226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 2097226890Sdim assert(CE && "non-constant post-idx-imm8s4 operand!"); 2098226890Sdim int Imm = CE->getValue(); 2099226890Sdim bool isAdd = Imm >= 0; 2100226890Sdim if (Imm == INT32_MIN) Imm = 0; 2101226890Sdim // Immediate is scaled by 4. 2102226890Sdim Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8; 2103226890Sdim Inst.addOperand(MCOperand::CreateImm(Imm)); 2104226890Sdim } 2105226890Sdim 2106226890Sdim void addPostIdxRegOperands(MCInst &Inst, unsigned N) const { 2107226890Sdim assert(N == 2 && "Invalid number of operands!"); 2108226890Sdim Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum)); 2109226890Sdim Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd)); 2110226890Sdim } 2111226890Sdim 2112226890Sdim void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const { 2113226890Sdim assert(N == 2 && "Invalid number of operands!"); 2114226890Sdim Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum)); 2115226890Sdim // The sign, shift type, and shift amount are encoded in a single operand 2116226890Sdim // using the AM2 encoding helpers. 2117226890Sdim ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub; 2118226890Sdim unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm, 2119226890Sdim PostIdxReg.ShiftTy); 2120226890Sdim Inst.addOperand(MCOperand::CreateImm(Imm)); 2121226890Sdim } 2122226890Sdim 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 2133235633Sdim void addVecListOperands(MCInst &Inst, unsigned N) const { 2134235633Sdim assert(N == 1 && "Invalid number of operands!"); 2135235633Sdim Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum)); 2136235633Sdim } 2137235633Sdim 2138235633Sdim void addVecListIndexedOperands(MCInst &Inst, unsigned N) const { 2139235633Sdim assert(N == 2 && "Invalid number of operands!"); 2140235633Sdim Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum)); 2141235633Sdim Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex)); 2142235633Sdim } 2143235633Sdim 2144226890Sdim void addVectorIndex8Operands(MCInst &Inst, unsigned N) const { 2145226890Sdim assert(N == 1 && "Invalid number of operands!"); 2146226890Sdim Inst.addOperand(MCOperand::CreateImm(getVectorIndex())); 2147226890Sdim } 2148226890Sdim 2149226890Sdim void addVectorIndex16Operands(MCInst &Inst, unsigned N) const { 2150226890Sdim assert(N == 1 && "Invalid number of operands!"); 2151226890Sdim Inst.addOperand(MCOperand::CreateImm(getVectorIndex())); 2152226890Sdim } 2153226890Sdim 2154226890Sdim void addVectorIndex32Operands(MCInst &Inst, unsigned N) const { 2155226890Sdim assert(N == 1 && "Invalid number of operands!"); 2156226890Sdim Inst.addOperand(MCOperand::CreateImm(getVectorIndex())); 2157226890Sdim } 2158226890Sdim 2159235633Sdim void addNEONi8splatOperands(MCInst &Inst, unsigned N) const { 2160235633Sdim assert(N == 1 && "Invalid number of operands!"); 2161235633Sdim // The immediate encodes the type of constant as well as the value. 2162235633Sdim // Mask in that this is an i8 splat. 2163235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 2164235633Sdim Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00)); 2165235633Sdim } 2166235633Sdim 2167235633Sdim void addNEONi16splatOperands(MCInst &Inst, unsigned N) const { 2168235633Sdim assert(N == 1 && "Invalid number of operands!"); 2169235633Sdim // The immediate encodes the type of constant as well as the value. 2170235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 2171235633Sdim unsigned Value = CE->getValue(); 2172235633Sdim if (Value >= 256) 2173235633Sdim Value = (Value >> 8) | 0xa00; 2174235633Sdim else 2175235633Sdim Value |= 0x800; 2176235633Sdim Inst.addOperand(MCOperand::CreateImm(Value)); 2177235633Sdim } 2178235633Sdim 2179235633Sdim void addNEONi32splatOperands(MCInst &Inst, unsigned N) const { 2180235633Sdim assert(N == 1 && "Invalid number of operands!"); 2181235633Sdim // The immediate encodes the type of constant as well as the value. 2182235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 2183235633Sdim unsigned Value = CE->getValue(); 2184235633Sdim if (Value >= 256 && Value <= 0xff00) 2185235633Sdim Value = (Value >> 8) | 0x200; 2186235633Sdim else if (Value > 0xffff && Value <= 0xff0000) 2187235633Sdim Value = (Value >> 16) | 0x400; 2188235633Sdim else if (Value > 0xffffff) 2189235633Sdim Value = (Value >> 24) | 0x600; 2190235633Sdim Inst.addOperand(MCOperand::CreateImm(Value)); 2191235633Sdim } 2192235633Sdim 2193235633Sdim void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const { 2194235633Sdim assert(N == 1 && "Invalid number of operands!"); 2195235633Sdim // The immediate encodes the type of constant as well as the value. 2196235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 2197235633Sdim unsigned Value = CE->getValue(); 2198235633Sdim if (Value >= 256 && Value <= 0xffff) 2199235633Sdim Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200); 2200235633Sdim else if (Value > 0xffff && Value <= 0xffffff) 2201235633Sdim Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400); 2202235633Sdim else if (Value > 0xffffff) 2203235633Sdim Value = (Value >> 24) | 0x600; 2204235633Sdim Inst.addOperand(MCOperand::CreateImm(Value)); 2205235633Sdim } 2206235633Sdim 2207235633Sdim void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const { 2208235633Sdim assert(N == 1 && "Invalid number of operands!"); 2209235633Sdim // The immediate encodes the type of constant as well as the value. 2210235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 2211235633Sdim unsigned Value = ~CE->getValue(); 2212235633Sdim if (Value >= 256 && Value <= 0xffff) 2213235633Sdim Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200); 2214235633Sdim else if (Value > 0xffff && Value <= 0xffffff) 2215235633Sdim Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400); 2216235633Sdim else if (Value > 0xffffff) 2217235633Sdim Value = (Value >> 24) | 0x600; 2218235633Sdim Inst.addOperand(MCOperand::CreateImm(Value)); 2219235633Sdim } 2220235633Sdim 2221235633Sdim void addNEONi64splatOperands(MCInst &Inst, unsigned N) const { 2222235633Sdim assert(N == 1 && "Invalid number of operands!"); 2223235633Sdim // The immediate encodes the type of constant as well as the value. 2224235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 2225235633Sdim uint64_t Value = CE->getValue(); 2226235633Sdim unsigned Imm = 0; 2227235633Sdim for (unsigned i = 0; i < 8; ++i, Value >>= 8) { 2228235633Sdim Imm |= (Value & 1) << i; 2229235633Sdim } 2230235633Sdim Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00)); 2231235633Sdim } 2232235633Sdim 2233224145Sdim virtual void print(raw_ostream &OS) const; 2234212904Sdim 2235226890Sdim static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) { 2236226890Sdim ARMOperand *Op = new ARMOperand(k_ITCondMask); 2237226890Sdim Op->ITMask.Mask = Mask; 2238226890Sdim Op->StartLoc = S; 2239226890Sdim Op->EndLoc = S; 2240226890Sdim return Op; 2241226890Sdim } 2242226890Sdim 2243218893Sdim static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) { 2244226890Sdim 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) { 2252226890Sdim 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) { 2260226890Sdim ARMOperand *Op = new ARMOperand(k_CoprocReg); 2261218893Sdim Op->Cop.Val = CopVal; 2262218893Sdim Op->StartLoc = S; 2263218893Sdim Op->EndLoc = S; 2264218893Sdim return Op; 2265218893Sdim } 2266218893Sdim 2267226890Sdim static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) { 2268226890Sdim ARMOperand *Op = new ARMOperand(k_CoprocOption); 2269226890Sdim Op->Cop.Val = Val; 2270226890Sdim Op->StartLoc = S; 2271226890Sdim Op->EndLoc = E; 2272226890Sdim return Op; 2273226890Sdim } 2274226890Sdim 2275218893Sdim static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) { 2276226890Sdim 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) { 2284226890Sdim 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) { 2293226890Sdim 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) { 2305226890Sdim ARMOperand *Op = new ARMOperand(k_ShiftedRegister); 2306226890Sdim Op->RegShiftedReg.ShiftTy = ShTy; 2307226890Sdim Op->RegShiftedReg.SrcReg = SrcReg; 2308226890Sdim Op->RegShiftedReg.ShiftReg = ShiftReg; 2309226890Sdim Op->RegShiftedReg.ShiftImm = ShiftImm; 2310224145Sdim Op->StartLoc = S; 2311224145Sdim Op->EndLoc = E; 2312224145Sdim return Op; 2313224145Sdim } 2314224145Sdim 2315226890Sdim static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy, 2316226890Sdim unsigned SrcReg, 2317226890Sdim unsigned ShiftImm, 2318226890Sdim SMLoc S, SMLoc E) { 2319226890Sdim ARMOperand *Op = new ARMOperand(k_ShiftedImmediate); 2320226890Sdim Op->RegShiftedImm.ShiftTy = ShTy; 2321226890Sdim Op->RegShiftedImm.SrcReg = SrcReg; 2322226890Sdim Op->RegShiftedImm.ShiftImm = ShiftImm; 2323226890Sdim Op->StartLoc = S; 2324226890Sdim Op->EndLoc = E; 2325226890Sdim return Op; 2326226890Sdim } 2327226890Sdim 2328226890Sdim static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm, 2329221345Sdim SMLoc S, SMLoc E) { 2330226890Sdim ARMOperand *Op = new ARMOperand(k_ShifterImmediate); 2331226890Sdim Op->ShifterImm.isASR = isASR; 2332226890Sdim Op->ShifterImm.Imm = Imm; 2333221345Sdim Op->StartLoc = S; 2334221345Sdim Op->EndLoc = E; 2335221345Sdim return Op; 2336221345Sdim } 2337221345Sdim 2338226890Sdim static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) { 2339226890Sdim ARMOperand *Op = new ARMOperand(k_RotateImmediate); 2340226890Sdim Op->RotImm.Imm = Imm; 2341226890Sdim Op->StartLoc = S; 2342226890Sdim Op->EndLoc = E; 2343226890Sdim return Op; 2344226890Sdim } 2345226890Sdim 2346226890Sdim static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width, 2347226890Sdim SMLoc S, SMLoc E) { 2348226890Sdim ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor); 2349226890Sdim Op->Bitfield.LSB = LSB; 2350226890Sdim Op->Bitfield.Width = Width; 2351226890Sdim Op->StartLoc = S; 2352226890Sdim Op->EndLoc = E; 2353226890Sdim return Op; 2354226890Sdim } 2355226890Sdim 2356218893Sdim static ARMOperand * 2357263509Sdim CreateRegList(SmallVectorImpl<std::pair<unsigned, unsigned> > &Regs, 2358218893Sdim SMLoc StartLoc, SMLoc EndLoc) { 2359263509Sdim assert (Regs.size() > 0 && "RegList contains no registers?"); 2360226890Sdim KindTy Kind = k_RegisterList; 2361218893Sdim 2362263509Sdim if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().second)) 2363226890Sdim Kind = k_DPRRegisterList; 2364226890Sdim else if (ARMMCRegisterClasses[ARM::SPRRegClassID]. 2365263509Sdim contains(Regs.front().second)) 2366226890Sdim Kind = k_SPRRegisterList; 2367218893Sdim 2368263509Sdim // Sort based on the register encoding values. 2369263509Sdim array_pod_sort(Regs.begin(), Regs.end()); 2370263509Sdim 2371218893Sdim ARMOperand *Op = new ARMOperand(Kind); 2372263509Sdim for (SmallVectorImpl<std::pair<unsigned, unsigned> >::const_iterator 2373218893Sdim I = Regs.begin(), E = Regs.end(); I != E; ++I) 2374263509Sdim Op->Registers.push_back(I->second); 2375218893Sdim Op->StartLoc = StartLoc; 2376218893Sdim Op->EndLoc = EndLoc; 2377218893Sdim return Op; 2378218893Sdim } 2379218893Sdim 2380235633Sdim static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count, 2381235633Sdim bool isDoubleSpaced, SMLoc S, SMLoc E) { 2382235633Sdim ARMOperand *Op = new ARMOperand(k_VectorList); 2383235633Sdim Op->VectorList.RegNum = RegNum; 2384235633Sdim Op->VectorList.Count = Count; 2385235633Sdim Op->VectorList.isDoubleSpaced = isDoubleSpaced; 2386235633Sdim Op->StartLoc = S; 2387235633Sdim Op->EndLoc = E; 2388235633Sdim return Op; 2389235633Sdim } 2390235633Sdim 2391235633Sdim static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count, 2392235633Sdim bool isDoubleSpaced, 2393235633Sdim SMLoc S, SMLoc E) { 2394235633Sdim ARMOperand *Op = new ARMOperand(k_VectorListAllLanes); 2395235633Sdim Op->VectorList.RegNum = RegNum; 2396235633Sdim Op->VectorList.Count = Count; 2397235633Sdim Op->VectorList.isDoubleSpaced = isDoubleSpaced; 2398235633Sdim Op->StartLoc = S; 2399235633Sdim Op->EndLoc = E; 2400235633Sdim return Op; 2401235633Sdim } 2402235633Sdim 2403235633Sdim static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count, 2404235633Sdim unsigned Index, 2405235633Sdim bool isDoubleSpaced, 2406235633Sdim SMLoc S, SMLoc E) { 2407235633Sdim ARMOperand *Op = new ARMOperand(k_VectorListIndexed); 2408235633Sdim Op->VectorList.RegNum = RegNum; 2409235633Sdim Op->VectorList.Count = Count; 2410235633Sdim Op->VectorList.LaneIndex = Index; 2411235633Sdim Op->VectorList.isDoubleSpaced = isDoubleSpaced; 2412235633Sdim Op->StartLoc = S; 2413235633Sdim Op->EndLoc = E; 2414235633Sdim return Op; 2415235633Sdim } 2416235633Sdim 2417226890Sdim static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, 2418226890Sdim MCContext &Ctx) { 2419226890Sdim ARMOperand *Op = new ARMOperand(k_VectorIndex); 2420226890Sdim Op->VectorIndex.Val = Idx; 2421226890Sdim Op->StartLoc = S; 2422226890Sdim Op->EndLoc = E; 2423226890Sdim return Op; 2424226890Sdim } 2425226890Sdim 2426218893Sdim static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) { 2427226890Sdim ARMOperand *Op = new ARMOperand(k_Immediate); 2428206124Srdivacky Op->Imm.Val = Val; 2429206124Srdivacky Op->StartLoc = S; 2430206124Srdivacky Op->EndLoc = E; 2431218893Sdim return Op; 2432198090Srdivacky } 2433198090Srdivacky 2434226890Sdim static ARMOperand *CreateMem(unsigned BaseRegNum, 2435226890Sdim const MCConstantExpr *OffsetImm, 2436226890Sdim unsigned OffsetRegNum, 2437226890Sdim ARM_AM::ShiftOpc ShiftType, 2438226890Sdim unsigned ShiftImm, 2439226890Sdim unsigned Alignment, 2440226890Sdim bool isNegative, 2441218893Sdim SMLoc S, SMLoc E) { 2442226890Sdim ARMOperand *Op = new ARMOperand(k_Memory); 2443226890Sdim Op->Memory.BaseRegNum = BaseRegNum; 2444226890Sdim Op->Memory.OffsetImm = OffsetImm; 2445226890Sdim Op->Memory.OffsetRegNum = OffsetRegNum; 2446226890Sdim Op->Memory.ShiftType = ShiftType; 2447226890Sdim Op->Memory.ShiftImm = ShiftImm; 2448226890Sdim Op->Memory.Alignment = Alignment; 2449226890Sdim Op->Memory.isNegative = isNegative; 2450226890Sdim Op->StartLoc = S; 2451226890Sdim Op->EndLoc = E; 2452226890Sdim return Op; 2453226890Sdim } 2454218893Sdim 2455226890Sdim static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd, 2456226890Sdim ARM_AM::ShiftOpc ShiftTy, 2457226890Sdim unsigned ShiftImm, 2458226890Sdim SMLoc S, SMLoc E) { 2459226890Sdim ARMOperand *Op = new ARMOperand(k_PostIndexRegister); 2460226890Sdim Op->PostIdxReg.RegNum = RegNum; 2461226890Sdim Op->PostIdxReg.isAdd = isAdd; 2462226890Sdim Op->PostIdxReg.ShiftTy = ShiftTy; 2463226890Sdim 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) { 2470226890Sdim ARMOperand *Op = new ARMOperand(k_MemBarrierOpt); 2471218893Sdim Op->MBOpt.Val = Opt; 2472218893Sdim Op->StartLoc = S; 2473218893Sdim Op->EndLoc = S; 2474218893Sdim return Op; 2475218893Sdim } 2476218893Sdim 2477263509Sdim static ARMOperand *CreateInstSyncBarrierOpt(ARM_ISB::InstSyncBOpt Opt, 2478263509Sdim SMLoc S) { 2479263509Sdim ARMOperand *Op = new ARMOperand(k_InstSyncBarrierOpt); 2480263509Sdim Op->ISBOpt.Val = Opt; 2481263509Sdim Op->StartLoc = S; 2482263509Sdim Op->EndLoc = S; 2483263509Sdim return Op; 2484263509Sdim } 2485263509Sdim 2486218893Sdim static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) { 2487226890Sdim 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) { 2495226890Sdim 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) { 2507226890Sdim case k_CondCode: 2508218893Sdim OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">"; 2509212904Sdim break; 2510226890Sdim case k_CCOut: 2511218893Sdim OS << "<ccout " << getReg() << ">"; 2512218893Sdim break; 2513226890Sdim case k_ITCondMask: { 2514245431Sdim static const char *const MaskStr[] = { 2515235633Sdim "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)", 2516235633Sdim "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)" 2517235633Sdim }; 2518226890Sdim assert((ITMask.Mask & 0xf) == ITMask.Mask); 2519226890Sdim OS << "<it-mask " << MaskStr[ITMask.Mask] << ">"; 2520226890Sdim break; 2521226890Sdim } 2522226890Sdim case k_CoprocNum: 2523218893Sdim OS << "<coprocessor number: " << getCoproc() << ">"; 2524218893Sdim break; 2525226890Sdim case k_CoprocReg: 2526218893Sdim OS << "<coprocessor register: " << getCoproc() << ">"; 2527218893Sdim break; 2528226890Sdim case k_CoprocOption: 2529226890Sdim OS << "<coprocessor option: " << CoprocOption.Val << ">"; 2530226890Sdim break; 2531226890Sdim case k_MSRMask: 2532218893Sdim OS << "<mask: " << getMSRMask() << ">"; 2533218893Sdim break; 2534226890Sdim case k_Immediate: 2535212904Sdim getImm()->print(OS); 2536212904Sdim break; 2537226890Sdim case k_MemBarrierOpt: 2538263509Sdim OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt(), false) << ">"; 2539218893Sdim break; 2540263509Sdim case k_InstSyncBarrierOpt: 2541263509Sdim OS << "<ARM_ISB::" << InstSyncBOptToString(getInstSyncBarrierOpt()) << ">"; 2542263509Sdim break; 2543226890Sdim case k_Memory: 2544218893Sdim OS << "<memory " 2545226890Sdim << " base:" << Memory.BaseRegNum; 2546218893Sdim OS << ">"; 2547212904Sdim break; 2548226890Sdim case k_PostIndexRegister: 2549226890Sdim OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-") 2550226890Sdim << PostIdxReg.RegNum; 2551226890Sdim if (PostIdxReg.ShiftTy != ARM_AM::no_shift) 2552226890Sdim OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " " 2553226890Sdim << PostIdxReg.ShiftImm; 2554226890Sdim OS << ">"; 2555226890Sdim break; 2556226890Sdim 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 } 2565226890Sdim case k_Register: 2566212904Sdim OS << "<register " << getReg() << ">"; 2567212904Sdim break; 2568226890Sdim case k_ShifterImmediate: 2569226890Sdim OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl") 2570226890Sdim << " #" << ShifterImm.Imm << ">"; 2571221345Sdim break; 2572226890Sdim case k_ShiftedRegister: 2573226890Sdim OS << "<so_reg_reg " 2574235633Sdim << RegShiftedReg.SrcReg << " " 2575235633Sdim << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy) 2576235633Sdim << " " << RegShiftedReg.ShiftReg << ">"; 2577224145Sdim break; 2578226890Sdim case k_ShiftedImmediate: 2579226890Sdim OS << "<so_reg_imm " 2580235633Sdim << RegShiftedImm.SrcReg << " " 2581235633Sdim << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy) 2582235633Sdim << " #" << RegShiftedImm.ShiftImm << ">"; 2583226890Sdim break; 2584226890Sdim case k_RotateImmediate: 2585226890Sdim OS << "<ror " << " #" << (RotImm.Imm * 8) << ">"; 2586226890Sdim break; 2587226890Sdim case k_BitfieldDescriptor: 2588226890Sdim OS << "<bitfield " << "lsb: " << Bitfield.LSB 2589226890Sdim << ", width: " << Bitfield.Width << ">"; 2590226890Sdim break; 2591226890Sdim case k_RegisterList: 2592226890Sdim case k_DPRRegisterList: 2593226890Sdim 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 } 2606235633Sdim case k_VectorList: 2607235633Sdim OS << "<vector_list " << VectorList.Count << " * " 2608235633Sdim << VectorList.RegNum << ">"; 2609235633Sdim break; 2610235633Sdim case k_VectorListAllLanes: 2611235633Sdim OS << "<vector_list(all lanes) " << VectorList.Count << " * " 2612235633Sdim << VectorList.RegNum << ">"; 2613235633Sdim break; 2614235633Sdim case k_VectorListIndexed: 2615235633Sdim OS << "<vector_list(lane " << VectorList.LaneIndex << ") " 2616235633Sdim << VectorList.Count << " * " << VectorList.RegNum << ">"; 2617235633Sdim break; 2618226890Sdim case k_Token: 2619212904Sdim OS << "'" << getToken() << "'"; 2620212904Sdim break; 2621226890Sdim case k_VectorIndex: 2622226890Sdim OS << "<vectorindex " << getVectorIndex() << ">"; 2623226890Sdim 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) { 2636235633Sdim StartLoc = Parser.getTok().getLoc(); 2637252723Sdim EndLoc = Parser.getTok().getEndLoc(); 2638226890Sdim 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/// 2647226890Sdimint ARMAsmParser::tryParseRegister() { 2648202878Srdivacky const AsmToken &Tok = Parser.getTok(); 2649226890Sdim if (Tok.isNot(AsmToken::Identifier)) return -1; 2650198090Srdivacky 2651235633Sdim 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) 2659235633Sdim // Additional register name aliases for 'gas' compatibility. 2660235633Sdim .Case("a1", ARM::R0) 2661235633Sdim .Case("a2", ARM::R1) 2662235633Sdim .Case("a3", ARM::R2) 2663235633Sdim .Case("a4", ARM::R3) 2664235633Sdim .Case("v1", ARM::R4) 2665235633Sdim .Case("v2", ARM::R5) 2666235633Sdim .Case("v3", ARM::R6) 2667235633Sdim .Case("v4", ARM::R7) 2668235633Sdim .Case("v5", ARM::R8) 2669235633Sdim .Case("v6", ARM::R9) 2670235633Sdim .Case("v7", ARM::R10) 2671235633Sdim .Case("v8", ARM::R11) 2672235633Sdim .Case("sb", ARM::R9) 2673235633Sdim .Case("sl", ARM::R10) 2674235633Sdim .Case("fp", ARM::R11) 2675218893Sdim .Default(0); 2676218893Sdim } 2677235633Sdim if (!RegNum) { 2678235633Sdim // Check for aliases registered via .req. Canonicalize to lower case. 2679235633Sdim // That's more consistent since register names are case insensitive, and 2680235633Sdim // it's how the original entry was passed in from MC/MCParser/AsmParser. 2681235633Sdim StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase); 2682235633Sdim // If no match, return failure. 2683235633Sdim if (Entry == RegisterReqs.end()) 2684235633Sdim return -1; 2685235633Sdim Parser.Lex(); // Eat identifier token. 2686235633Sdim return Entry->getValue(); 2687235633Sdim } 2688198090Srdivacky 2689202878Srdivacky Parser.Lex(); // Eat identifier token. 2690226890Sdim 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). 2699226890Sdimint 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 2705235633Sdim std::string lowerCase = Tok.getString().lower(); 2706221345Sdim ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase) 2707235633Sdim .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(); 2727252723Sdim 2728252723Sdim 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). 2738235633Sdim if (Parser.getTok().is(AsmToken::Hash) || 2739235633Sdim Parser.getTok().is(AsmToken::Dollar)) { 2740224145Sdim Parser.Lex(); // Eat hash. 2741224145Sdim SMLoc ImmLoc = Parser.getTok().getLoc(); 2742224145Sdim const MCExpr *ShiftExpr = 0; 2743252723Sdim 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 } 2763235633Sdim // shift by zero is a nop. Always send it through as lsl. 2764235633Sdim // ('as' compatibility) 2765235633Sdim if (Imm == 0) 2766235633Sdim ShiftTy = ARM_AM::lsl; 2767224145Sdim } else if (Parser.getTok().is(AsmToken::Identifier)) { 2768252723Sdim SMLoc L = Parser.getTok().getLoc(); 2769252723Sdim EndLoc = Parser.getTok().getEndLoc(); 2770226890Sdim 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 2782226890Sdim if (ShiftReg && ShiftTy != ARM_AM::rrx) 2783226890Sdim Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg, 2784226890Sdim ShiftReg, Imm, 2785252723Sdim S, EndLoc)); 2786226890Sdim else 2787226890Sdim Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm, 2788252723Sdim 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:: 2801226890SdimtryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 2802252723Sdim const AsmToken &RegTok = Parser.getTok(); 2803226890Sdim int RegNo = tryParseRegister(); 2804218893Sdim if (RegNo == -1) 2805218893Sdim return true; 2806218893Sdim 2807252723Sdim Operands.push_back(ARMOperand::CreateReg(RegNo, RegTok.getLoc(), 2808252723Sdim 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 2815226890Sdim return false; 2816218893Sdim } 2817218893Sdim 2818226890Sdim // Also check for an index operand. This is only legal for vector registers, 2819226890Sdim // but that'll get caught OK in operand matching, so we don't need to 2820226890Sdim // explicitly filter everything else out here. 2821226890Sdim if (Parser.getTok().is(AsmToken::LBrac)) { 2822226890Sdim SMLoc SIdx = Parser.getTok().getLoc(); 2823226890Sdim Parser.Lex(); // Eat left bracket token. 2824226890Sdim 2825226890Sdim const MCExpr *ImmVal; 2826252723Sdim if (getParser().parseExpression(ImmVal)) 2827235633Sdim return true; 2828226890Sdim const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal); 2829235633Sdim if (!MCE) 2830235633Sdim return TokError("immediate value expected for vector index"); 2831226890Sdim 2832235633Sdim if (Parser.getTok().isNot(AsmToken::RBrac)) 2833252723Sdim return Error(Parser.getTok().getLoc(), "']' expected"); 2834226890Sdim 2835252723Sdim SMLoc E = Parser.getTok().getEndLoc(); 2836226890Sdim Parser.Lex(); // Eat right bracket token. 2837226890Sdim 2838226890Sdim Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(), 2839226890Sdim SIdx, E, 2840226890Sdim getContext())); 2841226890Sdim } 2842226890Sdim 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()) { 2853235633Sdim 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; 2875263509Sdim // p10 and p11 are invalid for coproc instructions (reserved for FP/NEON) 2876263509Sdim case '0': return CoprocOp == 'p'? -1: 10; 2877263509Sdim 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 2886226890Sdim/// parseITCondCode - Try to parse a condition code for an IT instruction. 2887226890SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 2888226890SdimparseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 2889226890Sdim SMLoc S = Parser.getTok().getLoc(); 2890226890Sdim const AsmToken &Tok = Parser.getTok(); 2891226890Sdim if (!Tok.is(AsmToken::Identifier)) 2892226890Sdim return MatchOperand_NoMatch; 2893245431Sdim unsigned CC = StringSwitch<unsigned>(Tok.getString().lower()) 2894226890Sdim .Case("eq", ARMCC::EQ) 2895226890Sdim .Case("ne", ARMCC::NE) 2896226890Sdim .Case("hs", ARMCC::HS) 2897226890Sdim .Case("cs", ARMCC::HS) 2898226890Sdim .Case("lo", ARMCC::LO) 2899226890Sdim .Case("cc", ARMCC::LO) 2900226890Sdim .Case("mi", ARMCC::MI) 2901226890Sdim .Case("pl", ARMCC::PL) 2902226890Sdim .Case("vs", ARMCC::VS) 2903226890Sdim .Case("vc", ARMCC::VC) 2904226890Sdim .Case("hi", ARMCC::HI) 2905226890Sdim .Case("ls", ARMCC::LS) 2906226890Sdim .Case("ge", ARMCC::GE) 2907226890Sdim .Case("lt", ARMCC::LT) 2908226890Sdim .Case("gt", ARMCC::GT) 2909226890Sdim .Case("le", ARMCC::LE) 2910226890Sdim .Case("al", ARMCC::AL) 2911226890Sdim .Default(~0U); 2912226890Sdim if (CC == ~0U) 2913226890Sdim return MatchOperand_NoMatch; 2914226890Sdim Parser.Lex(); // Eat the token. 2915226890Sdim 2916226890Sdim Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S)); 2917226890Sdim 2918226890Sdim return MatchOperand_Success; 2919226890Sdim} 2920226890Sdim 2921226890Sdim/// 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:: 2925226890SdimparseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 2926218893Sdim SMLoc S = Parser.getTok().getLoc(); 2927218893Sdim const AsmToken &Tok = Parser.getTok(); 2928226890Sdim if (Tok.isNot(AsmToken::Identifier)) 2929226890Sdim 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 2940226890Sdim/// 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:: 2944226890SdimparseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 2945218893Sdim SMLoc S = Parser.getTok().getLoc(); 2946218893Sdim const AsmToken &Tok = Parser.getTok(); 2947226890Sdim if (Tok.isNot(AsmToken::Identifier)) 2948226890Sdim 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 2959226890Sdim/// parseCoprocOptionOperand - Try to parse an coprocessor option operand. 2960226890Sdim/// coproc_option : '{' imm0_255 '}' 2961226890SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 2962226890SdimparseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 2963218893Sdim SMLoc S = Parser.getTok().getLoc(); 2964198090Srdivacky 2965226890Sdim // If this isn't a '{', this isn't a coprocessor immediate operand. 2966226890Sdim if (Parser.getTok().isNot(AsmToken::LCurly)) 2967226890Sdim return MatchOperand_NoMatch; 2968226890Sdim Parser.Lex(); // Eat the '{' 2969218893Sdim 2970226890Sdim const MCExpr *Expr; 2971226890Sdim SMLoc Loc = Parser.getTok().getLoc(); 2972252723Sdim if (getParser().parseExpression(Expr)) { 2973226890Sdim Error(Loc, "illegal expression"); 2974226890Sdim return MatchOperand_ParseFail; 2975226890Sdim } 2976226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr); 2977226890Sdim if (!CE || CE->getValue() < 0 || CE->getValue() > 255) { 2978226890Sdim Error(Loc, "coprocessor option must be an immediate in range [0, 255]"); 2979226890Sdim return MatchOperand_ParseFail; 2980226890Sdim } 2981226890Sdim int Val = CE->getValue(); 2982218893Sdim 2983226890Sdim // Check for and consume the closing '}' 2984226890Sdim if (Parser.getTok().isNot(AsmToken::RCurly)) 2985226890Sdim return MatchOperand_ParseFail; 2986252723Sdim SMLoc E = Parser.getTok().getEndLoc(); 2987226890Sdim Parser.Lex(); // Eat the '}' 2988198090Srdivacky 2989226890Sdim Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E)); 2990226890Sdim return MatchOperand_Success; 2991226890Sdim} 2992198090Srdivacky 2993226890Sdim// For register list parsing, we need to map from raw GPR register numbering 2994226890Sdim// to the enumeration values. The enumeration values aren't sorted by 2995226890Sdim// register number due to our using "sp", "lr" and "pc" as canonical names. 2996226890Sdimstatic unsigned getNextRegister(unsigned Reg) { 2997226890Sdim // If this is a GPR, we need to do it manually, otherwise we can rely 2998226890Sdim // on the sort ordering of the enumeration since the other reg-classes 2999226890Sdim // are sane. 3000226890Sdim if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg)) 3001226890Sdim return Reg + 1; 3002226890Sdim switch(Reg) { 3003235633Sdim default: llvm_unreachable("Invalid GPR number!"); 3004226890Sdim case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2; 3005226890Sdim case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4; 3006226890Sdim case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6; 3007226890Sdim case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8; 3008226890Sdim case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10; 3009226890Sdim case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12; 3010226890Sdim case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR; 3011226890Sdim case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0; 3012198090Srdivacky } 3013226890Sdim} 3014198090Srdivacky 3015235633Sdim// Return the low-subreg of a given Q register. 3016235633Sdimstatic unsigned getDRegFromQReg(unsigned QReg) { 3017235633Sdim switch (QReg) { 3018235633Sdim default: llvm_unreachable("expected a Q register!"); 3019235633Sdim case ARM::Q0: return ARM::D0; 3020235633Sdim case ARM::Q1: return ARM::D2; 3021235633Sdim case ARM::Q2: return ARM::D4; 3022235633Sdim case ARM::Q3: return ARM::D6; 3023235633Sdim case ARM::Q4: return ARM::D8; 3024235633Sdim case ARM::Q5: return ARM::D10; 3025235633Sdim case ARM::Q6: return ARM::D12; 3026235633Sdim case ARM::Q7: return ARM::D14; 3027235633Sdim case ARM::Q8: return ARM::D16; 3028235633Sdim case ARM::Q9: return ARM::D18; 3029235633Sdim case ARM::Q10: return ARM::D20; 3030235633Sdim case ARM::Q11: return ARM::D22; 3031235633Sdim case ARM::Q12: return ARM::D24; 3032235633Sdim case ARM::Q13: return ARM::D26; 3033235633Sdim case ARM::Q14: return ARM::D28; 3034235633Sdim case ARM::Q15: return ARM::D30; 3035235633Sdim } 3036235633Sdim} 3037235633Sdim 3038226890Sdim/// Parse a register list. 3039226890Sdimbool ARMAsmParser:: 3040226890SdimparseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 3041226890Sdim assert(Parser.getTok().is(AsmToken::LCurly) && 3042226890Sdim "Token is not a Left Curly Brace"); 3043226890Sdim SMLoc S = Parser.getTok().getLoc(); 3044226890Sdim Parser.Lex(); // Eat '{' token. 3045226890Sdim SMLoc RegLoc = Parser.getTok().getLoc(); 3046218893Sdim 3047226890Sdim // Check the first register in the list to see what register class 3048226890Sdim // this is a list of. 3049226890Sdim int Reg = tryParseRegister(); 3050226890Sdim if (Reg == -1) 3051226890Sdim return Error(RegLoc, "register expected"); 3052218893Sdim 3053235633Sdim // The reglist instructions have at most 16 registers, so reserve 3054235633Sdim // space for that many. 3055263509Sdim int EReg = 0; 3056263509Sdim SmallVector<std::pair<unsigned, unsigned>, 16> Registers; 3057235633Sdim 3058235633Sdim // Allow Q regs and just interpret them as the two D sub-registers. 3059235633Sdim if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { 3060235633Sdim Reg = getDRegFromQReg(Reg); 3061263509Sdim EReg = MRI->getEncodingValue(Reg); 3062263509Sdim Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg)); 3063235633Sdim ++Reg; 3064235633Sdim } 3065235633Sdim const MCRegisterClass *RC; 3066226890Sdim if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg)) 3067226890Sdim RC = &ARMMCRegisterClasses[ARM::GPRRegClassID]; 3068226890Sdim else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) 3069226890Sdim RC = &ARMMCRegisterClasses[ARM::DPRRegClassID]; 3070226890Sdim else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg)) 3071226890Sdim RC = &ARMMCRegisterClasses[ARM::SPRRegClassID]; 3072226890Sdim else 3073226890Sdim return Error(RegLoc, "invalid register in register list"); 3074218893Sdim 3075235633Sdim // Store the register. 3076263509Sdim EReg = MRI->getEncodingValue(Reg); 3077263509Sdim Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg)); 3078218893Sdim 3079226890Sdim // This starts immediately after the first register token in the list, 3080226890Sdim // so we can see either a comma or a minus (range separator) as a legal 3081226890Sdim // next token. 3082226890Sdim while (Parser.getTok().is(AsmToken::Comma) || 3083226890Sdim Parser.getTok().is(AsmToken::Minus)) { 3084226890Sdim if (Parser.getTok().is(AsmToken::Minus)) { 3085235633Sdim Parser.Lex(); // Eat the minus. 3086252723Sdim SMLoc AfterMinusLoc = Parser.getTok().getLoc(); 3087226890Sdim int EndReg = tryParseRegister(); 3088226890Sdim if (EndReg == -1) 3089252723Sdim return Error(AfterMinusLoc, "register expected"); 3090235633Sdim // Allow Q regs and just interpret them as the two D sub-registers. 3091235633Sdim if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg)) 3092235633Sdim EndReg = getDRegFromQReg(EndReg) + 1; 3093226890Sdim // If the register is the same as the start reg, there's nothing 3094226890Sdim // more to do. 3095226890Sdim if (Reg == EndReg) 3096226890Sdim continue; 3097226890Sdim // The register must be in the same register class as the first. 3098226890Sdim if (!RC->contains(EndReg)) 3099252723Sdim return Error(AfterMinusLoc, "invalid register in register list"); 3100226890Sdim // Ranges must go from low to high. 3101245431Sdim if (MRI->getEncodingValue(Reg) > MRI->getEncodingValue(EndReg)) 3102252723Sdim return Error(AfterMinusLoc, "bad range in register list"); 3103218893Sdim 3104226890Sdim // Add all the registers in the range to the register list. 3105226890Sdim while (Reg != EndReg) { 3106226890Sdim Reg = getNextRegister(Reg); 3107263509Sdim EReg = MRI->getEncodingValue(Reg); 3108263509Sdim Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg)); 3109226890Sdim } 3110226890Sdim continue; 3111218893Sdim } 3112226890Sdim Parser.Lex(); // Eat the comma. 3113226890Sdim RegLoc = Parser.getTok().getLoc(); 3114226890Sdim int OldReg = Reg; 3115235633Sdim const AsmToken RegTok = Parser.getTok(); 3116226890Sdim Reg = tryParseRegister(); 3117226890Sdim if (Reg == -1) 3118226890Sdim return Error(RegLoc, "register expected"); 3119235633Sdim // Allow Q regs and just interpret them as the two D sub-registers. 3120235633Sdim bool isQReg = false; 3121235633Sdim if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { 3122235633Sdim Reg = getDRegFromQReg(Reg); 3123235633Sdim isQReg = true; 3124235633Sdim } 3125226890Sdim // The register must be in the same register class as the first. 3126226890Sdim if (!RC->contains(Reg)) 3127226890Sdim return Error(RegLoc, "invalid register in register list"); 3128226890Sdim // List must be monotonically increasing. 3129245431Sdim if (MRI->getEncodingValue(Reg) < MRI->getEncodingValue(OldReg)) { 3130235633Sdim if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg)) 3131235633Sdim Warning(RegLoc, "register list not in ascending order"); 3132235633Sdim else 3133235633Sdim return Error(RegLoc, "register list not in ascending order"); 3134235633Sdim } 3135245431Sdim if (MRI->getEncodingValue(Reg) == MRI->getEncodingValue(OldReg)) { 3136235633Sdim Warning(RegLoc, "duplicated register (" + RegTok.getString() + 3137235633Sdim ") in register list"); 3138235633Sdim continue; 3139235633Sdim } 3140226890Sdim // VFP register lists must also be contiguous. 3141226890Sdim if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] && 3142226890Sdim Reg != OldReg + 1) 3143226890Sdim return Error(RegLoc, "non-contiguous register range"); 3144263509Sdim EReg = MRI->getEncodingValue(Reg); 3145263509Sdim Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg)); 3146263509Sdim if (isQReg) { 3147263509Sdim EReg = MRI->getEncodingValue(++Reg); 3148263509Sdim Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg)); 3149263509Sdim } 3150226890Sdim } 3151218893Sdim 3152226890Sdim if (Parser.getTok().isNot(AsmToken::RCurly)) 3153252723Sdim return Error(Parser.getTok().getLoc(), "'}' expected"); 3154252723Sdim SMLoc E = Parser.getTok().getEndLoc(); 3155226890Sdim Parser.Lex(); // Eat '}' token. 3156218893Sdim 3157235633Sdim // Push the register list operand. 3158218893Sdim Operands.push_back(ARMOperand::CreateRegList(Registers, S, E)); 3159235633Sdim 3160235633Sdim // The ARM system instruction variants for LDM/STM have a '^' token here. 3161235633Sdim if (Parser.getTok().is(AsmToken::Caret)) { 3162235633Sdim Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc())); 3163235633Sdim Parser.Lex(); // Eat '^' token. 3164235633Sdim } 3165235633Sdim 3166198090Srdivacky return false; 3167198090Srdivacky} 3168198090Srdivacky 3169235633Sdim// Helper function to parse the lane index for vector lists. 3170235633SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 3171252723SdimparseVectorLane(VectorLaneTy &LaneKind, unsigned &Index, SMLoc &EndLoc) { 3172235633Sdim Index = 0; // Always return a defined index value. 3173235633Sdim if (Parser.getTok().is(AsmToken::LBrac)) { 3174235633Sdim Parser.Lex(); // Eat the '['. 3175235633Sdim if (Parser.getTok().is(AsmToken::RBrac)) { 3176235633Sdim // "Dn[]" is the 'all lanes' syntax. 3177235633Sdim LaneKind = AllLanes; 3178252723Sdim EndLoc = Parser.getTok().getEndLoc(); 3179235633Sdim Parser.Lex(); // Eat the ']'. 3180235633Sdim return MatchOperand_Success; 3181235633Sdim } 3182235633Sdim 3183235633Sdim // There's an optional '#' token here. Normally there wouldn't be, but 3184235633Sdim // inline assemble puts one in, and it's friendly to accept that. 3185235633Sdim if (Parser.getTok().is(AsmToken::Hash)) 3186263509Sdim Parser.Lex(); // Eat '#' or '$'. 3187235633Sdim 3188235633Sdim const MCExpr *LaneIndex; 3189235633Sdim SMLoc Loc = Parser.getTok().getLoc(); 3190252723Sdim if (getParser().parseExpression(LaneIndex)) { 3191235633Sdim Error(Loc, "illegal expression"); 3192235633Sdim return MatchOperand_ParseFail; 3193235633Sdim } 3194235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex); 3195235633Sdim if (!CE) { 3196235633Sdim Error(Loc, "lane index must be empty or an integer"); 3197235633Sdim return MatchOperand_ParseFail; 3198235633Sdim } 3199235633Sdim if (Parser.getTok().isNot(AsmToken::RBrac)) { 3200235633Sdim Error(Parser.getTok().getLoc(), "']' expected"); 3201235633Sdim return MatchOperand_ParseFail; 3202235633Sdim } 3203252723Sdim EndLoc = Parser.getTok().getEndLoc(); 3204235633Sdim Parser.Lex(); // Eat the ']'. 3205235633Sdim int64_t Val = CE->getValue(); 3206235633Sdim 3207235633Sdim // FIXME: Make this range check context sensitive for .8, .16, .32. 3208235633Sdim if (Val < 0 || Val > 7) { 3209235633Sdim Error(Parser.getTok().getLoc(), "lane index out of range"); 3210235633Sdim return MatchOperand_ParseFail; 3211235633Sdim } 3212235633Sdim Index = Val; 3213235633Sdim LaneKind = IndexedLane; 3214235633Sdim return MatchOperand_Success; 3215235633Sdim } 3216235633Sdim LaneKind = NoLanes; 3217235633Sdim return MatchOperand_Success; 3218235633Sdim} 3219235633Sdim 3220235633Sdim// parse a vector register list 3221235633SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 3222235633SdimparseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 3223235633Sdim VectorLaneTy LaneKind; 3224235633Sdim unsigned LaneIndex; 3225235633Sdim SMLoc S = Parser.getTok().getLoc(); 3226235633Sdim // As an extension (to match gas), support a plain D register or Q register 3227235633Sdim // (without encosing curly braces) as a single or double entry list, 3228235633Sdim // respectively. 3229235633Sdim if (Parser.getTok().is(AsmToken::Identifier)) { 3230252723Sdim SMLoc E = Parser.getTok().getEndLoc(); 3231235633Sdim int Reg = tryParseRegister(); 3232235633Sdim if (Reg == -1) 3233235633Sdim return MatchOperand_NoMatch; 3234235633Sdim if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) { 3235252723Sdim OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex, E); 3236235633Sdim if (Res != MatchOperand_Success) 3237235633Sdim return Res; 3238235633Sdim switch (LaneKind) { 3239235633Sdim case NoLanes: 3240235633Sdim Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E)); 3241235633Sdim break; 3242235633Sdim case AllLanes: 3243235633Sdim Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false, 3244235633Sdim S, E)); 3245235633Sdim break; 3246235633Sdim case IndexedLane: 3247235633Sdim Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1, 3248235633Sdim LaneIndex, 3249235633Sdim false, S, E)); 3250235633Sdim break; 3251235633Sdim } 3252235633Sdim return MatchOperand_Success; 3253235633Sdim } 3254235633Sdim if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { 3255235633Sdim Reg = getDRegFromQReg(Reg); 3256252723Sdim OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex, E); 3257235633Sdim if (Res != MatchOperand_Success) 3258235633Sdim return Res; 3259235633Sdim switch (LaneKind) { 3260235633Sdim case NoLanes: 3261235633Sdim Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0, 3262235633Sdim &ARMMCRegisterClasses[ARM::DPairRegClassID]); 3263235633Sdim Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E)); 3264235633Sdim break; 3265235633Sdim case AllLanes: 3266235633Sdim Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0, 3267235633Sdim &ARMMCRegisterClasses[ARM::DPairRegClassID]); 3268235633Sdim Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false, 3269235633Sdim S, E)); 3270235633Sdim break; 3271235633Sdim case IndexedLane: 3272235633Sdim Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2, 3273235633Sdim LaneIndex, 3274235633Sdim false, S, E)); 3275235633Sdim break; 3276235633Sdim } 3277235633Sdim return MatchOperand_Success; 3278235633Sdim } 3279235633Sdim Error(S, "vector register expected"); 3280235633Sdim return MatchOperand_ParseFail; 3281235633Sdim } 3282235633Sdim 3283235633Sdim if (Parser.getTok().isNot(AsmToken::LCurly)) 3284235633Sdim return MatchOperand_NoMatch; 3285235633Sdim 3286235633Sdim Parser.Lex(); // Eat '{' token. 3287235633Sdim SMLoc RegLoc = Parser.getTok().getLoc(); 3288235633Sdim 3289235633Sdim int Reg = tryParseRegister(); 3290235633Sdim if (Reg == -1) { 3291235633Sdim Error(RegLoc, "register expected"); 3292235633Sdim return MatchOperand_ParseFail; 3293235633Sdim } 3294235633Sdim unsigned Count = 1; 3295235633Sdim int Spacing = 0; 3296235633Sdim unsigned FirstReg = Reg; 3297235633Sdim // The list is of D registers, but we also allow Q regs and just interpret 3298235633Sdim // them as the two D sub-registers. 3299235633Sdim if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { 3300235633Sdim FirstReg = Reg = getDRegFromQReg(Reg); 3301235633Sdim Spacing = 1; // double-spacing requires explicit D registers, otherwise 3302235633Sdim // it's ambiguous with four-register single spaced. 3303235633Sdim ++Reg; 3304235633Sdim ++Count; 3305235633Sdim } 3306252723Sdim 3307252723Sdim SMLoc E; 3308252723Sdim if (parseVectorLane(LaneKind, LaneIndex, E) != MatchOperand_Success) 3309235633Sdim return MatchOperand_ParseFail; 3310235633Sdim 3311235633Sdim while (Parser.getTok().is(AsmToken::Comma) || 3312235633Sdim Parser.getTok().is(AsmToken::Minus)) { 3313235633Sdim if (Parser.getTok().is(AsmToken::Minus)) { 3314235633Sdim if (!Spacing) 3315235633Sdim Spacing = 1; // Register range implies a single spaced list. 3316235633Sdim else if (Spacing == 2) { 3317235633Sdim Error(Parser.getTok().getLoc(), 3318235633Sdim "sequential registers in double spaced list"); 3319235633Sdim return MatchOperand_ParseFail; 3320235633Sdim } 3321235633Sdim Parser.Lex(); // Eat the minus. 3322252723Sdim SMLoc AfterMinusLoc = Parser.getTok().getLoc(); 3323235633Sdim int EndReg = tryParseRegister(); 3324235633Sdim if (EndReg == -1) { 3325252723Sdim Error(AfterMinusLoc, "register expected"); 3326235633Sdim return MatchOperand_ParseFail; 3327235633Sdim } 3328235633Sdim // Allow Q regs and just interpret them as the two D sub-registers. 3329235633Sdim if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg)) 3330235633Sdim EndReg = getDRegFromQReg(EndReg) + 1; 3331235633Sdim // If the register is the same as the start reg, there's nothing 3332235633Sdim // more to do. 3333235633Sdim if (Reg == EndReg) 3334235633Sdim continue; 3335235633Sdim // The register must be in the same register class as the first. 3336235633Sdim if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) { 3337252723Sdim Error(AfterMinusLoc, "invalid register in register list"); 3338235633Sdim return MatchOperand_ParseFail; 3339235633Sdim } 3340235633Sdim // Ranges must go from low to high. 3341235633Sdim if (Reg > EndReg) { 3342252723Sdim Error(AfterMinusLoc, "bad range in register list"); 3343235633Sdim return MatchOperand_ParseFail; 3344235633Sdim } 3345235633Sdim // Parse the lane specifier if present. 3346235633Sdim VectorLaneTy NextLaneKind; 3347235633Sdim unsigned NextLaneIndex; 3348252723Sdim if (parseVectorLane(NextLaneKind, NextLaneIndex, E) != 3349252723Sdim MatchOperand_Success) 3350235633Sdim return MatchOperand_ParseFail; 3351235633Sdim if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) { 3352252723Sdim Error(AfterMinusLoc, "mismatched lane index in register list"); 3353235633Sdim return MatchOperand_ParseFail; 3354235633Sdim } 3355235633Sdim 3356235633Sdim // Add all the registers in the range to the register list. 3357235633Sdim Count += EndReg - Reg; 3358235633Sdim Reg = EndReg; 3359235633Sdim continue; 3360235633Sdim } 3361235633Sdim Parser.Lex(); // Eat the comma. 3362235633Sdim RegLoc = Parser.getTok().getLoc(); 3363235633Sdim int OldReg = Reg; 3364235633Sdim Reg = tryParseRegister(); 3365235633Sdim if (Reg == -1) { 3366235633Sdim Error(RegLoc, "register expected"); 3367235633Sdim return MatchOperand_ParseFail; 3368235633Sdim } 3369235633Sdim // vector register lists must be contiguous. 3370235633Sdim // It's OK to use the enumeration values directly here rather, as the 3371235633Sdim // VFP register classes have the enum sorted properly. 3372235633Sdim // 3373235633Sdim // The list is of D registers, but we also allow Q regs and just interpret 3374235633Sdim // them as the two D sub-registers. 3375235633Sdim if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { 3376235633Sdim if (!Spacing) 3377235633Sdim Spacing = 1; // Register range implies a single spaced list. 3378235633Sdim else if (Spacing == 2) { 3379235633Sdim Error(RegLoc, 3380235633Sdim "invalid register in double-spaced list (must be 'D' register')"); 3381235633Sdim return MatchOperand_ParseFail; 3382235633Sdim } 3383235633Sdim Reg = getDRegFromQReg(Reg); 3384235633Sdim if (Reg != OldReg + 1) { 3385235633Sdim Error(RegLoc, "non-contiguous register range"); 3386235633Sdim return MatchOperand_ParseFail; 3387235633Sdim } 3388235633Sdim ++Reg; 3389235633Sdim Count += 2; 3390235633Sdim // Parse the lane specifier if present. 3391235633Sdim VectorLaneTy NextLaneKind; 3392235633Sdim unsigned NextLaneIndex; 3393252723Sdim SMLoc LaneLoc = Parser.getTok().getLoc(); 3394252723Sdim if (parseVectorLane(NextLaneKind, NextLaneIndex, E) != 3395252723Sdim MatchOperand_Success) 3396235633Sdim return MatchOperand_ParseFail; 3397235633Sdim if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) { 3398252723Sdim Error(LaneLoc, "mismatched lane index in register list"); 3399235633Sdim return MatchOperand_ParseFail; 3400235633Sdim } 3401235633Sdim continue; 3402235633Sdim } 3403235633Sdim // Normal D register. 3404235633Sdim // Figure out the register spacing (single or double) of the list if 3405235633Sdim // we don't know it already. 3406235633Sdim if (!Spacing) 3407235633Sdim Spacing = 1 + (Reg == OldReg + 2); 3408235633Sdim 3409235633Sdim // Just check that it's contiguous and keep going. 3410235633Sdim if (Reg != OldReg + Spacing) { 3411235633Sdim Error(RegLoc, "non-contiguous register range"); 3412235633Sdim return MatchOperand_ParseFail; 3413235633Sdim } 3414235633Sdim ++Count; 3415235633Sdim // Parse the lane specifier if present. 3416235633Sdim VectorLaneTy NextLaneKind; 3417235633Sdim unsigned NextLaneIndex; 3418235633Sdim SMLoc EndLoc = Parser.getTok().getLoc(); 3419252723Sdim if (parseVectorLane(NextLaneKind, NextLaneIndex, E) != MatchOperand_Success) 3420235633Sdim return MatchOperand_ParseFail; 3421235633Sdim if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) { 3422235633Sdim Error(EndLoc, "mismatched lane index in register list"); 3423235633Sdim return MatchOperand_ParseFail; 3424235633Sdim } 3425235633Sdim } 3426235633Sdim 3427235633Sdim if (Parser.getTok().isNot(AsmToken::RCurly)) { 3428252723Sdim Error(Parser.getTok().getLoc(), "'}' expected"); 3429235633Sdim return MatchOperand_ParseFail; 3430235633Sdim } 3431252723Sdim E = Parser.getTok().getEndLoc(); 3432235633Sdim Parser.Lex(); // Eat '}' token. 3433235633Sdim 3434235633Sdim switch (LaneKind) { 3435235633Sdim case NoLanes: 3436235633Sdim // Two-register operands have been converted to the 3437235633Sdim // composite register classes. 3438235633Sdim if (Count == 2) { 3439235633Sdim const MCRegisterClass *RC = (Spacing == 1) ? 3440235633Sdim &ARMMCRegisterClasses[ARM::DPairRegClassID] : 3441235633Sdim &ARMMCRegisterClasses[ARM::DPairSpcRegClassID]; 3442235633Sdim FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC); 3443235633Sdim } 3444235633Sdim 3445235633Sdim Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, 3446235633Sdim (Spacing == 2), S, E)); 3447235633Sdim break; 3448235633Sdim case AllLanes: 3449235633Sdim // Two-register operands have been converted to the 3450235633Sdim // composite register classes. 3451235633Sdim if (Count == 2) { 3452235633Sdim const MCRegisterClass *RC = (Spacing == 1) ? 3453235633Sdim &ARMMCRegisterClasses[ARM::DPairRegClassID] : 3454235633Sdim &ARMMCRegisterClasses[ARM::DPairSpcRegClassID]; 3455235633Sdim FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC); 3456235633Sdim } 3457235633Sdim Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count, 3458235633Sdim (Spacing == 2), 3459235633Sdim S, E)); 3460235633Sdim break; 3461235633Sdim case IndexedLane: 3462235633Sdim Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count, 3463235633Sdim LaneIndex, 3464235633Sdim (Spacing == 2), 3465235633Sdim S, E)); 3466235633Sdim break; 3467235633Sdim } 3468235633Sdim return MatchOperand_Success; 3469235633Sdim} 3470235633Sdim 3471226890Sdim/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options. 3472218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 3473226890SdimparseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 3474218893Sdim SMLoc S = Parser.getTok().getLoc(); 3475218893Sdim const AsmToken &Tok = Parser.getTok(); 3476245431Sdim unsigned Opt; 3477218893Sdim 3478245431Sdim if (Tok.is(AsmToken::Identifier)) { 3479245431Sdim StringRef OptStr = Tok.getString(); 3480218893Sdim 3481245431Sdim Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()).lower()) 3482245431Sdim .Case("sy", ARM_MB::SY) 3483245431Sdim .Case("st", ARM_MB::ST) 3484263509Sdim .Case("ld", ARM_MB::LD) 3485245431Sdim .Case("sh", ARM_MB::ISH) 3486245431Sdim .Case("ish", ARM_MB::ISH) 3487245431Sdim .Case("shst", ARM_MB::ISHST) 3488245431Sdim .Case("ishst", ARM_MB::ISHST) 3489263509Sdim .Case("ishld", ARM_MB::ISHLD) 3490245431Sdim .Case("nsh", ARM_MB::NSH) 3491245431Sdim .Case("un", ARM_MB::NSH) 3492245431Sdim .Case("nshst", ARM_MB::NSHST) 3493263509Sdim .Case("nshld", ARM_MB::NSHLD) 3494245431Sdim .Case("unst", ARM_MB::NSHST) 3495245431Sdim .Case("osh", ARM_MB::OSH) 3496245431Sdim .Case("oshst", ARM_MB::OSHST) 3497263509Sdim .Case("oshld", ARM_MB::OSHLD) 3498245431Sdim .Default(~0U); 3499218893Sdim 3500263509Sdim // ishld, oshld, nshld and ld are only available from ARMv8. 3501263509Sdim if (!hasV8Ops() && (Opt == ARM_MB::ISHLD || Opt == ARM_MB::OSHLD || 3502263509Sdim Opt == ARM_MB::NSHLD || Opt == ARM_MB::LD)) 3503263509Sdim Opt = ~0U; 3504263509Sdim 3505245431Sdim if (Opt == ~0U) 3506245431Sdim return MatchOperand_NoMatch; 3507245431Sdim 3508245431Sdim Parser.Lex(); // Eat identifier token. 3509245431Sdim } else if (Tok.is(AsmToken::Hash) || 3510245431Sdim Tok.is(AsmToken::Dollar) || 3511245431Sdim Tok.is(AsmToken::Integer)) { 3512245431Sdim if (Parser.getTok().isNot(AsmToken::Integer)) 3513263509Sdim Parser.Lex(); // Eat '#' or '$'. 3514245431Sdim SMLoc Loc = Parser.getTok().getLoc(); 3515245431Sdim 3516245431Sdim const MCExpr *MemBarrierID; 3517252723Sdim if (getParser().parseExpression(MemBarrierID)) { 3518245431Sdim Error(Loc, "illegal expression"); 3519245431Sdim return MatchOperand_ParseFail; 3520245431Sdim } 3521245431Sdim 3522245431Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(MemBarrierID); 3523245431Sdim if (!CE) { 3524245431Sdim Error(Loc, "constant expression expected"); 3525245431Sdim return MatchOperand_ParseFail; 3526245431Sdim } 3527245431Sdim 3528245431Sdim int Val = CE->getValue(); 3529245431Sdim if (Val & ~0xf) { 3530245431Sdim Error(Loc, "immediate value out of range"); 3531245431Sdim return MatchOperand_ParseFail; 3532245431Sdim } 3533245431Sdim 3534245431Sdim Opt = ARM_MB::RESERVED_0 + Val; 3535245431Sdim } else 3536245431Sdim return MatchOperand_ParseFail; 3537245431Sdim 3538218893Sdim Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S)); 3539218893Sdim return MatchOperand_Success; 3540218893Sdim} 3541218893Sdim 3542263509Sdim/// parseInstSyncBarrierOptOperand - Try to parse ISB inst sync barrier options. 3543263509SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 3544263509SdimparseInstSyncBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 3545263509Sdim SMLoc S = Parser.getTok().getLoc(); 3546263509Sdim const AsmToken &Tok = Parser.getTok(); 3547263509Sdim unsigned Opt; 3548263509Sdim 3549263509Sdim if (Tok.is(AsmToken::Identifier)) { 3550263509Sdim StringRef OptStr = Tok.getString(); 3551263509Sdim 3552263509Sdim if (OptStr.equals_lower("sy")) 3553263509Sdim Opt = ARM_ISB::SY; 3554263509Sdim else 3555263509Sdim return MatchOperand_NoMatch; 3556263509Sdim 3557263509Sdim Parser.Lex(); // Eat identifier token. 3558263509Sdim } else if (Tok.is(AsmToken::Hash) || 3559263509Sdim Tok.is(AsmToken::Dollar) || 3560263509Sdim Tok.is(AsmToken::Integer)) { 3561263509Sdim if (Parser.getTok().isNot(AsmToken::Integer)) 3562263509Sdim Parser.Lex(); // Eat '#' or '$'. 3563263509Sdim SMLoc Loc = Parser.getTok().getLoc(); 3564263509Sdim 3565263509Sdim const MCExpr *ISBarrierID; 3566263509Sdim if (getParser().parseExpression(ISBarrierID)) { 3567263509Sdim Error(Loc, "illegal expression"); 3568263509Sdim return MatchOperand_ParseFail; 3569263509Sdim } 3570263509Sdim 3571263509Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ISBarrierID); 3572263509Sdim if (!CE) { 3573263509Sdim Error(Loc, "constant expression expected"); 3574263509Sdim return MatchOperand_ParseFail; 3575263509Sdim } 3576263509Sdim 3577263509Sdim int Val = CE->getValue(); 3578263509Sdim if (Val & ~0xf) { 3579263509Sdim Error(Loc, "immediate value out of range"); 3580263509Sdim return MatchOperand_ParseFail; 3581263509Sdim } 3582263509Sdim 3583263509Sdim Opt = ARM_ISB::RESERVED_0 + Val; 3584263509Sdim } else 3585263509Sdim return MatchOperand_ParseFail; 3586263509Sdim 3587263509Sdim Operands.push_back(ARMOperand::CreateInstSyncBarrierOpt( 3588263509Sdim (ARM_ISB::InstSyncBOpt)Opt, S)); 3589263509Sdim return MatchOperand_Success; 3590263509Sdim} 3591263509Sdim 3592263509Sdim 3593226890Sdim/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction. 3594218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 3595226890SdimparseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 3596218893Sdim SMLoc S = Parser.getTok().getLoc(); 3597218893Sdim const AsmToken &Tok = Parser.getTok(); 3598245431Sdim if (!Tok.is(AsmToken::Identifier)) 3599245431Sdim return MatchOperand_NoMatch; 3600218893Sdim StringRef IFlagsStr = Tok.getString(); 3601218893Sdim 3602226890Sdim // An iflags string of "none" is interpreted to mean that none of the AIF 3603226890Sdim // bits are set. Not a terribly useful instruction, but a valid encoding. 3604218893Sdim unsigned IFlags = 0; 3605226890Sdim if (IFlagsStr != "none") { 3606226890Sdim for (int i = 0, e = IFlagsStr.size(); i != e; ++i) { 3607226890Sdim unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1)) 3608226890Sdim .Case("a", ARM_PROC::A) 3609226890Sdim .Case("i", ARM_PROC::I) 3610226890Sdim .Case("f", ARM_PROC::F) 3611226890Sdim .Default(~0U); 3612218893Sdim 3613226890Sdim // If some specific iflag is already set, it means that some letter is 3614226890Sdim // present more than once, this is not acceptable. 3615226890Sdim if (Flag == ~0U || (IFlags & Flag)) 3616226890Sdim return MatchOperand_NoMatch; 3617218893Sdim 3618226890Sdim IFlags |= Flag; 3619226890Sdim } 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 3627226890Sdim/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction. 3628218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 3629226890SdimparseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 3630218893Sdim SMLoc S = Parser.getTok().getLoc(); 3631218893Sdim const AsmToken &Tok = Parser.getTok(); 3632245431Sdim if (!Tok.is(AsmToken::Identifier)) 3633245431Sdim return MatchOperand_NoMatch; 3634218893Sdim StringRef Mask = Tok.getString(); 3635218893Sdim 3636226890Sdim if (isMClass()) { 3637226890Sdim // See ARMv6-M 10.1.1 3638235633Sdim std::string Name = Mask.lower(); 3639235633Sdim unsigned FlagsVal = StringSwitch<unsigned>(Name) 3640245431Sdim // Note: in the documentation: 3641245431Sdim // ARM deprecates using MSR APSR without a _<bits> qualifier as an alias 3642245431Sdim // for MSR APSR_nzcvq. 3643245431Sdim // but we do make it an alias here. This is so to get the "mask encoding" 3644245431Sdim // bits correct on MSR APSR writes. 3645245431Sdim // 3646245431Sdim // FIXME: Note the 0xc00 "mask encoding" bits version of the registers 3647245431Sdim // should really only be allowed when writing a special register. Note 3648245431Sdim // they get dropped in the MRS instruction reading a special register as 3649245431Sdim // the SYSm field is only 8 bits. 3650245431Sdim // 3651245431Sdim // FIXME: the _g and _nzcvqg versions are only allowed if the processor 3652245431Sdim // includes the DSP extension but that is not checked. 3653245431Sdim .Case("apsr", 0x800) 3654245431Sdim .Case("apsr_nzcvq", 0x800) 3655245431Sdim .Case("apsr_g", 0x400) 3656245431Sdim .Case("apsr_nzcvqg", 0xc00) 3657245431Sdim .Case("iapsr", 0x801) 3658245431Sdim .Case("iapsr_nzcvq", 0x801) 3659245431Sdim .Case("iapsr_g", 0x401) 3660245431Sdim .Case("iapsr_nzcvqg", 0xc01) 3661245431Sdim .Case("eapsr", 0x802) 3662245431Sdim .Case("eapsr_nzcvq", 0x802) 3663245431Sdim .Case("eapsr_g", 0x402) 3664245431Sdim .Case("eapsr_nzcvqg", 0xc02) 3665245431Sdim .Case("xpsr", 0x803) 3666245431Sdim .Case("xpsr_nzcvq", 0x803) 3667245431Sdim .Case("xpsr_g", 0x403) 3668245431Sdim .Case("xpsr_nzcvqg", 0xc03) 3669245431Sdim .Case("ipsr", 0x805) 3670245431Sdim .Case("epsr", 0x806) 3671245431Sdim .Case("iepsr", 0x807) 3672245431Sdim .Case("msp", 0x808) 3673245431Sdim .Case("psp", 0x809) 3674245431Sdim .Case("primask", 0x810) 3675245431Sdim .Case("basepri", 0x811) 3676245431Sdim .Case("basepri_max", 0x812) 3677245431Sdim .Case("faultmask", 0x813) 3678245431Sdim .Case("control", 0x814) 3679226890Sdim .Default(~0U); 3680235633Sdim 3681226890Sdim if (FlagsVal == ~0U) 3682226890Sdim return MatchOperand_NoMatch; 3683226890Sdim 3684245431Sdim if (!hasV7Ops() && FlagsVal >= 0x811 && FlagsVal <= 0x813) 3685226890Sdim // basepri, basepri_max and faultmask only valid for V7m. 3686226890Sdim return MatchOperand_NoMatch; 3687235633Sdim 3688226890Sdim Parser.Lex(); // Eat identifier token. 3689226890Sdim Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S)); 3690226890Sdim return MatchOperand_Success; 3691226890Sdim } 3692226890Sdim 3693218893Sdim // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf" 3694218893Sdim size_t Start = 0, Next = Mask.find('_'); 3695218893Sdim StringRef Flags = ""; 3696235633Sdim 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) 3707226890Sdim .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 3716226890Sdim FlagsVal = 8; // No flag 3717218893Sdim } 3718218893Sdim } else if (SpecReg == "cpsr" || SpecReg == "spsr") { 3719235633Sdim // cpsr_all is an alias for cpsr_fc, as is plain cpsr. 3720235633Sdim 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 3739235633Sdim // Special register without flags is NOT equivalent to "fc" flags. 3740235633Sdim // NOTE: This is a divergence from gas' behavior. Uncommenting the following 3741235633Sdim // two lines would enable gas compatibility at the expense of breaking 3742235633Sdim // round-tripping. 3743235633Sdim // 3744235633Sdim // if (!FlagsVal) 3745235633Sdim // 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:: 3757226890SdimparsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op, 3758226890Sdim int Low, int High) { 3759226890Sdim const AsmToken &Tok = Parser.getTok(); 3760226890Sdim if (Tok.isNot(AsmToken::Identifier)) { 3761226890Sdim Error(Parser.getTok().getLoc(), Op + " operand expected."); 3762226890Sdim return MatchOperand_ParseFail; 3763226890Sdim } 3764226890Sdim StringRef ShiftName = Tok.getString(); 3765235633Sdim std::string LowerOp = Op.lower(); 3766235633Sdim std::string UpperOp = Op.upper(); 3767226890Sdim if (ShiftName != LowerOp && ShiftName != UpperOp) { 3768226890Sdim Error(Parser.getTok().getLoc(), Op + " operand expected."); 3769226890Sdim return MatchOperand_ParseFail; 3770226890Sdim } 3771226890Sdim Parser.Lex(); // Eat shift type token. 3772221345Sdim 3773226890Sdim // There must be a '#' and a shift amount. 3774235633Sdim if (Parser.getTok().isNot(AsmToken::Hash) && 3775235633Sdim Parser.getTok().isNot(AsmToken::Dollar)) { 3776226890Sdim Error(Parser.getTok().getLoc(), "'#' expected"); 3777226890Sdim return MatchOperand_ParseFail; 3778226890Sdim } 3779226890Sdim Parser.Lex(); // Eat hash token. 3780221345Sdim 3781226890Sdim const MCExpr *ShiftAmount; 3782226890Sdim SMLoc Loc = Parser.getTok().getLoc(); 3783252723Sdim SMLoc EndLoc; 3784252723Sdim if (getParser().parseExpression(ShiftAmount, EndLoc)) { 3785226890Sdim Error(Loc, "illegal expression"); 3786226890Sdim return MatchOperand_ParseFail; 3787226890Sdim } 3788226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount); 3789226890Sdim if (!CE) { 3790226890Sdim Error(Loc, "constant expression expected"); 3791226890Sdim return MatchOperand_ParseFail; 3792226890Sdim } 3793226890Sdim int Val = CE->getValue(); 3794226890Sdim if (Val < Low || Val > High) { 3795226890Sdim Error(Loc, "immediate value out of range"); 3796226890Sdim return MatchOperand_ParseFail; 3797226890Sdim } 3798226890Sdim 3799252723Sdim Operands.push_back(ARMOperand::CreateImm(CE, Loc, EndLoc)); 3800226890Sdim 3801221345Sdim return MatchOperand_Success; 3802221345Sdim} 3803221345Sdim 3804221345SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 3805226890SdimparseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 3806226890Sdim const AsmToken &Tok = Parser.getTok(); 3807226890Sdim SMLoc S = Tok.getLoc(); 3808226890Sdim if (Tok.isNot(AsmToken::Identifier)) { 3809252723Sdim Error(S, "'be' or 'le' operand expected"); 3810226890Sdim return MatchOperand_ParseFail; 3811226890Sdim } 3812263509Sdim int Val = StringSwitch<int>(Tok.getString().lower()) 3813226890Sdim .Case("be", 1) 3814226890Sdim .Case("le", 0) 3815226890Sdim .Default(-1); 3816226890Sdim Parser.Lex(); // Eat the token. 3817221345Sdim 3818226890Sdim if (Val == -1) { 3819252723Sdim Error(S, "'be' or 'le' operand expected"); 3820226890Sdim return MatchOperand_ParseFail; 3821226890Sdim } 3822226890Sdim Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val, 3823226890Sdim getContext()), 3824252723Sdim S, Tok.getEndLoc())); 3825226890Sdim return MatchOperand_Success; 3826226890Sdim} 3827226890Sdim 3828226890Sdim/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT 3829226890Sdim/// instructions. Legal values are: 3830226890Sdim/// lsl #n 'n' in [0,31] 3831226890Sdim/// asr #n 'n' in [1,32] 3832226890Sdim/// n == 32 encoded as n == 0. 3833226890SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 3834226890SdimparseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 3835226890Sdim const AsmToken &Tok = Parser.getTok(); 3836226890Sdim SMLoc S = Tok.getLoc(); 3837226890Sdim if (Tok.isNot(AsmToken::Identifier)) { 3838226890Sdim Error(S, "shift operator 'asr' or 'lsl' expected"); 3839226890Sdim return MatchOperand_ParseFail; 3840226890Sdim } 3841226890Sdim StringRef ShiftName = Tok.getString(); 3842226890Sdim bool isASR; 3843226890Sdim if (ShiftName == "lsl" || ShiftName == "LSL") 3844226890Sdim isASR = false; 3845226890Sdim else if (ShiftName == "asr" || ShiftName == "ASR") 3846226890Sdim isASR = true; 3847226890Sdim else { 3848226890Sdim Error(S, "shift operator 'asr' or 'lsl' expected"); 3849226890Sdim return MatchOperand_ParseFail; 3850226890Sdim } 3851226890Sdim Parser.Lex(); // Eat the operator. 3852226890Sdim 3853226890Sdim // A '#' and a shift amount. 3854235633Sdim if (Parser.getTok().isNot(AsmToken::Hash) && 3855235633Sdim Parser.getTok().isNot(AsmToken::Dollar)) { 3856226890Sdim Error(Parser.getTok().getLoc(), "'#' expected"); 3857226890Sdim return MatchOperand_ParseFail; 3858226890Sdim } 3859226890Sdim Parser.Lex(); // Eat hash token. 3860252723Sdim SMLoc ExLoc = Parser.getTok().getLoc(); 3861226890Sdim 3862226890Sdim const MCExpr *ShiftAmount; 3863252723Sdim SMLoc EndLoc; 3864252723Sdim if (getParser().parseExpression(ShiftAmount, EndLoc)) { 3865252723Sdim Error(ExLoc, "malformed shift expression"); 3866226890Sdim return MatchOperand_ParseFail; 3867226890Sdim } 3868226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount); 3869226890Sdim if (!CE) { 3870252723Sdim Error(ExLoc, "shift amount must be an immediate"); 3871226890Sdim return MatchOperand_ParseFail; 3872226890Sdim } 3873226890Sdim 3874226890Sdim int64_t Val = CE->getValue(); 3875226890Sdim if (isASR) { 3876226890Sdim // Shift amount must be in [1,32] 3877226890Sdim if (Val < 1 || Val > 32) { 3878252723Sdim Error(ExLoc, "'asr' shift amount must be in range [1,32]"); 3879226890Sdim return MatchOperand_ParseFail; 3880226890Sdim } 3881226890Sdim // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode. 3882226890Sdim if (isThumb() && Val == 32) { 3883252723Sdim Error(ExLoc, "'asr #32' shift amount not allowed in Thumb mode"); 3884226890Sdim return MatchOperand_ParseFail; 3885226890Sdim } 3886226890Sdim if (Val == 32) Val = 0; 3887226890Sdim } else { 3888226890Sdim // Shift amount must be in [1,32] 3889226890Sdim if (Val < 0 || Val > 31) { 3890252723Sdim Error(ExLoc, "'lsr' shift amount must be in range [0,31]"); 3891226890Sdim return MatchOperand_ParseFail; 3892226890Sdim } 3893226890Sdim } 3894226890Sdim 3895252723Sdim Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, EndLoc)); 3896226890Sdim 3897226890Sdim return MatchOperand_Success; 3898226890Sdim} 3899226890Sdim 3900226890Sdim/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family 3901226890Sdim/// of instructions. Legal values are: 3902226890Sdim/// ror #n 'n' in {0, 8, 16, 24} 3903226890SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 3904226890SdimparseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 3905226890Sdim const AsmToken &Tok = Parser.getTok(); 3906226890Sdim SMLoc S = Tok.getLoc(); 3907226890Sdim if (Tok.isNot(AsmToken::Identifier)) 3908221345Sdim return MatchOperand_NoMatch; 3909226890Sdim StringRef ShiftName = Tok.getString(); 3910226890Sdim if (ShiftName != "ror" && ShiftName != "ROR") 3911226890Sdim return MatchOperand_NoMatch; 3912226890Sdim Parser.Lex(); // Eat the operator. 3913221345Sdim 3914226890Sdim // A '#' and a rotate amount. 3915235633Sdim if (Parser.getTok().isNot(AsmToken::Hash) && 3916235633Sdim Parser.getTok().isNot(AsmToken::Dollar)) { 3917226890Sdim Error(Parser.getTok().getLoc(), "'#' expected"); 3918226890Sdim return MatchOperand_ParseFail; 3919226890Sdim } 3920226890Sdim Parser.Lex(); // Eat hash token. 3921252723Sdim SMLoc ExLoc = Parser.getTok().getLoc(); 3922226890Sdim 3923226890Sdim const MCExpr *ShiftAmount; 3924252723Sdim SMLoc EndLoc; 3925252723Sdim if (getParser().parseExpression(ShiftAmount, EndLoc)) { 3926252723Sdim Error(ExLoc, "malformed rotate expression"); 3927226890Sdim return MatchOperand_ParseFail; 3928226890Sdim } 3929226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount); 3930226890Sdim if (!CE) { 3931252723Sdim Error(ExLoc, "rotate amount must be an immediate"); 3932226890Sdim return MatchOperand_ParseFail; 3933226890Sdim } 3934226890Sdim 3935226890Sdim int64_t Val = CE->getValue(); 3936226890Sdim // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension) 3937226890Sdim // normally, zero is represented in asm by omitting the rotate operand 3938226890Sdim // entirely. 3939226890Sdim if (Val != 8 && Val != 16 && Val != 24 && Val != 0) { 3940252723Sdim Error(ExLoc, "'ror' rotate amount must be 8, 16, or 24"); 3941226890Sdim return MatchOperand_ParseFail; 3942226890Sdim } 3943226890Sdim 3944252723Sdim Operands.push_back(ARMOperand::CreateRotImm(Val, S, EndLoc)); 3945226890Sdim 3946221345Sdim return MatchOperand_Success; 3947221345Sdim} 3948221345Sdim 3949226890SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 3950226890SdimparseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 3951226890Sdim SMLoc S = Parser.getTok().getLoc(); 3952226890Sdim // The bitfield descriptor is really two operands, the LSB and the width. 3953235633Sdim if (Parser.getTok().isNot(AsmToken::Hash) && 3954235633Sdim Parser.getTok().isNot(AsmToken::Dollar)) { 3955226890Sdim Error(Parser.getTok().getLoc(), "'#' expected"); 3956226890Sdim return MatchOperand_ParseFail; 3957226890Sdim } 3958226890Sdim Parser.Lex(); // Eat hash token. 3959226890Sdim 3960226890Sdim const MCExpr *LSBExpr; 3961226890Sdim SMLoc E = Parser.getTok().getLoc(); 3962252723Sdim if (getParser().parseExpression(LSBExpr)) { 3963226890Sdim Error(E, "malformed immediate expression"); 3964226890Sdim return MatchOperand_ParseFail; 3965226890Sdim } 3966226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr); 3967226890Sdim if (!CE) { 3968226890Sdim Error(E, "'lsb' operand must be an immediate"); 3969226890Sdim return MatchOperand_ParseFail; 3970226890Sdim } 3971226890Sdim 3972226890Sdim int64_t LSB = CE->getValue(); 3973226890Sdim // The LSB must be in the range [0,31] 3974226890Sdim if (LSB < 0 || LSB > 31) { 3975226890Sdim Error(E, "'lsb' operand must be in the range [0,31]"); 3976226890Sdim return MatchOperand_ParseFail; 3977226890Sdim } 3978226890Sdim E = Parser.getTok().getLoc(); 3979226890Sdim 3980226890Sdim // Expect another immediate operand. 3981226890Sdim if (Parser.getTok().isNot(AsmToken::Comma)) { 3982226890Sdim Error(Parser.getTok().getLoc(), "too few operands"); 3983226890Sdim return MatchOperand_ParseFail; 3984226890Sdim } 3985226890Sdim Parser.Lex(); // Eat hash token. 3986235633Sdim if (Parser.getTok().isNot(AsmToken::Hash) && 3987235633Sdim Parser.getTok().isNot(AsmToken::Dollar)) { 3988226890Sdim Error(Parser.getTok().getLoc(), "'#' expected"); 3989226890Sdim return MatchOperand_ParseFail; 3990226890Sdim } 3991226890Sdim Parser.Lex(); // Eat hash token. 3992226890Sdim 3993226890Sdim const MCExpr *WidthExpr; 3994252723Sdim SMLoc EndLoc; 3995252723Sdim if (getParser().parseExpression(WidthExpr, EndLoc)) { 3996226890Sdim Error(E, "malformed immediate expression"); 3997226890Sdim return MatchOperand_ParseFail; 3998226890Sdim } 3999226890Sdim CE = dyn_cast<MCConstantExpr>(WidthExpr); 4000226890Sdim if (!CE) { 4001226890Sdim Error(E, "'width' operand must be an immediate"); 4002226890Sdim return MatchOperand_ParseFail; 4003226890Sdim } 4004226890Sdim 4005226890Sdim int64_t Width = CE->getValue(); 4006226890Sdim // The LSB must be in the range [1,32-lsb] 4007226890Sdim if (Width < 1 || Width > 32 - LSB) { 4008226890Sdim Error(E, "'width' operand must be in the range [1,32-lsb]"); 4009226890Sdim return MatchOperand_ParseFail; 4010226890Sdim } 4011226890Sdim 4012252723Sdim Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, EndLoc)); 4013226890Sdim 4014226890Sdim return MatchOperand_Success; 4015226890Sdim} 4016226890Sdim 4017226890SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 4018226890SdimparsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 4019226890Sdim // Check for a post-index addressing register operand. Specifically: 4020226890Sdim // postidx_reg := '+' register {, shift} 4021226890Sdim // | '-' register {, shift} 4022226890Sdim // | register {, shift} 4023226890Sdim 4024226890Sdim // This method must return MatchOperand_NoMatch without consuming any tokens 4025226890Sdim // in the case where there is no match, as other alternatives take other 4026226890Sdim // parse methods. 4027226890Sdim AsmToken Tok = Parser.getTok(); 4028226890Sdim SMLoc S = Tok.getLoc(); 4029226890Sdim bool haveEaten = false; 4030226890Sdim bool isAdd = true; 4031226890Sdim if (Tok.is(AsmToken::Plus)) { 4032226890Sdim Parser.Lex(); // Eat the '+' token. 4033226890Sdim haveEaten = true; 4034226890Sdim } else if (Tok.is(AsmToken::Minus)) { 4035226890Sdim Parser.Lex(); // Eat the '-' token. 4036226890Sdim isAdd = false; 4037226890Sdim haveEaten = true; 4038226890Sdim } 4039252723Sdim 4040252723Sdim SMLoc E = Parser.getTok().getEndLoc(); 4041252723Sdim int Reg = tryParseRegister(); 4042226890Sdim if (Reg == -1) { 4043226890Sdim if (!haveEaten) 4044226890Sdim return MatchOperand_NoMatch; 4045226890Sdim Error(Parser.getTok().getLoc(), "register expected"); 4046226890Sdim return MatchOperand_ParseFail; 4047226890Sdim } 4048226890Sdim 4049226890Sdim ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift; 4050226890Sdim unsigned ShiftImm = 0; 4051226890Sdim if (Parser.getTok().is(AsmToken::Comma)) { 4052226890Sdim Parser.Lex(); // Eat the ','. 4053226890Sdim if (parseMemRegOffsetShift(ShiftTy, ShiftImm)) 4054226890Sdim return MatchOperand_ParseFail; 4055252723Sdim 4056252723Sdim // FIXME: Only approximates end...may include intervening whitespace. 4057252723Sdim E = Parser.getTok().getLoc(); 4058226890Sdim } 4059226890Sdim 4060226890Sdim Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy, 4061226890Sdim ShiftImm, S, E)); 4062226890Sdim 4063226890Sdim return MatchOperand_Success; 4064226890Sdim} 4065226890Sdim 4066226890SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 4067226890SdimparseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 4068226890Sdim // Check for a post-index addressing register operand. Specifically: 4069226890Sdim // am3offset := '+' register 4070226890Sdim // | '-' register 4071226890Sdim // | register 4072226890Sdim // | # imm 4073226890Sdim // | # + imm 4074226890Sdim // | # - imm 4075226890Sdim 4076226890Sdim // This method must return MatchOperand_NoMatch without consuming any tokens 4077226890Sdim // in the case where there is no match, as other alternatives take other 4078226890Sdim // parse methods. 4079226890Sdim AsmToken Tok = Parser.getTok(); 4080226890Sdim SMLoc S = Tok.getLoc(); 4081226890Sdim 4082226890Sdim // Do immediates first, as we always parse those if we have a '#'. 4083235633Sdim if (Parser.getTok().is(AsmToken::Hash) || 4084235633Sdim Parser.getTok().is(AsmToken::Dollar)) { 4085263509Sdim Parser.Lex(); // Eat '#' or '$'. 4086226890Sdim // Explicitly look for a '-', as we need to encode negative zero 4087226890Sdim // differently. 4088226890Sdim bool isNegative = Parser.getTok().is(AsmToken::Minus); 4089226890Sdim const MCExpr *Offset; 4090252723Sdim SMLoc E; 4091252723Sdim if (getParser().parseExpression(Offset, E)) 4092226890Sdim return MatchOperand_ParseFail; 4093226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset); 4094226890Sdim if (!CE) { 4095226890Sdim Error(S, "constant expression expected"); 4096226890Sdim return MatchOperand_ParseFail; 4097226890Sdim } 4098226890Sdim // Negative zero is encoded as the flag value INT32_MIN. 4099226890Sdim int32_t Val = CE->getValue(); 4100226890Sdim if (isNegative && Val == 0) 4101226890Sdim Val = INT32_MIN; 4102226890Sdim 4103226890Sdim Operands.push_back( 4104226890Sdim ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E)); 4105226890Sdim 4106226890Sdim return MatchOperand_Success; 4107226890Sdim } 4108226890Sdim 4109226890Sdim 4110226890Sdim bool haveEaten = false; 4111226890Sdim bool isAdd = true; 4112226890Sdim if (Tok.is(AsmToken::Plus)) { 4113226890Sdim Parser.Lex(); // Eat the '+' token. 4114226890Sdim haveEaten = true; 4115226890Sdim } else if (Tok.is(AsmToken::Minus)) { 4116226890Sdim Parser.Lex(); // Eat the '-' token. 4117226890Sdim isAdd = false; 4118226890Sdim haveEaten = true; 4119226890Sdim } 4120252723Sdim 4121252723Sdim Tok = Parser.getTok(); 4122252723Sdim int Reg = tryParseRegister(); 4123226890Sdim if (Reg == -1) { 4124226890Sdim if (!haveEaten) 4125226890Sdim return MatchOperand_NoMatch; 4126252723Sdim Error(Tok.getLoc(), "register expected"); 4127226890Sdim return MatchOperand_ParseFail; 4128226890Sdim } 4129226890Sdim 4130226890Sdim Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift, 4131252723Sdim 0, S, Tok.getEndLoc())); 4132226890Sdim 4133226890Sdim return MatchOperand_Success; 4134226890Sdim} 4135226890Sdim 4136263509Sdim/// Convert parsed operands to MCInst. Needed here because this instruction 4137263509Sdim/// only has two register operands, but multiplication is commutative so 4138263509Sdim/// assemblers should accept both "mul rD, rN, rD" and "mul rD, rD, rN". 4139245431Sdimvoid ARMAsmParser:: 4140245431SdimcvtThumbMultiply(MCInst &Inst, 4141226890Sdim const SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 4142226890Sdim ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1); 4143226890Sdim ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1); 4144235633Sdim // If we have a three-operand form, make sure to set Rn to be the operand 4145235633Sdim // that isn't the same as Rd. 4146235633Sdim unsigned RegOp = 4; 4147235633Sdim if (Operands.size() == 6 && 4148235633Sdim ((ARMOperand*)Operands[4])->getReg() == 4149235633Sdim ((ARMOperand*)Operands[3])->getReg()) 4150235633Sdim RegOp = 5; 4151235633Sdim ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1); 4152235633Sdim Inst.addOperand(Inst.getOperand(0)); 4153226890Sdim ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2); 4154226890Sdim} 4155226890Sdim 4156245431Sdimvoid ARMAsmParser:: 4157263509SdimcvtThumbBranches(MCInst &Inst, 4158263509Sdim const SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 4159263509Sdim int CondOp = -1, ImmOp = -1; 4160263509Sdim switch(Inst.getOpcode()) { 4161263509Sdim case ARM::tB: 4162263509Sdim case ARM::tBcc: CondOp = 1; ImmOp = 2; break; 4163235633Sdim 4164263509Sdim case ARM::t2B: 4165263509Sdim case ARM::t2Bcc: CondOp = 1; ImmOp = 3; break; 4166235633Sdim 4167263509Sdim default: llvm_unreachable("Unexpected instruction in cvtThumbBranches"); 4168263509Sdim } 4169263509Sdim // first decide whether or not the branch should be conditional 4170263509Sdim // by looking at it's location relative to an IT block 4171263509Sdim if(inITBlock()) { 4172263509Sdim // inside an IT block we cannot have any conditional branches. any 4173263509Sdim // such instructions needs to be converted to unconditional form 4174263509Sdim switch(Inst.getOpcode()) { 4175263509Sdim case ARM::tBcc: Inst.setOpcode(ARM::tB); break; 4176263509Sdim case ARM::t2Bcc: Inst.setOpcode(ARM::t2B); break; 4177263509Sdim } 4178263509Sdim } else { 4179263509Sdim // outside IT blocks we can only have unconditional branches with AL 4180263509Sdim // condition code or conditional branches with non-AL condition code 4181263509Sdim unsigned Cond = static_cast<ARMOperand*>(Operands[CondOp])->getCondCode(); 4182263509Sdim switch(Inst.getOpcode()) { 4183263509Sdim case ARM::tB: 4184263509Sdim case ARM::tBcc: 4185263509Sdim Inst.setOpcode(Cond == ARMCC::AL ? ARM::tB : ARM::tBcc); 4186263509Sdim break; 4187263509Sdim case ARM::t2B: 4188263509Sdim case ARM::t2Bcc: 4189263509Sdim Inst.setOpcode(Cond == ARMCC::AL ? ARM::t2B : ARM::t2Bcc); 4190263509Sdim break; 4191263509Sdim } 4192263509Sdim } 4193263509Sdim 4194263509Sdim // now decide on encoding size based on branch target range 4195263509Sdim switch(Inst.getOpcode()) { 4196263509Sdim // classify tB as either t2B or t1B based on range of immediate operand 4197263509Sdim case ARM::tB: { 4198263509Sdim ARMOperand* op = static_cast<ARMOperand*>(Operands[ImmOp]); 4199263509Sdim if(!op->isSignedOffset<11, 1>() && isThumbTwo()) 4200263509Sdim Inst.setOpcode(ARM::t2B); 4201263509Sdim break; 4202263509Sdim } 4203263509Sdim // classify tBcc as either t2Bcc or t1Bcc based on range of immediate operand 4204263509Sdim case ARM::tBcc: { 4205263509Sdim ARMOperand* op = static_cast<ARMOperand*>(Operands[ImmOp]); 4206263509Sdim if(!op->isSignedOffset<8, 1>() && isThumbTwo()) 4207263509Sdim Inst.setOpcode(ARM::t2Bcc); 4208263509Sdim break; 4209263509Sdim } 4210263509Sdim } 4211263509Sdim ((ARMOperand*)Operands[ImmOp])->addImmOperands(Inst, 1); 4212263509Sdim ((ARMOperand*)Operands[CondOp])->addCondCodeOperands(Inst, 2); 4213235633Sdim} 4214235633Sdim 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:: 4218226890SdimparseMemory(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(); 4226226890Sdim int BaseRegNum = tryParseRegister(); 4227226890Sdim if (BaseRegNum == -1) 4228226890Sdim return Error(BaseRegTok.getLoc(), "register expected"); 4229198090Srdivacky 4230252723Sdim // The next token must either be a comma, a colon or a closing bracket. 4231218893Sdim const AsmToken &Tok = Parser.getTok(); 4232252723Sdim if (!Tok.is(AsmToken::Colon) && !Tok.is(AsmToken::Comma) && 4233252723Sdim !Tok.is(AsmToken::RBrac)) 4234226890Sdim return Error(Tok.getLoc(), "malformed memory operand"); 4235218893Sdim 4236226890Sdim if (Tok.is(AsmToken::RBrac)) { 4237252723Sdim E = Tok.getEndLoc(); 4238226890Sdim Parser.Lex(); // Eat right bracket token. 4239198090Srdivacky 4240226890Sdim Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift, 4241226890Sdim 0, 0, false, S, E)); 4242218893Sdim 4243226890Sdim // If there's a pre-indexing writeback marker, '!', just add it as a token 4244226890Sdim // operand. It's rather odd, but syntactically valid. 4245226890Sdim if (Parser.getTok().is(AsmToken::Exclaim)) { 4246226890Sdim Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); 4247226890Sdim Parser.Lex(); // Eat the '!'. 4248218893Sdim } 4249198090Srdivacky 4250226890Sdim return false; 4251226890Sdim } 4252221345Sdim 4253252723Sdim assert((Tok.is(AsmToken::Colon) || Tok.is(AsmToken::Comma)) && 4254252723Sdim "Lost colon or comma in memory operand?!"); 4255252723Sdim if (Tok.is(AsmToken::Comma)) { 4256252723Sdim Parser.Lex(); // Eat the comma. 4257252723Sdim } 4258218893Sdim 4259226890Sdim // If we have a ':', it's an alignment specifier. 4260226890Sdim if (Parser.getTok().is(AsmToken::Colon)) { 4261226890Sdim Parser.Lex(); // Eat the ':'. 4262226890Sdim E = Parser.getTok().getLoc(); 4263198090Srdivacky 4264226890Sdim const MCExpr *Expr; 4265252723Sdim if (getParser().parseExpression(Expr)) 4266226890Sdim return true; 4267198090Srdivacky 4268226890Sdim // The expression has to be a constant. Memory references with relocations 4269226890Sdim // don't come through here, as they use the <label> forms of the relevant 4270226890Sdim // instructions. 4271226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr); 4272226890Sdim if (!CE) 4273226890Sdim return Error (E, "constant expression expected"); 4274218893Sdim 4275226890Sdim unsigned Align = 0; 4276226890Sdim switch (CE->getValue()) { 4277226890Sdim default: 4278235633Sdim return Error(E, 4279235633Sdim "alignment specifier must be 16, 32, 64, 128, or 256 bits"); 4280235633Sdim case 16: Align = 2; break; 4281235633Sdim case 32: Align = 4; break; 4282226890Sdim case 64: Align = 8; break; 4283226890Sdim case 128: Align = 16; break; 4284226890Sdim case 256: Align = 32; break; 4285226890Sdim } 4286218893Sdim 4287226890Sdim // Now we should have the closing ']' 4288226890Sdim if (Parser.getTok().isNot(AsmToken::RBrac)) 4289252723Sdim return Error(Parser.getTok().getLoc(), "']' expected"); 4290252723Sdim E = Parser.getTok().getEndLoc(); 4291226890Sdim Parser.Lex(); // Eat right bracket token. 4292218893Sdim 4293226890Sdim // Don't worry about range checking the value here. That's handled by 4294226890Sdim // the is*() predicates. 4295226890Sdim Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, 4296226890Sdim ARM_AM::no_shift, 0, Align, 4297226890Sdim false, S, E)); 4298226890Sdim 4299226890Sdim // If there's a pre-indexing writeback marker, '!', just add it as a token 4300226890Sdim // operand. 4301226890Sdim if (Parser.getTok().is(AsmToken::Exclaim)) { 4302226890Sdim Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); 4303226890Sdim Parser.Lex(); // Eat the '!'. 4304198090Srdivacky } 4305198090Srdivacky 4306226890Sdim return false; 4307198090Srdivacky } 4308198090Srdivacky 4309226890Sdim // If we have a '#', it's an immediate offset, else assume it's a register 4310235633Sdim // offset. Be friendly and also accept a plain integer (without a leading 4311235633Sdim // hash) for gas compatibility. 4312235633Sdim if (Parser.getTok().is(AsmToken::Hash) || 4313235633Sdim Parser.getTok().is(AsmToken::Dollar) || 4314235633Sdim Parser.getTok().is(AsmToken::Integer)) { 4315235633Sdim if (Parser.getTok().isNot(AsmToken::Integer)) 4316263509Sdim Parser.Lex(); // Eat '#' or '$'. 4317226890Sdim E = Parser.getTok().getLoc(); 4318218893Sdim 4319226890Sdim bool isNegative = getParser().getTok().is(AsmToken::Minus); 4320226890Sdim const MCExpr *Offset; 4321252723Sdim if (getParser().parseExpression(Offset)) 4322226890Sdim return true; 4323198090Srdivacky 4324226890Sdim // The expression has to be a constant. Memory references with relocations 4325226890Sdim // don't come through here, as they use the <label> forms of the relevant 4326226890Sdim // instructions. 4327226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset); 4328226890Sdim if (!CE) 4329226890Sdim return Error (E, "constant expression expected"); 4330226890Sdim 4331226890Sdim // If the constant was #-0, represent it as INT32_MIN. 4332226890Sdim int32_t Val = CE->getValue(); 4333226890Sdim if (isNegative && Val == 0) 4334226890Sdim CE = MCConstantExpr::Create(INT32_MIN, getContext()); 4335226890Sdim 4336226890Sdim // Now we should have the closing ']' 4337226890Sdim if (Parser.getTok().isNot(AsmToken::RBrac)) 4338252723Sdim return Error(Parser.getTok().getLoc(), "']' expected"); 4339252723Sdim E = Parser.getTok().getEndLoc(); 4340226890Sdim Parser.Lex(); // Eat right bracket token. 4341226890Sdim 4342226890Sdim // Don't worry about range checking the value here. That's handled by 4343226890Sdim // the is*() predicates. 4344226890Sdim Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0, 4345226890Sdim ARM_AM::no_shift, 0, 0, 4346226890Sdim false, S, E)); 4347226890Sdim 4348226890Sdim // If there's a pre-indexing writeback marker, '!', just add it as a token 4349226890Sdim // operand. 4350226890Sdim if (Parser.getTok().is(AsmToken::Exclaim)) { 4351226890Sdim Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); 4352226890Sdim Parser.Lex(); // Eat the '!'. 4353206124Srdivacky } 4354226890Sdim 4355226890Sdim return false; 4356198892Srdivacky } 4357218893Sdim 4358226890Sdim // The register offset is optionally preceded by a '+' or '-' 4359226890Sdim bool isNegative = false; 4360226890Sdim if (Parser.getTok().is(AsmToken::Minus)) { 4361226890Sdim isNegative = true; 4362226890Sdim Parser.Lex(); // Eat the '-'. 4363226890Sdim } else if (Parser.getTok().is(AsmToken::Plus)) { 4364226890Sdim // Nothing to do. 4365226890Sdim Parser.Lex(); // Eat the '+'. 4366226890Sdim } 4367198892Srdivacky 4368226890Sdim E = Parser.getTok().getLoc(); 4369226890Sdim int OffsetRegNum = tryParseRegister(); 4370226890Sdim if (OffsetRegNum == -1) 4371226890Sdim return Error(E, "register expected"); 4372226890Sdim 4373226890Sdim // If there's a shift operator, handle it. 4374226890Sdim ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift; 4375226890Sdim unsigned ShiftImm = 0; 4376226890Sdim if (Parser.getTok().is(AsmToken::Comma)) { 4377226890Sdim Parser.Lex(); // Eat the ','. 4378226890Sdim if (parseMemRegOffsetShift(ShiftType, ShiftImm)) 4379226890Sdim return true; 4380198892Srdivacky } 4381218893Sdim 4382226890Sdim // Now we should have the closing ']' 4383226890Sdim if (Parser.getTok().isNot(AsmToken::RBrac)) 4384252723Sdim return Error(Parser.getTok().getLoc(), "']' expected"); 4385252723Sdim E = Parser.getTok().getEndLoc(); 4386226890Sdim Parser.Lex(); // Eat right bracket token. 4387198892Srdivacky 4388226890Sdim Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum, 4389226890Sdim ShiftType, ShiftImm, 0, isNegative, 4390226890Sdim S, E)); 4391226890Sdim 4392226890Sdim // If there's a pre-indexing writeback marker, '!', just add it as a token 4393226890Sdim // operand. 4394226890Sdim if (Parser.getTok().is(AsmToken::Exclaim)) { 4395226890Sdim Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); 4396226890Sdim Parser.Lex(); // Eat the '!'. 4397198892Srdivacky } 4398226890Sdim 4399198892Srdivacky return false; 4400198892Srdivacky} 4401198892Srdivacky 4402226890Sdim/// parseMemRegOffsetShift - one of these two: 4403198090Srdivacky/// ( lsl | lsr | asr | ror ) , # shift_amount 4404198090Srdivacky/// rrx 4405226890Sdim/// return true if it parses a shift otherwise it returns false. 4406226890Sdimbool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St, 4407226890Sdim unsigned &Amount) { 4408226890Sdim 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(); 4413235633Sdim if (ShiftName == "lsl" || ShiftName == "LSL" || 4414235633Sdim 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 4425226890Sdim return Error(Loc, "illegal shift operator"); 4426202878Srdivacky Parser.Lex(); // Eat shift type token. 4427198090Srdivacky 4428226890Sdim // rrx stands alone. 4429226890Sdim Amount = 0; 4430226890Sdim if (St != ARM_AM::rrx) { 4431226890Sdim Loc = Parser.getTok().getLoc(); 4432226890Sdim // A '#' and a shift amount. 4433226890Sdim const AsmToken &HashTok = Parser.getTok(); 4434235633Sdim if (HashTok.isNot(AsmToken::Hash) && 4435235633Sdim HashTok.isNot(AsmToken::Dollar)) 4436226890Sdim return Error(HashTok.getLoc(), "'#' expected"); 4437226890Sdim Parser.Lex(); // Eat hash token. 4438198090Srdivacky 4439226890Sdim const MCExpr *Expr; 4440252723Sdim if (getParser().parseExpression(Expr)) 4441226890Sdim return true; 4442226890Sdim // Range check the immediate. 4443226890Sdim // lsl, ror: 0 <= imm <= 31 4444226890Sdim // lsr, asr: 0 <= imm <= 32 4445226890Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr); 4446226890Sdim if (!CE) 4447226890Sdim return Error(Loc, "shift amount must be an immediate"); 4448226890Sdim int64_t Imm = CE->getValue(); 4449226890Sdim if (Imm < 0 || 4450226890Sdim ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) || 4451226890Sdim ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32)) 4452226890Sdim return Error(Loc, "immediate shift value out of range"); 4453245431Sdim // If <ShiftTy> #0, turn it into a no_shift. 4454245431Sdim if (Imm == 0) 4455245431Sdim St = ARM_AM::lsl; 4456245431Sdim // For consistency, treat lsr #32 and asr #32 as having immediate value 0. 4457245431Sdim if (Imm == 32) 4458245431Sdim Imm = 0; 4459226890Sdim Amount = Imm; 4460226890Sdim } 4461198090Srdivacky 4462198090Srdivacky return false; 4463198090Srdivacky} 4464198090Srdivacky 4465226890Sdim/// parseFPImm - A floating point immediate expression operand. 4466226890SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 4467226890SdimparseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 4468235633Sdim // Anything that can accept a floating point constant as an operand 4469252723Sdim // needs to go through here, as the regular parseExpression is 4470235633Sdim // integer only. 4471235633Sdim // 4472235633Sdim // This routine still creates a generic Immediate operand, containing 4473235633Sdim // a bitcast of the 64-bit floating point value. The various operands 4474235633Sdim // that accept floats can check whether the value is valid for them 4475235633Sdim // via the standard is*() predicates. 4476235633Sdim 4477226890Sdim SMLoc S = Parser.getTok().getLoc(); 4478226890Sdim 4479235633Sdim if (Parser.getTok().isNot(AsmToken::Hash) && 4480235633Sdim Parser.getTok().isNot(AsmToken::Dollar)) 4481226890Sdim return MatchOperand_NoMatch; 4482235633Sdim 4483235633Sdim // Disambiguate the VMOV forms that can accept an FP immediate. 4484235633Sdim // vmov.f32 <sreg>, #imm 4485235633Sdim // vmov.f64 <dreg>, #imm 4486235633Sdim // vmov.f32 <dreg>, #imm @ vector f32x2 4487235633Sdim // vmov.f32 <qreg>, #imm @ vector f32x4 4488235633Sdim // 4489235633Sdim // There are also the NEON VMOV instructions which expect an 4490235633Sdim // integer constant. Make sure we don't try to parse an FPImm 4491235633Sdim // for these: 4492235633Sdim // vmov.i{8|16|32|64} <dreg|qreg>, #imm 4493235633Sdim ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]); 4494235633Sdim if (!TyOp->isToken() || (TyOp->getToken() != ".f32" && 4495235633Sdim TyOp->getToken() != ".f64")) 4496235633Sdim return MatchOperand_NoMatch; 4497235633Sdim 4498263509Sdim Parser.Lex(); // Eat '#' or '$'. 4499226890Sdim 4500226890Sdim // Handle negation, as that still comes through as a separate token. 4501226890Sdim bool isNegative = false; 4502226890Sdim if (Parser.getTok().is(AsmToken::Minus)) { 4503226890Sdim isNegative = true; 4504226890Sdim Parser.Lex(); 4505226890Sdim } 4506226890Sdim const AsmToken &Tok = Parser.getTok(); 4507235633Sdim SMLoc Loc = Tok.getLoc(); 4508226890Sdim if (Tok.is(AsmToken::Real)) { 4509235633Sdim APFloat RealVal(APFloat::IEEEsingle, Tok.getString()); 4510226890Sdim uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue(); 4511226890Sdim // If we had a '-' in front, toggle the sign bit. 4512235633Sdim IntVal ^= (uint64_t)isNegative << 31; 4513226890Sdim Parser.Lex(); // Eat the token. 4514235633Sdim Operands.push_back(ARMOperand::CreateImm( 4515235633Sdim MCConstantExpr::Create(IntVal, getContext()), 4516235633Sdim S, Parser.getTok().getLoc())); 4517226890Sdim return MatchOperand_Success; 4518226890Sdim } 4519235633Sdim // Also handle plain integers. Instructions which allow floating point 4520235633Sdim // immediates also allow a raw encoded 8-bit value. 4521226890Sdim if (Tok.is(AsmToken::Integer)) { 4522226890Sdim int64_t Val = Tok.getIntVal(); 4523226890Sdim Parser.Lex(); // Eat the token. 4524226890Sdim if (Val > 255 || Val < 0) { 4525235633Sdim Error(Loc, "encoded floating point value out of range"); 4526226890Sdim return MatchOperand_ParseFail; 4527226890Sdim } 4528235633Sdim double RealVal = ARM_AM::getFPImmFloat(Val); 4529235633Sdim Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue(); 4530235633Sdim Operands.push_back(ARMOperand::CreateImm( 4531235633Sdim MCConstantExpr::Create(Val, getContext()), S, 4532235633Sdim Parser.getTok().getLoc())); 4533226890Sdim return MatchOperand_Success; 4534226890Sdim } 4535226890Sdim 4536235633Sdim Error(Loc, "invalid floating point immediate"); 4537226890Sdim return MatchOperand_ParseFail; 4538226890Sdim} 4539235633Sdim 4540198892Srdivacky/// Parse a arm instruction operand. For now this parses the operand regardless 4541198892Srdivacky/// of the mnemonic. 4542226890Sdimbool 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: { 4562252723Sdim // If we've seen a branch mnemonic, the next operand must be a label. This 4563252723Sdim // is true even if the label is a register name. So "br r1" means branch to 4564252723Sdim // label "r1". 4565252723Sdim bool ExpectLabel = Mnemonic == "b" || Mnemonic == "bl"; 4566252723Sdim if (!ExpectLabel) { 4567252723Sdim if (!tryParseRegisterWithWriteBack(Operands)) 4568252723Sdim return false; 4569252723Sdim int Res = tryParseShiftRegister(Operands); 4570252723Sdim if (Res == 0) // success 4571252723Sdim return false; 4572252723Sdim else if (Res == -1) // irrecoverable error 4573252723Sdim return true; 4574252723Sdim // If this is VMRS, check for the apsr_nzcv operand. 4575252723Sdim if (Mnemonic == "vmrs" && 4576252723Sdim Parser.getTok().getString().equals_lower("apsr_nzcv")) { 4577252723Sdim S = Parser.getTok().getLoc(); 4578252723Sdim Parser.Lex(); 4579252723Sdim Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S)); 4580252723Sdim return false; 4581252723Sdim } 4582226890Sdim } 4583218893Sdim 4584218893Sdim // Fall though for the Identifier case that is not a register or a 4585218893Sdim // special name. 4586224145Sdim } 4587235633Sdim case AsmToken::LParen: // parenthesized expressions like (_strcmp-4) 4588218893Sdim case AsmToken::Integer: // things like 1f and 2b as a branch targets 4589235633Sdim 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(); 4595252723Sdim 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: 4602226890Sdim return parseMemory(Operands); 4603198090Srdivacky case AsmToken::LCurly: 4604226890Sdim return parseRegisterList(Operands); 4605235633Sdim case AsmToken::Dollar: 4606226890Sdim case AsmToken::Hash: { 4607198090Srdivacky // #42 -> immediate. 4608206124Srdivacky S = Parser.getTok().getLoc(); 4609202878Srdivacky Parser.Lex(); 4610235633Sdim 4611235633Sdim if (Parser.getTok().isNot(AsmToken::Colon)) { 4612235633Sdim bool isNegative = Parser.getTok().is(AsmToken::Minus); 4613235633Sdim const MCExpr *ImmVal; 4614252723Sdim if (getParser().parseExpression(ImmVal)) 4615235633Sdim return true; 4616235633Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal); 4617235633Sdim if (CE) { 4618235633Sdim int32_t Val = CE->getValue(); 4619235633Sdim if (isNegative && Val == 0) 4620235633Sdim ImmVal = MCConstantExpr::Create(INT32_MIN, getContext()); 4621235633Sdim } 4622235633Sdim E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 4623235633Sdim Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E)); 4624252723Sdim 4625252723Sdim // There can be a trailing '!' on operands that we want as a separate 4626252723Sdim // '!' Token operand. Handle that here. For example, the compatibilty 4627252723Sdim // alias for 'srsdb sp!, #imm' is 'srsdb #imm!'. 4628252723Sdim if (Parser.getTok().is(AsmToken::Exclaim)) { 4629252723Sdim Operands.push_back(ARMOperand::CreateToken(Parser.getTok().getString(), 4630252723Sdim Parser.getTok().getLoc())); 4631252723Sdim Parser.Lex(); // Eat exclaim token 4632252723Sdim } 4633235633Sdim return false; 4634226890Sdim } 4635235633Sdim // w/ a ':' after the '#', it's just like a plain ':'. 4636235633Sdim // FALLTHROUGH 4637226890Sdim } 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; 4643226890Sdim if (parsePrefix(RefKind)) 4644218893Sdim return true; 4645218893Sdim 4646218893Sdim const MCExpr *SubExprVal; 4647252723Sdim if (getParser().parseExpression(SubExprVal)) 4648218893Sdim return true; 4649218893Sdim 4650218893Sdim const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal, 4651245431Sdim 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 4659226890Sdim// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e. 4660218893Sdim// :lower16: and :upper16:. 4661226890Sdimbool 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. 4696226890Sdim// FIXME: This is a bit of a maze of special cases. 4697226890SdimStringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic, 4698226890Sdim unsigned &PredicationCode, 4699226890Sdim bool &CarrySetting, 4700226890Sdim unsigned &ProcessorIMod, 4701226890Sdim 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. 4709226890Sdim if ((Mnemonic == "movs" && isThumb()) || 4710226890Sdim Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" || 4711226890Sdim Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" || 4712226890Sdim Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" || 4713226890Sdim Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" || 4714263509Sdim Mnemonic == "vaclt" || Mnemonic == "vacle" || Mnemonic == "hlt" || 4715226890Sdim Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" || 4716226890Sdim Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" || 4717235633Sdim Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" || 4718263509Sdim Mnemonic == "fmuls" || Mnemonic == "vmaxnm" || Mnemonic == "vminnm" || 4719263509Sdim Mnemonic == "vcvta" || Mnemonic == "vcvtn" || Mnemonic == "vcvtp" || 4720263509Sdim Mnemonic == "vcvtm" || Mnemonic == "vrinta" || Mnemonic == "vrintn" || 4721263509Sdim 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. 4726226890Sdim if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" && 4727226890Sdim Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" && 4728226890Sdim Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" && 4729226890Sdim 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") && 4758226890Sdim !(Mnemonic == "cps" || Mnemonic == "mls" || 4759226890Sdim Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" || 4760226890Sdim Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" || 4761226890Sdim Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" || 4762235633Sdim Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" || 4763235633Sdim Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" || 4764235633Sdim Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" || 4765235633Sdim Mnemonic == "fmuls" || Mnemonic == "fcmps" || Mnemonic == "fcmpzs" || 4766235633Sdim Mnemonic == "vfms" || Mnemonic == "vfnms" || 4767226890Sdim (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 4787226890Sdim // The "it" instruction has the condition mask on the end of the mnemonic. 4788226890Sdim if (Mnemonic.startswith("it")) { 4789226890Sdim ITMask = Mnemonic.slice(2, Mnemonic.size()); 4790226890Sdim Mnemonic = Mnemonic.slice(0, 2); 4791226890Sdim } 4792226890Sdim 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:: 4801263509SdimgetMnemonicAcceptInfo(StringRef Mnemonic, StringRef FullInst, 4802263509Sdim bool &CanAcceptCarrySet, bool &CanAcceptPredicationCode) { 4803218893Sdim if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" || 4804218893Sdim Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" || 4805226890Sdim Mnemonic == "add" || Mnemonic == "adc" || 4806218893Sdim Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" || 4807226890Sdim Mnemonic == "orr" || Mnemonic == "mvn" || 4808218893Sdim Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" || 4809226890Sdim Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" || 4810235633Sdim Mnemonic == "vfm" || Mnemonic == "vfnm" || 4811226890Sdim (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" || 4812226890Sdim Mnemonic == "mla" || Mnemonic == "smlal" || 4813226890Sdim Mnemonic == "umlal" || Mnemonic == "umull"))) { 4814218893Sdim CanAcceptCarrySet = true; 4815226890Sdim } else 4816218893Sdim CanAcceptCarrySet = false; 4817218893Sdim 4818263509Sdim if (Mnemonic == "bkpt" || Mnemonic == "cbnz" || Mnemonic == "setend" || 4819263509Sdim Mnemonic == "cps" || Mnemonic == "it" || Mnemonic == "cbz" || 4820263509Sdim Mnemonic == "trap" || Mnemonic == "hlt" || Mnemonic.startswith("crc32") || 4821263509Sdim Mnemonic.startswith("cps") || Mnemonic.startswith("vsel") || 4822263509Sdim Mnemonic == "vmaxnm" || Mnemonic == "vminnm" || Mnemonic == "vcvta" || 4823263509Sdim Mnemonic == "vcvtn" || Mnemonic == "vcvtp" || Mnemonic == "vcvtm" || 4824263509Sdim Mnemonic == "vrinta" || Mnemonic == "vrintn" || Mnemonic == "vrintp" || 4825263509Sdim Mnemonic == "vrintm" || Mnemonic.startswith("aes") || 4826263509Sdim Mnemonic.startswith("sha1") || Mnemonic.startswith("sha256") || 4827263509Sdim (FullInst.startswith("vmull") && FullInst.endswith(".p64"))) { 4828263509Sdim // These mnemonics are never predicable 4829218893Sdim CanAcceptPredicationCode = false; 4830263509Sdim } else if (!isThumb()) { 4831263509Sdim // Some instructions are only predicable in Thumb mode 4832263509Sdim CanAcceptPredicationCode 4833263509Sdim = Mnemonic != "cdp2" && Mnemonic != "clrex" && Mnemonic != "mcr2" && 4834263509Sdim Mnemonic != "mcrr2" && Mnemonic != "mrc2" && Mnemonic != "mrrc2" && 4835263509Sdim Mnemonic != "dmb" && Mnemonic != "dsb" && Mnemonic != "isb" && 4836263509Sdim Mnemonic != "pld" && Mnemonic != "pli" && Mnemonic != "pldw" && 4837263509Sdim Mnemonic != "ldc2" && Mnemonic != "ldc2l" && 4838263509Sdim Mnemonic != "stc2" && Mnemonic != "stc2l" && 4839263509Sdim !Mnemonic.startswith("rfe") && !Mnemonic.startswith("srs"); 4840263509Sdim } else if (isThumbOne()) { 4841263509Sdim if (hasV6MOps()) 4842263509Sdim CanAcceptPredicationCode = Mnemonic != "movs"; 4843263509Sdim else 4844263509Sdim CanAcceptPredicationCode = Mnemonic != "nop" && Mnemonic != "movs"; 4845226890Sdim } else 4846218893Sdim CanAcceptPredicationCode = true; 4847218893Sdim} 4848218893Sdim 4849226890Sdimbool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic, 4850226890Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 4851226890Sdim // FIXME: This is all horribly hacky. We really need a better way to deal 4852226890Sdim // with optional operands like this in the matcher table. 4853226890Sdim 4854226890Sdim // The 'mov' mnemonic is special. One variant has a cc_out operand, while 4855226890Sdim // another does not. Specifically, the MOVW instruction does not. So we 4856226890Sdim // special case it here and remove the defaulted (non-setting) cc_out 4857226890Sdim // operand if that's the instruction we're trying to match. 4858226890Sdim // 4859226890Sdim // We do this as post-processing of the explicit operands rather than just 4860226890Sdim // conditionally adding the cc_out in the first place because we need 4861226890Sdim // to check the type of the parsed immediate operand. 4862226890Sdim if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() && 4863226890Sdim !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() && 4864226890Sdim static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() && 4865226890Sdim static_cast<ARMOperand*>(Operands[1])->getReg() == 0) 4866226890Sdim return true; 4867226890Sdim 4868226890Sdim // Register-register 'add' for thumb does not have a cc_out operand 4869226890Sdim // when there are only two register operands. 4870226890Sdim if (isThumb() && Mnemonic == "add" && Operands.size() == 5 && 4871226890Sdim static_cast<ARMOperand*>(Operands[3])->isReg() && 4872226890Sdim static_cast<ARMOperand*>(Operands[4])->isReg() && 4873226890Sdim static_cast<ARMOperand*>(Operands[1])->getReg() == 0) 4874226890Sdim return true; 4875226890Sdim // Register-register 'add' for thumb does not have a cc_out operand 4876226890Sdim // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do 4877226890Sdim // have to check the immediate range here since Thumb2 has a variant 4878226890Sdim // that can handle a different range and has a cc_out operand. 4879226890Sdim if (((isThumb() && Mnemonic == "add") || 4880226890Sdim (isThumbTwo() && Mnemonic == "sub")) && 4881226890Sdim Operands.size() == 6 && 4882226890Sdim static_cast<ARMOperand*>(Operands[3])->isReg() && 4883226890Sdim static_cast<ARMOperand*>(Operands[4])->isReg() && 4884226890Sdim static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP && 4885226890Sdim static_cast<ARMOperand*>(Operands[1])->getReg() == 0 && 4886235633Sdim ((Mnemonic == "add" &&static_cast<ARMOperand*>(Operands[5])->isReg()) || 4887226890Sdim static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4())) 4888226890Sdim return true; 4889226890Sdim // For Thumb2, add/sub immediate does not have a cc_out operand for the 4890226890Sdim // imm0_4095 variant. That's the least-preferred variant when 4891226890Sdim // selecting via the generic "add" mnemonic, so to know that we 4892226890Sdim // should remove the cc_out operand, we have to explicitly check that 4893226890Sdim // it's not one of the other variants. Ugh. 4894226890Sdim if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") && 4895226890Sdim Operands.size() == 6 && 4896226890Sdim static_cast<ARMOperand*>(Operands[3])->isReg() && 4897226890Sdim static_cast<ARMOperand*>(Operands[4])->isReg() && 4898226890Sdim static_cast<ARMOperand*>(Operands[5])->isImm()) { 4899226890Sdim // Nest conditions rather than one big 'if' statement for readability. 4900226890Sdim // 4901226890Sdim // If both registers are low, we're in an IT block, and the immediate is 4902226890Sdim // in range, we should use encoding T1 instead, which has a cc_out. 4903226890Sdim if (inITBlock() && 4904226890Sdim isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) && 4905226890Sdim isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) && 4906226890Sdim static_cast<ARMOperand*>(Operands[5])->isImm0_7()) 4907226890Sdim return false; 4908263509Sdim // Check against T3. If the second register is the PC, this is an 4909263509Sdim // alternate form of ADR, which uses encoding T4, so check for that too. 4910263509Sdim if (static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC && 4911263509Sdim static_cast<ARMOperand*>(Operands[5])->isT2SOImm()) 4912263509Sdim return false; 4913226890Sdim 4914226890Sdim // Otherwise, we use encoding T4, which does not have a cc_out 4915226890Sdim // operand. 4916226890Sdim return true; 4917226890Sdim } 4918226890Sdim 4919226890Sdim // The thumb2 multiply instruction doesn't have a CCOut register, so 4920226890Sdim // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to 4921226890Sdim // use the 16-bit encoding or not. 4922226890Sdim if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 && 4923226890Sdim static_cast<ARMOperand*>(Operands[1])->getReg() == 0 && 4924226890Sdim static_cast<ARMOperand*>(Operands[3])->isReg() && 4925226890Sdim static_cast<ARMOperand*>(Operands[4])->isReg() && 4926226890Sdim static_cast<ARMOperand*>(Operands[5])->isReg() && 4927226890Sdim // If the registers aren't low regs, the destination reg isn't the 4928226890Sdim // same as one of the source regs, or the cc_out operand is zero 4929226890Sdim // outside of an IT block, we have to use the 32-bit encoding, so 4930226890Sdim // remove the cc_out operand. 4931226890Sdim (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) || 4932226890Sdim !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) || 4933235633Sdim !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) || 4934226890Sdim !inITBlock() || 4935226890Sdim (static_cast<ARMOperand*>(Operands[3])->getReg() != 4936226890Sdim static_cast<ARMOperand*>(Operands[5])->getReg() && 4937226890Sdim static_cast<ARMOperand*>(Operands[3])->getReg() != 4938226890Sdim static_cast<ARMOperand*>(Operands[4])->getReg()))) 4939226890Sdim return true; 4940226890Sdim 4941235633Sdim // Also check the 'mul' syntax variant that doesn't specify an explicit 4942235633Sdim // destination register. 4943235633Sdim if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 && 4944235633Sdim static_cast<ARMOperand*>(Operands[1])->getReg() == 0 && 4945235633Sdim static_cast<ARMOperand*>(Operands[3])->isReg() && 4946235633Sdim static_cast<ARMOperand*>(Operands[4])->isReg() && 4947235633Sdim // If the registers aren't low regs or the cc_out operand is zero 4948235633Sdim // outside of an IT block, we have to use the 32-bit encoding, so 4949235633Sdim // remove the cc_out operand. 4950235633Sdim (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) || 4951235633Sdim !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) || 4952235633Sdim !inITBlock())) 4953235633Sdim return true; 4954226890Sdim 4955226890Sdim 4956235633Sdim 4957226890Sdim // Register-register 'add/sub' for thumb does not have a cc_out operand 4958226890Sdim // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also 4959226890Sdim // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't 4960226890Sdim // right, this will result in better diagnostics (which operand is off) 4961226890Sdim // anyway. 4962226890Sdim if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") && 4963226890Sdim (Operands.size() == 5 || Operands.size() == 6) && 4964226890Sdim static_cast<ARMOperand*>(Operands[3])->isReg() && 4965226890Sdim static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP && 4966235633Sdim static_cast<ARMOperand*>(Operands[1])->getReg() == 0 && 4967235633Sdim (static_cast<ARMOperand*>(Operands[4])->isImm() || 4968235633Sdim (Operands.size() == 6 && 4969235633Sdim static_cast<ARMOperand*>(Operands[5])->isImm()))) 4970226890Sdim return true; 4971226890Sdim 4972226890Sdim return false; 4973226890Sdim} 4974226890Sdim 4975263509Sdimbool ARMAsmParser::shouldOmitPredicateOperand( 4976263509Sdim StringRef Mnemonic, SmallVectorImpl<MCParsedAsmOperand *> &Operands) { 4977263509Sdim // VRINT{Z, R, X} have a predicate operand in VFP, but not in NEON 4978263509Sdim unsigned RegIdx = 3; 4979263509Sdim if ((Mnemonic == "vrintz" || Mnemonic == "vrintx" || Mnemonic == "vrintr") && 4980263509Sdim static_cast<ARMOperand *>(Operands[2])->getToken() == ".f32") { 4981263509Sdim if (static_cast<ARMOperand *>(Operands[3])->isToken() && 4982263509Sdim static_cast<ARMOperand *>(Operands[3])->getToken() == ".f32") 4983263509Sdim RegIdx = 4; 4984263509Sdim 4985263509Sdim if (static_cast<ARMOperand *>(Operands[RegIdx])->isReg() && 4986263509Sdim (ARMMCRegisterClasses[ARM::DPRRegClassID] 4987263509Sdim .contains(static_cast<ARMOperand *>(Operands[RegIdx])->getReg()) || 4988263509Sdim ARMMCRegisterClasses[ARM::QPRRegClassID] 4989263509Sdim .contains(static_cast<ARMOperand *>(Operands[RegIdx])->getReg()))) 4990263509Sdim return true; 4991263509Sdim } 4992263509Sdim return false; 4993263509Sdim} 4994263509Sdim 4995235633Sdimstatic bool isDataTypeToken(StringRef Tok) { 4996235633Sdim return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" || 4997235633Sdim Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" || 4998235633Sdim Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" || 4999235633Sdim Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" || 5000235633Sdim Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" || 5001235633Sdim Tok == ".f" || Tok == ".d"; 5002235633Sdim} 5003235633Sdim 5004235633Sdim// FIXME: This bit should probably be handled via an explicit match class 5005235633Sdim// in the .td files that matches the suffix instead of having it be 5006235633Sdim// a literal string token the way it is now. 5007235633Sdimstatic bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) { 5008235633Sdim return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm"); 5009235633Sdim} 5010252723Sdimstatic void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features, 5011252723Sdim unsigned VariantID); 5012218893Sdim/// Parse an arm instruction mnemonic followed by its operands. 5013245431Sdimbool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 5014245431Sdim SMLoc NameLoc, 5015218893Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 5016235633Sdim // Apply mnemonic aliases before doing anything else, as the destination 5017235633Sdim // mnemnonic may include suffices and we want to handle them normally. 5018235633Sdim // The generic tblgen'erated code does this later, at the start of 5019235633Sdim // MatchInstructionImpl(), but that's too late for aliases that include 5020235633Sdim // any sort of suffix. 5021235633Sdim unsigned AvailableFeatures = getAvailableFeatures(); 5022252723Sdim unsigned AssemblerDialect = getParser().getAssemblerDialect(); 5023252723Sdim applyMnemonicAliases(Name, AvailableFeatures, AssemblerDialect); 5024235633Sdim 5025235633Sdim // First check for the ARM-specific .req directive. 5026235633Sdim if (Parser.getTok().is(AsmToken::Identifier) && 5027235633Sdim Parser.getTok().getIdentifier() == ".req") { 5028235633Sdim parseDirectiveReq(Name, NameLoc); 5029235633Sdim // We always return 'error' for this, as we're done with this 5030235633Sdim // statement and don't need to match the 'instruction." 5031235633Sdim return true; 5032235633Sdim } 5033235633Sdim 5034218893Sdim // Create the leading tokens for the mnemonic, split by '.' characters. 5035218893Sdim size_t Start = 0, Next = Name.find('.'); 5036226890Sdim 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; 5042226890Sdim StringRef ITMask; 5043226890Sdim Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting, 5044226890Sdim ProcessorIMod, ITMask); 5045218893Sdim 5046226890Sdim // In Thumb1, only the branch (B) instruction can be predicated. 5047226890Sdim if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") { 5048252723Sdim Parser.eatToEndOfStatement(); 5049226890Sdim return Error(NameLoc, "conditional execution not supported in Thumb1"); 5050226890Sdim } 5051218893Sdim 5052226890Sdim Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc)); 5053226890Sdim 5054226890Sdim // Handle the IT instruction ITMask. Convert it to a bitmask. This 5055226890Sdim // is the mask as it will be for the IT encoding if the conditional 5056226890Sdim // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case 5057226890Sdim // where the conditional bit0 is zero, the instruction post-processing 5058226890Sdim // will adjust the mask accordingly. 5059226890Sdim if (Mnemonic == "it") { 5060226890Sdim SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2); 5061226890Sdim if (ITMask.size() > 3) { 5062252723Sdim Parser.eatToEndOfStatement(); 5063226890Sdim return Error(Loc, "too many conditions on IT instruction"); 5064226890Sdim } 5065226890Sdim unsigned Mask = 8; 5066226890Sdim for (unsigned i = ITMask.size(); i != 0; --i) { 5067226890Sdim char pos = ITMask[i - 1]; 5068226890Sdim if (pos != 't' && pos != 'e') { 5069252723Sdim Parser.eatToEndOfStatement(); 5070226890Sdim return Error(Loc, "illegal IT block condition mask '" + ITMask + "'"); 5071226890Sdim } 5072226890Sdim Mask >>= 1; 5073226890Sdim if (ITMask[i - 1] == 't') 5074226890Sdim Mask |= 8; 5075226890Sdim } 5076226890Sdim Operands.push_back(ARMOperand::CreateITMask(Mask, Loc)); 5077226890Sdim } 5078226890Sdim 5079226890Sdim // FIXME: This is all a pretty gross hack. We should automatically handle 5080226890Sdim // optional operands like this via tblgen. 5081226890Sdim 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; 5090263509Sdim 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) { 5095252723Sdim Parser.eatToEndOfStatement(); 5096226890Sdim return Error(NameLoc, "instruction '" + Mnemonic + 5097224145Sdim "' can not set flags, but 's' suffix specified"); 5098224145Sdim } 5099226890Sdim // If we had a predication code on an instruction that can't do that, issue an 5100226890Sdim // error. 5101226890Sdim if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) { 5102252723Sdim Parser.eatToEndOfStatement(); 5103226890Sdim return Error(NameLoc, "instruction '" + Mnemonic + 5104226890Sdim "' is not predicable, but condition code specified"); 5105226890Sdim } 5106224145Sdim 5107218893Sdim // Add the carry setting operand, if necessary. 5108226890Sdim if (CanAcceptCarrySet) { 5109226890Sdim SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size()); 5110218893Sdim Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0, 5111226890Sdim Loc)); 5112226890Sdim } 5113218893Sdim 5114218893Sdim // Add the predication code operand, if necessary. 5115218893Sdim if (CanAcceptPredicationCode) { 5116226890Sdim SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() + 5117226890Sdim CarrySetting); 5118218893Sdim Operands.push_back(ARMOperand::CreateCondCode( 5119226890Sdim 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 5135235633Sdim // Some NEON instructions have an optional datatype suffix that is 5136235633Sdim // completely ignored. Check for that. 5137235633Sdim if (isDataTypeToken(ExtraToken) && 5138235633Sdim doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken)) 5139235633Sdim continue; 5140235633Sdim 5141263509Sdim // For for ARM mode generate an error if the .n qualifier is used. 5142263509Sdim if (ExtraToken == ".n" && !isThumb()) { 5143226890Sdim SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start); 5144263509Sdim return Error(Loc, "instruction with .n (narrow) qualifier not allowed in " 5145263509Sdim "arm mode"); 5146263509Sdim } 5147263509Sdim 5148263509Sdim // The .n qualifier is always discarded as that is what the tables 5149263509Sdim // and matcher expect. In ARM mode the .w qualifier has no effect, 5150263509Sdim // so discard it to avoid errors that can be caused by the matcher. 5151263509Sdim if (ExtraToken != ".n" && (isThumb() || ExtraToken != ".w")) { 5152263509Sdim SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start); 5153226890Sdim Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc)); 5154226890Sdim } 5155212904Sdim } 5156212904Sdim 5157212904Sdim // Read the remaining operands. 5158198090Srdivacky if (getLexer().isNot(AsmToken::EndOfStatement)) { 5159198090Srdivacky // Read the first operand. 5160226890Sdim if (parseOperand(Operands, Mnemonic)) { 5161252723Sdim 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. 5169226890Sdim if (parseOperand(Operands, Mnemonic)) { 5170252723Sdim Parser.eatToEndOfStatement(); 5171218893Sdim return true; 5172218893Sdim } 5173198090Srdivacky } 5174198090Srdivacky } 5175218893Sdim 5176218893Sdim if (getLexer().isNot(AsmToken::EndOfStatement)) { 5177226890Sdim SMLoc Loc = getLexer().getLoc(); 5178252723Sdim Parser.eatToEndOfStatement(); 5179226890Sdim return Error(Loc, "unexpected token in argument list"); 5180218893Sdim } 5181218893Sdim 5182218893Sdim Parser.Lex(); // Consume the EndOfStatement 5183226890Sdim 5184226890Sdim // Some instructions, mostly Thumb, have forms for the same mnemonic that 5185226890Sdim // do and don't have a cc_out optional-def operand. With some spot-checks 5186226890Sdim // of the operand list, we can figure out which variant we're trying to 5187226890Sdim // parse and adjust accordingly before actually matching. We shouldn't ever 5188226890Sdim // try to remove a cc_out operand that was explicitly set on the the 5189226890Sdim // mnemonic, of course (CarrySetting == true). Reason number #317 the 5190226890Sdim // table driven matcher doesn't fit well with the ARM instruction set. 5191226890Sdim if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) { 5192226890Sdim ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]); 5193226890Sdim Operands.erase(Operands.begin() + 1); 5194226890Sdim delete Op; 5195226890Sdim } 5196226890Sdim 5197263509Sdim // Some instructions have the same mnemonic, but don't always 5198263509Sdim // have a predicate. Distinguish them here and delete the 5199263509Sdim // predicate if needed. 5200263509Sdim if (shouldOmitPredicateOperand(Mnemonic, Operands)) { 5201263509Sdim ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]); 5202263509Sdim Operands.erase(Operands.begin() + 1); 5203263509Sdim delete Op; 5204263509Sdim } 5205263509Sdim 5206226890Sdim // ARM mode 'blx' need special handling, as the register operand version 5207226890Sdim // is predicable, but the label operand version is not. So, we can't rely 5208226890Sdim // on the Mnemonic based checking to correctly figure out when to put 5209226890Sdim // a k_CondCode operand in the list. If we're trying to match the label 5210226890Sdim // version, remove the k_CondCode operand here. 5211226890Sdim if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 && 5212226890Sdim static_cast<ARMOperand*>(Operands[2])->isImm()) { 5213226890Sdim ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]); 5214226890Sdim Operands.erase(Operands.begin() + 1); 5215226890Sdim delete Op; 5216226890Sdim } 5217226890Sdim 5218252723Sdim // Adjust operands of ldrexd/strexd to MCK_GPRPair. 5219252723Sdim // ldrexd/strexd require even/odd GPR pair. To enforce this constraint, 5220252723Sdim // a single GPRPair reg operand is used in the .td file to replace the two 5221252723Sdim // GPRs. However, when parsing from asm, the two GRPs cannot be automatically 5222252723Sdim // expressed as a GPRPair, so we have to manually merge them. 5223252723Sdim // FIXME: We would really like to be able to tablegen'erate this. 5224252723Sdim if (!isThumb() && Operands.size() > 4 && 5225263509Sdim (Mnemonic == "ldrexd" || Mnemonic == "strexd" || Mnemonic == "ldaexd" || 5226263509Sdim Mnemonic == "stlexd")) { 5227263509Sdim bool isLoad = (Mnemonic == "ldrexd" || Mnemonic == "ldaexd"); 5228252723Sdim unsigned Idx = isLoad ? 2 : 3; 5229252723Sdim ARMOperand* Op1 = static_cast<ARMOperand*>(Operands[Idx]); 5230252723Sdim ARMOperand* Op2 = static_cast<ARMOperand*>(Operands[Idx+1]); 5231252723Sdim 5232252723Sdim const MCRegisterClass& MRC = MRI->getRegClass(ARM::GPRRegClassID); 5233252723Sdim // Adjust only if Op1 and Op2 are GPRs. 5234252723Sdim if (Op1->isReg() && Op2->isReg() && MRC.contains(Op1->getReg()) && 5235252723Sdim MRC.contains(Op2->getReg())) { 5236252723Sdim unsigned Reg1 = Op1->getReg(); 5237252723Sdim unsigned Reg2 = Op2->getReg(); 5238252723Sdim unsigned Rt = MRI->getEncodingValue(Reg1); 5239252723Sdim unsigned Rt2 = MRI->getEncodingValue(Reg2); 5240252723Sdim 5241252723Sdim // Rt2 must be Rt + 1 and Rt must be even. 5242252723Sdim if (Rt + 1 != Rt2 || (Rt & 1)) { 5243252723Sdim Error(Op2->getStartLoc(), isLoad ? 5244252723Sdim "destination operands must be sequential" : 5245252723Sdim "source operands must be sequential"); 5246252723Sdim return true; 5247252723Sdim } 5248252723Sdim unsigned NewReg = MRI->getMatchingSuperReg(Reg1, ARM::gsub_0, 5249252723Sdim &(MRI->getRegClass(ARM::GPRPairRegClassID))); 5250252723Sdim Operands.erase(Operands.begin() + Idx, Operands.begin() + Idx + 2); 5251252723Sdim Operands.insert(Operands.begin() + Idx, ARMOperand::CreateReg( 5252252723Sdim NewReg, Op1->getStartLoc(), Op2->getEndLoc())); 5253252723Sdim delete Op1; 5254252723Sdim delete Op2; 5255226890Sdim } 5256226890Sdim } 5257226890Sdim 5258263509Sdim // FIXME: As said above, this is all a pretty gross hack. This instruction 5259263509Sdim // does not fit with other "subs" and tblgen. 5260263509Sdim // Adjust operands of B9.3.19 SUBS PC, LR, #imm (Thumb2) system instruction 5261263509Sdim // so the Mnemonic is the original name "subs" and delete the predicate 5262263509Sdim // operand so it will match the table entry. 5263263509Sdim if (isThumbTwo() && Mnemonic == "sub" && Operands.size() == 6 && 5264263509Sdim static_cast<ARMOperand*>(Operands[3])->isReg() && 5265263509Sdim static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::PC && 5266263509Sdim static_cast<ARMOperand*>(Operands[4])->isReg() && 5267263509Sdim static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::LR && 5268263509Sdim static_cast<ARMOperand*>(Operands[5])->isImm()) { 5269263509Sdim ARMOperand *Op0 = static_cast<ARMOperand*>(Operands[0]); 5270263509Sdim Operands.erase(Operands.begin()); 5271263509Sdim delete Op0; 5272263509Sdim Operands.insert(Operands.begin(), ARMOperand::CreateToken(Name, NameLoc)); 5273263509Sdim 5274263509Sdim ARMOperand *Op1 = static_cast<ARMOperand*>(Operands[1]); 5275263509Sdim Operands.erase(Operands.begin() + 1); 5276263509Sdim delete Op1; 5277263509Sdim } 5278202375Srdivacky return false; 5279198090Srdivacky} 5280198090Srdivacky 5281226890Sdim// Validate context-sensitive operand constraints. 5282226890Sdim 5283226890Sdim// return 'true' if register list contains non-low GPR registers, 5284226890Sdim// 'false' otherwise. If Reg is in the register list or is HiReg, set 5285226890Sdim// 'containsReg' to true. 5286226890Sdimstatic bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg, 5287226890Sdim unsigned HiReg, bool &containsReg) { 5288226890Sdim containsReg = false; 5289226890Sdim for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) { 5290226890Sdim unsigned OpReg = Inst.getOperand(i).getReg(); 5291226890Sdim if (OpReg == Reg) 5292226890Sdim containsReg = true; 5293226890Sdim // Anything other than a low register isn't legal here. 5294226890Sdim if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg)) 5295226890Sdim return true; 5296226890Sdim } 5297226890Sdim return false; 5298226890Sdim} 5299226890Sdim 5300226890Sdim// Check if the specified regisgter is in the register list of the inst, 5301226890Sdim// starting at the indicated operand number. 5302226890Sdimstatic bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) { 5303226890Sdim for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) { 5304226890Sdim unsigned OpReg = Inst.getOperand(i).getReg(); 5305226890Sdim if (OpReg == Reg) 5306226890Sdim return true; 5307226890Sdim } 5308226890Sdim return false; 5309226890Sdim} 5310226890Sdim 5311263509Sdim// Return true if instruction has the interesting property of being 5312263509Sdim// allowed in IT blocks, but not being predicable. 5313263509Sdimstatic bool instIsBreakpoint(const MCInst &Inst) { 5314263509Sdim return Inst.getOpcode() == ARM::tBKPT || 5315263509Sdim Inst.getOpcode() == ARM::BKPT || 5316263509Sdim Inst.getOpcode() == ARM::tHLT || 5317263509Sdim Inst.getOpcode() == ARM::HLT; 5318263509Sdim 5319226890Sdim} 5320226890Sdim 5321226890Sdim// FIXME: We would really like to be able to tablegen'erate this. 5322218893Sdimbool ARMAsmParser:: 5323226890SdimvalidateInstruction(MCInst &Inst, 5324226890Sdim const SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 5325263509Sdim const MCInstrDesc &MCID = MII.get(Inst.getOpcode()); 5326226890Sdim SMLoc Loc = Operands[0]->getStartLoc(); 5327263509Sdim 5328226890Sdim // Check the IT block state first. 5329263509Sdim // NOTE: BKPT and HLT instructions have the interesting property of being 5330263509Sdim // allowed in IT blocks, but not being predicable. They just always execute. 5331263509Sdim if (inITBlock() && !instIsBreakpoint(Inst)) { 5332263509Sdim unsigned Bit = 1; 5333226890Sdim if (ITState.FirstCond) 5334226890Sdim ITState.FirstCond = false; 5335226890Sdim else 5336263509Sdim Bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1; 5337226890Sdim // The instruction must be predicable. 5338226890Sdim if (!MCID.isPredicable()) 5339226890Sdim return Error(Loc, "instructions in IT block must be predicable"); 5340226890Sdim unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm(); 5341263509Sdim unsigned ITCond = Bit ? ITState.Cond : 5342226890Sdim ARMCC::getOppositeCondition(ITState.Cond); 5343226890Sdim if (Cond != ITCond) { 5344226890Sdim // Find the condition code Operand to get its SMLoc information. 5345226890Sdim SMLoc CondLoc; 5346263509Sdim for (unsigned I = 1; I < Operands.size(); ++I) 5347263509Sdim if (static_cast<ARMOperand*>(Operands[I])->isCondCode()) 5348263509Sdim CondLoc = Operands[I]->getStartLoc(); 5349226890Sdim return Error(CondLoc, "incorrect condition in IT block; got '" + 5350226890Sdim StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) + 5351226890Sdim "', but expected '" + 5352226890Sdim ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'"); 5353226890Sdim } 5354226890Sdim // Check for non-'al' condition codes outside of the IT block. 5355226890Sdim } else if (isThumbTwo() && MCID.isPredicable() && 5356226890Sdim Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() != 5357263509Sdim ARMCC::AL && Inst.getOpcode() != ARM::tBcc && 5358263509Sdim Inst.getOpcode() != ARM::t2Bcc) 5359226890Sdim return Error(Loc, "predicated instructions must be in IT block"); 5360226890Sdim 5361263509Sdim const unsigned Opcode = Inst.getOpcode(); 5362263509Sdim switch (Opcode) { 5363226890Sdim case ARM::LDRD: 5364226890Sdim case ARM::LDRD_PRE: 5365252723Sdim case ARM::LDRD_POST: { 5366263509Sdim const unsigned RtReg = Inst.getOperand(0).getReg(); 5367263509Sdim 5368263509Sdim // Rt can't be R14. 5369263509Sdim if (RtReg == ARM::LR) 5370263509Sdim return Error(Operands[3]->getStartLoc(), 5371263509Sdim "Rt can't be R14"); 5372263509Sdim 5373263509Sdim const unsigned Rt = MRI->getEncodingValue(RtReg); 5374263509Sdim // Rt must be even-numbered. 5375263509Sdim if ((Rt & 1) == 1) 5376263509Sdim return Error(Operands[3]->getStartLoc(), 5377263509Sdim "Rt must be even-numbered"); 5378263509Sdim 5379226890Sdim // Rt2 must be Rt + 1. 5380263509Sdim const unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(1).getReg()); 5381226890Sdim if (Rt2 != Rt + 1) 5382226890Sdim return Error(Operands[3]->getStartLoc(), 5383226890Sdim "destination operands must be sequential"); 5384263509Sdim 5385263509Sdim if (Opcode == ARM::LDRD_PRE || Opcode == ARM::LDRD_POST) { 5386263509Sdim const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(3).getReg()); 5387263509Sdim // For addressing modes with writeback, the base register needs to be 5388263509Sdim // different from the destination registers. 5389263509Sdim if (Rn == Rt || Rn == Rt2) 5390263509Sdim return Error(Operands[3]->getStartLoc(), 5391263509Sdim "base register needs to be different from destination " 5392263509Sdim "registers"); 5393263509Sdim } 5394263509Sdim 5395226890Sdim return false; 5396226890Sdim } 5397263509Sdim case ARM::t2LDRDi8: 5398263509Sdim case ARM::t2LDRD_PRE: 5399263509Sdim case ARM::t2LDRD_POST: { 5400263509Sdim // Rt2 must be different from Rt. 5401263509Sdim unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg()); 5402263509Sdim unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(1).getReg()); 5403263509Sdim if (Rt2 == Rt) 5404263509Sdim return Error(Operands[3]->getStartLoc(), 5405263509Sdim "destination operands can't be identical"); 5406263509Sdim return false; 5407263509Sdim } 5408226890Sdim case ARM::STRD: { 5409226890Sdim // Rt2 must be Rt + 1. 5410245431Sdim unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg()); 5411245431Sdim unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(1).getReg()); 5412226890Sdim if (Rt2 != Rt + 1) 5413226890Sdim return Error(Operands[3]->getStartLoc(), 5414226890Sdim "source operands must be sequential"); 5415226890Sdim return false; 5416226890Sdim } 5417226890Sdim case ARM::STRD_PRE: 5418252723Sdim case ARM::STRD_POST: { 5419226890Sdim // Rt2 must be Rt + 1. 5420245431Sdim unsigned Rt = MRI->getEncodingValue(Inst.getOperand(1).getReg()); 5421245431Sdim unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(2).getReg()); 5422226890Sdim if (Rt2 != Rt + 1) 5423226890Sdim return Error(Operands[3]->getStartLoc(), 5424226890Sdim "source operands must be sequential"); 5425226890Sdim return false; 5426226890Sdim } 5427226890Sdim case ARM::SBFX: 5428226890Sdim case ARM::UBFX: { 5429263509Sdim // Width must be in range [1, 32-lsb]. 5430263509Sdim unsigned LSB = Inst.getOperand(2).getImm(); 5431263509Sdim unsigned Widthm1 = Inst.getOperand(3).getImm(); 5432263509Sdim if (Widthm1 >= 32 - LSB) 5433226890Sdim return Error(Operands[5]->getStartLoc(), 5434226890Sdim "bitfield width must be in range [1,32-lsb]"); 5435226890Sdim return false; 5436226890Sdim } 5437263509Sdim // Notionally handles ARM::tLDMIA_UPD too. 5438226890Sdim case ARM::tLDMIA: { 5439226890Sdim // If we're parsing Thumb2, the .w variant is available and handles 5440263509Sdim // most cases that are normally illegal for a Thumb1 LDM instruction. 5441263509Sdim // We'll make the transformation in processInstruction() if necessary. 5442226890Sdim // 5443226890Sdim // Thumb LDM instructions are writeback iff the base register is not 5444226890Sdim // in the register list. 5445226890Sdim unsigned Rn = Inst.getOperand(0).getReg(); 5446263509Sdim bool HasWritebackToken = 5447226890Sdim (static_cast<ARMOperand*>(Operands[3])->isToken() && 5448226890Sdim static_cast<ARMOperand*>(Operands[3])->getToken() == "!"); 5449263509Sdim bool ListContainsBase; 5450263509Sdim if (checkLowRegisterList(Inst, 3, Rn, 0, ListContainsBase) && !isThumbTwo()) 5451263509Sdim return Error(Operands[3 + HasWritebackToken]->getStartLoc(), 5452226890Sdim "registers must be in range r0-r7"); 5453226890Sdim // If we should have writeback, then there should be a '!' token. 5454263509Sdim if (!ListContainsBase && !HasWritebackToken && !isThumbTwo()) 5455226890Sdim return Error(Operands[2]->getStartLoc(), 5456226890Sdim "writeback operator '!' expected"); 5457226890Sdim // If we should not have writeback, there must not be a '!'. This is 5458226890Sdim // true even for the 32-bit wide encodings. 5459263509Sdim if (ListContainsBase && HasWritebackToken) 5460226890Sdim return Error(Operands[3]->getStartLoc(), 5461226890Sdim "writeback operator '!' not allowed when base register " 5462226890Sdim "in register list"); 5463226890Sdim 5464226890Sdim break; 5465226890Sdim } 5466263509Sdim case ARM::LDMIA_UPD: 5467263509Sdim case ARM::LDMDB_UPD: 5468263509Sdim case ARM::LDMIB_UPD: 5469263509Sdim case ARM::LDMDA_UPD: 5470263509Sdim // ARM variants loading and updating the same register are only officially 5471263509Sdim // UNPREDICTABLE on v7 upwards. Goodness knows what they did before. 5472263509Sdim if (!hasV7Ops()) 5473263509Sdim break; 5474263509Sdim // Fallthrough 5475263509Sdim case ARM::t2LDMIA_UPD: 5476263509Sdim case ARM::t2LDMDB_UPD: 5477263509Sdim case ARM::t2STMIA_UPD: 5478263509Sdim case ARM::t2STMDB_UPD: { 5479226890Sdim if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg())) 5480263509Sdim return Error(Operands.back()->getStartLoc(), 5481263509Sdim "writeback register not allowed in register list"); 5482263509Sdim break; 5483263509Sdim } 5484263509Sdim case ARM::sysLDMIA_UPD: 5485263509Sdim case ARM::sysLDMDA_UPD: 5486263509Sdim case ARM::sysLDMDB_UPD: 5487263509Sdim case ARM::sysLDMIB_UPD: 5488263509Sdim if (!listContainsReg(Inst, 3, ARM::PC)) 5489226890Sdim return Error(Operands[4]->getStartLoc(), 5490263509Sdim "writeback register only allowed on system LDM " 5491263509Sdim "if PC in register-list"); 5492226890Sdim break; 5493263509Sdim case ARM::sysSTMIA_UPD: 5494263509Sdim case ARM::sysSTMDA_UPD: 5495263509Sdim case ARM::sysSTMDB_UPD: 5496263509Sdim case ARM::sysSTMIB_UPD: 5497263509Sdim return Error(Operands[2]->getStartLoc(), 5498263509Sdim "system STM cannot have writeback register"); 5499263509Sdim break; 5500245431Sdim case ARM::tMUL: { 5501245431Sdim // The second source operand must be the same register as the destination 5502245431Sdim // operand. 5503245431Sdim // 5504245431Sdim // In this case, we must directly check the parsed operands because the 5505245431Sdim // cvtThumbMultiply() function is written in such a way that it guarantees 5506245431Sdim // this first statement is always true for the new Inst. Essentially, the 5507245431Sdim // destination is unconditionally copied into the second source operand 5508245431Sdim // without checking to see if it matches what we actually parsed. 5509245431Sdim if (Operands.size() == 6 && 5510245431Sdim (((ARMOperand*)Operands[3])->getReg() != 5511245431Sdim ((ARMOperand*)Operands[5])->getReg()) && 5512245431Sdim (((ARMOperand*)Operands[3])->getReg() != 5513245431Sdim ((ARMOperand*)Operands[4])->getReg())) { 5514245431Sdim return Error(Operands[3]->getStartLoc(), 5515245431Sdim "destination register must match source register"); 5516245431Sdim } 5517245431Sdim break; 5518245431Sdim } 5519235633Sdim // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2, 5520235633Sdim // so only issue a diagnostic for thumb1. The instructions will be 5521235633Sdim // switched to the t2 encodings in processInstruction() if necessary. 5522226890Sdim case ARM::tPOP: { 5523263509Sdim bool ListContainsBase; 5524263509Sdim if (checkLowRegisterList(Inst, 2, 0, ARM::PC, ListContainsBase) && 5525235633Sdim !isThumbTwo()) 5526226890Sdim return Error(Operands[2]->getStartLoc(), 5527226890Sdim "registers must be in range r0-r7 or pc"); 5528226890Sdim break; 5529226890Sdim } 5530226890Sdim case ARM::tPUSH: { 5531263509Sdim bool ListContainsBase; 5532263509Sdim if (checkLowRegisterList(Inst, 2, 0, ARM::LR, ListContainsBase) && 5533235633Sdim !isThumbTwo()) 5534226890Sdim return Error(Operands[2]->getStartLoc(), 5535226890Sdim "registers must be in range r0-r7 or lr"); 5536226890Sdim break; 5537226890Sdim } 5538226890Sdim case ARM::tSTMIA_UPD: { 5539263509Sdim bool ListContainsBase, InvalidLowList; 5540263509Sdim InvalidLowList = checkLowRegisterList(Inst, 4, Inst.getOperand(0).getReg(), 5541263509Sdim 0, ListContainsBase); 5542263509Sdim if (InvalidLowList && !isThumbTwo()) 5543226890Sdim return Error(Operands[4]->getStartLoc(), 5544226890Sdim "registers must be in range r0-r7"); 5545263509Sdim 5546263509Sdim // This would be converted to a 32-bit stm, but that's not valid if the 5547263509Sdim // writeback register is in the list. 5548263509Sdim if (InvalidLowList && ListContainsBase) 5549263509Sdim return Error(Operands[4]->getStartLoc(), 5550263509Sdim "writeback operator '!' not allowed when base register " 5551263509Sdim "in register list"); 5552226890Sdim break; 5553226890Sdim } 5554245431Sdim case ARM::tADDrSP: { 5555245431Sdim // If the non-SP source operand and the destination operand are not the 5556245431Sdim // same, we need thumb2 (for the wide encoding), or we have an error. 5557245431Sdim if (!isThumbTwo() && 5558245431Sdim Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) { 5559245431Sdim return Error(Operands[4]->getStartLoc(), 5560245431Sdim "source register must be the same as destination"); 5561245431Sdim } 5562245431Sdim break; 5563226890Sdim } 5564263509Sdim // Final range checking for Thumb unconditional branch instructions. 5565263509Sdim case ARM::tB: 5566263509Sdim if (!(static_cast<ARMOperand*>(Operands[2]))->isSignedOffset<11, 1>()) 5567263509Sdim return Error(Operands[2]->getStartLoc(), "branch target out of range"); 5568263509Sdim break; 5569263509Sdim case ARM::t2B: { 5570263509Sdim int op = (Operands[2]->isImm()) ? 2 : 3; 5571263509Sdim if (!(static_cast<ARMOperand*>(Operands[op]))->isSignedOffset<24, 1>()) 5572263509Sdim return Error(Operands[op]->getStartLoc(), "branch target out of range"); 5573263509Sdim break; 5574245431Sdim } 5575263509Sdim // Final range checking for Thumb conditional branch instructions. 5576263509Sdim case ARM::tBcc: 5577263509Sdim if (!(static_cast<ARMOperand*>(Operands[2]))->isSignedOffset<8, 1>()) 5578263509Sdim return Error(Operands[2]->getStartLoc(), "branch target out of range"); 5579263509Sdim break; 5580263509Sdim case ARM::t2Bcc: { 5581263509Sdim int Op = (Operands[2]->isImm()) ? 2 : 3; 5582263509Sdim if (!(static_cast<ARMOperand*>(Operands[Op]))->isSignedOffset<20, 1>()) 5583263509Sdim return Error(Operands[Op]->getStartLoc(), "branch target out of range"); 5584263509Sdim break; 5585263509Sdim } 5586263509Sdim } 5587226890Sdim 5588226890Sdim return false; 5589226890Sdim} 5590226890Sdim 5591235633Sdimstatic unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) { 5592235633Sdim switch(Opc) { 5593235633Sdim default: llvm_unreachable("unexpected opcode!"); 5594235633Sdim // VST1LN 5595235633Sdim case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD; 5596235633Sdim case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD; 5597235633Sdim case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD; 5598235633Sdim case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD; 5599235633Sdim case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD; 5600235633Sdim case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD; 5601235633Sdim case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8; 5602235633Sdim case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16; 5603235633Sdim case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32; 5604235633Sdim 5605235633Sdim // VST2LN 5606235633Sdim case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD; 5607235633Sdim case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD; 5608235633Sdim case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD; 5609235633Sdim case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD; 5610235633Sdim case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD; 5611235633Sdim 5612235633Sdim case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD; 5613235633Sdim case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD; 5614235633Sdim case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD; 5615235633Sdim case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD; 5616235633Sdim case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD; 5617235633Sdim 5618235633Sdim case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8; 5619235633Sdim case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16; 5620235633Sdim case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32; 5621235633Sdim case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16; 5622235633Sdim case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32; 5623235633Sdim 5624235633Sdim // VST3LN 5625235633Sdim case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD; 5626235633Sdim case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD; 5627235633Sdim case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD; 5628235633Sdim case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD; 5629235633Sdim case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD; 5630235633Sdim case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD; 5631235633Sdim case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD; 5632235633Sdim case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD; 5633235633Sdim case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD; 5634235633Sdim case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD; 5635235633Sdim case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8; 5636235633Sdim case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16; 5637235633Sdim case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32; 5638235633Sdim case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16; 5639235633Sdim case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32; 5640235633Sdim 5641235633Sdim // VST3 5642235633Sdim case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD; 5643235633Sdim case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD; 5644235633Sdim case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD; 5645235633Sdim case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD; 5646235633Sdim case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD; 5647235633Sdim case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD; 5648235633Sdim case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD; 5649235633Sdim case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD; 5650235633Sdim case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD; 5651235633Sdim case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD; 5652235633Sdim case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD; 5653235633Sdim case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD; 5654235633Sdim case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8; 5655235633Sdim case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16; 5656235633Sdim case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32; 5657235633Sdim case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8; 5658235633Sdim case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16; 5659235633Sdim case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32; 5660235633Sdim 5661235633Sdim // VST4LN 5662235633Sdim case ARM::VST4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD; 5663235633Sdim case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD; 5664235633Sdim case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD; 5665235633Sdim case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD; 5666235633Sdim case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD; 5667235633Sdim case ARM::VST4LNdWB_register_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD; 5668235633Sdim case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD; 5669235633Sdim case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD; 5670235633Sdim case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD; 5671235633Sdim case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD; 5672235633Sdim case ARM::VST4LNdAsm_8: Spacing = 1; return ARM::VST4LNd8; 5673235633Sdim case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16; 5674235633Sdim case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32; 5675235633Sdim case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16; 5676235633Sdim case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32; 5677235633Sdim 5678235633Sdim // VST4 5679235633Sdim case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD; 5680235633Sdim case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD; 5681235633Sdim case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD; 5682235633Sdim case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD; 5683235633Sdim case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD; 5684235633Sdim case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD; 5685235633Sdim case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD; 5686235633Sdim case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD; 5687235633Sdim case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD; 5688235633Sdim case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD; 5689235633Sdim case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD; 5690235633Sdim case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD; 5691235633Sdim case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8; 5692235633Sdim case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16; 5693235633Sdim case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32; 5694235633Sdim case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8; 5695235633Sdim case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16; 5696235633Sdim case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32; 5697235633Sdim } 5698235633Sdim} 5699235633Sdim 5700235633Sdimstatic unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) { 5701235633Sdim switch(Opc) { 5702235633Sdim default: llvm_unreachable("unexpected opcode!"); 5703235633Sdim // VLD1LN 5704235633Sdim case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD; 5705235633Sdim case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD; 5706235633Sdim case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD; 5707235633Sdim case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD; 5708235633Sdim case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD; 5709235633Sdim case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD; 5710235633Sdim case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8; 5711235633Sdim case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16; 5712235633Sdim case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32; 5713235633Sdim 5714235633Sdim // VLD2LN 5715235633Sdim case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD; 5716235633Sdim case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD; 5717235633Sdim case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD; 5718235633Sdim case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD; 5719235633Sdim case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD; 5720235633Sdim case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD; 5721235633Sdim case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD; 5722235633Sdim case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD; 5723235633Sdim case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD; 5724235633Sdim case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD; 5725235633Sdim case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8; 5726235633Sdim case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16; 5727235633Sdim case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32; 5728235633Sdim case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16; 5729235633Sdim case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32; 5730235633Sdim 5731235633Sdim // VLD3DUP 5732235633Sdim case ARM::VLD3DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD; 5733235633Sdim case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD; 5734235633Sdim case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD; 5735235633Sdim case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD; 5736235633Sdim case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPq16_UPD; 5737235633Sdim case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD; 5738235633Sdim case ARM::VLD3DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD; 5739235633Sdim case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD; 5740235633Sdim case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD; 5741235633Sdim case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD; 5742235633Sdim case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD; 5743235633Sdim case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD; 5744235633Sdim case ARM::VLD3DUPdAsm_8: Spacing = 1; return ARM::VLD3DUPd8; 5745235633Sdim case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16; 5746235633Sdim case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32; 5747235633Sdim case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8; 5748235633Sdim case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16; 5749235633Sdim case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32; 5750235633Sdim 5751235633Sdim // VLD3LN 5752235633Sdim case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD; 5753235633Sdim case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD; 5754235633Sdim case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD; 5755235633Sdim case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD; 5756235633Sdim case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD; 5757235633Sdim case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD; 5758235633Sdim case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD; 5759235633Sdim case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD; 5760235633Sdim case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD; 5761235633Sdim case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD; 5762235633Sdim case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8; 5763235633Sdim case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16; 5764235633Sdim case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32; 5765235633Sdim case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16; 5766235633Sdim case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32; 5767235633Sdim 5768235633Sdim // VLD3 5769235633Sdim case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD; 5770235633Sdim case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD; 5771235633Sdim case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD; 5772235633Sdim case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD; 5773235633Sdim case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD; 5774235633Sdim case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD; 5775235633Sdim case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD; 5776235633Sdim case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD; 5777235633Sdim case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD; 5778235633Sdim case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD; 5779235633Sdim case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD; 5780235633Sdim case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD; 5781235633Sdim case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8; 5782235633Sdim case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16; 5783235633Sdim case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32; 5784235633Sdim case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8; 5785235633Sdim case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16; 5786235633Sdim case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32; 5787235633Sdim 5788235633Sdim // VLD4LN 5789235633Sdim case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD; 5790235633Sdim case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD; 5791235633Sdim case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD; 5792235633Sdim case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNq16_UPD; 5793235633Sdim case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD; 5794235633Sdim case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD; 5795235633Sdim case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD; 5796235633Sdim case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD; 5797235633Sdim case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD; 5798235633Sdim case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD; 5799235633Sdim case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8; 5800235633Sdim case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16; 5801235633Sdim case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32; 5802235633Sdim case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16; 5803235633Sdim case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32; 5804235633Sdim 5805235633Sdim // VLD4DUP 5806235633Sdim case ARM::VLD4DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD; 5807235633Sdim case ARM::VLD4DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD; 5808235633Sdim case ARM::VLD4DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD; 5809235633Sdim case ARM::VLD4DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPq8_UPD; 5810235633Sdim case ARM::VLD4DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPq16_UPD; 5811235633Sdim case ARM::VLD4DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD; 5812235633Sdim case ARM::VLD4DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD; 5813235633Sdim case ARM::VLD4DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD; 5814235633Sdim case ARM::VLD4DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD; 5815235633Sdim case ARM::VLD4DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD4DUPq8_UPD; 5816235633Sdim case ARM::VLD4DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD4DUPq16_UPD; 5817235633Sdim case ARM::VLD4DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD; 5818235633Sdim case ARM::VLD4DUPdAsm_8: Spacing = 1; return ARM::VLD4DUPd8; 5819235633Sdim case ARM::VLD4DUPdAsm_16: Spacing = 1; return ARM::VLD4DUPd16; 5820235633Sdim case ARM::VLD4DUPdAsm_32: Spacing = 1; return ARM::VLD4DUPd32; 5821235633Sdim case ARM::VLD4DUPqAsm_8: Spacing = 2; return ARM::VLD4DUPq8; 5822235633Sdim case ARM::VLD4DUPqAsm_16: Spacing = 2; return ARM::VLD4DUPq16; 5823235633Sdim case ARM::VLD4DUPqAsm_32: Spacing = 2; return ARM::VLD4DUPq32; 5824235633Sdim 5825235633Sdim // VLD4 5826235633Sdim case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD; 5827235633Sdim case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD; 5828235633Sdim case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD; 5829235633Sdim case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD; 5830235633Sdim case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD; 5831235633Sdim case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD; 5832235633Sdim case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD; 5833235633Sdim case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD; 5834235633Sdim case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD; 5835235633Sdim case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD; 5836235633Sdim case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD; 5837235633Sdim case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD; 5838235633Sdim case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8; 5839235633Sdim case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16; 5840235633Sdim case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32; 5841235633Sdim case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8; 5842235633Sdim case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16; 5843235633Sdim case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32; 5844235633Sdim } 5845235633Sdim} 5846235633Sdim 5847235633Sdimbool ARMAsmParser:: 5848226890SdimprocessInstruction(MCInst &Inst, 5849226890Sdim const SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 5850226890Sdim switch (Inst.getOpcode()) { 5851245431Sdim // Alias for alternate form of 'ADR Rd, #imm' instruction. 5852245431Sdim case ARM::ADDri: { 5853245431Sdim if (Inst.getOperand(1).getReg() != ARM::PC || 5854245431Sdim Inst.getOperand(5).getReg() != 0) 5855245431Sdim return false; 5856245431Sdim MCInst TmpInst; 5857245431Sdim TmpInst.setOpcode(ARM::ADR); 5858245431Sdim TmpInst.addOperand(Inst.getOperand(0)); 5859245431Sdim TmpInst.addOperand(Inst.getOperand(2)); 5860245431Sdim TmpInst.addOperand(Inst.getOperand(3)); 5861245431Sdim TmpInst.addOperand(Inst.getOperand(4)); 5862245431Sdim Inst = TmpInst; 5863245431Sdim return true; 5864245431Sdim } 5865235633Sdim // Aliases for alternate PC+imm syntax of LDR instructions. 5866235633Sdim case ARM::t2LDRpcrel: 5867252723Sdim // Select the narrow version if the immediate will fit. 5868252723Sdim if (Inst.getOperand(1).getImm() > 0 && 5869263509Sdim Inst.getOperand(1).getImm() <= 0xff && 5870263509Sdim !(static_cast<ARMOperand*>(Operands[2])->isToken() && 5871263509Sdim static_cast<ARMOperand*>(Operands[2])->getToken() == ".w")) 5872252723Sdim Inst.setOpcode(ARM::tLDRpci); 5873252723Sdim else 5874252723Sdim Inst.setOpcode(ARM::t2LDRpci); 5875235633Sdim return true; 5876235633Sdim case ARM::t2LDRBpcrel: 5877235633Sdim Inst.setOpcode(ARM::t2LDRBpci); 5878235633Sdim return true; 5879235633Sdim case ARM::t2LDRHpcrel: 5880235633Sdim Inst.setOpcode(ARM::t2LDRHpci); 5881235633Sdim return true; 5882235633Sdim case ARM::t2LDRSBpcrel: 5883235633Sdim Inst.setOpcode(ARM::t2LDRSBpci); 5884235633Sdim return true; 5885235633Sdim case ARM::t2LDRSHpcrel: 5886235633Sdim Inst.setOpcode(ARM::t2LDRSHpci); 5887235633Sdim return true; 5888235633Sdim // Handle NEON VST complex aliases. 5889235633Sdim case ARM::VST1LNdWB_register_Asm_8: 5890235633Sdim case ARM::VST1LNdWB_register_Asm_16: 5891235633Sdim case ARM::VST1LNdWB_register_Asm_32: { 5892235633Sdim MCInst TmpInst; 5893235633Sdim // Shuffle the operands around so the lane index operand is in the 5894235633Sdim // right place. 5895235633Sdim unsigned Spacing; 5896235633Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 5897235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 5898235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 5899235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 5900235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rm 5901235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 5902235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 5903235633Sdim TmpInst.addOperand(Inst.getOperand(5)); // CondCode 5904235633Sdim TmpInst.addOperand(Inst.getOperand(6)); 5905235633Sdim Inst = TmpInst; 5906235633Sdim return true; 5907235633Sdim } 5908235633Sdim 5909235633Sdim case ARM::VST2LNdWB_register_Asm_8: 5910235633Sdim case ARM::VST2LNdWB_register_Asm_16: 5911235633Sdim case ARM::VST2LNdWB_register_Asm_32: 5912235633Sdim case ARM::VST2LNqWB_register_Asm_16: 5913235633Sdim case ARM::VST2LNqWB_register_Asm_32: { 5914235633Sdim MCInst TmpInst; 5915235633Sdim // Shuffle the operands around so the lane index operand is in the 5916235633Sdim // right place. 5917235633Sdim unsigned Spacing; 5918235633Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 5919235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 5920235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 5921235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 5922235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rm 5923235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 5924235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 5925235633Sdim Spacing)); 5926235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 5927235633Sdim TmpInst.addOperand(Inst.getOperand(5)); // CondCode 5928235633Sdim TmpInst.addOperand(Inst.getOperand(6)); 5929235633Sdim Inst = TmpInst; 5930235633Sdim return true; 5931235633Sdim } 5932235633Sdim 5933235633Sdim case ARM::VST3LNdWB_register_Asm_8: 5934235633Sdim case ARM::VST3LNdWB_register_Asm_16: 5935235633Sdim case ARM::VST3LNdWB_register_Asm_32: 5936235633Sdim case ARM::VST3LNqWB_register_Asm_16: 5937235633Sdim case ARM::VST3LNqWB_register_Asm_32: { 5938235633Sdim MCInst TmpInst; 5939235633Sdim // Shuffle the operands around so the lane index operand is in the 5940235633Sdim // right place. 5941235633Sdim unsigned Spacing; 5942235633Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 5943235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 5944235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 5945235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 5946235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rm 5947235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 5948235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 5949235633Sdim Spacing)); 5950235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 5951235633Sdim Spacing * 2)); 5952235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 5953235633Sdim TmpInst.addOperand(Inst.getOperand(5)); // CondCode 5954235633Sdim TmpInst.addOperand(Inst.getOperand(6)); 5955235633Sdim Inst = TmpInst; 5956235633Sdim return true; 5957235633Sdim } 5958235633Sdim 5959235633Sdim case ARM::VST4LNdWB_register_Asm_8: 5960235633Sdim case ARM::VST4LNdWB_register_Asm_16: 5961235633Sdim case ARM::VST4LNdWB_register_Asm_32: 5962235633Sdim case ARM::VST4LNqWB_register_Asm_16: 5963235633Sdim case ARM::VST4LNqWB_register_Asm_32: { 5964235633Sdim MCInst TmpInst; 5965235633Sdim // Shuffle the operands around so the lane index operand is in the 5966235633Sdim // right place. 5967235633Sdim unsigned Spacing; 5968235633Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 5969235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 5970235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 5971235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 5972235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rm 5973235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 5974235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 5975235633Sdim Spacing)); 5976235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 5977235633Sdim Spacing * 2)); 5978235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 5979235633Sdim Spacing * 3)); 5980235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 5981235633Sdim TmpInst.addOperand(Inst.getOperand(5)); // CondCode 5982235633Sdim TmpInst.addOperand(Inst.getOperand(6)); 5983235633Sdim Inst = TmpInst; 5984235633Sdim return true; 5985235633Sdim } 5986235633Sdim 5987235633Sdim case ARM::VST1LNdWB_fixed_Asm_8: 5988235633Sdim case ARM::VST1LNdWB_fixed_Asm_16: 5989235633Sdim case ARM::VST1LNdWB_fixed_Asm_32: { 5990235633Sdim MCInst TmpInst; 5991235633Sdim // Shuffle the operands around so the lane index operand is in the 5992235633Sdim // right place. 5993235633Sdim unsigned Spacing; 5994235633Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 5995235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 5996235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 5997235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 5998235633Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 5999235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6000235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6001235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6002235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6003235633Sdim Inst = TmpInst; 6004235633Sdim return true; 6005235633Sdim } 6006235633Sdim 6007235633Sdim case ARM::VST2LNdWB_fixed_Asm_8: 6008235633Sdim case ARM::VST2LNdWB_fixed_Asm_16: 6009235633Sdim case ARM::VST2LNdWB_fixed_Asm_32: 6010235633Sdim case ARM::VST2LNqWB_fixed_Asm_16: 6011235633Sdim case ARM::VST2LNqWB_fixed_Asm_32: { 6012235633Sdim MCInst TmpInst; 6013235633Sdim // Shuffle the operands around so the lane index operand is in the 6014235633Sdim // right place. 6015235633Sdim unsigned Spacing; 6016235633Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6017235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 6018235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6019235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6020235633Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6021235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6022235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6023235633Sdim Spacing)); 6024235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6025235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6026235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6027235633Sdim Inst = TmpInst; 6028235633Sdim return true; 6029235633Sdim } 6030235633Sdim 6031235633Sdim case ARM::VST3LNdWB_fixed_Asm_8: 6032235633Sdim case ARM::VST3LNdWB_fixed_Asm_16: 6033235633Sdim case ARM::VST3LNdWB_fixed_Asm_32: 6034235633Sdim case ARM::VST3LNqWB_fixed_Asm_16: 6035235633Sdim case ARM::VST3LNqWB_fixed_Asm_32: { 6036235633Sdim MCInst TmpInst; 6037235633Sdim // Shuffle the operands around so the lane index operand is in the 6038235633Sdim // right place. 6039235633Sdim unsigned Spacing; 6040235633Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6041235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 6042235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6043235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6044235633Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6045235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6046235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6047235633Sdim Spacing)); 6048235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6049235633Sdim Spacing * 2)); 6050235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6051235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6052235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6053235633Sdim Inst = TmpInst; 6054235633Sdim return true; 6055235633Sdim } 6056235633Sdim 6057235633Sdim case ARM::VST4LNdWB_fixed_Asm_8: 6058235633Sdim case ARM::VST4LNdWB_fixed_Asm_16: 6059235633Sdim case ARM::VST4LNdWB_fixed_Asm_32: 6060235633Sdim case ARM::VST4LNqWB_fixed_Asm_16: 6061235633Sdim case ARM::VST4LNqWB_fixed_Asm_32: { 6062235633Sdim MCInst TmpInst; 6063235633Sdim // Shuffle the operands around so the lane index operand is in the 6064235633Sdim // right place. 6065235633Sdim unsigned Spacing; 6066235633Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6067235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 6068235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6069235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6070235633Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6071235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6072235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6073235633Sdim Spacing)); 6074235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6075235633Sdim Spacing * 2)); 6076235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6077235633Sdim Spacing * 3)); 6078235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6079235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6080235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6081235633Sdim Inst = TmpInst; 6082235633Sdim return true; 6083235633Sdim } 6084235633Sdim 6085235633Sdim case ARM::VST1LNdAsm_8: 6086235633Sdim case ARM::VST1LNdAsm_16: 6087235633Sdim case ARM::VST1LNdAsm_32: { 6088235633Sdim MCInst TmpInst; 6089235633Sdim // Shuffle the operands around so the lane index operand is in the 6090235633Sdim // right place. 6091235633Sdim unsigned Spacing; 6092235633Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6093235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6094235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6095235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6096235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6097235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6098235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6099235633Sdim Inst = TmpInst; 6100235633Sdim return true; 6101235633Sdim } 6102235633Sdim 6103235633Sdim case ARM::VST2LNdAsm_8: 6104235633Sdim case ARM::VST2LNdAsm_16: 6105235633Sdim case ARM::VST2LNdAsm_32: 6106235633Sdim case ARM::VST2LNqAsm_16: 6107235633Sdim case ARM::VST2LNqAsm_32: { 6108235633Sdim MCInst TmpInst; 6109235633Sdim // Shuffle the operands around so the lane index operand is in the 6110235633Sdim // right place. 6111235633Sdim unsigned Spacing; 6112235633Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6113235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6114235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6115235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6116235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6117235633Sdim Spacing)); 6118235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6119235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6120235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6121235633Sdim Inst = TmpInst; 6122235633Sdim return true; 6123235633Sdim } 6124235633Sdim 6125235633Sdim case ARM::VST3LNdAsm_8: 6126235633Sdim case ARM::VST3LNdAsm_16: 6127235633Sdim case ARM::VST3LNdAsm_32: 6128235633Sdim case ARM::VST3LNqAsm_16: 6129235633Sdim case ARM::VST3LNqAsm_32: { 6130235633Sdim MCInst TmpInst; 6131235633Sdim // Shuffle the operands around so the lane index operand is in the 6132235633Sdim // right place. 6133235633Sdim unsigned Spacing; 6134235633Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6135235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6136235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6137235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6138235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6139235633Sdim Spacing)); 6140235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6141235633Sdim Spacing * 2)); 6142235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6143235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6144235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6145235633Sdim Inst = TmpInst; 6146235633Sdim return true; 6147235633Sdim } 6148235633Sdim 6149235633Sdim case ARM::VST4LNdAsm_8: 6150235633Sdim case ARM::VST4LNdAsm_16: 6151235633Sdim case ARM::VST4LNdAsm_32: 6152235633Sdim case ARM::VST4LNqAsm_16: 6153235633Sdim case ARM::VST4LNqAsm_32: { 6154235633Sdim MCInst TmpInst; 6155235633Sdim // Shuffle the operands around so the lane index operand is in the 6156235633Sdim // right place. 6157235633Sdim unsigned Spacing; 6158235633Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6159235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6160235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6161235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6162235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6163235633Sdim Spacing)); 6164235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6165235633Sdim Spacing * 2)); 6166235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6167235633Sdim Spacing * 3)); 6168235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6169235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6170235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6171235633Sdim Inst = TmpInst; 6172235633Sdim return true; 6173235633Sdim } 6174235633Sdim 6175235633Sdim // Handle NEON VLD complex aliases. 6176235633Sdim case ARM::VLD1LNdWB_register_Asm_8: 6177235633Sdim case ARM::VLD1LNdWB_register_Asm_16: 6178235633Sdim case ARM::VLD1LNdWB_register_Asm_32: { 6179235633Sdim MCInst TmpInst; 6180235633Sdim // Shuffle the operands around so the lane index operand is in the 6181235633Sdim // right place. 6182235633Sdim unsigned Spacing; 6183235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6184235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6185235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 6186235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6187235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6188235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rm 6189235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6190235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6191235633Sdim TmpInst.addOperand(Inst.getOperand(5)); // CondCode 6192235633Sdim TmpInst.addOperand(Inst.getOperand(6)); 6193235633Sdim Inst = TmpInst; 6194235633Sdim return true; 6195235633Sdim } 6196235633Sdim 6197235633Sdim case ARM::VLD2LNdWB_register_Asm_8: 6198235633Sdim case ARM::VLD2LNdWB_register_Asm_16: 6199235633Sdim case ARM::VLD2LNdWB_register_Asm_32: 6200235633Sdim case ARM::VLD2LNqWB_register_Asm_16: 6201235633Sdim case ARM::VLD2LNqWB_register_Asm_32: { 6202235633Sdim MCInst TmpInst; 6203235633Sdim // Shuffle the operands around so the lane index operand is in the 6204235633Sdim // right place. 6205235633Sdim unsigned Spacing; 6206235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6207235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6208235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6209235633Sdim Spacing)); 6210235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 6211235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6212235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6213235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rm 6214235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6215235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6216235633Sdim Spacing)); 6217235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6218235633Sdim TmpInst.addOperand(Inst.getOperand(5)); // CondCode 6219235633Sdim TmpInst.addOperand(Inst.getOperand(6)); 6220235633Sdim Inst = TmpInst; 6221235633Sdim return true; 6222235633Sdim } 6223235633Sdim 6224235633Sdim case ARM::VLD3LNdWB_register_Asm_8: 6225235633Sdim case ARM::VLD3LNdWB_register_Asm_16: 6226235633Sdim case ARM::VLD3LNdWB_register_Asm_32: 6227235633Sdim case ARM::VLD3LNqWB_register_Asm_16: 6228235633Sdim case ARM::VLD3LNqWB_register_Asm_32: { 6229235633Sdim MCInst TmpInst; 6230235633Sdim // Shuffle the operands around so the lane index operand is in the 6231235633Sdim // right place. 6232235633Sdim unsigned Spacing; 6233235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6234235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6235235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6236235633Sdim Spacing)); 6237235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6238235633Sdim Spacing * 2)); 6239235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 6240235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6241235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6242235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rm 6243235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6244235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6245235633Sdim Spacing)); 6246235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6247235633Sdim Spacing * 2)); 6248235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6249235633Sdim TmpInst.addOperand(Inst.getOperand(5)); // CondCode 6250235633Sdim TmpInst.addOperand(Inst.getOperand(6)); 6251235633Sdim Inst = TmpInst; 6252235633Sdim return true; 6253235633Sdim } 6254235633Sdim 6255235633Sdim case ARM::VLD4LNdWB_register_Asm_8: 6256235633Sdim case ARM::VLD4LNdWB_register_Asm_16: 6257235633Sdim case ARM::VLD4LNdWB_register_Asm_32: 6258235633Sdim case ARM::VLD4LNqWB_register_Asm_16: 6259235633Sdim case ARM::VLD4LNqWB_register_Asm_32: { 6260235633Sdim MCInst TmpInst; 6261235633Sdim // Shuffle the operands around so the lane index operand is in the 6262235633Sdim // right place. 6263235633Sdim unsigned Spacing; 6264235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6265235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6266235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6267235633Sdim Spacing)); 6268235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6269235633Sdim Spacing * 2)); 6270235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6271235633Sdim Spacing * 3)); 6272235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 6273235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6274235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6275235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rm 6276235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6277235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6278235633Sdim Spacing)); 6279235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6280235633Sdim Spacing * 2)); 6281235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6282235633Sdim Spacing * 3)); 6283235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6284235633Sdim TmpInst.addOperand(Inst.getOperand(5)); // CondCode 6285235633Sdim TmpInst.addOperand(Inst.getOperand(6)); 6286235633Sdim Inst = TmpInst; 6287235633Sdim return true; 6288235633Sdim } 6289235633Sdim 6290235633Sdim case ARM::VLD1LNdWB_fixed_Asm_8: 6291235633Sdim case ARM::VLD1LNdWB_fixed_Asm_16: 6292235633Sdim case ARM::VLD1LNdWB_fixed_Asm_32: { 6293235633Sdim MCInst TmpInst; 6294235633Sdim // Shuffle the operands around so the lane index operand is in the 6295235633Sdim // right place. 6296235633Sdim unsigned Spacing; 6297235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6298235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6299235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 6300235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6301235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6302235633Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6303235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6304235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6305235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6306235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6307235633Sdim Inst = TmpInst; 6308235633Sdim return true; 6309235633Sdim } 6310235633Sdim 6311235633Sdim case ARM::VLD2LNdWB_fixed_Asm_8: 6312235633Sdim case ARM::VLD2LNdWB_fixed_Asm_16: 6313235633Sdim case ARM::VLD2LNdWB_fixed_Asm_32: 6314235633Sdim case ARM::VLD2LNqWB_fixed_Asm_16: 6315235633Sdim case ARM::VLD2LNqWB_fixed_Asm_32: { 6316235633Sdim MCInst TmpInst; 6317235633Sdim // Shuffle the operands around so the lane index operand is in the 6318235633Sdim // right place. 6319235633Sdim unsigned Spacing; 6320235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6321235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6322235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6323235633Sdim Spacing)); 6324235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 6325235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6326235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6327235633Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6328235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6329235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6330235633Sdim Spacing)); 6331235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6332235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6333235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6334235633Sdim Inst = TmpInst; 6335235633Sdim return true; 6336235633Sdim } 6337235633Sdim 6338235633Sdim case ARM::VLD3LNdWB_fixed_Asm_8: 6339235633Sdim case ARM::VLD3LNdWB_fixed_Asm_16: 6340235633Sdim case ARM::VLD3LNdWB_fixed_Asm_32: 6341235633Sdim case ARM::VLD3LNqWB_fixed_Asm_16: 6342235633Sdim case ARM::VLD3LNqWB_fixed_Asm_32: { 6343235633Sdim MCInst TmpInst; 6344235633Sdim // Shuffle the operands around so the lane index operand is in the 6345235633Sdim // right place. 6346235633Sdim unsigned Spacing; 6347235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6348235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6349235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6350235633Sdim Spacing)); 6351235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6352235633Sdim Spacing * 2)); 6353235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 6354235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6355235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6356235633Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6357235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6358235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6359235633Sdim Spacing)); 6360235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6361235633Sdim Spacing * 2)); 6362235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6363235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6364235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6365235633Sdim Inst = TmpInst; 6366235633Sdim return true; 6367235633Sdim } 6368235633Sdim 6369235633Sdim case ARM::VLD4LNdWB_fixed_Asm_8: 6370235633Sdim case ARM::VLD4LNdWB_fixed_Asm_16: 6371235633Sdim case ARM::VLD4LNdWB_fixed_Asm_32: 6372235633Sdim case ARM::VLD4LNqWB_fixed_Asm_16: 6373235633Sdim case ARM::VLD4LNqWB_fixed_Asm_32: { 6374235633Sdim MCInst TmpInst; 6375235633Sdim // Shuffle the operands around so the lane index operand is in the 6376235633Sdim // right place. 6377235633Sdim unsigned Spacing; 6378235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6379235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6380235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6381235633Sdim Spacing)); 6382235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6383235633Sdim Spacing * 2)); 6384235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6385235633Sdim Spacing * 3)); 6386235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb 6387235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6388235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6389235633Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6390235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6391235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6392235633Sdim Spacing)); 6393235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6394235633Sdim Spacing * 2)); 6395235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6396235633Sdim Spacing * 3)); 6397235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6398235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6399235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6400235633Sdim Inst = TmpInst; 6401235633Sdim return true; 6402235633Sdim } 6403235633Sdim 6404235633Sdim case ARM::VLD1LNdAsm_8: 6405235633Sdim case ARM::VLD1LNdAsm_16: 6406235633Sdim case ARM::VLD1LNdAsm_32: { 6407235633Sdim MCInst TmpInst; 6408235633Sdim // Shuffle the operands around so the lane index operand is in the 6409235633Sdim // right place. 6410235633Sdim unsigned Spacing; 6411235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6412235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6413235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6414235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6415235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6416235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6417235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6418235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6419235633Sdim Inst = TmpInst; 6420235633Sdim return true; 6421235633Sdim } 6422235633Sdim 6423235633Sdim case ARM::VLD2LNdAsm_8: 6424235633Sdim case ARM::VLD2LNdAsm_16: 6425235633Sdim case ARM::VLD2LNdAsm_32: 6426235633Sdim case ARM::VLD2LNqAsm_16: 6427235633Sdim case ARM::VLD2LNqAsm_32: { 6428235633Sdim MCInst TmpInst; 6429235633Sdim // Shuffle the operands around so the lane index operand is in the 6430235633Sdim // right place. 6431235633Sdim unsigned Spacing; 6432235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6433235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6434235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6435235633Sdim Spacing)); 6436235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6437235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6438235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6439235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6440235633Sdim Spacing)); 6441235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6442235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6443235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6444235633Sdim Inst = TmpInst; 6445235633Sdim return true; 6446235633Sdim } 6447235633Sdim 6448235633Sdim case ARM::VLD3LNdAsm_8: 6449235633Sdim case ARM::VLD3LNdAsm_16: 6450235633Sdim case ARM::VLD3LNdAsm_32: 6451235633Sdim case ARM::VLD3LNqAsm_16: 6452235633Sdim case ARM::VLD3LNqAsm_32: { 6453235633Sdim MCInst TmpInst; 6454235633Sdim // Shuffle the operands around so the lane index operand is in the 6455235633Sdim // right place. 6456235633Sdim unsigned Spacing; 6457235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6458235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6459235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6460235633Sdim Spacing)); 6461235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6462235633Sdim Spacing * 2)); 6463235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6464235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6465235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6466235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6467235633Sdim Spacing)); 6468235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6469235633Sdim Spacing * 2)); 6470235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6471235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6472235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6473235633Sdim Inst = TmpInst; 6474235633Sdim return true; 6475235633Sdim } 6476235633Sdim 6477235633Sdim case ARM::VLD4LNdAsm_8: 6478235633Sdim case ARM::VLD4LNdAsm_16: 6479235633Sdim case ARM::VLD4LNdAsm_32: 6480235633Sdim case ARM::VLD4LNqAsm_16: 6481235633Sdim case ARM::VLD4LNqAsm_32: { 6482235633Sdim MCInst TmpInst; 6483235633Sdim // Shuffle the operands around so the lane index operand is in the 6484235633Sdim // right place. 6485235633Sdim unsigned Spacing; 6486235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6487235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6488235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6489235633Sdim Spacing)); 6490235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6491235633Sdim Spacing * 2)); 6492235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6493235633Sdim Spacing * 3)); 6494235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rn 6495235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // alignment 6496235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) 6497235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6498235633Sdim Spacing)); 6499235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6500235633Sdim Spacing * 2)); 6501235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6502235633Sdim Spacing * 3)); 6503235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // lane 6504235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6505235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6506235633Sdim Inst = TmpInst; 6507235633Sdim return true; 6508235633Sdim } 6509235633Sdim 6510235633Sdim // VLD3DUP single 3-element structure to all lanes instructions. 6511235633Sdim case ARM::VLD3DUPdAsm_8: 6512235633Sdim case ARM::VLD3DUPdAsm_16: 6513235633Sdim case ARM::VLD3DUPdAsm_32: 6514235633Sdim case ARM::VLD3DUPqAsm_8: 6515235633Sdim case ARM::VLD3DUPqAsm_16: 6516235633Sdim case ARM::VLD3DUPqAsm_32: { 6517235633Sdim MCInst TmpInst; 6518235633Sdim unsigned Spacing; 6519235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6520235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6521235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6522235633Sdim Spacing)); 6523235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6524235633Sdim Spacing * 2)); 6525235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6526235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6527235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6528235633Sdim TmpInst.addOperand(Inst.getOperand(4)); 6529235633Sdim Inst = TmpInst; 6530235633Sdim return true; 6531235633Sdim } 6532235633Sdim 6533235633Sdim case ARM::VLD3DUPdWB_fixed_Asm_8: 6534235633Sdim case ARM::VLD3DUPdWB_fixed_Asm_16: 6535235633Sdim case ARM::VLD3DUPdWB_fixed_Asm_32: 6536235633Sdim case ARM::VLD3DUPqWB_fixed_Asm_8: 6537235633Sdim case ARM::VLD3DUPqWB_fixed_Asm_16: 6538235633Sdim case ARM::VLD3DUPqWB_fixed_Asm_32: { 6539235633Sdim MCInst TmpInst; 6540235633Sdim unsigned Spacing; 6541235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6542235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6543235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6544235633Sdim Spacing)); 6545235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6546235633Sdim Spacing * 2)); 6547235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6548235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6549235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6550235633Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6551235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6552235633Sdim TmpInst.addOperand(Inst.getOperand(4)); 6553235633Sdim Inst = TmpInst; 6554235633Sdim return true; 6555235633Sdim } 6556235633Sdim 6557235633Sdim case ARM::VLD3DUPdWB_register_Asm_8: 6558235633Sdim case ARM::VLD3DUPdWB_register_Asm_16: 6559235633Sdim case ARM::VLD3DUPdWB_register_Asm_32: 6560235633Sdim case ARM::VLD3DUPqWB_register_Asm_8: 6561235633Sdim case ARM::VLD3DUPqWB_register_Asm_16: 6562235633Sdim case ARM::VLD3DUPqWB_register_Asm_32: { 6563235633Sdim MCInst TmpInst; 6564235633Sdim unsigned Spacing; 6565235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6566235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6567235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6568235633Sdim Spacing)); 6569235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6570235633Sdim Spacing * 2)); 6571235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6572235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6573235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6574235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // Rm 6575235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6576235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6577235633Sdim Inst = TmpInst; 6578235633Sdim return true; 6579235633Sdim } 6580235633Sdim 6581235633Sdim // VLD3 multiple 3-element structure instructions. 6582235633Sdim case ARM::VLD3dAsm_8: 6583235633Sdim case ARM::VLD3dAsm_16: 6584235633Sdim case ARM::VLD3dAsm_32: 6585235633Sdim case ARM::VLD3qAsm_8: 6586235633Sdim case ARM::VLD3qAsm_16: 6587235633Sdim case ARM::VLD3qAsm_32: { 6588235633Sdim MCInst TmpInst; 6589235633Sdim unsigned Spacing; 6590235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6591235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6592235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6593235633Sdim Spacing)); 6594235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6595235633Sdim Spacing * 2)); 6596235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6597235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6598235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6599235633Sdim TmpInst.addOperand(Inst.getOperand(4)); 6600235633Sdim Inst = TmpInst; 6601235633Sdim return true; 6602235633Sdim } 6603235633Sdim 6604235633Sdim case ARM::VLD3dWB_fixed_Asm_8: 6605235633Sdim case ARM::VLD3dWB_fixed_Asm_16: 6606235633Sdim case ARM::VLD3dWB_fixed_Asm_32: 6607235633Sdim case ARM::VLD3qWB_fixed_Asm_8: 6608235633Sdim case ARM::VLD3qWB_fixed_Asm_16: 6609235633Sdim case ARM::VLD3qWB_fixed_Asm_32: { 6610235633Sdim MCInst TmpInst; 6611235633Sdim unsigned Spacing; 6612235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6613235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6614235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6615235633Sdim Spacing)); 6616235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6617235633Sdim Spacing * 2)); 6618235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6619235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6620235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6621235633Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6622235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6623235633Sdim TmpInst.addOperand(Inst.getOperand(4)); 6624235633Sdim Inst = TmpInst; 6625235633Sdim return true; 6626235633Sdim } 6627235633Sdim 6628235633Sdim case ARM::VLD3dWB_register_Asm_8: 6629235633Sdim case ARM::VLD3dWB_register_Asm_16: 6630235633Sdim case ARM::VLD3dWB_register_Asm_32: 6631235633Sdim case ARM::VLD3qWB_register_Asm_8: 6632235633Sdim case ARM::VLD3qWB_register_Asm_16: 6633235633Sdim case ARM::VLD3qWB_register_Asm_32: { 6634235633Sdim MCInst TmpInst; 6635235633Sdim unsigned Spacing; 6636235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6637235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6638235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6639235633Sdim Spacing)); 6640235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6641235633Sdim Spacing * 2)); 6642235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6643235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6644235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6645235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // Rm 6646235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6647235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6648235633Sdim Inst = TmpInst; 6649235633Sdim return true; 6650235633Sdim } 6651235633Sdim 6652235633Sdim // VLD4DUP single 3-element structure to all lanes instructions. 6653235633Sdim case ARM::VLD4DUPdAsm_8: 6654235633Sdim case ARM::VLD4DUPdAsm_16: 6655235633Sdim case ARM::VLD4DUPdAsm_32: 6656235633Sdim case ARM::VLD4DUPqAsm_8: 6657235633Sdim case ARM::VLD4DUPqAsm_16: 6658235633Sdim case ARM::VLD4DUPqAsm_32: { 6659235633Sdim MCInst TmpInst; 6660235633Sdim unsigned Spacing; 6661235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6662235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6663235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6664235633Sdim Spacing)); 6665235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6666235633Sdim Spacing * 2)); 6667235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6668235633Sdim Spacing * 3)); 6669235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6670235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6671235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6672235633Sdim TmpInst.addOperand(Inst.getOperand(4)); 6673235633Sdim Inst = TmpInst; 6674235633Sdim return true; 6675235633Sdim } 6676235633Sdim 6677235633Sdim case ARM::VLD4DUPdWB_fixed_Asm_8: 6678235633Sdim case ARM::VLD4DUPdWB_fixed_Asm_16: 6679235633Sdim case ARM::VLD4DUPdWB_fixed_Asm_32: 6680235633Sdim case ARM::VLD4DUPqWB_fixed_Asm_8: 6681235633Sdim case ARM::VLD4DUPqWB_fixed_Asm_16: 6682235633Sdim case ARM::VLD4DUPqWB_fixed_Asm_32: { 6683235633Sdim MCInst TmpInst; 6684235633Sdim unsigned Spacing; 6685235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6686235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6687235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6688235633Sdim Spacing)); 6689235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6690235633Sdim Spacing * 2)); 6691235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6692235633Sdim Spacing * 3)); 6693235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6694235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6695235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6696235633Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6697235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6698235633Sdim TmpInst.addOperand(Inst.getOperand(4)); 6699235633Sdim Inst = TmpInst; 6700235633Sdim return true; 6701235633Sdim } 6702235633Sdim 6703235633Sdim case ARM::VLD4DUPdWB_register_Asm_8: 6704235633Sdim case ARM::VLD4DUPdWB_register_Asm_16: 6705235633Sdim case ARM::VLD4DUPdWB_register_Asm_32: 6706235633Sdim case ARM::VLD4DUPqWB_register_Asm_8: 6707235633Sdim case ARM::VLD4DUPqWB_register_Asm_16: 6708235633Sdim case ARM::VLD4DUPqWB_register_Asm_32: { 6709235633Sdim MCInst TmpInst; 6710235633Sdim unsigned Spacing; 6711235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6712235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6713235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6714235633Sdim Spacing)); 6715235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6716235633Sdim Spacing * 2)); 6717235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6718235633Sdim Spacing * 3)); 6719235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6720235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6721235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6722235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // Rm 6723235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6724235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6725235633Sdim Inst = TmpInst; 6726235633Sdim return true; 6727235633Sdim } 6728235633Sdim 6729235633Sdim // VLD4 multiple 4-element structure instructions. 6730235633Sdim case ARM::VLD4dAsm_8: 6731235633Sdim case ARM::VLD4dAsm_16: 6732235633Sdim case ARM::VLD4dAsm_32: 6733235633Sdim case ARM::VLD4qAsm_8: 6734235633Sdim case ARM::VLD4qAsm_16: 6735235633Sdim case ARM::VLD4qAsm_32: { 6736235633Sdim MCInst TmpInst; 6737235633Sdim unsigned Spacing; 6738235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6739235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6740235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6741235633Sdim Spacing)); 6742235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6743235633Sdim Spacing * 2)); 6744235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6745235633Sdim Spacing * 3)); 6746235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6747235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6748235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6749235633Sdim TmpInst.addOperand(Inst.getOperand(4)); 6750235633Sdim Inst = TmpInst; 6751235633Sdim return true; 6752235633Sdim } 6753235633Sdim 6754235633Sdim case ARM::VLD4dWB_fixed_Asm_8: 6755235633Sdim case ARM::VLD4dWB_fixed_Asm_16: 6756235633Sdim case ARM::VLD4dWB_fixed_Asm_32: 6757235633Sdim case ARM::VLD4qWB_fixed_Asm_8: 6758235633Sdim case ARM::VLD4qWB_fixed_Asm_16: 6759235633Sdim case ARM::VLD4qWB_fixed_Asm_32: { 6760235633Sdim MCInst TmpInst; 6761235633Sdim unsigned Spacing; 6762235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6763235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6764235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6765235633Sdim Spacing)); 6766235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6767235633Sdim Spacing * 2)); 6768235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6769235633Sdim Spacing * 3)); 6770235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6771235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6772235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6773235633Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6774235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6775235633Sdim TmpInst.addOperand(Inst.getOperand(4)); 6776235633Sdim Inst = TmpInst; 6777235633Sdim return true; 6778235633Sdim } 6779235633Sdim 6780235633Sdim case ARM::VLD4dWB_register_Asm_8: 6781235633Sdim case ARM::VLD4dWB_register_Asm_16: 6782235633Sdim case ARM::VLD4dWB_register_Asm_32: 6783235633Sdim case ARM::VLD4qWB_register_Asm_8: 6784235633Sdim case ARM::VLD4qWB_register_Asm_16: 6785235633Sdim case ARM::VLD4qWB_register_Asm_32: { 6786235633Sdim MCInst TmpInst; 6787235633Sdim unsigned Spacing; 6788235633Sdim TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); 6789235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6790235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6791235633Sdim Spacing)); 6792235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6793235633Sdim Spacing * 2)); 6794235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6795235633Sdim Spacing * 3)); 6796235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6797235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6798235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6799235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // Rm 6800235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6801235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6802235633Sdim Inst = TmpInst; 6803235633Sdim return true; 6804235633Sdim } 6805235633Sdim 6806235633Sdim // VST3 multiple 3-element structure instructions. 6807235633Sdim case ARM::VST3dAsm_8: 6808235633Sdim case ARM::VST3dAsm_16: 6809235633Sdim case ARM::VST3dAsm_32: 6810235633Sdim case ARM::VST3qAsm_8: 6811235633Sdim case ARM::VST3qAsm_16: 6812235633Sdim case ARM::VST3qAsm_32: { 6813235633Sdim MCInst TmpInst; 6814235633Sdim unsigned Spacing; 6815235633Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6816235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6817235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6818235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6819235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6820235633Sdim Spacing)); 6821235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6822235633Sdim Spacing * 2)); 6823235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6824235633Sdim TmpInst.addOperand(Inst.getOperand(4)); 6825235633Sdim Inst = TmpInst; 6826235633Sdim return true; 6827235633Sdim } 6828235633Sdim 6829235633Sdim case ARM::VST3dWB_fixed_Asm_8: 6830235633Sdim case ARM::VST3dWB_fixed_Asm_16: 6831235633Sdim case ARM::VST3dWB_fixed_Asm_32: 6832235633Sdim case ARM::VST3qWB_fixed_Asm_8: 6833235633Sdim case ARM::VST3qWB_fixed_Asm_16: 6834235633Sdim case ARM::VST3qWB_fixed_Asm_32: { 6835235633Sdim MCInst TmpInst; 6836235633Sdim unsigned Spacing; 6837235633Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6838235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6839235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6840235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6841235633Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6842235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6843235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6844235633Sdim Spacing)); 6845235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6846235633Sdim Spacing * 2)); 6847235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6848235633Sdim TmpInst.addOperand(Inst.getOperand(4)); 6849235633Sdim Inst = TmpInst; 6850235633Sdim return true; 6851235633Sdim } 6852235633Sdim 6853235633Sdim case ARM::VST3dWB_register_Asm_8: 6854235633Sdim case ARM::VST3dWB_register_Asm_16: 6855235633Sdim case ARM::VST3dWB_register_Asm_32: 6856235633Sdim case ARM::VST3qWB_register_Asm_8: 6857235633Sdim case ARM::VST3qWB_register_Asm_16: 6858235633Sdim case ARM::VST3qWB_register_Asm_32: { 6859235633Sdim MCInst TmpInst; 6860235633Sdim unsigned Spacing; 6861235633Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6862235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6863235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6864235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6865235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // Rm 6866235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6867235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6868235633Sdim Spacing)); 6869235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6870235633Sdim Spacing * 2)); 6871235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6872235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6873235633Sdim Inst = TmpInst; 6874235633Sdim return true; 6875235633Sdim } 6876235633Sdim 6877235633Sdim // VST4 multiple 3-element structure instructions. 6878235633Sdim case ARM::VST4dAsm_8: 6879235633Sdim case ARM::VST4dAsm_16: 6880235633Sdim case ARM::VST4dAsm_32: 6881235633Sdim case ARM::VST4qAsm_8: 6882235633Sdim case ARM::VST4qAsm_16: 6883235633Sdim case ARM::VST4qAsm_32: { 6884235633Sdim MCInst TmpInst; 6885235633Sdim unsigned Spacing; 6886235633Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6887235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6888235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6889235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6890235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6891235633Sdim Spacing)); 6892235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6893235633Sdim Spacing * 2)); 6894235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6895235633Sdim Spacing * 3)); 6896235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6897235633Sdim TmpInst.addOperand(Inst.getOperand(4)); 6898235633Sdim Inst = TmpInst; 6899235633Sdim return true; 6900235633Sdim } 6901235633Sdim 6902235633Sdim case ARM::VST4dWB_fixed_Asm_8: 6903235633Sdim case ARM::VST4dWB_fixed_Asm_16: 6904235633Sdim case ARM::VST4dWB_fixed_Asm_32: 6905235633Sdim case ARM::VST4qWB_fixed_Asm_8: 6906235633Sdim case ARM::VST4qWB_fixed_Asm_16: 6907235633Sdim case ARM::VST4qWB_fixed_Asm_32: { 6908235633Sdim MCInst TmpInst; 6909235633Sdim unsigned Spacing; 6910235633Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6911235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6912235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6913235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6914235633Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm 6915235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6916235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6917235633Sdim Spacing)); 6918235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6919235633Sdim Spacing * 2)); 6920235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6921235633Sdim Spacing * 3)); 6922235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 6923235633Sdim TmpInst.addOperand(Inst.getOperand(4)); 6924235633Sdim Inst = TmpInst; 6925235633Sdim return true; 6926235633Sdim } 6927235633Sdim 6928235633Sdim case ARM::VST4dWB_register_Asm_8: 6929235633Sdim case ARM::VST4dWB_register_Asm_16: 6930235633Sdim case ARM::VST4dWB_register_Asm_32: 6931235633Sdim case ARM::VST4qWB_register_Asm_8: 6932235633Sdim case ARM::VST4qWB_register_Asm_16: 6933235633Sdim case ARM::VST4qWB_register_Asm_32: { 6934235633Sdim MCInst TmpInst; 6935235633Sdim unsigned Spacing; 6936235633Sdim TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); 6937235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 6938235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn 6939235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // alignment 6940235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // Rm 6941235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Vd 6942235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6943235633Sdim Spacing)); 6944235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6945235633Sdim Spacing * 2)); 6946235633Sdim TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + 6947235633Sdim Spacing * 3)); 6948235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 6949235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6950235633Sdim Inst = TmpInst; 6951235633Sdim return true; 6952235633Sdim } 6953235633Sdim 6954235633Sdim // Handle encoding choice for the shift-immediate instructions. 6955235633Sdim case ARM::t2LSLri: 6956235633Sdim case ARM::t2LSRri: 6957235633Sdim case ARM::t2ASRri: { 6958235633Sdim if (isARMLowRegister(Inst.getOperand(0).getReg()) && 6959235633Sdim Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() && 6960235633Sdim Inst.getOperand(5).getReg() == (inITBlock() ? 0 : ARM::CPSR) && 6961235633Sdim !(static_cast<ARMOperand*>(Operands[3])->isToken() && 6962235633Sdim static_cast<ARMOperand*>(Operands[3])->getToken() == ".w")) { 6963235633Sdim unsigned NewOpc; 6964235633Sdim switch (Inst.getOpcode()) { 6965235633Sdim default: llvm_unreachable("unexpected opcode"); 6966235633Sdim case ARM::t2LSLri: NewOpc = ARM::tLSLri; break; 6967235633Sdim case ARM::t2LSRri: NewOpc = ARM::tLSRri; break; 6968235633Sdim case ARM::t2ASRri: NewOpc = ARM::tASRri; break; 6969235633Sdim } 6970235633Sdim // The Thumb1 operands aren't in the same order. Awesome, eh? 6971235633Sdim MCInst TmpInst; 6972235633Sdim TmpInst.setOpcode(NewOpc); 6973235633Sdim TmpInst.addOperand(Inst.getOperand(0)); 6974235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 6975235633Sdim TmpInst.addOperand(Inst.getOperand(1)); 6976235633Sdim TmpInst.addOperand(Inst.getOperand(2)); 6977235633Sdim TmpInst.addOperand(Inst.getOperand(3)); 6978235633Sdim TmpInst.addOperand(Inst.getOperand(4)); 6979235633Sdim Inst = TmpInst; 6980235633Sdim return true; 6981235633Sdim } 6982235633Sdim return false; 6983235633Sdim } 6984235633Sdim 6985235633Sdim // Handle the Thumb2 mode MOV complex aliases. 6986235633Sdim case ARM::t2MOVsr: 6987235633Sdim case ARM::t2MOVSsr: { 6988235633Sdim // Which instruction to expand to depends on the CCOut operand and 6989235633Sdim // whether we're in an IT block if the register operands are low 6990235633Sdim // registers. 6991235633Sdim bool isNarrow = false; 6992235633Sdim if (isARMLowRegister(Inst.getOperand(0).getReg()) && 6993235633Sdim isARMLowRegister(Inst.getOperand(1).getReg()) && 6994235633Sdim isARMLowRegister(Inst.getOperand(2).getReg()) && 6995235633Sdim Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() && 6996235633Sdim inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr)) 6997235633Sdim isNarrow = true; 6998235633Sdim MCInst TmpInst; 6999235633Sdim unsigned newOpc; 7000235633Sdim switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) { 7001235633Sdim default: llvm_unreachable("unexpected opcode!"); 7002235633Sdim case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break; 7003235633Sdim case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break; 7004235633Sdim case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break; 7005235633Sdim case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break; 7006235633Sdim } 7007235633Sdim TmpInst.setOpcode(newOpc); 7008235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Rd 7009235633Sdim if (isNarrow) 7010235633Sdim TmpInst.addOperand(MCOperand::CreateReg( 7011235633Sdim Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0)); 7012235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 7013235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rm 7014235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // CondCode 7015235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 7016235633Sdim if (!isNarrow) 7017235633Sdim TmpInst.addOperand(MCOperand::CreateReg( 7018235633Sdim Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0)); 7019235633Sdim Inst = TmpInst; 7020235633Sdim return true; 7021235633Sdim } 7022235633Sdim case ARM::t2MOVsi: 7023235633Sdim case ARM::t2MOVSsi: { 7024235633Sdim // Which instruction to expand to depends on the CCOut operand and 7025235633Sdim // whether we're in an IT block if the register operands are low 7026235633Sdim // registers. 7027235633Sdim bool isNarrow = false; 7028235633Sdim if (isARMLowRegister(Inst.getOperand(0).getReg()) && 7029235633Sdim isARMLowRegister(Inst.getOperand(1).getReg()) && 7030235633Sdim inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi)) 7031235633Sdim isNarrow = true; 7032235633Sdim MCInst TmpInst; 7033235633Sdim unsigned newOpc; 7034235633Sdim switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) { 7035235633Sdim default: llvm_unreachable("unexpected opcode!"); 7036235633Sdim case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break; 7037235633Sdim case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break; 7038235633Sdim case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break; 7039235633Sdim case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break; 7040235633Sdim case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break; 7041235633Sdim } 7042245431Sdim unsigned Amount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()); 7043245431Sdim if (Amount == 32) Amount = 0; 7044235633Sdim TmpInst.setOpcode(newOpc); 7045235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Rd 7046235633Sdim if (isNarrow) 7047235633Sdim TmpInst.addOperand(MCOperand::CreateReg( 7048235633Sdim Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0)); 7049235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 7050235633Sdim if (newOpc != ARM::t2RRX) 7051245431Sdim TmpInst.addOperand(MCOperand::CreateImm(Amount)); 7052235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 7053235633Sdim TmpInst.addOperand(Inst.getOperand(4)); 7054235633Sdim if (!isNarrow) 7055235633Sdim TmpInst.addOperand(MCOperand::CreateReg( 7056235633Sdim Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0)); 7057235633Sdim Inst = TmpInst; 7058235633Sdim return true; 7059235633Sdim } 7060235633Sdim // Handle the ARM mode MOV complex aliases. 7061235633Sdim case ARM::ASRr: 7062235633Sdim case ARM::LSRr: 7063235633Sdim case ARM::LSLr: 7064235633Sdim case ARM::RORr: { 7065235633Sdim ARM_AM::ShiftOpc ShiftTy; 7066235633Sdim switch(Inst.getOpcode()) { 7067235633Sdim default: llvm_unreachable("unexpected opcode!"); 7068235633Sdim case ARM::ASRr: ShiftTy = ARM_AM::asr; break; 7069235633Sdim case ARM::LSRr: ShiftTy = ARM_AM::lsr; break; 7070235633Sdim case ARM::LSLr: ShiftTy = ARM_AM::lsl; break; 7071235633Sdim case ARM::RORr: ShiftTy = ARM_AM::ror; break; 7072235633Sdim } 7073235633Sdim unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0); 7074235633Sdim MCInst TmpInst; 7075235633Sdim TmpInst.setOpcode(ARM::MOVsr); 7076235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Rd 7077235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 7078235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // Rm 7079235633Sdim TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty 7080235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 7081235633Sdim TmpInst.addOperand(Inst.getOperand(4)); 7082235633Sdim TmpInst.addOperand(Inst.getOperand(5)); // cc_out 7083235633Sdim Inst = TmpInst; 7084235633Sdim return true; 7085235633Sdim } 7086235633Sdim case ARM::ASRi: 7087235633Sdim case ARM::LSRi: 7088235633Sdim case ARM::LSLi: 7089235633Sdim case ARM::RORi: { 7090235633Sdim ARM_AM::ShiftOpc ShiftTy; 7091235633Sdim switch(Inst.getOpcode()) { 7092235633Sdim default: llvm_unreachable("unexpected opcode!"); 7093235633Sdim case ARM::ASRi: ShiftTy = ARM_AM::asr; break; 7094235633Sdim case ARM::LSRi: ShiftTy = ARM_AM::lsr; break; 7095235633Sdim case ARM::LSLi: ShiftTy = ARM_AM::lsl; break; 7096235633Sdim case ARM::RORi: ShiftTy = ARM_AM::ror; break; 7097235633Sdim } 7098235633Sdim // A shift by zero is a plain MOVr, not a MOVsi. 7099235633Sdim unsigned Amt = Inst.getOperand(2).getImm(); 7100235633Sdim unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi; 7101245431Sdim // A shift by 32 should be encoded as 0 when permitted 7102245431Sdim if (Amt == 32 && (ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr)) 7103245431Sdim Amt = 0; 7104235633Sdim unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt); 7105235633Sdim MCInst TmpInst; 7106235633Sdim TmpInst.setOpcode(Opc); 7107235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Rd 7108235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 7109235633Sdim if (Opc == ARM::MOVsi) 7110235633Sdim TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty 7111235633Sdim TmpInst.addOperand(Inst.getOperand(3)); // CondCode 7112235633Sdim TmpInst.addOperand(Inst.getOperand(4)); 7113235633Sdim TmpInst.addOperand(Inst.getOperand(5)); // cc_out 7114235633Sdim Inst = TmpInst; 7115235633Sdim return true; 7116235633Sdim } 7117235633Sdim case ARM::RRXi: { 7118235633Sdim unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0); 7119235633Sdim MCInst TmpInst; 7120235633Sdim TmpInst.setOpcode(ARM::MOVsi); 7121235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Rd 7122235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 7123235633Sdim TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty 7124235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // CondCode 7125235633Sdim TmpInst.addOperand(Inst.getOperand(3)); 7126235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // cc_out 7127235633Sdim Inst = TmpInst; 7128235633Sdim return true; 7129235633Sdim } 7130235633Sdim case ARM::t2LDMIA_UPD: { 7131235633Sdim // If this is a load of a single register, then we should use 7132235633Sdim // a post-indexed LDR instruction instead, per the ARM ARM. 7133235633Sdim if (Inst.getNumOperands() != 5) 7134235633Sdim return false; 7135235633Sdim MCInst TmpInst; 7136235633Sdim TmpInst.setOpcode(ARM::t2LDR_POST); 7137235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rt 7138235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb 7139235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 7140235633Sdim TmpInst.addOperand(MCOperand::CreateImm(4)); 7141235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // CondCode 7142235633Sdim TmpInst.addOperand(Inst.getOperand(3)); 7143235633Sdim Inst = TmpInst; 7144235633Sdim return true; 7145235633Sdim } 7146235633Sdim case ARM::t2STMDB_UPD: { 7147235633Sdim // If this is a store of a single register, then we should use 7148235633Sdim // a pre-indexed STR instruction instead, per the ARM ARM. 7149235633Sdim if (Inst.getNumOperands() != 5) 7150235633Sdim return false; 7151235633Sdim MCInst TmpInst; 7152235633Sdim TmpInst.setOpcode(ARM::t2STR_PRE); 7153235633Sdim TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb 7154235633Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rt 7155235633Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 7156235633Sdim TmpInst.addOperand(MCOperand::CreateImm(-4)); 7157235633Sdim TmpInst.addOperand(Inst.getOperand(2)); // CondCode 7158235633Sdim TmpInst.addOperand(Inst.getOperand(3)); 7159235633Sdim Inst = TmpInst; 7160235633Sdim return true; 7161235633Sdim } 7162226890Sdim case ARM::LDMIA_UPD: 7163226890Sdim // If this is a load of a single register via a 'pop', then we should use 7164226890Sdim // a post-indexed LDR instruction instead, per the ARM ARM. 7165226890Sdim if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" && 7166226890Sdim Inst.getNumOperands() == 5) { 7167226890Sdim MCInst TmpInst; 7168226890Sdim TmpInst.setOpcode(ARM::LDR_POST_IMM); 7169226890Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rt 7170226890Sdim TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb 7171226890Sdim TmpInst.addOperand(Inst.getOperand(1)); // Rn 7172226890Sdim TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset 7173226890Sdim TmpInst.addOperand(MCOperand::CreateImm(4)); 7174226890Sdim TmpInst.addOperand(Inst.getOperand(2)); // CondCode 7175226890Sdim TmpInst.addOperand(Inst.getOperand(3)); 7176226890Sdim Inst = TmpInst; 7177235633Sdim return true; 7178226890Sdim } 7179226890Sdim break; 7180226890Sdim case ARM::STMDB_UPD: 7181226890Sdim // If this is a store of a single register via a 'push', then we should use 7182226890Sdim // a pre-indexed STR instruction instead, per the ARM ARM. 7183226890Sdim if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" && 7184226890Sdim Inst.getNumOperands() == 5) { 7185226890Sdim MCInst TmpInst; 7186226890Sdim TmpInst.setOpcode(ARM::STR_PRE_IMM); 7187226890Sdim TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb 7188226890Sdim TmpInst.addOperand(Inst.getOperand(4)); // Rt 7189226890Sdim TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12 7190226890Sdim TmpInst.addOperand(MCOperand::CreateImm(-4)); 7191226890Sdim TmpInst.addOperand(Inst.getOperand(2)); // CondCode 7192226890Sdim TmpInst.addOperand(Inst.getOperand(3)); 7193226890Sdim Inst = TmpInst; 7194226890Sdim } 7195226890Sdim break; 7196235633Sdim case ARM::t2ADDri12: 7197235633Sdim // If the immediate fits for encoding T3 (t2ADDri) and the generic "add" 7198235633Sdim // mnemonic was used (not "addw"), encoding T3 is preferred. 7199235633Sdim if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" || 7200235633Sdim ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1) 7201235633Sdim break; 7202235633Sdim Inst.setOpcode(ARM::t2ADDri); 7203235633Sdim Inst.addOperand(MCOperand::CreateReg(0)); // cc_out 7204235633Sdim break; 7205235633Sdim case ARM::t2SUBri12: 7206235633Sdim // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub" 7207235633Sdim // mnemonic was used (not "subw"), encoding T3 is preferred. 7208235633Sdim if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" || 7209235633Sdim ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1) 7210235633Sdim break; 7211235633Sdim Inst.setOpcode(ARM::t2SUBri); 7212235633Sdim Inst.addOperand(MCOperand::CreateReg(0)); // cc_out 7213235633Sdim break; 7214226890Sdim case ARM::tADDi8: 7215226890Sdim // If the immediate is in the range 0-7, we want tADDi3 iff Rd was 7216226890Sdim // explicitly specified. From the ARM ARM: "Encoding T1 is preferred 7217226890Sdim // to encoding T2 if <Rd> is specified and encoding T2 is preferred 7218226890Sdim // to encoding T1 if <Rd> is omitted." 7219235633Sdim if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) { 7220226890Sdim Inst.setOpcode(ARM::tADDi3); 7221235633Sdim return true; 7222235633Sdim } 7223226890Sdim break; 7224226890Sdim case ARM::tSUBi8: 7225226890Sdim // If the immediate is in the range 0-7, we want tADDi3 iff Rd was 7226226890Sdim // explicitly specified. From the ARM ARM: "Encoding T1 is preferred 7227226890Sdim // to encoding T2 if <Rd> is specified and encoding T2 is preferred 7228226890Sdim // to encoding T1 if <Rd> is omitted." 7229235633Sdim if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) { 7230226890Sdim Inst.setOpcode(ARM::tSUBi3); 7231235633Sdim return true; 7232235633Sdim } 7233226890Sdim break; 7234235633Sdim case ARM::t2ADDri: 7235235633Sdim case ARM::t2SUBri: { 7236235633Sdim // If the destination and first source operand are the same, and 7237235633Sdim // the flags are compatible with the current IT status, use encoding T2 7238235633Sdim // instead of T3. For compatibility with the system 'as'. Make sure the 7239235633Sdim // wide encoding wasn't explicit. 7240235633Sdim if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() || 7241235633Sdim !isARMLowRegister(Inst.getOperand(0).getReg()) || 7242235633Sdim (unsigned)Inst.getOperand(2).getImm() > 255 || 7243235633Sdim ((!inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR) || 7244235633Sdim (inITBlock() && Inst.getOperand(5).getReg() != 0)) || 7245235633Sdim (static_cast<ARMOperand*>(Operands[3])->isToken() && 7246235633Sdim static_cast<ARMOperand*>(Operands[3])->getToken() == ".w")) 7247235633Sdim break; 7248235633Sdim MCInst TmpInst; 7249235633Sdim TmpInst.setOpcode(Inst.getOpcode() == ARM::t2ADDri ? 7250235633Sdim ARM::tADDi8 : ARM::tSUBi8); 7251235633Sdim TmpInst.addOperand(Inst.getOperand(0)); 7252235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 7253235633Sdim TmpInst.addOperand(Inst.getOperand(0)); 7254235633Sdim TmpInst.addOperand(Inst.getOperand(2)); 7255235633Sdim TmpInst.addOperand(Inst.getOperand(3)); 7256235633Sdim TmpInst.addOperand(Inst.getOperand(4)); 7257235633Sdim Inst = TmpInst; 7258235633Sdim return true; 7259235633Sdim } 7260235633Sdim case ARM::t2ADDrr: { 7261235633Sdim // If the destination and first source operand are the same, and 7262235633Sdim // there's no setting of the flags, use encoding T2 instead of T3. 7263235633Sdim // Note that this is only for ADD, not SUB. This mirrors the system 7264235633Sdim // 'as' behaviour. Make sure the wide encoding wasn't explicit. 7265235633Sdim if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() || 7266235633Sdim Inst.getOperand(5).getReg() != 0 || 7267235633Sdim (static_cast<ARMOperand*>(Operands[3])->isToken() && 7268235633Sdim static_cast<ARMOperand*>(Operands[3])->getToken() == ".w")) 7269235633Sdim break; 7270235633Sdim MCInst TmpInst; 7271235633Sdim TmpInst.setOpcode(ARM::tADDhirr); 7272235633Sdim TmpInst.addOperand(Inst.getOperand(0)); 7273235633Sdim TmpInst.addOperand(Inst.getOperand(0)); 7274235633Sdim TmpInst.addOperand(Inst.getOperand(2)); 7275235633Sdim TmpInst.addOperand(Inst.getOperand(3)); 7276235633Sdim TmpInst.addOperand(Inst.getOperand(4)); 7277235633Sdim Inst = TmpInst; 7278235633Sdim return true; 7279235633Sdim } 7280245431Sdim case ARM::tADDrSP: { 7281245431Sdim // If the non-SP source operand and the destination operand are not the 7282245431Sdim // same, we need to use the 32-bit encoding if it's available. 7283245431Sdim if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) { 7284245431Sdim Inst.setOpcode(ARM::t2ADDrr); 7285245431Sdim Inst.addOperand(MCOperand::CreateReg(0)); // cc_out 7286245431Sdim return true; 7287245431Sdim } 7288245431Sdim break; 7289245431Sdim } 7290226890Sdim case ARM::tB: 7291226890Sdim // A Thumb conditional branch outside of an IT block is a tBcc. 7292235633Sdim if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) { 7293226890Sdim Inst.setOpcode(ARM::tBcc); 7294235633Sdim return true; 7295235633Sdim } 7296226890Sdim break; 7297226890Sdim case ARM::t2B: 7298226890Sdim // A Thumb2 conditional branch outside of an IT block is a t2Bcc. 7299235633Sdim if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){ 7300226890Sdim Inst.setOpcode(ARM::t2Bcc); 7301235633Sdim return true; 7302235633Sdim } 7303226890Sdim break; 7304226890Sdim case ARM::t2Bcc: 7305226890Sdim // If the conditional is AL or we're in an IT block, we really want t2B. 7306235633Sdim if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) { 7307226890Sdim Inst.setOpcode(ARM::t2B); 7308235633Sdim return true; 7309235633Sdim } 7310226890Sdim break; 7311226890Sdim case ARM::tBcc: 7312226890Sdim // If the conditional is AL, we really want tB. 7313235633Sdim if (Inst.getOperand(1).getImm() == ARMCC::AL) { 7314226890Sdim Inst.setOpcode(ARM::tB); 7315235633Sdim return true; 7316235633Sdim } 7317226890Sdim break; 7318226890Sdim case ARM::tLDMIA: { 7319226890Sdim // If the register list contains any high registers, or if the writeback 7320226890Sdim // doesn't match what tLDMIA can do, we need to use the 32-bit encoding 7321226890Sdim // instead if we're in Thumb2. Otherwise, this should have generated 7322226890Sdim // an error in validateInstruction(). 7323226890Sdim unsigned Rn = Inst.getOperand(0).getReg(); 7324226890Sdim bool hasWritebackToken = 7325226890Sdim (static_cast<ARMOperand*>(Operands[3])->isToken() && 7326226890Sdim static_cast<ARMOperand*>(Operands[3])->getToken() == "!"); 7327226890Sdim bool listContainsBase; 7328226890Sdim if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) || 7329226890Sdim (!listContainsBase && !hasWritebackToken) || 7330226890Sdim (listContainsBase && hasWritebackToken)) { 7331226890Sdim // 16-bit encoding isn't sufficient. Switch to the 32-bit version. 7332226890Sdim assert (isThumbTwo()); 7333226890Sdim Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA); 7334226890Sdim // If we're switching to the updating version, we need to insert 7335226890Sdim // the writeback tied operand. 7336226890Sdim if (hasWritebackToken) 7337226890Sdim Inst.insert(Inst.begin(), 7338226890Sdim MCOperand::CreateReg(Inst.getOperand(0).getReg())); 7339235633Sdim return true; 7340226890Sdim } 7341226890Sdim break; 7342226890Sdim } 7343226890Sdim case ARM::tSTMIA_UPD: { 7344226890Sdim // If the register list contains any high registers, we need to use 7345226890Sdim // the 32-bit encoding instead if we're in Thumb2. Otherwise, this 7346226890Sdim // should have generated an error in validateInstruction(). 7347226890Sdim unsigned Rn = Inst.getOperand(0).getReg(); 7348226890Sdim bool listContainsBase; 7349226890Sdim if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) { 7350226890Sdim // 16-bit encoding isn't sufficient. Switch to the 32-bit version. 7351226890Sdim assert (isThumbTwo()); 7352226890Sdim Inst.setOpcode(ARM::t2STMIA_UPD); 7353235633Sdim return true; 7354226890Sdim } 7355226890Sdim break; 7356226890Sdim } 7357235633Sdim case ARM::tPOP: { 7358235633Sdim bool listContainsBase; 7359235633Sdim // If the register list contains any high registers, we need to use 7360235633Sdim // the 32-bit encoding instead if we're in Thumb2. Otherwise, this 7361235633Sdim // should have generated an error in validateInstruction(). 7362235633Sdim if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase)) 7363235633Sdim return false; 7364235633Sdim assert (isThumbTwo()); 7365235633Sdim Inst.setOpcode(ARM::t2LDMIA_UPD); 7366235633Sdim // Add the base register and writeback operands. 7367235633Sdim Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP)); 7368235633Sdim Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP)); 7369235633Sdim return true; 7370235633Sdim } 7371235633Sdim case ARM::tPUSH: { 7372235633Sdim bool listContainsBase; 7373235633Sdim if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase)) 7374235633Sdim return false; 7375235633Sdim assert (isThumbTwo()); 7376235633Sdim Inst.setOpcode(ARM::t2STMDB_UPD); 7377235633Sdim // Add the base register and writeback operands. 7378235633Sdim Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP)); 7379235633Sdim Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP)); 7380235633Sdim return true; 7381235633Sdim } 7382226890Sdim case ARM::t2MOVi: { 7383226890Sdim // If we can use the 16-bit encoding and the user didn't explicitly 7384226890Sdim // request the 32-bit variant, transform it here. 7385226890Sdim if (isARMLowRegister(Inst.getOperand(0).getReg()) && 7386235633Sdim (unsigned)Inst.getOperand(1).getImm() <= 255 && 7387226890Sdim ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL && 7388226890Sdim Inst.getOperand(4).getReg() == ARM::CPSR) || 7389226890Sdim (inITBlock() && Inst.getOperand(4).getReg() == 0)) && 7390226890Sdim (!static_cast<ARMOperand*>(Operands[2])->isToken() || 7391226890Sdim static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) { 7392226890Sdim // The operands aren't in the same order for tMOVi8... 7393226890Sdim MCInst TmpInst; 7394226890Sdim TmpInst.setOpcode(ARM::tMOVi8); 7395226890Sdim TmpInst.addOperand(Inst.getOperand(0)); 7396226890Sdim TmpInst.addOperand(Inst.getOperand(4)); 7397226890Sdim TmpInst.addOperand(Inst.getOperand(1)); 7398226890Sdim TmpInst.addOperand(Inst.getOperand(2)); 7399226890Sdim TmpInst.addOperand(Inst.getOperand(3)); 7400226890Sdim Inst = TmpInst; 7401235633Sdim return true; 7402226890Sdim } 7403226890Sdim break; 7404226890Sdim } 7405226890Sdim case ARM::t2MOVr: { 7406226890Sdim // If we can use the 16-bit encoding and the user didn't explicitly 7407226890Sdim // request the 32-bit variant, transform it here. 7408226890Sdim if (isARMLowRegister(Inst.getOperand(0).getReg()) && 7409226890Sdim isARMLowRegister(Inst.getOperand(1).getReg()) && 7410226890Sdim Inst.getOperand(2).getImm() == ARMCC::AL && 7411226890Sdim Inst.getOperand(4).getReg() == ARM::CPSR && 7412226890Sdim (!static_cast<ARMOperand*>(Operands[2])->isToken() || 7413226890Sdim static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) { 7414226890Sdim // The operands aren't the same for tMOV[S]r... (no cc_out) 7415226890Sdim MCInst TmpInst; 7416226890Sdim TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr); 7417226890Sdim TmpInst.addOperand(Inst.getOperand(0)); 7418226890Sdim TmpInst.addOperand(Inst.getOperand(1)); 7419226890Sdim TmpInst.addOperand(Inst.getOperand(2)); 7420226890Sdim TmpInst.addOperand(Inst.getOperand(3)); 7421226890Sdim Inst = TmpInst; 7422235633Sdim return true; 7423226890Sdim } 7424226890Sdim break; 7425226890Sdim } 7426226890Sdim case ARM::t2SXTH: 7427226890Sdim case ARM::t2SXTB: 7428226890Sdim case ARM::t2UXTH: 7429226890Sdim case ARM::t2UXTB: { 7430226890Sdim // If we can use the 16-bit encoding and the user didn't explicitly 7431226890Sdim // request the 32-bit variant, transform it here. 7432226890Sdim if (isARMLowRegister(Inst.getOperand(0).getReg()) && 7433226890Sdim isARMLowRegister(Inst.getOperand(1).getReg()) && 7434226890Sdim Inst.getOperand(2).getImm() == 0 && 7435226890Sdim (!static_cast<ARMOperand*>(Operands[2])->isToken() || 7436226890Sdim static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) { 7437226890Sdim unsigned NewOpc; 7438226890Sdim switch (Inst.getOpcode()) { 7439226890Sdim default: llvm_unreachable("Illegal opcode!"); 7440226890Sdim case ARM::t2SXTH: NewOpc = ARM::tSXTH; break; 7441226890Sdim case ARM::t2SXTB: NewOpc = ARM::tSXTB; break; 7442226890Sdim case ARM::t2UXTH: NewOpc = ARM::tUXTH; break; 7443226890Sdim case ARM::t2UXTB: NewOpc = ARM::tUXTB; break; 7444226890Sdim } 7445226890Sdim // The operands aren't the same for thumb1 (no rotate operand). 7446226890Sdim MCInst TmpInst; 7447226890Sdim TmpInst.setOpcode(NewOpc); 7448226890Sdim TmpInst.addOperand(Inst.getOperand(0)); 7449226890Sdim TmpInst.addOperand(Inst.getOperand(1)); 7450226890Sdim TmpInst.addOperand(Inst.getOperand(3)); 7451226890Sdim TmpInst.addOperand(Inst.getOperand(4)); 7452226890Sdim Inst = TmpInst; 7453235633Sdim return true; 7454226890Sdim } 7455226890Sdim break; 7456226890Sdim } 7457235633Sdim case ARM::MOVsi: { 7458235633Sdim ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm()); 7459245431Sdim // rrx shifts and asr/lsr of #32 is encoded as 0 7460245431Sdim if (SOpc == ARM_AM::rrx || SOpc == ARM_AM::asr || SOpc == ARM_AM::lsr) 7461245431Sdim return false; 7462235633Sdim if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) { 7463235633Sdim // Shifting by zero is accepted as a vanilla 'MOVr' 7464235633Sdim MCInst TmpInst; 7465235633Sdim TmpInst.setOpcode(ARM::MOVr); 7466235633Sdim TmpInst.addOperand(Inst.getOperand(0)); 7467235633Sdim TmpInst.addOperand(Inst.getOperand(1)); 7468235633Sdim TmpInst.addOperand(Inst.getOperand(3)); 7469235633Sdim TmpInst.addOperand(Inst.getOperand(4)); 7470235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 7471235633Sdim Inst = TmpInst; 7472235633Sdim return true; 7473235633Sdim } 7474235633Sdim return false; 7475235633Sdim } 7476235633Sdim case ARM::ANDrsi: 7477235633Sdim case ARM::ORRrsi: 7478235633Sdim case ARM::EORrsi: 7479235633Sdim case ARM::BICrsi: 7480235633Sdim case ARM::SUBrsi: 7481235633Sdim case ARM::ADDrsi: { 7482235633Sdim unsigned newOpc; 7483235633Sdim ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm()); 7484235633Sdim if (SOpc == ARM_AM::rrx) return false; 7485235633Sdim switch (Inst.getOpcode()) { 7486235633Sdim default: llvm_unreachable("unexpected opcode!"); 7487235633Sdim case ARM::ANDrsi: newOpc = ARM::ANDrr; break; 7488235633Sdim case ARM::ORRrsi: newOpc = ARM::ORRrr; break; 7489235633Sdim case ARM::EORrsi: newOpc = ARM::EORrr; break; 7490235633Sdim case ARM::BICrsi: newOpc = ARM::BICrr; break; 7491235633Sdim case ARM::SUBrsi: newOpc = ARM::SUBrr; break; 7492235633Sdim case ARM::ADDrsi: newOpc = ARM::ADDrr; break; 7493235633Sdim } 7494235633Sdim // If the shift is by zero, use the non-shifted instruction definition. 7495245431Sdim // The exception is for right shifts, where 0 == 32 7496245431Sdim if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0 && 7497245431Sdim !(SOpc == ARM_AM::lsr || SOpc == ARM_AM::asr)) { 7498235633Sdim MCInst TmpInst; 7499235633Sdim TmpInst.setOpcode(newOpc); 7500235633Sdim TmpInst.addOperand(Inst.getOperand(0)); 7501235633Sdim TmpInst.addOperand(Inst.getOperand(1)); 7502235633Sdim TmpInst.addOperand(Inst.getOperand(2)); 7503235633Sdim TmpInst.addOperand(Inst.getOperand(4)); 7504235633Sdim TmpInst.addOperand(Inst.getOperand(5)); 7505235633Sdim TmpInst.addOperand(Inst.getOperand(6)); 7506235633Sdim Inst = TmpInst; 7507235633Sdim return true; 7508235633Sdim } 7509235633Sdim return false; 7510235633Sdim } 7511235633Sdim case ARM::ITasm: 7512226890Sdim case ARM::t2IT: { 7513226890Sdim // The mask bits for all but the first condition are represented as 7514226890Sdim // the low bit of the condition code value implies 't'. We currently 7515226890Sdim // always have 1 implies 't', so XOR toggle the bits if the low bit 7516245431Sdim // of the condition code is zero. 7517226890Sdim MCOperand &MO = Inst.getOperand(1); 7518226890Sdim unsigned Mask = MO.getImm(); 7519226890Sdim unsigned OrigMask = Mask; 7520263509Sdim unsigned TZ = countTrailingZeros(Mask); 7521226890Sdim if ((Inst.getOperand(0).getImm() & 1) == 0) { 7522226890Sdim assert(Mask && TZ <= 3 && "illegal IT mask value!"); 7523263509Sdim Mask ^= (0xE << TZ) & 0xF; 7524245431Sdim } 7525226890Sdim MO.setImm(Mask); 7526226890Sdim 7527226890Sdim // Set up the IT block state according to the IT instruction we just 7528226890Sdim // matched. 7529226890Sdim assert(!inITBlock() && "nested IT blocks?!"); 7530226890Sdim ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm()); 7531226890Sdim ITState.Mask = OrigMask; // Use the original mask, not the updated one. 7532226890Sdim ITState.CurPosition = 0; 7533226890Sdim ITState.FirstCond = true; 7534226890Sdim break; 7535226890Sdim } 7536245431Sdim case ARM::t2LSLrr: 7537245431Sdim case ARM::t2LSRrr: 7538245431Sdim case ARM::t2ASRrr: 7539245431Sdim case ARM::t2SBCrr: 7540245431Sdim case ARM::t2RORrr: 7541245431Sdim case ARM::t2BICrr: 7542245431Sdim { 7543245431Sdim // Assemblers should use the narrow encodings of these instructions when permissible. 7544245431Sdim if ((isARMLowRegister(Inst.getOperand(1).getReg()) && 7545245431Sdim isARMLowRegister(Inst.getOperand(2).getReg())) && 7546245431Sdim Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() && 7547245431Sdim ((!inITBlock() && Inst.getOperand(5).getReg() == ARM::CPSR) || 7548245431Sdim (inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR)) && 7549245431Sdim (!static_cast<ARMOperand*>(Operands[3])->isToken() || 7550245431Sdim !static_cast<ARMOperand*>(Operands[3])->getToken().equals_lower(".w"))) { 7551245431Sdim unsigned NewOpc; 7552245431Sdim switch (Inst.getOpcode()) { 7553245431Sdim default: llvm_unreachable("unexpected opcode"); 7554245431Sdim case ARM::t2LSLrr: NewOpc = ARM::tLSLrr; break; 7555245431Sdim case ARM::t2LSRrr: NewOpc = ARM::tLSRrr; break; 7556245431Sdim case ARM::t2ASRrr: NewOpc = ARM::tASRrr; break; 7557245431Sdim case ARM::t2SBCrr: NewOpc = ARM::tSBC; break; 7558245431Sdim case ARM::t2RORrr: NewOpc = ARM::tROR; break; 7559245431Sdim case ARM::t2BICrr: NewOpc = ARM::tBIC; break; 7560245431Sdim } 7561245431Sdim MCInst TmpInst; 7562245431Sdim TmpInst.setOpcode(NewOpc); 7563245431Sdim TmpInst.addOperand(Inst.getOperand(0)); 7564245431Sdim TmpInst.addOperand(Inst.getOperand(5)); 7565245431Sdim TmpInst.addOperand(Inst.getOperand(1)); 7566245431Sdim TmpInst.addOperand(Inst.getOperand(2)); 7567245431Sdim TmpInst.addOperand(Inst.getOperand(3)); 7568245431Sdim TmpInst.addOperand(Inst.getOperand(4)); 7569245431Sdim Inst = TmpInst; 7570245431Sdim return true; 7571245431Sdim } 7572245431Sdim return false; 7573226890Sdim } 7574245431Sdim case ARM::t2ANDrr: 7575245431Sdim case ARM::t2EORrr: 7576245431Sdim case ARM::t2ADCrr: 7577245431Sdim case ARM::t2ORRrr: 7578245431Sdim { 7579245431Sdim // Assemblers should use the narrow encodings of these instructions when permissible. 7580245431Sdim // These instructions are special in that they are commutable, so shorter encodings 7581245431Sdim // are available more often. 7582245431Sdim if ((isARMLowRegister(Inst.getOperand(1).getReg()) && 7583245431Sdim isARMLowRegister(Inst.getOperand(2).getReg())) && 7584245431Sdim (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() || 7585245431Sdim Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg()) && 7586245431Sdim ((!inITBlock() && Inst.getOperand(5).getReg() == ARM::CPSR) || 7587245431Sdim (inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR)) && 7588245431Sdim (!static_cast<ARMOperand*>(Operands[3])->isToken() || 7589245431Sdim !static_cast<ARMOperand*>(Operands[3])->getToken().equals_lower(".w"))) { 7590245431Sdim unsigned NewOpc; 7591245431Sdim switch (Inst.getOpcode()) { 7592245431Sdim default: llvm_unreachable("unexpected opcode"); 7593245431Sdim case ARM::t2ADCrr: NewOpc = ARM::tADC; break; 7594245431Sdim case ARM::t2ANDrr: NewOpc = ARM::tAND; break; 7595245431Sdim case ARM::t2EORrr: NewOpc = ARM::tEOR; break; 7596245431Sdim case ARM::t2ORRrr: NewOpc = ARM::tORR; break; 7597245431Sdim } 7598245431Sdim MCInst TmpInst; 7599245431Sdim TmpInst.setOpcode(NewOpc); 7600245431Sdim TmpInst.addOperand(Inst.getOperand(0)); 7601245431Sdim TmpInst.addOperand(Inst.getOperand(5)); 7602245431Sdim if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()) { 7603245431Sdim TmpInst.addOperand(Inst.getOperand(1)); 7604245431Sdim TmpInst.addOperand(Inst.getOperand(2)); 7605245431Sdim } else { 7606245431Sdim TmpInst.addOperand(Inst.getOperand(2)); 7607245431Sdim TmpInst.addOperand(Inst.getOperand(1)); 7608245431Sdim } 7609245431Sdim TmpInst.addOperand(Inst.getOperand(3)); 7610245431Sdim TmpInst.addOperand(Inst.getOperand(4)); 7611245431Sdim Inst = TmpInst; 7612245431Sdim return true; 7613245431Sdim } 7614245431Sdim return false; 7615245431Sdim } 7616245431Sdim } 7617235633Sdim return false; 7618226890Sdim} 7619226890Sdim 7620226890Sdimunsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) { 7621226890Sdim // 16-bit thumb arithmetic instructions either require or preclude the 'S' 7622226890Sdim // suffix depending on whether they're in an IT block or not. 7623226890Sdim unsigned Opc = Inst.getOpcode(); 7624263509Sdim const MCInstrDesc &MCID = MII.get(Opc); 7625226890Sdim if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) { 7626226890Sdim assert(MCID.hasOptionalDef() && 7627226890Sdim "optionally flag setting instruction missing optional def operand"); 7628226890Sdim assert(MCID.NumOperands == Inst.getNumOperands() && 7629226890Sdim "operand count mismatch!"); 7630226890Sdim // Find the optional-def operand (cc_out). 7631226890Sdim unsigned OpNo; 7632226890Sdim for (OpNo = 0; 7633226890Sdim !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands; 7634226890Sdim ++OpNo) 7635226890Sdim ; 7636226890Sdim // If we're parsing Thumb1, reject it completely. 7637226890Sdim if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR) 7638226890Sdim return Match_MnemonicFail; 7639226890Sdim // If we're parsing Thumb2, which form is legal depends on whether we're 7640226890Sdim // in an IT block. 7641226890Sdim if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR && 7642226890Sdim !inITBlock()) 7643226890Sdim return Match_RequiresITBlock; 7644226890Sdim if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR && 7645226890Sdim inITBlock()) 7646226890Sdim return Match_RequiresNotITBlock; 7647226890Sdim } 7648226890Sdim // Some high-register supporting Thumb1 encodings only allow both registers 7649226890Sdim // to be from r0-r7 when in Thumb2. 7650226890Sdim else if (Opc == ARM::tADDhirr && isThumbOne() && 7651226890Sdim isARMLowRegister(Inst.getOperand(1).getReg()) && 7652226890Sdim isARMLowRegister(Inst.getOperand(2).getReg())) 7653226890Sdim return Match_RequiresThumb2; 7654226890Sdim // Others only require ARMv6 or later. 7655226890Sdim else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() && 7656226890Sdim isARMLowRegister(Inst.getOperand(0).getReg()) && 7657226890Sdim isARMLowRegister(Inst.getOperand(1).getReg())) 7658226890Sdim return Match_RequiresV6; 7659226890Sdim return Match_Success; 7660226890Sdim} 7661226890Sdim 7662245431Sdimstatic const char *getSubtargetFeatureName(unsigned Val); 7663226890Sdimbool ARMAsmParser:: 7664245431SdimMatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 7665218893Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands, 7666245431Sdim MCStreamer &Out, unsigned &ErrorInfo, 7667245431Sdim bool MatchingInlineAsm) { 7668218893Sdim MCInst Inst; 7669226890Sdim unsigned MatchResult; 7670252723Sdim 7671245431Sdim MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, 7672245431Sdim MatchingInlineAsm); 7673218893Sdim switch (MatchResult) { 7674226890Sdim default: break; 7675218893Sdim case Match_Success: 7676226890Sdim // Context sensitive operand constraints aren't handled by the matcher, 7677226890Sdim // so check them here. 7678226890Sdim if (validateInstruction(Inst, Operands)) { 7679226890Sdim // Still progress the IT block, otherwise one wrong condition causes 7680226890Sdim // nasty cascading errors. 7681226890Sdim forwardITPosition(); 7682226890Sdim return true; 7683226890Sdim } 7684226890Sdim 7685263509Sdim { // processInstruction() updates inITBlock state, we need to save it away 7686263509Sdim bool wasInITBlock = inITBlock(); 7687226890Sdim 7688263509Sdim // Some instructions need post-processing to, for example, tweak which 7689263509Sdim // encoding is selected. Loop on it while changes happen so the 7690263509Sdim // individual transformations can chain off each other. E.g., 7691263509Sdim // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8) 7692263509Sdim while (processInstruction(Inst, Operands)) 7693263509Sdim ; 7694263509Sdim 7695263509Sdim // Only after the instruction is fully processed, we can validate it 7696263509Sdim if (wasInITBlock && hasV8Ops() && isThumb() && 7697263509Sdim !isV8EligibleForIT(&Inst, 2)) { 7698263509Sdim Warning(IDLoc, "deprecated instruction in IT block"); 7699263509Sdim } 7700263509Sdim } 7701263509Sdim 7702226890Sdim // Only move forward at the very end so that everything in validate 7703226890Sdim // and process gets a consistent answer about whether we're in an IT 7704226890Sdim // block. 7705226890Sdim forwardITPosition(); 7706226890Sdim 7707235633Sdim // ITasm is an ARM mode pseudo-instruction that just sets the ITblock and 7708235633Sdim // doesn't actually encode. 7709235633Sdim if (Inst.getOpcode() == ARM::ITasm) 7710235633Sdim return false; 7711235633Sdim 7712235633Sdim Inst.setLoc(IDLoc); 7713218893Sdim Out.EmitInstruction(Inst); 7714218893Sdim return false; 7715245431Sdim case Match_MissingFeature: { 7716245431Sdim assert(ErrorInfo && "Unknown missing feature!"); 7717245431Sdim // Special case the error message for the very common case where only 7718245431Sdim // a single subtarget feature is missing (Thumb vs. ARM, e.g.). 7719245431Sdim std::string Msg = "instruction requires:"; 7720245431Sdim unsigned Mask = 1; 7721245431Sdim for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) { 7722245431Sdim if (ErrorInfo & Mask) { 7723245431Sdim Msg += " "; 7724245431Sdim Msg += getSubtargetFeatureName(ErrorInfo & Mask); 7725245431Sdim } 7726245431Sdim Mask <<= 1; 7727245431Sdim } 7728245431Sdim return Error(IDLoc, Msg); 7729245431Sdim } 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: 7743235633Sdim return Error(IDLoc, "invalid instruction", 7744235633Sdim ((ARMOperand*)Operands[0])->getLocRange()); 7745226890Sdim case Match_RequiresNotITBlock: 7746226890Sdim return Error(IDLoc, "flag setting instruction only valid outside IT block"); 7747226890Sdim case Match_RequiresITBlock: 7748226890Sdim return Error(IDLoc, "instruction only valid inside IT block"); 7749226890Sdim case Match_RequiresV6: 7750226890Sdim return Error(IDLoc, "instruction variant requires ARMv6 or later"); 7751226890Sdim case Match_RequiresThumb2: 7752226890Sdim return Error(IDLoc, "instruction variant requires Thumb2"); 7753263509Sdim case Match_ImmRange0_15: { 7754252723Sdim SMLoc ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc(); 7755252723Sdim if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc; 7756263509Sdim return Error(ErrorLoc, "immediate operand must be in the range [0,15]"); 7757252723Sdim } 7758263509Sdim case Match_ImmRange0_239: { 7759245431Sdim SMLoc ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc(); 7760245431Sdim if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc; 7761263509Sdim return Error(ErrorLoc, "immediate operand must be in the range [0,239]"); 7762218893Sdim } 7763245431Sdim } 7764218893Sdim 7765218893Sdim llvm_unreachable("Implement any new match types added!"); 7766218893Sdim} 7767218893Sdim 7768226890Sdim/// parseDirective parses the arm specific directives 7769198090Srdivackybool ARMAsmParser::ParseDirective(AsmToken DirectiveID) { 7770198090Srdivacky StringRef IDVal = DirectiveID.getIdentifier(); 7771198090Srdivacky if (IDVal == ".word") 7772226890Sdim return parseDirectiveWord(4, DirectiveID.getLoc()); 7773198396Srdivacky else if (IDVal == ".thumb") 7774226890Sdim return parseDirectiveThumb(DirectiveID.getLoc()); 7775235633Sdim else if (IDVal == ".arm") 7776235633Sdim return parseDirectiveARM(DirectiveID.getLoc()); 7777198396Srdivacky else if (IDVal == ".thumb_func") 7778226890Sdim return parseDirectiveThumbFunc(DirectiveID.getLoc()); 7779198396Srdivacky else if (IDVal == ".code") 7780226890Sdim return parseDirectiveCode(DirectiveID.getLoc()); 7781198396Srdivacky else if (IDVal == ".syntax") 7782226890Sdim return parseDirectiveSyntax(DirectiveID.getLoc()); 7783235633Sdim else if (IDVal == ".unreq") 7784235633Sdim return parseDirectiveUnreq(DirectiveID.getLoc()); 7785235633Sdim else if (IDVal == ".arch") 7786235633Sdim return parseDirectiveArch(DirectiveID.getLoc()); 7787235633Sdim else if (IDVal == ".eabi_attribute") 7788235633Sdim return parseDirectiveEabiAttr(DirectiveID.getLoc()); 7789263509Sdim else if (IDVal == ".cpu") 7790263509Sdim return parseDirectiveCPU(DirectiveID.getLoc()); 7791263509Sdim else if (IDVal == ".fpu") 7792263509Sdim return parseDirectiveFPU(DirectiveID.getLoc()); 7793263509Sdim else if (IDVal == ".fnstart") 7794263509Sdim return parseDirectiveFnStart(DirectiveID.getLoc()); 7795263509Sdim else if (IDVal == ".fnend") 7796263509Sdim return parseDirectiveFnEnd(DirectiveID.getLoc()); 7797263509Sdim else if (IDVal == ".cantunwind") 7798263509Sdim return parseDirectiveCantUnwind(DirectiveID.getLoc()); 7799263509Sdim else if (IDVal == ".personality") 7800263509Sdim return parseDirectivePersonality(DirectiveID.getLoc()); 7801263509Sdim else if (IDVal == ".handlerdata") 7802263509Sdim return parseDirectiveHandlerData(DirectiveID.getLoc()); 7803263509Sdim else if (IDVal == ".setfp") 7804263509Sdim return parseDirectiveSetFP(DirectiveID.getLoc()); 7805263509Sdim else if (IDVal == ".pad") 7806263509Sdim return parseDirectivePad(DirectiveID.getLoc()); 7807263509Sdim else if (IDVal == ".save") 7808263509Sdim return parseDirectiveRegSave(DirectiveID.getLoc(), false); 7809263509Sdim else if (IDVal == ".vsave") 7810263509Sdim return parseDirectiveRegSave(DirectiveID.getLoc(), true); 7811198090Srdivacky return true; 7812198090Srdivacky} 7813198090Srdivacky 7814226890Sdim/// parseDirectiveWord 7815198090Srdivacky/// ::= .word [ expression (, expression)* ] 7816226890Sdimbool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) { 7817198090Srdivacky if (getLexer().isNot(AsmToken::EndOfStatement)) { 7818198090Srdivacky for (;;) { 7819198090Srdivacky const MCExpr *Value; 7820252723Sdim if (getParser().parseExpression(Value)) 7821198090Srdivacky return true; 7822198090Srdivacky 7823252723Sdim 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 7839226890Sdim/// parseDirectiveThumb 7840198396Srdivacky/// ::= .thumb 7841226890Sdimbool ARMAsmParser::parseDirectiveThumb(SMLoc L) { 7842198396Srdivacky if (getLexer().isNot(AsmToken::EndOfStatement)) 7843198396Srdivacky return Error(L, "unexpected token in directive"); 7844202878Srdivacky Parser.Lex(); 7845198396Srdivacky 7846263509Sdim if (!hasThumb()) 7847263509Sdim return Error(L, "target does not support Thumb mode"); 7848263509Sdim 7849235633Sdim if (!isThumb()) 7850235633Sdim SwitchMode(); 7851235633Sdim getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16); 7852198396Srdivacky return false; 7853198396Srdivacky} 7854198396Srdivacky 7855235633Sdim/// parseDirectiveARM 7856235633Sdim/// ::= .arm 7857235633Sdimbool ARMAsmParser::parseDirectiveARM(SMLoc L) { 7858235633Sdim if (getLexer().isNot(AsmToken::EndOfStatement)) 7859235633Sdim return Error(L, "unexpected token in directive"); 7860235633Sdim Parser.Lex(); 7861235633Sdim 7862263509Sdim if (!hasARM()) 7863263509Sdim return Error(L, "target does not support ARM mode"); 7864263509Sdim 7865235633Sdim if (isThumb()) 7866235633Sdim SwitchMode(); 7867235633Sdim getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32); 7868235633Sdim return false; 7869235633Sdim} 7870235633Sdim 7871263509Sdimvoid ARMAsmParser::onLabelParsed(MCSymbol *Symbol) { 7872263509Sdim if (NextSymbolIsThumb) { 7873263509Sdim getParser().getStreamer().EmitThumbFunc(Symbol); 7874263509Sdim NextSymbolIsThumb = false; 7875263509Sdim } 7876263509Sdim} 7877263509Sdim 7878226890Sdim/// parseDirectiveThumbFunc 7879198396Srdivacky/// ::= .thumbfunc symbol_name 7880226890Sdimbool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) { 7881263509Sdim const MCAsmInfo *MAI = getParser().getStreamer().getContext().getAsmInfo(); 7882263509Sdim bool isMachO = MAI->hasSubsectionsViaSymbols(); 7883223017Sdim 7884235633Sdim // Darwin asm has (optionally) function name after .thumb_func direction 7885223017Sdim // ELF doesn't 7886223017Sdim if (isMachO) { 7887223017Sdim const AsmToken &Tok = Parser.getTok(); 7888235633Sdim if (Tok.isNot(AsmToken::EndOfStatement)) { 7889235633Sdim if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String)) 7890235633Sdim return Error(L, "unexpected token in .thumb_func directive"); 7891263509Sdim MCSymbol *Func = 7892263509Sdim getParser().getContext().GetOrCreateSymbol(Tok.getIdentifier()); 7893263509Sdim getParser().getStreamer().EmitThumbFunc(Func); 7894235633Sdim Parser.Lex(); // Consume the identifier token. 7895263509Sdim return false; 7896235633Sdim } 7897223017Sdim } 7898223017Sdim 7899198396Srdivacky if (getLexer().isNot(AsmToken::EndOfStatement)) 7900198396Srdivacky return Error(L, "unexpected token in directive"); 7901198396Srdivacky 7902263509Sdim NextSymbolIsThumb = true; 7903235633Sdim 7904198396Srdivacky return false; 7905198396Srdivacky} 7906198396Srdivacky 7907226890Sdim/// parseDirectiveSyntax 7908198396Srdivacky/// ::= .syntax unified | divided 7909226890Sdimbool 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 7930226890Sdim/// parseDirectiveCode 7931198396Srdivacky/// ::= .code 16 | 32 7932226890Sdimbool 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) { 7949263509Sdim if (!hasThumb()) 7950263509Sdim return Error(L, "target does not support Thumb mode"); 7951263509Sdim 7952224145Sdim if (!isThumb()) 7953224145Sdim SwitchMode(); 7954218893Sdim getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16); 7955224145Sdim } else { 7956263509Sdim if (!hasARM()) 7957263509Sdim return Error(L, "target does not support ARM mode"); 7958263509Sdim 7959224145Sdim if (isThumb()) 7960224145Sdim SwitchMode(); 7961224145Sdim getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32); 7962218893Sdim } 7963218893Sdim 7964198396Srdivacky return false; 7965198396Srdivacky} 7966198396Srdivacky 7967235633Sdim/// parseDirectiveReq 7968235633Sdim/// ::= name .req registername 7969235633Sdimbool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) { 7970235633Sdim Parser.Lex(); // Eat the '.req' token. 7971235633Sdim unsigned Reg; 7972235633Sdim SMLoc SRegLoc, ERegLoc; 7973235633Sdim if (ParseRegister(Reg, SRegLoc, ERegLoc)) { 7974252723Sdim Parser.eatToEndOfStatement(); 7975235633Sdim return Error(SRegLoc, "register name expected"); 7976235633Sdim } 7977235633Sdim 7978235633Sdim // Shouldn't be anything else. 7979235633Sdim if (Parser.getTok().isNot(AsmToken::EndOfStatement)) { 7980252723Sdim Parser.eatToEndOfStatement(); 7981235633Sdim return Error(Parser.getTok().getLoc(), 7982235633Sdim "unexpected input in .req directive."); 7983235633Sdim } 7984235633Sdim 7985235633Sdim Parser.Lex(); // Consume the EndOfStatement 7986235633Sdim 7987235633Sdim if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg) 7988235633Sdim return Error(SRegLoc, "redefinition of '" + Name + 7989235633Sdim "' does not match original."); 7990235633Sdim 7991235633Sdim return false; 7992235633Sdim} 7993235633Sdim 7994235633Sdim/// parseDirectiveUneq 7995235633Sdim/// ::= .unreq registername 7996235633Sdimbool ARMAsmParser::parseDirectiveUnreq(SMLoc L) { 7997235633Sdim if (Parser.getTok().isNot(AsmToken::Identifier)) { 7998252723Sdim Parser.eatToEndOfStatement(); 7999235633Sdim return Error(L, "unexpected input in .unreq directive."); 8000235633Sdim } 8001235633Sdim RegisterReqs.erase(Parser.getTok().getIdentifier()); 8002235633Sdim Parser.Lex(); // Eat the identifier. 8003235633Sdim return false; 8004235633Sdim} 8005235633Sdim 8006235633Sdim/// parseDirectiveArch 8007235633Sdim/// ::= .arch token 8008235633Sdimbool ARMAsmParser::parseDirectiveArch(SMLoc L) { 8009235633Sdim return true; 8010235633Sdim} 8011235633Sdim 8012235633Sdim/// parseDirectiveEabiAttr 8013235633Sdim/// ::= .eabi_attribute int, int 8014235633Sdimbool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) { 8015263509Sdim if (Parser.getTok().isNot(AsmToken::Integer)) 8016263509Sdim return Error(L, "integer expected"); 8017263509Sdim int64_t Tag = Parser.getTok().getIntVal(); 8018263509Sdim Parser.Lex(); // eat tag integer 8019263509Sdim 8020263509Sdim if (Parser.getTok().isNot(AsmToken::Comma)) 8021263509Sdim return Error(L, "comma expected"); 8022263509Sdim Parser.Lex(); // skip comma 8023263509Sdim 8024263509Sdim L = Parser.getTok().getLoc(); 8025263509Sdim if (Parser.getTok().isNot(AsmToken::Integer)) 8026263509Sdim return Error(L, "integer expected"); 8027263509Sdim int64_t Value = Parser.getTok().getIntVal(); 8028263509Sdim Parser.Lex(); // eat value integer 8029263509Sdim 8030263509Sdim getTargetStreamer().emitAttribute(Tag, Value); 8031263509Sdim return false; 8032235633Sdim} 8033235633Sdim 8034263509Sdim/// parseDirectiveCPU 8035263509Sdim/// ::= .cpu str 8036263509Sdimbool ARMAsmParser::parseDirectiveCPU(SMLoc L) { 8037263509Sdim StringRef CPU = getParser().parseStringToEndOfStatement().trim(); 8038263509Sdim getTargetStreamer().emitTextAttribute(ARMBuildAttrs::CPU_name, CPU); 8039263509Sdim return false; 8040263509Sdim} 8041263509Sdim 8042263509Sdim/// parseDirectiveFPU 8043263509Sdim/// ::= .fpu str 8044263509Sdimbool ARMAsmParser::parseDirectiveFPU(SMLoc L) { 8045263509Sdim StringRef FPU = getParser().parseStringToEndOfStatement().trim(); 8046263509Sdim 8047263509Sdim unsigned ID = StringSwitch<unsigned>(FPU) 8048263509Sdim#define ARM_FPU_NAME(NAME, ID) .Case(NAME, ARM::ID) 8049263509Sdim#include "ARMFPUName.def" 8050263509Sdim .Default(ARM::INVALID_FPU); 8051263509Sdim 8052263509Sdim if (ID == ARM::INVALID_FPU) 8053263509Sdim return Error(L, "Unknown FPU name"); 8054263509Sdim 8055263509Sdim getTargetStreamer().emitFPU(ID); 8056263509Sdim return false; 8057263509Sdim} 8058263509Sdim 8059263509Sdim/// parseDirectiveFnStart 8060263509Sdim/// ::= .fnstart 8061263509Sdimbool ARMAsmParser::parseDirectiveFnStart(SMLoc L) { 8062263509Sdim if (FnStartLoc.isValid()) { 8063263509Sdim Error(L, ".fnstart starts before the end of previous one"); 8064263509Sdim Error(FnStartLoc, "previous .fnstart starts here"); 8065263509Sdim return true; 8066263509Sdim } 8067263509Sdim 8068263509Sdim FnStartLoc = L; 8069263509Sdim getTargetStreamer().emitFnStart(); 8070263509Sdim return false; 8071263509Sdim} 8072263509Sdim 8073263509Sdim/// parseDirectiveFnEnd 8074263509Sdim/// ::= .fnend 8075263509Sdimbool ARMAsmParser::parseDirectiveFnEnd(SMLoc L) { 8076263509Sdim // Check the ordering of unwind directives 8077263509Sdim if (!FnStartLoc.isValid()) 8078263509Sdim return Error(L, ".fnstart must precede .fnend directive"); 8079263509Sdim 8080263509Sdim // Reset the unwind directives parser state 8081263509Sdim resetUnwindDirectiveParserState(); 8082263509Sdim getTargetStreamer().emitFnEnd(); 8083263509Sdim return false; 8084263509Sdim} 8085263509Sdim 8086263509Sdim/// parseDirectiveCantUnwind 8087263509Sdim/// ::= .cantunwind 8088263509Sdimbool ARMAsmParser::parseDirectiveCantUnwind(SMLoc L) { 8089263509Sdim // Check the ordering of unwind directives 8090263509Sdim CantUnwindLoc = L; 8091263509Sdim if (!FnStartLoc.isValid()) 8092263509Sdim return Error(L, ".fnstart must precede .cantunwind directive"); 8093263509Sdim if (HandlerDataLoc.isValid()) { 8094263509Sdim Error(L, ".cantunwind can't be used with .handlerdata directive"); 8095263509Sdim Error(HandlerDataLoc, ".handlerdata was specified here"); 8096263509Sdim return true; 8097263509Sdim } 8098263509Sdim if (PersonalityLoc.isValid()) { 8099263509Sdim Error(L, ".cantunwind can't be used with .personality directive"); 8100263509Sdim Error(PersonalityLoc, ".personality was specified here"); 8101263509Sdim return true; 8102263509Sdim } 8103263509Sdim 8104263509Sdim getTargetStreamer().emitCantUnwind(); 8105263509Sdim return false; 8106263509Sdim} 8107263509Sdim 8108263509Sdim/// parseDirectivePersonality 8109263509Sdim/// ::= .personality name 8110263509Sdimbool ARMAsmParser::parseDirectivePersonality(SMLoc L) { 8111263509Sdim // Check the ordering of unwind directives 8112263509Sdim PersonalityLoc = L; 8113263509Sdim if (!FnStartLoc.isValid()) 8114263509Sdim return Error(L, ".fnstart must precede .personality directive"); 8115263509Sdim if (CantUnwindLoc.isValid()) { 8116263509Sdim Error(L, ".personality can't be used with .cantunwind directive"); 8117263509Sdim Error(CantUnwindLoc, ".cantunwind was specified here"); 8118263509Sdim return true; 8119263509Sdim } 8120263509Sdim if (HandlerDataLoc.isValid()) { 8121263509Sdim Error(L, ".personality must precede .handlerdata directive"); 8122263509Sdim Error(HandlerDataLoc, ".handlerdata was specified here"); 8123263509Sdim return true; 8124263509Sdim } 8125263509Sdim 8126263509Sdim // Parse the name of the personality routine 8127263509Sdim if (Parser.getTok().isNot(AsmToken::Identifier)) { 8128263509Sdim Parser.eatToEndOfStatement(); 8129263509Sdim return Error(L, "unexpected input in .personality directive."); 8130263509Sdim } 8131263509Sdim StringRef Name(Parser.getTok().getIdentifier()); 8132263509Sdim Parser.Lex(); 8133263509Sdim 8134263509Sdim MCSymbol *PR = getParser().getContext().GetOrCreateSymbol(Name); 8135263509Sdim getTargetStreamer().emitPersonality(PR); 8136263509Sdim return false; 8137263509Sdim} 8138263509Sdim 8139263509Sdim/// parseDirectiveHandlerData 8140263509Sdim/// ::= .handlerdata 8141263509Sdimbool ARMAsmParser::parseDirectiveHandlerData(SMLoc L) { 8142263509Sdim // Check the ordering of unwind directives 8143263509Sdim HandlerDataLoc = L; 8144263509Sdim if (!FnStartLoc.isValid()) 8145263509Sdim return Error(L, ".fnstart must precede .personality directive"); 8146263509Sdim if (CantUnwindLoc.isValid()) { 8147263509Sdim Error(L, ".handlerdata can't be used with .cantunwind directive"); 8148263509Sdim Error(CantUnwindLoc, ".cantunwind was specified here"); 8149263509Sdim return true; 8150263509Sdim } 8151263509Sdim 8152263509Sdim getTargetStreamer().emitHandlerData(); 8153263509Sdim return false; 8154263509Sdim} 8155263509Sdim 8156263509Sdim/// parseDirectiveSetFP 8157263509Sdim/// ::= .setfp fpreg, spreg [, offset] 8158263509Sdimbool ARMAsmParser::parseDirectiveSetFP(SMLoc L) { 8159263509Sdim // Check the ordering of unwind directives 8160263509Sdim if (!FnStartLoc.isValid()) 8161263509Sdim return Error(L, ".fnstart must precede .setfp directive"); 8162263509Sdim if (HandlerDataLoc.isValid()) 8163263509Sdim return Error(L, ".setfp must precede .handlerdata directive"); 8164263509Sdim 8165263509Sdim // Parse fpreg 8166263509Sdim SMLoc NewFPRegLoc = Parser.getTok().getLoc(); 8167263509Sdim int NewFPReg = tryParseRegister(); 8168263509Sdim if (NewFPReg == -1) 8169263509Sdim return Error(NewFPRegLoc, "frame pointer register expected"); 8170263509Sdim 8171263509Sdim // Consume comma 8172263509Sdim if (!Parser.getTok().is(AsmToken::Comma)) 8173263509Sdim return Error(Parser.getTok().getLoc(), "comma expected"); 8174263509Sdim Parser.Lex(); // skip comma 8175263509Sdim 8176263509Sdim // Parse spreg 8177263509Sdim SMLoc NewSPRegLoc = Parser.getTok().getLoc(); 8178263509Sdim int NewSPReg = tryParseRegister(); 8179263509Sdim if (NewSPReg == -1) 8180263509Sdim return Error(NewSPRegLoc, "stack pointer register expected"); 8181263509Sdim 8182263509Sdim if (NewSPReg != ARM::SP && NewSPReg != FPReg) 8183263509Sdim return Error(NewSPRegLoc, 8184263509Sdim "register should be either $sp or the latest fp register"); 8185263509Sdim 8186263509Sdim // Update the frame pointer register 8187263509Sdim FPReg = NewFPReg; 8188263509Sdim 8189263509Sdim // Parse offset 8190263509Sdim int64_t Offset = 0; 8191263509Sdim if (Parser.getTok().is(AsmToken::Comma)) { 8192263509Sdim Parser.Lex(); // skip comma 8193263509Sdim 8194263509Sdim if (Parser.getTok().isNot(AsmToken::Hash) && 8195263509Sdim Parser.getTok().isNot(AsmToken::Dollar)) { 8196263509Sdim return Error(Parser.getTok().getLoc(), "'#' expected"); 8197263509Sdim } 8198263509Sdim Parser.Lex(); // skip hash token. 8199263509Sdim 8200263509Sdim const MCExpr *OffsetExpr; 8201263509Sdim SMLoc ExLoc = Parser.getTok().getLoc(); 8202263509Sdim SMLoc EndLoc; 8203263509Sdim if (getParser().parseExpression(OffsetExpr, EndLoc)) 8204263509Sdim return Error(ExLoc, "malformed setfp offset"); 8205263509Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(OffsetExpr); 8206263509Sdim if (!CE) 8207263509Sdim return Error(ExLoc, "setfp offset must be an immediate"); 8208263509Sdim 8209263509Sdim Offset = CE->getValue(); 8210263509Sdim } 8211263509Sdim 8212263509Sdim getTargetStreamer().emitSetFP(static_cast<unsigned>(NewFPReg), 8213263509Sdim static_cast<unsigned>(NewSPReg), Offset); 8214263509Sdim return false; 8215263509Sdim} 8216263509Sdim 8217263509Sdim/// parseDirective 8218263509Sdim/// ::= .pad offset 8219263509Sdimbool ARMAsmParser::parseDirectivePad(SMLoc L) { 8220263509Sdim // Check the ordering of unwind directives 8221263509Sdim if (!FnStartLoc.isValid()) 8222263509Sdim return Error(L, ".fnstart must precede .pad directive"); 8223263509Sdim if (HandlerDataLoc.isValid()) 8224263509Sdim return Error(L, ".pad must precede .handlerdata directive"); 8225263509Sdim 8226263509Sdim // Parse the offset 8227263509Sdim if (Parser.getTok().isNot(AsmToken::Hash) && 8228263509Sdim Parser.getTok().isNot(AsmToken::Dollar)) { 8229263509Sdim return Error(Parser.getTok().getLoc(), "'#' expected"); 8230263509Sdim } 8231263509Sdim Parser.Lex(); // skip hash token. 8232263509Sdim 8233263509Sdim const MCExpr *OffsetExpr; 8234263509Sdim SMLoc ExLoc = Parser.getTok().getLoc(); 8235263509Sdim SMLoc EndLoc; 8236263509Sdim if (getParser().parseExpression(OffsetExpr, EndLoc)) 8237263509Sdim return Error(ExLoc, "malformed pad offset"); 8238263509Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(OffsetExpr); 8239263509Sdim if (!CE) 8240263509Sdim return Error(ExLoc, "pad offset must be an immediate"); 8241263509Sdim 8242263509Sdim getTargetStreamer().emitPad(CE->getValue()); 8243263509Sdim return false; 8244263509Sdim} 8245263509Sdim 8246263509Sdim/// parseDirectiveRegSave 8247263509Sdim/// ::= .save { registers } 8248263509Sdim/// ::= .vsave { registers } 8249263509Sdimbool ARMAsmParser::parseDirectiveRegSave(SMLoc L, bool IsVector) { 8250263509Sdim // Check the ordering of unwind directives 8251263509Sdim if (!FnStartLoc.isValid()) 8252263509Sdim return Error(L, ".fnstart must precede .save or .vsave directives"); 8253263509Sdim if (HandlerDataLoc.isValid()) 8254263509Sdim return Error(L, ".save or .vsave must precede .handlerdata directive"); 8255263509Sdim 8256263509Sdim // RAII object to make sure parsed operands are deleted. 8257263509Sdim struct CleanupObject { 8258263509Sdim SmallVector<MCParsedAsmOperand *, 1> Operands; 8259263509Sdim ~CleanupObject() { 8260263509Sdim for (unsigned I = 0, E = Operands.size(); I != E; ++I) 8261263509Sdim delete Operands[I]; 8262263509Sdim } 8263263509Sdim } CO; 8264263509Sdim 8265263509Sdim // Parse the register list 8266263509Sdim if (parseRegisterList(CO.Operands)) 8267263509Sdim return true; 8268263509Sdim ARMOperand *Op = (ARMOperand*)CO.Operands[0]; 8269263509Sdim if (!IsVector && !Op->isRegList()) 8270263509Sdim return Error(L, ".save expects GPR registers"); 8271263509Sdim if (IsVector && !Op->isDPRRegList()) 8272263509Sdim return Error(L, ".vsave expects DPR registers"); 8273263509Sdim 8274263509Sdim getTargetStreamer().emitRegSave(Op->getRegList(), IsVector); 8275263509Sdim return false; 8276263509Sdim} 8277263509Sdim 8278198892Srdivacky/// Force static initialization. 8279198090Srdivackyextern "C" void LLVMInitializeARMAsmParser() { 8280226890Sdim RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget); 8281226890Sdim RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget); 8282198090Srdivacky} 8283212904Sdim 8284218893Sdim#define GET_REGISTER_MATCHER 8285245431Sdim#define GET_SUBTARGET_FEATURE_NAME 8286218893Sdim#define GET_MATCHER_IMPLEMENTATION 8287212904Sdim#include "ARMGenAsmMatcher.inc" 8288252723Sdim 8289252723Sdim// Define this matcher function after the auto-generated include so we 8290252723Sdim// have the match class enum definitions. 8291252723Sdimunsigned ARMAsmParser::validateTargetOperandClass(MCParsedAsmOperand *AsmOp, 8292252723Sdim unsigned Kind) { 8293252723Sdim ARMOperand *Op = static_cast<ARMOperand*>(AsmOp); 8294252723Sdim // If the kind is a token for a literal immediate, check if our asm 8295252723Sdim // operand matches. This is for InstAliases which have a fixed-value 8296252723Sdim // immediate in the syntax. 8297252723Sdim if (Kind == MCK__35_0 && Op->isImm()) { 8298252723Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm()); 8299252723Sdim if (!CE) 8300252723Sdim return Match_InvalidOperand; 8301252723Sdim if (CE->getValue() == 0) 8302252723Sdim return Match_Success; 8303252723Sdim } 8304252723Sdim return Match_InvalidOperand; 8305252723Sdim} 8306