ARMAsmParser.cpp revision 221345
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 10198090Srdivacky#include "ARM.h" 11218893Sdim#include "ARMAddressingModes.h" 12218893Sdim#include "ARMMCExpr.h" 13218893Sdim#include "ARMBaseRegisterInfo.h" 14212904Sdim#include "ARMSubtarget.h" 15202878Srdivacky#include "llvm/MC/MCParser/MCAsmLexer.h" 16202878Srdivacky#include "llvm/MC/MCParser/MCAsmParser.h" 17202878Srdivacky#include "llvm/MC/MCParser/MCParsedAsmOperand.h" 18218893Sdim#include "llvm/MC/MCContext.h" 19198090Srdivacky#include "llvm/MC/MCStreamer.h" 20198090Srdivacky#include "llvm/MC/MCExpr.h" 21198090Srdivacky#include "llvm/MC/MCInst.h" 22202878Srdivacky#include "llvm/Target/TargetRegistry.h" 23202878Srdivacky#include "llvm/Target/TargetAsmParser.h" 24198090Srdivacky#include "llvm/Support/SourceMgr.h" 25212904Sdim#include "llvm/Support/raw_ostream.h" 26202878Srdivacky#include "llvm/ADT/SmallVector.h" 27218893Sdim#include "llvm/ADT/StringExtras.h" 28212904Sdim#include "llvm/ADT/StringSwitch.h" 29202878Srdivacky#include "llvm/ADT/Twine.h" 30198090Srdivackyusing namespace llvm; 31198090Srdivacky 32218893Sdimnamespace { 33218893Sdim 34218893Sdimclass ARMOperand; 35218893Sdim 36198090Srdivackyclass ARMAsmParser : public TargetAsmParser { 37198090Srdivacky MCAsmParser &Parser; 38212904Sdim TargetMachine &TM; 39198090Srdivacky 40198090Srdivacky MCAsmParser &getParser() const { return Parser; } 41198090Srdivacky MCAsmLexer &getLexer() const { return Parser.getLexer(); } 42198090Srdivacky 43198090Srdivacky void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); } 44198090Srdivacky bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); } 45198090Srdivacky 46218893Sdim int TryParseRegister(); 47218893Sdim virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); 48218893Sdim bool TryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &); 49221345Sdim bool TryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &); 50218893Sdim bool ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &); 51221345Sdim bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &, 52221345Sdim ARMII::AddrMode AddrMode); 53218893Sdim bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic); 54218893Sdim bool ParsePrefix(ARMMCExpr::VariantKind &RefKind); 55218893Sdim const MCExpr *ApplyPrefixToExpr(const MCExpr *E, 56218893Sdim MCSymbolRefExpr::VariantKind Variant); 57198090Srdivacky 58198090Srdivacky 59198892Srdivacky bool ParseMemoryOffsetReg(bool &Negative, 60198892Srdivacky bool &OffsetRegShifted, 61221345Sdim enum ARM_AM::ShiftOpc &ShiftType, 62198892Srdivacky const MCExpr *&ShiftAmount, 63198892Srdivacky const MCExpr *&Offset, 64198892Srdivacky bool &OffsetIsReg, 65206124Srdivacky int &OffsetRegNum, 66206124Srdivacky SMLoc &E); 67221345Sdim bool ParseShift(enum ARM_AM::ShiftOpc &St, 68221345Sdim const MCExpr *&ShiftAmount, SMLoc &E); 69198090Srdivacky bool ParseDirectiveWord(unsigned Size, SMLoc L); 70198396Srdivacky bool ParseDirectiveThumb(SMLoc L); 71198396Srdivacky bool ParseDirectiveThumbFunc(SMLoc L); 72198396Srdivacky bool ParseDirectiveCode(SMLoc L); 73198396Srdivacky bool ParseDirectiveSyntax(SMLoc L); 74198396Srdivacky 75218893Sdim bool MatchAndEmitInstruction(SMLoc IDLoc, 76218893Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands, 77218893Sdim MCStreamer &Out); 78218893Sdim void GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, 79218893Sdim bool &CanAcceptPredicationCode); 80198090Srdivacky 81198090Srdivacky /// @name Auto-generated Match Functions 82198090Srdivacky /// { 83198090Srdivacky 84218893Sdim#define GET_ASSEMBLER_HEADER 85218893Sdim#include "ARMGenAsmMatcher.inc" 86198090Srdivacky 87198090Srdivacky /// } 88198090Srdivacky 89218893Sdim OperandMatchResultTy tryParseCoprocNumOperand( 90218893Sdim SmallVectorImpl<MCParsedAsmOperand*>&); 91218893Sdim OperandMatchResultTy tryParseCoprocRegOperand( 92218893Sdim SmallVectorImpl<MCParsedAsmOperand*>&); 93218893Sdim OperandMatchResultTy tryParseMemBarrierOptOperand( 94218893Sdim SmallVectorImpl<MCParsedAsmOperand*>&); 95218893Sdim OperandMatchResultTy tryParseProcIFlagsOperand( 96218893Sdim SmallVectorImpl<MCParsedAsmOperand*>&); 97218893Sdim OperandMatchResultTy tryParseMSRMaskOperand( 98218893Sdim SmallVectorImpl<MCParsedAsmOperand*>&); 99221345Sdim OperandMatchResultTy tryParseMemMode2Operand( 100221345Sdim SmallVectorImpl<MCParsedAsmOperand*>&); 101221345Sdim OperandMatchResultTy tryParseMemMode3Operand( 102221345Sdim SmallVectorImpl<MCParsedAsmOperand*>&); 103198090Srdivacky 104221345Sdim // Asm Match Converter Methods 105221345Sdim bool CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode, 106221345Sdim const SmallVectorImpl<MCParsedAsmOperand*> &); 107221345Sdim bool CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode, 108221345Sdim const SmallVectorImpl<MCParsedAsmOperand*> &); 109221345Sdim bool CvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode, 110221345Sdim const SmallVectorImpl<MCParsedAsmOperand*> &); 111221345Sdim bool CvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode, 112221345Sdim const SmallVectorImpl<MCParsedAsmOperand*> &); 113221345Sdim 114198090Srdivackypublic: 115212904Sdim ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM) 116218893Sdim : TargetAsmParser(T), Parser(_Parser), TM(_TM) { 117221345Sdim MCAsmParserExtension::Initialize(_Parser); 118218893Sdim // Initialize the set of available features. 119218893Sdim setAvailableFeatures(ComputeAvailableFeatures( 120218893Sdim &TM.getSubtarget<ARMSubtarget>())); 121218893Sdim } 122198090Srdivacky 123210299Sed virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc, 124202375Srdivacky SmallVectorImpl<MCParsedAsmOperand*> &Operands); 125198090Srdivacky virtual bool ParseDirective(AsmToken DirectiveID); 126198090Srdivacky}; 127218893Sdim} // end anonymous namespace 128218893Sdim 129218893Sdimnamespace { 130218893Sdim 131198090Srdivacky/// ARMOperand - Instances of this class represent a parsed ARM machine 132198090Srdivacky/// instruction. 133218893Sdimclass ARMOperand : public MCParsedAsmOperand { 134206124Srdivacky enum KindTy { 135212904Sdim CondCode, 136218893Sdim CCOut, 137218893Sdim CoprocNum, 138218893Sdim CoprocReg, 139212904Sdim Immediate, 140218893Sdim MemBarrierOpt, 141212904Sdim Memory, 142218893Sdim MSRMask, 143218893Sdim ProcIFlags, 144198090Srdivacky Register, 145218893Sdim RegisterList, 146218893Sdim DPRRegisterList, 147218893Sdim SPRRegisterList, 148221345Sdim Shifter, 149212904Sdim Token 150198090Srdivacky } Kind; 151198090Srdivacky 152206124Srdivacky SMLoc StartLoc, EndLoc; 153218893Sdim SmallVector<unsigned, 8> Registers; 154198090Srdivacky 155198090Srdivacky union { 156198090Srdivacky struct { 157212904Sdim ARMCC::CondCodes Val; 158212904Sdim } CC; 159212904Sdim 160212904Sdim struct { 161218893Sdim ARM_MB::MemBOpt Val; 162218893Sdim } MBOpt; 163218893Sdim 164218893Sdim struct { 165218893Sdim unsigned Val; 166218893Sdim } Cop; 167218893Sdim 168218893Sdim struct { 169218893Sdim ARM_PROC::IFlags Val; 170218893Sdim } IFlags; 171218893Sdim 172218893Sdim struct { 173218893Sdim unsigned Val; 174218893Sdim } MMask; 175218893Sdim 176218893Sdim struct { 177198090Srdivacky const char *Data; 178198090Srdivacky unsigned Length; 179198090Srdivacky } Tok; 180198090Srdivacky 181198090Srdivacky struct { 182198090Srdivacky unsigned RegNum; 183198090Srdivacky } Reg; 184198090Srdivacky 185198090Srdivacky struct { 186198090Srdivacky const MCExpr *Val; 187198090Srdivacky } Imm; 188218893Sdim 189218893Sdim /// Combined record for all forms of ARM address expressions. 190198090Srdivacky struct { 191221345Sdim ARMII::AddrMode AddrMode; 192198090Srdivacky unsigned BaseRegNum; 193218893Sdim union { 194218893Sdim unsigned RegNum; ///< Offset register num, when OffsetIsReg. 195218893Sdim const MCExpr *Value; ///< Offset value, when !OffsetIsReg. 196218893Sdim } Offset; 197218893Sdim const MCExpr *ShiftAmount; // used when OffsetRegShifted is true 198221345Sdim enum ARM_AM::ShiftOpc ShiftType; // used when OffsetRegShifted is true 199218893Sdim unsigned OffsetRegShifted : 1; // only used when OffsetIsReg is true 200218893Sdim unsigned Preindexed : 1; 201218893Sdim unsigned Postindexed : 1; 202218893Sdim unsigned OffsetIsReg : 1; 203218893Sdim unsigned Negative : 1; // only used when OffsetIsReg is true 204218893Sdim unsigned Writeback : 1; 205198090Srdivacky } Mem; 206221345Sdim 207221345Sdim struct { 208221345Sdim ARM_AM::ShiftOpc ShiftTy; 209221345Sdim unsigned RegNum; 210221345Sdim } Shift; 211218893Sdim }; 212198090Srdivacky 213218893Sdim ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} 214218893Sdimpublic: 215206124Srdivacky ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() { 216206124Srdivacky Kind = o.Kind; 217206124Srdivacky StartLoc = o.StartLoc; 218206124Srdivacky EndLoc = o.EndLoc; 219206124Srdivacky switch (Kind) { 220212904Sdim case CondCode: 221212904Sdim CC = o.CC; 222212904Sdim break; 223206124Srdivacky case Token: 224212904Sdim Tok = o.Tok; 225206124Srdivacky break; 226218893Sdim case CCOut: 227206124Srdivacky case Register: 228206124Srdivacky Reg = o.Reg; 229206124Srdivacky break; 230218893Sdim case RegisterList: 231218893Sdim case DPRRegisterList: 232218893Sdim case SPRRegisterList: 233218893Sdim Registers = o.Registers; 234218893Sdim break; 235218893Sdim case CoprocNum: 236218893Sdim case CoprocReg: 237218893Sdim Cop = o.Cop; 238218893Sdim break; 239206124Srdivacky case Immediate: 240206124Srdivacky Imm = o.Imm; 241206124Srdivacky break; 242218893Sdim case MemBarrierOpt: 243218893Sdim MBOpt = o.MBOpt; 244218893Sdim break; 245206124Srdivacky case Memory: 246206124Srdivacky Mem = o.Mem; 247206124Srdivacky break; 248218893Sdim case MSRMask: 249218893Sdim MMask = o.MMask; 250218893Sdim break; 251218893Sdim case ProcIFlags: 252218893Sdim IFlags = o.IFlags; 253221345Sdim break; 254221345Sdim case Shifter: 255221345Sdim Shift = o.Shift; 256221345Sdim break; 257206124Srdivacky } 258206124Srdivacky } 259218893Sdim 260206124Srdivacky /// getStartLoc - Get the location of the first token of this operand. 261206124Srdivacky SMLoc getStartLoc() const { return StartLoc; } 262206124Srdivacky /// getEndLoc - Get the location of the last token of this operand. 263206124Srdivacky SMLoc getEndLoc() const { return EndLoc; } 264198090Srdivacky 265212904Sdim ARMCC::CondCodes getCondCode() const { 266212904Sdim assert(Kind == CondCode && "Invalid access!"); 267212904Sdim return CC.Val; 268212904Sdim } 269212904Sdim 270218893Sdim unsigned getCoproc() const { 271218893Sdim assert((Kind == CoprocNum || Kind == CoprocReg) && "Invalid access!"); 272218893Sdim return Cop.Val; 273218893Sdim } 274218893Sdim 275198090Srdivacky StringRef getToken() const { 276198090Srdivacky assert(Kind == Token && "Invalid access!"); 277198090Srdivacky return StringRef(Tok.Data, Tok.Length); 278198090Srdivacky } 279198090Srdivacky 280198090Srdivacky unsigned getReg() const { 281218893Sdim assert((Kind == Register || Kind == CCOut) && "Invalid access!"); 282198090Srdivacky return Reg.RegNum; 283198090Srdivacky } 284198090Srdivacky 285218893Sdim const SmallVectorImpl<unsigned> &getRegList() const { 286218893Sdim assert((Kind == RegisterList || Kind == DPRRegisterList || 287218893Sdim Kind == SPRRegisterList) && "Invalid access!"); 288218893Sdim return Registers; 289218893Sdim } 290218893Sdim 291198090Srdivacky const MCExpr *getImm() const { 292198090Srdivacky assert(Kind == Immediate && "Invalid access!"); 293198090Srdivacky return Imm.Val; 294198090Srdivacky } 295198090Srdivacky 296218893Sdim ARM_MB::MemBOpt getMemBarrierOpt() const { 297218893Sdim assert(Kind == MemBarrierOpt && "Invalid access!"); 298218893Sdim return MBOpt.Val; 299218893Sdim } 300218893Sdim 301218893Sdim ARM_PROC::IFlags getProcIFlags() const { 302218893Sdim assert(Kind == ProcIFlags && "Invalid access!"); 303218893Sdim return IFlags.Val; 304218893Sdim } 305218893Sdim 306218893Sdim unsigned getMSRMask() const { 307218893Sdim assert(Kind == MSRMask && "Invalid access!"); 308218893Sdim return MMask.Val; 309218893Sdim } 310218893Sdim 311218893Sdim /// @name Memory Operand Accessors 312218893Sdim /// @{ 313221345Sdim ARMII::AddrMode getMemAddrMode() const { 314221345Sdim return Mem.AddrMode; 315221345Sdim } 316218893Sdim unsigned getMemBaseRegNum() const { 317218893Sdim return Mem.BaseRegNum; 318218893Sdim } 319218893Sdim unsigned getMemOffsetRegNum() const { 320218893Sdim assert(Mem.OffsetIsReg && "Invalid access!"); 321218893Sdim return Mem.Offset.RegNum; 322218893Sdim } 323218893Sdim const MCExpr *getMemOffset() const { 324218893Sdim assert(!Mem.OffsetIsReg && "Invalid access!"); 325218893Sdim return Mem.Offset.Value; 326218893Sdim } 327218893Sdim unsigned getMemOffsetRegShifted() const { 328218893Sdim assert(Mem.OffsetIsReg && "Invalid access!"); 329218893Sdim return Mem.OffsetRegShifted; 330218893Sdim } 331218893Sdim const MCExpr *getMemShiftAmount() const { 332218893Sdim assert(Mem.OffsetIsReg && Mem.OffsetRegShifted && "Invalid access!"); 333218893Sdim return Mem.ShiftAmount; 334218893Sdim } 335221345Sdim enum ARM_AM::ShiftOpc getMemShiftType() const { 336218893Sdim assert(Mem.OffsetIsReg && Mem.OffsetRegShifted && "Invalid access!"); 337218893Sdim return Mem.ShiftType; 338218893Sdim } 339218893Sdim bool getMemPreindexed() const { return Mem.Preindexed; } 340218893Sdim bool getMemPostindexed() const { return Mem.Postindexed; } 341218893Sdim bool getMemOffsetIsReg() const { return Mem.OffsetIsReg; } 342218893Sdim bool getMemNegative() const { return Mem.Negative; } 343218893Sdim bool getMemWriteback() const { return Mem.Writeback; } 344218893Sdim 345218893Sdim /// @} 346218893Sdim 347218893Sdim bool isCoprocNum() const { return Kind == CoprocNum; } 348218893Sdim bool isCoprocReg() const { return Kind == CoprocReg; } 349212904Sdim bool isCondCode() const { return Kind == CondCode; } 350218893Sdim bool isCCOut() const { return Kind == CCOut; } 351212904Sdim bool isImm() const { return Kind == Immediate; } 352198090Srdivacky bool isReg() const { return Kind == Register; } 353218893Sdim bool isRegList() const { return Kind == RegisterList; } 354218893Sdim bool isDPRRegList() const { return Kind == DPRRegisterList; } 355218893Sdim bool isSPRRegList() const { return Kind == SPRRegisterList; } 356218893Sdim bool isToken() const { return Kind == Token; } 357218893Sdim bool isMemBarrierOpt() const { return Kind == MemBarrierOpt; } 358218893Sdim bool isMemory() const { return Kind == Memory; } 359221345Sdim bool isShifter() const { return Kind == Shifter; } 360221345Sdim bool isMemMode2() const { 361221345Sdim if (getMemAddrMode() != ARMII::AddrMode2) 362221345Sdim return false; 363221345Sdim 364221345Sdim if (getMemOffsetIsReg()) 365221345Sdim return true; 366221345Sdim 367221345Sdim if (getMemNegative() && 368221345Sdim !(getMemPostindexed() || getMemPreindexed())) 369221345Sdim return false; 370221345Sdim 371221345Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset()); 372221345Sdim if (!CE) return false; 373221345Sdim int64_t Value = CE->getValue(); 374221345Sdim 375221345Sdim // The offset must be in the range 0-4095 (imm12). 376221345Sdim if (Value > 4095 || Value < -4095) 377221345Sdim return false; 378221345Sdim 379221345Sdim return true; 380221345Sdim } 381221345Sdim bool isMemMode3() const { 382221345Sdim if (getMemAddrMode() != ARMII::AddrMode3) 383221345Sdim return false; 384221345Sdim 385221345Sdim if (getMemOffsetIsReg()) { 386221345Sdim if (getMemOffsetRegShifted()) 387221345Sdim return false; // No shift with offset reg allowed 388221345Sdim return true; 389221345Sdim } 390221345Sdim 391221345Sdim if (getMemNegative() && 392221345Sdim !(getMemPostindexed() || getMemPreindexed())) 393221345Sdim return false; 394221345Sdim 395221345Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset()); 396221345Sdim if (!CE) return false; 397221345Sdim int64_t Value = CE->getValue(); 398221345Sdim 399221345Sdim // The offset must be in the range 0-255 (imm8). 400221345Sdim if (Value > 255 || Value < -255) 401221345Sdim return false; 402221345Sdim 403221345Sdim return true; 404221345Sdim } 405218893Sdim bool isMemMode5() const { 406218893Sdim if (!isMemory() || getMemOffsetIsReg() || getMemWriteback() || 407218893Sdim getMemNegative()) 408218893Sdim return false; 409198090Srdivacky 410218893Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset()); 411218893Sdim if (!CE) return false; 412212904Sdim 413218893Sdim // The offset must be a multiple of 4 in the range 0-1020. 414218893Sdim int64_t Value = CE->getValue(); 415218893Sdim return ((Value & 0x3) == 0 && Value <= 1020 && Value >= -1020); 416218893Sdim } 417221345Sdim bool isMemMode7() const { 418221345Sdim if (!isMemory() || 419221345Sdim getMemPreindexed() || 420221345Sdim getMemPostindexed() || 421221345Sdim getMemOffsetIsReg() || 422221345Sdim getMemNegative() || 423221345Sdim getMemWriteback()) 424221345Sdim return false; 425221345Sdim 426221345Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset()); 427221345Sdim if (!CE) return false; 428221345Sdim 429221345Sdim if (CE->getValue()) 430221345Sdim return false; 431221345Sdim 432221345Sdim return true; 433221345Sdim } 434218893Sdim bool isMemModeRegThumb() const { 435218893Sdim if (!isMemory() || !getMemOffsetIsReg() || getMemWriteback()) 436218893Sdim return false; 437218893Sdim return true; 438218893Sdim } 439218893Sdim bool isMemModeImmThumb() const { 440218893Sdim if (!isMemory() || getMemOffsetIsReg() || getMemWriteback()) 441218893Sdim return false; 442218893Sdim 443218893Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset()); 444218893Sdim if (!CE) return false; 445218893Sdim 446218893Sdim // The offset must be a multiple of 4 in the range 0-124. 447218893Sdim uint64_t Value = CE->getValue(); 448218893Sdim return ((Value & 0x3) == 0 && Value <= 124); 449218893Sdim } 450218893Sdim bool isMSRMask() const { return Kind == MSRMask; } 451218893Sdim bool isProcIFlags() const { return Kind == ProcIFlags; } 452218893Sdim 453212904Sdim void addExpr(MCInst &Inst, const MCExpr *Expr) const { 454218893Sdim // Add as immediates when possible. Null MCExpr = 0. 455218893Sdim if (Expr == 0) 456218893Sdim Inst.addOperand(MCOperand::CreateImm(0)); 457218893Sdim else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) 458212904Sdim Inst.addOperand(MCOperand::CreateImm(CE->getValue())); 459212904Sdim else 460212904Sdim Inst.addOperand(MCOperand::CreateExpr(Expr)); 461212904Sdim } 462212904Sdim 463212904Sdim void addCondCodeOperands(MCInst &Inst, unsigned N) const { 464212904Sdim assert(N == 2 && "Invalid number of operands!"); 465212904Sdim Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode()))); 466218893Sdim unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR; 467218893Sdim Inst.addOperand(MCOperand::CreateReg(RegNum)); 468212904Sdim } 469212904Sdim 470218893Sdim void addCoprocNumOperands(MCInst &Inst, unsigned N) const { 471218893Sdim assert(N == 1 && "Invalid number of operands!"); 472218893Sdim Inst.addOperand(MCOperand::CreateImm(getCoproc())); 473218893Sdim } 474218893Sdim 475218893Sdim void addCoprocRegOperands(MCInst &Inst, unsigned N) const { 476218893Sdim assert(N == 1 && "Invalid number of operands!"); 477218893Sdim Inst.addOperand(MCOperand::CreateImm(getCoproc())); 478218893Sdim } 479218893Sdim 480218893Sdim void addCCOutOperands(MCInst &Inst, unsigned N) const { 481218893Sdim assert(N == 1 && "Invalid number of operands!"); 482218893Sdim Inst.addOperand(MCOperand::CreateReg(getReg())); 483218893Sdim } 484218893Sdim 485198090Srdivacky void addRegOperands(MCInst &Inst, unsigned N) const { 486198090Srdivacky assert(N == 1 && "Invalid number of operands!"); 487198090Srdivacky Inst.addOperand(MCOperand::CreateReg(getReg())); 488198090Srdivacky } 489198090Srdivacky 490221345Sdim void addShifterOperands(MCInst &Inst, unsigned N) const { 491221345Sdim assert(N == 1 && "Invalid number of operands!"); 492221345Sdim Inst.addOperand(MCOperand::CreateImm( 493221345Sdim ARM_AM::getSORegOpc(Shift.ShiftTy, 0))); 494221345Sdim } 495221345Sdim 496218893Sdim void addRegListOperands(MCInst &Inst, unsigned N) const { 497218893Sdim assert(N == 1 && "Invalid number of operands!"); 498218893Sdim const SmallVectorImpl<unsigned> &RegList = getRegList(); 499218893Sdim for (SmallVectorImpl<unsigned>::const_iterator 500218893Sdim I = RegList.begin(), E = RegList.end(); I != E; ++I) 501218893Sdim Inst.addOperand(MCOperand::CreateReg(*I)); 502218893Sdim } 503218893Sdim 504218893Sdim void addDPRRegListOperands(MCInst &Inst, unsigned N) const { 505218893Sdim addRegListOperands(Inst, N); 506218893Sdim } 507218893Sdim 508218893Sdim void addSPRRegListOperands(MCInst &Inst, unsigned N) const { 509218893Sdim addRegListOperands(Inst, N); 510218893Sdim } 511218893Sdim 512212904Sdim void addImmOperands(MCInst &Inst, unsigned N) const { 513212904Sdim assert(N == 1 && "Invalid number of operands!"); 514212904Sdim addExpr(Inst, getImm()); 515212904Sdim } 516212904Sdim 517218893Sdim void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const { 518218893Sdim assert(N == 1 && "Invalid number of operands!"); 519218893Sdim Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt()))); 520218893Sdim } 521218893Sdim 522221345Sdim void addMemMode7Operands(MCInst &Inst, unsigned N) const { 523221345Sdim assert(N == 1 && isMemMode7() && "Invalid number of operands!"); 524221345Sdim Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum())); 525221345Sdim 526221345Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset()); 527221345Sdim (void)CE; 528221345Sdim assert((CE || CE->getValue() == 0) && 529221345Sdim "No offset operand support in mode 7"); 530221345Sdim } 531221345Sdim 532221345Sdim void addMemMode2Operands(MCInst &Inst, unsigned N) const { 533221345Sdim assert(isMemMode2() && "Invalid mode or number of operands!"); 534221345Sdim Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum())); 535221345Sdim unsigned IdxMode = (getMemPreindexed() | getMemPostindexed() << 1); 536221345Sdim 537221345Sdim if (getMemOffsetIsReg()) { 538221345Sdim Inst.addOperand(MCOperand::CreateReg(getMemOffsetRegNum())); 539221345Sdim 540221345Sdim ARM_AM::AddrOpc AMOpc = getMemNegative() ? ARM_AM::sub : ARM_AM::add; 541221345Sdim ARM_AM::ShiftOpc ShOpc = ARM_AM::no_shift; 542221345Sdim int64_t ShiftAmount = 0; 543221345Sdim 544221345Sdim if (getMemOffsetRegShifted()) { 545221345Sdim ShOpc = getMemShiftType(); 546221345Sdim const MCConstantExpr *CE = 547221345Sdim dyn_cast<MCConstantExpr>(getMemShiftAmount()); 548221345Sdim ShiftAmount = CE->getValue(); 549221345Sdim } 550221345Sdim 551221345Sdim Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(AMOpc, ShiftAmount, 552221345Sdim ShOpc, IdxMode))); 553221345Sdim return; 554221345Sdim } 555221345Sdim 556221345Sdim // Create a operand placeholder to always yield the same number of operands. 557221345Sdim Inst.addOperand(MCOperand::CreateReg(0)); 558221345Sdim 559221345Sdim // FIXME: #-0 is encoded differently than #0. Does the parser preserve 560221345Sdim // the difference? 561221345Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset()); 562221345Sdim assert(CE && "Non-constant mode 2 offset operand!"); 563221345Sdim int64_t Offset = CE->getValue(); 564221345Sdim 565221345Sdim if (Offset >= 0) 566221345Sdim Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(ARM_AM::add, 567221345Sdim Offset, ARM_AM::no_shift, IdxMode))); 568221345Sdim else 569221345Sdim Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(ARM_AM::sub, 570221345Sdim -Offset, ARM_AM::no_shift, IdxMode))); 571221345Sdim } 572221345Sdim 573221345Sdim void addMemMode3Operands(MCInst &Inst, unsigned N) const { 574221345Sdim assert(isMemMode3() && "Invalid mode or number of operands!"); 575221345Sdim Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum())); 576221345Sdim unsigned IdxMode = (getMemPreindexed() | getMemPostindexed() << 1); 577221345Sdim 578221345Sdim if (getMemOffsetIsReg()) { 579221345Sdim Inst.addOperand(MCOperand::CreateReg(getMemOffsetRegNum())); 580221345Sdim 581221345Sdim ARM_AM::AddrOpc AMOpc = getMemNegative() ? ARM_AM::sub : ARM_AM::add; 582221345Sdim Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM3Opc(AMOpc, 0, 583221345Sdim IdxMode))); 584221345Sdim return; 585221345Sdim } 586221345Sdim 587221345Sdim // Create a operand placeholder to always yield the same number of operands. 588221345Sdim Inst.addOperand(MCOperand::CreateReg(0)); 589221345Sdim 590221345Sdim // FIXME: #-0 is encoded differently than #0. Does the parser preserve 591221345Sdim // the difference? 592221345Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset()); 593221345Sdim assert(CE && "Non-constant mode 3 offset operand!"); 594221345Sdim int64_t Offset = CE->getValue(); 595221345Sdim 596221345Sdim if (Offset >= 0) 597221345Sdim Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM3Opc(ARM_AM::add, 598221345Sdim Offset, IdxMode))); 599221345Sdim else 600221345Sdim Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM3Opc(ARM_AM::sub, 601221345Sdim -Offset, IdxMode))); 602221345Sdim } 603221345Sdim 604218893Sdim void addMemMode5Operands(MCInst &Inst, unsigned N) const { 605218893Sdim assert(N == 2 && isMemMode5() && "Invalid number of operands!"); 606218893Sdim 607218893Sdim Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum())); 608218893Sdim assert(!getMemOffsetIsReg() && "Invalid mode 5 operand"); 609218893Sdim 610218893Sdim // FIXME: #-0 is encoded differently than #0. Does the parser preserve 611218893Sdim // the difference? 612218893Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset()); 613218893Sdim assert(CE && "Non-constant mode 5 offset operand!"); 614218893Sdim 615218893Sdim // The MCInst offset operand doesn't include the low two bits (like 616218893Sdim // the instruction encoding). 617218893Sdim int64_t Offset = CE->getValue() / 4; 618218893Sdim if (Offset >= 0) 619218893Sdim Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::add, 620218893Sdim Offset))); 621218893Sdim else 622218893Sdim Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::sub, 623218893Sdim -Offset))); 624218893Sdim } 625218893Sdim 626218893Sdim void addMemModeRegThumbOperands(MCInst &Inst, unsigned N) const { 627218893Sdim assert(N == 2 && isMemModeRegThumb() && "Invalid number of operands!"); 628218893Sdim Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum())); 629218893Sdim Inst.addOperand(MCOperand::CreateReg(getMemOffsetRegNum())); 630218893Sdim } 631218893Sdim 632218893Sdim void addMemModeImmThumbOperands(MCInst &Inst, unsigned N) const { 633218893Sdim assert(N == 2 && isMemModeImmThumb() && "Invalid number of operands!"); 634218893Sdim Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum())); 635218893Sdim const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset()); 636218893Sdim assert(CE && "Non-constant mode offset operand!"); 637218893Sdim Inst.addOperand(MCOperand::CreateImm(CE->getValue())); 638218893Sdim } 639218893Sdim 640218893Sdim void addMSRMaskOperands(MCInst &Inst, unsigned N) const { 641218893Sdim assert(N == 1 && "Invalid number of operands!"); 642218893Sdim Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask()))); 643218893Sdim } 644218893Sdim 645218893Sdim void addProcIFlagsOperands(MCInst &Inst, unsigned N) const { 646218893Sdim assert(N == 1 && "Invalid number of operands!"); 647218893Sdim Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags()))); 648218893Sdim } 649218893Sdim 650212904Sdim virtual void dump(raw_ostream &OS) const; 651212904Sdim 652218893Sdim static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) { 653218893Sdim ARMOperand *Op = new ARMOperand(CondCode); 654212904Sdim Op->CC.Val = CC; 655212904Sdim Op->StartLoc = S; 656212904Sdim Op->EndLoc = S; 657218893Sdim return Op; 658212904Sdim } 659212904Sdim 660218893Sdim static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) { 661218893Sdim ARMOperand *Op = new ARMOperand(CoprocNum); 662218893Sdim Op->Cop.Val = CopVal; 663218893Sdim Op->StartLoc = S; 664218893Sdim Op->EndLoc = S; 665218893Sdim return Op; 666218893Sdim } 667218893Sdim 668218893Sdim static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) { 669218893Sdim ARMOperand *Op = new ARMOperand(CoprocReg); 670218893Sdim Op->Cop.Val = CopVal; 671218893Sdim Op->StartLoc = S; 672218893Sdim Op->EndLoc = S; 673218893Sdim return Op; 674218893Sdim } 675218893Sdim 676218893Sdim static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) { 677218893Sdim ARMOperand *Op = new ARMOperand(CCOut); 678218893Sdim Op->Reg.RegNum = RegNum; 679218893Sdim Op->StartLoc = S; 680218893Sdim Op->EndLoc = S; 681218893Sdim return Op; 682218893Sdim } 683218893Sdim 684218893Sdim static ARMOperand *CreateToken(StringRef Str, SMLoc S) { 685218893Sdim ARMOperand *Op = new ARMOperand(Token); 686206124Srdivacky Op->Tok.Data = Str.data(); 687206124Srdivacky Op->Tok.Length = Str.size(); 688206124Srdivacky Op->StartLoc = S; 689206124Srdivacky Op->EndLoc = S; 690218893Sdim return Op; 691198090Srdivacky } 692198090Srdivacky 693218893Sdim static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) { 694218893Sdim ARMOperand *Op = new ARMOperand(Register); 695206124Srdivacky Op->Reg.RegNum = RegNum; 696206124Srdivacky Op->StartLoc = S; 697206124Srdivacky Op->EndLoc = E; 698218893Sdim return Op; 699198090Srdivacky } 700198090Srdivacky 701221345Sdim static ARMOperand *CreateShifter(ARM_AM::ShiftOpc ShTy, 702221345Sdim SMLoc S, SMLoc E) { 703221345Sdim ARMOperand *Op = new ARMOperand(Shifter); 704221345Sdim Op->Shift.ShiftTy = ShTy; 705221345Sdim Op->StartLoc = S; 706221345Sdim Op->EndLoc = E; 707221345Sdim return Op; 708221345Sdim } 709221345Sdim 710218893Sdim static ARMOperand * 711218893Sdim CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs, 712218893Sdim SMLoc StartLoc, SMLoc EndLoc) { 713218893Sdim KindTy Kind = RegisterList; 714218893Sdim 715218893Sdim if (ARM::DPRRegClass.contains(Regs.front().first)) 716218893Sdim Kind = DPRRegisterList; 717218893Sdim else if (ARM::SPRRegClass.contains(Regs.front().first)) 718218893Sdim Kind = SPRRegisterList; 719218893Sdim 720218893Sdim ARMOperand *Op = new ARMOperand(Kind); 721218893Sdim for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator 722218893Sdim I = Regs.begin(), E = Regs.end(); I != E; ++I) 723218893Sdim Op->Registers.push_back(I->first); 724218893Sdim array_pod_sort(Op->Registers.begin(), Op->Registers.end()); 725218893Sdim Op->StartLoc = StartLoc; 726218893Sdim Op->EndLoc = EndLoc; 727218893Sdim return Op; 728218893Sdim } 729218893Sdim 730218893Sdim static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) { 731218893Sdim ARMOperand *Op = new ARMOperand(Immediate); 732206124Srdivacky Op->Imm.Val = Val; 733206124Srdivacky Op->StartLoc = S; 734206124Srdivacky Op->EndLoc = E; 735218893Sdim return Op; 736198090Srdivacky } 737198090Srdivacky 738221345Sdim static ARMOperand *CreateMem(ARMII::AddrMode AddrMode, unsigned BaseRegNum, 739221345Sdim bool OffsetIsReg, const MCExpr *Offset, 740221345Sdim int OffsetRegNum, bool OffsetRegShifted, 741221345Sdim enum ARM_AM::ShiftOpc ShiftType, 742218893Sdim const MCExpr *ShiftAmount, bool Preindexed, 743218893Sdim bool Postindexed, bool Negative, bool Writeback, 744218893Sdim SMLoc S, SMLoc E) { 745218893Sdim assert((OffsetRegNum == -1 || OffsetIsReg) && 746218893Sdim "OffsetRegNum must imply OffsetIsReg!"); 747218893Sdim assert((!OffsetRegShifted || OffsetIsReg) && 748218893Sdim "OffsetRegShifted must imply OffsetIsReg!"); 749218893Sdim assert((Offset || OffsetIsReg) && 750218893Sdim "Offset must exists unless register offset is used!"); 751218893Sdim assert((!ShiftAmount || (OffsetIsReg && OffsetRegShifted)) && 752218893Sdim "Cannot have shift amount without shifted register offset!"); 753218893Sdim assert((!Offset || !OffsetIsReg) && 754218893Sdim "Cannot have expression offset and register offset!"); 755218893Sdim 756218893Sdim ARMOperand *Op = new ARMOperand(Memory); 757221345Sdim Op->Mem.AddrMode = AddrMode; 758206124Srdivacky Op->Mem.BaseRegNum = BaseRegNum; 759206124Srdivacky Op->Mem.OffsetIsReg = OffsetIsReg; 760218893Sdim if (OffsetIsReg) 761218893Sdim Op->Mem.Offset.RegNum = OffsetRegNum; 762218893Sdim else 763218893Sdim Op->Mem.Offset.Value = Offset; 764206124Srdivacky Op->Mem.OffsetRegShifted = OffsetRegShifted; 765206124Srdivacky Op->Mem.ShiftType = ShiftType; 766206124Srdivacky Op->Mem.ShiftAmount = ShiftAmount; 767206124Srdivacky Op->Mem.Preindexed = Preindexed; 768206124Srdivacky Op->Mem.Postindexed = Postindexed; 769206124Srdivacky Op->Mem.Negative = Negative; 770206124Srdivacky Op->Mem.Writeback = Writeback; 771218893Sdim 772206124Srdivacky Op->StartLoc = S; 773206124Srdivacky Op->EndLoc = E; 774218893Sdim return Op; 775198090Srdivacky } 776218893Sdim 777218893Sdim static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) { 778218893Sdim ARMOperand *Op = new ARMOperand(MemBarrierOpt); 779218893Sdim Op->MBOpt.Val = Opt; 780218893Sdim Op->StartLoc = S; 781218893Sdim Op->EndLoc = S; 782218893Sdim return Op; 783218893Sdim } 784218893Sdim 785218893Sdim static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) { 786218893Sdim ARMOperand *Op = new ARMOperand(ProcIFlags); 787218893Sdim Op->IFlags.Val = IFlags; 788218893Sdim Op->StartLoc = S; 789218893Sdim Op->EndLoc = S; 790218893Sdim return Op; 791218893Sdim } 792218893Sdim 793218893Sdim static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) { 794218893Sdim ARMOperand *Op = new ARMOperand(MSRMask); 795218893Sdim Op->MMask.Val = MMask; 796218893Sdim Op->StartLoc = S; 797218893Sdim Op->EndLoc = S; 798218893Sdim return Op; 799218893Sdim } 800198090Srdivacky}; 801198090Srdivacky 802198090Srdivacky} // end anonymous namespace. 803198090Srdivacky 804212904Sdimvoid ARMOperand::dump(raw_ostream &OS) const { 805212904Sdim switch (Kind) { 806212904Sdim case CondCode: 807218893Sdim OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">"; 808212904Sdim break; 809218893Sdim case CCOut: 810218893Sdim OS << "<ccout " << getReg() << ">"; 811218893Sdim break; 812218893Sdim case CoprocNum: 813218893Sdim OS << "<coprocessor number: " << getCoproc() << ">"; 814218893Sdim break; 815218893Sdim case CoprocReg: 816218893Sdim OS << "<coprocessor register: " << getCoproc() << ">"; 817218893Sdim break; 818218893Sdim case MSRMask: 819218893Sdim OS << "<mask: " << getMSRMask() << ">"; 820218893Sdim break; 821212904Sdim case Immediate: 822212904Sdim getImm()->print(OS); 823212904Sdim break; 824218893Sdim case MemBarrierOpt: 825218893Sdim OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">"; 826218893Sdim break; 827212904Sdim case Memory: 828218893Sdim OS << "<memory " 829221345Sdim << "am:" << ARMII::AddrModeToString(getMemAddrMode()) 830221345Sdim << " base:" << getMemBaseRegNum(); 831218893Sdim if (getMemOffsetIsReg()) { 832218893Sdim OS << " offset:<register " << getMemOffsetRegNum(); 833218893Sdim if (getMemOffsetRegShifted()) { 834218893Sdim OS << " offset-shift-type:" << getMemShiftType(); 835218893Sdim OS << " offset-shift-amount:" << *getMemShiftAmount(); 836218893Sdim } 837218893Sdim } else { 838218893Sdim OS << " offset:" << *getMemOffset(); 839218893Sdim } 840218893Sdim if (getMemOffsetIsReg()) 841218893Sdim OS << " (offset-is-reg)"; 842218893Sdim if (getMemPreindexed()) 843218893Sdim OS << " (pre-indexed)"; 844218893Sdim if (getMemPostindexed()) 845218893Sdim OS << " (post-indexed)"; 846218893Sdim if (getMemNegative()) 847218893Sdim OS << " (negative)"; 848218893Sdim if (getMemWriteback()) 849218893Sdim OS << " (writeback)"; 850218893Sdim OS << ">"; 851212904Sdim break; 852218893Sdim case ProcIFlags: { 853218893Sdim OS << "<ARM_PROC::"; 854218893Sdim unsigned IFlags = getProcIFlags(); 855218893Sdim for (int i=2; i >= 0; --i) 856218893Sdim if (IFlags & (1 << i)) 857218893Sdim OS << ARM_PROC::IFlagsToString(1 << i); 858218893Sdim OS << ">"; 859218893Sdim break; 860218893Sdim } 861212904Sdim case Register: 862212904Sdim OS << "<register " << getReg() << ">"; 863212904Sdim break; 864221345Sdim case Shifter: 865221345Sdim OS << "<shifter " << getShiftOpcStr(Shift.ShiftTy) << ">"; 866221345Sdim break; 867218893Sdim case RegisterList: 868218893Sdim case DPRRegisterList: 869218893Sdim case SPRRegisterList: { 870218893Sdim OS << "<register_list "; 871218893Sdim 872218893Sdim const SmallVectorImpl<unsigned> &RegList = getRegList(); 873218893Sdim for (SmallVectorImpl<unsigned>::const_iterator 874218893Sdim I = RegList.begin(), E = RegList.end(); I != E; ) { 875218893Sdim OS << *I; 876218893Sdim if (++I < E) OS << ", "; 877218893Sdim } 878218893Sdim 879218893Sdim OS << ">"; 880218893Sdim break; 881218893Sdim } 882212904Sdim case Token: 883212904Sdim OS << "'" << getToken() << "'"; 884212904Sdim break; 885212904Sdim } 886212904Sdim} 887212904Sdim 888212904Sdim/// @name Auto-generated Match Functions 889212904Sdim/// { 890212904Sdim 891212904Sdimstatic unsigned MatchRegisterName(StringRef Name); 892212904Sdim 893212904Sdim/// } 894212904Sdim 895218893Sdimbool ARMAsmParser::ParseRegister(unsigned &RegNo, 896218893Sdim SMLoc &StartLoc, SMLoc &EndLoc) { 897218893Sdim RegNo = TryParseRegister(); 898218893Sdim 899218893Sdim return (RegNo == (unsigned)-1); 900218893Sdim} 901218893Sdim 902198892Srdivacky/// Try to parse a register name. The token must be an Identifier when called, 903218893Sdim/// and if it is a register name the token is eaten and the register number is 904218893Sdim/// returned. Otherwise return -1. 905218893Sdim/// 906218893Sdimint ARMAsmParser::TryParseRegister() { 907202878Srdivacky const AsmToken &Tok = Parser.getTok(); 908198090Srdivacky assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); 909198090Srdivacky 910198090Srdivacky // FIXME: Validate register for the current architecture; we have to do 911198090Srdivacky // validation later, so maybe there is no need for this here. 912218893Sdim std::string upperCase = Tok.getString().str(); 913218893Sdim std::string lowerCase = LowercaseString(upperCase); 914218893Sdim unsigned RegNum = MatchRegisterName(lowerCase); 915218893Sdim if (!RegNum) { 916218893Sdim RegNum = StringSwitch<unsigned>(lowerCase) 917218893Sdim .Case("r13", ARM::SP) 918218893Sdim .Case("r14", ARM::LR) 919218893Sdim .Case("r15", ARM::PC) 920218893Sdim .Case("ip", ARM::R12) 921218893Sdim .Default(0); 922218893Sdim } 923218893Sdim if (!RegNum) return -1; 924198090Srdivacky 925202878Srdivacky Parser.Lex(); // Eat identifier token. 926218893Sdim return RegNum; 927218893Sdim} 928198090Srdivacky 929221345Sdim/// Try to parse a register name. The token must be an Identifier when called, 930221345Sdim/// and if it is a register name the token is eaten and the register number is 931221345Sdim/// returned. Otherwise return -1. 932221345Sdim/// 933221345Sdimbool ARMAsmParser::TryParseShiftRegister( 934221345Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 935221345Sdim SMLoc S = Parser.getTok().getLoc(); 936221345Sdim const AsmToken &Tok = Parser.getTok(); 937221345Sdim assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); 938221345Sdim 939221345Sdim std::string upperCase = Tok.getString().str(); 940221345Sdim std::string lowerCase = LowercaseString(upperCase); 941221345Sdim ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase) 942221345Sdim .Case("lsl", ARM_AM::lsl) 943221345Sdim .Case("lsr", ARM_AM::lsr) 944221345Sdim .Case("asr", ARM_AM::asr) 945221345Sdim .Case("ror", ARM_AM::ror) 946221345Sdim .Case("rrx", ARM_AM::rrx) 947221345Sdim .Default(ARM_AM::no_shift); 948221345Sdim 949221345Sdim if (ShiftTy == ARM_AM::no_shift) 950221345Sdim return true; 951221345Sdim 952221345Sdim Parser.Lex(); // Eat shift-type operand; 953221345Sdim int RegNum = TryParseRegister(); 954221345Sdim if (RegNum == -1) 955221345Sdim return Error(Parser.getTok().getLoc(), "register expected"); 956221345Sdim 957221345Sdim Operands.push_back(ARMOperand::CreateReg(RegNum,S, Parser.getTok().getLoc())); 958221345Sdim Operands.push_back(ARMOperand::CreateShifter(ShiftTy, 959221345Sdim S, Parser.getTok().getLoc())); 960221345Sdim 961221345Sdim return false; 962221345Sdim} 963221345Sdim 964221345Sdim 965218893Sdim/// Try to parse a register name. The token must be an Identifier when called. 966218893Sdim/// If it's a register, an AsmOperand is created. Another AsmOperand is created 967218893Sdim/// if there is a "writeback". 'true' if it's not a register. 968218893Sdim/// 969218893Sdim/// TODO this is likely to change to allow different register types and or to 970218893Sdim/// parse for a specific register type. 971218893Sdimbool ARMAsmParser:: 972218893SdimTryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 973218893Sdim SMLoc S = Parser.getTok().getLoc(); 974218893Sdim int RegNo = TryParseRegister(); 975218893Sdim if (RegNo == -1) 976218893Sdim return true; 977218893Sdim 978218893Sdim Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc())); 979218893Sdim 980218893Sdim const AsmToken &ExclaimTok = Parser.getTok(); 981218893Sdim if (ExclaimTok.is(AsmToken::Exclaim)) { 982218893Sdim Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(), 983218893Sdim ExclaimTok.getLoc())); 984218893Sdim Parser.Lex(); // Eat exclaim token 985218893Sdim } 986218893Sdim 987218893Sdim return false; 988218893Sdim} 989218893Sdim 990218893Sdim/// MatchCoprocessorOperandName - Try to parse an coprocessor related 991218893Sdim/// instruction with a symbolic operand name. Example: "p1", "p7", "c3", 992218893Sdim/// "c5", ... 993218893Sdimstatic int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) { 994218893Sdim // Use the same layout as the tablegen'erated register name matcher. Ugly, 995218893Sdim // but efficient. 996218893Sdim switch (Name.size()) { 997218893Sdim default: break; 998218893Sdim case 2: 999218893Sdim if (Name[0] != CoprocOp) 1000218893Sdim return -1; 1001218893Sdim switch (Name[1]) { 1002218893Sdim default: return -1; 1003218893Sdim case '0': return 0; 1004218893Sdim case '1': return 1; 1005218893Sdim case '2': return 2; 1006218893Sdim case '3': return 3; 1007218893Sdim case '4': return 4; 1008218893Sdim case '5': return 5; 1009218893Sdim case '6': return 6; 1010218893Sdim case '7': return 7; 1011218893Sdim case '8': return 8; 1012218893Sdim case '9': return 9; 1013198892Srdivacky } 1014218893Sdim break; 1015218893Sdim case 3: 1016218893Sdim if (Name[0] != CoprocOp || Name[1] != '1') 1017218893Sdim return -1; 1018218893Sdim switch (Name[2]) { 1019218893Sdim default: return -1; 1020218893Sdim case '0': return 10; 1021218893Sdim case '1': return 11; 1022218893Sdim case '2': return 12; 1023218893Sdim case '3': return 13; 1024218893Sdim case '4': return 14; 1025218893Sdim case '5': return 15; 1026218893Sdim } 1027218893Sdim break; 1028198090Srdivacky } 1029198090Srdivacky 1030218893Sdim return -1; 1031218893Sdim} 1032198090Srdivacky 1033218893Sdim/// tryParseCoprocNumOperand - Try to parse an coprocessor number operand. The 1034218893Sdim/// token must be an Identifier when called, and if it is a coprocessor 1035218893Sdim/// number, the token is eaten and the operand is added to the operand list. 1036218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 1037218893SdimtryParseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 1038218893Sdim SMLoc S = Parser.getTok().getLoc(); 1039218893Sdim const AsmToken &Tok = Parser.getTok(); 1040218893Sdim assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); 1041218893Sdim 1042218893Sdim int Num = MatchCoprocessorOperandName(Tok.getString(), 'p'); 1043218893Sdim if (Num == -1) 1044218893Sdim return MatchOperand_NoMatch; 1045218893Sdim 1046218893Sdim Parser.Lex(); // Eat identifier token. 1047218893Sdim Operands.push_back(ARMOperand::CreateCoprocNum(Num, S)); 1048218893Sdim return MatchOperand_Success; 1049198090Srdivacky} 1050198090Srdivacky 1051218893Sdim/// tryParseCoprocRegOperand - Try to parse an coprocessor register operand. The 1052218893Sdim/// token must be an Identifier when called, and if it is a coprocessor 1053218893Sdim/// number, the token is eaten and the operand is added to the operand list. 1054218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 1055218893SdimtryParseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 1056218893Sdim SMLoc S = Parser.getTok().getLoc(); 1057218893Sdim const AsmToken &Tok = Parser.getTok(); 1058218893Sdim assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); 1059198090Srdivacky 1060218893Sdim int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c'); 1061218893Sdim if (Reg == -1) 1062218893Sdim return MatchOperand_NoMatch; 1063218893Sdim 1064202878Srdivacky Parser.Lex(); // Eat identifier token. 1065218893Sdim Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S)); 1066218893Sdim return MatchOperand_Success; 1067218893Sdim} 1068198090Srdivacky 1069218893Sdim/// Parse a register list, return it if successful else return null. The first 1070218893Sdim/// token must be a '{' when called. 1071218893Sdimbool ARMAsmParser:: 1072218893SdimParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 1073218893Sdim assert(Parser.getTok().is(AsmToken::LCurly) && 1074218893Sdim "Token is not a Left Curly Brace"); 1075218893Sdim SMLoc S = Parser.getTok().getLoc(); 1076198090Srdivacky 1077218893Sdim // Read the rest of the registers in the list. 1078218893Sdim unsigned PrevRegNum = 0; 1079218893Sdim SmallVector<std::pair<unsigned, SMLoc>, 32> Registers; 1080218893Sdim 1081218893Sdim do { 1082218893Sdim bool IsRange = Parser.getTok().is(AsmToken::Minus); 1083218893Sdim Parser.Lex(); // Eat non-identifier token. 1084218893Sdim 1085202878Srdivacky const AsmToken &RegTok = Parser.getTok(); 1086198090Srdivacky SMLoc RegLoc = RegTok.getLoc(); 1087218893Sdim if (RegTok.isNot(AsmToken::Identifier)) { 1088218893Sdim Error(RegLoc, "register expected"); 1089218893Sdim return true; 1090218893Sdim } 1091198090Srdivacky 1092218893Sdim int RegNum = TryParseRegister(); 1093218893Sdim if (RegNum == -1) { 1094218893Sdim Error(RegLoc, "register expected"); 1095218893Sdim return true; 1096218893Sdim } 1097198090Srdivacky 1098218893Sdim if (IsRange) { 1099218893Sdim int Reg = PrevRegNum; 1100218893Sdim do { 1101218893Sdim ++Reg; 1102218893Sdim Registers.push_back(std::make_pair(Reg, RegLoc)); 1103218893Sdim } while (Reg != RegNum); 1104218893Sdim } else { 1105218893Sdim Registers.push_back(std::make_pair(RegNum, RegLoc)); 1106218893Sdim } 1107218893Sdim 1108218893Sdim PrevRegNum = RegNum; 1109218893Sdim } while (Parser.getTok().is(AsmToken::Comma) || 1110218893Sdim Parser.getTok().is(AsmToken::Minus)); 1111218893Sdim 1112218893Sdim // Process the right curly brace of the list. 1113218893Sdim const AsmToken &RCurlyTok = Parser.getTok(); 1114218893Sdim if (RCurlyTok.isNot(AsmToken::RCurly)) { 1115218893Sdim Error(RCurlyTok.getLoc(), "'}' expected"); 1116218893Sdim return true; 1117198090Srdivacky } 1118198090Srdivacky 1119218893Sdim SMLoc E = RCurlyTok.getLoc(); 1120218893Sdim Parser.Lex(); // Eat right curly brace token. 1121218893Sdim 1122218893Sdim // Verify the register list. 1123218893Sdim SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator 1124218893Sdim RI = Registers.begin(), RE = Registers.end(); 1125218893Sdim 1126218893Sdim unsigned HighRegNum = getARMRegisterNumbering(RI->first); 1127218893Sdim bool EmittedWarning = false; 1128218893Sdim 1129218893Sdim DenseMap<unsigned, bool> RegMap; 1130218893Sdim RegMap[HighRegNum] = true; 1131218893Sdim 1132218893Sdim for (++RI; RI != RE; ++RI) { 1133218893Sdim const std::pair<unsigned, SMLoc> &RegInfo = *RI; 1134218893Sdim unsigned Reg = getARMRegisterNumbering(RegInfo.first); 1135218893Sdim 1136218893Sdim if (RegMap[Reg]) { 1137218893Sdim Error(RegInfo.second, "register duplicated in register list"); 1138218893Sdim return true; 1139218893Sdim } 1140218893Sdim 1141218893Sdim if (!EmittedWarning && Reg < HighRegNum) 1142218893Sdim Warning(RegInfo.second, 1143218893Sdim "register not in ascending order in register list"); 1144218893Sdim 1145218893Sdim RegMap[Reg] = true; 1146218893Sdim HighRegNum = std::max(Reg, HighRegNum); 1147218893Sdim } 1148218893Sdim 1149218893Sdim Operands.push_back(ARMOperand::CreateRegList(Registers, S, E)); 1150198090Srdivacky return false; 1151198090Srdivacky} 1152198090Srdivacky 1153218893Sdim/// tryParseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options. 1154218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 1155218893SdimtryParseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 1156218893Sdim SMLoc S = Parser.getTok().getLoc(); 1157218893Sdim const AsmToken &Tok = Parser.getTok(); 1158218893Sdim assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); 1159218893Sdim StringRef OptStr = Tok.getString(); 1160218893Sdim 1161218893Sdim unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size())) 1162218893Sdim .Case("sy", ARM_MB::SY) 1163218893Sdim .Case("st", ARM_MB::ST) 1164218893Sdim .Case("ish", ARM_MB::ISH) 1165218893Sdim .Case("ishst", ARM_MB::ISHST) 1166218893Sdim .Case("nsh", ARM_MB::NSH) 1167218893Sdim .Case("nshst", ARM_MB::NSHST) 1168218893Sdim .Case("osh", ARM_MB::OSH) 1169218893Sdim .Case("oshst", ARM_MB::OSHST) 1170218893Sdim .Default(~0U); 1171218893Sdim 1172218893Sdim if (Opt == ~0U) 1173218893Sdim return MatchOperand_NoMatch; 1174218893Sdim 1175218893Sdim Parser.Lex(); // Eat identifier token. 1176218893Sdim Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S)); 1177218893Sdim return MatchOperand_Success; 1178218893Sdim} 1179218893Sdim 1180218893Sdim/// tryParseProcIFlagsOperand - Try to parse iflags from CPS instruction. 1181218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 1182218893SdimtryParseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 1183218893Sdim SMLoc S = Parser.getTok().getLoc(); 1184218893Sdim const AsmToken &Tok = Parser.getTok(); 1185218893Sdim assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); 1186218893Sdim StringRef IFlagsStr = Tok.getString(); 1187218893Sdim 1188218893Sdim unsigned IFlags = 0; 1189218893Sdim for (int i = 0, e = IFlagsStr.size(); i != e; ++i) { 1190218893Sdim unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1)) 1191218893Sdim .Case("a", ARM_PROC::A) 1192218893Sdim .Case("i", ARM_PROC::I) 1193218893Sdim .Case("f", ARM_PROC::F) 1194218893Sdim .Default(~0U); 1195218893Sdim 1196218893Sdim // If some specific iflag is already set, it means that some letter is 1197218893Sdim // present more than once, this is not acceptable. 1198218893Sdim if (Flag == ~0U || (IFlags & Flag)) 1199218893Sdim return MatchOperand_NoMatch; 1200218893Sdim 1201218893Sdim IFlags |= Flag; 1202218893Sdim } 1203218893Sdim 1204218893Sdim Parser.Lex(); // Eat identifier token. 1205218893Sdim Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S)); 1206218893Sdim return MatchOperand_Success; 1207218893Sdim} 1208218893Sdim 1209218893Sdim/// tryParseMSRMaskOperand - Try to parse mask flags from MSR instruction. 1210218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 1211218893SdimtryParseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 1212218893Sdim SMLoc S = Parser.getTok().getLoc(); 1213218893Sdim const AsmToken &Tok = Parser.getTok(); 1214218893Sdim assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); 1215218893Sdim StringRef Mask = Tok.getString(); 1216218893Sdim 1217218893Sdim // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf" 1218218893Sdim size_t Start = 0, Next = Mask.find('_'); 1219218893Sdim StringRef Flags = ""; 1220218893Sdim StringRef SpecReg = Mask.slice(Start, Next); 1221218893Sdim if (Next != StringRef::npos) 1222218893Sdim Flags = Mask.slice(Next+1, Mask.size()); 1223218893Sdim 1224218893Sdim // FlagsVal contains the complete mask: 1225218893Sdim // 3-0: Mask 1226218893Sdim // 4: Special Reg (cpsr, apsr => 0; spsr => 1) 1227218893Sdim unsigned FlagsVal = 0; 1228218893Sdim 1229218893Sdim if (SpecReg == "apsr") { 1230218893Sdim FlagsVal = StringSwitch<unsigned>(Flags) 1231218893Sdim .Case("nzcvq", 0x8) // same as CPSR_c 1232218893Sdim .Case("g", 0x4) // same as CPSR_s 1233218893Sdim .Case("nzcvqg", 0xc) // same as CPSR_fs 1234218893Sdim .Default(~0U); 1235218893Sdim 1236218893Sdim if (FlagsVal == ~0U) { 1237218893Sdim if (!Flags.empty()) 1238218893Sdim return MatchOperand_NoMatch; 1239218893Sdim else 1240218893Sdim FlagsVal = 0; // No flag 1241218893Sdim } 1242218893Sdim } else if (SpecReg == "cpsr" || SpecReg == "spsr") { 1243218893Sdim for (int i = 0, e = Flags.size(); i != e; ++i) { 1244218893Sdim unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1)) 1245218893Sdim .Case("c", 1) 1246218893Sdim .Case("x", 2) 1247218893Sdim .Case("s", 4) 1248218893Sdim .Case("f", 8) 1249218893Sdim .Default(~0U); 1250218893Sdim 1251218893Sdim // If some specific flag is already set, it means that some letter is 1252218893Sdim // present more than once, this is not acceptable. 1253218893Sdim if (FlagsVal == ~0U || (FlagsVal & Flag)) 1254218893Sdim return MatchOperand_NoMatch; 1255218893Sdim FlagsVal |= Flag; 1256218893Sdim } 1257218893Sdim } else // No match for special register. 1258218893Sdim return MatchOperand_NoMatch; 1259218893Sdim 1260218893Sdim // Special register without flags are equivalent to "fc" flags. 1261218893Sdim if (!FlagsVal) 1262218893Sdim FlagsVal = 0x9; 1263218893Sdim 1264218893Sdim // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1) 1265218893Sdim if (SpecReg == "spsr") 1266218893Sdim FlagsVal |= 16; 1267218893Sdim 1268218893Sdim Parser.Lex(); // Eat identifier token. 1269218893Sdim Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S)); 1270218893Sdim return MatchOperand_Success; 1271218893Sdim} 1272218893Sdim 1273221345Sdim/// tryParseMemMode2Operand - Try to parse memory addressing mode 2 operand. 1274221345SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 1275221345SdimtryParseMemMode2Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 1276221345Sdim assert(Parser.getTok().is(AsmToken::LBrac) && "Token is not a \"[\""); 1277221345Sdim 1278221345Sdim if (ParseMemory(Operands, ARMII::AddrMode2)) 1279221345Sdim return MatchOperand_NoMatch; 1280221345Sdim 1281221345Sdim return MatchOperand_Success; 1282221345Sdim} 1283221345Sdim 1284221345Sdim/// tryParseMemMode3Operand - Try to parse memory addressing mode 3 operand. 1285221345SdimARMAsmParser::OperandMatchResultTy ARMAsmParser:: 1286221345SdimtryParseMemMode3Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 1287221345Sdim assert(Parser.getTok().is(AsmToken::LBrac) && "Token is not a \"[\""); 1288221345Sdim 1289221345Sdim if (ParseMemory(Operands, ARMII::AddrMode3)) 1290221345Sdim return MatchOperand_NoMatch; 1291221345Sdim 1292221345Sdim return MatchOperand_Success; 1293221345Sdim} 1294221345Sdim 1295221345Sdim/// CvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst. 1296221345Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands 1297221345Sdim/// when they refer multiple MIOperands inside a single one. 1298221345Sdimbool ARMAsmParser:: 1299221345SdimCvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode, 1300221345Sdim const SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 1301221345Sdim ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); 1302221345Sdim 1303221345Sdim // Create a writeback register dummy placeholder. 1304221345Sdim Inst.addOperand(MCOperand::CreateImm(0)); 1305221345Sdim 1306221345Sdim ((ARMOperand*)Operands[3])->addMemMode2Operands(Inst, 3); 1307221345Sdim ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); 1308221345Sdim return true; 1309221345Sdim} 1310221345Sdim 1311221345Sdim/// CvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst. 1312221345Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands 1313221345Sdim/// when they refer multiple MIOperands inside a single one. 1314221345Sdimbool ARMAsmParser:: 1315221345SdimCvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode, 1316221345Sdim const SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 1317221345Sdim // Create a writeback register dummy placeholder. 1318221345Sdim Inst.addOperand(MCOperand::CreateImm(0)); 1319221345Sdim ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); 1320221345Sdim ((ARMOperand*)Operands[3])->addMemMode2Operands(Inst, 3); 1321221345Sdim ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); 1322221345Sdim return true; 1323221345Sdim} 1324221345Sdim 1325221345Sdim/// CvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst. 1326221345Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands 1327221345Sdim/// when they refer multiple MIOperands inside a single one. 1328221345Sdimbool ARMAsmParser:: 1329221345SdimCvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode, 1330221345Sdim const SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 1331221345Sdim ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); 1332221345Sdim 1333221345Sdim // Create a writeback register dummy placeholder. 1334221345Sdim Inst.addOperand(MCOperand::CreateImm(0)); 1335221345Sdim 1336221345Sdim ((ARMOperand*)Operands[3])->addMemMode3Operands(Inst, 3); 1337221345Sdim ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); 1338221345Sdim return true; 1339221345Sdim} 1340221345Sdim 1341221345Sdim/// CvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst. 1342221345Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands 1343221345Sdim/// when they refer multiple MIOperands inside a single one. 1344221345Sdimbool ARMAsmParser:: 1345221345SdimCvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode, 1346221345Sdim const SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 1347221345Sdim // Create a writeback register dummy placeholder. 1348221345Sdim Inst.addOperand(MCOperand::CreateImm(0)); 1349221345Sdim ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); 1350221345Sdim ((ARMOperand*)Operands[3])->addMemMode3Operands(Inst, 3); 1351221345Sdim ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); 1352221345Sdim return true; 1353221345Sdim} 1354221345Sdim 1355218893Sdim/// Parse an ARM memory expression, return false if successful else return true 1356198892Srdivacky/// or an error. The first token must be a '[' when called. 1357218893Sdim/// 1358198892Srdivacky/// TODO Only preindexing and postindexing addressing are started, unindexed 1359198892Srdivacky/// with option, etc are still to do. 1360218893Sdimbool ARMAsmParser:: 1361221345SdimParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands, 1362221345Sdim ARMII::AddrMode AddrMode = ARMII::AddrModeNone) { 1363206124Srdivacky SMLoc S, E; 1364202878Srdivacky assert(Parser.getTok().is(AsmToken::LBrac) && 1365218893Sdim "Token is not a Left Bracket"); 1366206124Srdivacky S = Parser.getTok().getLoc(); 1367202878Srdivacky Parser.Lex(); // Eat left bracket token. 1368198090Srdivacky 1369202878Srdivacky const AsmToken &BaseRegTok = Parser.getTok(); 1370218893Sdim if (BaseRegTok.isNot(AsmToken::Identifier)) { 1371218893Sdim Error(BaseRegTok.getLoc(), "register expected"); 1372218893Sdim return true; 1373218893Sdim } 1374218893Sdim int BaseRegNum = TryParseRegister(); 1375218893Sdim if (BaseRegNum == -1) { 1376218893Sdim Error(BaseRegTok.getLoc(), "register expected"); 1377218893Sdim return true; 1378218893Sdim } 1379198090Srdivacky 1380218893Sdim // The next token must either be a comma or a closing bracket. 1381218893Sdim const AsmToken &Tok = Parser.getTok(); 1382218893Sdim if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac)) 1383218893Sdim return true; 1384218893Sdim 1385198090Srdivacky bool Preindexed = false; 1386198090Srdivacky bool Postindexed = false; 1387198090Srdivacky bool OffsetIsReg = false; 1388198090Srdivacky bool Negative = false; 1389198090Srdivacky bool Writeback = false; 1390218893Sdim ARMOperand *WBOp = 0; 1391218893Sdim int OffsetRegNum = -1; 1392218893Sdim bool OffsetRegShifted = false; 1393221345Sdim enum ARM_AM::ShiftOpc ShiftType = ARM_AM::lsl; 1394218893Sdim const MCExpr *ShiftAmount = 0; 1395218893Sdim const MCExpr *Offset = 0; 1396198090Srdivacky 1397198892Srdivacky // First look for preindexed address forms, that is after the "[Rn" we now 1398198892Srdivacky // have to see if the next token is a comma. 1399198090Srdivacky if (Tok.is(AsmToken::Comma)) { 1400198090Srdivacky Preindexed = true; 1401202878Srdivacky Parser.Lex(); // Eat comma token. 1402218893Sdim 1403218893Sdim if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount, 1404218893Sdim Offset, OffsetIsReg, OffsetRegNum, E)) 1405198892Srdivacky return true; 1406202878Srdivacky const AsmToken &RBracTok = Parser.getTok(); 1407218893Sdim if (RBracTok.isNot(AsmToken::RBrac)) { 1408218893Sdim Error(RBracTok.getLoc(), "']' expected"); 1409218893Sdim return true; 1410218893Sdim } 1411206124Srdivacky E = RBracTok.getLoc(); 1412202878Srdivacky Parser.Lex(); // Eat right bracket token. 1413198090Srdivacky 1414202878Srdivacky const AsmToken &ExclaimTok = Parser.getTok(); 1415198090Srdivacky if (ExclaimTok.is(AsmToken::Exclaim)) { 1416221345Sdim // None of addrmode3 instruction uses "!" 1417221345Sdim if (AddrMode == ARMII::AddrMode3) 1418221345Sdim return true; 1419221345Sdim 1420218893Sdim WBOp = ARMOperand::CreateToken(ExclaimTok.getString(), 1421218893Sdim ExclaimTok.getLoc()); 1422198090Srdivacky Writeback = true; 1423202878Srdivacky Parser.Lex(); // Eat exclaim token 1424221345Sdim } else { // In addressing mode 2, pre-indexed mode always end with "!" 1425221345Sdim if (AddrMode == ARMII::AddrMode2) 1426221345Sdim Preindexed = false; 1427198090Srdivacky } 1428218893Sdim } else { 1429218893Sdim // The "[Rn" we have so far was not followed by a comma. 1430218893Sdim 1431218893Sdim // If there's anything other than the right brace, this is a post indexing 1432218893Sdim // addressing form. 1433206124Srdivacky E = Tok.getLoc(); 1434202878Srdivacky Parser.Lex(); // Eat right bracket token. 1435198090Srdivacky 1436218893Sdim const AsmToken &NextTok = Parser.getTok(); 1437198090Srdivacky 1438198396Srdivacky if (NextTok.isNot(AsmToken::EndOfStatement)) { 1439218893Sdim Postindexed = true; 1440218893Sdim Writeback = true; 1441218893Sdim 1442218893Sdim if (NextTok.isNot(AsmToken::Comma)) { 1443218893Sdim Error(NextTok.getLoc(), "',' expected"); 1444218893Sdim return true; 1445218893Sdim } 1446218893Sdim 1447202878Srdivacky Parser.Lex(); // Eat comma token. 1448218893Sdim 1449218893Sdim if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, 1450218893Sdim ShiftAmount, Offset, OffsetIsReg, OffsetRegNum, 1451218893Sdim E)) 1452198892Srdivacky return true; 1453198090Srdivacky } 1454218893Sdim } 1455198090Srdivacky 1456218893Sdim // Force Offset to exist if used. 1457218893Sdim if (!OffsetIsReg) { 1458218893Sdim if (!Offset) 1459218893Sdim Offset = MCConstantExpr::Create(0, getContext()); 1460221345Sdim } else { 1461221345Sdim if (AddrMode == ARMII::AddrMode3 && OffsetRegShifted) { 1462221345Sdim Error(E, "shift amount not supported"); 1463221345Sdim return true; 1464221345Sdim } 1465198090Srdivacky } 1466198090Srdivacky 1467221345Sdim Operands.push_back(ARMOperand::CreateMem(AddrMode, BaseRegNum, OffsetIsReg, 1468221345Sdim Offset, OffsetRegNum, OffsetRegShifted, 1469221345Sdim ShiftType, ShiftAmount, Preindexed, 1470221345Sdim Postindexed, Negative, Writeback, S, E)); 1471218893Sdim if (WBOp) 1472218893Sdim Operands.push_back(WBOp); 1473218893Sdim 1474218893Sdim return false; 1475198090Srdivacky} 1476198090Srdivacky 1477198892Srdivacky/// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn]," 1478198892Srdivacky/// we will parse the following (were +/- means that a plus or minus is 1479198892Srdivacky/// optional): 1480198892Srdivacky/// +/-Rm 1481198892Srdivacky/// +/-Rm, shift 1482198892Srdivacky/// #offset 1483198892Srdivacky/// we return false on success or an error otherwise. 1484198892Srdivackybool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative, 1485206124Srdivacky bool &OffsetRegShifted, 1486221345Sdim enum ARM_AM::ShiftOpc &ShiftType, 1487198892Srdivacky const MCExpr *&ShiftAmount, 1488198892Srdivacky const MCExpr *&Offset, 1489198892Srdivacky bool &OffsetIsReg, 1490206124Srdivacky int &OffsetRegNum, 1491206124Srdivacky SMLoc &E) { 1492198892Srdivacky Negative = false; 1493198892Srdivacky OffsetRegShifted = false; 1494198892Srdivacky OffsetIsReg = false; 1495198892Srdivacky OffsetRegNum = -1; 1496202878Srdivacky const AsmToken &NextTok = Parser.getTok(); 1497206124Srdivacky E = NextTok.getLoc(); 1498198892Srdivacky if (NextTok.is(AsmToken::Plus)) 1499202878Srdivacky Parser.Lex(); // Eat plus token. 1500198892Srdivacky else if (NextTok.is(AsmToken::Minus)) { 1501198892Srdivacky Negative = true; 1502202878Srdivacky Parser.Lex(); // Eat minus token 1503198892Srdivacky } 1504198892Srdivacky // See if there is a register following the "[Rn," or "[Rn]," we have so far. 1505202878Srdivacky const AsmToken &OffsetRegTok = Parser.getTok(); 1506198892Srdivacky if (OffsetRegTok.is(AsmToken::Identifier)) { 1507218893Sdim SMLoc CurLoc = OffsetRegTok.getLoc(); 1508218893Sdim OffsetRegNum = TryParseRegister(); 1509218893Sdim if (OffsetRegNum != -1) { 1510218893Sdim OffsetIsReg = true; 1511218893Sdim E = CurLoc; 1512206124Srdivacky } 1513198892Srdivacky } 1514218893Sdim 1515218893Sdim // If we parsed a register as the offset then there can be a shift after that. 1516198892Srdivacky if (OffsetRegNum != -1) { 1517198892Srdivacky // Look for a comma then a shift 1518202878Srdivacky const AsmToken &Tok = Parser.getTok(); 1519198892Srdivacky if (Tok.is(AsmToken::Comma)) { 1520202878Srdivacky Parser.Lex(); // Eat comma token. 1521198892Srdivacky 1522202878Srdivacky const AsmToken &Tok = Parser.getTok(); 1523206124Srdivacky if (ParseShift(ShiftType, ShiftAmount, E)) 1524210299Sed return Error(Tok.getLoc(), "shift expected"); 1525198892Srdivacky OffsetRegShifted = true; 1526198892Srdivacky } 1527198892Srdivacky } 1528198892Srdivacky else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm" 1529198892Srdivacky // Look for #offset following the "[Rn," or "[Rn]," 1530202878Srdivacky const AsmToken &HashTok = Parser.getTok(); 1531198892Srdivacky if (HashTok.isNot(AsmToken::Hash)) 1532198892Srdivacky return Error(HashTok.getLoc(), "'#' expected"); 1533218893Sdim 1534202878Srdivacky Parser.Lex(); // Eat hash token. 1535198892Srdivacky 1536198892Srdivacky if (getParser().ParseExpression(Offset)) 1537198892Srdivacky return true; 1538206124Srdivacky E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 1539198892Srdivacky } 1540198892Srdivacky return false; 1541198892Srdivacky} 1542198892Srdivacky 1543198090Srdivacky/// ParseShift as one of these two: 1544198090Srdivacky/// ( lsl | lsr | asr | ror ) , # shift_amount 1545198090Srdivacky/// rrx 1546198090Srdivacky/// and returns true if it parses a shift otherwise it returns false. 1547221345Sdimbool ARMAsmParser::ParseShift(ARM_AM::ShiftOpc &St, 1548221345Sdim const MCExpr *&ShiftAmount, SMLoc &E) { 1549202878Srdivacky const AsmToken &Tok = Parser.getTok(); 1550198090Srdivacky if (Tok.isNot(AsmToken::Identifier)) 1551198090Srdivacky return true; 1552210299Sed StringRef ShiftName = Tok.getString(); 1553198090Srdivacky if (ShiftName == "lsl" || ShiftName == "LSL") 1554221345Sdim St = ARM_AM::lsl; 1555198090Srdivacky else if (ShiftName == "lsr" || ShiftName == "LSR") 1556221345Sdim St = ARM_AM::lsr; 1557198090Srdivacky else if (ShiftName == "asr" || ShiftName == "ASR") 1558221345Sdim St = ARM_AM::asr; 1559198090Srdivacky else if (ShiftName == "ror" || ShiftName == "ROR") 1560221345Sdim St = ARM_AM::ror; 1561198090Srdivacky else if (ShiftName == "rrx" || ShiftName == "RRX") 1562221345Sdim St = ARM_AM::rrx; 1563198090Srdivacky else 1564198090Srdivacky return true; 1565202878Srdivacky Parser.Lex(); // Eat shift type token. 1566198090Srdivacky 1567198892Srdivacky // Rrx stands alone. 1568221345Sdim if (St == ARM_AM::rrx) 1569198892Srdivacky return false; 1570198090Srdivacky 1571198892Srdivacky // Otherwise, there must be a '#' and a shift amount. 1572202878Srdivacky const AsmToken &HashTok = Parser.getTok(); 1573198892Srdivacky if (HashTok.isNot(AsmToken::Hash)) 1574198892Srdivacky return Error(HashTok.getLoc(), "'#' expected"); 1575202878Srdivacky Parser.Lex(); // Eat hash token. 1576198090Srdivacky 1577198892Srdivacky if (getParser().ParseExpression(ShiftAmount)) 1578198892Srdivacky return true; 1579198892Srdivacky 1580198090Srdivacky return false; 1581198090Srdivacky} 1582198090Srdivacky 1583198892Srdivacky/// Parse a arm instruction operand. For now this parses the operand regardless 1584198892Srdivacky/// of the mnemonic. 1585218893Sdimbool ARMAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands, 1586218893Sdim StringRef Mnemonic) { 1587206124Srdivacky SMLoc S, E; 1588218893Sdim 1589218893Sdim // Check if the current operand has a custom associated parser, if so, try to 1590218893Sdim // custom parse the operand, or fallback to the general approach. 1591218893Sdim OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); 1592218893Sdim if (ResTy == MatchOperand_Success) 1593218893Sdim return false; 1594218893Sdim // If there wasn't a custom match, try the generic matcher below. Otherwise, 1595218893Sdim // there was a match, but an error occurred, in which case, just return that 1596218893Sdim // the operand parsing failed. 1597218893Sdim if (ResTy == MatchOperand_ParseFail) 1598218893Sdim return true; 1599218893Sdim 1600198090Srdivacky switch (getLexer().getKind()) { 1601218893Sdim default: 1602218893Sdim Error(Parser.getTok().getLoc(), "unexpected token in operand"); 1603218893Sdim return true; 1604198090Srdivacky case AsmToken::Identifier: 1605218893Sdim if (!TryParseRegisterWithWriteBack(Operands)) 1606198090Srdivacky return false; 1607221345Sdim if (!TryParseShiftRegister(Operands)) 1608221345Sdim return false; 1609218893Sdim 1610221345Sdim 1611218893Sdim // Fall though for the Identifier case that is not a register or a 1612218893Sdim // special name. 1613218893Sdim case AsmToken::Integer: // things like 1f and 2b as a branch targets 1614218893Sdim case AsmToken::Dot: { // . as a branch target 1615198396Srdivacky // This was not a register so parse other operands that start with an 1616198396Srdivacky // identifier (like labels) as expressions and create them as immediates. 1617198396Srdivacky const MCExpr *IdVal; 1618206124Srdivacky S = Parser.getTok().getLoc(); 1619198396Srdivacky if (getParser().ParseExpression(IdVal)) 1620198396Srdivacky return true; 1621206124Srdivacky E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 1622218893Sdim Operands.push_back(ARMOperand::CreateImm(IdVal, S, E)); 1623198396Srdivacky return false; 1624218893Sdim } 1625198090Srdivacky case AsmToken::LBrac: 1626218893Sdim return ParseMemory(Operands); 1627198090Srdivacky case AsmToken::LCurly: 1628218893Sdim return ParseRegisterList(Operands); 1629198090Srdivacky case AsmToken::Hash: 1630198090Srdivacky // #42 -> immediate. 1631198090Srdivacky // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate 1632206124Srdivacky S = Parser.getTok().getLoc(); 1633202878Srdivacky Parser.Lex(); 1634198396Srdivacky const MCExpr *ImmVal; 1635198396Srdivacky if (getParser().ParseExpression(ImmVal)) 1636198090Srdivacky return true; 1637206124Srdivacky E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 1638218893Sdim Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E)); 1639198090Srdivacky return false; 1640218893Sdim case AsmToken::Colon: { 1641218893Sdim // ":lower16:" and ":upper16:" expression prefixes 1642218893Sdim // FIXME: Check it's an expression prefix, 1643218893Sdim // e.g. (FOO - :lower16:BAR) isn't legal. 1644218893Sdim ARMMCExpr::VariantKind RefKind; 1645218893Sdim if (ParsePrefix(RefKind)) 1646218893Sdim return true; 1647218893Sdim 1648218893Sdim const MCExpr *SubExprVal; 1649218893Sdim if (getParser().ParseExpression(SubExprVal)) 1650218893Sdim return true; 1651218893Sdim 1652218893Sdim const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal, 1653218893Sdim getContext()); 1654218893Sdim E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 1655218893Sdim Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E)); 1656218893Sdim return false; 1657198090Srdivacky } 1658218893Sdim } 1659198090Srdivacky} 1660198090Srdivacky 1661218893Sdim// ParsePrefix - Parse ARM 16-bit relocations expression prefix, i.e. 1662218893Sdim// :lower16: and :upper16:. 1663218893Sdimbool ARMAsmParser::ParsePrefix(ARMMCExpr::VariantKind &RefKind) { 1664218893Sdim RefKind = ARMMCExpr::VK_ARM_None; 1665212904Sdim 1666218893Sdim // :lower16: and :upper16: modifiers 1667218893Sdim assert(getLexer().is(AsmToken::Colon) && "expected a :"); 1668218893Sdim Parser.Lex(); // Eat ':' 1669212904Sdim 1670218893Sdim if (getLexer().isNot(AsmToken::Identifier)) { 1671218893Sdim Error(Parser.getTok().getLoc(), "expected prefix identifier in operand"); 1672218893Sdim return true; 1673218893Sdim } 1674218893Sdim 1675218893Sdim StringRef IDVal = Parser.getTok().getIdentifier(); 1676218893Sdim if (IDVal == "lower16") { 1677218893Sdim RefKind = ARMMCExpr::VK_ARM_LO16; 1678218893Sdim } else if (IDVal == "upper16") { 1679218893Sdim RefKind = ARMMCExpr::VK_ARM_HI16; 1680218893Sdim } else { 1681218893Sdim Error(Parser.getTok().getLoc(), "unexpected prefix in operand"); 1682218893Sdim return true; 1683218893Sdim } 1684218893Sdim Parser.Lex(); 1685218893Sdim 1686218893Sdim if (getLexer().isNot(AsmToken::Colon)) { 1687218893Sdim Error(Parser.getTok().getLoc(), "unexpected token after prefix"); 1688218893Sdim return true; 1689218893Sdim } 1690218893Sdim Parser.Lex(); // Eat the last ':' 1691218893Sdim return false; 1692218893Sdim} 1693218893Sdim 1694218893Sdimconst MCExpr * 1695218893SdimARMAsmParser::ApplyPrefixToExpr(const MCExpr *E, 1696218893Sdim MCSymbolRefExpr::VariantKind Variant) { 1697218893Sdim // Recurse over the given expression, rebuilding it to apply the given variant 1698218893Sdim // to the leftmost symbol. 1699218893Sdim if (Variant == MCSymbolRefExpr::VK_None) 1700218893Sdim return E; 1701218893Sdim 1702218893Sdim switch (E->getKind()) { 1703218893Sdim case MCExpr::Target: 1704218893Sdim llvm_unreachable("Can't handle target expr yet"); 1705218893Sdim case MCExpr::Constant: 1706218893Sdim llvm_unreachable("Can't handle lower16/upper16 of constant yet"); 1707218893Sdim 1708218893Sdim case MCExpr::SymbolRef: { 1709218893Sdim const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E); 1710218893Sdim 1711218893Sdim if (SRE->getKind() != MCSymbolRefExpr::VK_None) 1712218893Sdim return 0; 1713218893Sdim 1714218893Sdim return MCSymbolRefExpr::Create(&SRE->getSymbol(), Variant, getContext()); 1715218893Sdim } 1716218893Sdim 1717218893Sdim case MCExpr::Unary: 1718218893Sdim llvm_unreachable("Can't handle unary expressions yet"); 1719218893Sdim 1720218893Sdim case MCExpr::Binary: { 1721218893Sdim const MCBinaryExpr *BE = cast<MCBinaryExpr>(E); 1722218893Sdim const MCExpr *LHS = ApplyPrefixToExpr(BE->getLHS(), Variant); 1723218893Sdim const MCExpr *RHS = BE->getRHS(); 1724218893Sdim if (!LHS) 1725218893Sdim return 0; 1726218893Sdim 1727218893Sdim return MCBinaryExpr::Create(BE->getOpcode(), LHS, RHS, getContext()); 1728218893Sdim } 1729218893Sdim } 1730218893Sdim 1731218893Sdim assert(0 && "Invalid expression kind!"); 1732218893Sdim return 0; 1733218893Sdim} 1734218893Sdim 1735218893Sdim/// \brief Given a mnemonic, split out possible predication code and carry 1736218893Sdim/// setting letters to form a canonical mnemonic and flags. 1737218893Sdim// 1738218893Sdim// FIXME: Would be nice to autogen this. 1739218893Sdimstatic StringRef SplitMnemonic(StringRef Mnemonic, 1740218893Sdim unsigned &PredicationCode, 1741218893Sdim bool &CarrySetting, 1742218893Sdim unsigned &ProcessorIMod) { 1743218893Sdim PredicationCode = ARMCC::AL; 1744218893Sdim CarrySetting = false; 1745218893Sdim ProcessorIMod = 0; 1746218893Sdim 1747218893Sdim // Ignore some mnemonics we know aren't predicated forms. 1748212904Sdim // 1749218893Sdim // FIXME: Would be nice to autogen this. 1750218893Sdim if (Mnemonic == "teq" || Mnemonic == "vceq" || 1751218893Sdim Mnemonic == "movs" || 1752218893Sdim Mnemonic == "svc" || 1753218893Sdim (Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" || 1754218893Sdim Mnemonic == "vmls" || Mnemonic == "vnmls") || 1755218893Sdim Mnemonic == "vacge" || Mnemonic == "vcge" || 1756218893Sdim Mnemonic == "vclt" || 1757218893Sdim Mnemonic == "vacgt" || Mnemonic == "vcgt" || 1758218893Sdim Mnemonic == "vcle" || 1759218893Sdim (Mnemonic == "smlal" || Mnemonic == "umaal" || Mnemonic == "umlal" || 1760218893Sdim Mnemonic == "vabal" || Mnemonic == "vmlal" || Mnemonic == "vpadal" || 1761218893Sdim Mnemonic == "vqdmlal")) 1762218893Sdim return Mnemonic; 1763218893Sdim 1764218893Sdim // First, split out any predication code. 1765218893Sdim unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2)) 1766212904Sdim .Case("eq", ARMCC::EQ) 1767212904Sdim .Case("ne", ARMCC::NE) 1768212904Sdim .Case("hs", ARMCC::HS) 1769212904Sdim .Case("lo", ARMCC::LO) 1770212904Sdim .Case("mi", ARMCC::MI) 1771212904Sdim .Case("pl", ARMCC::PL) 1772212904Sdim .Case("vs", ARMCC::VS) 1773212904Sdim .Case("vc", ARMCC::VC) 1774212904Sdim .Case("hi", ARMCC::HI) 1775212904Sdim .Case("ls", ARMCC::LS) 1776212904Sdim .Case("ge", ARMCC::GE) 1777212904Sdim .Case("lt", ARMCC::LT) 1778212904Sdim .Case("gt", ARMCC::GT) 1779212904Sdim .Case("le", ARMCC::LE) 1780212904Sdim .Case("al", ARMCC::AL) 1781212904Sdim .Default(~0U); 1782212904Sdim if (CC != ~0U) { 1783218893Sdim Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2); 1784218893Sdim PredicationCode = CC; 1785218893Sdim } 1786212904Sdim 1787218893Sdim // Next, determine if we have a carry setting bit. We explicitly ignore all 1788218893Sdim // the instructions we know end in 's'. 1789218893Sdim if (Mnemonic.endswith("s") && 1790218893Sdim !(Mnemonic == "asrs" || Mnemonic == "cps" || Mnemonic == "mls" || 1791218893Sdim Mnemonic == "movs" || Mnemonic == "mrs" || Mnemonic == "smmls" || 1792218893Sdim Mnemonic == "vabs" || Mnemonic == "vcls" || Mnemonic == "vmls" || 1793218893Sdim Mnemonic == "vmrs" || Mnemonic == "vnmls" || Mnemonic == "vqabs" || 1794218893Sdim Mnemonic == "vrecps" || Mnemonic == "vrsqrts")) { 1795218893Sdim Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1); 1796218893Sdim CarrySetting = true; 1797218893Sdim } 1798198090Srdivacky 1799218893Sdim // The "cps" instruction can have a interrupt mode operand which is glued into 1800218893Sdim // the mnemonic. Check if this is the case, split it and parse the imod op 1801218893Sdim if (Mnemonic.startswith("cps")) { 1802218893Sdim // Split out any imod code. 1803218893Sdim unsigned IMod = 1804218893Sdim StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2)) 1805218893Sdim .Case("ie", ARM_PROC::IE) 1806218893Sdim .Case("id", ARM_PROC::ID) 1807218893Sdim .Default(~0U); 1808218893Sdim if (IMod != ~0U) { 1809218893Sdim Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2); 1810218893Sdim ProcessorIMod = IMod; 1811218893Sdim } 1812218893Sdim } 1813212904Sdim 1814218893Sdim return Mnemonic; 1815218893Sdim} 1816218893Sdim 1817218893Sdim/// \brief Given a canonical mnemonic, determine if the instruction ever allows 1818218893Sdim/// inclusion of carry set or predication code operands. 1819218893Sdim// 1820218893Sdim// FIXME: It would be nice to autogen this. 1821218893Sdimvoid ARMAsmParser:: 1822218893SdimGetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, 1823218893Sdim bool &CanAcceptPredicationCode) { 1824218893Sdim bool isThumb = TM.getSubtarget<ARMSubtarget>().isThumb(); 1825218893Sdim 1826218893Sdim if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" || 1827218893Sdim Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" || 1828218893Sdim Mnemonic == "smull" || Mnemonic == "add" || Mnemonic == "adc" || 1829218893Sdim Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" || 1830218893Sdim Mnemonic == "umlal" || Mnemonic == "orr" || Mnemonic == "mov" || 1831218893Sdim Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" || 1832218893Sdim Mnemonic == "sbc" || Mnemonic == "mla" || Mnemonic == "umull" || 1833218893Sdim Mnemonic == "eor" || Mnemonic == "smlal" || Mnemonic == "mvn") { 1834218893Sdim CanAcceptCarrySet = true; 1835218893Sdim } else { 1836218893Sdim CanAcceptCarrySet = false; 1837218893Sdim } 1838218893Sdim 1839218893Sdim if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" || 1840218893Sdim Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" || 1841218893Sdim Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" || 1842218893Sdim Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" || 1843218893Sdim Mnemonic == "dsb" || Mnemonic == "movs" || Mnemonic == "isb" || 1844218893Sdim Mnemonic == "clrex" || Mnemonic.startswith("cps")) { 1845218893Sdim CanAcceptPredicationCode = false; 1846218893Sdim } else { 1847218893Sdim CanAcceptPredicationCode = true; 1848218893Sdim } 1849218893Sdim 1850218893Sdim if (isThumb) 1851218893Sdim if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" || 1852218893Sdim Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp") 1853218893Sdim CanAcceptPredicationCode = false; 1854218893Sdim} 1855218893Sdim 1856218893Sdim/// Parse an arm instruction mnemonic followed by its operands. 1857218893Sdimbool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc, 1858218893Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 1859218893Sdim // Create the leading tokens for the mnemonic, split by '.' characters. 1860218893Sdim size_t Start = 0, Next = Name.find('.'); 1861218893Sdim StringRef Head = Name.slice(Start, Next); 1862218893Sdim 1863218893Sdim // Split out the predication code and carry setting flag from the mnemonic. 1864218893Sdim unsigned PredicationCode; 1865218893Sdim unsigned ProcessorIMod; 1866218893Sdim bool CarrySetting; 1867218893Sdim Head = SplitMnemonic(Head, PredicationCode, CarrySetting, 1868218893Sdim ProcessorIMod); 1869218893Sdim 1870218893Sdim Operands.push_back(ARMOperand::CreateToken(Head, NameLoc)); 1871218893Sdim 1872218893Sdim // Next, add the CCOut and ConditionCode operands, if needed. 1873218893Sdim // 1874218893Sdim // For mnemonics which can ever incorporate a carry setting bit or predication 1875218893Sdim // code, our matching model involves us always generating CCOut and 1876218893Sdim // ConditionCode operands to match the mnemonic "as written" and then we let 1877218893Sdim // the matcher deal with finding the right instruction or generating an 1878218893Sdim // appropriate error. 1879218893Sdim bool CanAcceptCarrySet, CanAcceptPredicationCode; 1880218893Sdim GetMnemonicAcceptInfo(Head, CanAcceptCarrySet, CanAcceptPredicationCode); 1881218893Sdim 1882218893Sdim // Add the carry setting operand, if necessary. 1883218893Sdim // 1884218893Sdim // FIXME: It would be awesome if we could somehow invent a location such that 1885218893Sdim // match errors on this operand would print a nice diagnostic about how the 1886218893Sdim // 's' character in the mnemonic resulted in a CCOut operand. 1887218893Sdim if (CanAcceptCarrySet) { 1888218893Sdim Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0, 1889218893Sdim NameLoc)); 1890218893Sdim } else { 1891218893Sdim // This mnemonic can't ever accept a carry set, but the user wrote one (or 1892218893Sdim // misspelled another mnemonic). 1893218893Sdim 1894218893Sdim // FIXME: Issue a nice error. 1895218893Sdim } 1896218893Sdim 1897218893Sdim // Add the predication code operand, if necessary. 1898218893Sdim if (CanAcceptPredicationCode) { 1899218893Sdim Operands.push_back(ARMOperand::CreateCondCode( 1900218893Sdim ARMCC::CondCodes(PredicationCode), NameLoc)); 1901218893Sdim } else { 1902218893Sdim // This mnemonic can't ever accept a predication code, but the user wrote 1903218893Sdim // one (or misspelled another mnemonic). 1904218893Sdim 1905218893Sdim // FIXME: Issue a nice error. 1906218893Sdim } 1907218893Sdim 1908218893Sdim // Add the processor imod operand, if necessary. 1909218893Sdim if (ProcessorIMod) { 1910218893Sdim Operands.push_back(ARMOperand::CreateImm( 1911218893Sdim MCConstantExpr::Create(ProcessorIMod, getContext()), 1912218893Sdim NameLoc, NameLoc)); 1913218893Sdim } else { 1914218893Sdim // This mnemonic can't ever accept a imod, but the user wrote 1915218893Sdim // one (or misspelled another mnemonic). 1916218893Sdim 1917218893Sdim // FIXME: Issue a nice error. 1918218893Sdim } 1919218893Sdim 1920212904Sdim // Add the remaining tokens in the mnemonic. 1921212904Sdim while (Next != StringRef::npos) { 1922212904Sdim Start = Next; 1923212904Sdim Next = Name.find('.', Start + 1); 1924218893Sdim StringRef ExtraToken = Name.slice(Start, Next); 1925212904Sdim 1926218893Sdim Operands.push_back(ARMOperand::CreateToken(ExtraToken, NameLoc)); 1927212904Sdim } 1928212904Sdim 1929212904Sdim // Read the remaining operands. 1930198090Srdivacky if (getLexer().isNot(AsmToken::EndOfStatement)) { 1931198090Srdivacky // Read the first operand. 1932218893Sdim if (ParseOperand(Operands, Head)) { 1933218893Sdim Parser.EatToEndOfStatement(); 1934218893Sdim return true; 1935218893Sdim } 1936198090Srdivacky 1937198090Srdivacky while (getLexer().is(AsmToken::Comma)) { 1938202878Srdivacky Parser.Lex(); // Eat the comma. 1939198090Srdivacky 1940198090Srdivacky // Parse and remember the operand. 1941218893Sdim if (ParseOperand(Operands, Head)) { 1942218893Sdim Parser.EatToEndOfStatement(); 1943218893Sdim return true; 1944218893Sdim } 1945198090Srdivacky } 1946198090Srdivacky } 1947218893Sdim 1948218893Sdim if (getLexer().isNot(AsmToken::EndOfStatement)) { 1949218893Sdim Parser.EatToEndOfStatement(); 1950218893Sdim return TokError("unexpected token in argument list"); 1951218893Sdim } 1952218893Sdim 1953218893Sdim Parser.Lex(); // Consume the EndOfStatement 1954202375Srdivacky return false; 1955198090Srdivacky} 1956198090Srdivacky 1957218893Sdimbool ARMAsmParser:: 1958218893SdimMatchAndEmitInstruction(SMLoc IDLoc, 1959218893Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands, 1960218893Sdim MCStreamer &Out) { 1961218893Sdim MCInst Inst; 1962218893Sdim unsigned ErrorInfo; 1963218893Sdim MatchResultTy MatchResult, MatchResult2; 1964218893Sdim MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo); 1965218893Sdim if (MatchResult != Match_Success) { 1966218893Sdim // If we get a Match_InvalidOperand it might be some arithmetic instruction 1967218893Sdim // that does not update the condition codes. So try adding a CCOut operand 1968218893Sdim // with a value of reg0. 1969218893Sdim if (MatchResult == Match_InvalidOperand) { 1970218893Sdim Operands.insert(Operands.begin() + 1, 1971218893Sdim ARMOperand::CreateCCOut(0, 1972218893Sdim ((ARMOperand*)Operands[0])->getStartLoc())); 1973218893Sdim MatchResult2 = MatchInstructionImpl(Operands, Inst, ErrorInfo); 1974218893Sdim if (MatchResult2 == Match_Success) 1975218893Sdim MatchResult = Match_Success; 1976218893Sdim else { 1977218893Sdim ARMOperand *CCOut = ((ARMOperand*)Operands[1]); 1978218893Sdim Operands.erase(Operands.begin() + 1); 1979218893Sdim delete CCOut; 1980218893Sdim } 1981218893Sdim } 1982218893Sdim // If we get a Match_MnemonicFail it might be some arithmetic instruction 1983218893Sdim // that updates the condition codes if it ends in 's'. So see if the 1984218893Sdim // mnemonic ends in 's' and if so try removing the 's' and adding a CCOut 1985218893Sdim // operand with a value of CPSR. 1986218893Sdim else if(MatchResult == Match_MnemonicFail) { 1987218893Sdim // Get the instruction mnemonic, which is the first token. 1988218893Sdim StringRef Mnemonic = ((ARMOperand*)Operands[0])->getToken(); 1989218893Sdim if (Mnemonic.substr(Mnemonic.size()-1) == "s") { 1990218893Sdim // removed the 's' from the mnemonic for matching. 1991218893Sdim StringRef MnemonicNoS = Mnemonic.slice(0, Mnemonic.size() - 1); 1992218893Sdim SMLoc NameLoc = ((ARMOperand*)Operands[0])->getStartLoc(); 1993218893Sdim ARMOperand *OldMnemonic = ((ARMOperand*)Operands[0]); 1994218893Sdim Operands.erase(Operands.begin()); 1995218893Sdim delete OldMnemonic; 1996218893Sdim Operands.insert(Operands.begin(), 1997218893Sdim ARMOperand::CreateToken(MnemonicNoS, NameLoc)); 1998218893Sdim Operands.insert(Operands.begin() + 1, 1999218893Sdim ARMOperand::CreateCCOut(ARM::CPSR, NameLoc)); 2000218893Sdim MatchResult2 = MatchInstructionImpl(Operands, Inst, ErrorInfo); 2001218893Sdim if (MatchResult2 == Match_Success) 2002218893Sdim MatchResult = Match_Success; 2003218893Sdim else { 2004218893Sdim ARMOperand *OldMnemonic = ((ARMOperand*)Operands[0]); 2005218893Sdim Operands.erase(Operands.begin()); 2006218893Sdim delete OldMnemonic; 2007218893Sdim Operands.insert(Operands.begin(), 2008218893Sdim ARMOperand::CreateToken(Mnemonic, NameLoc)); 2009218893Sdim ARMOperand *CCOut = ((ARMOperand*)Operands[1]); 2010218893Sdim Operands.erase(Operands.begin() + 1); 2011218893Sdim delete CCOut; 2012218893Sdim } 2013218893Sdim } 2014218893Sdim } 2015218893Sdim } 2016218893Sdim switch (MatchResult) { 2017218893Sdim case Match_Success: 2018218893Sdim Out.EmitInstruction(Inst); 2019218893Sdim return false; 2020218893Sdim case Match_MissingFeature: 2021218893Sdim Error(IDLoc, "instruction requires a CPU feature not currently enabled"); 2022218893Sdim return true; 2023218893Sdim case Match_InvalidOperand: { 2024218893Sdim SMLoc ErrorLoc = IDLoc; 2025218893Sdim if (ErrorInfo != ~0U) { 2026218893Sdim if (ErrorInfo >= Operands.size()) 2027218893Sdim return Error(IDLoc, "too few operands for instruction"); 2028218893Sdim 2029218893Sdim ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc(); 2030218893Sdim if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc; 2031218893Sdim } 2032218893Sdim 2033218893Sdim return Error(ErrorLoc, "invalid operand for instruction"); 2034218893Sdim } 2035218893Sdim case Match_MnemonicFail: 2036218893Sdim return Error(IDLoc, "unrecognized instruction mnemonic"); 2037218893Sdim case Match_ConversionFail: 2038218893Sdim return Error(IDLoc, "unable to convert operands to instruction"); 2039218893Sdim } 2040218893Sdim 2041218893Sdim llvm_unreachable("Implement any new match types added!"); 2042218893Sdim return true; 2043218893Sdim} 2044218893Sdim 2045198396Srdivacky/// ParseDirective parses the arm specific directives 2046198090Srdivackybool ARMAsmParser::ParseDirective(AsmToken DirectiveID) { 2047198090Srdivacky StringRef IDVal = DirectiveID.getIdentifier(); 2048198090Srdivacky if (IDVal == ".word") 2049198090Srdivacky return ParseDirectiveWord(4, DirectiveID.getLoc()); 2050198396Srdivacky else if (IDVal == ".thumb") 2051198396Srdivacky return ParseDirectiveThumb(DirectiveID.getLoc()); 2052198396Srdivacky else if (IDVal == ".thumb_func") 2053198396Srdivacky return ParseDirectiveThumbFunc(DirectiveID.getLoc()); 2054198396Srdivacky else if (IDVal == ".code") 2055198396Srdivacky return ParseDirectiveCode(DirectiveID.getLoc()); 2056198396Srdivacky else if (IDVal == ".syntax") 2057198396Srdivacky return ParseDirectiveSyntax(DirectiveID.getLoc()); 2058198090Srdivacky return true; 2059198090Srdivacky} 2060198090Srdivacky 2061198090Srdivacky/// ParseDirectiveWord 2062198090Srdivacky/// ::= .word [ expression (, expression)* ] 2063198090Srdivackybool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { 2064198090Srdivacky if (getLexer().isNot(AsmToken::EndOfStatement)) { 2065198090Srdivacky for (;;) { 2066198090Srdivacky const MCExpr *Value; 2067198090Srdivacky if (getParser().ParseExpression(Value)) 2068198090Srdivacky return true; 2069198090Srdivacky 2070202878Srdivacky getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/); 2071198090Srdivacky 2072198090Srdivacky if (getLexer().is(AsmToken::EndOfStatement)) 2073198090Srdivacky break; 2074218893Sdim 2075198090Srdivacky // FIXME: Improve diagnostic. 2076198090Srdivacky if (getLexer().isNot(AsmToken::Comma)) 2077198090Srdivacky return Error(L, "unexpected token in directive"); 2078202878Srdivacky Parser.Lex(); 2079198090Srdivacky } 2080198090Srdivacky } 2081198090Srdivacky 2082202878Srdivacky Parser.Lex(); 2083198090Srdivacky return false; 2084198090Srdivacky} 2085198090Srdivacky 2086198396Srdivacky/// ParseDirectiveThumb 2087198396Srdivacky/// ::= .thumb 2088198396Srdivackybool ARMAsmParser::ParseDirectiveThumb(SMLoc L) { 2089198396Srdivacky if (getLexer().isNot(AsmToken::EndOfStatement)) 2090198396Srdivacky return Error(L, "unexpected token in directive"); 2091202878Srdivacky Parser.Lex(); 2092198396Srdivacky 2093198396Srdivacky // TODO: set thumb mode 2094198396Srdivacky // TODO: tell the MC streamer the mode 2095198396Srdivacky // getParser().getStreamer().Emit???(); 2096198396Srdivacky return false; 2097198396Srdivacky} 2098198396Srdivacky 2099198396Srdivacky/// ParseDirectiveThumbFunc 2100198396Srdivacky/// ::= .thumbfunc symbol_name 2101198396Srdivackybool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) { 2102202878Srdivacky const AsmToken &Tok = Parser.getTok(); 2103198396Srdivacky if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String)) 2104218893Sdim return Error(L, "unexpected token in .thumb_func directive"); 2105218893Sdim StringRef Name = Tok.getString(); 2106202878Srdivacky Parser.Lex(); // Consume the identifier token. 2107198396Srdivacky if (getLexer().isNot(AsmToken::EndOfStatement)) 2108198396Srdivacky return Error(L, "unexpected token in directive"); 2109202878Srdivacky Parser.Lex(); 2110198396Srdivacky 2111218893Sdim // Mark symbol as a thumb symbol. 2112218893Sdim MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name); 2113218893Sdim getParser().getStreamer().EmitThumbFunc(Func); 2114198396Srdivacky return false; 2115198396Srdivacky} 2116198396Srdivacky 2117198396Srdivacky/// ParseDirectiveSyntax 2118198396Srdivacky/// ::= .syntax unified | divided 2119198396Srdivackybool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) { 2120202878Srdivacky const AsmToken &Tok = Parser.getTok(); 2121198396Srdivacky if (Tok.isNot(AsmToken::Identifier)) 2122198396Srdivacky return Error(L, "unexpected token in .syntax directive"); 2123210299Sed StringRef Mode = Tok.getString(); 2124210299Sed if (Mode == "unified" || Mode == "UNIFIED") 2125202878Srdivacky Parser.Lex(); 2126210299Sed else if (Mode == "divided" || Mode == "DIVIDED") 2127218893Sdim return Error(L, "'.syntax divided' arm asssembly not supported"); 2128198396Srdivacky else 2129198396Srdivacky return Error(L, "unrecognized syntax mode in .syntax directive"); 2130198396Srdivacky 2131198396Srdivacky if (getLexer().isNot(AsmToken::EndOfStatement)) 2132202878Srdivacky return Error(Parser.getTok().getLoc(), "unexpected token in directive"); 2133202878Srdivacky Parser.Lex(); 2134198396Srdivacky 2135198396Srdivacky // TODO tell the MC streamer the mode 2136198396Srdivacky // getParser().getStreamer().Emit???(); 2137198396Srdivacky return false; 2138198396Srdivacky} 2139198396Srdivacky 2140198396Srdivacky/// ParseDirectiveCode 2141198396Srdivacky/// ::= .code 16 | 32 2142198396Srdivackybool ARMAsmParser::ParseDirectiveCode(SMLoc L) { 2143202878Srdivacky const AsmToken &Tok = Parser.getTok(); 2144198396Srdivacky if (Tok.isNot(AsmToken::Integer)) 2145198396Srdivacky return Error(L, "unexpected token in .code directive"); 2146202878Srdivacky int64_t Val = Parser.getTok().getIntVal(); 2147210299Sed if (Val == 16) 2148202878Srdivacky Parser.Lex(); 2149210299Sed else if (Val == 32) 2150202878Srdivacky Parser.Lex(); 2151198396Srdivacky else 2152198396Srdivacky return Error(L, "invalid operand to .code directive"); 2153198396Srdivacky 2154198396Srdivacky if (getLexer().isNot(AsmToken::EndOfStatement)) 2155202878Srdivacky return Error(Parser.getTok().getLoc(), "unexpected token in directive"); 2156202878Srdivacky Parser.Lex(); 2157198396Srdivacky 2158218893Sdim // FIXME: We need to be able switch subtargets at this point so that 2159218893Sdim // MatchInstructionImpl() will work when it gets the AvailableFeatures which 2160218893Sdim // includes Feature_IsThumb or not to match the right instructions. This is 2161218893Sdim // blocked on the FIXME in llvm-mc.cpp when creating the TargetMachine. 2162218893Sdim if (Val == 16){ 2163218893Sdim assert(TM.getSubtarget<ARMSubtarget>().isThumb() && 2164218893Sdim "switching between arm/thumb not yet suppported via .code 16)"); 2165218893Sdim getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16); 2166218893Sdim } 2167218893Sdim else{ 2168218893Sdim assert(!TM.getSubtarget<ARMSubtarget>().isThumb() && 2169218893Sdim "switching between thumb/arm not yet suppported via .code 32)"); 2170218893Sdim getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32); 2171218893Sdim } 2172218893Sdim 2173198396Srdivacky return false; 2174198396Srdivacky} 2175198396Srdivacky 2176207618Srdivackyextern "C" void LLVMInitializeARMAsmLexer(); 2177207618Srdivacky 2178198892Srdivacky/// Force static initialization. 2179198090Srdivackyextern "C" void LLVMInitializeARMAsmParser() { 2180198090Srdivacky RegisterAsmParser<ARMAsmParser> X(TheARMTarget); 2181198090Srdivacky RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget); 2182207618Srdivacky LLVMInitializeARMAsmLexer(); 2183198090Srdivacky} 2184212904Sdim 2185218893Sdim#define GET_REGISTER_MATCHER 2186218893Sdim#define GET_MATCHER_IMPLEMENTATION 2187212904Sdim#include "ARMGenAsmMatcher.inc" 2188