MBlazeAsmParser.cpp revision c4d2560a2010456f4eea0007eb71829d5668e7dd
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  llvm_unreachable("Implement any new match types added!");
346}
347
348MBlazeOperand *MBlazeAsmParser::
349ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
350  if (Operands.size() != 4)
351    return 0;
352
353  MBlazeOperand &Base = *(MBlazeOperand*)Operands[2];
354  MBlazeOperand &Offset = *(MBlazeOperand*)Operands[3];
355
356  SMLoc S = Base.getStartLoc();
357  SMLoc O = Offset.getStartLoc();
358  SMLoc E = Offset.getEndLoc();
359
360  if (!Base.isReg()) {
361    Error(S, "base address must be a register");
362    return 0;
363  }
364
365  if (!Offset.isReg() && !Offset.isImm()) {
366    Error(O, "offset must be a register or immediate");
367    return 0;
368  }
369
370  MBlazeOperand *Op;
371  if (Offset.isReg())
372    Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getReg(), S, E);
373  else
374    Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getImm(), S, E);
375
376  delete Operands.pop_back_val();
377  delete Operands.pop_back_val();
378  Operands.push_back(Op);
379
380  return Op;
381}
382
383bool MBlazeAsmParser::ParseRegister(unsigned &RegNo,
384                                    SMLoc &StartLoc, SMLoc &EndLoc) {
385  return (ParseRegister(RegNo) == 0);
386}
387
388MBlazeOperand *MBlazeAsmParser::ParseRegister(unsigned &RegNo) {
389  SMLoc S = Parser.getTok().getLoc();
390  SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
391
392  switch (getLexer().getKind()) {
393  default: return 0;
394  case AsmToken::Identifier:
395    RegNo = MatchRegisterName(getLexer().getTok().getIdentifier());
396    if (RegNo == 0)
397      return 0;
398
399    getLexer().Lex();
400    return MBlazeOperand::CreateReg(RegNo, S, E);
401  }
402}
403
404static unsigned MatchFslRegister(StringRef String) {
405  if (!String.startswith("rfsl"))
406    return -1;
407
408  unsigned regNum;
409  if (String.substr(4).getAsInteger(10,regNum))
410    return -1;
411
412  return regNum;
413}
414
415MBlazeOperand *MBlazeAsmParser::ParseFsl() {
416  SMLoc S = Parser.getTok().getLoc();
417  SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
418
419  switch (getLexer().getKind()) {
420  default: return 0;
421  case AsmToken::Identifier:
422    unsigned reg = MatchFslRegister(getLexer().getTok().getIdentifier());
423    if (reg >= 16)
424      return 0;
425
426    getLexer().Lex();
427    const MCExpr *EVal = MCConstantExpr::Create(reg,getContext());
428    return MBlazeOperand::CreateFslImm(EVal,S,E);
429  }
430}
431
432MBlazeOperand *MBlazeAsmParser::ParseImmediate() {
433  SMLoc S = Parser.getTok().getLoc();
434  SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
435
436  const MCExpr *EVal;
437  switch (getLexer().getKind()) {
438  default: return 0;
439  case AsmToken::LParen:
440  case AsmToken::Plus:
441  case AsmToken::Minus:
442  case AsmToken::Integer:
443  case AsmToken::Identifier:
444    if (getParser().ParseExpression(EVal))
445      return 0;
446
447    return MBlazeOperand::CreateImm(EVal, S, E);
448  }
449}
450
451MBlazeOperand *MBlazeAsmParser::
452ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
453  MBlazeOperand *Op;
454
455  // Attempt to parse the next token as a register name
456  unsigned RegNo;
457  Op = ParseRegister(RegNo);
458
459  // Attempt to parse the next token as an FSL immediate
460  if (!Op)
461    Op = ParseFsl();
462
463  // Attempt to parse the next token as an immediate
464  if (!Op)
465    Op = ParseImmediate();
466
467  // If the token could not be parsed then fail
468  if (!Op) {
469    Error(Parser.getTok().getLoc(), "unknown operand");
470    return 0;
471  }
472
473  // Push the parsed operand into the list of operands
474  Operands.push_back(Op);
475  return Op;
476}
477
478/// Parse an mblaze instruction mnemonic followed by its operands.
479bool MBlazeAsmParser::
480ParseInstruction(StringRef Name, SMLoc NameLoc,
481                 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
482  // The first operands is the token for the instruction name
483  size_t dotLoc = Name.find('.');
484  Operands.push_back(MBlazeOperand::CreateToken(Name.substr(0,dotLoc),NameLoc));
485  if (dotLoc < Name.size())
486    Operands.push_back(MBlazeOperand::CreateToken(Name.substr(dotLoc),NameLoc));
487
488  // If there are no more operands then finish
489  if (getLexer().is(AsmToken::EndOfStatement))
490    return false;
491
492  // Parse the first operand
493  if (!ParseOperand(Operands))
494    return true;
495
496  while (getLexer().isNot(AsmToken::EndOfStatement) &&
497         getLexer().is(AsmToken::Comma)) {
498    // Consume the comma token
499    getLexer().Lex();
500
501    // Parse the next operand
502    if (!ParseOperand(Operands))
503      return true;
504  }
505
506  // If the instruction requires a memory operand then we need to
507  // replace the last two operands (base+offset) with a single
508  // memory operand.
509  if (Name.startswith("lw") || Name.startswith("sw") ||
510      Name.startswith("lh") || Name.startswith("sh") ||
511      Name.startswith("lb") || Name.startswith("sb"))
512    return (ParseMemory(Operands) == NULL);
513
514  return false;
515}
516
517/// ParseDirective parses the MBlaze specific directives
518bool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) {
519  StringRef IDVal = DirectiveID.getIdentifier();
520  if (IDVal == ".word")
521    return ParseDirectiveWord(2, DirectiveID.getLoc());
522  return true;
523}
524
525/// ParseDirectiveWord
526///  ::= .word [ expression (, expression)* ]
527bool MBlazeAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
528  if (getLexer().isNot(AsmToken::EndOfStatement)) {
529    for (;;) {
530      const MCExpr *Value;
531      if (getParser().ParseExpression(Value))
532        return true;
533
534      getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
535
536      if (getLexer().is(AsmToken::EndOfStatement))
537        break;
538
539      // FIXME: Improve diagnostic.
540      if (getLexer().isNot(AsmToken::Comma))
541        return Error(L, "unexpected token in directive");
542      Parser.Lex();
543    }
544  }
545
546  Parser.Lex();
547  return false;
548}
549
550extern "C" void LLVMInitializeMBlazeAsmLexer();
551
552/// Force static initialization.
553extern "C" void LLVMInitializeMBlazeAsmParser() {
554  RegisterMCAsmParser<MBlazeAsmParser> X(TheMBlazeTarget);
555  LLVMInitializeMBlazeAsmLexer();
556}
557
558#define GET_REGISTER_MATCHER
559#define GET_MATCHER_IMPLEMENTATION
560#include "MBlazeGenAsmMatcher.inc"
561