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