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/SmallVector.h"
12 #include "llvm/ADT/Twine.h"
13 #include "llvm/MC/MCExpr.h"
14 #include "llvm/MC/MCInst.h"
15 #include "llvm/MC/MCParser/MCAsmLexer.h"
16 #include "llvm/MC/MCParser/MCAsmParser.h"
17 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
18 #include "llvm/MC/MCStreamer.h"
19 #include "llvm/MC/MCTargetAsmParser.h"
20 #include "llvm/Support/SourceMgr.h"
21 #include "llvm/Support/TargetRegistry.h"
22 #include "llvm/Support/raw_ostream.h"
28 class MBlazeAsmParser : public MCTargetAsmParser {
31 MCAsmParser &getParser() const { return Parser; }
32 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
34 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
35 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
37 MBlazeOperand *ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
38 MBlazeOperand *ParseRegister(unsigned &RegNo);
39 MBlazeOperand *ParseImmediate();
40 MBlazeOperand *ParseFsl();
41 MBlazeOperand* ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
43 virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
45 bool ParseDirectiveWord(unsigned Size, SMLoc L);
47 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
48 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
49 MCStreamer &Out, unsigned &ErrorInfo,
50 bool MatchingInlineAsm);
52 /// @name Auto-generated Match Functions
55 #define GET_ASSEMBLER_HEADER
56 #include "MBlazeGenAsmMatcher.inc"
61 MBlazeAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
62 : MCTargetAsmParser(), Parser(_Parser) {}
64 virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
66 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
68 virtual bool ParseDirective(AsmToken DirectiveID);
71 /// MBlazeOperand - Instances of this class represent a parsed MBlaze machine
73 struct MBlazeOperand : public MCParsedAsmOperand {
82 SMLoc StartLoc, EndLoc;
109 MBlazeOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
111 MBlazeOperand(const MBlazeOperand &o) : MCParsedAsmOperand() {
113 StartLoc = o.StartLoc;
134 /// getStartLoc - Get the location of the first token of this operand.
135 SMLoc getStartLoc() const { return StartLoc; }
137 /// getEndLoc - Get the location of the last token of this operand.
138 SMLoc getEndLoc() const { return EndLoc; }
140 unsigned getReg() const {
141 assert(Kind == Register && "Invalid access!");
145 const MCExpr *getImm() const {
146 assert(Kind == Immediate && "Invalid access!");
150 const MCExpr *getFslImm() const {
151 assert(Kind == Fsl && "Invalid access!");
155 unsigned getMemBase() const {
156 assert(Kind == Memory && "Invalid access!");
160 const MCExpr* getMemOff() const {
161 assert(Kind == Memory && "Invalid access!");
165 unsigned getMemOffReg() const {
166 assert(Kind == Memory && "Invalid access!");
170 bool isToken() const { return Kind == Token; }
171 bool isImm() const { return Kind == Immediate; }
172 bool isMem() const { return Kind == Memory; }
173 bool isFsl() const { return Kind == Fsl; }
174 bool isReg() const { return Kind == Register; }
176 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
177 // Add as immediates when possible. Null MCExpr = 0.
179 Inst.addOperand(MCOperand::CreateImm(0));
180 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
181 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
183 Inst.addOperand(MCOperand::CreateExpr(Expr));
186 void addRegOperands(MCInst &Inst, unsigned N) const {
187 assert(N == 1 && "Invalid number of operands!");
188 Inst.addOperand(MCOperand::CreateReg(getReg()));
191 void addImmOperands(MCInst &Inst, unsigned N) const {
192 assert(N == 1 && "Invalid number of operands!");
193 addExpr(Inst, getImm());
196 void addFslOperands(MCInst &Inst, unsigned N) const {
197 assert(N == 1 && "Invalid number of operands!");
198 addExpr(Inst, getFslImm());
201 void addMemOperands(MCInst &Inst, unsigned N) const {
202 assert(N == 2 && "Invalid number of operands!");
204 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
206 unsigned RegOff = getMemOffReg();
208 Inst.addOperand(MCOperand::CreateReg(RegOff));
210 addExpr(Inst, getMemOff());
213 StringRef getToken() const {
214 assert(Kind == Token && "Invalid access!");
215 return StringRef(Tok.Data, Tok.Length);
218 virtual void print(raw_ostream &OS) const;
220 static MBlazeOperand *CreateToken(StringRef Str, SMLoc S) {
221 MBlazeOperand *Op = new MBlazeOperand(Token);
222 Op->Tok.Data = Str.data();
223 Op->Tok.Length = Str.size();
229 static MBlazeOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
230 MBlazeOperand *Op = new MBlazeOperand(Register);
231 Op->Reg.RegNum = RegNum;
237 static MBlazeOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
238 MBlazeOperand *Op = new MBlazeOperand(Immediate);
245 static MBlazeOperand *CreateFslImm(const MCExpr *Val, SMLoc S, SMLoc E) {
246 MBlazeOperand *Op = new MBlazeOperand(Fsl);
253 static MBlazeOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S,
255 MBlazeOperand *Op = new MBlazeOperand(Memory);
264 static MBlazeOperand *CreateMem(unsigned Base, unsigned Off, SMLoc S,
266 MBlazeOperand *Op = new MBlazeOperand(Memory);
268 Op->Mem.OffReg = Off;
276 } // end anonymous namespace.
278 void MBlazeOperand::print(raw_ostream &OS) const {
285 OS << getMBlazeRegisterNumbering(getReg()) << ">";
288 OS << "'" << getToken() << "'";
292 OS << getMBlazeRegisterNumbering(getMemBase());
295 unsigned RegOff = getMemOffReg();
297 OS << "R" << getMBlazeRegisterNumbering(RegOff);
304 getFslImm()->print(OS);
309 /// @name Auto-generated Match Functions
312 static unsigned MatchRegisterName(StringRef Name);
316 bool MBlazeAsmParser::
317 MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
318 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
319 MCStreamer &Out, unsigned &ErrorInfo,
320 bool MatchingInlineAsm) {
322 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo,
323 MatchingInlineAsm)) {
326 Out.EmitInstruction(Inst);
328 case Match_MissingFeature:
329 return Error(IDLoc, "instruction use requires an option to be enabled");
330 case Match_MnemonicFail:
331 return Error(IDLoc, "unrecognized instruction mnemonic");
332 case Match_InvalidOperand: {
333 SMLoc ErrorLoc = IDLoc;
334 if (ErrorInfo != ~0U) {
335 if (ErrorInfo >= Operands.size())
336 return Error(IDLoc, "too few operands for instruction");
338 ErrorLoc = ((MBlazeOperand*)Operands[ErrorInfo])->getStartLoc();
339 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
342 return Error(ErrorLoc, "invalid operand for instruction");
346 llvm_unreachable("Implement any new match types added!");
349 MBlazeOperand *MBlazeAsmParser::
350 ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
351 if (Operands.size() != 4)
354 MBlazeOperand &Base = *(MBlazeOperand*)Operands[2];
355 MBlazeOperand &Offset = *(MBlazeOperand*)Operands[3];
357 SMLoc S = Base.getStartLoc();
358 SMLoc O = Offset.getStartLoc();
359 SMLoc E = Offset.getEndLoc();
362 Error(S, "base address must be a register");
366 if (!Offset.isReg() && !Offset.isImm()) {
367 Error(O, "offset must be a register or immediate");
373 Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getReg(), S, E);
375 Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getImm(), S, E);
377 delete Operands.pop_back_val();
378 delete Operands.pop_back_val();
379 Operands.push_back(Op);
384 bool MBlazeAsmParser::ParseRegister(unsigned &RegNo,
385 SMLoc &StartLoc, SMLoc &EndLoc) {
386 return (ParseRegister(RegNo) == 0);
389 MBlazeOperand *MBlazeAsmParser::ParseRegister(unsigned &RegNo) {
390 SMLoc S = Parser.getTok().getLoc();
391 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
393 switch (getLexer().getKind()) {
395 case AsmToken::Identifier:
396 RegNo = MatchRegisterName(getLexer().getTok().getIdentifier());
401 return MBlazeOperand::CreateReg(RegNo, S, E);
405 static unsigned MatchFslRegister(StringRef String) {
406 if (!String.startswith("rfsl"))
410 if (String.substr(4).getAsInteger(10,regNum))
416 MBlazeOperand *MBlazeAsmParser::ParseFsl() {
417 SMLoc S = Parser.getTok().getLoc();
418 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
420 switch (getLexer().getKind()) {
422 case AsmToken::Identifier:
423 unsigned reg = MatchFslRegister(getLexer().getTok().getIdentifier());
428 const MCExpr *EVal = MCConstantExpr::Create(reg,getContext());
429 return MBlazeOperand::CreateFslImm(EVal,S,E);
433 MBlazeOperand *MBlazeAsmParser::ParseImmediate() {
434 SMLoc S = Parser.getTok().getLoc();
435 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
438 switch (getLexer().getKind()) {
440 case AsmToken::LParen:
442 case AsmToken::Minus:
443 case AsmToken::Integer:
444 case AsmToken::Identifier:
445 if (getParser().ParseExpression(EVal))
448 return MBlazeOperand::CreateImm(EVal, S, E);
452 MBlazeOperand *MBlazeAsmParser::
453 ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
456 // Attempt to parse the next token as a register name
458 Op = ParseRegister(RegNo);
460 // Attempt to parse the next token as an FSL immediate
464 // Attempt to parse the next token as an immediate
466 Op = ParseImmediate();
468 // If the token could not be parsed then fail
470 Error(Parser.getTok().getLoc(), "unknown operand");
474 // Push the parsed operand into the list of operands
475 Operands.push_back(Op);
479 /// Parse an mblaze instruction mnemonic followed by its operands.
480 bool MBlazeAsmParser::
481 ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
482 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
483 // The first operands is the token for the instruction name
484 size_t dotLoc = Name.find('.');
485 Operands.push_back(MBlazeOperand::CreateToken(Name.substr(0,dotLoc),NameLoc));
486 if (dotLoc < Name.size())
487 Operands.push_back(MBlazeOperand::CreateToken(Name.substr(dotLoc),NameLoc));
489 // If there are no more operands then finish
490 if (getLexer().is(AsmToken::EndOfStatement))
493 // Parse the first operand
494 if (!ParseOperand(Operands))
497 while (getLexer().isNot(AsmToken::EndOfStatement) &&
498 getLexer().is(AsmToken::Comma)) {
499 // Consume the comma token
502 // Parse the next operand
503 if (!ParseOperand(Operands))
507 // If the instruction requires a memory operand then we need to
508 // replace the last two operands (base+offset) with a single
510 if (Name.startswith("lw") || Name.startswith("sw") ||
511 Name.startswith("lh") || Name.startswith("sh") ||
512 Name.startswith("lb") || Name.startswith("sb"))
513 return (ParseMemory(Operands) == NULL);
518 /// ParseDirective parses the MBlaze specific directives
519 bool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) {
520 StringRef IDVal = DirectiveID.getIdentifier();
521 if (IDVal == ".word")
522 return ParseDirectiveWord(2, DirectiveID.getLoc());
526 /// ParseDirectiveWord
527 /// ::= .word [ expression (, expression)* ]
528 bool MBlazeAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
529 if (getLexer().isNot(AsmToken::EndOfStatement)) {
532 if (getParser().ParseExpression(Value))
535 getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
537 if (getLexer().is(AsmToken::EndOfStatement))
540 // FIXME: Improve diagnostic.
541 if (getLexer().isNot(AsmToken::Comma))
542 return Error(L, "unexpected token in directive");
551 extern "C" void LLVMInitializeMBlazeAsmLexer();
553 /// Force static initialization.
554 extern "C" void LLVMInitializeMBlazeAsmParser() {
555 RegisterMCAsmParser<MBlazeAsmParser> X(TheMBlazeTarget);
556 LLVMInitializeMBlazeAsmLexer();
559 #define GET_REGISTER_MATCHER
560 #define GET_MATCHER_IMPLEMENTATION
561 #include "MBlazeGenAsmMatcher.inc"