MBlazeAsmParser.cpp revision f2210eda2e37b08b3835a6c2d79929319ae1f603
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"
23using namespace llvm;
24
25namespace {
26struct MBlazeOperand;
27
28class 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
60public:
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.
72struct 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) {}
109public:
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
277void 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
311static unsigned MatchRegisterName(StringRef Name);
312
313/// }
314//
315bool MBlazeAsmParser::
316MatchAndEmitInstruction(SMLoc IDLoc,
317                        SmallVectorImpl<MCParsedAsmOperand*> &Operands,
318                        MCStreamer &Out) {
319  MCInst Inst;
320  unsigned Kind;
321  unsigned ErrorInfo;
322
323  switch (MatchInstructionImpl(Operands, Kind, 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_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(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