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