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