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