1 //===-- MBlazeAsmParser.cpp - Parse MBlaze asm to MCInst instructions -----===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
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/Support/SourceMgr.h"
19 #include "llvm/Support/TargetRegistry.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"
25 using namespace llvm;
26 
27 namespace {
28 struct MBlazeOperand;
29 
30 class MBlazeAsmParser : public MCTargetAsmParser {
31   MCAsmParser &Parser;
32 
getParser() const33   MCAsmParser &getParser() const { return Parser; }
getLexer() const34   MCAsmLexer &getLexer() const { return Parser.getLexer(); }
35 
Warning(SMLoc L,const Twine & Msg)36   void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Error(SMLoc L,const Twine & Msg)37   bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
38 
39   MBlazeOperand *ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
40   MBlazeOperand *ParseRegister(unsigned &RegNo);
41   MBlazeOperand *ParseImmediate();
42   MBlazeOperand *ParseFsl();
43   MBlazeOperand* ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
44 
45   virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
46 
47   bool ParseDirectiveWord(unsigned Size, SMLoc L);
48 
49   bool MatchAndEmitInstruction(SMLoc IDLoc,
50                                SmallVectorImpl<MCParsedAsmOperand*> &Operands,
51                                MCStreamer &Out);
52 
53   /// @name Auto-generated Match Functions
54   /// {
55 
56 #define GET_ASSEMBLER_HEADER
57 #include "MBlazeGenAsmMatcher.inc"
58 
59   /// }
60 
61 
62 public:
MBlazeAsmParser(MCSubtargetInfo & _STI,MCAsmParser & _Parser)63   MBlazeAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
64     : MCTargetAsmParser(), Parser(_Parser) {}
65 
66   virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
67                                 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
68 
69   virtual bool ParseDirective(AsmToken DirectiveID);
70 };
71 
72 /// MBlazeOperand - Instances of this class represent a parsed MBlaze machine
73 /// instruction.
74 struct MBlazeOperand : public MCParsedAsmOperand {
75   enum KindTy {
76     Token,
77     Immediate,
78     Register,
79     Memory,
80     Fsl
81   } Kind;
82 
83   SMLoc StartLoc, EndLoc;
84 
85   union {
86     struct {
87       const char *Data;
88       unsigned Length;
89     } Tok;
90 
91     struct {
92       unsigned RegNum;
93     } Reg;
94 
95     struct {
96       const MCExpr *Val;
97     } Imm;
98 
99     struct {
100       unsigned Base;
101       unsigned OffReg;
102       const MCExpr *Off;
103     } Mem;
104 
105     struct {
106       const MCExpr *Val;
107     } FslImm;
108   };
109 
MBlazeOperand__anondaef85440111::MBlazeOperand110   MBlazeOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
111 public:
MBlazeOperand__anondaef85440111::MBlazeOperand112   MBlazeOperand(const MBlazeOperand &o) : MCParsedAsmOperand() {
113     Kind = o.Kind;
114     StartLoc = o.StartLoc;
115     EndLoc = o.EndLoc;
116     switch (Kind) {
117     case Register:
118       Reg = o.Reg;
119       break;
120     case Immediate:
121       Imm = o.Imm;
122       break;
123     case Token:
124       Tok = o.Tok;
125       break;
126     case Memory:
127       Mem = o.Mem;
128       break;
129     case Fsl:
130       FslImm = o.FslImm;
131       break;
132     }
133   }
134 
135   /// getStartLoc - Get the location of the first token of this operand.
getStartLoc__anondaef85440111::MBlazeOperand136   SMLoc getStartLoc() const { return StartLoc; }
137 
138   /// getEndLoc - Get the location of the last token of this operand.
getEndLoc__anondaef85440111::MBlazeOperand139   SMLoc getEndLoc() const { return EndLoc; }
140 
getReg__anondaef85440111::MBlazeOperand141   unsigned getReg() const {
142     assert(Kind == Register && "Invalid access!");
143     return Reg.RegNum;
144   }
145 
getImm__anondaef85440111::MBlazeOperand146   const MCExpr *getImm() const {
147     assert(Kind == Immediate && "Invalid access!");
148     return Imm.Val;
149   }
150 
getFslImm__anondaef85440111::MBlazeOperand151   const MCExpr *getFslImm() const {
152     assert(Kind == Fsl && "Invalid access!");
153     return FslImm.Val;
154   }
155 
getMemBase__anondaef85440111::MBlazeOperand156   unsigned getMemBase() const {
157     assert(Kind == Memory && "Invalid access!");
158     return Mem.Base;
159   }
160 
getMemOff__anondaef85440111::MBlazeOperand161   const MCExpr* getMemOff() const {
162     assert(Kind == Memory && "Invalid access!");
163     return Mem.Off;
164   }
165 
getMemOffReg__anondaef85440111::MBlazeOperand166   unsigned getMemOffReg() const {
167     assert(Kind == Memory && "Invalid access!");
168     return Mem.OffReg;
169   }
170 
isToken__anondaef85440111::MBlazeOperand171   bool isToken() const { return Kind == Token; }
isImm__anondaef85440111::MBlazeOperand172   bool isImm() const { return Kind == Immediate; }
isMem__anondaef85440111::MBlazeOperand173   bool isMem() const { return Kind == Memory; }
isFsl__anondaef85440111::MBlazeOperand174   bool isFsl() const { return Kind == Fsl; }
isReg__anondaef85440111::MBlazeOperand175   bool isReg() const { return Kind == Register; }
176 
addExpr__anondaef85440111::MBlazeOperand177   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
178     // Add as immediates when possible.  Null MCExpr = 0.
179     if (Expr == 0)
180       Inst.addOperand(MCOperand::CreateImm(0));
181     else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
182       Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
183     else
184       Inst.addOperand(MCOperand::CreateExpr(Expr));
185   }
186 
addRegOperands__anondaef85440111::MBlazeOperand187   void addRegOperands(MCInst &Inst, unsigned N) const {
188     assert(N == 1 && "Invalid number of operands!");
189     Inst.addOperand(MCOperand::CreateReg(getReg()));
190   }
191 
addImmOperands__anondaef85440111::MBlazeOperand192   void addImmOperands(MCInst &Inst, unsigned N) const {
193     assert(N == 1 && "Invalid number of operands!");
194     addExpr(Inst, getImm());
195   }
196 
addFslOperands__anondaef85440111::MBlazeOperand197   void addFslOperands(MCInst &Inst, unsigned N) const {
198     assert(N == 1 && "Invalid number of operands!");
199     addExpr(Inst, getFslImm());
200   }
201 
addMemOperands__anondaef85440111::MBlazeOperand202   void addMemOperands(MCInst &Inst, unsigned N) const {
203     assert(N == 2 && "Invalid number of operands!");
204 
205     Inst.addOperand(MCOperand::CreateReg(getMemBase()));
206 
207     unsigned RegOff = getMemOffReg();
208     if (RegOff)
209       Inst.addOperand(MCOperand::CreateReg(RegOff));
210     else
211       addExpr(Inst, getMemOff());
212   }
213 
getToken__anondaef85440111::MBlazeOperand214   StringRef getToken() const {
215     assert(Kind == Token && "Invalid access!");
216     return StringRef(Tok.Data, Tok.Length);
217   }
218 
219   virtual void print(raw_ostream &OS) const;
220 
CreateToken__anondaef85440111::MBlazeOperand221   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();
225     Op->StartLoc = S;
226     Op->EndLoc = S;
227     return Op;
228   }
229 
CreateReg__anondaef85440111::MBlazeOperand230   static MBlazeOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
231     MBlazeOperand *Op = new MBlazeOperand(Register);
232     Op->Reg.RegNum = RegNum;
233     Op->StartLoc = S;
234     Op->EndLoc = E;
235     return Op;
236   }
237 
CreateImm__anondaef85440111::MBlazeOperand238   static MBlazeOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
239     MBlazeOperand *Op = new MBlazeOperand(Immediate);
240     Op->Imm.Val = Val;
241     Op->StartLoc = S;
242     Op->EndLoc = E;
243     return Op;
244   }
245 
CreateFslImm__anondaef85440111::MBlazeOperand246   static MBlazeOperand *CreateFslImm(const MCExpr *Val, SMLoc S, SMLoc E) {
247     MBlazeOperand *Op = new MBlazeOperand(Fsl);
248     Op->Imm.Val = Val;
249     Op->StartLoc = S;
250     Op->EndLoc = E;
251     return Op;
252   }
253 
CreateMem__anondaef85440111::MBlazeOperand254   static MBlazeOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S,
255                                   SMLoc E) {
256     MBlazeOperand *Op = new MBlazeOperand(Memory);
257     Op->Mem.Base = Base;
258     Op->Mem.Off = Off;
259     Op->Mem.OffReg = 0;
260     Op->StartLoc = S;
261     Op->EndLoc = E;
262     return Op;
263   }
264 
CreateMem__anondaef85440111::MBlazeOperand265   static MBlazeOperand *CreateMem(unsigned Base, unsigned Off, SMLoc S,
266                                   SMLoc E) {
267     MBlazeOperand *Op = new MBlazeOperand(Memory);
268     Op->Mem.Base = Base;
269     Op->Mem.OffReg = Off;
270     Op->Mem.Off = 0;
271     Op->StartLoc = S;
272     Op->EndLoc = E;
273     return Op;
274   }
275 };
276 
277 } // end anonymous namespace.
278 
print(raw_ostream & OS) const279 void MBlazeOperand::print(raw_ostream &OS) const {
280   switch (Kind) {
281   case Immediate:
282     getImm()->print(OS);
283     break;
284   case Register:
285     OS << "<register R";
286     OS << getMBlazeRegisterNumbering(getReg()) << ">";
287     break;
288   case Token:
289     OS << "'" << getToken() << "'";
290     break;
291   case Memory: {
292     OS << "<memory R";
293     OS << getMBlazeRegisterNumbering(getMemBase());
294     OS << ", ";
295 
296     unsigned RegOff = getMemOffReg();
297     if (RegOff)
298       OS << "R" << getMBlazeRegisterNumbering(RegOff);
299     else
300       OS << getMemOff();
301     OS << ">";
302     }
303     break;
304   case Fsl:
305     getFslImm()->print(OS);
306     break;
307   }
308 }
309 
310 /// @name Auto-generated Match Functions
311 /// {
312 
313 static unsigned MatchRegisterName(StringRef Name);
314 
315 /// }
316 //
317 bool MBlazeAsmParser::
MatchAndEmitInstruction(SMLoc IDLoc,SmallVectorImpl<MCParsedAsmOperand * > & Operands,MCStreamer & Out)318 MatchAndEmitInstruction(SMLoc IDLoc,
319                         SmallVectorImpl<MCParsedAsmOperand*> &Operands,
320                         MCStreamer &Out) {
321   MCInst Inst;
322   SMLoc ErrorLoc;
323   unsigned ErrorInfo;
324 
325   switch (MatchInstructionImpl(Operands, Inst, ErrorInfo)) {
326   default: break;
327   case Match_Success:
328     Out.EmitInstruction(Inst);
329     return false;
330   case Match_MissingFeature:
331     return Error(IDLoc, "instruction use requires an option to be enabled");
332   case Match_MnemonicFail:
333       return Error(IDLoc, "unrecognized instruction mnemonic");
334   case Match_ConversionFail:
335     return Error(IDLoc, "unable to convert operands to instruction");
336   case Match_InvalidOperand:
337     ErrorLoc = IDLoc;
338     if (ErrorInfo != ~0U) {
339       if (ErrorInfo >= Operands.size())
340         return Error(IDLoc, "too few operands for instruction");
341 
342       ErrorLoc = ((MBlazeOperand*)Operands[ErrorInfo])->getStartLoc();
343       if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
344     }
345 
346     return Error(ErrorLoc, "invalid operand for instruction");
347   }
348 
349   llvm_unreachable("Implement any new match types added!");
350   return true;
351 }
352 
353 MBlazeOperand *MBlazeAsmParser::
ParseMemory(SmallVectorImpl<MCParsedAsmOperand * > & Operands)354 ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
355   if (Operands.size() != 4)
356     return 0;
357 
358   MBlazeOperand &Base = *(MBlazeOperand*)Operands[2];
359   MBlazeOperand &Offset = *(MBlazeOperand*)Operands[3];
360 
361   SMLoc S = Base.getStartLoc();
362   SMLoc O = Offset.getStartLoc();
363   SMLoc E = Offset.getEndLoc();
364 
365   if (!Base.isReg()) {
366     Error(S, "base address must be a register");
367     return 0;
368   }
369 
370   if (!Offset.isReg() && !Offset.isImm()) {
371     Error(O, "offset must be a register or immediate");
372     return 0;
373   }
374 
375   MBlazeOperand *Op;
376   if (Offset.isReg())
377     Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getReg(), S, E);
378   else
379     Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getImm(), S, E);
380 
381   delete Operands.pop_back_val();
382   delete Operands.pop_back_val();
383   Operands.push_back(Op);
384 
385   return Op;
386 }
387 
ParseRegister(unsigned & RegNo,SMLoc & StartLoc,SMLoc & EndLoc)388 bool MBlazeAsmParser::ParseRegister(unsigned &RegNo,
389                                     SMLoc &StartLoc, SMLoc &EndLoc) {
390   return (ParseRegister(RegNo) == 0);
391 }
392 
ParseRegister(unsigned & RegNo)393 MBlazeOperand *MBlazeAsmParser::ParseRegister(unsigned &RegNo) {
394   SMLoc S = Parser.getTok().getLoc();
395   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
396 
397   switch (getLexer().getKind()) {
398   default: return 0;
399   case AsmToken::Identifier:
400     RegNo = MatchRegisterName(getLexer().getTok().getIdentifier());
401     if (RegNo == 0)
402       return 0;
403 
404     getLexer().Lex();
405     return MBlazeOperand::CreateReg(RegNo, S, E);
406   }
407 }
408 
MatchFslRegister(StringRef String)409 static unsigned MatchFslRegister(StringRef String) {
410   if (!String.startswith("rfsl"))
411     return -1;
412 
413   unsigned regNum;
414   if (String.substr(4).getAsInteger(10,regNum))
415     return -1;
416 
417   return regNum;
418 }
419 
ParseFsl()420 MBlazeOperand *MBlazeAsmParser::ParseFsl() {
421   SMLoc S = Parser.getTok().getLoc();
422   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
423 
424   switch (getLexer().getKind()) {
425   default: return 0;
426   case AsmToken::Identifier:
427     unsigned reg = MatchFslRegister(getLexer().getTok().getIdentifier());
428     if (reg >= 16)
429       return 0;
430 
431     getLexer().Lex();
432     const MCExpr *EVal = MCConstantExpr::Create(reg,getContext());
433     return MBlazeOperand::CreateFslImm(EVal,S,E);
434   }
435 }
436 
ParseImmediate()437 MBlazeOperand *MBlazeAsmParser::ParseImmediate() {
438   SMLoc S = Parser.getTok().getLoc();
439   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
440 
441   const MCExpr *EVal;
442   switch (getLexer().getKind()) {
443   default: return 0;
444   case AsmToken::LParen:
445   case AsmToken::Plus:
446   case AsmToken::Minus:
447   case AsmToken::Integer:
448   case AsmToken::Identifier:
449     if (getParser().ParseExpression(EVal))
450       return 0;
451 
452     return MBlazeOperand::CreateImm(EVal, S, E);
453   }
454 }
455 
456 MBlazeOperand *MBlazeAsmParser::
ParseOperand(SmallVectorImpl<MCParsedAsmOperand * > & Operands)457 ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
458   MBlazeOperand *Op;
459 
460   // Attempt to parse the next token as a register name
461   unsigned RegNo;
462   Op = ParseRegister(RegNo);
463 
464   // Attempt to parse the next token as an FSL immediate
465   if (!Op)
466     Op = ParseFsl();
467 
468   // Attempt to parse the next token as an immediate
469   if (!Op)
470     Op = ParseImmediate();
471 
472   // If the token could not be parsed then fail
473   if (!Op) {
474     Error(Parser.getTok().getLoc(), "unknown operand");
475     return 0;
476   }
477 
478   // Push the parsed operand into the list of operands
479   Operands.push_back(Op);
480   return Op;
481 }
482 
483 /// Parse an mblaze instruction mnemonic followed by its operands.
484 bool MBlazeAsmParser::
ParseInstruction(StringRef Name,SMLoc NameLoc,SmallVectorImpl<MCParsedAsmOperand * > & Operands)485 ParseInstruction(StringRef Name, SMLoc NameLoc,
486                  SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
487   // The first operands is the token for the instruction name
488   size_t dotLoc = Name.find('.');
489   Operands.push_back(MBlazeOperand::CreateToken(Name.substr(0,dotLoc),NameLoc));
490   if (dotLoc < Name.size())
491     Operands.push_back(MBlazeOperand::CreateToken(Name.substr(dotLoc),NameLoc));
492 
493   // If there are no more operands then finish
494   if (getLexer().is(AsmToken::EndOfStatement))
495     return false;
496 
497   // Parse the first operand
498   if (!ParseOperand(Operands))
499     return true;
500 
501   while (getLexer().isNot(AsmToken::EndOfStatement) &&
502          getLexer().is(AsmToken::Comma)) {
503     // Consume the comma token
504     getLexer().Lex();
505 
506     // Parse the next operand
507     if (!ParseOperand(Operands))
508       return true;
509   }
510 
511   // If the instruction requires a memory operand then we need to
512   // replace the last two operands (base+offset) with a single
513   // memory operand.
514   if (Name.startswith("lw") || Name.startswith("sw") ||
515       Name.startswith("lh") || Name.startswith("sh") ||
516       Name.startswith("lb") || Name.startswith("sb"))
517     return (ParseMemory(Operands) == NULL);
518 
519   return false;
520 }
521 
522 /// ParseDirective parses the MBlaze specific directives
ParseDirective(AsmToken DirectiveID)523 bool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) {
524   StringRef IDVal = DirectiveID.getIdentifier();
525   if (IDVal == ".word")
526     return ParseDirectiveWord(2, DirectiveID.getLoc());
527   return true;
528 }
529 
530 /// ParseDirectiveWord
531 ///  ::= .word [ expression (, expression)* ]
ParseDirectiveWord(unsigned Size,SMLoc L)532 bool MBlazeAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
533   if (getLexer().isNot(AsmToken::EndOfStatement)) {
534     for (;;) {
535       const MCExpr *Value;
536       if (getParser().ParseExpression(Value))
537         return true;
538 
539       getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
540 
541       if (getLexer().is(AsmToken::EndOfStatement))
542         break;
543 
544       // FIXME: Improve diagnostic.
545       if (getLexer().isNot(AsmToken::Comma))
546         return Error(L, "unexpected token in directive");
547       Parser.Lex();
548     }
549   }
550 
551   Parser.Lex();
552   return false;
553 }
554 
555 extern "C" void LLVMInitializeMBlazeAsmLexer();
556 
557 /// Force static initialization.
LLVMInitializeMBlazeAsmParser()558 extern "C" void LLVMInitializeMBlazeAsmParser() {
559   RegisterMCAsmParser<MBlazeAsmParser> X(TheMBlazeTarget);
560   LLVMInitializeMBlazeAsmLexer();
561 }
562 
563 #define GET_REGISTER_MATCHER
564 #define GET_MATCHER_IMPLEMENTATION
565 #include "MBlazeGenAsmMatcher.inc"
566