Improvements to MIPS64 assembler:
[oota-llvm.git] / lib / Target / Mips / AsmParser / MipsAsmParser.cpp
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
24 using namespace llvm;
25
26 namespace {
27 class MipsAssemblerOptions {
28 public:
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
44 private:
45   unsigned aTReg;
46   bool reorder;
47   bool macro;
48 };
49 }
50
51 namespace {
52 class 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();
144 public:
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
157 namespace {
158
159 /// MipsOperand - Instances of this class represent a parsed Mips machine
160 /// instruction.
161 class 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
197 public:
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
304 bool MipsAsmParser::needsExpansion(MCInst &Inst) {
305
306   switch(Inst.getOpcode()) {
307     case Mips::LoadImm32Reg:
308       return true;
309     default:
310       return false;
311   }
312 }
313
314 void 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
322 void 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
368 bool MipsAsmParser::
369 MatchAndEmitInstruction(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
416 int 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 }
520 void MipsAsmParser::setDefaultFpFormat() {
521
522   if (isMips64() || isFP64())
523     FpFormat = FP_FORMAT_D;
524   else
525     FpFormat = FP_FORMAT_S;
526 }
527
528 bool 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 }
539 void 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
549 bool MipsAssemblerOptions::setATReg(unsigned Reg) {
550   if (Reg > 31)
551     return false;
552
553   aTReg = Reg;
554   return true;
555 }
556
557 unsigned 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
565 unsigned MipsAsmParser::getReg(int RC,int RegNo) {
566   return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
567 }
568
569 int 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
585 int 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
605 bool 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
630 bool 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
720 bool 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
782 bool 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
791 bool 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
810 MipsAsmParser::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
866 MCSymbolRefExpr::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
892 static 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
915 bool MipsAsmParser::
916 parseMathOperation(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
968 bool MipsAsmParser::
969 ParseInstruction(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
1048 bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1049    SMLoc Loc = getLexer().getLoc();
1050    Parser.EatToEndOfStatement();
1051    return Error(Loc, ErrorMsg);
1052 }
1053
1054 bool 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 }
1069 bool 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
1108 bool 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
1120 bool 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
1132 bool 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
1144 bool 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 }
1159 bool 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
1188 bool 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
1233 extern "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"