MBlazeAsmParser.cpp revision 243830
1117119Stmm//===-- MBlazeAsmParser.cpp - Parse MBlaze asm to MCInst instructions -----===//
2117119Stmm//
3117119Stmm//                     The LLVM Compiler Infrastructure
4117119Stmm//
5117119Stmm// This file is distributed under the University of Illinois Open Source
6117119Stmm// License. See LICENSE.TXT for details.
7117119Stmm//
8117119Stmm//===----------------------------------------------------------------------===//
9117119Stmm
10117119Stmm#include "MCTargetDesc/MBlazeBaseInfo.h"
11117119Stmm#include "llvm/MC/MCParser/MCAsmLexer.h"
12117119Stmm#include "llvm/MC/MCParser/MCAsmParser.h"
13117119Stmm#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
14117119Stmm#include "llvm/MC/MCStreamer.h"
15117119Stmm#include "llvm/MC/MCExpr.h"
16117119Stmm#include "llvm/MC/MCInst.h"
17117119Stmm#include "llvm/MC/MCTargetAsmParser.h"
18117119Stmm#include "llvm/Support/SourceMgr.h"
19117119Stmm#include "llvm/Support/TargetRegistry.h"
20117119Stmm#include "llvm/Support/raw_ostream.h"
21117119Stmm#include "llvm/ADT/SmallVector.h"
22117119Stmm#include "llvm/ADT/Twine.h"
23117119Stmmusing namespace llvm;
24117119Stmm
25117119Stmmnamespace {
26117119Stmmstruct MBlazeOperand;
27117119Stmm
28117119Stmmclass MBlazeAsmParser : public MCTargetAsmParser {
29117119Stmm  MCAsmParser &Parser;
30152684Smarius
31152684Smarius  MCAsmParser &getParser() const { return Parser; }
32152684Smarius  MCAsmLexer &getLexer() const { return Parser.getLexer(); }
33117119Stmm
34133589Smarius  void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
35117119Stmm  bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
36117119Stmm
37117119Stmm  MBlazeOperand *ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
38117119Stmm  MBlazeOperand *ParseRegister(unsigned &RegNo);
39117119Stmm  MBlazeOperand *ParseImmediate();
40117119Stmm  MBlazeOperand *ParseFsl();
41117119Stmm  MBlazeOperand* ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
42133589Smarius
43152684Smarius  virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
44133589Smarius
45117119Stmm  bool ParseDirectiveWord(unsigned Size, SMLoc L);
46117119Stmm
47117119Stmm  bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
48117119Stmm                               SmallVectorImpl<MCParsedAsmOperand*> &Operands,
49163146Skmacy                               MCStreamer &Out, unsigned &ErrorInfo,
50117119Stmm                               bool MatchingInlineAsm);
51163146Skmacy
52117119Stmm  /// @name Auto-generated Match Functions
53117119Stmm  /// {
54117119Stmm
55117119Stmm#define GET_ASSEMBLER_HEADER
56117119Stmm#include "MBlazeGenAsmMatcher.inc"
57117119Stmm
58117119Stmm  /// }
59117119Stmm
60117119Stmmpublic:
61117119Stmm  MBlazeAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
62117119Stmm    : MCTargetAsmParser(), Parser(_Parser) {}
63117119Stmm
64117119Stmm  virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
65117119Stmm                                SMLoc NameLoc,
66117119Stmm                                SmallVectorImpl<MCParsedAsmOperand*> &Operands);
67117119Stmm
68117119Stmm  virtual bool ParseDirective(AsmToken DirectiveID);
69117119Stmm};
70117119Stmm
71152684Smarius/// MBlazeOperand - Instances of this class represent a parsed MBlaze machine
72117119Stmm/// instruction.
73117119Stmmstruct MBlazeOperand : public MCParsedAsmOperand {
74117119Stmm  enum KindTy {
75117119Stmm    Token,
76117119Stmm    Immediate,
77117119Stmm    Register,
78117119Stmm    Memory,
79117119Stmm    Fsl
80117119Stmm  } Kind;
81117119Stmm
82117119Stmm  SMLoc StartLoc, EndLoc;
83133589Smarius
84152684Smarius  union {
85152684Smarius    struct {
86152684Smarius      const char *Data;
87152684Smarius      unsigned Length;
88152684Smarius    } Tok;
89152684Smarius
90117119Stmm    struct {
91117119Stmm      unsigned RegNum;
92117119Stmm    } Reg;
93117119Stmm
94117119Stmm    struct {
95117119Stmm      const MCExpr *Val;
96152684Smarius    } Imm;
97117119Stmm
98117119Stmm    struct {
99117119Stmm      unsigned Base;
100117119Stmm      unsigned OffReg;
101117119Stmm      const MCExpr *Off;
102117119Stmm    } Mem;
103154600Sjhb
104117119Stmm    struct {
105154600Sjhb      const MCExpr *Val;
106154600Sjhb    } FslImm;
107117119Stmm  };
108117119Stmm
109117119Stmm  MBlazeOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
110117119Stmmpublic:
111117119Stmm  MBlazeOperand(const MBlazeOperand &o) : MCParsedAsmOperand() {
112117119Stmm    Kind = o.Kind;
113117119Stmm    StartLoc = o.StartLoc;
114117119Stmm    EndLoc = o.EndLoc;
115133589Smarius    switch (Kind) {
116117119Stmm    case Register:
117117119Stmm      Reg = o.Reg;
118117119Stmm      break;
119117119Stmm    case Immediate:
120117119Stmm      Imm = o.Imm;
121117119Stmm      break;
122117119Stmm    case Token:
123117119Stmm      Tok = o.Tok;
124117119Stmm      break;
125117119Stmm    case Memory:
126117119Stmm      Mem = o.Mem;
127117119Stmm      break;
128163146Skmacy    case Fsl:
129163146Skmacy      FslImm = o.FslImm;
130163146Skmacy      break;
131163146Skmacy    }
132117119Stmm  }
133117119Stmm
134117119Stmm  /// getStartLoc - Get the location of the first token of this operand.
135117119Stmm  SMLoc getStartLoc() const { return StartLoc; }
136117119Stmm
137117119Stmm  /// getEndLoc - Get the location of the last token of this operand.
138117119Stmm  SMLoc getEndLoc() const { return EndLoc; }
139117119Stmm
140117119Stmm  unsigned getReg() const {
141117119Stmm    assert(Kind == Register && "Invalid access!");
142117119Stmm    return Reg.RegNum;
143117119Stmm  }
144117119Stmm
145117119Stmm  const MCExpr *getImm() const {
146117119Stmm    assert(Kind == Immediate && "Invalid access!");
147117119Stmm    return Imm.Val;
148117119Stmm  }
149117119Stmm
150133774Smarius  const MCExpr *getFslImm() const {
151117119Stmm    assert(Kind == Fsl && "Invalid access!");
152117119Stmm    return FslImm.Val;
153163146Skmacy  }
154117119Stmm
155117119Stmm  unsigned getMemBase() const {
156117119Stmm    assert(Kind == Memory && "Invalid access!");
157117119Stmm    return Mem.Base;
158117119Stmm  }
159133774Smarius
160117119Stmm  const MCExpr* getMemOff() const {
161117119Stmm    assert(Kind == Memory && "Invalid access!");
162117119Stmm    return Mem.Off;
163117119Stmm  }
164117119Stmm
165117119Stmm  unsigned getMemOffReg() const {
166163146Skmacy    assert(Kind == Memory && "Invalid access!");
167117119Stmm    return Mem.OffReg;
168117119Stmm  }
169117119Stmm
170117119Stmm  bool isToken() const { return Kind == Token; }
171117119Stmm  bool isImm() const { return Kind == Immediate; }
172117119Stmm  bool isMem() const { return Kind == Memory; }
173117119Stmm  bool isFsl() const { return Kind == Fsl; }
174117119Stmm  bool isReg() const { return Kind == Register; }
175117119Stmm
176117119Stmm  void addExpr(MCInst &Inst, const MCExpr *Expr) const {
177117119Stmm    // Add as immediates when possible.  Null MCExpr = 0.
178153057Smarius    if (Expr == 0)
179117119Stmm      Inst.addOperand(MCOperand::CreateImm(0));
180117119Stmm    else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
181117119Stmm      Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
182117119Stmm    else
183117119Stmm      Inst.addOperand(MCOperand::CreateExpr(Expr));
184153057Smarius  }
185153057Smarius
186117119Stmm  void addRegOperands(MCInst &Inst, unsigned N) const {
187117119Stmm    assert(N == 1 && "Invalid number of operands!");
188117119Stmm    Inst.addOperand(MCOperand::CreateReg(getReg()));
189117119Stmm  }
190117119Stmm
191117119Stmm  void addImmOperands(MCInst &Inst, unsigned N) const {
192117119Stmm    assert(N == 1 && "Invalid number of operands!");
193117119Stmm    addExpr(Inst, getImm());
194133589Smarius  }
195117119Stmm
196152684Smarius  void addFslOperands(MCInst &Inst, unsigned N) const {
197140512Smarius    assert(N == 1 && "Invalid number of operands!");
198117119Stmm    addExpr(Inst, getFslImm());
199117119Stmm  }
200117119Stmm
201117119Stmm  void addMemOperands(MCInst &Inst, unsigned N) const {
202117119Stmm    assert(N == 2 && "Invalid number of operands!");
203152684Smarius
204152684Smarius    Inst.addOperand(MCOperand::CreateReg(getMemBase()));
205152684Smarius
206152684Smarius    unsigned RegOff = getMemOffReg();
207152684Smarius    if (RegOff)
208152684Smarius      Inst.addOperand(MCOperand::CreateReg(RegOff));
209152684Smarius    else
210152684Smarius      addExpr(Inst, getMemOff());
211117119Stmm  }
212117119Stmm
213117119Stmm  StringRef getToken() const {
214117119Stmm    assert(Kind == Token && "Invalid access!");
215117119Stmm    return StringRef(Tok.Data, Tok.Length);
216117119Stmm  }
217117119Stmm
218117119Stmm  virtual void print(raw_ostream &OS) const;
219117119Stmm
220117119Stmm  static MBlazeOperand *CreateToken(StringRef Str, SMLoc S) {
221117119Stmm    MBlazeOperand *Op = new MBlazeOperand(Token);
222152684Smarius    Op->Tok.Data = Str.data();
223152684Smarius    Op->Tok.Length = Str.size();
224117119Stmm    Op->StartLoc = S;
225117119Stmm    Op->EndLoc = S;
226152684Smarius    return Op;
227117119Stmm  }
228117119Stmm
229117119Stmm  static MBlazeOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
230117119Stmm    MBlazeOperand *Op = new MBlazeOperand(Register);
231117119Stmm    Op->Reg.RegNum = RegNum;
232117119Stmm    Op->StartLoc = S;
233117119Stmm    Op->EndLoc = E;
234117119Stmm    return Op;
235117119Stmm  }
236117119Stmm
237117119Stmm  static MBlazeOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
238117119Stmm    MBlazeOperand *Op = new MBlazeOperand(Immediate);
239117119Stmm    Op->Imm.Val = Val;
240117119Stmm    Op->StartLoc = S;
241117119Stmm    Op->EndLoc = E;
242117119Stmm    return Op;
243117119Stmm  }
244117119Stmm
245117119Stmm  static MBlazeOperand *CreateFslImm(const MCExpr *Val, SMLoc S, SMLoc E) {
246152684Smarius    MBlazeOperand *Op = new MBlazeOperand(Fsl);
247152684Smarius    Op->Imm.Val = Val;
248133589Smarius    Op->StartLoc = S;
249133589Smarius    Op->EndLoc = E;
250133589Smarius    return Op;
251133589Smarius  }
252152684Smarius
253133589Smarius  static MBlazeOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S,
254                                  SMLoc E) {
255    MBlazeOperand *Op = new MBlazeOperand(Memory);
256    Op->Mem.Base = Base;
257    Op->Mem.Off = Off;
258    Op->Mem.OffReg = 0;
259    Op->StartLoc = S;
260    Op->EndLoc = E;
261    return Op;
262  }
263
264  static MBlazeOperand *CreateMem(unsigned Base, unsigned Off, SMLoc S,
265                                  SMLoc E) {
266    MBlazeOperand *Op = new MBlazeOperand(Memory);
267    Op->Mem.Base = Base;
268    Op->Mem.OffReg = Off;
269    Op->Mem.Off = 0;
270    Op->StartLoc = S;
271    Op->EndLoc = E;
272    return Op;
273  }
274};
275
276} // end anonymous namespace.
277
278void MBlazeOperand::print(raw_ostream &OS) const {
279  switch (Kind) {
280  case Immediate:
281    getImm()->print(OS);
282    break;
283  case Register:
284    OS << "<register R";
285    OS << getMBlazeRegisterNumbering(getReg()) << ">";
286    break;
287  case Token:
288    OS << "'" << getToken() << "'";
289    break;
290  case Memory: {
291    OS << "<memory R";
292    OS << getMBlazeRegisterNumbering(getMemBase());
293    OS << ", ";
294
295    unsigned RegOff = getMemOffReg();
296    if (RegOff)
297      OS << "R" << getMBlazeRegisterNumbering(RegOff);
298    else
299      OS << getMemOff();
300    OS << ">";
301    }
302    break;
303  case Fsl:
304    getFslImm()->print(OS);
305    break;
306  }
307}
308
309/// @name Auto-generated Match Functions
310/// {
311
312static unsigned MatchRegisterName(StringRef Name);
313
314/// }
315//
316bool MBlazeAsmParser::
317MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
318                        SmallVectorImpl<MCParsedAsmOperand*> &Operands,
319                        MCStreamer &Out, unsigned &ErrorInfo,
320                        bool MatchingInlineAsm) {
321  MCInst Inst;
322  switch (MatchInstructionImpl(Operands, Inst, ErrorInfo,
323                               MatchingInlineAsm)) {
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_InvalidOperand: {
333    SMLoc ErrorLoc = IDLoc;
334    if (ErrorInfo != ~0U) {
335      if (ErrorInfo >= Operands.size())
336        return Error(IDLoc, "too few operands for instruction");
337
338      ErrorLoc = ((MBlazeOperand*)Operands[ErrorInfo])->getStartLoc();
339      if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
340    }
341
342    return Error(ErrorLoc, "invalid operand for instruction");
343  }
344  }
345
346  llvm_unreachable("Implement any new match types added!");
347}
348
349MBlazeOperand *MBlazeAsmParser::
350ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
351  if (Operands.size() != 4)
352    return 0;
353
354  MBlazeOperand &Base = *(MBlazeOperand*)Operands[2];
355  MBlazeOperand &Offset = *(MBlazeOperand*)Operands[3];
356
357  SMLoc S = Base.getStartLoc();
358  SMLoc O = Offset.getStartLoc();
359  SMLoc E = Offset.getEndLoc();
360
361  if (!Base.isReg()) {
362    Error(S, "base address must be a register");
363    return 0;
364  }
365
366  if (!Offset.isReg() && !Offset.isImm()) {
367    Error(O, "offset must be a register or immediate");
368    return 0;
369  }
370
371  MBlazeOperand *Op;
372  if (Offset.isReg())
373    Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getReg(), S, E);
374  else
375    Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getImm(), S, E);
376
377  delete Operands.pop_back_val();
378  delete Operands.pop_back_val();
379  Operands.push_back(Op);
380
381  return Op;
382}
383
384bool MBlazeAsmParser::ParseRegister(unsigned &RegNo,
385                                    SMLoc &StartLoc, SMLoc &EndLoc) {
386  return (ParseRegister(RegNo) == 0);
387}
388
389MBlazeOperand *MBlazeAsmParser::ParseRegister(unsigned &RegNo) {
390  SMLoc S = Parser.getTok().getLoc();
391  SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
392
393  switch (getLexer().getKind()) {
394  default: return 0;
395  case AsmToken::Identifier:
396    RegNo = MatchRegisterName(getLexer().getTok().getIdentifier());
397    if (RegNo == 0)
398      return 0;
399
400    getLexer().Lex();
401    return MBlazeOperand::CreateReg(RegNo, S, E);
402  }
403}
404
405static unsigned MatchFslRegister(StringRef String) {
406  if (!String.startswith("rfsl"))
407    return -1;
408
409  unsigned regNum;
410  if (String.substr(4).getAsInteger(10,regNum))
411    return -1;
412
413  return regNum;
414}
415
416MBlazeOperand *MBlazeAsmParser::ParseFsl() {
417  SMLoc S = Parser.getTok().getLoc();
418  SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
419
420  switch (getLexer().getKind()) {
421  default: return 0;
422  case AsmToken::Identifier:
423    unsigned reg = MatchFslRegister(getLexer().getTok().getIdentifier());
424    if (reg >= 16)
425      return 0;
426
427    getLexer().Lex();
428    const MCExpr *EVal = MCConstantExpr::Create(reg,getContext());
429    return MBlazeOperand::CreateFslImm(EVal,S,E);
430  }
431}
432
433MBlazeOperand *MBlazeAsmParser::ParseImmediate() {
434  SMLoc S = Parser.getTok().getLoc();
435  SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
436
437  const MCExpr *EVal;
438  switch (getLexer().getKind()) {
439  default: return 0;
440  case AsmToken::LParen:
441  case AsmToken::Plus:
442  case AsmToken::Minus:
443  case AsmToken::Integer:
444  case AsmToken::Identifier:
445    if (getParser().ParseExpression(EVal))
446      return 0;
447
448    return MBlazeOperand::CreateImm(EVal, S, E);
449  }
450}
451
452MBlazeOperand *MBlazeAsmParser::
453ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
454  MBlazeOperand *Op;
455
456  // Attempt to parse the next token as a register name
457  unsigned RegNo;
458  Op = ParseRegister(RegNo);
459
460  // Attempt to parse the next token as an FSL immediate
461  if (!Op)
462    Op = ParseFsl();
463
464  // Attempt to parse the next token as an immediate
465  if (!Op)
466    Op = ParseImmediate();
467
468  // If the token could not be parsed then fail
469  if (!Op) {
470    Error(Parser.getTok().getLoc(), "unknown operand");
471    return 0;
472  }
473
474  // Push the parsed operand into the list of operands
475  Operands.push_back(Op);
476  return Op;
477}
478
479/// Parse an mblaze instruction mnemonic followed by its operands.
480bool MBlazeAsmParser::
481ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
482                 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
483  // The first operands is the token for the instruction name
484  size_t dotLoc = Name.find('.');
485  Operands.push_back(MBlazeOperand::CreateToken(Name.substr(0,dotLoc),NameLoc));
486  if (dotLoc < Name.size())
487    Operands.push_back(MBlazeOperand::CreateToken(Name.substr(dotLoc),NameLoc));
488
489  // If there are no more operands then finish
490  if (getLexer().is(AsmToken::EndOfStatement))
491    return false;
492
493  // Parse the first operand
494  if (!ParseOperand(Operands))
495    return true;
496
497  while (getLexer().isNot(AsmToken::EndOfStatement) &&
498         getLexer().is(AsmToken::Comma)) {
499    // Consume the comma token
500    getLexer().Lex();
501
502    // Parse the next operand
503    if (!ParseOperand(Operands))
504      return true;
505  }
506
507  // If the instruction requires a memory operand then we need to
508  // replace the last two operands (base+offset) with a single
509  // memory operand.
510  if (Name.startswith("lw") || Name.startswith("sw") ||
511      Name.startswith("lh") || Name.startswith("sh") ||
512      Name.startswith("lb") || Name.startswith("sb"))
513    return (ParseMemory(Operands) == NULL);
514
515  return false;
516}
517
518/// ParseDirective parses the MBlaze specific directives
519bool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) {
520  StringRef IDVal = DirectiveID.getIdentifier();
521  if (IDVal == ".word")
522    return ParseDirectiveWord(2, DirectiveID.getLoc());
523  return true;
524}
525
526/// ParseDirectiveWord
527///  ::= .word [ expression (, expression)* ]
528bool MBlazeAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
529  if (getLexer().isNot(AsmToken::EndOfStatement)) {
530    for (;;) {
531      const MCExpr *Value;
532      if (getParser().ParseExpression(Value))
533        return true;
534
535      getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
536
537      if (getLexer().is(AsmToken::EndOfStatement))
538        break;
539
540      // FIXME: Improve diagnostic.
541      if (getLexer().isNot(AsmToken::Comma))
542        return Error(L, "unexpected token in directive");
543      Parser.Lex();
544    }
545  }
546
547  Parser.Lex();
548  return false;
549}
550
551extern "C" void LLVMInitializeMBlazeAsmLexer();
552
553/// Force static initialization.
554extern "C" void LLVMInitializeMBlazeAsmParser() {
555  RegisterMCAsmParser<MBlazeAsmParser> X(TheMBlazeTarget);
556  LLVMInitializeMBlazeAsmLexer();
557}
558
559#define GET_REGISTER_MATCHER
560#define GET_MATCHER_IMPLEMENTATION
561#include "MBlazeGenAsmMatcher.inc"
562