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