diff options
author | Wesley Peck <peckw@wesleypeck.com> | 2010-11-08 19:40:01 +0000 |
---|---|---|
committer | Wesley Peck <peckw@wesleypeck.com> | 2010-11-08 19:40:01 +0000 |
commit | 0a67d92938d77b6a8cde6e1676750264b274cebc (patch) | |
tree | 0c6b0c4c8679380835d14ad474b4e38c0a5c54b7 /lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp | |
parent | 554375b707d741c357a78650160ba5d093b4993a (diff) |
Adding working version of assembly parser for the MBlaze backend
Major cleanup of whitespace and formatting issues in MBlaze backend
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@118434 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp')
-rw-r--r-- | lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp | 873 |
1 files changed, 277 insertions, 596 deletions
diff --git a/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp b/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp index d7e3047ed6..80d7f3935a 100644 --- a/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp +++ b/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp @@ -1,4 +1,4 @@ -//===-- MBlazeAsmParser.cpp - Parse MBlaze assembly to MCInst instructions ------===// +//===-- MBlazeAsmParser.cpp - Parse MBlaze asm to MCInst instructions -----===// // // The LLVM Compiler Infrastructure // @@ -29,67 +29,25 @@ using namespace llvm; namespace { struct MBlazeOperand; -// The shift types for register controlled shifts in arm memory addressing -enum ShiftType { - Lsl, - Lsr, - Asr, - Ror, - Rrx -}; - class MBlazeAsmParser : public TargetAsmParser { MCAsmParser &Parser; TargetMachine &TM; -private: MCAsmParser &getParser() const { return Parser; } - MCAsmLexer &getLexer() const { return Parser.getLexer(); } void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); } - bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); } - bool MaybeParseRegister(OwningPtr<MBlazeOperand> &Op, bool ParseWriteBack); - - bool ParseRegisterList(OwningPtr<MBlazeOperand> &Op); - - bool ParseMemory(OwningPtr<MBlazeOperand> &Op); - - bool ParseMemoryOffsetReg(bool &Negative, - bool &OffsetRegShifted, - enum ShiftType &ShiftType, - const MCExpr *&ShiftAmount, - const MCExpr *&Offset, - bool &OffsetIsReg, - int &OffsetRegNum, - SMLoc &E); - - bool ParseShift(enum ShiftType &St, const MCExpr *&ShiftAmount, SMLoc &E); - - bool ParseOperand(OwningPtr<MBlazeOperand> &Op); - - bool ParseDirectiveWord(unsigned Size, SMLoc L); - - bool ParseDirectiveCode(SMLoc L); - - bool ParseDirectiveSyntax(SMLoc L); + MBlazeOperand *ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands); + MBlazeOperand *ParseRegister(); + MBlazeOperand *ParseImmediate(); + MBlazeOperand *ParseFsl(); + MBlazeOperand* ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands); bool MatchAndEmitInstruction(SMLoc IDLoc, SmallVectorImpl<MCParsedAsmOperand*> &Operands, - MCStreamer &Out) { - MCInst Inst; - unsigned ErrorInfo; - if (MatchInstructionImpl(Operands, Inst, ErrorInfo) == Match_Success) { - Out.EmitInstruction(Inst); - return false; - } - - // FIXME: We should give nicer diagnostics about the exact failure. - Error(IDLoc, "unrecognized instruction"); - return true; - } + MCStreamer &Out); /// @name Auto-generated Match Functions /// { @@ -109,101 +67,76 @@ public: virtual bool ParseDirective(AsmToken DirectiveID); }; - + /// MBlazeOperand - Instances of this class represent a parsed MBlaze machine /// instruction. struct MBlazeOperand : public MCParsedAsmOperand { -private: - MBlazeOperand() {} -public: enum KindTy { - CondCode, + Token, Immediate, - Memory, Register, - Token + Memory, + Fsl } Kind; SMLoc StartLoc, EndLoc; union { struct { - MBlazeCC::CC Val; - } CC; - - struct { const char *Data; unsigned Length; } Tok; struct { unsigned RegNum; - bool Writeback; } Reg; struct { const MCExpr *Val; } Imm; - - // This is for all forms of MBlaze address expressions + struct { - unsigned BaseRegNum; - unsigned OffsetRegNum; // used when OffsetIsReg is true - const MCExpr *Offset; // used when OffsetIsReg is false - const MCExpr *ShiftAmount; // used when OffsetRegShifted is true - enum ShiftType ShiftType; // used when OffsetRegShifted is true - unsigned - OffsetRegShifted : 1, // only used when OffsetIsReg is true - Preindexed : 1, - Postindexed : 1, - OffsetIsReg : 1, - Negative : 1, // only used when OffsetIsReg is true - Writeback : 1; + unsigned Base; + unsigned OffReg; + const MCExpr *Off; } Mem; + struct { + const MCExpr *Val; + } FslImm; }; - - //MBlazeOperand(KindTy K, SMLoc S, SMLoc E) - // : Kind(K), StartLoc(S), EndLoc(E) {} - + + MBlazeOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} +public: MBlazeOperand(const MBlazeOperand &o) : MCParsedAsmOperand() { Kind = o.Kind; StartLoc = o.StartLoc; EndLoc = o.EndLoc; switch (Kind) { - case CondCode: - CC = o.CC; - break; - case Token: - Tok = o.Tok; - break; case Register: Reg = o.Reg; break; case Immediate: Imm = o.Imm; break; + case Token: + Tok = o.Tok; + break; case Memory: Mem = o.Mem; break; + case Fsl: + FslImm = o.FslImm; + break; } } - + /// getStartLoc - Get the location of the first token of this operand. SMLoc getStartLoc() const { return StartLoc; } + /// getEndLoc - Get the location of the last token of this operand. SMLoc getEndLoc() const { return EndLoc; } - MBlazeCC::CC getCondCode() const { - assert(Kind == CondCode && "Invalid access!"); - return CC.Val; - } - - StringRef getToken() const { - assert(Kind == Token && "Invalid access!"); - return StringRef(Tok.Data, Tok.Length); - } - unsigned getReg() const { assert(Kind == Register && "Invalid access!"); return Reg.RegNum; @@ -214,29 +147,42 @@ public: return Imm.Val; } - bool isCondCode() const { return Kind == CondCode; } + const MCExpr *getFslImm() const { + assert(Kind == Fsl && "Invalid access!"); + return FslImm.Val; + } - bool isImm() const { return Kind == Immediate; } + unsigned getMemBase() const { + assert(Kind == Memory && "Invalid access!"); + return Mem.Base; + } - bool isReg() const { return Kind == Register; } + const MCExpr* getMemOff() const { + assert(Kind == Memory && "Invalid access!"); + return Mem.Off; + } + + unsigned getMemOffReg() const { + assert(Kind == Memory && "Invalid access!"); + return Mem.OffReg; + } - bool isToken() const {return Kind == Token; } + bool isToken() const { return Kind == Token; } + bool isImm() const { return Kind == Immediate; } + bool isMem() const { return Kind == Memory; } + bool isFsl() const { return Kind == Fsl; } + bool isReg() const { return Kind == Register; } void addExpr(MCInst &Inst, const MCExpr *Expr) const { - // Add as immediates when possible. - if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) + // Add as immediates when possible. Null MCExpr = 0. + if (Expr == 0) + Inst.addOperand(MCOperand::CreateImm(0)); + else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) Inst.addOperand(MCOperand::CreateImm(CE->getValue())); else Inst.addOperand(MCOperand::CreateExpr(Expr)); } - void addCondCodeOperands(MCInst &Inst, unsigned N) const { - assert(N == 2 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode()))); - // FIXME: What belongs here? - Inst.addOperand(MCOperand::CreateReg(0)); - } - void addRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateReg(getReg())); @@ -247,71 +193,83 @@ public: addExpr(Inst, getImm()); } - virtual void dump(raw_ostream &OS) const; + void addFslOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + addExpr(Inst, getFslImm()); + } - static void CreateCondCode(OwningPtr<MBlazeOperand> &Op, MBlazeCC::CC CC, - SMLoc S) { - Op.reset(new MBlazeOperand); - Op->Kind = CondCode; - Op->CC.Val = CC; - Op->StartLoc = S; - Op->EndLoc = S; + void addMemOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + + unsigned RegOff = getMemOffReg(); + if (RegOff) + Inst.addOperand(MCOperand::CreateReg(RegOff)); + else + addExpr(Inst, getMemOff()); + + Inst.addOperand(MCOperand::CreateReg(getMemBase())); + } + + StringRef getToken() const { + assert(Kind == Token && "Invalid access!"); + return StringRef(Tok.Data, Tok.Length); } - static void CreateToken(OwningPtr<MBlazeOperand> &Op, StringRef Str, - SMLoc S) { - Op.reset(new MBlazeOperand); - Op->Kind = Token; + virtual void dump(raw_ostream &OS) const; + + static MBlazeOperand *CreateToken(StringRef Str, SMLoc S) { + MBlazeOperand *Op = new MBlazeOperand(Token); Op->Tok.Data = Str.data(); Op->Tok.Length = Str.size(); Op->StartLoc = S; Op->EndLoc = S; + return Op; } - static void CreateReg(OwningPtr<MBlazeOperand> &Op, unsigned RegNum, - bool Writeback, SMLoc S, SMLoc E) { - Op.reset(new MBlazeOperand); - Op->Kind = Register; + static MBlazeOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) { + MBlazeOperand *Op = new MBlazeOperand(Register); Op->Reg.RegNum = RegNum; - Op->Reg.Writeback = Writeback; - Op->StartLoc = S; Op->EndLoc = E; + return Op; + } + + static MBlazeOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) { + MBlazeOperand *Op = new MBlazeOperand(Immediate); + Op->Imm.Val = Val; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; } - static void CreateImm(OwningPtr<MBlazeOperand> &Op, const MCExpr *Val, - SMLoc S, SMLoc E) { - Op.reset(new MBlazeOperand); - Op->Kind = Immediate; + static MBlazeOperand *CreateFslImm(const MCExpr *Val, SMLoc S, SMLoc E) { + MBlazeOperand *Op = new MBlazeOperand(Fsl); Op->Imm.Val = Val; - Op->StartLoc = S; Op->EndLoc = E; + return Op; + } + + static MBlazeOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S, + SMLoc E) { + MBlazeOperand *Op = new MBlazeOperand(Memory); + Op->Mem.Base = Base; + Op->Mem.Off = Off; + Op->Mem.OffReg = 0; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; } - static void CreateMem(OwningPtr<MBlazeOperand> &Op, - unsigned BaseRegNum, bool OffsetIsReg, - const MCExpr *Offset, unsigned OffsetRegNum, - bool OffsetRegShifted, enum ShiftType ShiftType, - const MCExpr *ShiftAmount, bool Preindexed, - bool Postindexed, bool Negative, bool Writeback, - SMLoc S, SMLoc E) { - Op.reset(new MBlazeOperand); - Op->Kind = Memory; - Op->Mem.BaseRegNum = BaseRegNum; - Op->Mem.OffsetIsReg = OffsetIsReg; - Op->Mem.Offset = Offset; - Op->Mem.OffsetRegNum = OffsetRegNum; - Op->Mem.OffsetRegShifted = OffsetRegShifted; - Op->Mem.ShiftType = ShiftType; - Op->Mem.ShiftAmount = ShiftAmount; - Op->Mem.Preindexed = Preindexed; - Op->Mem.Postindexed = Postindexed; - Op->Mem.Negative = Negative; - Op->Mem.Writeback = Writeback; - + static MBlazeOperand *CreateMem(unsigned Base, unsigned Off, SMLoc S, + SMLoc E) { + MBlazeOperand *Op = new MBlazeOperand(Memory); + Op->Mem.Base = Base; + Op->Mem.OffReg = Off; + Op->Mem.Off = 0; Op->StartLoc = S; Op->EndLoc = E; + return Op; } }; @@ -319,21 +277,21 @@ public: void MBlazeOperand::dump(raw_ostream &OS) const { switch (Kind) { - case CondCode: - OS << MBlazeCCToString(getCondCode()); - break; case Immediate: getImm()->print(OS); break; - case Memory: - OS << "<memory>"; - break; case Register: OS << "<register " << getReg() << ">"; break; case Token: OS << "'" << getToken() << "'"; break; + case Memory: + OS << "MEMORY"; + break; + case Fsl: + getFslImm()->print(OS); + break; } } @@ -343,487 +301,210 @@ void MBlazeOperand::dump(raw_ostream &OS) const { 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 a Reg operand is created, the token is eaten -/// and false is returned. Else true is returned and no token is eaten. -/// TODO this is likely to change to allow different register types and or to -/// parse for a specific register type. -bool MBlazeAsmParser::MaybeParseRegister - (OwningPtr<MBlazeOperand> &Op, bool ParseWriteBack) { - SMLoc S, E; - 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 true; - - S = Tok.getLoc(); - - Parser.Lex(); // Eat identifier token. - - 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 +// +bool MBlazeAsmParser:: +MatchAndEmitInstruction(SMLoc IDLoc, + SmallVectorImpl<MCParsedAsmOperand*> &Operands, + MCStreamer &Out) { + MCInst Inst; + SMLoc ErrorLoc; + unsigned ErrorInfo; + + switch (MatchInstructionImpl(Operands, Inst, ErrorInfo)) { + case Match_Success: + Out.EmitInstruction(Inst); + return false; + case Match_MissingFeature: + return Error(IDLoc, "instruction use requires an option to be enabled"); + case Match_MnemonicFail: + return Error(IDLoc, "unrecognized instruction mnemonic"); + case Match_InvalidOperand: + ErrorLoc = IDLoc; + if (ErrorInfo != ~0U) { + if (ErrorInfo >= Operands.size()) + return Error(IDLoc, "too few operands for instruction"); + + ErrorLoc = ((MBlazeOperand*)Operands[ErrorInfo])->getStartLoc(); + if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc; } - } - MBlazeOperand::CreateReg(Op, RegNum, Writeback, S, E); + return Error(ErrorLoc, "invalid operand for instruction"); + } - return false; + llvm_unreachable("Implement any new match types added!"); + return true; } -/// Parse a register list, return false if successful else return true or an -/// error. The first token must be a '{' when called. -bool MBlazeAsmParser::ParseRegisterList(OwningPtr<MBlazeOperand> &Op) { - SMLoc S, E; - assert(Parser.getTok().is(AsmToken::LCurly) && - "Token is not an Left Curly Brace"); - S = Parser.getTok().getLoc(); - Parser.Lex(); // Eat left curly brace token. - - const AsmToken &RegTok = Parser.getTok(); - SMLoc RegLoc = RegTok.getLoc(); - if (RegTok.isNot(AsmToken::Identifier)) - return Error(RegLoc, "register expected"); - int RegNum = MatchRegisterName(RegTok.getString()); - if (RegNum == -1) - return Error(RegLoc, "register expected"); - Parser.Lex(); // Eat identifier token. - unsigned RegList = 1 << RegNum; - - int HighRegNum = RegNum; - // TODO ranges like "{Rn-Rm}" - while (Parser.getTok().is(AsmToken::Comma)) { - Parser.Lex(); // Eat comma token. - - const AsmToken &RegTok = Parser.getTok(); - SMLoc RegLoc = RegTok.getLoc(); - if (RegTok.isNot(AsmToken::Identifier)) - return Error(RegLoc, "register expected"); - int RegNum = MatchRegisterName(RegTok.getString()); - if (RegNum == -1) - return Error(RegLoc, "register expected"); - - if (RegList & (1 << RegNum)) - Warning(RegLoc, "register duplicated in register list"); - else if (RegNum <= HighRegNum) - 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)) - return Error(RCurlyTok.getLoc(), "'}' expected"); - E = RCurlyTok.getLoc(); - Parser.Lex(); // Eat left curly brace token. +MBlazeOperand *MBlazeAsmParser:: +ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { + if (Operands.size() != 4) + return 0; - return false; -} + MBlazeOperand &Base = *(MBlazeOperand*)Operands[2]; + MBlazeOperand &Offset = *(MBlazeOperand*)Operands[3]; -/// Parse an arm memory expression, return false if successful else return true -/// or an error. The first token must be a '[' when called. -/// TODO Only preindexing and postindexing addressing are started, unindexed -/// with option, etc are still to do. -bool MBlazeAsmParser::ParseMemory(OwningPtr<MBlazeOperand> &Op) { - SMLoc S, E; - assert(Parser.getTok().is(AsmToken::LBrac) && - "Token is not an Left Bracket"); - S = Parser.getTok().getLoc(); - Parser.Lex(); // Eat left bracket token. - - const AsmToken &BaseRegTok = Parser.getTok(); - if (BaseRegTok.isNot(AsmToken::Identifier)) - return Error(BaseRegTok.getLoc(), "register expected"); - if (MaybeParseRegister(Op, false)) - return Error(BaseRegTok.getLoc(), "register expected"); - int BaseRegNum = Op->getReg(); - - bool Preindexed = false; - bool Postindexed = false; - bool OffsetIsReg = false; - bool Negative = false; - bool Writeback = false; - - // First look for preindexed address forms, that is after the "[Rn" we now - // have to see if the next token is a comma. - const AsmToken &Tok = Parser.getTok(); - if (Tok.is(AsmToken::Comma)) { - Preindexed = true; - Parser.Lex(); // Eat comma token. - int OffsetRegNum; - bool OffsetRegShifted; - enum ShiftType ShiftType; - const MCExpr *ShiftAmount; - const MCExpr *Offset; - if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount, - Offset, OffsetIsReg, OffsetRegNum, E)) - return true; - const AsmToken &RBracTok = Parser.getTok(); - if (RBracTok.isNot(AsmToken::RBrac)) - return Error(RBracTok.getLoc(), "']' expected"); - E = RBracTok.getLoc(); - Parser.Lex(); // Eat right bracket token. - - const AsmToken &ExclaimTok = Parser.getTok(); - if (ExclaimTok.is(AsmToken::Exclaim)) { - E = ExclaimTok.getLoc(); - Writeback = true; - Parser.Lex(); // Eat exclaim token - } - MBlazeOperand::CreateMem(Op, BaseRegNum, OffsetIsReg, Offset, OffsetRegNum, - OffsetRegShifted, ShiftType, ShiftAmount, - Preindexed, Postindexed, Negative, Writeback, S, E); - return false; + SMLoc S = Base.getStartLoc(); + SMLoc O = Offset.getStartLoc(); + SMLoc E = Offset.getEndLoc(); + + if (!Base.isReg()) { + Error(S, "base address must be a register"); + return 0; } - // The "[Rn" we have so far was not followed by a comma. - else if (Tok.is(AsmToken::RBrac)) { - // This is a post indexing addressing forms, that is a ']' follows after - // the "[Rn". - Postindexed = true; - Writeback = true; - E = Tok.getLoc(); - Parser.Lex(); // Eat right bracket token. - - int OffsetRegNum = 0; - bool OffsetRegShifted = false; - enum ShiftType ShiftType; - const MCExpr *ShiftAmount; - const MCExpr *Offset; - - const AsmToken &NextTok = Parser.getTok(); - if (NextTok.isNot(AsmToken::EndOfStatement)) { - if (NextTok.isNot(AsmToken::Comma)) - return Error(NextTok.getLoc(), "',' expected"); - Parser.Lex(); // Eat comma token. - if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, - ShiftAmount, Offset, OffsetIsReg, OffsetRegNum, - E)) - return true; - } - MBlazeOperand::CreateMem(Op, BaseRegNum, OffsetIsReg, Offset, OffsetRegNum, - OffsetRegShifted, ShiftType, ShiftAmount, - Preindexed, Postindexed, Negative, Writeback, S, E); - return false; + if (!Offset.isReg() && !Offset.isImm()) { + Error(O, "offset must be a register or immediate"); + return 0; } - return true; + MBlazeOperand *Op; + if (Offset.isReg()) + Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getReg(), S, E); + else + Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getImm(), S, E); + + delete Operands.pop_back_val(); + delete Operands.pop_back_val(); + Operands.push_back(Op); + + return Op; } -/// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn]," -/// we will parse the following (were +/- means that a plus or minus is -/// optional): -/// +/-Rm -/// +/-Rm, shift -/// #offset -/// we return false on success or an error otherwise. -bool MBlazeAsmParser::ParseMemoryOffsetReg(bool &Negative, - bool &OffsetRegShifted, - enum ShiftType &ShiftType, - const MCExpr *&ShiftAmount, - const MCExpr *&Offset, - bool &OffsetIsReg, - int &OffsetRegNum, - SMLoc &E) { - OwningPtr<MBlazeOperand> Op; - Negative = false; - OffsetRegShifted = false; - OffsetIsReg = false; - OffsetRegNum = -1; - const AsmToken &NextTok = Parser.getTok(); - E = NextTok.getLoc(); - if (NextTok.is(AsmToken::Plus)) - Parser.Lex(); // Eat plus token. - else if (NextTok.is(AsmToken::Minus)) { - Negative = true; - Parser.Lex(); // Eat minus token - } - // 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)) { - OffsetIsReg = !MaybeParseRegister(Op, false); - if (OffsetIsReg) { - E = Op->getEndLoc(); - OffsetRegNum = Op->getReg(); - } - } - // 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 - const AsmToken &Tok = Parser.getTok(); - if (Tok.is(AsmToken::Comma)) { - Parser.Lex(); // Eat comma token. - - const AsmToken &Tok = Parser.getTok(); - if (ParseShift(ShiftType, ShiftAmount, E)) - return Error(Tok.getLoc(), "shift expected"); - OffsetRegShifted = true; - } - } - else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm" - // Look for #offset following the "[Rn," or "[Rn]," - const AsmToken &HashTok = Parser.getTok(); - if (HashTok.isNot(AsmToken::Hash)) - return Error(HashTok.getLoc(), "'#' expected"); - - Parser.Lex(); // Eat hash token. - - if (getParser().ParseExpression(Offset)) - return true; - E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); +MBlazeOperand *MBlazeAsmParser::ParseRegister() { + SMLoc S = Parser.getTok().getLoc(); + SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + + switch (getLexer().getKind()) { + default: return 0; + case AsmToken::Identifier: + unsigned RegNo = MatchRegisterName(getLexer().getTok().getIdentifier()); + if (RegNo == 0) + return 0; + + return MBlazeOperand::CreateReg(RegNo, S, E); } - return false; } -/// ParseShift as one of these two: -/// ( lsl | lsr | asr | ror ) , # shift_amount -/// rrx -/// and returns true if it parses a shift otherwise it returns false. -bool MBlazeAsmParser::ParseShift(ShiftType &St, - const MCExpr *&ShiftAmount, - SMLoc &E) { - const AsmToken &Tok = Parser.getTok(); - if (Tok.isNot(AsmToken::Identifier)) - return true; - StringRef ShiftName = Tok.getString(); - if (ShiftName == "lsl" || ShiftName == "LSL") - St = Lsl; - else if (ShiftName == "lsr" || ShiftName == "LSR") - St = Lsr; - else if (ShiftName == "asr" || ShiftName == "ASR") - St = Asr; - else if (ShiftName == "ror" || ShiftName == "ROR") - St = Ror; - else if (ShiftName == "rrx" || ShiftName == "RRX") - St = Rrx; - else - return true; - Parser.Lex(); // Eat shift type token. +static unsigned MatchFslRegister(const StringRef &String) { + if (!String.startswith("rfsl")) + return -1; - // Rrx stands alone. - if (St == Rrx) - return false; + unsigned regNum; + if (String.substr(4).getAsInteger(10,regNum)) + return -1; - // Otherwise, there must be a '#' and a shift amount. - const AsmToken &HashTok = Parser.getTok(); - if (HashTok.isNot(AsmToken::Hash)) - return Error(HashTok.getLoc(), "'#' expected"); - Parser.Lex(); // Eat hash token. + return regNum; +} - if (getParser().ParseExpression(ShiftAmount)) - return true; +MBlazeOperand *MBlazeAsmParser::ParseFsl() { + SMLoc S = Parser.getTok().getLoc(); + SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - return false; + switch (getLexer().getKind()) { + default: return 0; + case AsmToken::Identifier: + unsigned reg = MatchFslRegister(getLexer().getTok().getIdentifier()); + if (reg >= 16) + return 0; + + const MCExpr *EVal = MCConstantExpr::Create(reg,getContext()); + return MBlazeOperand::CreateFslImm(EVal,S,E); + } } -/// Parse a arm instruction operand. For now this parses the operand regardless -/// of the mnemonic. -bool MBlazeAsmParser::ParseOperand(OwningPtr<MBlazeOperand> &Op) { - SMLoc S, E; - +MBlazeOperand *MBlazeAsmParser::ParseImmediate() { + SMLoc S = Parser.getTok().getLoc(); + SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + + const MCExpr *EVal; switch (getLexer().getKind()) { + default: return 0; + case AsmToken::LParen: + case AsmToken::Plus: + case AsmToken::Minus: + case AsmToken::Integer: case AsmToken::Identifier: - if (!MaybeParseRegister(Op, true)) - return false; - // This was not a register so parse other operands that start with an - // identifier (like labels) as expressions and create them as immediates. - const MCExpr *IdVal; - S = Parser.getTok().getLoc(); - if (getParser().ParseExpression(IdVal)) - return true; - E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - MBlazeOperand::CreateImm(Op, IdVal, S, E); - return false; - case AsmToken::LBrac: - return ParseMemory(Op); - case AsmToken::LCurly: - return ParseRegisterList(Op); - case AsmToken::Hash: - // #42 -> immediate. - // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate - S = Parser.getTok().getLoc(); - Parser.Lex(); - const MCExpr *ImmVal; - if (getParser().ParseExpression(ImmVal)) - return true; - E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - MBlazeOperand::CreateImm(Op, ImmVal, S, E); - return false; - default: - return Error(Parser.getTok().getLoc(), "unexpected token in operand"); + if (getParser().ParseExpression(EVal)) + return 0; + + return MBlazeOperand::CreateImm(EVal, S, E); } } -/// Parse an mblaze instruction mnemonic followed by its operands. -bool MBlazeAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc, - SmallVectorImpl<MCParsedAsmOperand*> &Operands) { - OwningPtr<MBlazeOperand> Op; - - // Create the leading tokens for the mnemonic, split by '.' characters. - size_t Start = 0, Next = Name.find('.'); - StringRef Head = Name.slice(Start, Next); - - // Determine the predicate, if any. - // - // FIXME: We need a way to check whether a prefix supports predication, - // otherwise we will end up with an ambiguity for instructions that happen to - // end with a predicate name. - unsigned CC = StringSwitch<unsigned>(Head.substr(Head.size()-2)) - .Case("eq", MBlazeCC::EQ) - .Case("ne", MBlazeCC::NE) - .Case("gt", MBlazeCC::GT) - .Case("lt", MBlazeCC::LT) - .Case("ge", MBlazeCC::GE) - .Case("le", MBlazeCC::LE) - .Default(~0U); - if (CC != ~0U) { - Head = Head.slice(0, Head.size() - 2); - } else - CC = MBlazeCC::EQ; - - MBlazeOperand::CreateToken(Op, Head, NameLoc); - Operands.push_back(Op.take()); - - MBlazeOperand::CreateCondCode(Op, MBlazeCC::CC(CC), NameLoc); - Operands.push_back(Op.take()); - - // Add the remaining tokens in the mnemonic. - while (Next != StringRef::npos) { - Start = Next; - Next = Name.find('.', Start + 1); - Head = Name.slice(Start, Next); - - MBlazeOperand::CreateToken(Op, Head, NameLoc); - Operands.push_back(Op.take()); - } +MBlazeOperand *MBlazeAsmParser:: +ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { + MBlazeOperand *Op; - // Read the remaining operands. - if (getLexer().isNot(AsmToken::EndOfStatement)) { - // Read the first operand. - OwningPtr<MBlazeOperand> Op; - if (ParseOperand(Op)) { - Parser.EatToEndOfStatement(); - return true; - } - Operands.push_back(Op.take()); + // Attempt to parse the next token as a register name + Op = ParseRegister(); - while (getLexer().is(AsmToken::Comma)) { - Parser.Lex(); // Eat the comma. + // Attempt to parse the next token as an FSL immediate + if (!Op) + Op = ParseFsl(); - // Parse and remember the operand. - if (ParseOperand(Op)) { - Parser.EatToEndOfStatement(); - return true; - } - Operands.push_back(Op.take()); - } - } - - if (getLexer().isNot(AsmToken::EndOfStatement)) { - Parser.EatToEndOfStatement(); - return TokError("unexpected token in argument list"); - } - Parser.Lex(); // Consume the EndOfStatement - return false; -} + // Attempt to parse the next token as an immediate + if (!Op) + Op = ParseImmediate(); -/// ParseDirective parses the arm specific directives -bool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) { - StringRef IDVal = DirectiveID.getIdentifier(); - if (IDVal == ".word") - return ParseDirectiveWord(4, DirectiveID.getLoc()); - else if (IDVal == ".code") - return ParseDirectiveCode(DirectiveID.getLoc()); - else if (IDVal == ".syntax") - return ParseDirectiveSyntax(DirectiveID.getLoc()); - return true; -} + // Move past the parsed token in the token stream + getLexer().Lex(); -/// ParseDirectiveWord -/// ::= .word [ expression (, expression)* ] -bool MBlazeAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { - if (getLexer().isNot(AsmToken::EndOfStatement)) { - for (;;) { - const MCExpr *Value; - if (getParser().ParseExpression(Value)) - return true; - - getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/); - - if (getLexer().is(AsmToken::EndOfStatement)) - break; - - // FIXME: Improve diagnostic. - if (getLexer().isNot(AsmToken::Comma)) - return Error(L, "unexpected token in directive"); - Parser.Lex(); - } + // If the token could not be parsed then fail + if (!Op) { + Error(Parser.getTok().getLoc(), "unknown operand"); + return 0; } - Parser.Lex(); - return false; + // Push the parsed operand into the list of operands + Operands.push_back(Op); + return Op; } -/// ParseDirectiveSyntax -/// ::= .syntax unified | divided -bool MBlazeAsmParser::ParseDirectiveSyntax(SMLoc L) { - const AsmToken &Tok = Parser.getTok(); - if (Tok.isNot(AsmToken::Identifier)) - return Error(L, "unexpected token in .syntax directive"); - StringRef Mode = Tok.getString(); - if (Mode == "unified" || Mode == "UNIFIED") - Parser.Lex(); - else if (Mode == "divided" || Mode == "DIVIDED") - Parser.Lex(); - else - return Error(L, "unrecognized syntax mode in .syntax directive"); +/// Parse an mblaze instruction mnemonic followed by its operands. +bool MBlazeAsmParser:: +ParseInstruction(StringRef Name, SMLoc NameLoc, + SmallVectorImpl<MCParsedAsmOperand*> &Operands) { + // The first operand is the token for the instruction name + Operands.push_back(MBlazeOperand::CreateToken(Name, NameLoc)); + + // If there are no more operands then finish + if (getLexer().is(AsmToken::EndOfStatement)) + return false; - if (getLexer().isNot(AsmToken::EndOfStatement)) - return Error(Parser.getTok().getLoc(), "unexpected token in directive"); - Parser.Lex(); + // Parse the first operand + if (ParseOperand(Operands)) + return true; - // TODO tell the MC streamer the mode - // getParser().getStreamer().Emit???(); - return false; -} + while (getLexer().isNot(AsmToken::EndOfStatement) && + getLexer().is(AsmToken::Comma)) { + // Make sure there is a comma separating operands + // if (getLexer().isNot(AsmToken::Comma)) + // return false; -/// ParseDirectiveCode -/// ::= .code 16 | 32 -bool MBlazeAsmParser::ParseDirectiveCode(SMLoc L) { - const AsmToken &Tok = Parser.getTok(); - if (Tok.isNot(AsmToken::Integer)) - return Error(L, "unexpected token in .code directive"); - int64_t Val = Parser.getTok().getIntVal(); - if (Val == 16) - Parser.Lex(); - else if (Val == 32) - Parser.Lex(); - else - return Error(L, "invalid operand to .code directive"); + // Consume the comma token + getLexer().Lex(); + + // Parse the next operand + if (ParseOperand(Operands)) + return true; + } - if (getLexer().isNot(AsmToken::EndOfStatement)) - return Error(Parser.getTok().getLoc(), "unexpected token in directive"); - Parser.Lex(); + // If the instruction requires a memory operand then we need to + // replace the last two operands (base+offset) with a single + // memory operand. + if (Name.startswith("lw") || Name.startswith("sw") || + Name.startswith("lh") || Name.startswith("sh") || + Name.startswith("lb") || Name.startswith("sb")) + return ParseMemory(Operands); - // TODO tell the MC streamer the mode - // getParser().getStreamer().Emit???(); return false; } +/// ParseDirective parses the arm specific directives +bool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) { + return true; +} + extern "C" void LLVMInitializeMBlazeAsmLexer(); /// Force static initialization. |