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/MC/MCParser/MCAsmLexer.h"
12 #include "llvm/MC/MCParser/MCAsmParser.h"
13 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
14 #include "llvm/MC/MCStreamer.h"
15 #include "llvm/MC/MCExpr.h"
16 #include "llvm/MC/MCInst.h"
17 #include "llvm/MC/MCTargetAsmParser.h"
18 #include "llvm/Target/TargetRegistry.h"
19 #include "llvm/Support/SourceMgr.h"
20 #include "llvm/Support/raw_ostream.h"
21 #include "llvm/ADT/OwningPtr.h"
22 #include "llvm/ADT/SmallVector.h"
23 #include "llvm/ADT/StringSwitch.h"
24 #include "llvm/ADT/Twine.h"
30 class MBlazeAsmParser : public MCTargetAsmParser {
33 MCAsmParser &getParser() const { return Parser; }
34 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
36 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
37 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
39 MBlazeOperand *ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
40 MBlazeOperand *ParseRegister(unsigned &RegNo);
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,
50 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
53 /// @name Auto-generated Match Functions
56 #define GET_ASSEMBLER_HEADER
57 #include "MBlazeGenAsmMatcher.inc"
63 MBlazeAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
64 : MCTargetAsmParser(), Parser(_Parser) {}
66 virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
67 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
69 virtual bool ParseDirective(AsmToken DirectiveID);
72 /// MBlazeOperand - Instances of this class represent a parsed MBlaze machine
74 struct MBlazeOperand : public MCParsedAsmOperand {
83 SMLoc StartLoc, EndLoc;
110 MBlazeOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
112 MBlazeOperand(const MBlazeOperand &o) : MCParsedAsmOperand() {
114 StartLoc = o.StartLoc;
135 /// getStartLoc - Get the location of the first token of this operand.
136 SMLoc getStartLoc() const { return StartLoc; }
138 /// getEndLoc - Get the location of the last token of this operand.
139 SMLoc getEndLoc() const { return EndLoc; }
141 unsigned getReg() const {
142 assert(Kind == Register && "Invalid access!");
146 const MCExpr *getImm() const {
147 assert(Kind == Immediate && "Invalid access!");
151 const MCExpr *getFslImm() const {
152 assert(Kind == Fsl && "Invalid access!");
156 unsigned getMemBase() const {
157 assert(Kind == Memory && "Invalid access!");
161 const MCExpr* getMemOff() const {
162 assert(Kind == Memory && "Invalid access!");
166 unsigned getMemOffReg() const {
167 assert(Kind == Memory && "Invalid access!");
171 bool isToken() const { return Kind == Token; }
172 bool isImm() const { return Kind == Immediate; }
173 bool isMem() const { return Kind == Memory; }
174 bool isFsl() const { return Kind == Fsl; }
175 bool isReg() const { return Kind == Register; }
177 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
178 // Add as immediates when possible. Null MCExpr = 0.
180 Inst.addOperand(MCOperand::CreateImm(0));
181 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
182 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
184 Inst.addOperand(MCOperand::CreateExpr(Expr));
187 void addRegOperands(MCInst &Inst, unsigned N) const {
188 assert(N == 1 && "Invalid number of operands!");
189 Inst.addOperand(MCOperand::CreateReg(getReg()));
192 void addImmOperands(MCInst &Inst, unsigned N) const {
193 assert(N == 1 && "Invalid number of operands!");
194 addExpr(Inst, getImm());
197 void addFslOperands(MCInst &Inst, unsigned N) const {
198 assert(N == 1 && "Invalid number of operands!");
199 addExpr(Inst, getFslImm());
202 void addMemOperands(MCInst &Inst, unsigned N) const {
203 assert(N == 2 && "Invalid number of operands!");
205 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
207 unsigned RegOff = getMemOffReg();
209 Inst.addOperand(MCOperand::CreateReg(RegOff));
211 addExpr(Inst, getMemOff());
214 StringRef getToken() const {
215 assert(Kind == Token && "Invalid access!");
216 return StringRef(Tok.Data, Tok.Length);
219 virtual void print(raw_ostream &OS) const;
221 static MBlazeOperand *CreateToken(StringRef Str, SMLoc S) {
222 MBlazeOperand *Op = new MBlazeOperand(Token);
223 Op->Tok.Data = Str.data();
224 Op->Tok.Length = Str.size();
230 static MBlazeOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
231 MBlazeOperand *Op = new MBlazeOperand(Register);
232 Op->Reg.RegNum = RegNum;
238 static MBlazeOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
239 MBlazeOperand *Op = new MBlazeOperand(Immediate);
246 static MBlazeOperand *CreateFslImm(const MCExpr *Val, SMLoc S, SMLoc E) {
247 MBlazeOperand *Op = new MBlazeOperand(Fsl);
254 static MBlazeOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S,
256 MBlazeOperand *Op = new MBlazeOperand(Memory);
265 static MBlazeOperand *CreateMem(unsigned Base, unsigned Off, SMLoc S,
267 MBlazeOperand *Op = new MBlazeOperand(Memory);
269 Op->Mem.OffReg = Off;
277 } // end anonymous namespace.
279 void MBlazeOperand::print(raw_ostream &OS) const {
286 OS << getMBlazeRegisterNumbering(getReg()) << ">";
289 OS << "'" << getToken() << "'";
293 OS << getMBlazeRegisterNumbering(getMemBase());
296 unsigned RegOff = getMemOffReg();
298 OS << "R" << getMBlazeRegisterNumbering(RegOff);
305 getFslImm()->print(OS);
310 /// @name Auto-generated Match Functions
313 static unsigned MatchRegisterName(StringRef Name);
317 bool MBlazeAsmParser::
318 MatchAndEmitInstruction(SMLoc IDLoc,
319 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
325 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo)) {
327 Out.EmitInstruction(Inst);
329 case Match_MissingFeature:
330 return Error(IDLoc, "instruction use requires an option to be enabled");
331 case Match_MnemonicFail:
332 return Error(IDLoc, "unrecognized instruction mnemonic");
333 case Match_ConversionFail:
334 return Error(IDLoc, "unable to convert operands to instruction");
335 case Match_InvalidOperand:
337 if (ErrorInfo != ~0U) {
338 if (ErrorInfo >= Operands.size())
339 return Error(IDLoc, "too few operands for instruction");
341 ErrorLoc = ((MBlazeOperand*)Operands[ErrorInfo])->getStartLoc();
342 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
345 return Error(ErrorLoc, "invalid operand for instruction");
348 llvm_unreachable("Implement any new match types added!");
352 MBlazeOperand *MBlazeAsmParser::
353 ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
354 if (Operands.size() != 4)
357 MBlazeOperand &Base = *(MBlazeOperand*)Operands[2];
358 MBlazeOperand &Offset = *(MBlazeOperand*)Operands[3];
360 SMLoc S = Base.getStartLoc();
361 SMLoc O = Offset.getStartLoc();
362 SMLoc E = Offset.getEndLoc();
365 Error(S, "base address must be a register");
369 if (!Offset.isReg() && !Offset.isImm()) {
370 Error(O, "offset must be a register or immediate");
376 Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getReg(), S, E);
378 Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getImm(), S, E);
380 delete Operands.pop_back_val();
381 delete Operands.pop_back_val();
382 Operands.push_back(Op);
387 bool MBlazeAsmParser::ParseRegister(unsigned &RegNo,
388 SMLoc &StartLoc, SMLoc &EndLoc) {
389 return (ParseRegister(RegNo) == 0);
392 MBlazeOperand *MBlazeAsmParser::ParseRegister(unsigned &RegNo) {
393 SMLoc S = Parser.getTok().getLoc();
394 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
396 switch (getLexer().getKind()) {
398 case AsmToken::Identifier:
399 RegNo = MatchRegisterName(getLexer().getTok().getIdentifier());
404 return MBlazeOperand::CreateReg(RegNo, S, E);
408 static unsigned MatchFslRegister(StringRef String) {
409 if (!String.startswith("rfsl"))
413 if (String.substr(4).getAsInteger(10,regNum))
419 MBlazeOperand *MBlazeAsmParser::ParseFsl() {
420 SMLoc S = Parser.getTok().getLoc();
421 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
423 switch (getLexer().getKind()) {
425 case AsmToken::Identifier:
426 unsigned reg = MatchFslRegister(getLexer().getTok().getIdentifier());
431 const MCExpr *EVal = MCConstantExpr::Create(reg,getContext());
432 return MBlazeOperand::CreateFslImm(EVal,S,E);
436 MBlazeOperand *MBlazeAsmParser::ParseImmediate() {
437 SMLoc S = Parser.getTok().getLoc();
438 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
441 switch (getLexer().getKind()) {
443 case AsmToken::LParen:
445 case AsmToken::Minus:
446 case AsmToken::Integer:
447 case AsmToken::Identifier:
448 if (getParser().ParseExpression(EVal))
451 return MBlazeOperand::CreateImm(EVal, S, E);
455 MBlazeOperand *MBlazeAsmParser::
456 ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
459 // Attempt to parse the next token as a register name
461 Op = ParseRegister(RegNo);
463 // Attempt to parse the next token as an FSL immediate
467 // Attempt to parse the next token as an immediate
469 Op = ParseImmediate();
471 // If the token could not be parsed then fail
473 Error(Parser.getTok().getLoc(), "unknown operand");
477 // Push the parsed operand into the list of operands
478 Operands.push_back(Op);
482 /// Parse an mblaze instruction mnemonic followed by its operands.
483 bool MBlazeAsmParser::
484 ParseInstruction(StringRef Name, SMLoc NameLoc,
485 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
486 // The first operands is the token for the instruction name
487 size_t dotLoc = Name.find('.');
488 Operands.push_back(MBlazeOperand::CreateToken(Name.substr(0,dotLoc),NameLoc));
489 if (dotLoc < Name.size())
490 Operands.push_back(MBlazeOperand::CreateToken(Name.substr(dotLoc),NameLoc));
492 // If there are no more operands then finish
493 if (getLexer().is(AsmToken::EndOfStatement))
496 // Parse the first operand
497 if (!ParseOperand(Operands))
500 while (getLexer().isNot(AsmToken::EndOfStatement) &&
501 getLexer().is(AsmToken::Comma)) {
502 // Consume the comma token
505 // Parse the next operand
506 if (!ParseOperand(Operands))
510 // If the instruction requires a memory operand then we need to
511 // replace the last two operands (base+offset) with a single
513 if (Name.startswith("lw") || Name.startswith("sw") ||
514 Name.startswith("lh") || Name.startswith("sh") ||
515 Name.startswith("lb") || Name.startswith("sb"))
516 return (ParseMemory(Operands) == NULL);
521 /// ParseDirective parses the arm specific directives
522 bool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) {
523 StringRef IDVal = DirectiveID.getIdentifier();
524 if (IDVal == ".word")
525 return ParseDirectiveWord(2, DirectiveID.getLoc());
529 /// ParseDirectiveWord
530 /// ::= .word [ expression (, expression)* ]
531 bool MBlazeAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
532 if (getLexer().isNot(AsmToken::EndOfStatement)) {
535 if (getParser().ParseExpression(Value))
538 getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
540 if (getLexer().is(AsmToken::EndOfStatement))
543 // FIXME: Improve diagnostic.
544 if (getLexer().isNot(AsmToken::Comma))
545 return Error(L, "unexpected token in directive");
554 extern "C" void LLVMInitializeMBlazeAsmLexer();
556 /// Force static initialization.
557 extern "C" void LLVMInitializeMBlazeAsmParser() {
558 RegisterMCAsmParser<MBlazeAsmParser> X(TheMBlazeTarget);
559 LLVMInitializeMBlazeAsmLexer();
562 #define GET_REGISTER_MATCHER
563 #define GET_MATCHER_IMPLEMENTATION
564 #include "MBlazeGenAsmMatcher.inc"