X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FARM%2FAsmParser%2FARMAsmParser.cpp;h=b41b71d4b0a842d9299b24207aa5af7973771fe0;hb=d68fd9c79eeb30980c18dc3f74b2da839bb259f3;hp=327af20d9934532590cd0cedf68ef38e5d03e4a3;hpb=52925b60f1cd4cf810524ca05b00a207a926ab9f;p=oota-llvm.git diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 327af20d993..b41b71d4b0a 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -8,10 +8,12 @@ //===----------------------------------------------------------------------===// #include "ARM.h" +#include "ARMAddressingModes.h" #include "ARMSubtarget.h" #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" @@ -49,7 +51,8 @@ private: bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); } - ARMOperand *MaybeParseRegister(bool ParseWriteBack); + int TryParseRegister(); + ARMOperand *TryParseRegisterWithWriteBack(); ARMOperand *ParseRegisterList(); ARMOperand *ParseMemory(); @@ -91,7 +94,11 @@ private: public: ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM) - : TargetAsmParser(T), Parser(_Parser), TM(_TM) {} + : TargetAsmParser(T), Parser(_Parser), TM(_TM) { + // Initialize the set of available features. + setAvailableFeatures(ComputeAvailableFeatures( + &TM.getSubtarget())); + } virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc, SmallVectorImpl &Operands); @@ -255,16 +262,25 @@ public: Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); assert(!Mem.OffsetIsReg && "invalid mode 5 operand"); + // FIXME: #-0 is encoded differently than #0. Does the parser preserve // the difference? if (Mem.Offset) { const MCConstantExpr *CE = dyn_cast(Mem.Offset); - assert (CE && "non-constant mode 5 offset operand!"); + assert(CE && "Non-constant mode 5 offset operand!"); + // The MCInst offset operand doesn't include the low two bits (like // the instruction encoding). - Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4)); - } else + int64_t Offset = CE->getValue() / 4; + if (Offset >= 0) + Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::add, + Offset))); + else + Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::sub, + -Offset))); + } else { Inst.addOperand(MCOperand::CreateImm(0)); + } } virtual void dump(raw_ostream &OS) const; @@ -362,41 +378,45 @@ static unsigned MatchRegisterName(StringRef Name); /// } /// Try to parse a register name. The token must be an Identifier when called, -/// and if it is a register name the token is eaten and a Reg operand is created -/// and returned. Otherwise return null. +/// and if it is a register name the token is eaten and the register number is +/// returned. Otherwise return -1. /// -/// TODO this is likely to change to allow different register types and or to -/// parse for a specific register type. -ARMOperand *ARMAsmParser::MaybeParseRegister(bool ParseWriteBack) { - SMLoc S, E; +int ARMAsmParser::TryParseRegister() { const AsmToken &Tok = Parser.getTok(); assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); // FIXME: Validate register for the current architecture; we have to do // validation later, so maybe there is no need for this here. - int RegNum; - - RegNum = MatchRegisterName(Tok.getString()); - if (RegNum == -1) - return 0; + unsigned RegNum = MatchRegisterName(Tok.getString()); + if (RegNum == 0) + return -1; + Parser.Lex(); // Eat identifier token. + return RegNum; +} - S = Tok.getLoc(); - Parser.Lex(); // Eat identifier token. +/// Try to parse a register name. The token must be an Identifier when called, +/// and if it is a register name the token is eaten and the register number is +/// returned. Otherwise return -1. +/// +/// TODO this is likely to change to allow different register types and or to +/// parse for a specific register type. +ARMOperand *ARMAsmParser::TryParseRegisterWithWriteBack() { + SMLoc S = Parser.getTok().getLoc(); + int RegNo = TryParseRegister(); + if (RegNo == -1) return 0; - E = Parser.getTok().getLoc(); + SMLoc E = Parser.getTok().getLoc(); bool Writeback = false; - if (ParseWriteBack) { - const AsmToken &ExclaimTok = Parser.getTok(); - if (ExclaimTok.is(AsmToken::Exclaim)) { - E = ExclaimTok.getLoc(); - Writeback = true; - Parser.Lex(); // Eat exclaim token - } + const AsmToken &ExclaimTok = Parser.getTok(); + if (ExclaimTok.is(AsmToken::Exclaim)) { + E = ExclaimTok.getLoc(); + Writeback = true; + Parser.Lex(); // Eat exclaim token } - return ARMOperand::CreateReg(RegNum, Writeback, S, E); + return ARMOperand::CreateReg(RegNo, Writeback, S, E); } /// Parse a register list, return it if successful else return null. The first @@ -414,13 +434,12 @@ ARMOperand *ARMAsmParser::ParseRegisterList() { Error(RegLoc, "register expected"); return 0; } - int RegNum = MatchRegisterName(RegTok.getString()); + int RegNum = TryParseRegister(); if (RegNum == -1) { Error(RegLoc, "register expected"); return 0; } - Parser.Lex(); // Eat identifier token. unsigned RegList = 1 << RegNum; int HighRegNum = RegNum; @@ -434,7 +453,7 @@ ARMOperand *ARMAsmParser::ParseRegisterList() { Error(RegLoc, "register expected"); return 0; } - int RegNum = MatchRegisterName(RegTok.getString()); + int RegNum = TryParseRegister(); if (RegNum == -1) { Error(RegLoc, "register expected"); return 0; @@ -446,8 +465,6 @@ ARMOperand *ARMAsmParser::ParseRegisterList() { Warning(RegLoc, "register not in ascending order in register list"); RegList |= 1 << RegNum; HighRegNum = RegNum; - - Parser.Lex(); // Eat identifier token. } const AsmToken &RCurlyTok = Parser.getTok(); if (RCurlyTok.isNot(AsmToken::RCurly)) { @@ -478,11 +495,8 @@ ARMOperand *ARMAsmParser::ParseMemory() { Error(BaseRegTok.getLoc(), "register expected"); return 0; } - int BaseRegNum = 0; - if (ARMOperand *Op = MaybeParseRegister(false)) { - BaseRegNum = Op->getReg(); - delete Op; - } else { + int BaseRegNum = TryParseRegister(); + if (BaseRegNum == -1) { Error(BaseRegTok.getLoc(), "register expected"); return 0; } @@ -593,13 +607,14 @@ bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative, // See if there is a register following the "[Rn," or "[Rn]," we have so far. const AsmToken &OffsetRegTok = Parser.getTok(); if (OffsetRegTok.is(AsmToken::Identifier)) { - if (ARMOperand *Op = MaybeParseRegister(false)) { + SMLoc CurLoc = OffsetRegTok.getLoc(); + OffsetRegNum = TryParseRegister(); + if (OffsetRegNum != -1) { OffsetIsReg = true; - E = Op->getEndLoc(); - OffsetRegNum = Op->getReg(); - delete Op; + E = CurLoc; } } + // If we parsed a register as the offset then their can be a shift after that if (OffsetRegNum != -1) { // Look for a comma then a shift @@ -675,7 +690,7 @@ ARMOperand *ARMAsmParser::ParseOperand() { switch (getLexer().getKind()) { case AsmToken::Identifier: - if (ARMOperand *Op = MaybeParseRegister(true)) + if (ARMOperand *Op = TryParseRegisterWithWriteBack()) return Op; // This was not a register so parse other operands that start with an @@ -741,18 +756,15 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc, .Case("al", ARMCC::AL) .Default(~0U); - if (CC != ~0U) { - if (CC == ARMCC::LS && - (Head.compare("vmls") == 0 || Head.compare("vnmls") == 0)) { - CC = ARMCC::AL; - } else { - Head = Head.slice(0, Head.size() - 2); - } - } else { + if (CC == ~0U || + (CC == ARMCC::LS && (Head == "vmls" || Head == "vnmls"))) { CC = ARMCC::AL; + } else { + Head = Head.slice(0, Head.size() - 2); } Operands.push_back(ARMOperand::CreateToken(Head, NameLoc)); + // FIXME: Should only add this operand for predicated instructions Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), NameLoc)); // Add the remaining tokens in the mnemonic. @@ -889,15 +901,16 @@ bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) { bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) { const AsmToken &Tok = Parser.getTok(); if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String)) - return Error(L, "unexpected token in .syntax directive"); + return Error(L, "unexpected token in .thumb_func directive"); + StringRef Name = Tok.getString(); Parser.Lex(); // Consume the identifier token. - if (getLexer().isNot(AsmToken::EndOfStatement)) return Error(L, "unexpected token in directive"); Parser.Lex(); - // TODO: mark symbol as a thumb symbol - // getParser().getStreamer().Emit???(); + // Mark symbol as a thumb symbol. + MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name); + getParser().getStreamer().EmitThumbFunc(Func); return false; } @@ -942,8 +955,11 @@ bool ARMAsmParser::ParseDirectiveCode(SMLoc L) { return Error(Parser.getTok().getLoc(), "unexpected token in directive"); Parser.Lex(); - // TODO tell the MC streamer the mode - // getParser().getStreamer().Emit???(); + if (Val == 16) + getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16); + else + getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32); + return false; }