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