MipsAsmParser.cpp revision 3ebe59c892051375623fea55e977ff559fdb3323
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, SMLoc &E);
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  SMLoc E = Parser.getTok().getEndLoc();
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, E));
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(Identifier.end());
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    SMLoc E;
784    if (getParser().ParseExpression(IdVal, E))
785      return true;
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    SMLoc E;
794    if (parseRelocOperand(IdVal, E))
795      return true;
796
797    Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
798    return false;
799  } // case AsmToken::Percent
800  } // switch(getLexer().getKind())
801  return true;
802}
803
804bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res, SMLoc &EndLoc) {
805
806  Parser.Lex(); // eat % token
807  const AsmToken &Tok = Parser.getTok(); // get next token, operation
808  if (Tok.isNot(AsmToken::Identifier))
809    return true;
810
811  std::string Str = Tok.getIdentifier().str();
812
813  Parser.Lex(); // eat identifier
814  // now make expression from the rest of the operand
815  const MCExpr *IdVal;
816
817  if (getLexer().getKind() == AsmToken::LParen) {
818    while (1) {
819      Parser.Lex(); // eat '(' token
820      if (getLexer().getKind() == AsmToken::Percent) {
821        Parser.Lex(); // eat % token
822        const AsmToken &nextTok = Parser.getTok();
823        if (nextTok.isNot(AsmToken::Identifier))
824          return true;
825        Str += "(%";
826        Str += nextTok.getIdentifier();
827        Parser.Lex(); // eat identifier
828        if (getLexer().getKind() != AsmToken::LParen)
829          return true;
830      } else
831        break;
832    }
833    if (getParser().ParseParenExpression(IdVal,EndLoc))
834      return true;
835
836    while (getLexer().getKind() == AsmToken::RParen) {
837      EndLoc = Parser.getTok().getEndLoc();
838      Parser.Lex(); // eat ')' token
839    }
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  EndLoc = Parser.getTok().getEndLoc();
872  RegNo = tryParseRegister("");
873  return (RegNo == (unsigned)-1);
874}
875
876bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
877  switch(getLexer().getKind()) {
878  default:
879    return true;
880  case AsmToken::Integer:
881  case AsmToken::Minus:
882  case AsmToken::Plus:
883    return getParser().ParseExpression(Res);
884  case AsmToken::Percent: {
885    SMLoc E;
886    return parseRelocOperand(Res, E);
887  }
888  case AsmToken::LParen:
889    return false;  // it's probably assuming 0
890  }
891  return true;
892}
893
894MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
895               SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
896
897  const MCExpr *IdVal = 0;
898  SMLoc S = Parser.getTok().getLoc();
899  SMLoc E = Parser.getTok().getEndLoc();
900
901  if (parseMemOffset(IdVal))
902    return MatchOperand_ParseFail;
903
904  const AsmToken &Tok = Parser.getTok(); // get next token
905  if (Tok.isNot(AsmToken::LParen)) {
906    MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
907    if (Mnemonic->getToken() == "la") {
908      Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
909      return MatchOperand_Success;
910    }
911    Error(Parser.getTok().getLoc(), "'(' expected");
912    return MatchOperand_ParseFail;
913  }
914
915  Parser.Lex(); // Eat '(' token.
916
917  const AsmToken &Tok1 = Parser.getTok(); // get next token
918  if (Tok1.is(AsmToken::Dollar)) {
919    Parser.Lex(); // Eat '$' token.
920    if (tryParseRegisterOperand(Operands,"")) {
921      Error(Parser.getTok().getLoc(), "unexpected token in operand");
922      return MatchOperand_ParseFail;
923    }
924
925  } else {
926    Error(Parser.getTok().getLoc(), "unexpected token in operand");
927    return MatchOperand_ParseFail;
928  }
929
930  const AsmToken &Tok2 = Parser.getTok(); // get next token
931  if (Tok2.isNot(AsmToken::RParen)) {
932    Error(Parser.getTok().getLoc(), "')' expected");
933    return MatchOperand_ParseFail;
934  }
935
936  E = Parser.getTok().getEndLoc();
937  Parser.Lex(); // Eat ')' token.
938
939  if (IdVal == 0)
940    IdVal = MCConstantExpr::Create(0, getContext());
941
942  // now replace register operand with the mem operand
943  MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
944  int RegNo = op->getReg();
945  // remove register from operands
946  Operands.pop_back();
947  // and add memory operand
948  Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
949  delete op;
950  return MatchOperand_Success;
951}
952
953MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
954
955  MCSymbolRefExpr::VariantKind VK
956                   = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
957    .Case("hi",          MCSymbolRefExpr::VK_Mips_ABS_HI)
958    .Case("lo",          MCSymbolRefExpr::VK_Mips_ABS_LO)
959    .Case("gp_rel",      MCSymbolRefExpr::VK_Mips_GPREL)
960    .Case("call16",      MCSymbolRefExpr::VK_Mips_GOT_CALL)
961    .Case("got",         MCSymbolRefExpr::VK_Mips_GOT)
962    .Case("tlsgd",       MCSymbolRefExpr::VK_Mips_TLSGD)
963    .Case("tlsldm",      MCSymbolRefExpr::VK_Mips_TLSLDM)
964    .Case("dtprel_hi",   MCSymbolRefExpr::VK_Mips_DTPREL_HI)
965    .Case("dtprel_lo",   MCSymbolRefExpr::VK_Mips_DTPREL_LO)
966    .Case("gottprel",    MCSymbolRefExpr::VK_Mips_GOTTPREL)
967    .Case("tprel_hi",    MCSymbolRefExpr::VK_Mips_TPREL_HI)
968    .Case("tprel_lo",    MCSymbolRefExpr::VK_Mips_TPREL_LO)
969    .Case("got_disp",    MCSymbolRefExpr::VK_Mips_GOT_DISP)
970    .Case("got_page",    MCSymbolRefExpr::VK_Mips_GOT_PAGE)
971    .Case("got_ofst",    MCSymbolRefExpr::VK_Mips_GOT_OFST)
972    .Case("hi(%neg(%gp_rel",    MCSymbolRefExpr::VK_Mips_GPOFF_HI)
973    .Case("lo(%neg(%gp_rel",    MCSymbolRefExpr::VK_Mips_GPOFF_LO)
974    .Default(MCSymbolRefExpr::VK_None);
975
976  return VK;
977}
978
979static int ConvertCcString(StringRef CondString) {
980  int CC = StringSwitch<unsigned>(CondString)
981      .Case(".f",    0)
982      .Case(".un",   1)
983      .Case(".eq",   2)
984      .Case(".ueq",  3)
985      .Case(".olt",  4)
986      .Case(".ult",  5)
987      .Case(".ole",  6)
988      .Case(".ule",  7)
989      .Case(".sf",   8)
990      .Case(".ngle", 9)
991      .Case(".seq",  10)
992      .Case(".ngl",  11)
993      .Case(".lt",   12)
994      .Case(".nge",  13)
995      .Case(".le",   14)
996      .Case(".ngt",  15)
997      .Default(-1);
998
999  return CC;
1000}
1001
1002bool MipsAsmParser::
1003parseMathOperation(StringRef Name, SMLoc NameLoc,
1004                   SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1005  // split the format
1006  size_t Start = Name.find('.'), Next = Name.rfind('.');
1007  StringRef Format1 = Name.slice(Start, Next);
1008  // and add the first format to the operands
1009  Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
1010  // now for the second format
1011  StringRef Format2 = Name.slice(Next, StringRef::npos);
1012  Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1013
1014  // set the format for the first register
1015  setFpFormat(Format1);
1016
1017  // Read the remaining operands.
1018  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1019    // Read the first operand.
1020    if (ParseOperand(Operands, Name)) {
1021      SMLoc Loc = getLexer().getLoc();
1022      Parser.EatToEndOfStatement();
1023      return Error(Loc, "unexpected token in argument list");
1024    }
1025
1026    if (getLexer().isNot(AsmToken::Comma)) {
1027      SMLoc Loc = getLexer().getLoc();
1028      Parser.EatToEndOfStatement();
1029      return Error(Loc, "unexpected token in argument list");
1030
1031    }
1032    Parser.Lex();  // Eat the comma.
1033
1034    //set the format for the first register
1035    setFpFormat(Format2);
1036
1037    // Parse and remember the operand.
1038    if (ParseOperand(Operands, Name)) {
1039      SMLoc Loc = getLexer().getLoc();
1040      Parser.EatToEndOfStatement();
1041      return Error(Loc, "unexpected token in argument list");
1042    }
1043  }
1044
1045  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1046    SMLoc Loc = getLexer().getLoc();
1047    Parser.EatToEndOfStatement();
1048    return Error(Loc, "unexpected token in argument list");
1049  }
1050
1051  Parser.Lex(); // Consume the EndOfStatement
1052  return false;
1053}
1054
1055bool MipsAsmParser::
1056ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
1057                 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1058  // floating point instructions: should register be treated as double?
1059  if (requestsDoubleOperand(Name)) {
1060    setFpFormat(FP_FORMAT_D);
1061  Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
1062  }
1063  else {
1064    setDefaultFpFormat();
1065    // Create the leading tokens for the mnemonic, split by '.' characters.
1066    size_t Start = 0, Next = Name.find('.');
1067    StringRef Mnemonic = Name.slice(Start, Next);
1068
1069    Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1070
1071    if (Next != StringRef::npos) {
1072      // there is a format token in mnemonic
1073      // StringRef Rest = Name.slice(Next, StringRef::npos);
1074      size_t Dot = Name.find('.', Next+1);
1075      StringRef Format = Name.slice(Next, Dot);
1076      if (Dot == StringRef::npos) //only one '.' in a string, it's a format
1077        Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1078      else {
1079        if (Name.startswith("c.")){
1080          // floating point compare, add '.' and immediate represent for cc
1081          Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1082          int Cc = ConvertCcString(Format);
1083          if (Cc == -1) {
1084            return Error(NameLoc, "Invalid conditional code");
1085          }
1086          // FIXME: May include trailing whitespace...
1087          SMLoc E = Parser.getTok().getLoc();
1088          Operands.push_back(MipsOperand::CreateImm(
1089              MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
1090        } else {
1091          // trunc, ceil, floor ...
1092          return parseMathOperation(Name, NameLoc, Operands);
1093        }
1094
1095        // the rest is a format
1096        Format = Name.slice(Dot, StringRef::npos);
1097        Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1098      }
1099
1100      setFpFormat(Format);
1101    }
1102  }
1103
1104  // Read the remaining operands.
1105  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1106    // Read the first operand.
1107    if (ParseOperand(Operands, Name)) {
1108      SMLoc Loc = getLexer().getLoc();
1109      Parser.EatToEndOfStatement();
1110      return Error(Loc, "unexpected token in argument list");
1111    }
1112
1113    while (getLexer().is(AsmToken::Comma) ) {
1114      Parser.Lex();  // Eat the comma.
1115
1116      // Parse and remember the operand.
1117      if (ParseOperand(Operands, Name)) {
1118        SMLoc Loc = getLexer().getLoc();
1119        Parser.EatToEndOfStatement();
1120        return Error(Loc, "unexpected token in argument list");
1121      }
1122    }
1123  }
1124
1125  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1126    SMLoc Loc = getLexer().getLoc();
1127    Parser.EatToEndOfStatement();
1128    return Error(Loc, "unexpected token in argument list");
1129  }
1130
1131  Parser.Lex(); // Consume the EndOfStatement
1132  return false;
1133}
1134
1135bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1136   SMLoc Loc = getLexer().getLoc();
1137   Parser.EatToEndOfStatement();
1138   return Error(Loc, ErrorMsg);
1139}
1140
1141bool MipsAsmParser::parseSetNoAtDirective() {
1142  // line should look like:
1143  //  .set noat
1144  // set at reg to 0
1145  Options.setATReg(0);
1146  // eat noat
1147  Parser.Lex();
1148  // if this is not the end of the statement, report error
1149  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1150    reportParseError("unexpected token in statement");
1151    return false;
1152  }
1153  Parser.Lex(); // Consume the EndOfStatement
1154  return false;
1155}
1156bool MipsAsmParser::parseSetAtDirective() {
1157  // line can be
1158  //  .set at - defaults to $1
1159  // or .set at=$reg
1160  getParser().Lex();
1161  if (getLexer().is(AsmToken::EndOfStatement)) {
1162    Options.setATReg(1);
1163    Parser.Lex(); // Consume the EndOfStatement
1164    return false;
1165  } else if (getLexer().is(AsmToken::Equal)) {
1166    getParser().Lex(); //eat '='
1167    if (getLexer().isNot(AsmToken::Dollar)) {
1168      reportParseError("unexpected token in statement");
1169      return false;
1170    }
1171    Parser.Lex(); // eat '$'
1172    if (getLexer().isNot(AsmToken::Integer)) {
1173      reportParseError("unexpected token in statement");
1174      return false;
1175    }
1176    const AsmToken &Reg = Parser.getTok();
1177    if (!Options.setATReg(Reg.getIntVal())) {
1178      reportParseError("unexpected token in statement");
1179      return false;
1180    }
1181    getParser().Lex(); //eat reg
1182
1183    if (getLexer().isNot(AsmToken::EndOfStatement)) {
1184      reportParseError("unexpected token in statement");
1185      return false;
1186     }
1187    Parser.Lex(); // Consume the EndOfStatement
1188    return false;
1189  } else {
1190    reportParseError("unexpected token in statement");
1191    return false;
1192  }
1193}
1194
1195bool MipsAsmParser::parseSetReorderDirective() {
1196  Parser.Lex();
1197  // if this is not the end of the statement, report error
1198  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1199    reportParseError("unexpected token in statement");
1200    return false;
1201  }
1202  Options.setReorder();
1203  Parser.Lex(); // Consume the EndOfStatement
1204  return false;
1205}
1206
1207bool MipsAsmParser::parseSetNoReorderDirective() {
1208    Parser.Lex();
1209    // if this is not the end of the statement, report error
1210    if (getLexer().isNot(AsmToken::EndOfStatement)) {
1211      reportParseError("unexpected token in statement");
1212      return false;
1213    }
1214    Options.setNoreorder();
1215    Parser.Lex(); // Consume the EndOfStatement
1216    return false;
1217}
1218
1219bool MipsAsmParser::parseSetMacroDirective() {
1220  Parser.Lex();
1221  // if this is not the end of the statement, report error
1222  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1223    reportParseError("unexpected token in statement");
1224    return false;
1225  }
1226  Options.setMacro();
1227  Parser.Lex(); // Consume the EndOfStatement
1228  return false;
1229}
1230
1231bool MipsAsmParser::parseSetNoMacroDirective() {
1232  Parser.Lex();
1233  // if this is not the end of the statement, report error
1234  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1235    reportParseError("`noreorder' must be set before `nomacro'");
1236    return false;
1237  }
1238  if (Options.isReorder()) {
1239    reportParseError("`noreorder' must be set before `nomacro'");
1240    return false;
1241  }
1242  Options.setNomacro();
1243  Parser.Lex(); // Consume the EndOfStatement
1244  return false;
1245}
1246bool MipsAsmParser::parseDirectiveSet() {
1247
1248  // get next token
1249  const AsmToken &Tok = Parser.getTok();
1250
1251  if (Tok.getString() == "noat") {
1252    return parseSetNoAtDirective();
1253  } else if (Tok.getString() == "at") {
1254    return parseSetAtDirective();
1255  } else if (Tok.getString() == "reorder") {
1256    return parseSetReorderDirective();
1257  } else if (Tok.getString() == "noreorder") {
1258    return parseSetNoReorderDirective();
1259  } else if (Tok.getString() == "macro") {
1260    return parseSetMacroDirective();
1261  } else if (Tok.getString() == "nomacro") {
1262    return parseSetNoMacroDirective();
1263  } else if (Tok.getString() == "nomips16") {
1264    // ignore this directive for now
1265    Parser.EatToEndOfStatement();
1266    return false;
1267  } else if (Tok.getString() == "nomicromips") {
1268    // ignore this directive for now
1269    Parser.EatToEndOfStatement();
1270    return false;
1271  }
1272  return true;
1273}
1274
1275bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
1276
1277  if (DirectiveID.getString() == ".ent") {
1278    // ignore this directive for now
1279    Parser.Lex();
1280    return false;
1281  }
1282
1283  if (DirectiveID.getString() == ".end") {
1284    // ignore this directive for now
1285    Parser.Lex();
1286    return false;
1287  }
1288
1289  if (DirectiveID.getString() == ".frame") {
1290    // ignore this directive for now
1291    Parser.EatToEndOfStatement();
1292    return false;
1293  }
1294
1295  if (DirectiveID.getString() == ".set") {
1296    return parseDirectiveSet();
1297  }
1298
1299  if (DirectiveID.getString() == ".fmask") {
1300    // ignore this directive for now
1301    Parser.EatToEndOfStatement();
1302    return false;
1303  }
1304
1305  if (DirectiveID.getString() == ".mask") {
1306    // ignore this directive for now
1307    Parser.EatToEndOfStatement();
1308    return false;
1309  }
1310
1311  if (DirectiveID.getString() == ".gpword") {
1312    // ignore this directive for now
1313    Parser.EatToEndOfStatement();
1314    return false;
1315  }
1316
1317  return true;
1318}
1319
1320extern "C" void LLVMInitializeMipsAsmParser() {
1321  RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1322  RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1323  RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1324  RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1325}
1326
1327#define GET_REGISTER_MATCHER
1328#define GET_MATCHER_IMPLEMENTATION
1329#include "MipsGenAsmMatcher.inc"
1330