2e9b3101d0225a7ac204ac54cd2d32b69fdac536
[oota-llvm.git] / lib / Target / MBlaze / AsmParser / MBlazeAsmParser.cpp
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/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"
24 using namespace llvm;
25
26 namespace {
27 struct MBlazeOperand;
28
29 class MBlazeAsmParser : public MCTargetAsmParser {
30   MCAsmParser &Parser;
31
32   MCAsmParser &getParser() const { return Parser; }
33   MCAsmLexer &getLexer() const { return Parser.getLexer(); }
34
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); }
37
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);
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, unsigned &Opcode,
50                                SmallVectorImpl<MCParsedAsmOperand*> &Operands,
51                                MCStreamer &Out, unsigned &ErrorInfo,
52                                bool MatchingInlineAsm);
53
54   /// @name Auto-generated Match Functions
55   /// {
56
57 #define GET_ASSEMBLER_HEADER
58 #include "MBlazeGenAsmMatcher.inc"
59
60   /// }
61
62 public:
63   MBlazeAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
64     : MCTargetAsmParser(), Parser(_Parser) {}
65
66   virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
67                                 SMLoc NameLoc,
68                                 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
69
70   virtual bool ParseDirective(AsmToken DirectiveID);
71 };
72
73 /// MBlazeOperand - Instances of this class represent a parsed MBlaze machine
74 /// instruction.
75 struct MBlazeOperand : public MCParsedAsmOperand {
76   enum KindTy {
77     Token,
78     Immediate,
79     Register,
80     Memory,
81     Fsl
82   } Kind;
83
84   SMLoc StartLoc, EndLoc;
85
86   struct TokOp {
87     const char *Data;
88     unsigned Length;
89   };
90
91   struct RegOp {
92     unsigned RegNum;
93   };
94
95   struct ImmOp {
96     const MCExpr *Val;
97   };
98
99   struct MemOp {
100     unsigned Base;
101     unsigned OffReg;
102     const MCExpr *Off;
103   };
104
105   struct FslImmOp {
106     const MCExpr *Val;
107   };
108
109   union {
110     struct TokOp Tok;
111     struct RegOp Reg;
112     struct ImmOp Imm;
113     struct MemOp Mem;
114     struct FslImmOp FslImm;
115   };
116
117   MBlazeOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
118 public:
119   MBlazeOperand(const MBlazeOperand &o) : MCParsedAsmOperand() {
120     Kind = o.Kind;
121     StartLoc = o.StartLoc;
122     EndLoc = o.EndLoc;
123     switch (Kind) {
124     case Register:
125       Reg = o.Reg;
126       break;
127     case Immediate:
128       Imm = o.Imm;
129       break;
130     case Token:
131       Tok = o.Tok;
132       break;
133     case Memory:
134       Mem = o.Mem;
135       break;
136     case Fsl:
137       FslImm = o.FslImm;
138       break;
139     }
140   }
141
142   /// getStartLoc - Get the location of the first token of this operand.
143   SMLoc getStartLoc() const { return StartLoc; }
144
145   /// getEndLoc - Get the location of the last token of this operand.
146   SMLoc getEndLoc() const { return EndLoc; }
147
148   unsigned getReg() const {
149     assert(Kind == Register && "Invalid access!");
150     return Reg.RegNum;
151   }
152
153   const MCExpr *getImm() const {
154     assert(Kind == Immediate && "Invalid access!");
155     return Imm.Val;
156   }
157
158   const MCExpr *getFslImm() const {
159     assert(Kind == Fsl && "Invalid access!");
160     return FslImm.Val;
161   }
162
163   unsigned getMemBase() const {
164     assert(Kind == Memory && "Invalid access!");
165     return Mem.Base;
166   }
167
168   const MCExpr* getMemOff() const {
169     assert(Kind == Memory && "Invalid access!");
170     return Mem.Off;
171   }
172
173   unsigned getMemOffReg() const {
174     assert(Kind == Memory && "Invalid access!");
175     return Mem.OffReg;
176   }
177
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; }
183
184   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
185     // Add as immediates when possible.  Null MCExpr = 0.
186     if (Expr == 0)
187       Inst.addOperand(MCOperand::CreateImm(0));
188     else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
189       Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
190     else
191       Inst.addOperand(MCOperand::CreateExpr(Expr));
192   }
193
194   void addRegOperands(MCInst &Inst, unsigned N) const {
195     assert(N == 1 && "Invalid number of operands!");
196     Inst.addOperand(MCOperand::CreateReg(getReg()));
197   }
198
199   void addImmOperands(MCInst &Inst, unsigned N) const {
200     assert(N == 1 && "Invalid number of operands!");
201     addExpr(Inst, getImm());
202   }
203
204   void addFslOperands(MCInst &Inst, unsigned N) const {
205     assert(N == 1 && "Invalid number of operands!");
206     addExpr(Inst, getFslImm());
207   }
208
209   void addMemOperands(MCInst &Inst, unsigned N) const {
210     assert(N == 2 && "Invalid number of operands!");
211
212     Inst.addOperand(MCOperand::CreateReg(getMemBase()));
213
214     unsigned RegOff = getMemOffReg();
215     if (RegOff)
216       Inst.addOperand(MCOperand::CreateReg(RegOff));
217     else
218       addExpr(Inst, getMemOff());
219   }
220
221   StringRef getToken() const {
222     assert(Kind == Token && "Invalid access!");
223     return StringRef(Tok.Data, Tok.Length);
224   }
225
226   virtual void print(raw_ostream &OS) const;
227
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();
232     Op->StartLoc = S;
233     Op->EndLoc = S;
234     return Op;
235   }
236
237   static MBlazeOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
238     MBlazeOperand *Op = new MBlazeOperand(Register);
239     Op->Reg.RegNum = RegNum;
240     Op->StartLoc = S;
241     Op->EndLoc = E;
242     return Op;
243   }
244
245   static MBlazeOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
246     MBlazeOperand *Op = new MBlazeOperand(Immediate);
247     Op->Imm.Val = Val;
248     Op->StartLoc = S;
249     Op->EndLoc = E;
250     return Op;
251   }
252
253   static MBlazeOperand *CreateFslImm(const MCExpr *Val, SMLoc S, SMLoc E) {
254     MBlazeOperand *Op = new MBlazeOperand(Fsl);
255     Op->Imm.Val = Val;
256     Op->StartLoc = S;
257     Op->EndLoc = E;
258     return Op;
259   }
260
261   static MBlazeOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S,
262                                   SMLoc E) {
263     MBlazeOperand *Op = new MBlazeOperand(Memory);
264     Op->Mem.Base = Base;
265     Op->Mem.Off = Off;
266     Op->Mem.OffReg = 0;
267     Op->StartLoc = S;
268     Op->EndLoc = E;
269     return Op;
270   }
271
272   static MBlazeOperand *CreateMem(unsigned Base, unsigned Off, SMLoc S,
273                                   SMLoc E) {
274     MBlazeOperand *Op = new MBlazeOperand(Memory);
275     Op->Mem.Base = Base;
276     Op->Mem.OffReg = Off;
277     Op->Mem.Off = 0;
278     Op->StartLoc = S;
279     Op->EndLoc = E;
280     return Op;
281   }
282 };
283
284 } // end anonymous namespace.
285
286 void MBlazeOperand::print(raw_ostream &OS) const {
287   switch (Kind) {
288   case Immediate:
289     getImm()->print(OS);
290     break;
291   case Register:
292     OS << "<register R";
293     OS << getMBlazeRegisterNumbering(getReg()) << ">";
294     break;
295   case Token:
296     OS << "'" << getToken() << "'";
297     break;
298   case Memory: {
299     OS << "<memory R";
300     OS << getMBlazeRegisterNumbering(getMemBase());
301     OS << ", ";
302
303     unsigned RegOff = getMemOffReg();
304     if (RegOff)
305       OS << "R" << getMBlazeRegisterNumbering(RegOff);
306     else
307       OS << getMemOff();
308     OS << ">";
309     }
310     break;
311   case Fsl:
312     getFslImm()->print(OS);
313     break;
314   }
315 }
316
317 /// @name Auto-generated Match Functions
318 /// {
319
320 static unsigned MatchRegisterName(StringRef Name);
321
322 /// }
323 //
324 bool MBlazeAsmParser::
325 MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
326                         SmallVectorImpl<MCParsedAsmOperand*> &Operands,
327                         MCStreamer &Out, unsigned &ErrorInfo,
328                         bool MatchingInlineAsm) {
329   MCInst Inst;
330   switch (MatchInstructionImpl(Operands, Inst, ErrorInfo,
331                                MatchingInlineAsm)) {
332   default: break;
333   case Match_Success:
334     Out.EmitInstruction(Inst);
335     return false;
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");
345
346       ErrorLoc = ((MBlazeOperand*)Operands[ErrorInfo])->getStartLoc();
347       if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
348     }
349
350     return Error(ErrorLoc, "invalid operand for instruction");
351   }
352   }
353
354   llvm_unreachable("Implement any new match types added!");
355 }
356
357 MBlazeOperand *MBlazeAsmParser::
358 ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
359   if (Operands.size() != 4)
360     return 0;
361
362   MBlazeOperand &Base = *(MBlazeOperand*)Operands[2];
363   MBlazeOperand &Offset = *(MBlazeOperand*)Operands[3];
364
365   SMLoc S = Base.getStartLoc();
366   SMLoc O = Offset.getStartLoc();
367   SMLoc E = Offset.getEndLoc();
368
369   if (!Base.isReg()) {
370     Error(S, "base address must be a register");
371     return 0;
372   }
373
374   if (!Offset.isReg() && !Offset.isImm()) {
375     Error(O, "offset must be a register or immediate");
376     return 0;
377   }
378
379   MBlazeOperand *Op;
380   if (Offset.isReg())
381     Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getReg(), S, E);
382   else
383     Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getImm(), S, E);
384
385   delete Operands.pop_back_val();
386   delete Operands.pop_back_val();
387   Operands.push_back(Op);
388
389   return Op;
390 }
391
392 bool MBlazeAsmParser::ParseRegister(unsigned &RegNo,
393                                     SMLoc &StartLoc, SMLoc &EndLoc) {
394   MBlazeOperand *Reg = ParseRegister(StartLoc, EndLoc);
395   if (!Reg)
396     return true;
397   RegNo = Reg->getReg();
398   return false;
399 }
400
401 MBlazeOperand *MBlazeAsmParser::ParseRegister() {
402   SMLoc S, E;
403   return ParseRegister(S, E);
404 }
405
406 MBlazeOperand *MBlazeAsmParser::ParseRegister(SMLoc &StartLoc, SMLoc &EndLoc) {
407   StartLoc = Parser.getTok().getLoc();
408   EndLoc = Parser.getTok().getEndLoc();
409
410   if (getLexer().getKind() != AsmToken::Identifier)
411     return 0;
412
413   unsigned RegNo = MatchRegisterName(getLexer().getTok().getIdentifier());
414   if (RegNo == 0)
415     return 0;
416
417   getLexer().Lex();
418   return MBlazeOperand::CreateReg(RegNo, StartLoc, EndLoc);
419 }
420
421 static unsigned MatchFslRegister(StringRef String) {
422   if (!String.startswith("rfsl"))
423     return -1;
424
425   unsigned regNum;
426   if (String.substr(4).getAsInteger(10,regNum))
427     return -1;
428
429   return regNum;
430 }
431
432 MBlazeOperand *MBlazeAsmParser::ParseFsl() {
433   SMLoc S = Parser.getTok().getLoc();
434   SMLoc E = Parser.getTok().getEndLoc();
435
436   switch (getLexer().getKind()) {
437   default: return 0;
438   case AsmToken::Identifier:
439     unsigned reg = MatchFslRegister(getLexer().getTok().getIdentifier());
440     if (reg >= 16)
441       return 0;
442
443     getLexer().Lex();
444     const MCExpr *EVal = MCConstantExpr::Create(reg,getContext());
445     return MBlazeOperand::CreateFslImm(EVal,S,E);
446   }
447 }
448
449 MBlazeOperand *MBlazeAsmParser::ParseImmediate() {
450   SMLoc S = Parser.getTok().getLoc();
451   SMLoc E = Parser.getTok().getEndLoc();
452
453   const MCExpr *EVal;
454   switch (getLexer().getKind()) {
455   default: return 0;
456   case AsmToken::LParen:
457   case AsmToken::Plus:
458   case AsmToken::Minus:
459   case AsmToken::Integer:
460   case AsmToken::Identifier:
461     if (getParser().parseExpression(EVal))
462       return 0;
463
464     return MBlazeOperand::CreateImm(EVal, S, E);
465   }
466 }
467
468 MBlazeOperand *MBlazeAsmParser::
469 ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
470   MBlazeOperand *Op;
471
472   // Attempt to parse the next token as a register name
473   Op = ParseRegister();
474
475   // Attempt to parse the next token as an FSL immediate
476   if (!Op)
477     Op = ParseFsl();
478
479   // Attempt to parse the next token as an immediate
480   if (!Op)
481     Op = ParseImmediate();
482
483   // If the token could not be parsed then fail
484   if (!Op) {
485     Error(Parser.getTok().getLoc(), "unknown operand");
486     return 0;
487   }
488
489   // Push the parsed operand into the list of operands
490   Operands.push_back(Op);
491   return Op;
492 }
493
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));
503
504   // If there are no more operands then finish
505   if (getLexer().is(AsmToken::EndOfStatement))
506     return false;
507
508   // Parse the first operand
509   if (!ParseOperand(Operands))
510     return true;
511
512   while (getLexer().isNot(AsmToken::EndOfStatement) &&
513          getLexer().is(AsmToken::Comma)) {
514     // Consume the comma token
515     getLexer().Lex();
516
517     // Parse the next operand
518     if (!ParseOperand(Operands))
519       return true;
520   }
521
522   // If the instruction requires a memory operand then we need to
523   // replace the last two operands (base+offset) with a single
524   // memory operand.
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);
529
530   return false;
531 }
532
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());
538   return true;
539 }
540
541 /// ParseDirectiveWord
542 ///  ::= .word [ expression (, expression)* ]
543 bool MBlazeAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
544   if (getLexer().isNot(AsmToken::EndOfStatement)) {
545     for (;;) {
546       const MCExpr *Value;
547       if (getParser().parseExpression(Value))
548         return true;
549
550       getParser().getStreamer().EmitValue(Value, Size);
551
552       if (getLexer().is(AsmToken::EndOfStatement))
553         break;
554
555       // FIXME: Improve diagnostic.
556       if (getLexer().isNot(AsmToken::Comma))
557         return Error(L, "unexpected token in directive");
558       Parser.Lex();
559     }
560   }
561
562   Parser.Lex();
563   return false;
564 }
565
566 /// Force static initialization.
567 extern "C" void LLVMInitializeMBlazeAsmParser() {
568   RegisterMCAsmParser<MBlazeAsmParser> X(TheMBlazeTarget);
569 }
570
571 #define GET_REGISTER_MATCHER
572 #define GET_MATCHER_IMPLEMENTATION
573 #include "MBlazeGenAsmMatcher.inc"