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