1218885Sdim//===-- MBlazeAsmParser.cpp - Parse MBlaze asm to MCInst instructions -----===//
2218885Sdim//
3218885Sdim//                     The LLVM Compiler Infrastructure
4218885Sdim//
5218885Sdim// This file is distributed under the University of Illinois Open Source
6218885Sdim// License. See LICENSE.TXT for details.
7218885Sdim//
8218885Sdim//===----------------------------------------------------------------------===//
9218885Sdim
10226633Sdim#include "MCTargetDesc/MBlazeBaseInfo.h"
11249423Sdim#include "llvm/ADT/SmallVector.h"
12249423Sdim#include "llvm/ADT/Twine.h"
13249423Sdim#include "llvm/MC/MCExpr.h"
14249423Sdim#include "llvm/MC/MCInst.h"
15218885Sdim#include "llvm/MC/MCParser/MCAsmLexer.h"
16218885Sdim#include "llvm/MC/MCParser/MCAsmParser.h"
17218885Sdim#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
18218885Sdim#include "llvm/MC/MCStreamer.h"
19226633Sdim#include "llvm/MC/MCTargetAsmParser.h"
20218885Sdim#include "llvm/Support/SourceMgr.h"
21226633Sdim#include "llvm/Support/TargetRegistry.h"
22218885Sdim#include "llvm/Support/raw_ostream.h"
23218885Sdimusing namespace llvm;
24218885Sdim
25218885Sdimnamespace {
26218885Sdimstruct MBlazeOperand;
27218885Sdim
28226633Sdimclass MBlazeAsmParser : public MCTargetAsmParser {
29218885Sdim  MCAsmParser &Parser;
30218885Sdim
31218885Sdim  MCAsmParser &getParser() const { return Parser; }
32218885Sdim  MCAsmLexer &getLexer() const { return Parser.getLexer(); }
33218885Sdim
34218885Sdim  void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
35218885Sdim  bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
36218885Sdim
37218885Sdim  MBlazeOperand *ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
38249423Sdim  MBlazeOperand *ParseRegister();
39249423Sdim  MBlazeOperand *ParseRegister(SMLoc &StartLoc, SMLoc &EndLoc);
40218885Sdim  MBlazeOperand *ParseImmediate();
41218885Sdim  MBlazeOperand *ParseFsl();
42218885Sdim  MBlazeOperand* ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
43218885Sdim
44218885Sdim  virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
45218885Sdim
46218885Sdim  bool ParseDirectiveWord(unsigned Size, SMLoc L);
47218885Sdim
48243830Sdim  bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
49218885Sdim                               SmallVectorImpl<MCParsedAsmOperand*> &Operands,
50243830Sdim                               MCStreamer &Out, unsigned &ErrorInfo,
51243830Sdim                               bool MatchingInlineAsm);
52218885Sdim
53218885Sdim  /// @name Auto-generated Match Functions
54218885Sdim  /// {
55218885Sdim
56218885Sdim#define GET_ASSEMBLER_HEADER
57218885Sdim#include "MBlazeGenAsmMatcher.inc"
58218885Sdim
59218885Sdim  /// }
60218885Sdim
61218885Sdimpublic:
62224145Sdim  MBlazeAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
63226633Sdim    : MCTargetAsmParser(), Parser(_Parser) {}
64218885Sdim
65243830Sdim  virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
66243830Sdim                                SMLoc NameLoc,
67218885Sdim                                SmallVectorImpl<MCParsedAsmOperand*> &Operands);
68218885Sdim
69218885Sdim  virtual bool ParseDirective(AsmToken DirectiveID);
70218885Sdim};
71218885Sdim
72218885Sdim/// MBlazeOperand - Instances of this class represent a parsed MBlaze machine
73218885Sdim/// instruction.
74218885Sdimstruct MBlazeOperand : public MCParsedAsmOperand {
75218885Sdim  enum KindTy {
76218885Sdim    Token,
77218885Sdim    Immediate,
78218885Sdim    Register,
79218885Sdim    Memory,
80218885Sdim    Fsl
81218885Sdim  } Kind;
82218885Sdim
83218885Sdim  SMLoc StartLoc, EndLoc;
84218885Sdim
85249423Sdim  struct TokOp {
86249423Sdim    const char *Data;
87249423Sdim    unsigned Length;
88249423Sdim  };
89218885Sdim
90249423Sdim  struct RegOp {
91249423Sdim    unsigned RegNum;
92249423Sdim  };
93218885Sdim
94249423Sdim  struct ImmOp {
95249423Sdim    const MCExpr *Val;
96249423Sdim  };
97218885Sdim
98249423Sdim  struct MemOp {
99249423Sdim    unsigned Base;
100249423Sdim    unsigned OffReg;
101249423Sdim    const MCExpr *Off;
102249423Sdim  };
103218885Sdim
104249423Sdim  struct FslImmOp {
105249423Sdim    const MCExpr *Val;
106218885Sdim  };
107218885Sdim
108249423Sdim  union {
109249423Sdim    struct TokOp Tok;
110249423Sdim    struct RegOp Reg;
111249423Sdim    struct ImmOp Imm;
112249423Sdim    struct MemOp Mem;
113249423Sdim    struct FslImmOp FslImm;
114249423Sdim  };
115249423Sdim
116218885Sdim  MBlazeOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
117218885Sdimpublic:
118218885Sdim  MBlazeOperand(const MBlazeOperand &o) : MCParsedAsmOperand() {
119218885Sdim    Kind = o.Kind;
120218885Sdim    StartLoc = o.StartLoc;
121218885Sdim    EndLoc = o.EndLoc;
122218885Sdim    switch (Kind) {
123218885Sdim    case Register:
124218885Sdim      Reg = o.Reg;
125218885Sdim      break;
126218885Sdim    case Immediate:
127218885Sdim      Imm = o.Imm;
128218885Sdim      break;
129218885Sdim    case Token:
130218885Sdim      Tok = o.Tok;
131218885Sdim      break;
132218885Sdim    case Memory:
133218885Sdim      Mem = o.Mem;
134218885Sdim      break;
135218885Sdim    case Fsl:
136218885Sdim      FslImm = o.FslImm;
137218885Sdim      break;
138218885Sdim    }
139218885Sdim  }
140218885Sdim
141218885Sdim  /// getStartLoc - Get the location of the first token of this operand.
142218885Sdim  SMLoc getStartLoc() const { return StartLoc; }
143218885Sdim
144218885Sdim  /// getEndLoc - Get the location of the last token of this operand.
145218885Sdim  SMLoc getEndLoc() const { return EndLoc; }
146218885Sdim
147218885Sdim  unsigned getReg() const {
148218885Sdim    assert(Kind == Register && "Invalid access!");
149218885Sdim    return Reg.RegNum;
150218885Sdim  }
151218885Sdim
152218885Sdim  const MCExpr *getImm() const {
153218885Sdim    assert(Kind == Immediate && "Invalid access!");
154218885Sdim    return Imm.Val;
155218885Sdim  }
156218885Sdim
157218885Sdim  const MCExpr *getFslImm() const {
158218885Sdim    assert(Kind == Fsl && "Invalid access!");
159218885Sdim    return FslImm.Val;
160218885Sdim  }
161218885Sdim
162218885Sdim  unsigned getMemBase() const {
163218885Sdim    assert(Kind == Memory && "Invalid access!");
164218885Sdim    return Mem.Base;
165218885Sdim  }
166218885Sdim
167218885Sdim  const MCExpr* getMemOff() const {
168218885Sdim    assert(Kind == Memory && "Invalid access!");
169218885Sdim    return Mem.Off;
170218885Sdim  }
171218885Sdim
172218885Sdim  unsigned getMemOffReg() const {
173218885Sdim    assert(Kind == Memory && "Invalid access!");
174218885Sdim    return Mem.OffReg;
175218885Sdim  }
176218885Sdim
177218885Sdim  bool isToken() const { return Kind == Token; }
178218885Sdim  bool isImm() const { return Kind == Immediate; }
179218885Sdim  bool isMem() const { return Kind == Memory; }
180218885Sdim  bool isFsl() const { return Kind == Fsl; }
181218885Sdim  bool isReg() const { return Kind == Register; }
182218885Sdim
183218885Sdim  void addExpr(MCInst &Inst, const MCExpr *Expr) const {
184218885Sdim    // Add as immediates when possible.  Null MCExpr = 0.
185218885Sdim    if (Expr == 0)
186218885Sdim      Inst.addOperand(MCOperand::CreateImm(0));
187218885Sdim    else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
188218885Sdim      Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
189218885Sdim    else
190218885Sdim      Inst.addOperand(MCOperand::CreateExpr(Expr));
191218885Sdim  }
192218885Sdim
193218885Sdim  void addRegOperands(MCInst &Inst, unsigned N) const {
194218885Sdim    assert(N == 1 && "Invalid number of operands!");
195218885Sdim    Inst.addOperand(MCOperand::CreateReg(getReg()));
196218885Sdim  }
197218885Sdim
198218885Sdim  void addImmOperands(MCInst &Inst, unsigned N) const {
199218885Sdim    assert(N == 1 && "Invalid number of operands!");
200218885Sdim    addExpr(Inst, getImm());
201218885Sdim  }
202218885Sdim
203218885Sdim  void addFslOperands(MCInst &Inst, unsigned N) const {
204218885Sdim    assert(N == 1 && "Invalid number of operands!");
205218885Sdim    addExpr(Inst, getFslImm());
206218885Sdim  }
207218885Sdim
208218885Sdim  void addMemOperands(MCInst &Inst, unsigned N) const {
209218885Sdim    assert(N == 2 && "Invalid number of operands!");
210218885Sdim
211218885Sdim    Inst.addOperand(MCOperand::CreateReg(getMemBase()));
212218885Sdim
213218885Sdim    unsigned RegOff = getMemOffReg();
214218885Sdim    if (RegOff)
215218885Sdim      Inst.addOperand(MCOperand::CreateReg(RegOff));
216218885Sdim    else
217218885Sdim      addExpr(Inst, getMemOff());
218218885Sdim  }
219218885Sdim
220218885Sdim  StringRef getToken() const {
221218885Sdim    assert(Kind == Token && "Invalid access!");
222218885Sdim    return StringRef(Tok.Data, Tok.Length);
223218885Sdim  }
224218885Sdim
225224145Sdim  virtual void print(raw_ostream &OS) const;
226218885Sdim
227218885Sdim  static MBlazeOperand *CreateToken(StringRef Str, SMLoc S) {
228218885Sdim    MBlazeOperand *Op = new MBlazeOperand(Token);
229218885Sdim    Op->Tok.Data = Str.data();
230218885Sdim    Op->Tok.Length = Str.size();
231218885Sdim    Op->StartLoc = S;
232218885Sdim    Op->EndLoc = S;
233218885Sdim    return Op;
234218885Sdim  }
235218885Sdim
236218885Sdim  static MBlazeOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
237218885Sdim    MBlazeOperand *Op = new MBlazeOperand(Register);
238218885Sdim    Op->Reg.RegNum = RegNum;
239218885Sdim    Op->StartLoc = S;
240218885Sdim    Op->EndLoc = E;
241218885Sdim    return Op;
242218885Sdim  }
243218885Sdim
244218885Sdim  static MBlazeOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
245218885Sdim    MBlazeOperand *Op = new MBlazeOperand(Immediate);
246218885Sdim    Op->Imm.Val = Val;
247218885Sdim    Op->StartLoc = S;
248218885Sdim    Op->EndLoc = E;
249218885Sdim    return Op;
250218885Sdim  }
251218885Sdim
252218885Sdim  static MBlazeOperand *CreateFslImm(const MCExpr *Val, SMLoc S, SMLoc E) {
253218885Sdim    MBlazeOperand *Op = new MBlazeOperand(Fsl);
254218885Sdim    Op->Imm.Val = Val;
255218885Sdim    Op->StartLoc = S;
256218885Sdim    Op->EndLoc = E;
257218885Sdim    return Op;
258218885Sdim  }
259218885Sdim
260218885Sdim  static MBlazeOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S,
261218885Sdim                                  SMLoc E) {
262218885Sdim    MBlazeOperand *Op = new MBlazeOperand(Memory);
263218885Sdim    Op->Mem.Base = Base;
264218885Sdim    Op->Mem.Off = Off;
265218885Sdim    Op->Mem.OffReg = 0;
266218885Sdim    Op->StartLoc = S;
267218885Sdim    Op->EndLoc = E;
268218885Sdim    return Op;
269218885Sdim  }
270218885Sdim
271218885Sdim  static MBlazeOperand *CreateMem(unsigned Base, unsigned Off, SMLoc S,
272218885Sdim                                  SMLoc E) {
273218885Sdim    MBlazeOperand *Op = new MBlazeOperand(Memory);
274218885Sdim    Op->Mem.Base = Base;
275218885Sdim    Op->Mem.OffReg = Off;
276218885Sdim    Op->Mem.Off = 0;
277218885Sdim    Op->StartLoc = S;
278218885Sdim    Op->EndLoc = E;
279218885Sdim    return Op;
280218885Sdim  }
281218885Sdim};
282218885Sdim
283218885Sdim} // end anonymous namespace.
284218885Sdim
285224145Sdimvoid MBlazeOperand::print(raw_ostream &OS) const {
286218885Sdim  switch (Kind) {
287218885Sdim  case Immediate:
288218885Sdim    getImm()->print(OS);
289218885Sdim    break;
290218885Sdim  case Register:
291218885Sdim    OS << "<register R";
292226633Sdim    OS << getMBlazeRegisterNumbering(getReg()) << ">";
293218885Sdim    break;
294218885Sdim  case Token:
295218885Sdim    OS << "'" << getToken() << "'";
296218885Sdim    break;
297218885Sdim  case Memory: {
298218885Sdim    OS << "<memory R";
299226633Sdim    OS << getMBlazeRegisterNumbering(getMemBase());
300218885Sdim    OS << ", ";
301218885Sdim
302218885Sdim    unsigned RegOff = getMemOffReg();
303218885Sdim    if (RegOff)
304226633Sdim      OS << "R" << getMBlazeRegisterNumbering(RegOff);
305218885Sdim    else
306218885Sdim      OS << getMemOff();
307218885Sdim    OS << ">";
308218885Sdim    }
309218885Sdim    break;
310218885Sdim  case Fsl:
311218885Sdim    getFslImm()->print(OS);
312218885Sdim    break;
313218885Sdim  }
314218885Sdim}
315218885Sdim
316218885Sdim/// @name Auto-generated Match Functions
317218885Sdim/// {
318218885Sdim
319218885Sdimstatic unsigned MatchRegisterName(StringRef Name);
320218885Sdim
321218885Sdim/// }
322218885Sdim//
323218885Sdimbool MBlazeAsmParser::
324243830SdimMatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
325218885Sdim                        SmallVectorImpl<MCParsedAsmOperand*> &Operands,
326243830Sdim                        MCStreamer &Out, unsigned &ErrorInfo,
327243830Sdim                        bool MatchingInlineAsm) {
328218885Sdim  MCInst Inst;
329243830Sdim  switch (MatchInstructionImpl(Operands, Inst, ErrorInfo,
330243830Sdim                               MatchingInlineAsm)) {
331226633Sdim  default: break;
332218885Sdim  case Match_Success:
333218885Sdim    Out.EmitInstruction(Inst);
334218885Sdim    return false;
335218885Sdim  case Match_MissingFeature:
336218885Sdim    return Error(IDLoc, "instruction use requires an option to be enabled");
337218885Sdim  case Match_MnemonicFail:
338218885Sdim      return Error(IDLoc, "unrecognized instruction mnemonic");
339243830Sdim  case Match_InvalidOperand: {
340243830Sdim    SMLoc ErrorLoc = IDLoc;
341218885Sdim    if (ErrorInfo != ~0U) {
342218885Sdim      if (ErrorInfo >= Operands.size())
343218885Sdim        return Error(IDLoc, "too few operands for instruction");
344218885Sdim
345218885Sdim      ErrorLoc = ((MBlazeOperand*)Operands[ErrorInfo])->getStartLoc();
346218885Sdim      if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
347218885Sdim    }
348218885Sdim
349218885Sdim    return Error(ErrorLoc, "invalid operand for instruction");
350218885Sdim  }
351243830Sdim  }
352218885Sdim
353218885Sdim  llvm_unreachable("Implement any new match types added!");
354218885Sdim}
355218885Sdim
356218885SdimMBlazeOperand *MBlazeAsmParser::
357218885SdimParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
358218885Sdim  if (Operands.size() != 4)
359218885Sdim    return 0;
360218885Sdim
361218885Sdim  MBlazeOperand &Base = *(MBlazeOperand*)Operands[2];
362218885Sdim  MBlazeOperand &Offset = *(MBlazeOperand*)Operands[3];
363218885Sdim
364218885Sdim  SMLoc S = Base.getStartLoc();
365218885Sdim  SMLoc O = Offset.getStartLoc();
366218885Sdim  SMLoc E = Offset.getEndLoc();
367218885Sdim
368218885Sdim  if (!Base.isReg()) {
369218885Sdim    Error(S, "base address must be a register");
370218885Sdim    return 0;
371218885Sdim  }
372218885Sdim
373218885Sdim  if (!Offset.isReg() && !Offset.isImm()) {
374218885Sdim    Error(O, "offset must be a register or immediate");
375218885Sdim    return 0;
376218885Sdim  }
377218885Sdim
378218885Sdim  MBlazeOperand *Op;
379218885Sdim  if (Offset.isReg())
380218885Sdim    Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getReg(), S, E);
381218885Sdim  else
382218885Sdim    Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getImm(), S, E);
383218885Sdim
384218885Sdim  delete Operands.pop_back_val();
385218885Sdim  delete Operands.pop_back_val();
386218885Sdim  Operands.push_back(Op);
387218885Sdim
388218885Sdim  return Op;
389218885Sdim}
390218885Sdim
391218885Sdimbool MBlazeAsmParser::ParseRegister(unsigned &RegNo,
392218885Sdim                                    SMLoc &StartLoc, SMLoc &EndLoc) {
393249423Sdim  MBlazeOperand *Reg = ParseRegister(StartLoc, EndLoc);
394249423Sdim  if (!Reg)
395249423Sdim    return true;
396249423Sdim  RegNo = Reg->getReg();
397249423Sdim  return false;
398218885Sdim}
399218885Sdim
400249423SdimMBlazeOperand *MBlazeAsmParser::ParseRegister() {
401249423Sdim  SMLoc S, E;
402249423Sdim  return ParseRegister(S, E);
403249423Sdim}
404218885Sdim
405249423SdimMBlazeOperand *MBlazeAsmParser::ParseRegister(SMLoc &StartLoc, SMLoc &EndLoc) {
406249423Sdim  StartLoc = Parser.getTok().getLoc();
407249423Sdim  EndLoc = Parser.getTok().getEndLoc();
408218885Sdim
409249423Sdim  if (getLexer().getKind() != AsmToken::Identifier)
410249423Sdim    return 0;
411249423Sdim
412249423Sdim  unsigned RegNo = MatchRegisterName(getLexer().getTok().getIdentifier());
413249423Sdim  if (RegNo == 0)
414249423Sdim    return 0;
415249423Sdim
416249423Sdim  getLexer().Lex();
417249423Sdim  return MBlazeOperand::CreateReg(RegNo, StartLoc, EndLoc);
418218885Sdim}
419218885Sdim
420218885Sdimstatic unsigned MatchFslRegister(StringRef String) {
421218885Sdim  if (!String.startswith("rfsl"))
422218885Sdim    return -1;
423218885Sdim
424218885Sdim  unsigned regNum;
425218885Sdim  if (String.substr(4).getAsInteger(10,regNum))
426218885Sdim    return -1;
427218885Sdim
428218885Sdim  return regNum;
429218885Sdim}
430218885Sdim
431218885SdimMBlazeOperand *MBlazeAsmParser::ParseFsl() {
432218885Sdim  SMLoc S = Parser.getTok().getLoc();
433249423Sdim  SMLoc E = Parser.getTok().getEndLoc();
434218885Sdim
435218885Sdim  switch (getLexer().getKind()) {
436218885Sdim  default: return 0;
437218885Sdim  case AsmToken::Identifier:
438218885Sdim    unsigned reg = MatchFslRegister(getLexer().getTok().getIdentifier());
439218885Sdim    if (reg >= 16)
440218885Sdim      return 0;
441218885Sdim
442218885Sdim    getLexer().Lex();
443218885Sdim    const MCExpr *EVal = MCConstantExpr::Create(reg,getContext());
444218885Sdim    return MBlazeOperand::CreateFslImm(EVal,S,E);
445218885Sdim  }
446218885Sdim}
447218885Sdim
448218885SdimMBlazeOperand *MBlazeAsmParser::ParseImmediate() {
449218885Sdim  SMLoc S = Parser.getTok().getLoc();
450249423Sdim  SMLoc E = Parser.getTok().getEndLoc();
451218885Sdim
452218885Sdim  const MCExpr *EVal;
453218885Sdim  switch (getLexer().getKind()) {
454218885Sdim  default: return 0;
455218885Sdim  case AsmToken::LParen:
456218885Sdim  case AsmToken::Plus:
457218885Sdim  case AsmToken::Minus:
458218885Sdim  case AsmToken::Integer:
459218885Sdim  case AsmToken::Identifier:
460249423Sdim    if (getParser().parseExpression(EVal))
461218885Sdim      return 0;
462218885Sdim
463218885Sdim    return MBlazeOperand::CreateImm(EVal, S, E);
464218885Sdim  }
465218885Sdim}
466218885Sdim
467218885SdimMBlazeOperand *MBlazeAsmParser::
468218885SdimParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
469218885Sdim  MBlazeOperand *Op;
470218885Sdim
471218885Sdim  // Attempt to parse the next token as a register name
472249423Sdim  Op = ParseRegister();
473218885Sdim
474218885Sdim  // Attempt to parse the next token as an FSL immediate
475218885Sdim  if (!Op)
476218885Sdim    Op = ParseFsl();
477218885Sdim
478218885Sdim  // Attempt to parse the next token as an immediate
479218885Sdim  if (!Op)
480218885Sdim    Op = ParseImmediate();
481218885Sdim
482218885Sdim  // If the token could not be parsed then fail
483218885Sdim  if (!Op) {
484218885Sdim    Error(Parser.getTok().getLoc(), "unknown operand");
485218885Sdim    return 0;
486218885Sdim  }
487218885Sdim
488218885Sdim  // Push the parsed operand into the list of operands
489218885Sdim  Operands.push_back(Op);
490218885Sdim  return Op;
491218885Sdim}
492218885Sdim
493218885Sdim/// Parse an mblaze instruction mnemonic followed by its operands.
494218885Sdimbool MBlazeAsmParser::
495243830SdimParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
496218885Sdim                 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
497218885Sdim  // The first operands is the token for the instruction name
498218885Sdim  size_t dotLoc = Name.find('.');
499218885Sdim  Operands.push_back(MBlazeOperand::CreateToken(Name.substr(0,dotLoc),NameLoc));
500218885Sdim  if (dotLoc < Name.size())
501218885Sdim    Operands.push_back(MBlazeOperand::CreateToken(Name.substr(dotLoc),NameLoc));
502218885Sdim
503218885Sdim  // If there are no more operands then finish
504218885Sdim  if (getLexer().is(AsmToken::EndOfStatement))
505218885Sdim    return false;
506218885Sdim
507218885Sdim  // Parse the first operand
508218885Sdim  if (!ParseOperand(Operands))
509218885Sdim    return true;
510218885Sdim
511218885Sdim  while (getLexer().isNot(AsmToken::EndOfStatement) &&
512218885Sdim         getLexer().is(AsmToken::Comma)) {
513218885Sdim    // Consume the comma token
514218885Sdim    getLexer().Lex();
515218885Sdim
516218885Sdim    // Parse the next operand
517218885Sdim    if (!ParseOperand(Operands))
518218885Sdim      return true;
519218885Sdim  }
520218885Sdim
521218885Sdim  // If the instruction requires a memory operand then we need to
522218885Sdim  // replace the last two operands (base+offset) with a single
523218885Sdim  // memory operand.
524218885Sdim  if (Name.startswith("lw") || Name.startswith("sw") ||
525218885Sdim      Name.startswith("lh") || Name.startswith("sh") ||
526218885Sdim      Name.startswith("lb") || Name.startswith("sb"))
527218885Sdim    return (ParseMemory(Operands) == NULL);
528218885Sdim
529218885Sdim  return false;
530218885Sdim}
531218885Sdim
532226633Sdim/// ParseDirective parses the MBlaze specific directives
533218885Sdimbool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) {
534218885Sdim  StringRef IDVal = DirectiveID.getIdentifier();
535218885Sdim  if (IDVal == ".word")
536218885Sdim    return ParseDirectiveWord(2, DirectiveID.getLoc());
537218885Sdim  return true;
538218885Sdim}
539218885Sdim
540218885Sdim/// ParseDirectiveWord
541218885Sdim///  ::= .word [ expression (, expression)* ]
542218885Sdimbool MBlazeAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
543218885Sdim  if (getLexer().isNot(AsmToken::EndOfStatement)) {
544218885Sdim    for (;;) {
545218885Sdim      const MCExpr *Value;
546249423Sdim      if (getParser().parseExpression(Value))
547218885Sdim        return true;
548218885Sdim
549249423Sdim      getParser().getStreamer().EmitValue(Value, Size);
550218885Sdim
551218885Sdim      if (getLexer().is(AsmToken::EndOfStatement))
552218885Sdim        break;
553218885Sdim
554218885Sdim      // FIXME: Improve diagnostic.
555218885Sdim      if (getLexer().isNot(AsmToken::Comma))
556218885Sdim        return Error(L, "unexpected token in directive");
557218885Sdim      Parser.Lex();
558218885Sdim    }
559218885Sdim  }
560218885Sdim
561218885Sdim  Parser.Lex();
562218885Sdim  return false;
563218885Sdim}
564218885Sdim
565218885Sdim/// Force static initialization.
566218885Sdimextern "C" void LLVMInitializeMBlazeAsmParser() {
567226633Sdim  RegisterMCAsmParser<MBlazeAsmParser> X(TheMBlazeTarget);
568218885Sdim}
569218885Sdim
570218885Sdim#define GET_REGISTER_MATCHER
571218885Sdim#define GET_MATCHER_IMPLEMENTATION
572218885Sdim#include "MBlazeGenAsmMatcher.inc"
573