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