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