MipsAsmParser.cpp revision 10d5ff6b1dceec77c23cd200ef200e2e9dec4c85
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}
313void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
314                        SmallVectorImpl<MCInst*> &Instructions){
315  switch(Inst.getOpcode()) {
316    case Mips::LoadImm32Reg:
317      return expandLoadImm(Inst, IDLoc, Instructions);
318    }
319  return;
320}
321void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
322                        SmallVectorImpl<MCInst*> &Instructions){
323  MCInst *tmpInst = new MCInst();
324  const MCOperand &ImmOp = Inst.getOperand(1);
325  assert(ImmOp.isImm() && "expected imediate operand kind");
326  const MCOperand &RegOp = Inst.getOperand(0);
327  assert(RegOp.isReg() && "expected register operand kind");
328
329  int ImmValue = ImmOp.getImm();
330  tmpInst->setLoc(IDLoc);
331  if ( 0 <= ImmValue && ImmValue <= 65535) {
332    // for 0 = j = 65535.
333    // li d,j => ori d,$zero,j
334    tmpInst->setOpcode(isMips64() ? Mips::ORi64 : Mips::ORi);
335    tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg()));
336    tmpInst->addOperand(
337              MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO));
338    tmpInst->addOperand(MCOperand::CreateImm(ImmValue));
339    Instructions.push_back(tmpInst);
340  } else if ( ImmValue < 0 && ImmValue >= -32768) {
341    // for -32768 = j < 0.
342    // li d,j => addiu d,$zero,j
343    tmpInst->setOpcode(Mips::ADDiu); //TODO:no ADDiu64 in td files?
344    tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg()));
345    tmpInst->addOperand(
346              MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO));
347    tmpInst->addOperand(MCOperand::CreateImm(ImmValue));
348    Instructions.push_back(tmpInst);
349  } else {
350    // for any other value of j that is representable as a 32-bit integer.
351    // li d,j => lui d,hi16(j)
352    // ori d,d,lo16(j)
353    tmpInst->setOpcode(isMips64() ? Mips::LUi64 : Mips::LUi);
354    tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg()));
355    tmpInst->addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
356    Instructions.push_back(tmpInst);
357    tmpInst = new MCInst();
358    tmpInst->setOpcode(isMips64() ? Mips::ORi64 : Mips::ORi);
359    tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg()));
360    tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg()));
361    tmpInst->addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
362    tmpInst->setLoc(IDLoc);
363    Instructions.push_back(tmpInst);
364  }
365}
366bool MipsAsmParser::
367MatchAndEmitInstruction(SMLoc IDLoc,
368                        SmallVectorImpl<MCParsedAsmOperand*> &Operands,
369                        MCStreamer &Out) {
370  MCInst Inst;
371  unsigned Kind;
372  unsigned ErrorInfo;
373  MatchInstMapAndConstraints MapAndConstraints;
374  unsigned MatchResult = MatchInstructionImpl(Operands, Kind, Inst,
375                                              MapAndConstraints, ErrorInfo,
376                                              /*matchingInlineAsm*/ false);
377
378  switch (MatchResult) {
379  default: break;
380  case Match_Success: {
381    if (needsExpansion(Inst)) {
382      SmallVector<MCInst*, 4> Instructions;
383      expandInstruction(Inst, IDLoc, Instructions);
384      for(unsigned i =0; i < Instructions.size(); i++){
385        Inst = *(Instructions[i]);
386        Out.EmitInstruction(Inst);
387      }
388    } else {
389        Inst.setLoc(IDLoc);
390        Out.EmitInstruction(Inst);
391      }
392    return false;
393  }
394  case Match_MissingFeature:
395    Error(IDLoc, "instruction requires a CPU feature not currently enabled");
396    return true;
397  case Match_InvalidOperand: {
398    SMLoc ErrorLoc = IDLoc;
399    if (ErrorInfo != ~0U) {
400      if (ErrorInfo >= Operands.size())
401        return Error(IDLoc, "too few operands for instruction");
402
403      ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
404      if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
405    }
406
407    return Error(ErrorLoc, "invalid operand for instruction");
408  }
409  case Match_MnemonicFail:
410    return Error(IDLoc, "invalid instruction");
411  }
412  return true;
413}
414
415int MipsAsmParser::matchRegisterName(StringRef Name) {
416
417   int CC = StringSwitch<unsigned>(Name)
418    .Case("zero",  Mips::ZERO)
419    .Case("a0",  Mips::A0)
420    .Case("a1",  Mips::A1)
421    .Case("a2",  Mips::A2)
422    .Case("a3",  Mips::A3)
423    .Case("v0",  Mips::V0)
424    .Case("v1",  Mips::V1)
425    .Case("s0",  Mips::S0)
426    .Case("s1",  Mips::S1)
427    .Case("s2",  Mips::S2)
428    .Case("s3",  Mips::S3)
429    .Case("s4",  Mips::S4)
430    .Case("s5",  Mips::S5)
431    .Case("s6",  Mips::S6)
432    .Case("s7",  Mips::S7)
433    .Case("k0",  Mips::K0)
434    .Case("k1",  Mips::K1)
435    .Case("sp",  Mips::SP)
436    .Case("fp",  Mips::FP)
437    .Case("gp",  Mips::GP)
438    .Case("ra",  Mips::RA)
439    .Case("t0",  Mips::T0)
440    .Case("t1",  Mips::T1)
441    .Case("t2",  Mips::T2)
442    .Case("t3",  Mips::T3)
443    .Case("t4",  Mips::T4)
444    .Case("t5",  Mips::T5)
445    .Case("t6",  Mips::T6)
446    .Case("t7",  Mips::T7)
447    .Case("t8",  Mips::T8)
448    .Case("t9",  Mips::T9)
449    .Case("at",  Mips::AT)
450    .Case("fcc0",  Mips::FCC0)
451    .Default(-1);
452
453  if (CC != -1) {
454    // 64 bit register in Mips are following 32 bit definitions.
455    if (isMips64())
456      CC++;
457    return CC;
458  }
459
460  if (Name[0] == 'f') {
461    StringRef NumString = Name.substr(1);
462    unsigned IntVal;
463    if( NumString.getAsInteger(10, IntVal))
464      return -1; // not integer
465    if (IntVal > 31)
466      return -1;
467
468    FpFormatTy Format = getFpFormat();
469
470    if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
471      return getReg(Mips::FGR32RegClassID, IntVal);
472    if (Format == FP_FORMAT_D) {
473      if(isFP64()) {
474        return getReg(Mips::FGR64RegClassID, IntVal);
475      }
476      // only even numbers available as register pairs
477      if (( IntVal > 31) || (IntVal%2 !=  0))
478        return -1;
479      return getReg(Mips::AFGR64RegClassID, IntVal/2);
480    }
481  }
482
483  return -1;
484}
485void MipsAsmParser::setDefaultFpFormat() {
486
487  if (isMips64() || isFP64())
488    FpFormat = FP_FORMAT_D;
489  else
490    FpFormat = FP_FORMAT_S;
491}
492
493bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
494
495  bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
496    .Case("ldxc1", true)
497    .Case("ldc1",  true)
498    .Case("sdxc1", true)
499    .Case("sdc1",  true)
500    .Default(false);
501
502  return IsDouble;
503}
504void MipsAsmParser::setFpFormat(StringRef Format) {
505
506  FpFormat = StringSwitch<FpFormatTy>(Format.lower())
507    .Case(".s",  FP_FORMAT_S)
508    .Case(".d",  FP_FORMAT_D)
509    .Case(".l",  FP_FORMAT_L)
510    .Case(".w",  FP_FORMAT_W)
511    .Default(FP_FORMAT_NONE);
512}
513
514bool MipsAssemblerOptions::setATReg(unsigned Reg) {
515  if (Reg > 31)
516    return false;
517
518  aTReg = Reg;
519  return true;
520}
521
522unsigned MipsAsmParser::getATReg() {
523  unsigned Reg = Options.getATRegNum();
524  if (isMips64())
525    return getReg(Mips::CPU64RegsRegClassID,Reg);
526
527  return getReg(Mips::CPURegsRegClassID,Reg);
528}
529
530unsigned MipsAsmParser::getReg(int RC,int RegNo) {
531  return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
532}
533
534int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic) {
535
536  if (Mnemonic.lower() == "rdhwr") {
537    // at the moment only hwreg29 is supported
538    if (RegNum != 29)
539      return -1;
540    return Mips::HWR29;
541  }
542
543  if (RegNum > 31)
544    return -1;
545
546  return getReg(Mips::CPURegsRegClassID, RegNum);
547}
548
549int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
550  const AsmToken &Tok = Parser.getTok();
551  int RegNum = -1;
552
553  if (Tok.is(AsmToken::Identifier)) {
554    std::string lowerCase = Tok.getString().lower();
555    RegNum = matchRegisterName(lowerCase);
556  } else if (Tok.is(AsmToken::Integer))
557    RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
558                                   Mnemonic.lower());
559    else
560      return RegNum;  //error
561  // 64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64
562  if (isMips64() && RegNum == Mips::ZERO_64) {
563    if (Mnemonic.find("ddiv") != StringRef::npos)
564      RegNum = Mips::ZERO;
565  }
566  return RegNum;
567}
568
569bool MipsAsmParser::
570  tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
571                          StringRef Mnemonic){
572
573  SMLoc S = Parser.getTok().getLoc();
574  int RegNo = -1;
575
576  // FIXME: we should make a more generic method for CCR
577  if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
578      && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
579    RegNo = Parser.getTok().getIntVal();  // get the int value
580    // at the moment only fcc0 is supported
581    if (RegNo ==  0)
582      RegNo = Mips::FCC0;
583  } else
584    RegNo = tryParseRegister(Mnemonic);
585  if (RegNo == -1)
586    return true;
587
588  Operands.push_back(MipsOperand::CreateReg(RegNo, S,
589      Parser.getTok().getLoc()));
590  Parser.Lex(); // Eat register token.
591  return false;
592}
593
594bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
595                                 StringRef Mnemonic) {
596  // Check if the current operand has a custom associated parser, if so, try to
597  // custom parse the operand, or fallback to the general approach.
598  OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
599  if (ResTy == MatchOperand_Success)
600    return false;
601  // If there wasn't a custom match, try the generic matcher below. Otherwise,
602  // there was a match, but an error occurred, in which case, just return that
603  // the operand parsing failed.
604  if (ResTy == MatchOperand_ParseFail)
605    return true;
606
607  switch (getLexer().getKind()) {
608  default:
609    Error(Parser.getTok().getLoc(), "unexpected token in operand");
610    return true;
611  case AsmToken::Dollar: {
612    // parse register
613    SMLoc S = Parser.getTok().getLoc();
614    Parser.Lex(); // Eat dollar token.
615    // parse register operand
616    if (!tryParseRegisterOperand(Operands, Mnemonic)) {
617      if (getLexer().is(AsmToken::LParen)) {
618        // check if it is indexed addressing operand
619        Operands.push_back(MipsOperand::CreateToken("(", S));
620        Parser.Lex(); // eat parenthesis
621        if (getLexer().isNot(AsmToken::Dollar))
622          return true;
623
624        Parser.Lex(); // eat dollar
625        if (tryParseRegisterOperand(Operands, Mnemonic))
626          return true;
627
628        if (!getLexer().is(AsmToken::RParen))
629          return true;
630
631        S = Parser.getTok().getLoc();
632        Operands.push_back(MipsOperand::CreateToken(")", S));
633        Parser.Lex();
634      }
635      return false;
636    }
637    // maybe it is a symbol reference
638    StringRef Identifier;
639    if (Parser.ParseIdentifier(Identifier))
640      return true;
641
642    SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
643
644    MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
645
646    // Otherwise create a symbol ref.
647    const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
648                                                getContext());
649
650    Operands.push_back(MipsOperand::CreateImm(Res, S, E));
651    return false;
652  }
653  case AsmToken::Identifier:
654  case AsmToken::LParen:
655  case AsmToken::Minus:
656  case AsmToken::Plus:
657  case AsmToken::Integer:
658  case AsmToken::String: {
659     // quoted label names
660    const MCExpr *IdVal;
661    SMLoc S = Parser.getTok().getLoc();
662    if (getParser().ParseExpression(IdVal))
663      return true;
664    SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
665    Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
666    return false;
667  }
668  case AsmToken::Percent: {
669    // it is a symbol reference or constant expression
670    const MCExpr *IdVal;
671    SMLoc S = Parser.getTok().getLoc(); // start location of the operand
672    if (parseRelocOperand(IdVal))
673      return true;
674
675    SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
676
677    Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
678    return false;
679  } // case AsmToken::Percent
680  } // switch(getLexer().getKind())
681  return true;
682}
683
684bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
685
686  Parser.Lex(); // eat % token
687  const AsmToken &Tok = Parser.getTok(); // get next token, operation
688  if (Tok.isNot(AsmToken::Identifier))
689    return true;
690
691  std::string Str = Tok.getIdentifier().str();
692
693  Parser.Lex(); // eat identifier
694  // now make expression from the rest of the operand
695  const MCExpr *IdVal;
696  SMLoc EndLoc;
697
698  if (getLexer().getKind() == AsmToken::LParen) {
699    while (1) {
700      Parser.Lex(); // eat '(' token
701      if (getLexer().getKind() == AsmToken::Percent) {
702        Parser.Lex(); // eat % token
703        const AsmToken &nextTok = Parser.getTok();
704        if (nextTok.isNot(AsmToken::Identifier))
705          return true;
706        Str += "(%";
707        Str += nextTok.getIdentifier();
708        Parser.Lex(); // eat identifier
709        if (getLexer().getKind() != AsmToken::LParen)
710          return true;
711      } else
712        break;
713    }
714    if (getParser().ParseParenExpression(IdVal,EndLoc))
715      return true;
716
717    while (getLexer().getKind() == AsmToken::RParen)
718      Parser.Lex(); // eat ')' token
719
720  } else
721    return true; // parenthesis must follow reloc operand
722
723  // Check the type of the expression
724  if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
725    // it's a constant, evaluate lo or hi value
726    int Val = MCE->getValue();
727    if (Str == "lo") {
728      Val = Val & 0xffff;
729    } else if (Str == "hi") {
730      Val = (Val & 0xffff0000) >> 16;
731    }
732    Res = MCConstantExpr::Create(Val, getContext());
733    return false;
734  }
735
736  if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
737    // it's a symbol, create symbolic expression from symbol
738    StringRef Symbol = MSRE->getSymbol().getName();
739    MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
740    Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
741    return false;
742  }
743  return true;
744}
745
746bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
747                                  SMLoc &EndLoc) {
748
749  StartLoc = Parser.getTok().getLoc();
750  RegNo = tryParseRegister("");
751  EndLoc = Parser.getTok().getLoc();
752  return (RegNo == (unsigned)-1);
753}
754
755bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
756
757  SMLoc S;
758
759  switch(getLexer().getKind()) {
760  default:
761    return true;
762  case AsmToken::Integer:
763  case AsmToken::Minus:
764  case AsmToken::Plus:
765    return (getParser().ParseExpression(Res));
766  case AsmToken::Percent:
767    return parseRelocOperand(Res);
768  case AsmToken::LParen:
769    return false;  // it's probably assuming 0
770  }
771  return true;
772}
773
774MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
775               SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
776
777  const MCExpr *IdVal = 0;
778  SMLoc S;
779  // first operand is the offset
780  S = Parser.getTok().getLoc();
781
782  if (parseMemOffset(IdVal))
783    return MatchOperand_ParseFail;
784
785  const AsmToken &Tok = Parser.getTok(); // get next token
786  if (Tok.isNot(AsmToken::LParen)) {
787    Error(Parser.getTok().getLoc(), "'(' expected");
788    return MatchOperand_ParseFail;
789  }
790
791  Parser.Lex(); // Eat '(' token.
792
793  const AsmToken &Tok1 = Parser.getTok(); //get next token
794  if (Tok1.is(AsmToken::Dollar)) {
795    Parser.Lex(); // Eat '$' token.
796    if (tryParseRegisterOperand(Operands,"")) {
797      Error(Parser.getTok().getLoc(), "unexpected token in operand");
798      return MatchOperand_ParseFail;
799    }
800
801  } else {
802    Error(Parser.getTok().getLoc(), "unexpected token in operand");
803    return MatchOperand_ParseFail;
804  }
805
806  const AsmToken &Tok2 = Parser.getTok(); // get next token
807  if (Tok2.isNot(AsmToken::RParen)) {
808    Error(Parser.getTok().getLoc(), "')' expected");
809    return MatchOperand_ParseFail;
810  }
811
812  SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
813
814  Parser.Lex(); // Eat ')' token.
815
816  if (IdVal == 0)
817    IdVal = MCConstantExpr::Create(0, getContext());
818
819  // now replace register operand with the mem operand
820  MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
821  int RegNo = op->getReg();
822  // remove register from operands
823  Operands.pop_back();
824  // and add memory operand
825  Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
826  delete op;
827  return MatchOperand_Success;
828}
829
830MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
831
832  MCSymbolRefExpr::VariantKind VK
833                   = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
834    .Case("hi",          MCSymbolRefExpr::VK_Mips_ABS_HI)
835    .Case("lo",          MCSymbolRefExpr::VK_Mips_ABS_LO)
836    .Case("gp_rel",      MCSymbolRefExpr::VK_Mips_GPREL)
837    .Case("call16",      MCSymbolRefExpr::VK_Mips_GOT_CALL)
838    .Case("got",         MCSymbolRefExpr::VK_Mips_GOT)
839    .Case("tlsgd",       MCSymbolRefExpr::VK_Mips_TLSGD)
840    .Case("tlsldm",      MCSymbolRefExpr::VK_Mips_TLSLDM)
841    .Case("dtprel_hi",   MCSymbolRefExpr::VK_Mips_DTPREL_HI)
842    .Case("dtprel_lo",   MCSymbolRefExpr::VK_Mips_DTPREL_LO)
843    .Case("gottprel",    MCSymbolRefExpr::VK_Mips_GOTTPREL)
844    .Case("tprel_hi",    MCSymbolRefExpr::VK_Mips_TPREL_HI)
845    .Case("tprel_lo",    MCSymbolRefExpr::VK_Mips_TPREL_LO)
846    .Case("got_disp",    MCSymbolRefExpr::VK_Mips_GOT_DISP)
847    .Case("got_page",    MCSymbolRefExpr::VK_Mips_GOT_PAGE)
848    .Case("got_ofst",    MCSymbolRefExpr::VK_Mips_GOT_OFST)
849    .Case("hi(%neg(%gp_rel",    MCSymbolRefExpr::VK_Mips_GPOFF_HI)
850    .Case("lo(%neg(%gp_rel",    MCSymbolRefExpr::VK_Mips_GPOFF_LO)
851    .Default(MCSymbolRefExpr::VK_None);
852
853  return VK;
854}
855
856static int ConvertCcString(StringRef CondString) {
857  int CC = StringSwitch<unsigned>(CondString)
858      .Case(".f",    0)
859      .Case(".un",   1)
860      .Case(".eq",   2)
861      .Case(".ueq",  3)
862      .Case(".olt",  4)
863      .Case(".ult",  5)
864      .Case(".ole",  6)
865      .Case(".ule",  7)
866      .Case(".sf",   8)
867      .Case(".ngle", 9)
868      .Case(".seq",  10)
869      .Case(".ngl",  11)
870      .Case(".lt",   12)
871      .Case(".nge",  13)
872      .Case(".le",   14)
873      .Case(".ngt",  15)
874      .Default(-1);
875
876  return CC;
877}
878
879bool MipsAsmParser::
880parseMathOperation(StringRef Name, SMLoc NameLoc,
881                   SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
882  // split the format
883  size_t Start = Name.find('.'), Next = Name.rfind('.');
884  StringRef Format1 = Name.slice(Start, Next);
885  // and add the first format to the operands
886  Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
887  // now for the second format
888  StringRef Format2 = Name.slice(Next, StringRef::npos);
889  Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
890
891  // set the format for the first register
892  setFpFormat(Format1);
893
894  // Read the remaining operands.
895  if (getLexer().isNot(AsmToken::EndOfStatement)) {
896    // Read the first operand.
897    if (ParseOperand(Operands, Name)) {
898      SMLoc Loc = getLexer().getLoc();
899      Parser.EatToEndOfStatement();
900      return Error(Loc, "unexpected token in argument list");
901    }
902
903    if (getLexer().isNot(AsmToken::Comma)) {
904      SMLoc Loc = getLexer().getLoc();
905      Parser.EatToEndOfStatement();
906      return Error(Loc, "unexpected token in argument list");
907
908    }
909    Parser.Lex();  // Eat the comma.
910
911    //set the format for the first register
912    setFpFormat(Format2);
913
914    // Parse and remember the operand.
915    if (ParseOperand(Operands, Name)) {
916      SMLoc Loc = getLexer().getLoc();
917      Parser.EatToEndOfStatement();
918      return Error(Loc, "unexpected token in argument list");
919    }
920  }
921
922  if (getLexer().isNot(AsmToken::EndOfStatement)) {
923    SMLoc Loc = getLexer().getLoc();
924    Parser.EatToEndOfStatement();
925    return Error(Loc, "unexpected token in argument list");
926  }
927
928  Parser.Lex(); // Consume the EndOfStatement
929  return false;
930}
931
932bool MipsAsmParser::
933ParseInstruction(StringRef Name, SMLoc NameLoc,
934                 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
935  // floating point instructions: should register be treated as double?
936  if (requestsDoubleOperand(Name)) {
937    setFpFormat(FP_FORMAT_D);
938  Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
939  }
940  else {
941    setDefaultFpFormat();
942    // Create the leading tokens for the mnemonic, split by '.' characters.
943    size_t Start = 0, Next = Name.find('.');
944    StringRef Mnemonic = Name.slice(Start, Next);
945
946    Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
947
948    if (Next != StringRef::npos) {
949      // there is a format token in mnemonic
950      // StringRef Rest = Name.slice(Next, StringRef::npos);
951      size_t Dot = Name.find('.', Next+1);
952      StringRef Format = Name.slice(Next, Dot);
953      if (Dot == StringRef::npos) //only one '.' in a string, it's a format
954        Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
955      else {
956        if (Name.startswith("c.")){
957          // floating point compare, add '.' and immediate represent for cc
958          Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
959          int Cc = ConvertCcString(Format);
960          if (Cc == -1) {
961            return Error(NameLoc, "Invalid conditional code");
962          }
963          SMLoc E = SMLoc::getFromPointer(
964              Parser.getTok().getLoc().getPointer() -1 );
965          Operands.push_back(MipsOperand::CreateImm(
966              MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
967        } else {
968          // trunc, ceil, floor ...
969          return parseMathOperation(Name, NameLoc, Operands);
970        }
971
972        // the rest is a format
973        Format = Name.slice(Dot, StringRef::npos);
974        Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
975      }
976
977      setFpFormat(Format);
978    }
979  }
980
981  // Read the remaining operands.
982  if (getLexer().isNot(AsmToken::EndOfStatement)) {
983    // Read the first operand.
984    if (ParseOperand(Operands, Name)) {
985      SMLoc Loc = getLexer().getLoc();
986      Parser.EatToEndOfStatement();
987      return Error(Loc, "unexpected token in argument list");
988    }
989
990    while (getLexer().is(AsmToken::Comma) ) {
991      Parser.Lex();  // Eat the comma.
992
993      // Parse and remember the operand.
994      if (ParseOperand(Operands, Name)) {
995        SMLoc Loc = getLexer().getLoc();
996        Parser.EatToEndOfStatement();
997        return Error(Loc, "unexpected token in argument list");
998      }
999    }
1000  }
1001
1002  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1003    SMLoc Loc = getLexer().getLoc();
1004    Parser.EatToEndOfStatement();
1005    return Error(Loc, "unexpected token in argument list");
1006  }
1007
1008  Parser.Lex(); // Consume the EndOfStatement
1009  return false;
1010}
1011
1012bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1013   SMLoc Loc = getLexer().getLoc();
1014   Parser.EatToEndOfStatement();
1015   return Error(Loc, ErrorMsg);
1016}
1017
1018bool MipsAsmParser::parseSetNoAtDirective() {
1019  // line should look like:
1020  //  .set noat
1021  // set at reg to 0
1022  Options.setATReg(0);
1023  // eat noat
1024  Parser.Lex();
1025  // if this is not the end of the statement, report error
1026  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1027    reportParseError("unexpected token in statement");
1028    return false;
1029  }
1030  Parser.Lex(); // Consume the EndOfStatement
1031  return false;
1032}
1033bool MipsAsmParser::parseSetAtDirective() {
1034  // line can be
1035  //  .set at - defaults to $1
1036  // or .set at=$reg
1037  getParser().Lex();
1038  if (getLexer().is(AsmToken::EndOfStatement)) {
1039    Options.setATReg(1);
1040    Parser.Lex(); // Consume the EndOfStatement
1041    return false;
1042  } else if (getLexer().is(AsmToken::Equal)) {
1043    getParser().Lex(); //eat '='
1044    if (getLexer().isNot(AsmToken::Dollar)) {
1045      reportParseError("unexpected token in statement");
1046      return false;
1047    }
1048    Parser.Lex(); // eat '$'
1049    if (getLexer().isNot(AsmToken::Integer)) {
1050      reportParseError("unexpected token in statement");
1051      return false;
1052    }
1053    const AsmToken &Reg = Parser.getTok();
1054    if (!Options.setATReg(Reg.getIntVal())) {
1055      reportParseError("unexpected token in statement");
1056      return false;
1057    }
1058    getParser().Lex(); //eat reg
1059
1060    if (getLexer().isNot(AsmToken::EndOfStatement)) {
1061      reportParseError("unexpected token in statement");
1062      return false;
1063     }
1064    Parser.Lex(); // Consume the EndOfStatement
1065    return false;
1066  } else {
1067    reportParseError("unexpected token in statement");
1068    return false;
1069  }
1070}
1071
1072bool MipsAsmParser::parseSetReorderDirective() {
1073  Parser.Lex();
1074  // if this is not the end of the statement, report error
1075  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1076    reportParseError("unexpected token in statement");
1077    return false;
1078  }
1079  Options.setReorder();
1080  Parser.Lex(); // Consume the EndOfStatement
1081  return false;
1082}
1083
1084bool MipsAsmParser::parseSetNoReorderDirective() {
1085    Parser.Lex();
1086    // if this is not the end of the statement, report error
1087    if (getLexer().isNot(AsmToken::EndOfStatement)) {
1088      reportParseError("unexpected token in statement");
1089      return false;
1090    }
1091    Options.setNoreorder();
1092    Parser.Lex(); // Consume the EndOfStatement
1093    return false;
1094}
1095
1096bool MipsAsmParser::parseSetMacroDirective() {
1097  Parser.Lex();
1098  // if this is not the end of the statement, report error
1099  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1100    reportParseError("unexpected token in statement");
1101    return false;
1102  }
1103  Options.setMacro();
1104  Parser.Lex(); // Consume the EndOfStatement
1105  return false;
1106}
1107
1108bool MipsAsmParser::parseSetNoMacroDirective() {
1109  Parser.Lex();
1110  // if this is not the end of the statement, report error
1111  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1112    reportParseError("`noreorder' must be set before `nomacro'");
1113    return false;
1114  }
1115  if (Options.isReorder()) {
1116    reportParseError("`noreorder' must be set before `nomacro'");
1117    return false;
1118  }
1119  Options.setNomacro();
1120  Parser.Lex(); // Consume the EndOfStatement
1121  return false;
1122}
1123bool MipsAsmParser::parseDirectiveSet() {
1124
1125  // get next token
1126  const AsmToken &Tok = Parser.getTok();
1127
1128  if (Tok.getString() == "noat") {
1129    return parseSetNoAtDirective();
1130  } else if (Tok.getString() == "at") {
1131    return parseSetAtDirective();
1132  } else if (Tok.getString() == "reorder") {
1133    return parseSetReorderDirective();
1134  } else if (Tok.getString() == "noreorder") {
1135    return parseSetNoReorderDirective();
1136  } else if (Tok.getString() == "macro") {
1137    return parseSetMacroDirective();
1138  } else if (Tok.getString() == "nomacro") {
1139    return parseSetNoMacroDirective();
1140  } else if (Tok.getString() == "nomips16") {
1141    // ignore this directive for now
1142    Parser.EatToEndOfStatement();
1143    return false;
1144  } else if (Tok.getString() == "nomicromips") {
1145    // ignore this directive for now
1146    Parser.EatToEndOfStatement();
1147    return false;
1148  }
1149  return true;
1150}
1151
1152bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
1153
1154  if (DirectiveID.getString() == ".ent") {
1155    // ignore this directive for now
1156    Parser.Lex();
1157    return false;
1158  }
1159
1160  if (DirectiveID.getString() == ".end") {
1161    // ignore this directive for now
1162    Parser.Lex();
1163    return false;
1164  }
1165
1166  if (DirectiveID.getString() == ".frame") {
1167    // ignore this directive for now
1168    Parser.EatToEndOfStatement();
1169    return false;
1170  }
1171
1172  if (DirectiveID.getString() == ".set") {
1173    return parseDirectiveSet();
1174  }
1175
1176  if (DirectiveID.getString() == ".fmask") {
1177    // ignore this directive for now
1178    Parser.EatToEndOfStatement();
1179    return false;
1180  }
1181
1182  if (DirectiveID.getString() == ".mask") {
1183    // ignore this directive for now
1184    Parser.EatToEndOfStatement();
1185    return false;
1186  }
1187
1188  if (DirectiveID.getString() == ".gpword") {
1189    // ignore this directive for now
1190    Parser.EatToEndOfStatement();
1191    return false;
1192  }
1193
1194  return true;
1195}
1196
1197extern "C" void LLVMInitializeMipsAsmParser() {
1198  RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1199  RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1200  RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1201  RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1202}
1203
1204#define GET_REGISTER_MATCHER
1205#define GET_MATCHER_IMPLEMENTATION
1206#include "MipsGenAsmMatcher.inc"
1207