MipsAsmParser.cpp revision 6e006d3de882784527d4d9cc92b1a91f6773505e
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 ErrorInfo;
460  unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
461                                              /*matchingInlineAsm*/ false);
462
463  switch (MatchResult) {
464  default: break;
465  case Match_Success: {
466    if (needsExpansion(Inst)) {
467      SmallVector<MCInst, 4> Instructions;
468      expandInstruction(Inst, IDLoc, Instructions);
469      for(unsigned i =0; i < Instructions.size(); i++){
470        Out.EmitInstruction(Instructions[i]);
471      }
472    } else {
473        Inst.setLoc(IDLoc);
474        Out.EmitInstruction(Inst);
475      }
476    return false;
477  }
478  case Match_MissingFeature:
479    Error(IDLoc, "instruction requires a CPU feature not currently enabled");
480    return true;
481  case Match_InvalidOperand: {
482    SMLoc ErrorLoc = IDLoc;
483    if (ErrorInfo != ~0U) {
484      if (ErrorInfo >= Operands.size())
485        return Error(IDLoc, "too few operands for instruction");
486
487      ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
488      if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
489    }
490
491    return Error(ErrorLoc, "invalid operand for instruction");
492  }
493  case Match_MnemonicFail:
494    return Error(IDLoc, "invalid instruction");
495  }
496  return true;
497}
498
499int MipsAsmParser::matchRegisterName(StringRef Name) {
500
501   int CC;
502   if (!isMips64())
503    CC = StringSwitch<unsigned>(Name)
504      .Case("zero",  Mips::ZERO)
505      .Case("a0",  Mips::A0)
506      .Case("a1",  Mips::A1)
507      .Case("a2",  Mips::A2)
508      .Case("a3",  Mips::A3)
509      .Case("v0",  Mips::V0)
510      .Case("v1",  Mips::V1)
511      .Case("s0",  Mips::S0)
512      .Case("s1",  Mips::S1)
513      .Case("s2",  Mips::S2)
514      .Case("s3",  Mips::S3)
515      .Case("s4",  Mips::S4)
516      .Case("s5",  Mips::S5)
517      .Case("s6",  Mips::S6)
518      .Case("s7",  Mips::S7)
519      .Case("k0",  Mips::K0)
520      .Case("k1",  Mips::K1)
521      .Case("sp",  Mips::SP)
522      .Case("fp",  Mips::FP)
523      .Case("gp",  Mips::GP)
524      .Case("ra",  Mips::RA)
525      .Case("t0",  Mips::T0)
526      .Case("t1",  Mips::T1)
527      .Case("t2",  Mips::T2)
528      .Case("t3",  Mips::T3)
529      .Case("t4",  Mips::T4)
530      .Case("t5",  Mips::T5)
531      .Case("t6",  Mips::T6)
532      .Case("t7",  Mips::T7)
533      .Case("t8",  Mips::T8)
534      .Case("t9",  Mips::T9)
535      .Case("at",  Mips::AT)
536      .Case("fcc0",  Mips::FCC0)
537      .Default(-1);
538   else
539    CC = StringSwitch<unsigned>(Name)
540      .Case("zero", Mips::ZERO_64)
541      .Case("at", Mips::AT_64)
542      .Case("v0", Mips::V0_64)
543      .Case("v1", Mips::V1_64)
544      .Case("a0", Mips::A0_64)
545      .Case("a1", Mips::A1_64)
546      .Case("a2", Mips::A2_64)
547      .Case("a3", Mips::A3_64)
548      .Case("a4", Mips::T0_64)
549      .Case("a5", Mips::T1_64)
550      .Case("a6", Mips::T2_64)
551      .Case("a7", Mips::T3_64)
552      .Case("t4", Mips::T4_64)
553      .Case("t5", Mips::T5_64)
554      .Case("t6", Mips::T6_64)
555      .Case("t7", Mips::T7_64)
556      .Case("s0", Mips::S0_64)
557      .Case("s1", Mips::S1_64)
558      .Case("s2", Mips::S2_64)
559      .Case("s3", Mips::S3_64)
560      .Case("s4", Mips::S4_64)
561      .Case("s5", Mips::S5_64)
562      .Case("s6", Mips::S6_64)
563      .Case("s7", Mips::S7_64)
564      .Case("t8", Mips::T8_64)
565      .Case("t9", Mips::T9_64)
566      .Case("kt0", Mips::K0_64)
567      .Case("kt1", Mips::K1_64)
568      .Case("gp", Mips::GP_64)
569      .Case("sp", Mips::SP_64)
570      .Case("fp", Mips::FP_64)
571      .Case("s8", Mips::FP_64)
572      .Case("ra", Mips::RA_64)
573      .Default(-1);
574
575  if (CC != -1)
576    return CC;
577
578  if (Name[0] == 'f') {
579    StringRef NumString = Name.substr(1);
580    unsigned IntVal;
581    if( NumString.getAsInteger(10, IntVal))
582      return -1; // not integer
583    if (IntVal > 31)
584      return -1;
585
586    FpFormatTy Format = getFpFormat();
587
588    if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
589      return getReg(Mips::FGR32RegClassID, IntVal);
590    if (Format == FP_FORMAT_D) {
591      if(isFP64()) {
592        return getReg(Mips::FGR64RegClassID, IntVal);
593      }
594      // only even numbers available as register pairs
595      if (( IntVal > 31) || (IntVal%2 !=  0))
596        return -1;
597      return getReg(Mips::AFGR64RegClassID, IntVal/2);
598    }
599  }
600
601  return -1;
602}
603void MipsAsmParser::setDefaultFpFormat() {
604
605  if (isMips64() || isFP64())
606    FpFormat = FP_FORMAT_D;
607  else
608    FpFormat = FP_FORMAT_S;
609}
610
611bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
612
613  bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
614    .Case("ldxc1", true)
615    .Case("ldc1",  true)
616    .Case("sdxc1", true)
617    .Case("sdc1",  true)
618    .Default(false);
619
620  return IsDouble;
621}
622void MipsAsmParser::setFpFormat(StringRef Format) {
623
624  FpFormat = StringSwitch<FpFormatTy>(Format.lower())
625    .Case(".s",  FP_FORMAT_S)
626    .Case(".d",  FP_FORMAT_D)
627    .Case(".l",  FP_FORMAT_L)
628    .Case(".w",  FP_FORMAT_W)
629    .Default(FP_FORMAT_NONE);
630}
631
632bool MipsAssemblerOptions::setATReg(unsigned Reg) {
633  if (Reg > 31)
634    return false;
635
636  aTReg = Reg;
637  return true;
638}
639
640unsigned MipsAsmParser::getATReg() {
641  unsigned Reg = Options.getATRegNum();
642  if (isMips64())
643    return getReg(Mips::CPU64RegsRegClassID,Reg);
644
645  return getReg(Mips::CPURegsRegClassID,Reg);
646}
647
648unsigned MipsAsmParser::getReg(int RC,int RegNo) {
649  return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
650}
651
652int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic) {
653
654  if (Mnemonic.lower() == "rdhwr") {
655    // at the moment only hwreg29 is supported
656    if (RegNum != 29)
657      return -1;
658    return Mips::HWR29;
659  }
660
661  if (RegNum > 31)
662    return -1;
663
664  // MIPS64 registers are numbered 1 after the 32-bit equivalents
665  return getReg(Mips::CPURegsRegClassID, RegNum) + isMips64();
666}
667
668int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
669  const AsmToken &Tok = Parser.getTok();
670  int RegNum = -1;
671
672  if (Tok.is(AsmToken::Identifier)) {
673    std::string lowerCase = Tok.getString().lower();
674    RegNum = matchRegisterName(lowerCase);
675  } else if (Tok.is(AsmToken::Integer))
676    RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
677                                   Mnemonic.lower());
678    else
679      return RegNum;  //error
680  // 64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64
681  if (isMips64() && RegNum == Mips::ZERO_64) {
682    if (Mnemonic.find("ddiv") != StringRef::npos)
683      RegNum = Mips::ZERO;
684  }
685  return RegNum;
686}
687
688bool MipsAsmParser::
689  tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
690                          StringRef Mnemonic){
691
692  SMLoc S = Parser.getTok().getLoc();
693  int RegNo = -1;
694
695  // FIXME: we should make a more generic method for CCR
696  if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
697      && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
698    RegNo = Parser.getTok().getIntVal();  // get the int value
699    // at the moment only fcc0 is supported
700    if (RegNo ==  0)
701      RegNo = Mips::FCC0;
702  } else
703    RegNo = tryParseRegister(Mnemonic);
704  if (RegNo == -1)
705    return true;
706
707  Operands.push_back(MipsOperand::CreateReg(RegNo, S,
708      Parser.getTok().getLoc()));
709  Parser.Lex(); // Eat register token.
710  return false;
711}
712
713bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
714                                 StringRef Mnemonic) {
715  // Check if the current operand has a custom associated parser, if so, try to
716  // custom parse the operand, or fallback to the general approach.
717  OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
718  if (ResTy == MatchOperand_Success)
719    return false;
720  // If there wasn't a custom match, try the generic matcher below. Otherwise,
721  // there was a match, but an error occurred, in which case, just return that
722  // the operand parsing failed.
723  if (ResTy == MatchOperand_ParseFail)
724    return true;
725
726  switch (getLexer().getKind()) {
727  default:
728    Error(Parser.getTok().getLoc(), "unexpected token in operand");
729    return true;
730  case AsmToken::Dollar: {
731    // parse register
732    SMLoc S = Parser.getTok().getLoc();
733    Parser.Lex(); // Eat dollar token.
734    // parse register operand
735    if (!tryParseRegisterOperand(Operands, Mnemonic)) {
736      if (getLexer().is(AsmToken::LParen)) {
737        // check if it is indexed addressing operand
738        Operands.push_back(MipsOperand::CreateToken("(", S));
739        Parser.Lex(); // eat parenthesis
740        if (getLexer().isNot(AsmToken::Dollar))
741          return true;
742
743        Parser.Lex(); // eat dollar
744        if (tryParseRegisterOperand(Operands, Mnemonic))
745          return true;
746
747        if (!getLexer().is(AsmToken::RParen))
748          return true;
749
750        S = Parser.getTok().getLoc();
751        Operands.push_back(MipsOperand::CreateToken(")", S));
752        Parser.Lex();
753      }
754      return false;
755    }
756    // maybe it is a symbol reference
757    StringRef Identifier;
758    if (Parser.ParseIdentifier(Identifier))
759      return true;
760
761    SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
762
763    MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
764
765    // Otherwise create a symbol ref.
766    const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
767                                                getContext());
768
769    Operands.push_back(MipsOperand::CreateImm(Res, S, E));
770    return false;
771  }
772  case AsmToken::Identifier:
773  case AsmToken::LParen:
774  case AsmToken::Minus:
775  case AsmToken::Plus:
776  case AsmToken::Integer:
777  case AsmToken::String: {
778     // quoted label names
779    const MCExpr *IdVal;
780    SMLoc S = Parser.getTok().getLoc();
781    if (getParser().ParseExpression(IdVal))
782      return true;
783    SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
784    Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
785    return false;
786  }
787  case AsmToken::Percent: {
788    // it is a symbol reference or constant expression
789    const MCExpr *IdVal;
790    SMLoc S = Parser.getTok().getLoc(); // start location of the operand
791    if (parseRelocOperand(IdVal))
792      return true;
793
794    SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
795
796    Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
797    return false;
798  } // case AsmToken::Percent
799  } // switch(getLexer().getKind())
800  return true;
801}
802
803bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
804
805  Parser.Lex(); // eat % token
806  const AsmToken &Tok = Parser.getTok(); // get next token, operation
807  if (Tok.isNot(AsmToken::Identifier))
808    return true;
809
810  std::string Str = Tok.getIdentifier().str();
811
812  Parser.Lex(); // eat identifier
813  // now make expression from the rest of the operand
814  const MCExpr *IdVal;
815  SMLoc EndLoc;
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      Parser.Lex(); // eat ')' token
838
839  } else
840    return true; // parenthesis must follow reloc operand
841
842  // Check the type of the expression
843  if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
844    // it's a constant, evaluate lo or hi value
845    int Val = MCE->getValue();
846    if (Str == "lo") {
847      Val = Val & 0xffff;
848    } else if (Str == "hi") {
849      Val = (Val & 0xffff0000) >> 16;
850    }
851    Res = MCConstantExpr::Create(Val, getContext());
852    return false;
853  }
854
855  if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
856    // it's a symbol, create symbolic expression from symbol
857    StringRef Symbol = MSRE->getSymbol().getName();
858    MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
859    Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
860    return false;
861  }
862  return true;
863}
864
865bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
866                                  SMLoc &EndLoc) {
867
868  StartLoc = Parser.getTok().getLoc();
869  RegNo = tryParseRegister("");
870  EndLoc = Parser.getTok().getLoc();
871  return (RegNo == (unsigned)-1);
872}
873
874bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
875
876  SMLoc S;
877
878  switch(getLexer().getKind()) {
879  default:
880    return true;
881  case AsmToken::Integer:
882  case AsmToken::Minus:
883  case AsmToken::Plus:
884    return (getParser().ParseExpression(Res));
885  case AsmToken::Percent:
886    return parseRelocOperand(Res);
887  case AsmToken::LParen:
888    return false;  // it's probably assuming 0
889  }
890  return true;
891}
892
893MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
894               SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
895
896  const MCExpr *IdVal = 0;
897  SMLoc S;
898  // first operand is the offset
899  S = Parser.getTok().getLoc();
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      SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer()-1);
909      Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
910      return MatchOperand_Success;
911    }
912    Error(Parser.getTok().getLoc(), "'(' expected");
913    return MatchOperand_ParseFail;
914  }
915
916  Parser.Lex(); // Eat '(' token.
917
918  const AsmToken &Tok1 = Parser.getTok(); // get next token
919  if (Tok1.is(AsmToken::Dollar)) {
920    Parser.Lex(); // Eat '$' token.
921    if (tryParseRegisterOperand(Operands,"")) {
922      Error(Parser.getTok().getLoc(), "unexpected token in operand");
923      return MatchOperand_ParseFail;
924    }
925
926  } else {
927    Error(Parser.getTok().getLoc(), "unexpected token in operand");
928    return MatchOperand_ParseFail;
929  }
930
931  const AsmToken &Tok2 = Parser.getTok(); // get next token
932  if (Tok2.isNot(AsmToken::RParen)) {
933    Error(Parser.getTok().getLoc(), "')' expected");
934    return MatchOperand_ParseFail;
935  }
936
937  SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
938
939  Parser.Lex(); // Eat ')' token.
940
941  if (IdVal == 0)
942    IdVal = MCConstantExpr::Create(0, getContext());
943
944  // now replace register operand with the mem operand
945  MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
946  int RegNo = op->getReg();
947  // remove register from operands
948  Operands.pop_back();
949  // and add memory operand
950  Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
951  delete op;
952  return MatchOperand_Success;
953}
954
955MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
956
957  MCSymbolRefExpr::VariantKind VK
958                   = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
959    .Case("hi",          MCSymbolRefExpr::VK_Mips_ABS_HI)
960    .Case("lo",          MCSymbolRefExpr::VK_Mips_ABS_LO)
961    .Case("gp_rel",      MCSymbolRefExpr::VK_Mips_GPREL)
962    .Case("call16",      MCSymbolRefExpr::VK_Mips_GOT_CALL)
963    .Case("got",         MCSymbolRefExpr::VK_Mips_GOT)
964    .Case("tlsgd",       MCSymbolRefExpr::VK_Mips_TLSGD)
965    .Case("tlsldm",      MCSymbolRefExpr::VK_Mips_TLSLDM)
966    .Case("dtprel_hi",   MCSymbolRefExpr::VK_Mips_DTPREL_HI)
967    .Case("dtprel_lo",   MCSymbolRefExpr::VK_Mips_DTPREL_LO)
968    .Case("gottprel",    MCSymbolRefExpr::VK_Mips_GOTTPREL)
969    .Case("tprel_hi",    MCSymbolRefExpr::VK_Mips_TPREL_HI)
970    .Case("tprel_lo",    MCSymbolRefExpr::VK_Mips_TPREL_LO)
971    .Case("got_disp",    MCSymbolRefExpr::VK_Mips_GOT_DISP)
972    .Case("got_page",    MCSymbolRefExpr::VK_Mips_GOT_PAGE)
973    .Case("got_ofst",    MCSymbolRefExpr::VK_Mips_GOT_OFST)
974    .Case("hi(%neg(%gp_rel",    MCSymbolRefExpr::VK_Mips_GPOFF_HI)
975    .Case("lo(%neg(%gp_rel",    MCSymbolRefExpr::VK_Mips_GPOFF_LO)
976    .Default(MCSymbolRefExpr::VK_None);
977
978  return VK;
979}
980
981static int ConvertCcString(StringRef CondString) {
982  int CC = StringSwitch<unsigned>(CondString)
983      .Case(".f",    0)
984      .Case(".un",   1)
985      .Case(".eq",   2)
986      .Case(".ueq",  3)
987      .Case(".olt",  4)
988      .Case(".ult",  5)
989      .Case(".ole",  6)
990      .Case(".ule",  7)
991      .Case(".sf",   8)
992      .Case(".ngle", 9)
993      .Case(".seq",  10)
994      .Case(".ngl",  11)
995      .Case(".lt",   12)
996      .Case(".nge",  13)
997      .Case(".le",   14)
998      .Case(".ngt",  15)
999      .Default(-1);
1000
1001  return CC;
1002}
1003
1004bool MipsAsmParser::
1005parseMathOperation(StringRef Name, SMLoc NameLoc,
1006                   SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1007  // split the format
1008  size_t Start = Name.find('.'), Next = Name.rfind('.');
1009  StringRef Format1 = Name.slice(Start, Next);
1010  // and add the first format to the operands
1011  Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
1012  // now for the second format
1013  StringRef Format2 = Name.slice(Next, StringRef::npos);
1014  Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1015
1016  // set the format for the first register
1017  setFpFormat(Format1);
1018
1019  // Read the remaining operands.
1020  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1021    // Read the first operand.
1022    if (ParseOperand(Operands, Name)) {
1023      SMLoc Loc = getLexer().getLoc();
1024      Parser.EatToEndOfStatement();
1025      return Error(Loc, "unexpected token in argument list");
1026    }
1027
1028    if (getLexer().isNot(AsmToken::Comma)) {
1029      SMLoc Loc = getLexer().getLoc();
1030      Parser.EatToEndOfStatement();
1031      return Error(Loc, "unexpected token in argument list");
1032
1033    }
1034    Parser.Lex();  // Eat the comma.
1035
1036    //set the format for the first register
1037    setFpFormat(Format2);
1038
1039    // Parse and remember the operand.
1040    if (ParseOperand(Operands, Name)) {
1041      SMLoc Loc = getLexer().getLoc();
1042      Parser.EatToEndOfStatement();
1043      return Error(Loc, "unexpected token in argument list");
1044    }
1045  }
1046
1047  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1048    SMLoc Loc = getLexer().getLoc();
1049    Parser.EatToEndOfStatement();
1050    return Error(Loc, "unexpected token in argument list");
1051  }
1052
1053  Parser.Lex(); // Consume the EndOfStatement
1054  return false;
1055}
1056
1057bool MipsAsmParser::
1058ParseInstruction(StringRef Name, SMLoc NameLoc,
1059                 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1060  // floating point instructions: should register be treated as double?
1061  if (requestsDoubleOperand(Name)) {
1062    setFpFormat(FP_FORMAT_D);
1063  Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
1064  }
1065  else {
1066    setDefaultFpFormat();
1067    // Create the leading tokens for the mnemonic, split by '.' characters.
1068    size_t Start = 0, Next = Name.find('.');
1069    StringRef Mnemonic = Name.slice(Start, Next);
1070
1071    Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1072
1073    if (Next != StringRef::npos) {
1074      // there is a format token in mnemonic
1075      // StringRef Rest = Name.slice(Next, StringRef::npos);
1076      size_t Dot = Name.find('.', Next+1);
1077      StringRef Format = Name.slice(Next, Dot);
1078      if (Dot == StringRef::npos) //only one '.' in a string, it's a format
1079        Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1080      else {
1081        if (Name.startswith("c.")){
1082          // floating point compare, add '.' and immediate represent for cc
1083          Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1084          int Cc = ConvertCcString(Format);
1085          if (Cc == -1) {
1086            return Error(NameLoc, "Invalid conditional code");
1087          }
1088          SMLoc E = SMLoc::getFromPointer(
1089              Parser.getTok().getLoc().getPointer() -1 );
1090          Operands.push_back(MipsOperand::CreateImm(
1091              MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
1092        } else {
1093          // trunc, ceil, floor ...
1094          return parseMathOperation(Name, NameLoc, Operands);
1095        }
1096
1097        // the rest is a format
1098        Format = Name.slice(Dot, StringRef::npos);
1099        Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1100      }
1101
1102      setFpFormat(Format);
1103    }
1104  }
1105
1106  // Read the remaining operands.
1107  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1108    // Read the first operand.
1109    if (ParseOperand(Operands, Name)) {
1110      SMLoc Loc = getLexer().getLoc();
1111      Parser.EatToEndOfStatement();
1112      return Error(Loc, "unexpected token in argument list");
1113    }
1114
1115    while (getLexer().is(AsmToken::Comma) ) {
1116      Parser.Lex();  // Eat the comma.
1117
1118      // Parse and remember the operand.
1119      if (ParseOperand(Operands, Name)) {
1120        SMLoc Loc = getLexer().getLoc();
1121        Parser.EatToEndOfStatement();
1122        return Error(Loc, "unexpected token in argument list");
1123      }
1124    }
1125  }
1126
1127  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1128    SMLoc Loc = getLexer().getLoc();
1129    Parser.EatToEndOfStatement();
1130    return Error(Loc, "unexpected token in argument list");
1131  }
1132
1133  Parser.Lex(); // Consume the EndOfStatement
1134  return false;
1135}
1136
1137bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1138   SMLoc Loc = getLexer().getLoc();
1139   Parser.EatToEndOfStatement();
1140   return Error(Loc, ErrorMsg);
1141}
1142
1143bool MipsAsmParser::parseSetNoAtDirective() {
1144  // line should look like:
1145  //  .set noat
1146  // set at reg to 0
1147  Options.setATReg(0);
1148  // eat noat
1149  Parser.Lex();
1150  // if this is not the end of the statement, report error
1151  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1152    reportParseError("unexpected token in statement");
1153    return false;
1154  }
1155  Parser.Lex(); // Consume the EndOfStatement
1156  return false;
1157}
1158bool MipsAsmParser::parseSetAtDirective() {
1159  // line can be
1160  //  .set at - defaults to $1
1161  // or .set at=$reg
1162  getParser().Lex();
1163  if (getLexer().is(AsmToken::EndOfStatement)) {
1164    Options.setATReg(1);
1165    Parser.Lex(); // Consume the EndOfStatement
1166    return false;
1167  } else if (getLexer().is(AsmToken::Equal)) {
1168    getParser().Lex(); //eat '='
1169    if (getLexer().isNot(AsmToken::Dollar)) {
1170      reportParseError("unexpected token in statement");
1171      return false;
1172    }
1173    Parser.Lex(); // eat '$'
1174    if (getLexer().isNot(AsmToken::Integer)) {
1175      reportParseError("unexpected token in statement");
1176      return false;
1177    }
1178    const AsmToken &Reg = Parser.getTok();
1179    if (!Options.setATReg(Reg.getIntVal())) {
1180      reportParseError("unexpected token in statement");
1181      return false;
1182    }
1183    getParser().Lex(); //eat reg
1184
1185    if (getLexer().isNot(AsmToken::EndOfStatement)) {
1186      reportParseError("unexpected token in statement");
1187      return false;
1188     }
1189    Parser.Lex(); // Consume the EndOfStatement
1190    return false;
1191  } else {
1192    reportParseError("unexpected token in statement");
1193    return false;
1194  }
1195}
1196
1197bool MipsAsmParser::parseSetReorderDirective() {
1198  Parser.Lex();
1199  // if this is not the end of the statement, report error
1200  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1201    reportParseError("unexpected token in statement");
1202    return false;
1203  }
1204  Options.setReorder();
1205  Parser.Lex(); // Consume the EndOfStatement
1206  return false;
1207}
1208
1209bool MipsAsmParser::parseSetNoReorderDirective() {
1210    Parser.Lex();
1211    // if this is not the end of the statement, report error
1212    if (getLexer().isNot(AsmToken::EndOfStatement)) {
1213      reportParseError("unexpected token in statement");
1214      return false;
1215    }
1216    Options.setNoreorder();
1217    Parser.Lex(); // Consume the EndOfStatement
1218    return false;
1219}
1220
1221bool MipsAsmParser::parseSetMacroDirective() {
1222  Parser.Lex();
1223  // if this is not the end of the statement, report error
1224  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1225    reportParseError("unexpected token in statement");
1226    return false;
1227  }
1228  Options.setMacro();
1229  Parser.Lex(); // Consume the EndOfStatement
1230  return false;
1231}
1232
1233bool MipsAsmParser::parseSetNoMacroDirective() {
1234  Parser.Lex();
1235  // if this is not the end of the statement, report error
1236  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1237    reportParseError("`noreorder' must be set before `nomacro'");
1238    return false;
1239  }
1240  if (Options.isReorder()) {
1241    reportParseError("`noreorder' must be set before `nomacro'");
1242    return false;
1243  }
1244  Options.setNomacro();
1245  Parser.Lex(); // Consume the EndOfStatement
1246  return false;
1247}
1248bool MipsAsmParser::parseDirectiveSet() {
1249
1250  // get next token
1251  const AsmToken &Tok = Parser.getTok();
1252
1253  if (Tok.getString() == "noat") {
1254    return parseSetNoAtDirective();
1255  } else if (Tok.getString() == "at") {
1256    return parseSetAtDirective();
1257  } else if (Tok.getString() == "reorder") {
1258    return parseSetReorderDirective();
1259  } else if (Tok.getString() == "noreorder") {
1260    return parseSetNoReorderDirective();
1261  } else if (Tok.getString() == "macro") {
1262    return parseSetMacroDirective();
1263  } else if (Tok.getString() == "nomacro") {
1264    return parseSetNoMacroDirective();
1265  } else if (Tok.getString() == "nomips16") {
1266    // ignore this directive for now
1267    Parser.EatToEndOfStatement();
1268    return false;
1269  } else if (Tok.getString() == "nomicromips") {
1270    // ignore this directive for now
1271    Parser.EatToEndOfStatement();
1272    return false;
1273  }
1274  return true;
1275}
1276
1277bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
1278
1279  if (DirectiveID.getString() == ".ent") {
1280    // ignore this directive for now
1281    Parser.Lex();
1282    return false;
1283  }
1284
1285  if (DirectiveID.getString() == ".end") {
1286    // ignore this directive for now
1287    Parser.Lex();
1288    return false;
1289  }
1290
1291  if (DirectiveID.getString() == ".frame") {
1292    // ignore this directive for now
1293    Parser.EatToEndOfStatement();
1294    return false;
1295  }
1296
1297  if (DirectiveID.getString() == ".set") {
1298    return parseDirectiveSet();
1299  }
1300
1301  if (DirectiveID.getString() == ".fmask") {
1302    // ignore this directive for now
1303    Parser.EatToEndOfStatement();
1304    return false;
1305  }
1306
1307  if (DirectiveID.getString() == ".mask") {
1308    // ignore this directive for now
1309    Parser.EatToEndOfStatement();
1310    return false;
1311  }
1312
1313  if (DirectiveID.getString() == ".gpword") {
1314    // ignore this directive for now
1315    Parser.EatToEndOfStatement();
1316    return false;
1317  }
1318
1319  return true;
1320}
1321
1322extern "C" void LLVMInitializeMipsAsmParser() {
1323  RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1324  RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1325  RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1326  RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1327}
1328
1329#define GET_REGISTER_MATCHER
1330#define GET_MATCHER_IMPLEMENTATION
1331#include "MipsGenAsmMatcher.inc"
1332