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