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