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