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