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