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