2ab163e09150a34c81724a66efcb79a83373027b
[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/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"
23 using namespace llvm;
24
25 namespace {
26 struct MBlazeOperand;
27
28 class MBlazeAsmParser : public MCTargetAsmParser {
29   MCAsmParser &Parser;
30
31   MCAsmParser &getParser() const { return Parser; }
32   MCAsmLexer &getLexer() const { return Parser.getLexer(); }
33
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); }
36
37   MBlazeOperand *ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
38   MBlazeOperand *ParseRegister();
39   MBlazeOperand *ParseRegister(SMLoc &StartLoc, SMLoc &EndLoc);
40   MBlazeOperand *ParseImmediate();
41   MBlazeOperand *ParseFsl();
42   MBlazeOperand* ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
43
44   virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
45
46   bool ParseDirectiveWord(unsigned Size, SMLoc L);
47
48   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
49                                SmallVectorImpl<MCParsedAsmOperand*> &Operands,
50                                MCStreamer &Out, unsigned &ErrorInfo,
51                                bool MatchingInlineAsm);
52
53   /// @name Auto-generated Match Functions
54   /// {
55
56 #define GET_ASSEMBLER_HEADER
57 #include "MBlazeGenAsmMatcher.inc"
58
59   /// }
60
61 public:
62   MBlazeAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
63     : MCTargetAsmParser(), Parser(_Parser) {}
64
65   virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
66                                 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
110   MBlazeOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
111 public:
112   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.
136   SMLoc getStartLoc() const { return StartLoc; }
137
138   /// getEndLoc - Get the location of the last token of this operand.
139   SMLoc getEndLoc() const { return EndLoc; }
140
141   unsigned getReg() const {
142     assert(Kind == Register && "Invalid access!");
143     return Reg.RegNum;
144   }
145
146   const MCExpr *getImm() const {
147     assert(Kind == Immediate && "Invalid access!");
148     return Imm.Val;
149   }
150
151   const MCExpr *getFslImm() const {
152     assert(Kind == Fsl && "Invalid access!");
153     return FslImm.Val;
154   }
155
156   unsigned getMemBase() const {
157     assert(Kind == Memory && "Invalid access!");
158     return Mem.Base;
159   }
160
161   const MCExpr* getMemOff() const {
162     assert(Kind == Memory && "Invalid access!");
163     return Mem.Off;
164   }
165
166   unsigned getMemOffReg() const {
167     assert(Kind == Memory && "Invalid access!");
168     return Mem.OffReg;
169   }
170
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; }
176
177   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
187   void addRegOperands(MCInst &Inst, unsigned N) const {
188     assert(N == 1 && "Invalid number of operands!");
189     Inst.addOperand(MCOperand::CreateReg(getReg()));
190   }
191
192   void addImmOperands(MCInst &Inst, unsigned N) const {
193     assert(N == 1 && "Invalid number of operands!");
194     addExpr(Inst, getImm());
195   }
196
197   void addFslOperands(MCInst &Inst, unsigned N) const {
198     assert(N == 1 && "Invalid number of operands!");
199     addExpr(Inst, getFslImm());
200   }
201
202   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
214   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
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();
225     Op->StartLoc = S;
226     Op->EndLoc = S;
227     return Op;
228   }
229
230   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
238   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
246   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
254   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
265   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
279 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::
318 MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
319                         SmallVectorImpl<MCParsedAsmOperand*> &Operands,
320                         MCStreamer &Out, unsigned &ErrorInfo,
321                         bool MatchingInlineAsm) {
322   MCInst Inst;
323   switch (MatchInstructionImpl(Operands, Inst, ErrorInfo,
324                                MatchingInlineAsm)) {
325   default: break;
326   case Match_Success:
327     Out.EmitInstruction(Inst);
328     return false;
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_InvalidOperand: {
334     SMLoc ErrorLoc = IDLoc;
335     if (ErrorInfo != ~0U) {
336       if (ErrorInfo >= Operands.size())
337         return Error(IDLoc, "too few operands for instruction");
338
339       ErrorLoc = ((MBlazeOperand*)Operands[ErrorInfo])->getStartLoc();
340       if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
341     }
342
343     return Error(ErrorLoc, "invalid operand for instruction");
344   }
345   }
346
347   llvm_unreachable("Implement any new match types added!");
348 }
349
350 MBlazeOperand *MBlazeAsmParser::
351 ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
352   if (Operands.size() != 4)
353     return 0;
354
355   MBlazeOperand &Base = *(MBlazeOperand*)Operands[2];
356   MBlazeOperand &Offset = *(MBlazeOperand*)Operands[3];
357
358   SMLoc S = Base.getStartLoc();
359   SMLoc O = Offset.getStartLoc();
360   SMLoc E = Offset.getEndLoc();
361
362   if (!Base.isReg()) {
363     Error(S, "base address must be a register");
364     return 0;
365   }
366
367   if (!Offset.isReg() && !Offset.isImm()) {
368     Error(O, "offset must be a register or immediate");
369     return 0;
370   }
371
372   MBlazeOperand *Op;
373   if (Offset.isReg())
374     Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getReg(), S, E);
375   else
376     Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getImm(), S, E);
377
378   delete Operands.pop_back_val();
379   delete Operands.pop_back_val();
380   Operands.push_back(Op);
381
382   return Op;
383 }
384
385 bool MBlazeAsmParser::ParseRegister(unsigned &RegNo,
386                                     SMLoc &StartLoc, SMLoc &EndLoc) {
387   MBlazeOperand *Reg = ParseRegister(StartLoc, EndLoc);
388   if (!Reg)
389     return true;
390   RegNo = Reg->getReg();
391   return false;
392 }
393
394 MBlazeOperand *MBlazeAsmParser::ParseRegister() {
395   SMLoc S, E;
396   return ParseRegister(S, E);
397 }
398
399 MBlazeOperand *MBlazeAsmParser::ParseRegister(SMLoc &StartLoc, SMLoc &EndLoc) {
400   StartLoc = Parser.getTok().getLoc();
401   EndLoc = Parser.getTok().getEndLoc();
402
403   if (getLexer().getKind() != AsmToken::Identifier)
404     return 0;
405
406   unsigned RegNo = MatchRegisterName(getLexer().getTok().getIdentifier());
407   if (RegNo == 0)
408     return 0;
409
410   getLexer().Lex();
411   return MBlazeOperand::CreateReg(RegNo, StartLoc, EndLoc);
412 }
413
414 static unsigned MatchFslRegister(StringRef String) {
415   if (!String.startswith("rfsl"))
416     return -1;
417
418   unsigned regNum;
419   if (String.substr(4).getAsInteger(10,regNum))
420     return -1;
421
422   return regNum;
423 }
424
425 MBlazeOperand *MBlazeAsmParser::ParseFsl() {
426   SMLoc S = Parser.getTok().getLoc();
427   SMLoc E = Parser.getTok().getEndLoc();
428
429   switch (getLexer().getKind()) {
430   default: return 0;
431   case AsmToken::Identifier:
432     unsigned reg = MatchFslRegister(getLexer().getTok().getIdentifier());
433     if (reg >= 16)
434       return 0;
435
436     getLexer().Lex();
437     const MCExpr *EVal = MCConstantExpr::Create(reg,getContext());
438     return MBlazeOperand::CreateFslImm(EVal,S,E);
439   }
440 }
441
442 MBlazeOperand *MBlazeAsmParser::ParseImmediate() {
443   SMLoc S = Parser.getTok().getLoc();
444   SMLoc E = Parser.getTok().getEndLoc();
445
446   const MCExpr *EVal;
447   switch (getLexer().getKind()) {
448   default: return 0;
449   case AsmToken::LParen:
450   case AsmToken::Plus:
451   case AsmToken::Minus:
452   case AsmToken::Integer:
453   case AsmToken::Identifier:
454     if (getParser().ParseExpression(EVal))
455       return 0;
456
457     return MBlazeOperand::CreateImm(EVal, S, E);
458   }
459 }
460
461 MBlazeOperand *MBlazeAsmParser::
462 ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
463   MBlazeOperand *Op;
464
465   // Attempt to parse the next token as a register name
466   Op = ParseRegister();
467
468   // Attempt to parse the next token as an FSL immediate
469   if (!Op)
470     Op = ParseFsl();
471
472   // Attempt to parse the next token as an immediate
473   if (!Op)
474     Op = ParseImmediate();
475
476   // If the token could not be parsed then fail
477   if (!Op) {
478     Error(Parser.getTok().getLoc(), "unknown operand");
479     return 0;
480   }
481
482   // Push the parsed operand into the list of operands
483   Operands.push_back(Op);
484   return Op;
485 }
486
487 /// Parse an mblaze instruction mnemonic followed by its operands.
488 bool MBlazeAsmParser::
489 ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
490                  SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
491   // The first operands is the token for the instruction name
492   size_t dotLoc = Name.find('.');
493   Operands.push_back(MBlazeOperand::CreateToken(Name.substr(0,dotLoc),NameLoc));
494   if (dotLoc < Name.size())
495     Operands.push_back(MBlazeOperand::CreateToken(Name.substr(dotLoc),NameLoc));
496
497   // If there are no more operands then finish
498   if (getLexer().is(AsmToken::EndOfStatement))
499     return false;
500
501   // Parse the first operand
502   if (!ParseOperand(Operands))
503     return true;
504
505   while (getLexer().isNot(AsmToken::EndOfStatement) &&
506          getLexer().is(AsmToken::Comma)) {
507     // Consume the comma token
508     getLexer().Lex();
509
510     // Parse the next operand
511     if (!ParseOperand(Operands))
512       return true;
513   }
514
515   // If the instruction requires a memory operand then we need to
516   // replace the last two operands (base+offset) with a single
517   // memory operand.
518   if (Name.startswith("lw") || Name.startswith("sw") ||
519       Name.startswith("lh") || Name.startswith("sh") ||
520       Name.startswith("lb") || Name.startswith("sb"))
521     return (ParseMemory(Operands) == NULL);
522
523   return false;
524 }
525
526 /// ParseDirective parses the MBlaze specific directives
527 bool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) {
528   StringRef IDVal = DirectiveID.getIdentifier();
529   if (IDVal == ".word")
530     return ParseDirectiveWord(2, DirectiveID.getLoc());
531   return true;
532 }
533
534 /// ParseDirectiveWord
535 ///  ::= .word [ expression (, expression)* ]
536 bool MBlazeAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
537   if (getLexer().isNot(AsmToken::EndOfStatement)) {
538     for (;;) {
539       const MCExpr *Value;
540       if (getParser().ParseExpression(Value))
541         return true;
542
543       getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
544
545       if (getLexer().is(AsmToken::EndOfStatement))
546         break;
547
548       // FIXME: Improve diagnostic.
549       if (getLexer().isNot(AsmToken::Comma))
550         return Error(L, "unexpected token in directive");
551       Parser.Lex();
552     }
553   }
554
555   Parser.Lex();
556   return false;
557 }
558
559 /// Force static initialization.
560 extern "C" void LLVMInitializeMBlazeAsmParser() {
561   RegisterMCAsmParser<MBlazeAsmParser> X(TheMBlazeTarget);
562 }
563
564 #define GET_REGISTER_MATCHER
565 #define GET_MATCHER_IMPLEMENTATION
566 #include "MBlazeGenAsmMatcher.inc"