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 //===----------------------------------------------------------------------===//
11 #include "MBlazeSubtarget.h"
12 #include "MBlazeISelLowering.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/MCStreamer.h"
17 #include "llvm/MC/MCExpr.h"
18 #include "llvm/MC/MCInst.h"
19 #include "llvm/Target/TargetRegistry.h"
20 #include "llvm/Target/TargetAsmParser.h"
21 #include "llvm/Support/SourceMgr.h"
22 #include "llvm/Support/raw_ostream.h"
23 #include "llvm/ADT/OwningPtr.h"
24 #include "llvm/ADT/SmallVector.h"
25 #include "llvm/ADT/StringSwitch.h"
26 #include "llvm/ADT/Twine.h"
32 class MBlazeAsmParser : public TargetAsmParser {
36 MCAsmParser &getParser() const { return Parser; }
37 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
39 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
40 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
42 MBlazeOperand *ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
43 MBlazeOperand *ParseRegister();
44 MBlazeOperand *ParseImmediate();
45 MBlazeOperand *ParseFsl();
46 MBlazeOperand* ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
48 bool MatchAndEmitInstruction(SMLoc IDLoc,
49 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
52 /// @name Auto-generated Match Functions
55 #define GET_ASSEMBLER_HEADER
56 #include "MBlazeGenAsmMatcher.inc"
62 MBlazeAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
63 : TargetAsmParser(T), Parser(_Parser), TM(_TM) {}
65 virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
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 unsigned RegOff = getMemOffReg();
206 Inst.addOperand(MCOperand::CreateReg(RegOff));
208 addExpr(Inst, getMemOff());
210 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
213 StringRef getToken() const {
214 assert(Kind == Token && "Invalid access!");
215 return StringRef(Tok.Data, Tok.Length);
218 virtual void dump(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::dump(raw_ostream &OS) const {
284 OS << "<register " << getReg() << ">";
287 OS << "'" << getToken() << "'";
293 getFslImm()->print(OS);
298 /// @name Auto-generated Match Functions
301 static unsigned MatchRegisterName(StringRef Name);
305 bool MBlazeAsmParser::
306 MatchAndEmitInstruction(SMLoc IDLoc,
307 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
313 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo)) {
315 Out.EmitInstruction(Inst);
317 case Match_MissingFeature:
318 return Error(IDLoc, "instruction use requires an option to be enabled");
319 case Match_MnemonicFail:
320 return Error(IDLoc, "unrecognized instruction mnemonic");
321 case Match_InvalidOperand:
323 if (ErrorInfo != ~0U) {
324 if (ErrorInfo >= Operands.size())
325 return Error(IDLoc, "too few operands for instruction");
327 ErrorLoc = ((MBlazeOperand*)Operands[ErrorInfo])->getStartLoc();
328 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
331 return Error(ErrorLoc, "invalid operand for instruction");
334 llvm_unreachable("Implement any new match types added!");
338 MBlazeOperand *MBlazeAsmParser::
339 ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
340 if (Operands.size() != 4)
343 MBlazeOperand &Base = *(MBlazeOperand*)Operands[2];
344 MBlazeOperand &Offset = *(MBlazeOperand*)Operands[3];
346 SMLoc S = Base.getStartLoc();
347 SMLoc O = Offset.getStartLoc();
348 SMLoc E = Offset.getEndLoc();
351 Error(S, "base address must be a register");
355 if (!Offset.isReg() && !Offset.isImm()) {
356 Error(O, "offset must be a register or immediate");
362 Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getReg(), S, E);
364 Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getImm(), S, E);
366 delete Operands.pop_back_val();
367 delete Operands.pop_back_val();
368 Operands.push_back(Op);
373 MBlazeOperand *MBlazeAsmParser::ParseRegister() {
374 SMLoc S = Parser.getTok().getLoc();
375 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
377 switch (getLexer().getKind()) {
379 case AsmToken::Identifier:
380 unsigned RegNo = MatchRegisterName(getLexer().getTok().getIdentifier());
384 return MBlazeOperand::CreateReg(RegNo, S, E);
388 static unsigned MatchFslRegister(const StringRef &String) {
389 if (!String.startswith("rfsl"))
393 if (String.substr(4).getAsInteger(10,regNum))
399 MBlazeOperand *MBlazeAsmParser::ParseFsl() {
400 SMLoc S = Parser.getTok().getLoc();
401 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
403 switch (getLexer().getKind()) {
405 case AsmToken::Identifier:
406 unsigned reg = MatchFslRegister(getLexer().getTok().getIdentifier());
410 const MCExpr *EVal = MCConstantExpr::Create(reg,getContext());
411 return MBlazeOperand::CreateFslImm(EVal,S,E);
415 MBlazeOperand *MBlazeAsmParser::ParseImmediate() {
416 SMLoc S = Parser.getTok().getLoc();
417 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
420 switch (getLexer().getKind()) {
422 case AsmToken::LParen:
424 case AsmToken::Minus:
425 case AsmToken::Integer:
426 case AsmToken::Identifier:
427 if (getParser().ParseExpression(EVal))
430 return MBlazeOperand::CreateImm(EVal, S, E);
434 MBlazeOperand *MBlazeAsmParser::
435 ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
438 // Attempt to parse the next token as a register name
439 Op = ParseRegister();
441 // Attempt to parse the next token as an FSL immediate
445 // Attempt to parse the next token as an immediate
447 Op = ParseImmediate();
449 // If the token could not be parsed then fail
451 Error(Parser.getTok().getLoc(), "unknown operand");
455 // Move past the parsed token in the token stream
458 // Push the parsed operand into the list of operands
459 Operands.push_back(Op);
463 /// Parse an mblaze instruction mnemonic followed by its operands.
464 bool MBlazeAsmParser::
465 ParseInstruction(StringRef Name, SMLoc NameLoc,
466 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
467 // The first operand is the token for the instruction name
468 Operands.push_back(MBlazeOperand::CreateToken(Name, NameLoc));
470 // If there are no more operands then finish
471 if (getLexer().is(AsmToken::EndOfStatement))
474 // Parse the first operand
475 if (!ParseOperand(Operands))
478 while (getLexer().isNot(AsmToken::EndOfStatement) &&
479 getLexer().is(AsmToken::Comma)) {
480 // Make sure there is a comma separating operands
481 // if (getLexer().isNot(AsmToken::Comma))
484 // Consume the comma token
487 // Parse the next operand
488 if (!ParseOperand(Operands))
492 // If the instruction requires a memory operand then we need to
493 // replace the last two operands (base+offset) with a single
495 if (Name.startswith("lw") || Name.startswith("sw") ||
496 Name.startswith("lh") || Name.startswith("sh") ||
497 Name.startswith("lb") || Name.startswith("sb"))
498 return ParseMemory(Operands);
503 /// ParseDirective parses the arm specific directives
504 bool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) {
508 extern "C" void LLVMInitializeMBlazeAsmLexer();
510 /// Force static initialization.
511 extern "C" void LLVMInitializeMBlazeAsmParser() {
512 RegisterAsmParser<MBlazeAsmParser> X(TheMBlazeTarget);
513 LLVMInitializeMBlazeAsmLexer();
516 #define GET_REGISTER_MATCHER
517 #define GET_MATCHER_IMPLEMENTATION
518 #include "MBlazeGenAsmMatcher.inc"