1 //===-- MBlazeAsmParser.cpp - Parse MBlaze asm 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 //===----------------------------------------------------------------------===//
10 #include "MCTargetDesc/MBlazeBaseInfo.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/SmallVector.h"
13 #include "llvm/ADT/Twine.h"
14 #include "llvm/MC/MCExpr.h"
15 #include "llvm/MC/MCInst.h"
16 #include "llvm/MC/MCParser/MCAsmLexer.h"
17 #include "llvm/MC/MCParser/MCAsmParser.h"
18 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
19 #include "llvm/MC/MCStreamer.h"
20 #include "llvm/MC/MCTargetAsmParser.h"
21 #include "llvm/Support/SourceMgr.h"
22 #include "llvm/Support/TargetRegistry.h"
23 #include "llvm/Support/raw_ostream.h"
29 class MBlazeAsmParser : public MCTargetAsmParser {
32 MCAsmParser &getParser() const { return Parser; }
33 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
35 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
36 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
38 MBlazeOperand *ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
39 MBlazeOperand *ParseRegister();
40 MBlazeOperand *ParseRegister(SMLoc &StartLoc, SMLoc &EndLoc);
41 MBlazeOperand *ParseImmediate();
42 MBlazeOperand *ParseFsl();
43 MBlazeOperand* ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
45 virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
47 bool ParseDirectiveWord(unsigned Size, SMLoc L);
49 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
50 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
51 MCStreamer &Out, unsigned &ErrorInfo,
52 bool MatchingInlineAsm);
54 /// @name Auto-generated Match Functions
57 #define GET_ASSEMBLER_HEADER
58 #include "MBlazeGenAsmMatcher.inc"
63 MBlazeAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
64 : MCTargetAsmParser(), Parser(_Parser) {}
66 virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
68 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
70 virtual bool ParseDirective(AsmToken DirectiveID);
73 /// MBlazeOperand - Instances of this class represent a parsed MBlaze machine
75 struct MBlazeOperand : public MCParsedAsmOperand {
84 SMLoc StartLoc, EndLoc;
114 struct FslImmOp FslImm;
117 MBlazeOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
119 MBlazeOperand(const MBlazeOperand &o) : MCParsedAsmOperand() {
121 StartLoc = o.StartLoc;
142 /// getStartLoc - Get the location of the first token of this operand.
143 SMLoc getStartLoc() const { return StartLoc; }
145 /// getEndLoc - Get the location of the last token of this operand.
146 SMLoc getEndLoc() const { return EndLoc; }
148 unsigned getReg() const {
149 assert(Kind == Register && "Invalid access!");
153 const MCExpr *getImm() const {
154 assert(Kind == Immediate && "Invalid access!");
158 const MCExpr *getFslImm() const {
159 assert(Kind == Fsl && "Invalid access!");
163 unsigned getMemBase() const {
164 assert(Kind == Memory && "Invalid access!");
168 const MCExpr* getMemOff() const {
169 assert(Kind == Memory && "Invalid access!");
173 unsigned getMemOffReg() const {
174 assert(Kind == Memory && "Invalid access!");
178 bool isToken() const { return Kind == Token; }
179 bool isImm() const { return Kind == Immediate; }
180 bool isMem() const { return Kind == Memory; }
181 bool isFsl() const { return Kind == Fsl; }
182 bool isReg() const { return Kind == Register; }
184 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
185 // Add as immediates when possible. Null MCExpr = 0.
187 Inst.addOperand(MCOperand::CreateImm(0));
188 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
189 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
191 Inst.addOperand(MCOperand::CreateExpr(Expr));
194 void addRegOperands(MCInst &Inst, unsigned N) const {
195 assert(N == 1 && "Invalid number of operands!");
196 Inst.addOperand(MCOperand::CreateReg(getReg()));
199 void addImmOperands(MCInst &Inst, unsigned N) const {
200 assert(N == 1 && "Invalid number of operands!");
201 addExpr(Inst, getImm());
204 void addFslOperands(MCInst &Inst, unsigned N) const {
205 assert(N == 1 && "Invalid number of operands!");
206 addExpr(Inst, getFslImm());
209 void addMemOperands(MCInst &Inst, unsigned N) const {
210 assert(N == 2 && "Invalid number of operands!");
212 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
214 unsigned RegOff = getMemOffReg();
216 Inst.addOperand(MCOperand::CreateReg(RegOff));
218 addExpr(Inst, getMemOff());
221 StringRef getToken() const {
222 assert(Kind == Token && "Invalid access!");
223 return StringRef(Tok.Data, Tok.Length);
226 virtual void print(raw_ostream &OS) const;
228 static MBlazeOperand *CreateToken(StringRef Str, SMLoc S) {
229 MBlazeOperand *Op = new MBlazeOperand(Token);
230 Op->Tok.Data = Str.data();
231 Op->Tok.Length = Str.size();
237 static MBlazeOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
238 MBlazeOperand *Op = new MBlazeOperand(Register);
239 Op->Reg.RegNum = RegNum;
245 static MBlazeOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
246 MBlazeOperand *Op = new MBlazeOperand(Immediate);
253 static MBlazeOperand *CreateFslImm(const MCExpr *Val, SMLoc S, SMLoc E) {
254 MBlazeOperand *Op = new MBlazeOperand(Fsl);
261 static MBlazeOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S,
263 MBlazeOperand *Op = new MBlazeOperand(Memory);
272 static MBlazeOperand *CreateMem(unsigned Base, unsigned Off, SMLoc S,
274 MBlazeOperand *Op = new MBlazeOperand(Memory);
276 Op->Mem.OffReg = Off;
284 } // end anonymous namespace.
286 void MBlazeOperand::print(raw_ostream &OS) const {
293 OS << getMBlazeRegisterNumbering(getReg()) << ">";
296 OS << "'" << getToken() << "'";
300 OS << getMBlazeRegisterNumbering(getMemBase());
303 unsigned RegOff = getMemOffReg();
305 OS << "R" << getMBlazeRegisterNumbering(RegOff);
312 getFslImm()->print(OS);
317 /// @name Auto-generated Match Functions
320 static unsigned MatchRegisterName(StringRef Name);
324 bool MBlazeAsmParser::
325 MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
326 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
327 MCStreamer &Out, unsigned &ErrorInfo,
328 bool MatchingInlineAsm) {
330 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo,
331 MatchingInlineAsm)) {
334 Out.EmitInstruction(Inst);
336 case Match_MissingFeature:
337 return Error(IDLoc, "instruction use requires an option to be enabled");
338 case Match_MnemonicFail:
339 return Error(IDLoc, "unrecognized instruction mnemonic");
340 case Match_InvalidOperand: {
341 SMLoc ErrorLoc = IDLoc;
342 if (ErrorInfo != ~0U) {
343 if (ErrorInfo >= Operands.size())
344 return Error(IDLoc, "too few operands for instruction");
346 ErrorLoc = ((MBlazeOperand*)Operands[ErrorInfo])->getStartLoc();
347 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
350 return Error(ErrorLoc, "invalid operand for instruction");
354 llvm_unreachable("Implement any new match types added!");
357 MBlazeOperand *MBlazeAsmParser::
358 ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
359 if (Operands.size() != 4)
362 MBlazeOperand &Base = *(MBlazeOperand*)Operands[2];
363 MBlazeOperand &Offset = *(MBlazeOperand*)Operands[3];
365 SMLoc S = Base.getStartLoc();
366 SMLoc O = Offset.getStartLoc();
367 SMLoc E = Offset.getEndLoc();
370 Error(S, "base address must be a register");
374 if (!Offset.isReg() && !Offset.isImm()) {
375 Error(O, "offset must be a register or immediate");
381 Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getReg(), S, E);
383 Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getImm(), S, E);
385 delete Operands.pop_back_val();
386 delete Operands.pop_back_val();
387 Operands.push_back(Op);
392 bool MBlazeAsmParser::ParseRegister(unsigned &RegNo,
393 SMLoc &StartLoc, SMLoc &EndLoc) {
394 MBlazeOperand *Reg = ParseRegister(StartLoc, EndLoc);
397 RegNo = Reg->getReg();
401 MBlazeOperand *MBlazeAsmParser::ParseRegister() {
403 return ParseRegister(S, E);
406 MBlazeOperand *MBlazeAsmParser::ParseRegister(SMLoc &StartLoc, SMLoc &EndLoc) {
407 StartLoc = Parser.getTok().getLoc();
408 EndLoc = Parser.getTok().getEndLoc();
410 if (getLexer().getKind() != AsmToken::Identifier)
413 unsigned RegNo = MatchRegisterName(getLexer().getTok().getIdentifier());
418 return MBlazeOperand::CreateReg(RegNo, StartLoc, EndLoc);
421 static unsigned MatchFslRegister(StringRef String) {
422 if (!String.startswith("rfsl"))
426 if (String.substr(4).getAsInteger(10,regNum))
432 MBlazeOperand *MBlazeAsmParser::ParseFsl() {
433 SMLoc S = Parser.getTok().getLoc();
434 SMLoc E = Parser.getTok().getEndLoc();
436 switch (getLexer().getKind()) {
438 case AsmToken::Identifier:
439 unsigned reg = MatchFslRegister(getLexer().getTok().getIdentifier());
444 const MCExpr *EVal = MCConstantExpr::Create(reg,getContext());
445 return MBlazeOperand::CreateFslImm(EVal,S,E);
449 MBlazeOperand *MBlazeAsmParser::ParseImmediate() {
450 SMLoc S = Parser.getTok().getLoc();
451 SMLoc E = Parser.getTok().getEndLoc();
454 switch (getLexer().getKind()) {
456 case AsmToken::LParen:
458 case AsmToken::Minus:
459 case AsmToken::Integer:
460 case AsmToken::Identifier:
461 if (getParser().parseExpression(EVal))
464 return MBlazeOperand::CreateImm(EVal, S, E);
468 MBlazeOperand *MBlazeAsmParser::
469 ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
472 // Attempt to parse the next token as a register name
473 Op = ParseRegister();
475 // Attempt to parse the next token as an FSL immediate
479 // Attempt to parse the next token as an immediate
481 Op = ParseImmediate();
483 // If the token could not be parsed then fail
485 Error(Parser.getTok().getLoc(), "unknown operand");
489 // Push the parsed operand into the list of operands
490 Operands.push_back(Op);
494 /// Parse an mblaze instruction mnemonic followed by its operands.
495 bool MBlazeAsmParser::
496 ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
497 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
498 // The first operands is the token for the instruction name
499 size_t dotLoc = Name.find('.');
500 Operands.push_back(MBlazeOperand::CreateToken(Name.substr(0,dotLoc),NameLoc));
501 if (dotLoc < Name.size())
502 Operands.push_back(MBlazeOperand::CreateToken(Name.substr(dotLoc),NameLoc));
504 // If there are no more operands then finish
505 if (getLexer().is(AsmToken::EndOfStatement))
508 // Parse the first operand
509 if (!ParseOperand(Operands))
512 while (getLexer().isNot(AsmToken::EndOfStatement) &&
513 getLexer().is(AsmToken::Comma)) {
514 // Consume the comma token
517 // Parse the next operand
518 if (!ParseOperand(Operands))
522 // If the instruction requires a memory operand then we need to
523 // replace the last two operands (base+offset) with a single
525 if (Name.startswith("lw") || Name.startswith("sw") ||
526 Name.startswith("lh") || Name.startswith("sh") ||
527 Name.startswith("lb") || Name.startswith("sb"))
528 return (ParseMemory(Operands) == NULL);
533 /// ParseDirective parses the MBlaze specific directives
534 bool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) {
535 StringRef IDVal = DirectiveID.getIdentifier();
536 if (IDVal == ".word")
537 return ParseDirectiveWord(2, DirectiveID.getLoc());
541 /// ParseDirectiveWord
542 /// ::= .word [ expression (, expression)* ]
543 bool MBlazeAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
544 if (getLexer().isNot(AsmToken::EndOfStatement)) {
547 if (getParser().parseExpression(Value))
550 getParser().getStreamer().EmitValue(Value, Size);
552 if (getLexer().is(AsmToken::EndOfStatement))
555 // FIXME: Improve diagnostic.
556 if (getLexer().isNot(AsmToken::Comma))
557 return Error(L, "unexpected token in directive");
566 /// Force static initialization.
567 extern "C" void LLVMInitializeMBlazeAsmParser() {
568 RegisterMCAsmParser<MBlazeAsmParser> X(TheMBlazeTarget);
571 #define GET_REGISTER_MATCHER
572 #define GET_MATCHER_IMPLEMENTATION
573 #include "MBlazeGenAsmMatcher.inc"