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