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 {
113 SMLoc StartLoc, EndLoc;
117 ARMCC::CondCodes Val;
139 // This is for all forms of ARM address expressions
142 unsigned OffsetRegNum; // used when OffsetIsReg is true
143 const MCExpr *Offset; // used when OffsetIsReg is false
144 const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
145 enum ShiftType ShiftType; // used when OffsetRegShifted is true
146 unsigned OffsetRegShifted : 1; // only used when OffsetIsReg is true
147 unsigned Preindexed : 1;
148 unsigned Postindexed : 1;
149 unsigned OffsetIsReg : 1;
150 unsigned Negative : 1; // only used when OffsetIsReg is true
151 unsigned Writeback : 1;
155 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
157 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
159 StartLoc = o.StartLoc;
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 || Kind == RegisterList) && "Invalid access!");
201 if (Kind == Register)
204 RegNum = RegList.RegStart;
208 std::pair<unsigned, unsigned> getRegList() const {
209 assert(Kind == RegisterList && "Invalid access!");
210 return std::make_pair(RegList.RegStart, RegList.Number);
213 const MCExpr *getImm() const {
214 assert(Kind == Immediate && "Invalid access!");
218 bool isCondCode() const { return Kind == CondCode; }
219 bool isImm() const { return Kind == Immediate; }
220 bool isReg() const { return Kind == Register || Kind == RegisterList; }
221 bool isRegList() const { return Kind == RegisterList; }
222 bool isToken() const { return Kind == Token; }
223 bool isMemory() const { return Kind == Memory; }
225 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
226 // Add as immediates when possible. Null MCExpr = 0.
228 Inst.addOperand(MCOperand::CreateImm(0));
229 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
230 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
232 Inst.addOperand(MCOperand::CreateExpr(Expr));
235 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
236 assert(N == 2 && "Invalid number of operands!");
237 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
238 // FIXME: What belongs here?
239 Inst.addOperand(MCOperand::CreateReg(0));
242 void addRegOperands(MCInst &Inst, unsigned N) const {
243 assert(N == 1 && "Invalid number of operands!");
244 Inst.addOperand(MCOperand::CreateReg(getReg()));
247 void addImmOperands(MCInst &Inst, unsigned N) const {
248 assert(N == 1 && "Invalid number of operands!");
249 addExpr(Inst, getImm());
252 bool isMemMode5() const {
253 if (!isMemory() || Mem.OffsetIsReg || Mem.OffsetRegShifted ||
254 Mem.Writeback || Mem.Negative)
256 // If there is an offset expression, make sure it's valid.
259 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset);
262 // The offset must be a multiple of 4 in the range 0-1020.
263 int64_t Value = CE->getValue();
264 return ((Value & 0x3) == 0 && Value <= 1020 && Value >= -1020);
267 void addMemMode5Operands(MCInst &Inst, unsigned N) const {
268 assert(N == 2 && isMemMode5() && "Invalid number of operands!");
270 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
271 assert(!Mem.OffsetIsReg && "Invalid mode 5 operand");
273 // FIXME: #-0 is encoded differently than #0. Does the parser preserve
276 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset);
277 assert(CE && "Non-constant mode 5 offset operand!");
279 // The MCInst offset operand doesn't include the low two bits (like
280 // the instruction encoding).
281 int64_t Offset = CE->getValue() / 4;
283 Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::add,
286 Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::sub,
289 Inst.addOperand(MCOperand::CreateImm(0));
293 virtual void dump(raw_ostream &OS) const;
295 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
296 ARMOperand *Op = new ARMOperand(CondCode);
303 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
304 ARMOperand *Op = new ARMOperand(Token);
305 Op->Tok.Data = Str.data();
306 Op->Tok.Length = Str.size();
312 static ARMOperand *CreateReg(unsigned RegNum, bool Writeback, SMLoc S,
314 ARMOperand *Op = new ARMOperand(Register);
315 Op->Reg.RegNum = RegNum;
316 Op->Reg.Writeback = Writeback;
322 static ARMOperand *CreateRegList(unsigned RegStart, unsigned Number,
324 ARMOperand *Op = new ARMOperand(RegisterList);
325 Op->RegList.RegStart = RegStart;
326 Op->RegList.Number = Number;
332 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
333 ARMOperand *Op = new ARMOperand(Immediate);
340 static ARMOperand *CreateMem(unsigned BaseRegNum, bool OffsetIsReg,
341 const MCExpr *Offset, unsigned OffsetRegNum,
342 bool OffsetRegShifted, enum ShiftType ShiftType,
343 const MCExpr *ShiftAmount, bool Preindexed,
344 bool Postindexed, bool Negative, bool Writeback,
346 ARMOperand *Op = new ARMOperand(Memory);
347 Op->Mem.BaseRegNum = BaseRegNum;
348 Op->Mem.OffsetIsReg = OffsetIsReg;
349 Op->Mem.Offset = Offset;
350 Op->Mem.OffsetRegNum = OffsetRegNum;
351 Op->Mem.OffsetRegShifted = OffsetRegShifted;
352 Op->Mem.ShiftType = ShiftType;
353 Op->Mem.ShiftAmount = ShiftAmount;
354 Op->Mem.Preindexed = Preindexed;
355 Op->Mem.Postindexed = Postindexed;
356 Op->Mem.Negative = Negative;
357 Op->Mem.Writeback = Writeback;
365 } // end anonymous namespace.
367 void ARMOperand::dump(raw_ostream &OS) const {
370 OS << ARMCondCodeToString(getCondCode());
379 OS << "<register " << getReg() << ">";
382 OS << "<register_list ";
383 std::pair<unsigned, unsigned> List = getRegList();
384 unsigned RegEnd = List.first + List.second;
386 for (unsigned Idx = List.first; Idx < RegEnd; ) {
388 if (++Idx < RegEnd) OS << ", ";
395 OS << "'" << getToken() << "'";
400 /// @name Auto-generated Match Functions
403 static unsigned MatchRegisterName(StringRef Name);
407 /// Try to parse a register name. The token must be an Identifier when called,
408 /// and if it is a register name the token is eaten and the register number is
409 /// returned. Otherwise return -1.
411 int ARMAsmParser::TryParseRegister() {
412 const AsmToken &Tok = Parser.getTok();
413 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
415 // FIXME: Validate register for the current architecture; we have to do
416 // validation later, so maybe there is no need for this here.
417 unsigned RegNum = MatchRegisterName(Tok.getString());
420 Parser.Lex(); // Eat identifier token.
425 /// Try to parse a register name. The token must be an Identifier when called,
426 /// and if it is a register name the token is eaten and the register number is
427 /// returned. Otherwise return -1.
429 /// TODO this is likely to change to allow different register types and or to
430 /// parse for a specific register type.
431 ARMOperand *ARMAsmParser::TryParseRegisterWithWriteBack() {
432 SMLoc S = Parser.getTok().getLoc();
433 int RegNo = TryParseRegister();
437 SMLoc E = Parser.getTok().getLoc();
439 bool Writeback = false;
440 const AsmToken &ExclaimTok = Parser.getTok();
441 if (ExclaimTok.is(AsmToken::Exclaim)) {
442 E = ExclaimTok.getLoc();
444 Parser.Lex(); // Eat exclaim token
447 return ARMOperand::CreateReg(RegNo, Writeback, S, E);
450 /// Parse a register list, return it if successful else return null. The first
451 /// token must be a '{' when called.
452 ARMOperand *ARMAsmParser::ParseRegisterList() {
453 assert(Parser.getTok().is(AsmToken::LCurly) &&
454 "Token is not a Left Curly Brace");
455 SMLoc S = Parser.getTok().getLoc();
456 Parser.Lex(); // Eat left curly brace token.
458 const AsmToken &RegTok = Parser.getTok();
459 SMLoc RegLoc = RegTok.getLoc();
460 if (RegTok.isNot(AsmToken::Identifier)) {
461 Error(RegLoc, "register expected");
465 int RegNum = TryParseRegister();
467 Error(RegLoc, "register expected");
471 unsigned PrevRegNum = RegNum;
472 std::vector<std::pair<unsigned, SMLoc> > Registers;
473 Registers.reserve(32);
474 Registers.push_back(std::make_pair(RegNum, RegLoc));
476 while (Parser.getTok().is(AsmToken::Comma) ||
477 Parser.getTok().is(AsmToken::Minus)) {
478 bool IsRange = Parser.getTok().is(AsmToken::Minus);
479 Parser.Lex(); // Eat comma or minus token.
481 const AsmToken &RegTok = Parser.getTok();
482 SMLoc RegLoc = RegTok.getLoc();
483 if (RegTok.isNot(AsmToken::Identifier)) {
484 Error(RegLoc, "register expected");
488 int RegNum = TryParseRegister();
490 Error(RegLoc, "register expected");
495 int Reg = PrevRegNum;
498 Registers.push_back(std::make_pair(Reg, RegLoc));
499 } while (Reg != RegNum);
501 Registers.push_back(std::make_pair(RegNum, RegLoc));
507 // Process the right curly brace of the list.
508 const AsmToken &RCurlyTok = Parser.getTok();
509 if (RCurlyTok.isNot(AsmToken::RCurly)) {
510 Error(RCurlyTok.getLoc(), "'}' expected");
514 SMLoc E = RCurlyTok.getLoc();
515 Parser.Lex(); // Eat right curly brace token.
517 // Verify the register list.
518 std::vector<std::pair<unsigned, SMLoc> >::iterator
519 RI = Registers.begin(), RE = Registers.end();
521 unsigned Number = Registers.size();
522 unsigned HighRegNum = RI->first;
523 unsigned RegStart = RI->first;
525 DenseMap<unsigned, bool> RegMap;
526 RegMap[RI->first] = true;
528 for (++RI; RI != RE; ++RI) {
529 std::pair<unsigned, SMLoc> &RegInfo = *RI;
531 if (RegMap[RegInfo.first]) {
532 Error(RegInfo.second, "register duplicated in register list");
536 if (RegInfo.first < HighRegNum)
537 Warning(RegInfo.second,
538 "register not in ascending order in register list");
540 RegMap[RegInfo.first] = true;
541 HighRegNum = std::max(RegInfo.first, HighRegNum);
542 RegStart = std::min(RegInfo.first, RegStart);
545 if (RegStart + Number - 1 != HighRegNum) {
546 Error(RegLoc, "non-contiguous register range");
550 return ARMOperand::CreateRegList(RegStart, Number, S, E);
553 /// Parse an ARM memory expression, return false if successful else return true
554 /// or an error. The first token must be a '[' when called.
555 /// TODO Only preindexing and postindexing addressing are started, unindexed
556 /// with option, etc are still to do.
557 ARMOperand *ARMAsmParser::ParseMemory() {
559 assert(Parser.getTok().is(AsmToken::LBrac) &&
560 "Token is not a Left Bracket");
561 S = Parser.getTok().getLoc();
562 Parser.Lex(); // Eat left bracket token.
564 const AsmToken &BaseRegTok = Parser.getTok();
565 if (BaseRegTok.isNot(AsmToken::Identifier)) {
566 Error(BaseRegTok.getLoc(), "register expected");
569 int BaseRegNum = TryParseRegister();
570 if (BaseRegNum == -1) {
571 Error(BaseRegTok.getLoc(), "register expected");
575 bool Preindexed = false;
576 bool Postindexed = false;
577 bool OffsetIsReg = false;
578 bool Negative = false;
579 bool Writeback = false;
581 // First look for preindexed address forms, that is after the "[Rn" we now
582 // have to see if the next token is a comma.
583 const AsmToken &Tok = Parser.getTok();
584 if (Tok.is(AsmToken::Comma)) {
586 Parser.Lex(); // Eat comma token.
588 bool OffsetRegShifted;
589 enum ShiftType ShiftType;
590 const MCExpr *ShiftAmount;
591 const MCExpr *Offset;
592 if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
593 Offset, OffsetIsReg, OffsetRegNum, E))
595 const AsmToken &RBracTok = Parser.getTok();
596 if (RBracTok.isNot(AsmToken::RBrac)) {
597 Error(RBracTok.getLoc(), "']' expected");
600 E = RBracTok.getLoc();
601 Parser.Lex(); // Eat right bracket token.
603 const AsmToken &ExclaimTok = Parser.getTok();
604 if (ExclaimTok.is(AsmToken::Exclaim)) {
605 E = ExclaimTok.getLoc();
607 Parser.Lex(); // Eat exclaim token
609 return ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
610 OffsetRegShifted, ShiftType, ShiftAmount,
611 Preindexed, Postindexed, Negative, Writeback,
614 // The "[Rn" we have so far was not followed by a comma.
615 else if (Tok.is(AsmToken::RBrac)) {
616 // If there's anything other than the right brace, this is a post indexing
619 Parser.Lex(); // Eat right bracket token.
621 int OffsetRegNum = 0;
622 bool OffsetRegShifted = false;
623 enum ShiftType ShiftType;
624 const MCExpr *ShiftAmount;
625 const MCExpr *Offset = 0;
627 const AsmToken &NextTok = Parser.getTok();
628 if (NextTok.isNot(AsmToken::EndOfStatement)) {
631 if (NextTok.isNot(AsmToken::Comma)) {
632 Error(NextTok.getLoc(), "',' expected");
635 Parser.Lex(); // Eat comma token.
636 if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType,
637 ShiftAmount, Offset, OffsetIsReg, OffsetRegNum,
642 return ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
643 OffsetRegShifted, ShiftType, ShiftAmount,
644 Preindexed, Postindexed, Negative, Writeback,
651 /// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn],"
652 /// we will parse the following (were +/- means that a plus or minus is
657 /// we return false on success or an error otherwise.
658 bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
659 bool &OffsetRegShifted,
660 enum ShiftType &ShiftType,
661 const MCExpr *&ShiftAmount,
662 const MCExpr *&Offset,
667 OffsetRegShifted = false;
670 const AsmToken &NextTok = Parser.getTok();
671 E = NextTok.getLoc();
672 if (NextTok.is(AsmToken::Plus))
673 Parser.Lex(); // Eat plus token.
674 else if (NextTok.is(AsmToken::Minus)) {
676 Parser.Lex(); // Eat minus token
678 // See if there is a register following the "[Rn," or "[Rn]," we have so far.
679 const AsmToken &OffsetRegTok = Parser.getTok();
680 if (OffsetRegTok.is(AsmToken::Identifier)) {
681 SMLoc CurLoc = OffsetRegTok.getLoc();
682 OffsetRegNum = TryParseRegister();
683 if (OffsetRegNum != -1) {
689 // If we parsed a register as the offset then there can be a shift after that.
690 if (OffsetRegNum != -1) {
691 // Look for a comma then a shift
692 const AsmToken &Tok = Parser.getTok();
693 if (Tok.is(AsmToken::Comma)) {
694 Parser.Lex(); // Eat comma token.
696 const AsmToken &Tok = Parser.getTok();
697 if (ParseShift(ShiftType, ShiftAmount, E))
698 return Error(Tok.getLoc(), "shift expected");
699 OffsetRegShifted = true;
702 else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm"
703 // Look for #offset following the "[Rn," or "[Rn],"
704 const AsmToken &HashTok = Parser.getTok();
705 if (HashTok.isNot(AsmToken::Hash))
706 return Error(HashTok.getLoc(), "'#' expected");
708 Parser.Lex(); // Eat hash token.
710 if (getParser().ParseExpression(Offset))
712 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
717 /// ParseShift as one of these two:
718 /// ( lsl | lsr | asr | ror ) , # shift_amount
720 /// and returns true if it parses a shift otherwise it returns false.
721 bool ARMAsmParser::ParseShift(ShiftType &St, const MCExpr *&ShiftAmount,
723 const AsmToken &Tok = Parser.getTok();
724 if (Tok.isNot(AsmToken::Identifier))
726 StringRef ShiftName = Tok.getString();
727 if (ShiftName == "lsl" || ShiftName == "LSL")
729 else if (ShiftName == "lsr" || ShiftName == "LSR")
731 else if (ShiftName == "asr" || ShiftName == "ASR")
733 else if (ShiftName == "ror" || ShiftName == "ROR")
735 else if (ShiftName == "rrx" || ShiftName == "RRX")
739 Parser.Lex(); // Eat shift type token.
745 // Otherwise, there must be a '#' and a shift amount.
746 const AsmToken &HashTok = Parser.getTok();
747 if (HashTok.isNot(AsmToken::Hash))
748 return Error(HashTok.getLoc(), "'#' expected");
749 Parser.Lex(); // Eat hash token.
751 if (getParser().ParseExpression(ShiftAmount))
757 /// Parse a arm instruction operand. For now this parses the operand regardless
759 ARMOperand *ARMAsmParser::ParseOperand() {
761 switch (getLexer().getKind()) {
763 Error(Parser.getTok().getLoc(), "unexpected token in operand");
765 case AsmToken::Identifier:
766 if (ARMOperand *Op = TryParseRegisterWithWriteBack())
769 // This was not a register so parse other operands that start with an
770 // identifier (like labels) as expressions and create them as immediates.
772 S = Parser.getTok().getLoc();
773 if (getParser().ParseExpression(IdVal))
775 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
776 return ARMOperand::CreateImm(IdVal, S, E);
777 case AsmToken::LBrac:
778 return ParseMemory();
779 case AsmToken::LCurly:
780 return ParseRegisterList();
783 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
784 S = Parser.getTok().getLoc();
786 const MCExpr *ImmVal;
787 if (getParser().ParseExpression(ImmVal))
789 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
790 return ARMOperand::CreateImm(ImmVal, S, E);
794 /// Parse an arm instruction mnemonic followed by its operands.
795 bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
796 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
797 // Create the leading tokens for the mnemonic, split by '.' characters.
798 size_t Start = 0, Next = Name.find('.');
799 StringRef Head = Name.slice(Start, Next);
801 // Determine the predicate, if any.
803 // FIXME: We need a way to check whether a prefix supports predication,
804 // otherwise we will end up with an ambiguity for instructions that happen to
805 // end with a predicate name.
806 // FIXME: Likewise, some arithmetic instructions have an 's' prefix which
807 // indicates to update the condition codes. Those instructions have an
808 // additional immediate operand which encodes the prefix as reg0 or CPSR.
809 // Just checking for a suffix of 's' definitely creates ambiguities; e.g,
810 // the SMMLS instruction.
811 unsigned CC = StringSwitch<unsigned>(Head.substr(Head.size()-2))
812 .Case("eq", ARMCC::EQ)
813 .Case("ne", ARMCC::NE)
814 .Case("hs", ARMCC::HS)
815 .Case("lo", ARMCC::LO)
816 .Case("mi", ARMCC::MI)
817 .Case("pl", ARMCC::PL)
818 .Case("vs", ARMCC::VS)
819 .Case("vc", ARMCC::VC)
820 .Case("hi", ARMCC::HI)
821 .Case("ls", ARMCC::LS)
822 .Case("ge", ARMCC::GE)
823 .Case("lt", ARMCC::LT)
824 .Case("gt", ARMCC::GT)
825 .Case("le", ARMCC::LE)
826 .Case("al", ARMCC::AL)
830 (CC == ARMCC::LS && (Head == "vmls" || Head == "vnmls"))) {
833 Head = Head.slice(0, Head.size() - 2);
836 Operands.push_back(ARMOperand::CreateToken(Head, NameLoc));
837 // FIXME: Should only add this operand for predicated instructions
838 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), NameLoc));
840 // Add the remaining tokens in the mnemonic.
841 while (Next != StringRef::npos) {
843 Next = Name.find('.', Start + 1);
844 Head = Name.slice(Start, Next);
846 Operands.push_back(ARMOperand::CreateToken(Head, NameLoc));
849 // Read the remaining operands.
850 if (getLexer().isNot(AsmToken::EndOfStatement)) {
851 // Read the first operand.
852 if (ARMOperand *Op = ParseOperand())
853 Operands.push_back(Op);
855 Parser.EatToEndOfStatement();
859 while (getLexer().is(AsmToken::Comma)) {
860 Parser.Lex(); // Eat the comma.
862 // Parse and remember the operand.
863 if (ARMOperand *Op = ParseOperand())
864 Operands.push_back(Op);
866 Parser.EatToEndOfStatement();
872 if (getLexer().isNot(AsmToken::EndOfStatement)) {
873 Parser.EatToEndOfStatement();
874 return TokError("unexpected token in argument list");
877 Parser.Lex(); // Consume the EndOfStatement
882 MatchAndEmitInstruction(SMLoc IDLoc,
883 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
887 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo)) {
889 Out.EmitInstruction(Inst);
891 case Match_MissingFeature:
892 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
894 case Match_InvalidOperand: {
895 SMLoc ErrorLoc = IDLoc;
896 if (ErrorInfo != ~0U) {
897 if (ErrorInfo >= Operands.size())
898 return Error(IDLoc, "too few operands for instruction");
900 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
901 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
904 return Error(ErrorLoc, "invalid operand for instruction");
906 case Match_MnemonicFail:
907 return Error(IDLoc, "unrecognized instruction mnemonic");
910 llvm_unreachable("Implement any new match types added!");
914 /// ParseDirective parses the arm specific directives
915 bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
916 StringRef IDVal = DirectiveID.getIdentifier();
917 if (IDVal == ".word")
918 return ParseDirectiveWord(4, DirectiveID.getLoc());
919 else if (IDVal == ".thumb")
920 return ParseDirectiveThumb(DirectiveID.getLoc());
921 else if (IDVal == ".thumb_func")
922 return ParseDirectiveThumbFunc(DirectiveID.getLoc());
923 else if (IDVal == ".code")
924 return ParseDirectiveCode(DirectiveID.getLoc());
925 else if (IDVal == ".syntax")
926 return ParseDirectiveSyntax(DirectiveID.getLoc());
930 /// ParseDirectiveWord
931 /// ::= .word [ expression (, expression)* ]
932 bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
933 if (getLexer().isNot(AsmToken::EndOfStatement)) {
936 if (getParser().ParseExpression(Value))
939 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
941 if (getLexer().is(AsmToken::EndOfStatement))
944 // FIXME: Improve diagnostic.
945 if (getLexer().isNot(AsmToken::Comma))
946 return Error(L, "unexpected token in directive");
955 /// ParseDirectiveThumb
957 bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) {
958 if (getLexer().isNot(AsmToken::EndOfStatement))
959 return Error(L, "unexpected token in directive");
962 // TODO: set thumb mode
963 // TODO: tell the MC streamer the mode
964 // getParser().getStreamer().Emit???();
968 /// ParseDirectiveThumbFunc
969 /// ::= .thumbfunc symbol_name
970 bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) {
971 const AsmToken &Tok = Parser.getTok();
972 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
973 return Error(L, "unexpected token in .thumb_func directive");
974 StringRef Name = Tok.getString();
975 Parser.Lex(); // Consume the identifier token.
976 if (getLexer().isNot(AsmToken::EndOfStatement))
977 return Error(L, "unexpected token in directive");
980 // Mark symbol as a thumb symbol.
981 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
982 getParser().getStreamer().EmitThumbFunc(Func);
986 /// ParseDirectiveSyntax
987 /// ::= .syntax unified | divided
988 bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) {
989 const AsmToken &Tok = Parser.getTok();
990 if (Tok.isNot(AsmToken::Identifier))
991 return Error(L, "unexpected token in .syntax directive");
992 StringRef Mode = Tok.getString();
993 if (Mode == "unified" || Mode == "UNIFIED")
995 else if (Mode == "divided" || Mode == "DIVIDED")
998 return Error(L, "unrecognized syntax mode in .syntax directive");
1000 if (getLexer().isNot(AsmToken::EndOfStatement))
1001 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
1004 // TODO tell the MC streamer the mode
1005 // getParser().getStreamer().Emit???();
1009 /// ParseDirectiveCode
1010 /// ::= .code 16 | 32
1011 bool ARMAsmParser::ParseDirectiveCode(SMLoc L) {
1012 const AsmToken &Tok = Parser.getTok();
1013 if (Tok.isNot(AsmToken::Integer))
1014 return Error(L, "unexpected token in .code directive");
1015 int64_t Val = Parser.getTok().getIntVal();
1021 return Error(L, "invalid operand to .code directive");
1023 if (getLexer().isNot(AsmToken::EndOfStatement))
1024 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
1028 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
1030 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
1035 extern "C" void LLVMInitializeARMAsmLexer();
1037 /// Force static initialization.
1038 extern "C" void LLVMInitializeARMAsmParser() {
1039 RegisterAsmParser<ARMAsmParser> X(TheARMTarget);
1040 RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget);
1041 LLVMInitializeARMAsmLexer();
1044 #define GET_REGISTER_MATCHER
1045 #define GET_MATCHER_IMPLEMENTATION
1046 #include "ARMGenAsmMatcher.inc"