MipsAsmParser.cpp revision 9ba9d4d76bfa8de2b05cbce02a5a3ff7d46cb331
1a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
2a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin//
3a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin//                     The LLVM Compiler Infrastructure
4a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin//
5a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// This file is distributed under the University of Illinois Open Source
6a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// License. See LICENSE.TXT for details.
7a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin//
8a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin//===----------------------------------------------------------------------===//
9a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
10a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "MCTargetDesc/MipsMCTargetDesc.h"
11a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "MipsRegisterInfo.h"
12a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "llvm/ADT/StringSwitch.h"
13a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "llvm/MC/MCContext.h"
14a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "llvm/MC/MCExpr.h"
15a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "llvm/MC/MCInst.h"
16a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "llvm/MC/MCStreamer.h"
17a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "llvm/MC/MCSubtargetInfo.h"
18a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "llvm/MC/MCSymbol.h"
19a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "llvm/MC/MCParser/MCAsmLexer.h"
20a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
21a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "llvm/MC/MCTargetAsmParser.h"
22a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "llvm/Support/TargetRegistry.h"
23a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
24a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinusing namespace llvm;
25a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
26a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinnamespace {
27a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinclass MipsAssemblerOptions {
28a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinpublic:
29a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  MipsAssemblerOptions():
30a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    aTReg(1), reorder(true), macro(true) {
31a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  }
32a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
33a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  unsigned getATRegNum() {return aTReg;}
34a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  bool setATReg(unsigned Reg);
35a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
36a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  bool isReorder() {return reorder;}
37a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  void setReorder() {reorder = true;}
38a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  void setNoreorder() {reorder = false;}
39a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
40a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  bool isMacro() {return macro;}
41a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  void setMacro() {macro = true;}
42a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  void setNomacro() {macro = false;}
43a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
44a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinprivate:
45a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  unsigned aTReg;
46a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  bool reorder;
47a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  bool macro;
48a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin};
49a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
50a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
51a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinnamespace {
52a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinclass MipsAsmParser : public MCTargetAsmParser {
53a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
54a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  enum FpFormatTy {
55a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    FP_FORMAT_NONE = -1,
56a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    FP_FORMAT_S,
57a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    FP_FORMAT_D,
58a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    FP_FORMAT_L,
59a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    FP_FORMAT_W
60a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  } FpFormat;
61a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
62a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  MCSubtargetInfo &STI;
63a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  MCAsmParser &Parser;
64a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  MipsAssemblerOptions *Options;
65a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
66
67#define GET_ASSEMBLER_HEADER
68#include "MipsGenAsmMatcher.inc"
69
70  bool MatchAndEmitInstruction(SMLoc IDLoc,
71                               SmallVectorImpl<MCParsedAsmOperand*> &Operands,
72                               MCStreamer &Out);
73
74  bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
75
76  bool ParseInstruction(StringRef Name, SMLoc NameLoc,
77                        SmallVectorImpl<MCParsedAsmOperand*> &Operands);
78
79  bool parseMathOperation(StringRef Name, SMLoc NameLoc,
80                        SmallVectorImpl<MCParsedAsmOperand*> &Operands);
81
82  bool ParseDirective(AsmToken DirectiveID);
83
84  MipsAsmParser::OperandMatchResultTy
85  parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*>&);
86
87  bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
88                    StringRef Mnemonic);
89
90  int tryParseRegister(StringRef Mnemonic);
91
92  bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
93                               StringRef Mnemonic);
94
95  bool needsExpansion(MCInst &Inst);
96
97  void expandInstruction(MCInst &Inst, SMLoc IDLoc,
98                         SmallVectorImpl<MCInst*> &Instructions);
99  void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
100                     SmallVectorImpl<MCInst*> &Instructions);
101  bool reportParseError(StringRef ErrorMsg);
102
103  bool parseMemOffset(const MCExpr *&Res);
104  bool parseRelocOperand(const MCExpr *&Res);
105
106  bool parseDirectiveSet();
107
108  bool parseSetAtDirective();
109  bool parseSetNoAtDirective();
110  bool parseSetMacroDirective();
111  bool parseSetNoMacroDirective();
112  bool parseSetReorderDirective();
113  bool parseSetNoReorderDirective();
114
115  MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
116
117  bool isMips64() const {
118    return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
119  }
120
121  bool isFP64() const {
122    return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
123  }
124
125  int matchRegisterName(StringRef Symbol);
126
127  int matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic);
128
129  void setFpFormat(FpFormatTy Format) {
130    FpFormat = Format;
131  }
132
133  void setDefaultFpFormat();
134
135  void setFpFormat(StringRef Format);
136
137  FpFormatTy getFpFormat() {return FpFormat;}
138
139  bool requestsDoubleOperand(StringRef Mnemonic);
140
141  unsigned getReg(int RC,int RegNo);
142
143  unsigned getATReg();
144public:
145  MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
146    : MCTargetAsmParser(), STI(sti), Parser(parser) {
147    // Initialize the set of available features.
148    setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
149    Options = new MipsAssemblerOptions();
150  }
151
152  MCAsmParser &getParser() const { return Parser; }
153  MCAsmLexer &getLexer() const { return Parser.getLexer(); }
154
155};
156}
157
158namespace {
159
160/// MipsOperand - Instances of this class represent a parsed Mips machine
161/// instruction.
162class MipsOperand : public MCParsedAsmOperand {
163
164  enum KindTy {
165    k_CondCode,
166    k_CoprocNum,
167    k_Immediate,
168    k_Memory,
169    k_PostIndexRegister,
170    k_Register,
171    k_Token
172  } Kind;
173
174  MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
175
176  union {
177    struct {
178      const char *Data;
179      unsigned Length;
180    } Tok;
181
182    struct {
183      unsigned RegNum;
184    } Reg;
185
186    struct {
187      const MCExpr *Val;
188    } Imm;
189
190    struct {
191      unsigned Base;
192      const MCExpr *Off;
193    } Mem;
194  };
195
196  SMLoc StartLoc, EndLoc;
197
198public:
199  void addRegOperands(MCInst &Inst, unsigned N) const {
200    assert(N == 1 && "Invalid number of operands!");
201    Inst.addOperand(MCOperand::CreateReg(getReg()));
202  }
203
204  void addExpr(MCInst &Inst, const MCExpr *Expr) const{
205    // Add as immediate when possible.  Null MCExpr = 0.
206    if (Expr == 0)
207      Inst.addOperand(MCOperand::CreateImm(0));
208    else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
209      Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
210    else
211      Inst.addOperand(MCOperand::CreateExpr(Expr));
212  }
213
214  void addImmOperands(MCInst &Inst, unsigned N) const {
215    assert(N == 1 && "Invalid number of operands!");
216    const MCExpr *Expr = getImm();
217    addExpr(Inst,Expr);
218  }
219
220  void addMemOperands(MCInst &Inst, unsigned N) const {
221    assert(N == 2 && "Invalid number of operands!");
222
223    Inst.addOperand(MCOperand::CreateReg(getMemBase()));
224
225    const MCExpr *Expr = getMemOff();
226    addExpr(Inst,Expr);
227  }
228
229  bool isReg() const { return Kind == k_Register; }
230  bool isImm() const { return Kind == k_Immediate; }
231  bool isToken() const { return Kind == k_Token; }
232  bool isMem() const { return Kind == k_Memory; }
233
234  StringRef getToken() const {
235    assert(Kind == k_Token && "Invalid access!");
236    return StringRef(Tok.Data, Tok.Length);
237  }
238
239  unsigned getReg() const {
240    assert((Kind == k_Register) && "Invalid access!");
241    return Reg.RegNum;
242  }
243
244  const MCExpr *getImm() const {
245    assert((Kind == k_Immediate) && "Invalid access!");
246    return Imm.Val;
247  }
248
249  unsigned getMemBase() const {
250    assert((Kind == k_Memory) && "Invalid access!");
251    return Mem.Base;
252  }
253
254  const MCExpr *getMemOff() const {
255    assert((Kind == k_Memory) && "Invalid access!");
256    return Mem.Off;
257  }
258
259  static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
260    MipsOperand *Op = new MipsOperand(k_Token);
261    Op->Tok.Data = Str.data();
262    Op->Tok.Length = Str.size();
263    Op->StartLoc = S;
264    Op->EndLoc = S;
265    return Op;
266  }
267
268  static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
269    MipsOperand *Op = new MipsOperand(k_Register);
270    Op->Reg.RegNum = RegNum;
271    Op->StartLoc = S;
272    Op->EndLoc = E;
273    return Op;
274  }
275
276  static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
277    MipsOperand *Op = new MipsOperand(k_Immediate);
278    Op->Imm.Val = Val;
279    Op->StartLoc = S;
280    Op->EndLoc = E;
281    return Op;
282  }
283
284  static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
285                                 SMLoc S, SMLoc E) {
286    MipsOperand *Op = new MipsOperand(k_Memory);
287    Op->Mem.Base = Base;
288    Op->Mem.Off = Off;
289    Op->StartLoc = S;
290    Op->EndLoc = E;
291    return Op;
292  }
293
294  /// getStartLoc - Get the location of the first token of this operand.
295  SMLoc getStartLoc() const { return StartLoc; }
296  /// getEndLoc - Get the location of the last token of this operand.
297  SMLoc getEndLoc() const { return EndLoc; }
298
299  virtual void print(raw_ostream &OS) const {
300    llvm_unreachable("unimplemented!");
301  }
302};
303}
304
305bool MipsAsmParser::needsExpansion(MCInst &Inst) {
306
307  switch(Inst.getOpcode()) {
308    case Mips::LoadImm32Reg:
309      return true;
310    default:
311      return false;
312  }
313}
314void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
315                        SmallVectorImpl<MCInst*> &Instructions){
316  switch(Inst.getOpcode()) {
317    case Mips::LoadImm32Reg:
318      return expandLoadImm(Inst, IDLoc, Instructions);
319    }
320  return;
321}
322void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
323                        SmallVectorImpl<MCInst*> &Instructions){
324  MCInst *tmpInst = new MCInst();
325  const MCOperand &ImmOp = Inst.getOperand(1);
326  assert(ImmOp.isImm() && "expected imediate operand kind");
327  const MCOperand &RegOp = Inst.getOperand(0);
328  assert(RegOp.isReg() && "expected register operand kind");
329
330  int ImmValue = ImmOp.getImm();
331  tmpInst->setLoc(IDLoc);
332  if ( 0 <= ImmValue && ImmValue <= 65535) {
333    // for 0 = j = 65535.
334    // li d,j => ori d,$zero,j
335    tmpInst->setOpcode(isMips64() ? Mips::ORi64 : Mips::ORi);
336    tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg()));
337    tmpInst->addOperand(
338              MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO));
339    tmpInst->addOperand(MCOperand::CreateImm(ImmValue));
340    Instructions.push_back(tmpInst);
341  } else if ( ImmValue < 0 && ImmValue >= -32768) {
342    // for -32768 = j < 0.
343    // li d,j => addiu d,$zero,j
344    tmpInst->setOpcode(Mips::ADDiu); //TODO:no ADDiu64 in td files?
345    tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg()));
346    tmpInst->addOperand(
347              MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO));
348    tmpInst->addOperand(MCOperand::CreateImm(ImmValue));
349    Instructions.push_back(tmpInst);
350  } else {
351    // for any other value of j that is representable as a 32-bit integer.
352    // li d,j => lui d,hi16(j)
353    // ori d,d,lo16(j)
354    tmpInst->setOpcode(isMips64() ? Mips::LUi64 : Mips::LUi);
355    tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg()));
356    tmpInst->addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
357    Instructions.push_back(tmpInst);
358    tmpInst = new MCInst();
359    tmpInst->setOpcode(isMips64() ? Mips::ORi64 : Mips::ORi);
360    tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg()));
361    tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg()));
362    tmpInst->addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
363    tmpInst->setLoc(IDLoc);
364    Instructions.push_back(tmpInst);
365  }
366}
367bool MipsAsmParser::
368MatchAndEmitInstruction(SMLoc IDLoc,
369                        SmallVectorImpl<MCParsedAsmOperand*> &Operands,
370                        MCStreamer &Out) {
371  MCInst Inst;
372  unsigned Kind;
373  unsigned ErrorInfo;
374  MatchInstMapAndConstraints MapAndConstraints;
375  unsigned MatchResult = MatchInstructionImpl(Operands, Kind, Inst,
376                                              MapAndConstraints, ErrorInfo,
377                                              /*matchingInlineAsm*/ false);
378
379  switch (MatchResult) {
380  default: break;
381  case Match_Success: {
382    if (needsExpansion(Inst)) {
383      SmallVector<MCInst*, 4> Instructions;
384      expandInstruction(Inst, IDLoc, Instructions);
385      for(unsigned i =0; i < Instructions.size(); i++){
386        Inst = *(Instructions[i]);
387        Out.EmitInstruction(Inst);
388      }
389    } else {
390        Inst.setLoc(IDLoc);
391        Out.EmitInstruction(Inst);
392      }
393    return false;
394  }
395  case Match_MissingFeature:
396    Error(IDLoc, "instruction requires a CPU feature not currently enabled");
397    return true;
398  case Match_InvalidOperand: {
399    SMLoc ErrorLoc = IDLoc;
400    if (ErrorInfo != ~0U) {
401      if (ErrorInfo >= Operands.size())
402        return Error(IDLoc, "too few operands for instruction");
403
404      ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
405      if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
406    }
407
408    return Error(ErrorLoc, "invalid operand for instruction");
409  }
410  case Match_MnemonicFail:
411    return Error(IDLoc, "invalid instruction");
412  }
413  return true;
414}
415
416int MipsAsmParser::matchRegisterName(StringRef Name) {
417
418   int CC = StringSwitch<unsigned>(Name)
419    .Case("zero",  Mips::ZERO)
420    .Case("a0",  Mips::A0)
421    .Case("a1",  Mips::A1)
422    .Case("a2",  Mips::A2)
423    .Case("a3",  Mips::A3)
424    .Case("v0",  Mips::V0)
425    .Case("v1",  Mips::V1)
426    .Case("s0",  Mips::S0)
427    .Case("s1",  Mips::S1)
428    .Case("s2",  Mips::S2)
429    .Case("s3",  Mips::S3)
430    .Case("s4",  Mips::S4)
431    .Case("s5",  Mips::S5)
432    .Case("s6",  Mips::S6)
433    .Case("s7",  Mips::S7)
434    .Case("k0",  Mips::K0)
435    .Case("k1",  Mips::K1)
436    .Case("sp",  Mips::SP)
437    .Case("fp",  Mips::FP)
438    .Case("gp",  Mips::GP)
439    .Case("ra",  Mips::RA)
440    .Case("t0",  Mips::T0)
441    .Case("t1",  Mips::T1)
442    .Case("t2",  Mips::T2)
443    .Case("t3",  Mips::T3)
444    .Case("t4",  Mips::T4)
445    .Case("t5",  Mips::T5)
446    .Case("t6",  Mips::T6)
447    .Case("t7",  Mips::T7)
448    .Case("t8",  Mips::T8)
449    .Case("t9",  Mips::T9)
450    .Case("at",  Mips::AT)
451    .Case("fcc0",  Mips::FCC0)
452    .Default(-1);
453
454  if (CC != -1) {
455    // 64 bit register in Mips are following 32 bit definitions.
456    if (isMips64())
457      CC++;
458    return CC;
459  }
460
461  if (Name[0] == 'f') {
462    StringRef NumString = Name.substr(1);
463    unsigned IntVal;
464    if( NumString.getAsInteger(10, IntVal))
465      return -1; // not integer
466    if (IntVal > 31)
467      return -1;
468
469    FpFormatTy Format = getFpFormat();
470
471    if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
472      return getReg(Mips::FGR32RegClassID, IntVal);
473    if (Format == FP_FORMAT_D) {
474      if(isFP64()) {
475        return getReg(Mips::FGR64RegClassID, IntVal);
476      }
477      // only even numbers available as register pairs
478      if (( IntVal > 31) || (IntVal%2 !=  0))
479        return -1;
480      return getReg(Mips::AFGR64RegClassID, IntVal/2);
481    }
482  }
483
484  return -1;
485}
486void MipsAsmParser::setDefaultFpFormat() {
487
488  if (isMips64() || isFP64())
489    FpFormat = FP_FORMAT_D;
490  else
491    FpFormat = FP_FORMAT_S;
492}
493
494bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
495
496  bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
497    .Case("ldxc1", true)
498    .Case("ldc1",  true)
499    .Case("sdxc1", true)
500    .Case("sdc1",  true)
501    .Default(false);
502
503  return IsDouble;
504}
505void MipsAsmParser::setFpFormat(StringRef Format) {
506
507  FpFormat = StringSwitch<FpFormatTy>(Format.lower())
508    .Case(".s",  FP_FORMAT_S)
509    .Case(".d",  FP_FORMAT_D)
510    .Case(".l",  FP_FORMAT_L)
511    .Case(".w",  FP_FORMAT_W)
512    .Default(FP_FORMAT_NONE);
513}
514
515bool MipsAssemblerOptions::setATReg(unsigned Reg) {
516  if (Reg > 31)
517    return false;
518
519  aTReg = Reg;
520  return true;
521}
522
523unsigned MipsAsmParser::getATReg() {
524  unsigned Reg = Options->getATRegNum();
525  if (isMips64())
526    return getReg(Mips::CPU64RegsRegClassID,Reg);
527  else
528    return getReg(Mips::CPURegsRegClassID,Reg);
529}
530
531unsigned MipsAsmParser::getReg(int RC,int RegNo) {
532  return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
533}
534
535int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic) {
536
537  if (Mnemonic.lower() == "rdhwr") {
538    // at the moment only hwreg29 is supported
539    if (RegNum != 29)
540      return -1;
541    return Mips::HWR29;
542  }
543
544  if (RegNum > 31)
545    return -1;
546
547  return getReg(Mips::CPURegsRegClassID, RegNum);
548}
549
550int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
551  const AsmToken &Tok = Parser.getTok();
552  int RegNum = -1;
553
554  if (Tok.is(AsmToken::Identifier)) {
555    std::string lowerCase = Tok.getString().lower();
556    RegNum = matchRegisterName(lowerCase);
557  } else if (Tok.is(AsmToken::Integer))
558    RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
559                                   Mnemonic.lower());
560    else
561      return RegNum;  //error
562  // 64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64
563  if (isMips64() && RegNum == Mips::ZERO_64) {
564    if (Mnemonic.find("ddiv") != StringRef::npos)
565      RegNum = Mips::ZERO;
566  }
567  return RegNum;
568}
569
570bool MipsAsmParser::
571  tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
572                          StringRef Mnemonic){
573
574  SMLoc S = Parser.getTok().getLoc();
575  int RegNo = -1;
576
577  // FIXME: we should make a more generic method for CCR
578  if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
579      && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
580    RegNo = Parser.getTok().getIntVal();  // get the int value
581    // at the moment only fcc0 is supported
582    if (RegNo ==  0)
583      RegNo = Mips::FCC0;
584  } else
585    RegNo = tryParseRegister(Mnemonic);
586  if (RegNo == -1)
587    return true;
588
589  Operands.push_back(MipsOperand::CreateReg(RegNo, S,
590      Parser.getTok().getLoc()));
591  Parser.Lex(); // Eat register token.
592  return false;
593}
594
595bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
596                                 StringRef Mnemonic) {
597  // Check if the current operand has a custom associated parser, if so, try to
598  // custom parse the operand, or fallback to the general approach.
599  OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
600  if (ResTy == MatchOperand_Success)
601    return false;
602  // If there wasn't a custom match, try the generic matcher below. Otherwise,
603  // there was a match, but an error occurred, in which case, just return that
604  // the operand parsing failed.
605  if (ResTy == MatchOperand_ParseFail)
606    return true;
607
608  switch (getLexer().getKind()) {
609  default:
610    Error(Parser.getTok().getLoc(), "unexpected token in operand");
611    return true;
612  case AsmToken::Dollar: {
613    // parse register
614    SMLoc S = Parser.getTok().getLoc();
615    Parser.Lex(); // Eat dollar token.
616    // parse register operand
617    if (!tryParseRegisterOperand(Operands, Mnemonic)) {
618      if (getLexer().is(AsmToken::LParen)) {
619        // check if it is indexed addressing operand
620        Operands.push_back(MipsOperand::CreateToken("(", S));
621        Parser.Lex(); // eat parenthesis
622        if (getLexer().isNot(AsmToken::Dollar))
623          return true;
624
625        Parser.Lex(); // eat dollar
626        if (tryParseRegisterOperand(Operands, Mnemonic))
627          return true;
628
629        if (!getLexer().is(AsmToken::RParen))
630          return true;
631
632        S = Parser.getTok().getLoc();
633        Operands.push_back(MipsOperand::CreateToken(")", S));
634        Parser.Lex();
635      }
636      return false;
637    }
638    // maybe it is a symbol reference
639    StringRef Identifier;
640    if (Parser.ParseIdentifier(Identifier))
641      return true;
642
643    SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
644
645    MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
646
647    // Otherwise create a symbol ref.
648    const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
649                                                getContext());
650
651    Operands.push_back(MipsOperand::CreateImm(Res, S, E));
652    return false;
653  }
654  case AsmToken::Identifier:
655  case AsmToken::LParen:
656  case AsmToken::Minus:
657  case AsmToken::Plus:
658  case AsmToken::Integer:
659  case AsmToken::String: {
660     // quoted label names
661    const MCExpr *IdVal;
662    SMLoc S = Parser.getTok().getLoc();
663    if (getParser().ParseExpression(IdVal))
664      return true;
665    SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
666    Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
667    return false;
668  }
669  case AsmToken::Percent: {
670    // it is a symbol reference or constant expression
671    const MCExpr *IdVal;
672    SMLoc S = Parser.getTok().getLoc(); // start location of the operand
673    if (parseRelocOperand(IdVal))
674      return true;
675
676    SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
677
678    Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
679    return false;
680  } // case AsmToken::Percent
681  } // switch(getLexer().getKind())
682  return true;
683}
684
685bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
686
687  Parser.Lex(); // eat % token
688  const AsmToken &Tok = Parser.getTok(); // get next token, operation
689  if (Tok.isNot(AsmToken::Identifier))
690    return true;
691
692  std::string Str = Tok.getIdentifier().str();
693
694  Parser.Lex(); // eat identifier
695  // now make expression from the rest of the operand
696  const MCExpr *IdVal;
697  SMLoc EndLoc;
698
699  if (getLexer().getKind() == AsmToken::LParen) {
700    while (1) {
701      Parser.Lex(); // eat '(' token
702      if (getLexer().getKind() == AsmToken::Percent) {
703        Parser.Lex(); // eat % token
704        const AsmToken &nextTok = Parser.getTok();
705        if (nextTok.isNot(AsmToken::Identifier))
706          return true;
707        Str += "(%";
708        Str += nextTok.getIdentifier();
709        Parser.Lex(); // eat identifier
710        if (getLexer().getKind() != AsmToken::LParen)
711          return true;
712      } else
713        break;
714    }
715    if (getParser().ParseParenExpression(IdVal,EndLoc))
716      return true;
717
718    while (getLexer().getKind() == AsmToken::RParen)
719      Parser.Lex(); // eat ')' token
720
721  } else
722    return true; // parenthesis must follow reloc operand
723
724  // Check the type of the expression
725  if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
726    // it's a constant, evaluate lo or hi value
727    int Val = MCE->getValue();
728    if (Str == "lo") {
729      Val = Val & 0xffff;
730    } else if (Str == "hi") {
731      Val = (Val & 0xffff0000) >> 16;
732    }
733    Res = MCConstantExpr::Create(Val, getContext());
734    return false;
735  }
736
737  if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
738    // it's a symbol, create symbolic expression from symbol
739    StringRef Symbol = MSRE->getSymbol().getName();
740    MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
741    Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
742    return false;
743  }
744  return true;
745}
746
747bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
748                                  SMLoc &EndLoc) {
749
750  StartLoc = Parser.getTok().getLoc();
751  RegNo = tryParseRegister("");
752  EndLoc = Parser.getTok().getLoc();
753  return (RegNo == (unsigned)-1);
754}
755
756bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
757
758  SMLoc S;
759
760  switch(getLexer().getKind()) {
761  default:
762    return true;
763  case AsmToken::Integer:
764  case AsmToken::Minus:
765  case AsmToken::Plus:
766    return (getParser().ParseExpression(Res));
767  case AsmToken::Percent:
768    return parseRelocOperand(Res);
769  case AsmToken::LParen:
770    return false;  // it's probably assuming 0
771  }
772  return true;
773}
774
775MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
776               SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
777
778  const MCExpr *IdVal = 0;
779  SMLoc S;
780  // first operand is the offset
781  S = Parser.getTok().getLoc();
782
783  if (parseMemOffset(IdVal))
784    return MatchOperand_ParseFail;
785
786  const AsmToken &Tok = Parser.getTok(); // get next token
787  if (Tok.isNot(AsmToken::LParen)) {
788    Error(Parser.getTok().getLoc(), "'(' expected");
789    return MatchOperand_ParseFail;
790  }
791
792  Parser.Lex(); // Eat '(' token.
793
794  const AsmToken &Tok1 = Parser.getTok(); //get next token
795  if (Tok1.is(AsmToken::Dollar)) {
796    Parser.Lex(); // Eat '$' token.
797    if (tryParseRegisterOperand(Operands,"")) {
798      Error(Parser.getTok().getLoc(), "unexpected token in operand");
799      return MatchOperand_ParseFail;
800    }
801
802  } else {
803    Error(Parser.getTok().getLoc(), "unexpected token in operand");
804    return MatchOperand_ParseFail;
805  }
806
807  const AsmToken &Tok2 = Parser.getTok(); // get next token
808  if (Tok2.isNot(AsmToken::RParen)) {
809    Error(Parser.getTok().getLoc(), "')' expected");
810    return MatchOperand_ParseFail;
811  }
812
813  SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
814
815  Parser.Lex(); // Eat ')' token.
816
817  if (IdVal == 0)
818    IdVal = MCConstantExpr::Create(0, getContext());
819
820  // now replace register operand with the mem operand
821  MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
822  int RegNo = op->getReg();
823  // remove register from operands
824  Operands.pop_back();
825  // and add memory operand
826  Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
827  delete op;
828  return MatchOperand_Success;
829}
830
831MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
832
833  MCSymbolRefExpr::VariantKind VK
834                   = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
835    .Case("hi",          MCSymbolRefExpr::VK_Mips_ABS_HI)
836    .Case("lo",          MCSymbolRefExpr::VK_Mips_ABS_LO)
837    .Case("gp_rel",      MCSymbolRefExpr::VK_Mips_GPREL)
838    .Case("call16",      MCSymbolRefExpr::VK_Mips_GOT_CALL)
839    .Case("got",         MCSymbolRefExpr::VK_Mips_GOT)
840    .Case("tlsgd",       MCSymbolRefExpr::VK_Mips_TLSGD)
841    .Case("tlsldm",      MCSymbolRefExpr::VK_Mips_TLSLDM)
842    .Case("dtprel_hi",   MCSymbolRefExpr::VK_Mips_DTPREL_HI)
843    .Case("dtprel_lo",   MCSymbolRefExpr::VK_Mips_DTPREL_LO)
844    .Case("gottprel",    MCSymbolRefExpr::VK_Mips_GOTTPREL)
845    .Case("tprel_hi",    MCSymbolRefExpr::VK_Mips_TPREL_HI)
846    .Case("tprel_lo",    MCSymbolRefExpr::VK_Mips_TPREL_LO)
847    .Case("got_disp",    MCSymbolRefExpr::VK_Mips_GOT_DISP)
848    .Case("got_page",    MCSymbolRefExpr::VK_Mips_GOT_PAGE)
849    .Case("got_ofst",    MCSymbolRefExpr::VK_Mips_GOT_OFST)
850    .Case("hi(%neg(%gp_rel",    MCSymbolRefExpr::VK_Mips_GPOFF_HI)
851    .Case("lo(%neg(%gp_rel",    MCSymbolRefExpr::VK_Mips_GPOFF_LO)
852    .Default(MCSymbolRefExpr::VK_None);
853
854  return VK;
855}
856
857static int ConvertCcString(StringRef CondString) {
858  int CC = StringSwitch<unsigned>(CondString)
859      .Case(".f",    0)
860      .Case(".un",   1)
861      .Case(".eq",   2)
862      .Case(".ueq",  3)
863      .Case(".olt",  4)
864      .Case(".ult",  5)
865      .Case(".ole",  6)
866      .Case(".ule",  7)
867      .Case(".sf",   8)
868      .Case(".ngle", 9)
869      .Case(".seq",  10)
870      .Case(".ngl",  11)
871      .Case(".lt",   12)
872      .Case(".nge",  13)
873      .Case(".le",   14)
874      .Case(".ngt",  15)
875      .Default(-1);
876
877  return CC;
878}
879
880bool MipsAsmParser::
881parseMathOperation(StringRef Name, SMLoc NameLoc,
882                   SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
883  // split the format
884  size_t Start = Name.find('.'), Next = Name.rfind('.');
885  StringRef Format1 = Name.slice(Start, Next);
886  // and add the first format to the operands
887  Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
888  // now for the second format
889  StringRef Format2 = Name.slice(Next, StringRef::npos);
890  Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
891
892  // set the format for the first register
893  setFpFormat(Format1);
894
895  // Read the remaining operands.
896  if (getLexer().isNot(AsmToken::EndOfStatement)) {
897    // Read the first operand.
898    if (ParseOperand(Operands, Name)) {
899      SMLoc Loc = getLexer().getLoc();
900      Parser.EatToEndOfStatement();
901      return Error(Loc, "unexpected token in argument list");
902    }
903
904    if (getLexer().isNot(AsmToken::Comma)) {
905      SMLoc Loc = getLexer().getLoc();
906      Parser.EatToEndOfStatement();
907      return Error(Loc, "unexpected token in argument list");
908
909    }
910    Parser.Lex();  // Eat the comma.
911
912    //set the format for the first register
913    setFpFormat(Format2);
914
915    // Parse and remember the operand.
916    if (ParseOperand(Operands, Name)) {
917      SMLoc Loc = getLexer().getLoc();
918      Parser.EatToEndOfStatement();
919      return Error(Loc, "unexpected token in argument list");
920    }
921  }
922
923  if (getLexer().isNot(AsmToken::EndOfStatement)) {
924    SMLoc Loc = getLexer().getLoc();
925    Parser.EatToEndOfStatement();
926    return Error(Loc, "unexpected token in argument list");
927  }
928
929  Parser.Lex(); // Consume the EndOfStatement
930  return false;
931}
932
933bool MipsAsmParser::
934ParseInstruction(StringRef Name, SMLoc NameLoc,
935                 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
936  // floating point instructions: should register be treated as double?
937  if (requestsDoubleOperand(Name)) {
938    setFpFormat(FP_FORMAT_D);
939  Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
940  }
941  else {
942    setDefaultFpFormat();
943    // Create the leading tokens for the mnemonic, split by '.' characters.
944    size_t Start = 0, Next = Name.find('.');
945    StringRef Mnemonic = Name.slice(Start, Next);
946
947    Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
948
949    if (Next != StringRef::npos) {
950      // there is a format token in mnemonic
951      // StringRef Rest = Name.slice(Next, StringRef::npos);
952      size_t Dot = Name.find('.', Next+1);
953      StringRef Format = Name.slice(Next, Dot);
954      if (Dot == StringRef::npos) //only one '.' in a string, it's a format
955        Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
956      else {
957        if (Name.startswith("c.")){
958          // floating point compare, add '.' and immediate represent for cc
959          Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
960          int Cc = ConvertCcString(Format);
961          if (Cc == -1) {
962            return Error(NameLoc, "Invalid conditional code");
963          }
964          SMLoc E = SMLoc::getFromPointer(
965              Parser.getTok().getLoc().getPointer() -1 );
966          Operands.push_back(MipsOperand::CreateImm(
967              MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
968        } else {
969          // trunc, ceil, floor ...
970          return parseMathOperation(Name, NameLoc, Operands);
971        }
972
973        // the rest is a format
974        Format = Name.slice(Dot, StringRef::npos);
975        Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
976      }
977
978      setFpFormat(Format);
979    }
980  }
981
982  // Read the remaining operands.
983  if (getLexer().isNot(AsmToken::EndOfStatement)) {
984    // Read the first operand.
985    if (ParseOperand(Operands, Name)) {
986      SMLoc Loc = getLexer().getLoc();
987      Parser.EatToEndOfStatement();
988      return Error(Loc, "unexpected token in argument list");
989    }
990
991    while (getLexer().is(AsmToken::Comma) ) {
992      Parser.Lex();  // Eat the comma.
993
994      // Parse and remember the operand.
995      if (ParseOperand(Operands, Name)) {
996        SMLoc Loc = getLexer().getLoc();
997        Parser.EatToEndOfStatement();
998        return Error(Loc, "unexpected token in argument list");
999      }
1000    }
1001  }
1002
1003  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1004    SMLoc Loc = getLexer().getLoc();
1005    Parser.EatToEndOfStatement();
1006    return Error(Loc, "unexpected token in argument list");
1007  }
1008
1009  Parser.Lex(); // Consume the EndOfStatement
1010  return false;
1011}
1012
1013bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1014   SMLoc Loc = getLexer().getLoc();
1015   Parser.EatToEndOfStatement();
1016   return Error(Loc, ErrorMsg);
1017}
1018
1019bool MipsAsmParser::parseSetNoAtDirective() {
1020  // line should look like:
1021  //  .set noat
1022  // set at reg to 0
1023  Options->setATReg(0);
1024  // eat noat
1025  Parser.Lex();
1026  // if this is not the end of the statement, report error
1027  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1028    reportParseError("unexpected token in statement");
1029    return false;
1030  }
1031  Parser.Lex(); // Consume the EndOfStatement
1032  return false;
1033}
1034bool MipsAsmParser::parseSetAtDirective() {
1035  // line can be
1036  //  .set at - defaults to $1
1037  // or .set at=$reg
1038  getParser().Lex();
1039  if (getLexer().is(AsmToken::EndOfStatement)) {
1040    Options->setATReg(1);
1041    Parser.Lex(); // Consume the EndOfStatement
1042    return false;
1043  } else if (getLexer().is(AsmToken::Equal)) {
1044    getParser().Lex(); //eat '='
1045    if (getLexer().isNot(AsmToken::Dollar)) {
1046      reportParseError("unexpected token in statement");
1047      return false;
1048    }
1049    Parser.Lex(); // eat '$'
1050    if (getLexer().isNot(AsmToken::Integer)) {
1051      reportParseError("unexpected token in statement");
1052      return false;
1053    }
1054    const AsmToken &Reg = Parser.getTok();
1055    if (!Options->setATReg(Reg.getIntVal())) {
1056      reportParseError("unexpected token in statement");
1057      return false;
1058    }
1059    getParser().Lex(); //eat reg
1060
1061    if (getLexer().isNot(AsmToken::EndOfStatement)) {
1062      reportParseError("unexpected token in statement");
1063      return false;
1064     }
1065    Parser.Lex(); // Consume the EndOfStatement
1066    return false;
1067  } else {
1068    reportParseError("unexpected token in statement");
1069    return false;
1070  }
1071}
1072
1073bool MipsAsmParser::parseSetReorderDirective() {
1074  Parser.Lex();
1075  // if this is not the end of the statement, report error
1076  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1077    reportParseError("unexpected token in statement");
1078    return false;
1079  }
1080  Options->setReorder();
1081  Parser.Lex(); // Consume the EndOfStatement
1082  return false;
1083}
1084
1085bool MipsAsmParser::parseSetNoReorderDirective() {
1086    Parser.Lex();
1087    // if this is not the end of the statement, report error
1088    if (getLexer().isNot(AsmToken::EndOfStatement)) {
1089      reportParseError("unexpected token in statement");
1090      return false;
1091    }
1092    Options->setNoreorder();
1093    Parser.Lex(); // Consume the EndOfStatement
1094    return false;
1095}
1096
1097bool MipsAsmParser::parseSetMacroDirective() {
1098  Parser.Lex();
1099  // if this is not the end of the statement, report error
1100  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1101    reportParseError("unexpected token in statement");
1102    return false;
1103  }
1104  Options->setMacro();
1105  Parser.Lex(); // Consume the EndOfStatement
1106  return false;
1107}
1108
1109bool MipsAsmParser::parseSetNoMacroDirective() {
1110  Parser.Lex();
1111  // if this is not the end of the statement, report error
1112  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1113    reportParseError("`noreorder' must be set before `nomacro'");
1114    return false;
1115  }
1116  if (Options->isReorder()) {
1117    reportParseError("`noreorder' must be set before `nomacro'");
1118    return false;
1119  }
1120  Options->setNomacro();
1121  Parser.Lex(); // Consume the EndOfStatement
1122  return false;
1123}
1124bool MipsAsmParser::parseDirectiveSet() {
1125
1126  // get next token
1127  const AsmToken &Tok = Parser.getTok();
1128
1129  if (Tok.getString() == "noat") {
1130    return parseSetNoAtDirective();
1131  } else if (Tok.getString() == "at") {
1132    return parseSetAtDirective();
1133  } else if (Tok.getString() == "reorder") {
1134    return parseSetReorderDirective();
1135  } else if (Tok.getString() == "noreorder") {
1136    return parseSetNoReorderDirective();
1137  } else if (Tok.getString() == "macro") {
1138    return parseSetMacroDirective();
1139  } else if (Tok.getString() == "nomacro") {
1140    return parseSetNoMacroDirective();
1141  } else if (Tok.getString() == "nomips16") {
1142    // ignore this directive for now
1143    Parser.EatToEndOfStatement();
1144    return false;
1145  } else if (Tok.getString() == "nomicromips") {
1146    // ignore this directive for now
1147    Parser.EatToEndOfStatement();
1148    return false;
1149  }
1150  return true;
1151}
1152
1153bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
1154
1155  if (DirectiveID.getString() == ".ent") {
1156    // ignore this directive for now
1157    Parser.Lex();
1158    return false;
1159  }
1160
1161  if (DirectiveID.getString() == ".end") {
1162    // ignore this directive for now
1163    Parser.Lex();
1164    return false;
1165  }
1166
1167  if (DirectiveID.getString() == ".frame") {
1168    // ignore this directive for now
1169    Parser.EatToEndOfStatement();
1170    return false;
1171  }
1172
1173  if (DirectiveID.getString() == ".set") {
1174    return parseDirectiveSet();
1175  }
1176
1177  if (DirectiveID.getString() == ".fmask") {
1178    // ignore this directive for now
1179    Parser.EatToEndOfStatement();
1180    return false;
1181  }
1182
1183  if (DirectiveID.getString() == ".mask") {
1184    // ignore this directive for now
1185    Parser.EatToEndOfStatement();
1186    return false;
1187  }
1188
1189  if (DirectiveID.getString() == ".gpword") {
1190    // ignore this directive for now
1191    Parser.EatToEndOfStatement();
1192    return false;
1193  }
1194
1195  return true;
1196}
1197
1198extern "C" void LLVMInitializeMipsAsmParser() {
1199  RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1200  RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1201  RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1202  RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1203}
1204
1205#define GET_REGISTER_MATCHER
1206#define GET_MATCHER_IMPLEMENTATION
1207#include "MipsGenAsmMatcher.inc"
1208