1 //===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 #include "ARMAddressingModes.h"
12 #include "ARMSubtarget.h"
13 #include "llvm/MC/MCParser/MCAsmLexer.h"
14 #include "llvm/MC/MCParser/MCAsmParser.h"
15 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
16 #include "llvm/MC/MCContext.h"
17 #include "llvm/MC/MCStreamer.h"
18 #include "llvm/MC/MCExpr.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/Target/TargetRegistry.h"
21 #include "llvm/Target/TargetAsmParser.h"
22 #include "llvm/Support/SourceMgr.h"
23 #include "llvm/Support/raw_ostream.h"
24 #include "llvm/ADT/SmallVector.h"
25 #include "llvm/ADT/StringSwitch.h"
26 #include "llvm/ADT/Twine.h"
29 // The shift types for register controlled shifts in arm memory addressing
42 class ARMAsmParser : public TargetAsmParser {
46 MCAsmParser &getParser() const { return Parser; }
47 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
49 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
50 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
52 int TryParseRegister();
53 ARMOperand *TryParseRegisterWithWriteBack();
54 ARMOperand *ParseRegisterList();
55 ARMOperand *ParseMemory();
56 ARMOperand *ParseOperand();
58 bool ParseMemoryOffsetReg(bool &Negative,
59 bool &OffsetRegShifted,
60 enum ShiftType &ShiftType,
61 const MCExpr *&ShiftAmount,
62 const MCExpr *&Offset,
66 bool ParseShift(enum ShiftType &St, const MCExpr *&ShiftAmount, SMLoc &E);
67 bool ParseDirectiveWord(unsigned Size, SMLoc L);
68 bool ParseDirectiveThumb(SMLoc L);
69 bool ParseDirectiveThumbFunc(SMLoc L);
70 bool ParseDirectiveCode(SMLoc L);
71 bool ParseDirectiveSyntax(SMLoc L);
73 bool MatchAndEmitInstruction(SMLoc IDLoc,
74 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
77 /// @name Auto-generated Match Functions
80 #define GET_ASSEMBLER_HEADER
81 #include "ARMGenAsmMatcher.inc"
86 ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
87 : TargetAsmParser(T), Parser(_Parser), TM(_TM) {
88 // Initialize the set of available features.
89 setAvailableFeatures(ComputeAvailableFeatures(
90 &TM.getSubtarget<ARMSubtarget>()));
93 virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
94 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
95 virtual bool ParseDirective(AsmToken DirectiveID);
97 } // end anonymous namespace
101 /// ARMOperand - Instances of this class represent a parsed ARM machine
103 class ARMOperand : public MCParsedAsmOperand {
115 SMLoc StartLoc, EndLoc;
116 SmallVector<unsigned, 8> Registers;
120 ARMCC::CondCodes Val;
137 // This is for all forms of ARM address expressions
140 unsigned OffsetRegNum; // used when OffsetIsReg is true
141 const MCExpr *Offset; // used when OffsetIsReg is false
142 const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
143 enum ShiftType ShiftType; // used when OffsetRegShifted is true
144 unsigned OffsetRegShifted : 1; // only used when OffsetIsReg is true
145 unsigned Preindexed : 1;
146 unsigned Postindexed : 1;
147 unsigned OffsetIsReg : 1;
148 unsigned Negative : 1; // only used when OffsetIsReg is true
149 unsigned Writeback : 1;
153 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
155 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
157 StartLoc = o.StartLoc;
170 case DPRRegisterList:
171 case SPRRegisterList:
172 Registers = o.Registers;
183 /// getStartLoc - Get the location of the first token of this operand.
184 SMLoc getStartLoc() const { return StartLoc; }
185 /// getEndLoc - Get the location of the last token of this operand.
186 SMLoc getEndLoc() const { return EndLoc; }
188 ARMCC::CondCodes getCondCode() const {
189 assert(Kind == CondCode && "Invalid access!");
193 StringRef getToken() const {
194 assert(Kind == Token && "Invalid access!");
195 return StringRef(Tok.Data, Tok.Length);
198 unsigned getReg() const {
199 assert(Kind == Register && "Invalid access!");
203 const SmallVectorImpl<unsigned> &getRegList() const {
204 assert((Kind == RegisterList || Kind == DPRRegisterList ||
205 Kind == SPRRegisterList) && "Invalid access!");
209 const MCExpr *getImm() const {
210 assert(Kind == Immediate && "Invalid access!");
214 bool isCondCode() const { return Kind == CondCode; }
215 bool isImm() const { return Kind == Immediate; }
216 bool isReg() const { return Kind == Register; }
217 bool isRegList() const { return Kind == RegisterList; }
218 bool isDPRRegList() const { return Kind == DPRRegisterList; }
219 bool isSPRRegList() const { return Kind == SPRRegisterList; }
220 bool isToken() const { return Kind == Token; }
221 bool isMemory() const { return Kind == Memory; }
222 bool isMemMode5() const {
223 if (!isMemory() || Mem.OffsetIsReg || Mem.OffsetRegShifted ||
224 Mem.Writeback || Mem.Negative)
226 // If there is an offset expression, make sure it's valid.
229 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset);
232 // The offset must be a multiple of 4 in the range 0-1020.
233 int64_t Value = CE->getValue();
234 return ((Value & 0x3) == 0 && Value <= 1020 && Value >= -1020);
237 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
238 // Add as immediates when possible. Null MCExpr = 0.
240 Inst.addOperand(MCOperand::CreateImm(0));
241 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
242 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
244 Inst.addOperand(MCOperand::CreateExpr(Expr));
247 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
248 assert(N == 2 && "Invalid number of operands!");
249 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
250 // FIXME: What belongs here?
251 Inst.addOperand(MCOperand::CreateReg(0));
254 void addRegOperands(MCInst &Inst, unsigned N) const {
255 assert(N == 1 && "Invalid number of operands!");
256 Inst.addOperand(MCOperand::CreateReg(getReg()));
259 void addRegListOperands(MCInst &Inst, unsigned N) const {
260 assert(N == 1 && "Invalid number of operands!");
261 const SmallVectorImpl<unsigned> &RegList = getRegList();
262 for (SmallVectorImpl<unsigned>::const_iterator
263 I = RegList.begin(), E = RegList.end(); I != E; ++I)
264 Inst.addOperand(MCOperand::CreateReg(*I));
267 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
268 addRegListOperands(Inst, N);
271 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
272 addRegListOperands(Inst, N);
275 void addImmOperands(MCInst &Inst, unsigned N) const {
276 assert(N == 1 && "Invalid number of operands!");
277 addExpr(Inst, getImm());
280 void addMemMode5Operands(MCInst &Inst, unsigned N) const {
281 assert(N == 2 && isMemMode5() && "Invalid number of operands!");
283 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
284 assert(!Mem.OffsetIsReg && "Invalid mode 5 operand");
286 // FIXME: #-0 is encoded differently than #0. Does the parser preserve
289 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset);
290 assert(CE && "Non-constant mode 5 offset operand!");
292 // The MCInst offset operand doesn't include the low two bits (like
293 // the instruction encoding).
294 int64_t Offset = CE->getValue() / 4;
296 Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::add,
299 Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::sub,
302 Inst.addOperand(MCOperand::CreateImm(0));
306 virtual void dump(raw_ostream &OS) const;
308 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
309 ARMOperand *Op = new ARMOperand(CondCode);
316 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
317 ARMOperand *Op = new ARMOperand(Token);
318 Op->Tok.Data = Str.data();
319 Op->Tok.Length = Str.size();
325 static ARMOperand *CreateReg(unsigned RegNum, bool Writeback, SMLoc S,
327 ARMOperand *Op = new ARMOperand(Register);
328 Op->Reg.RegNum = RegNum;
329 Op->Reg.Writeback = Writeback;
336 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
337 SMLoc StartLoc, SMLoc EndLoc) {
338 KindTy Kind = RegisterList;
340 if (ARM::DPRRegClass.contains(Regs.front().first))
341 Kind = DPRRegisterList;
342 else if (ARM::SPRRegClass.contains(Regs.front().first))
343 Kind = SPRRegisterList;
345 ARMOperand *Op = new ARMOperand(Kind);
346 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
347 I = Regs.begin(), E = Regs.end(); I != E; ++I)
348 Op->Registers.push_back(I->first);
349 std::sort(Op->Registers.begin(), Op->Registers.end());
350 Op->StartLoc = StartLoc;
355 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
356 ARMOperand *Op = new ARMOperand(Immediate);
363 static ARMOperand *CreateMem(unsigned BaseRegNum, bool OffsetIsReg,
364 const MCExpr *Offset, unsigned OffsetRegNum,
365 bool OffsetRegShifted, enum ShiftType ShiftType,
366 const MCExpr *ShiftAmount, bool Preindexed,
367 bool Postindexed, bool Negative, bool Writeback,
369 ARMOperand *Op = new ARMOperand(Memory);
370 Op->Mem.BaseRegNum = BaseRegNum;
371 Op->Mem.OffsetIsReg = OffsetIsReg;
372 Op->Mem.Offset = Offset;
373 Op->Mem.OffsetRegNum = OffsetRegNum;
374 Op->Mem.OffsetRegShifted = OffsetRegShifted;
375 Op->Mem.ShiftType = ShiftType;
376 Op->Mem.ShiftAmount = ShiftAmount;
377 Op->Mem.Preindexed = Preindexed;
378 Op->Mem.Postindexed = Postindexed;
379 Op->Mem.Negative = Negative;
380 Op->Mem.Writeback = Writeback;
388 } // end anonymous namespace.
390 void ARMOperand::dump(raw_ostream &OS) const {
393 OS << ARMCondCodeToString(getCondCode());
399 OS << "<memory" << (!Mem.Writeback ? ">" : "!>");
402 OS << "<register " << getReg() << (!Reg.Writeback ? ">" : "!>");
405 case DPRRegisterList:
406 case SPRRegisterList: {
407 OS << "<register_list ";
409 const SmallVectorImpl<unsigned> &RegList = getRegList();
410 for (SmallVectorImpl<unsigned>::const_iterator
411 I = RegList.begin(), E = RegList.end(); I != E; ) {
413 if (++I < E) OS << ", ";
420 OS << "'" << getToken() << "'";
425 /// @name Auto-generated Match Functions
428 static unsigned MatchRegisterName(StringRef Name);
432 /// Try to parse a register name. The token must be an Identifier when called,
433 /// and if it is a register name the token is eaten and the register number is
434 /// returned. Otherwise return -1.
436 int ARMAsmParser::TryParseRegister() {
437 const AsmToken &Tok = Parser.getTok();
438 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
440 // FIXME: Validate register for the current architecture; we have to do
441 // validation later, so maybe there is no need for this here.
442 unsigned RegNum = MatchRegisterName(Tok.getString());
445 Parser.Lex(); // Eat identifier token.
450 /// Try to parse a register name. The token must be an Identifier when called,
451 /// and if it is a register name the token is eaten and the register number is
452 /// returned. Otherwise return -1.
454 /// TODO this is likely to change to allow different register types and or to
455 /// parse for a specific register type.
456 ARMOperand *ARMAsmParser::TryParseRegisterWithWriteBack() {
457 SMLoc S = Parser.getTok().getLoc();
458 int RegNo = TryParseRegister();
462 SMLoc E = Parser.getTok().getLoc();
464 bool Writeback = false;
465 const AsmToken &ExclaimTok = Parser.getTok();
466 if (ExclaimTok.is(AsmToken::Exclaim)) {
467 E = ExclaimTok.getLoc();
469 Parser.Lex(); // Eat exclaim token
472 return ARMOperand::CreateReg(RegNo, Writeback, S, E);
475 /// Parse a register list, return it if successful else return null. The first
476 /// token must be a '{' when called.
477 ARMOperand *ARMAsmParser::ParseRegisterList() {
478 assert(Parser.getTok().is(AsmToken::LCurly) &&
479 "Token is not a Left Curly Brace");
480 SMLoc S = Parser.getTok().getLoc();
482 // Read the rest of the registers in the list.
483 unsigned PrevRegNum = 0;
484 SmallVector<std::pair<unsigned, SMLoc>, 32> Registers;
487 bool IsRange = Parser.getTok().is(AsmToken::Minus);
488 Parser.Lex(); // Eat non-identifier token.
490 const AsmToken &RegTok = Parser.getTok();
491 SMLoc RegLoc = RegTok.getLoc();
492 if (RegTok.isNot(AsmToken::Identifier)) {
493 Error(RegLoc, "register expected");
497 int RegNum = TryParseRegister();
499 Error(RegLoc, "register expected");
504 int Reg = PrevRegNum;
507 Registers.push_back(std::make_pair(Reg, RegLoc));
508 } while (Reg != RegNum);
510 Registers.push_back(std::make_pair(RegNum, RegLoc));
514 } while (Parser.getTok().is(AsmToken::Comma) ||
515 Parser.getTok().is(AsmToken::Minus));
517 // Process the right curly brace of the list.
518 const AsmToken &RCurlyTok = Parser.getTok();
519 if (RCurlyTok.isNot(AsmToken::RCurly)) {
520 Error(RCurlyTok.getLoc(), "'}' expected");
524 SMLoc E = RCurlyTok.getLoc();
525 Parser.Lex(); // Eat right curly brace token.
527 // Verify the register list.
528 SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
529 RI = Registers.begin(), RE = Registers.end();
531 DenseMap<unsigned, bool> RegMap;
532 RegMap[RI->first] = true;
534 unsigned HighRegNum = RI->first;
535 bool EmittedWarning = false;
537 for (++RI; RI != RE; ++RI) {
538 const std::pair<unsigned, SMLoc> &RegInfo = *RI;
539 unsigned Reg = RegInfo.first;
542 Error(RegInfo.second, "register duplicated in register list");
546 if (!EmittedWarning && Reg < HighRegNum)
547 Warning(RegInfo.second,
548 "register not in ascending order in register list");
551 HighRegNum = std::max(Reg, HighRegNum);
554 return ARMOperand::CreateRegList(Registers, S, E);
557 /// Parse an ARM memory expression, return false if successful else return true
558 /// or an error. The first token must be a '[' when called.
559 /// TODO Only preindexing and postindexing addressing are started, unindexed
560 /// with option, etc are still to do.
561 ARMOperand *ARMAsmParser::ParseMemory() {
563 assert(Parser.getTok().is(AsmToken::LBrac) &&
564 "Token is not a Left Bracket");
565 S = Parser.getTok().getLoc();
566 Parser.Lex(); // Eat left bracket token.
568 const AsmToken &BaseRegTok = Parser.getTok();
569 if (BaseRegTok.isNot(AsmToken::Identifier)) {
570 Error(BaseRegTok.getLoc(), "register expected");
573 int BaseRegNum = TryParseRegister();
574 if (BaseRegNum == -1) {
575 Error(BaseRegTok.getLoc(), "register expected");
579 bool Preindexed = false;
580 bool Postindexed = false;
581 bool OffsetIsReg = false;
582 bool Negative = false;
583 bool Writeback = false;
585 // First look for preindexed address forms, that is after the "[Rn" we now
586 // have to see if the next token is a comma.
587 const AsmToken &Tok = Parser.getTok();
588 if (Tok.is(AsmToken::Comma)) {
590 Parser.Lex(); // Eat comma token.
592 bool OffsetRegShifted;
593 enum ShiftType ShiftType;
594 const MCExpr *ShiftAmount;
595 const MCExpr *Offset;
596 if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
597 Offset, OffsetIsReg, OffsetRegNum, E))
599 const AsmToken &RBracTok = Parser.getTok();
600 if (RBracTok.isNot(AsmToken::RBrac)) {
601 Error(RBracTok.getLoc(), "']' expected");
604 E = RBracTok.getLoc();
605 Parser.Lex(); // Eat right bracket token.
607 const AsmToken &ExclaimTok = Parser.getTok();
608 if (ExclaimTok.is(AsmToken::Exclaim)) {
609 E = ExclaimTok.getLoc();
611 Parser.Lex(); // Eat exclaim token
613 return ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
614 OffsetRegShifted, ShiftType, ShiftAmount,
615 Preindexed, Postindexed, Negative, Writeback,
618 // The "[Rn" we have so far was not followed by a comma.
619 else if (Tok.is(AsmToken::RBrac)) {
620 // If there's anything other than the right brace, this is a post indexing
623 Parser.Lex(); // Eat right bracket token.
625 int OffsetRegNum = 0;
626 bool OffsetRegShifted = false;
627 enum ShiftType ShiftType;
628 const MCExpr *ShiftAmount;
629 const MCExpr *Offset = 0;
631 const AsmToken &NextTok = Parser.getTok();
632 if (NextTok.isNot(AsmToken::EndOfStatement)) {
635 if (NextTok.isNot(AsmToken::Comma)) {
636 Error(NextTok.getLoc(), "',' expected");
639 Parser.Lex(); // Eat comma token.
640 if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType,
641 ShiftAmount, Offset, OffsetIsReg, OffsetRegNum,
646 return ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
647 OffsetRegShifted, ShiftType, ShiftAmount,
648 Preindexed, Postindexed, Negative, Writeback,
655 /// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn],"
656 /// we will parse the following (were +/- means that a plus or minus is
661 /// we return false on success or an error otherwise.
662 bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
663 bool &OffsetRegShifted,
664 enum ShiftType &ShiftType,
665 const MCExpr *&ShiftAmount,
666 const MCExpr *&Offset,
671 OffsetRegShifted = false;
674 const AsmToken &NextTok = Parser.getTok();
675 E = NextTok.getLoc();
676 if (NextTok.is(AsmToken::Plus))
677 Parser.Lex(); // Eat plus token.
678 else if (NextTok.is(AsmToken::Minus)) {
680 Parser.Lex(); // Eat minus token
682 // See if there is a register following the "[Rn," or "[Rn]," we have so far.
683 const AsmToken &OffsetRegTok = Parser.getTok();
684 if (OffsetRegTok.is(AsmToken::Identifier)) {
685 SMLoc CurLoc = OffsetRegTok.getLoc();
686 OffsetRegNum = TryParseRegister();
687 if (OffsetRegNum != -1) {
693 // If we parsed a register as the offset then there can be a shift after that.
694 if (OffsetRegNum != -1) {
695 // Look for a comma then a shift
696 const AsmToken &Tok = Parser.getTok();
697 if (Tok.is(AsmToken::Comma)) {
698 Parser.Lex(); // Eat comma token.
700 const AsmToken &Tok = Parser.getTok();
701 if (ParseShift(ShiftType, ShiftAmount, E))
702 return Error(Tok.getLoc(), "shift expected");
703 OffsetRegShifted = true;
706 else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm"
707 // Look for #offset following the "[Rn," or "[Rn],"
708 const AsmToken &HashTok = Parser.getTok();
709 if (HashTok.isNot(AsmToken::Hash))
710 return Error(HashTok.getLoc(), "'#' expected");
712 Parser.Lex(); // Eat hash token.
714 if (getParser().ParseExpression(Offset))
716 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
721 /// ParseShift as one of these two:
722 /// ( lsl | lsr | asr | ror ) , # shift_amount
724 /// and returns true if it parses a shift otherwise it returns false.
725 bool ARMAsmParser::ParseShift(ShiftType &St, const MCExpr *&ShiftAmount,
727 const AsmToken &Tok = Parser.getTok();
728 if (Tok.isNot(AsmToken::Identifier))
730 StringRef ShiftName = Tok.getString();
731 if (ShiftName == "lsl" || ShiftName == "LSL")
733 else if (ShiftName == "lsr" || ShiftName == "LSR")
735 else if (ShiftName == "asr" || ShiftName == "ASR")
737 else if (ShiftName == "ror" || ShiftName == "ROR")
739 else if (ShiftName == "rrx" || ShiftName == "RRX")
743 Parser.Lex(); // Eat shift type token.
749 // Otherwise, there must be a '#' and a shift amount.
750 const AsmToken &HashTok = Parser.getTok();
751 if (HashTok.isNot(AsmToken::Hash))
752 return Error(HashTok.getLoc(), "'#' expected");
753 Parser.Lex(); // Eat hash token.
755 if (getParser().ParseExpression(ShiftAmount))
761 /// Parse a arm instruction operand. For now this parses the operand regardless
763 ARMOperand *ARMAsmParser::ParseOperand() {
765 switch (getLexer().getKind()) {
767 Error(Parser.getTok().getLoc(), "unexpected token in operand");
769 case AsmToken::Identifier:
770 if (ARMOperand *Op = TryParseRegisterWithWriteBack())
773 // This was not a register so parse other operands that start with an
774 // identifier (like labels) as expressions and create them as immediates.
776 S = Parser.getTok().getLoc();
777 if (getParser().ParseExpression(IdVal))
779 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
780 return ARMOperand::CreateImm(IdVal, S, E);
781 case AsmToken::LBrac:
782 return ParseMemory();
783 case AsmToken::LCurly:
784 return ParseRegisterList();
787 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
788 S = Parser.getTok().getLoc();
790 const MCExpr *ImmVal;
791 if (getParser().ParseExpression(ImmVal))
793 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
794 return ARMOperand::CreateImm(ImmVal, S, E);
798 /// Parse an arm instruction mnemonic followed by its operands.
799 bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
800 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
801 // Create the leading tokens for the mnemonic, split by '.' characters.
802 size_t Start = 0, Next = Name.find('.');
803 StringRef Head = Name.slice(Start, Next);
805 // Determine the predicate, if any.
807 // FIXME: We need a way to check whether a prefix supports predication,
808 // otherwise we will end up with an ambiguity for instructions that happen to
809 // end with a predicate name.
810 // FIXME: Likewise, some arithmetic instructions have an 's' prefix which
811 // indicates to update the condition codes. Those instructions have an
812 // additional immediate operand which encodes the prefix as reg0 or CPSR.
813 // Just checking for a suffix of 's' definitely creates ambiguities; e.g,
814 // the SMMLS instruction.
815 unsigned CC = StringSwitch<unsigned>(Head.substr(Head.size()-2))
816 .Case("eq", ARMCC::EQ)
817 .Case("ne", ARMCC::NE)
818 .Case("hs", ARMCC::HS)
819 .Case("lo", ARMCC::LO)
820 .Case("mi", ARMCC::MI)
821 .Case("pl", ARMCC::PL)
822 .Case("vs", ARMCC::VS)
823 .Case("vc", ARMCC::VC)
824 .Case("hi", ARMCC::HI)
825 .Case("ls", ARMCC::LS)
826 .Case("ge", ARMCC::GE)
827 .Case("lt", ARMCC::LT)
828 .Case("gt", ARMCC::GT)
829 .Case("le", ARMCC::LE)
830 .Case("al", ARMCC::AL)
834 (CC == ARMCC::LS && (Head == "vmls" || Head == "vnmls"))) {
837 Head = Head.slice(0, Head.size() - 2);
840 Operands.push_back(ARMOperand::CreateToken(Head, NameLoc));
841 // FIXME: Should only add this operand for predicated instructions
842 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), NameLoc));
844 // Add the remaining tokens in the mnemonic.
845 while (Next != StringRef::npos) {
847 Next = Name.find('.', Start + 1);
848 Head = Name.slice(Start, Next);
850 Operands.push_back(ARMOperand::CreateToken(Head, NameLoc));
853 // Read the remaining operands.
854 if (getLexer().isNot(AsmToken::EndOfStatement)) {
855 // Read the first operand.
856 if (ARMOperand *Op = ParseOperand())
857 Operands.push_back(Op);
859 Parser.EatToEndOfStatement();
863 while (getLexer().is(AsmToken::Comma)) {
864 Parser.Lex(); // Eat the comma.
866 // Parse and remember the operand.
867 if (ARMOperand *Op = ParseOperand())
868 Operands.push_back(Op);
870 Parser.EatToEndOfStatement();
876 if (getLexer().isNot(AsmToken::EndOfStatement)) {
877 Parser.EatToEndOfStatement();
878 return TokError("unexpected token in argument list");
881 Parser.Lex(); // Consume the EndOfStatement
886 MatchAndEmitInstruction(SMLoc IDLoc,
887 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
891 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo)) {
893 Out.EmitInstruction(Inst);
895 case Match_MissingFeature:
896 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
898 case Match_InvalidOperand: {
899 SMLoc ErrorLoc = IDLoc;
900 if (ErrorInfo != ~0U) {
901 if (ErrorInfo >= Operands.size())
902 return Error(IDLoc, "too few operands for instruction");
904 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
905 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
908 return Error(ErrorLoc, "invalid operand for instruction");
910 case Match_MnemonicFail:
911 return Error(IDLoc, "unrecognized instruction mnemonic");
914 llvm_unreachable("Implement any new match types added!");
918 /// ParseDirective parses the arm specific directives
919 bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
920 StringRef IDVal = DirectiveID.getIdentifier();
921 if (IDVal == ".word")
922 return ParseDirectiveWord(4, DirectiveID.getLoc());
923 else if (IDVal == ".thumb")
924 return ParseDirectiveThumb(DirectiveID.getLoc());
925 else if (IDVal == ".thumb_func")
926 return ParseDirectiveThumbFunc(DirectiveID.getLoc());
927 else if (IDVal == ".code")
928 return ParseDirectiveCode(DirectiveID.getLoc());
929 else if (IDVal == ".syntax")
930 return ParseDirectiveSyntax(DirectiveID.getLoc());
934 /// ParseDirectiveWord
935 /// ::= .word [ expression (, expression)* ]
936 bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
937 if (getLexer().isNot(AsmToken::EndOfStatement)) {
940 if (getParser().ParseExpression(Value))
943 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
945 if (getLexer().is(AsmToken::EndOfStatement))
948 // FIXME: Improve diagnostic.
949 if (getLexer().isNot(AsmToken::Comma))
950 return Error(L, "unexpected token in directive");
959 /// ParseDirectiveThumb
961 bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) {
962 if (getLexer().isNot(AsmToken::EndOfStatement))
963 return Error(L, "unexpected token in directive");
966 // TODO: set thumb mode
967 // TODO: tell the MC streamer the mode
968 // getParser().getStreamer().Emit???();
972 /// ParseDirectiveThumbFunc
973 /// ::= .thumbfunc symbol_name
974 bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) {
975 const AsmToken &Tok = Parser.getTok();
976 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
977 return Error(L, "unexpected token in .thumb_func directive");
978 StringRef Name = Tok.getString();
979 Parser.Lex(); // Consume the identifier token.
980 if (getLexer().isNot(AsmToken::EndOfStatement))
981 return Error(L, "unexpected token in directive");
984 // Mark symbol as a thumb symbol.
985 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
986 getParser().getStreamer().EmitThumbFunc(Func);
990 /// ParseDirectiveSyntax
991 /// ::= .syntax unified | divided
992 bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) {
993 const AsmToken &Tok = Parser.getTok();
994 if (Tok.isNot(AsmToken::Identifier))
995 return Error(L, "unexpected token in .syntax directive");
996 StringRef Mode = Tok.getString();
997 if (Mode == "unified" || Mode == "UNIFIED")
999 else if (Mode == "divided" || Mode == "DIVIDED")
1002 return Error(L, "unrecognized syntax mode in .syntax directive");
1004 if (getLexer().isNot(AsmToken::EndOfStatement))
1005 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
1008 // TODO tell the MC streamer the mode
1009 // getParser().getStreamer().Emit???();
1013 /// ParseDirectiveCode
1014 /// ::= .code 16 | 32
1015 bool ARMAsmParser::ParseDirectiveCode(SMLoc L) {
1016 const AsmToken &Tok = Parser.getTok();
1017 if (Tok.isNot(AsmToken::Integer))
1018 return Error(L, "unexpected token in .code directive");
1019 int64_t Val = Parser.getTok().getIntVal();
1025 return Error(L, "invalid operand to .code directive");
1027 if (getLexer().isNot(AsmToken::EndOfStatement))
1028 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
1032 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
1034 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
1039 extern "C" void LLVMInitializeARMAsmLexer();
1041 /// Force static initialization.
1042 extern "C" void LLVMInitializeARMAsmParser() {
1043 RegisterAsmParser<ARMAsmParser> X(TheARMTarget);
1044 RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget);
1045 LLVMInitializeARMAsmLexer();
1048 #define GET_REGISTER_MATCHER
1049 #define GET_MATCHER_IMPLEMENTATION
1050 #include "ARMGenAsmMatcher.inc"