1262261Sdim//===-- SparcAsmParser.cpp - Parse Sparc assembly to MCInst instructions --===//
2262261Sdim//
3262261Sdim//                     The LLVM Compiler Infrastructure
4262261Sdim//
5262261Sdim// This file is distributed under the University of Illinois Open Source
6262261Sdim// License. See LICENSE.TXT for details.
7262261Sdim//
8262261Sdim//===----------------------------------------------------------------------===//
9262261Sdim
10262261Sdim#include "MCTargetDesc/SparcMCTargetDesc.h"
11262261Sdim#include "MCTargetDesc/SparcMCExpr.h"
12262261Sdim#include "llvm/ADT/STLExtras.h"
13262261Sdim#include "llvm/MC/MCContext.h"
14262261Sdim#include "llvm/MC/MCInst.h"
15262261Sdim#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
16262261Sdim#include "llvm/MC/MCStreamer.h"
17262261Sdim#include "llvm/MC/MCSubtargetInfo.h"
18262261Sdim#include "llvm/MC/MCTargetAsmParser.h"
19262261Sdim#include "llvm/Support/TargetRegistry.h"
20262261Sdim
21262261Sdimusing namespace llvm;
22262261Sdim
23262261Sdim// The generated AsmMatcher SparcGenAsmMatcher uses "Sparc" as the target
24262261Sdim// namespace. But SPARC backend uses "SP" as its namespace.
25262261Sdimnamespace llvm {
26262261Sdim  namespace Sparc {
27262261Sdim    using namespace SP;
28262261Sdim  }
29262261Sdim}
30262261Sdim
31262261Sdimnamespace {
32262261Sdimclass SparcOperand;
33262261Sdimclass SparcAsmParser : public MCTargetAsmParser {
34262261Sdim
35262261Sdim  MCSubtargetInfo &STI;
36262261Sdim  MCAsmParser &Parser;
37262261Sdim
38262261Sdim  /// @name Auto-generated Match Functions
39262261Sdim  /// {
40262261Sdim
41262261Sdim#define GET_ASSEMBLER_HEADER
42262261Sdim#include "SparcGenAsmMatcher.inc"
43262261Sdim
44262261Sdim  /// }
45262261Sdim
46262261Sdim  // public interface of the MCTargetAsmParser.
47262261Sdim  bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
48262261Sdim                               SmallVectorImpl<MCParsedAsmOperand*> &Operands,
49262261Sdim                               MCStreamer &Out, unsigned &ErrorInfo,
50262261Sdim                               bool MatchingInlineAsm);
51262261Sdim  bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
52262261Sdim  bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
53262261Sdim                        SMLoc NameLoc,
54262261Sdim                        SmallVectorImpl<MCParsedAsmOperand*> &Operands);
55262261Sdim  bool ParseDirective(AsmToken DirectiveID);
56262261Sdim
57262261Sdim  virtual unsigned validateTargetOperandClass(MCParsedAsmOperand *Op,
58262261Sdim                                              unsigned Kind);
59262261Sdim
60262261Sdim  // Custom parse functions for Sparc specific operands.
61262261Sdim  OperandMatchResultTy
62262261Sdim  parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
63262261Sdim
64262261Sdim  OperandMatchResultTy
65262261Sdim  parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
66262261Sdim               StringRef Name);
67262261Sdim
68262261Sdim  OperandMatchResultTy
69262261Sdim  parseSparcAsmOperand(SparcOperand *&Operand);
70262261Sdim
71262261Sdim  // returns true if Tok is matched to a register and returns register in RegNo.
72262261Sdim  bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo,
73262261Sdim                         unsigned &RegKind);
74262261Sdim
75262261Sdim  bool matchSparcAsmModifiers(const MCExpr *&EVal, SMLoc &EndLoc);
76262261Sdim
77262261Sdimpublic:
78262261Sdim  SparcAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
79262261Sdim                const MCInstrInfo &MII)
80262261Sdim      : MCTargetAsmParser(), STI(sti), Parser(parser) {
81262261Sdim    // Initialize the set of available features.
82262261Sdim    setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
83262261Sdim  }
84262261Sdim
85262261Sdim};
86262261Sdim
87262261Sdim  static unsigned IntRegs[32] = {
88262261Sdim    Sparc::G0, Sparc::G1, Sparc::G2, Sparc::G3,
89262261Sdim    Sparc::G4, Sparc::G5, Sparc::G6, Sparc::G7,
90262261Sdim    Sparc::O0, Sparc::O1, Sparc::O2, Sparc::O3,
91262261Sdim    Sparc::O4, Sparc::O5, Sparc::O6, Sparc::O7,
92262261Sdim    Sparc::L0, Sparc::L1, Sparc::L2, Sparc::L3,
93262261Sdim    Sparc::L4, Sparc::L5, Sparc::L6, Sparc::L7,
94262261Sdim    Sparc::I0, Sparc::I1, Sparc::I2, Sparc::I3,
95262261Sdim    Sparc::I4, Sparc::I5, Sparc::I6, Sparc::I7 };
96262261Sdim
97262261Sdim  static unsigned FloatRegs[32] = {
98262261Sdim    Sparc::F0,  Sparc::F1,  Sparc::F2,  Sparc::F3,
99262261Sdim    Sparc::F4,  Sparc::F5,  Sparc::F6,  Sparc::F7,
100262261Sdim    Sparc::F8,  Sparc::F9,  Sparc::F10, Sparc::F11,
101262261Sdim    Sparc::F12, Sparc::F13, Sparc::F14, Sparc::F15,
102262261Sdim    Sparc::F16, Sparc::F17, Sparc::F18, Sparc::F19,
103262261Sdim    Sparc::F20, Sparc::F21, Sparc::F22, Sparc::F23,
104262261Sdim    Sparc::F24, Sparc::F25, Sparc::F26, Sparc::F27,
105262261Sdim    Sparc::F28, Sparc::F29, Sparc::F30, Sparc::F31 };
106262261Sdim
107262261Sdim  static unsigned DoubleRegs[32] = {
108262261Sdim    Sparc::D0,  Sparc::D1,  Sparc::D2,  Sparc::D3,
109262261Sdim    Sparc::D4,  Sparc::D5,  Sparc::D6,  Sparc::D7,
110262261Sdim    Sparc::D8,  Sparc::D7,  Sparc::D8,  Sparc::D9,
111262261Sdim    Sparc::D12, Sparc::D13, Sparc::D14, Sparc::D15,
112262261Sdim    Sparc::D16, Sparc::D17, Sparc::D18, Sparc::D19,
113262261Sdim    Sparc::D20, Sparc::D21, Sparc::D22, Sparc::D23,
114262261Sdim    Sparc::D24, Sparc::D25, Sparc::D26, Sparc::D27,
115262261Sdim    Sparc::D28, Sparc::D29, Sparc::D30, Sparc::D31 };
116262261Sdim
117262261Sdim  static unsigned QuadFPRegs[32] = {
118262261Sdim    Sparc::Q0,  Sparc::Q1,  Sparc::Q2,  Sparc::Q3,
119262261Sdim    Sparc::Q4,  Sparc::Q5,  Sparc::Q6,  Sparc::Q7,
120262261Sdim    Sparc::Q8,  Sparc::Q9,  Sparc::Q10, Sparc::Q11,
121262261Sdim    Sparc::Q12, Sparc::Q13, Sparc::Q14, Sparc::Q15 };
122262261Sdim
123262261Sdim
124262261Sdim/// SparcOperand - Instances of this class represent a parsed Sparc machine
125262261Sdim/// instruction.
126262261Sdimclass SparcOperand : public MCParsedAsmOperand {
127262261Sdimpublic:
128262261Sdim  enum RegisterKind {
129262261Sdim    rk_None,
130262261Sdim    rk_IntReg,
131262261Sdim    rk_FloatReg,
132262261Sdim    rk_DoubleReg,
133262261Sdim    rk_QuadReg,
134262261Sdim    rk_CCReg,
135262261Sdim    rk_Y
136262261Sdim  };
137262261Sdimprivate:
138262261Sdim  enum KindTy {
139262261Sdim    k_Token,
140262261Sdim    k_Register,
141262261Sdim    k_Immediate,
142262261Sdim    k_MemoryReg,
143262261Sdim    k_MemoryImm
144262261Sdim  } Kind;
145262261Sdim
146262261Sdim  SMLoc StartLoc, EndLoc;
147262261Sdim
148262261Sdim  SparcOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
149262261Sdim
150262261Sdim  struct Token {
151262261Sdim    const char *Data;
152262261Sdim    unsigned Length;
153262261Sdim  };
154262261Sdim
155262261Sdim  struct RegOp {
156262261Sdim    unsigned RegNum;
157262261Sdim    RegisterKind Kind;
158262261Sdim  };
159262261Sdim
160262261Sdim  struct ImmOp {
161262261Sdim    const MCExpr *Val;
162262261Sdim  };
163262261Sdim
164262261Sdim  struct MemOp {
165262261Sdim    unsigned Base;
166262261Sdim    unsigned OffsetReg;
167262261Sdim    const MCExpr *Off;
168262261Sdim  };
169262261Sdim
170262261Sdim  union {
171262261Sdim    struct Token Tok;
172262261Sdim    struct RegOp Reg;
173262261Sdim    struct ImmOp Imm;
174262261Sdim    struct MemOp Mem;
175262261Sdim  };
176262261Sdimpublic:
177262261Sdim  bool isToken() const { return Kind == k_Token; }
178262261Sdim  bool isReg() const { return Kind == k_Register; }
179262261Sdim  bool isImm() const { return Kind == k_Immediate; }
180262261Sdim  bool isMem() const { return isMEMrr() || isMEMri(); }
181262261Sdim  bool isMEMrr() const { return Kind == k_MemoryReg; }
182262261Sdim  bool isMEMri() const { return Kind == k_MemoryImm; }
183262261Sdim
184262261Sdim  bool isFloatReg() const {
185262261Sdim    return (Kind == k_Register && Reg.Kind == rk_FloatReg);
186262261Sdim  }
187262261Sdim
188262261Sdim  bool isFloatOrDoubleReg() const {
189262261Sdim    return (Kind == k_Register && (Reg.Kind == rk_FloatReg
190262261Sdim                                   || Reg.Kind == rk_DoubleReg));
191262261Sdim  }
192262261Sdim
193262261Sdim
194262261Sdim  StringRef getToken() const {
195262261Sdim    assert(Kind == k_Token && "Invalid access!");
196262261Sdim    return StringRef(Tok.Data, Tok.Length);
197262261Sdim  }
198262261Sdim
199262261Sdim  unsigned getReg() const {
200262261Sdim    assert((Kind == k_Register) && "Invalid access!");
201262261Sdim    return Reg.RegNum;
202262261Sdim  }
203262261Sdim
204262261Sdim  const MCExpr *getImm() const {
205262261Sdim    assert((Kind == k_Immediate) && "Invalid access!");
206262261Sdim    return Imm.Val;
207262261Sdim  }
208262261Sdim
209262261Sdim  unsigned getMemBase() const {
210262261Sdim    assert((Kind == k_MemoryReg || Kind == k_MemoryImm) && "Invalid access!");
211262261Sdim    return Mem.Base;
212262261Sdim  }
213262261Sdim
214262261Sdim  unsigned getMemOffsetReg() const {
215262261Sdim    assert((Kind == k_MemoryReg) && "Invalid access!");
216262261Sdim    return Mem.OffsetReg;
217262261Sdim  }
218262261Sdim
219262261Sdim  const MCExpr *getMemOff() const {
220262261Sdim    assert((Kind == k_MemoryImm) && "Invalid access!");
221262261Sdim    return Mem.Off;
222262261Sdim  }
223262261Sdim
224262261Sdim  /// getStartLoc - Get the location of the first token of this operand.
225262261Sdim  SMLoc getStartLoc() const {
226262261Sdim    return StartLoc;
227262261Sdim  }
228262261Sdim  /// getEndLoc - Get the location of the last token of this operand.
229262261Sdim  SMLoc getEndLoc() const {
230262261Sdim    return EndLoc;
231262261Sdim  }
232262261Sdim
233262261Sdim  virtual void print(raw_ostream &OS) const {
234262261Sdim    switch (Kind) {
235262261Sdim    case k_Token:     OS << "Token: " << getToken() << "\n"; break;
236262261Sdim    case k_Register:  OS << "Reg: #" << getReg() << "\n"; break;
237262261Sdim    case k_Immediate: OS << "Imm: " << getImm() << "\n"; break;
238262261Sdim    case k_MemoryReg: OS << "Mem: " << getMemBase() << "+"
239262261Sdim                         << getMemOffsetReg() << "\n"; break;
240262261Sdim    case k_MemoryImm: assert(getMemOff() != 0);
241262261Sdim      OS << "Mem: " << getMemBase()
242262261Sdim         << "+" << *getMemOff()
243262261Sdim         << "\n"; break;
244262261Sdim    }
245262261Sdim  }
246262261Sdim
247262261Sdim  void addRegOperands(MCInst &Inst, unsigned N) const {
248262261Sdim    assert(N == 1 && "Invalid number of operands!");
249262261Sdim    Inst.addOperand(MCOperand::CreateReg(getReg()));
250262261Sdim  }
251262261Sdim
252262261Sdim  void addImmOperands(MCInst &Inst, unsigned N) const {
253262261Sdim    assert(N == 1 && "Invalid number of operands!");
254262261Sdim    const MCExpr *Expr = getImm();
255262261Sdim    addExpr(Inst, Expr);
256262261Sdim  }
257262261Sdim
258262261Sdim  void addExpr(MCInst &Inst, const MCExpr *Expr) const{
259262261Sdim    // Add as immediate when possible.  Null MCExpr = 0.
260262261Sdim    if (Expr == 0)
261262261Sdim      Inst.addOperand(MCOperand::CreateImm(0));
262262261Sdim    else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
263262261Sdim      Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
264262261Sdim    else
265262261Sdim      Inst.addOperand(MCOperand::CreateExpr(Expr));
266262261Sdim  }
267262261Sdim
268262261Sdim  void addMEMrrOperands(MCInst &Inst, unsigned N) const {
269262261Sdim    assert(N == 2 && "Invalid number of operands!");
270262261Sdim
271262261Sdim    Inst.addOperand(MCOperand::CreateReg(getMemBase()));
272262261Sdim
273262261Sdim    assert(getMemOffsetReg() != 0 && "Invalid offset");
274262261Sdim    Inst.addOperand(MCOperand::CreateReg(getMemOffsetReg()));
275262261Sdim  }
276262261Sdim
277262261Sdim  void addMEMriOperands(MCInst &Inst, unsigned N) const {
278262261Sdim    assert(N == 2 && "Invalid number of operands!");
279262261Sdim
280262261Sdim    Inst.addOperand(MCOperand::CreateReg(getMemBase()));
281262261Sdim
282262261Sdim    const MCExpr *Expr = getMemOff();
283262261Sdim    addExpr(Inst, Expr);
284262261Sdim  }
285262261Sdim
286262261Sdim  static SparcOperand *CreateToken(StringRef Str, SMLoc S) {
287262261Sdim    SparcOperand *Op = new SparcOperand(k_Token);
288262261Sdim    Op->Tok.Data = Str.data();
289262261Sdim    Op->Tok.Length = Str.size();
290262261Sdim    Op->StartLoc = S;
291262261Sdim    Op->EndLoc = S;
292262261Sdim    return Op;
293262261Sdim  }
294262261Sdim
295262261Sdim  static SparcOperand *CreateReg(unsigned RegNum,
296262261Sdim                                 unsigned Kind,
297262261Sdim                                 SMLoc S, SMLoc E) {
298262261Sdim    SparcOperand *Op = new SparcOperand(k_Register);
299262261Sdim    Op->Reg.RegNum = RegNum;
300262261Sdim    Op->Reg.Kind   = (SparcOperand::RegisterKind)Kind;
301262261Sdim    Op->StartLoc = S;
302262261Sdim    Op->EndLoc = E;
303262261Sdim    return Op;
304262261Sdim  }
305262261Sdim
306262261Sdim  static SparcOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
307262261Sdim    SparcOperand *Op = new SparcOperand(k_Immediate);
308262261Sdim    Op->Imm.Val = Val;
309262261Sdim    Op->StartLoc = S;
310262261Sdim    Op->EndLoc = E;
311262261Sdim    return Op;
312262261Sdim  }
313262261Sdim
314262261Sdim  static SparcOperand *MorphToDoubleReg(SparcOperand *Op) {
315262261Sdim    unsigned Reg = Op->getReg();
316262261Sdim    assert(Op->Reg.Kind == rk_FloatReg);
317262261Sdim    unsigned regIdx = Reg - Sparc::F0;
318262261Sdim    if (regIdx % 2 || regIdx > 31)
319262261Sdim      return 0;
320262261Sdim    Op->Reg.RegNum = DoubleRegs[regIdx / 2];
321262261Sdim    Op->Reg.Kind = rk_DoubleReg;
322262261Sdim    return Op;
323262261Sdim  }
324262261Sdim
325262261Sdim  static SparcOperand *MorphToQuadReg(SparcOperand *Op) {
326262261Sdim    unsigned Reg = Op->getReg();
327262261Sdim    unsigned regIdx = 0;
328262261Sdim    switch (Op->Reg.Kind) {
329262261Sdim    default: assert(0 && "Unexpected register kind!");
330262261Sdim    case rk_FloatReg:
331262261Sdim      regIdx = Reg - Sparc::F0;
332262261Sdim      if (regIdx % 4 || regIdx > 31)
333262261Sdim        return 0;
334262261Sdim      Reg = QuadFPRegs[regIdx / 4];
335262261Sdim      break;
336262261Sdim    case rk_DoubleReg:
337262261Sdim      regIdx =  Reg - Sparc::D0;
338262261Sdim      if (regIdx % 2 || regIdx > 31)
339262261Sdim        return 0;
340262261Sdim      Reg = QuadFPRegs[regIdx / 2];
341262261Sdim      break;
342262261Sdim    }
343262261Sdim    Op->Reg.RegNum  = Reg;
344262261Sdim    Op->Reg.Kind = rk_QuadReg;
345262261Sdim    return Op;
346262261Sdim  }
347262261Sdim
348262261Sdim  static SparcOperand *MorphToMEMrr(unsigned Base, SparcOperand *Op) {
349262261Sdim    unsigned offsetReg = Op->getReg();
350262261Sdim    Op->Kind = k_MemoryReg;
351262261Sdim    Op->Mem.Base = Base;
352262261Sdim    Op->Mem.OffsetReg = offsetReg;
353262261Sdim    Op->Mem.Off = 0;
354262261Sdim    return Op;
355262261Sdim  }
356262261Sdim
357262261Sdim  static SparcOperand *CreateMEMri(unsigned Base,
358262261Sdim                                 const MCExpr *Off,
359262261Sdim                                 SMLoc S, SMLoc E) {
360262261Sdim    SparcOperand *Op = new SparcOperand(k_MemoryImm);
361262261Sdim    Op->Mem.Base = Base;
362262261Sdim    Op->Mem.OffsetReg = 0;
363262261Sdim    Op->Mem.Off = Off;
364262261Sdim    Op->StartLoc = S;
365262261Sdim    Op->EndLoc = E;
366262261Sdim    return Op;
367262261Sdim  }
368262261Sdim
369262261Sdim  static SparcOperand *MorphToMEMri(unsigned Base, SparcOperand *Op) {
370262261Sdim    const MCExpr *Imm  = Op->getImm();
371262261Sdim    Op->Kind = k_MemoryImm;
372262261Sdim    Op->Mem.Base = Base;
373262261Sdim    Op->Mem.OffsetReg = 0;
374262261Sdim    Op->Mem.Off = Imm;
375262261Sdim    return Op;
376262261Sdim  }
377262261Sdim};
378262261Sdim
379262261Sdim} // end namespace
380262261Sdim
381262261Sdimbool SparcAsmParser::
382262261SdimMatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
383262261Sdim                        SmallVectorImpl<MCParsedAsmOperand*> &Operands,
384262261Sdim                        MCStreamer &Out, unsigned &ErrorInfo,
385262261Sdim                        bool MatchingInlineAsm) {
386262261Sdim  MCInst Inst;
387262261Sdim  SmallVector<MCInst, 8> Instructions;
388262261Sdim  unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
389262261Sdim                                              MatchingInlineAsm);
390262261Sdim  switch (MatchResult) {
391262261Sdim  default:
392262261Sdim    break;
393262261Sdim
394262261Sdim  case Match_Success: {
395262261Sdim    Inst.setLoc(IDLoc);
396262261Sdim    Out.EmitInstruction(Inst);
397262261Sdim    return false;
398262261Sdim  }
399262261Sdim
400262261Sdim  case Match_MissingFeature:
401262261Sdim    return Error(IDLoc,
402262261Sdim                 "instruction requires a CPU feature not currently enabled");
403262261Sdim
404262261Sdim  case Match_InvalidOperand: {
405262261Sdim    SMLoc ErrorLoc = IDLoc;
406262261Sdim    if (ErrorInfo != ~0U) {
407262261Sdim      if (ErrorInfo >= Operands.size())
408262261Sdim        return Error(IDLoc, "too few operands for instruction");
409262261Sdim
410262261Sdim      ErrorLoc = ((SparcOperand*) Operands[ErrorInfo])->getStartLoc();
411262261Sdim      if (ErrorLoc == SMLoc())
412262261Sdim        ErrorLoc = IDLoc;
413262261Sdim    }
414262261Sdim
415262261Sdim    return Error(ErrorLoc, "invalid operand for instruction");
416262261Sdim  }
417262261Sdim  case Match_MnemonicFail:
418262261Sdim    return Error(IDLoc, "invalid instruction");
419262261Sdim  }
420262261Sdim  return true;
421262261Sdim}
422262261Sdim
423262261Sdimbool SparcAsmParser::
424262261SdimParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc)
425262261Sdim{
426262261Sdim  const AsmToken &Tok = Parser.getTok();
427262261Sdim  StartLoc = Tok.getLoc();
428262261Sdim  EndLoc = Tok.getEndLoc();
429262261Sdim  RegNo = 0;
430262261Sdim  if (getLexer().getKind() != AsmToken::Percent)
431262261Sdim    return false;
432262261Sdim  Parser.Lex();
433262261Sdim  unsigned regKind = SparcOperand::rk_None;
434262261Sdim  if (matchRegisterName(Tok, RegNo, regKind)) {
435262261Sdim    Parser.Lex();
436262261Sdim    return false;
437262261Sdim  }
438262261Sdim
439262261Sdim  return Error(StartLoc, "invalid register name");
440262261Sdim}
441262261Sdim
442262261Sdimbool SparcAsmParser::
443262261SdimParseInstruction(ParseInstructionInfo &Info, StringRef Name,
444262261Sdim                 SMLoc NameLoc,
445262261Sdim                 SmallVectorImpl<MCParsedAsmOperand*> &Operands)
446262261Sdim{
447262261Sdim  // Check if we have valid mnemonic.
448262261Sdim  if (!mnemonicIsValid(Name, 0)) {
449262261Sdim    Parser.eatToEndOfStatement();
450262261Sdim    return Error(NameLoc, "Unknown instruction");
451262261Sdim  }
452262261Sdim  // First operand in MCInst is instruction mnemonic.
453262261Sdim  Operands.push_back(SparcOperand::CreateToken(Name, NameLoc));
454262261Sdim
455262261Sdim  if (getLexer().isNot(AsmToken::EndOfStatement)) {
456262261Sdim    // Read the first operand.
457262261Sdim    if (parseOperand(Operands, Name) != MatchOperand_Success) {
458262261Sdim      SMLoc Loc = getLexer().getLoc();
459262261Sdim      Parser.eatToEndOfStatement();
460262261Sdim      return Error(Loc, "unexpected token");
461262261Sdim    }
462262261Sdim
463262261Sdim    while (getLexer().is(AsmToken::Comma)) {
464262261Sdim      Parser.Lex(); // Eat the comma.
465262261Sdim      // Parse and remember the operand.
466262261Sdim      if (parseOperand(Operands, Name) != MatchOperand_Success) {
467262261Sdim        SMLoc Loc = getLexer().getLoc();
468262261Sdim        Parser.eatToEndOfStatement();
469262261Sdim        return Error(Loc, "unexpected token");
470262261Sdim      }
471262261Sdim    }
472262261Sdim  }
473262261Sdim  if (getLexer().isNot(AsmToken::EndOfStatement)) {
474262261Sdim    SMLoc Loc = getLexer().getLoc();
475262261Sdim    Parser.eatToEndOfStatement();
476262261Sdim    return Error(Loc, "unexpected token");
477262261Sdim  }
478262261Sdim  Parser.Lex(); // Consume the EndOfStatement.
479262261Sdim  return false;
480262261Sdim}
481262261Sdim
482262261Sdimbool SparcAsmParser::
483262261SdimParseDirective(AsmToken DirectiveID)
484262261Sdim{
485262261Sdim  // Ignore all directives for now.
486262261Sdim  Parser.eatToEndOfStatement();
487262261Sdim  return false;
488262261Sdim}
489262261Sdim
490262261SdimSparcAsmParser::OperandMatchResultTy SparcAsmParser::
491262261SdimparseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
492262261Sdim{
493262261Sdim
494262261Sdim  SMLoc S, E;
495262261Sdim  unsigned BaseReg = 0;
496262261Sdim
497262261Sdim  if (ParseRegister(BaseReg, S, E)) {
498262261Sdim    return MatchOperand_NoMatch;
499262261Sdim  }
500262261Sdim
501262261Sdim  switch (getLexer().getKind()) {
502262261Sdim  default: return MatchOperand_NoMatch;
503262261Sdim
504262261Sdim  case AsmToken::Comma:
505262261Sdim  case AsmToken::RBrac:
506262261Sdim  case AsmToken::EndOfStatement:
507262261Sdim    Operands.push_back(SparcOperand::CreateMEMri(BaseReg, 0, S, E));
508262261Sdim    return MatchOperand_Success;
509262261Sdim
510262261Sdim  case AsmToken:: Plus:
511262261Sdim    Parser.Lex(); // Eat the '+'
512262261Sdim    break;
513262261Sdim  case AsmToken::Minus:
514262261Sdim    break;
515262261Sdim  }
516262261Sdim
517262261Sdim  SparcOperand *Offset = 0;
518262261Sdim  OperandMatchResultTy ResTy = parseSparcAsmOperand(Offset);
519262261Sdim  if (ResTy != MatchOperand_Success || !Offset)
520262261Sdim    return MatchOperand_NoMatch;
521262261Sdim
522262261Sdim  Offset = (Offset->isImm()
523262261Sdim            ? SparcOperand::MorphToMEMri(BaseReg, Offset)
524262261Sdim            : SparcOperand::MorphToMEMrr(BaseReg, Offset));
525262261Sdim
526262261Sdim  Operands.push_back(Offset);
527262261Sdim  return MatchOperand_Success;
528262261Sdim}
529262261Sdim
530262261SdimSparcAsmParser::OperandMatchResultTy SparcAsmParser::
531262261SdimparseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
532262261Sdim             StringRef Mnemonic)
533262261Sdim{
534262261Sdim
535262261Sdim  OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
536262261Sdim
537262261Sdim  // If there wasn't a custom match, try the generic matcher below. Otherwise,
538262261Sdim  // there was a match, but an error occurred, in which case, just return that
539262261Sdim  // the operand parsing failed.
540262261Sdim  if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail)
541262261Sdim    return ResTy;
542262261Sdim
543262261Sdim  if (getLexer().is(AsmToken::LBrac)) {
544262261Sdim    // Memory operand
545262261Sdim    Operands.push_back(SparcOperand::CreateToken("[",
546262261Sdim                                                 Parser.getTok().getLoc()));
547262261Sdim    Parser.Lex(); // Eat the [
548262261Sdim
549262261Sdim    if (Mnemonic == "cas" || Mnemonic == "casx") {
550262261Sdim      SMLoc S = Parser.getTok().getLoc();
551262261Sdim      if (getLexer().getKind() != AsmToken::Percent)
552262261Sdim        return MatchOperand_NoMatch;
553262261Sdim      Parser.Lex(); // eat %
554262261Sdim
555262261Sdim      unsigned RegNo, RegKind;
556262261Sdim      if (!matchRegisterName(Parser.getTok(), RegNo, RegKind))
557262261Sdim        return MatchOperand_NoMatch;
558262261Sdim
559262261Sdim      Parser.Lex(); // Eat the identifier token.
560262261Sdim      SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer()-1);
561262261Sdim      Operands.push_back(SparcOperand::CreateReg(RegNo, RegKind, S, E));
562262261Sdim      ResTy = MatchOperand_Success;
563262261Sdim    } else {
564262261Sdim      ResTy = parseMEMOperand(Operands);
565262261Sdim    }
566262261Sdim
567262261Sdim    if (ResTy != MatchOperand_Success)
568262261Sdim      return ResTy;
569262261Sdim
570262261Sdim    if (!getLexer().is(AsmToken::RBrac))
571262261Sdim      return MatchOperand_ParseFail;
572262261Sdim
573262261Sdim    Operands.push_back(SparcOperand::CreateToken("]",
574262261Sdim                                                 Parser.getTok().getLoc()));
575262261Sdim    Parser.Lex(); // Eat the ]
576262261Sdim    return MatchOperand_Success;
577262261Sdim  }
578262261Sdim
579262261Sdim  SparcOperand *Op = 0;
580262261Sdim  ResTy = parseSparcAsmOperand(Op);
581262261Sdim  if (ResTy != MatchOperand_Success || !Op)
582262261Sdim    return MatchOperand_ParseFail;
583262261Sdim
584262261Sdim  // Push the parsed operand into the list of operands
585262261Sdim  Operands.push_back(Op);
586262261Sdim
587262261Sdim  return MatchOperand_Success;
588262261Sdim}
589262261Sdim
590262261SdimSparcAsmParser::OperandMatchResultTy
591262261SdimSparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op)
592262261Sdim{
593262261Sdim
594262261Sdim  SMLoc S = Parser.getTok().getLoc();
595262261Sdim  SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
596262261Sdim  const MCExpr *EVal;
597262261Sdim
598262261Sdim  Op = 0;
599262261Sdim  switch (getLexer().getKind()) {
600262261Sdim  default:  break;
601262261Sdim
602262261Sdim  case AsmToken::Percent:
603262261Sdim    Parser.Lex(); // Eat the '%'.
604262261Sdim    unsigned RegNo;
605262261Sdim    unsigned RegKind;
606262261Sdim    if (matchRegisterName(Parser.getTok(), RegNo, RegKind)) {
607262261Sdim      StringRef name = Parser.getTok().getString();
608262261Sdim      Parser.Lex(); // Eat the identifier token.
609262261Sdim      E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
610262261Sdim      switch (RegNo) {
611262261Sdim      default:
612262261Sdim        Op = SparcOperand::CreateReg(RegNo, RegKind, S, E);
613262261Sdim        break;
614262261Sdim      case Sparc::Y:
615262261Sdim        Op = SparcOperand::CreateToken("%y", S);
616262261Sdim        break;
617262261Sdim
618262261Sdim      case Sparc::ICC:
619262261Sdim        if (name == "xcc")
620262261Sdim          Op = SparcOperand::CreateToken("%xcc", S);
621262261Sdim        else
622262261Sdim          Op = SparcOperand::CreateToken("%icc", S);
623262261Sdim        break;
624262261Sdim
625262261Sdim      case Sparc::FCC:
626262261Sdim        assert(name == "fcc0" && "Cannot handle %fcc other than %fcc0 yet");
627262261Sdim        Op = SparcOperand::CreateToken("%fcc0", S);
628262261Sdim        break;
629262261Sdim      }
630262261Sdim      break;
631262261Sdim    }
632262261Sdim    if (matchSparcAsmModifiers(EVal, E)) {
633262261Sdim      E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
634262261Sdim      Op = SparcOperand::CreateImm(EVal, S, E);
635262261Sdim    }
636262261Sdim    break;
637262261Sdim
638262261Sdim  case AsmToken::Minus:
639262261Sdim  case AsmToken::Integer:
640262261Sdim    if (!getParser().parseExpression(EVal, E))
641262261Sdim      Op = SparcOperand::CreateImm(EVal, S, E);
642262261Sdim    break;
643262261Sdim
644262261Sdim  case AsmToken::Identifier: {
645262261Sdim    StringRef Identifier;
646262261Sdim    if (!getParser().parseIdentifier(Identifier)) {
647262261Sdim      E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
648262261Sdim      MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier);
649262261Sdim
650262261Sdim      const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
651262261Sdim                                                  getContext());
652262261Sdim      Op = SparcOperand::CreateImm(Res, S, E);
653262261Sdim    }
654262261Sdim    break;
655262261Sdim  }
656262261Sdim  }
657262261Sdim  return (Op) ? MatchOperand_Success : MatchOperand_ParseFail;
658262261Sdim}
659262261Sdim
660262261Sdimbool SparcAsmParser::matchRegisterName(const AsmToken &Tok,
661262261Sdim                                       unsigned &RegNo,
662262261Sdim                                       unsigned &RegKind)
663262261Sdim{
664262261Sdim  int64_t intVal = 0;
665262261Sdim  RegNo = 0;
666262261Sdim  RegKind = SparcOperand::rk_None;
667262261Sdim  if (Tok.is(AsmToken::Identifier)) {
668262261Sdim    StringRef name = Tok.getString();
669262261Sdim
670262261Sdim    // %fp
671262261Sdim    if (name.equals("fp")) {
672262261Sdim      RegNo = Sparc::I6;
673262261Sdim      RegKind = SparcOperand::rk_IntReg;
674262261Sdim      return true;
675262261Sdim    }
676262261Sdim    // %sp
677262261Sdim    if (name.equals("sp")) {
678262261Sdim      RegNo = Sparc::O6;
679262261Sdim      RegKind = SparcOperand::rk_IntReg;
680262261Sdim      return true;
681262261Sdim    }
682262261Sdim
683262261Sdim    if (name.equals("y")) {
684262261Sdim      RegNo = Sparc::Y;
685262261Sdim      RegKind = SparcOperand::rk_Y;
686262261Sdim      return true;
687262261Sdim    }
688262261Sdim
689262261Sdim    if (name.equals("icc")) {
690262261Sdim      RegNo = Sparc::ICC;
691262261Sdim      RegKind = SparcOperand::rk_CCReg;
692262261Sdim      return true;
693262261Sdim    }
694262261Sdim
695262261Sdim    if (name.equals("xcc")) {
696262261Sdim      // FIXME:: check 64bit.
697262261Sdim      RegNo = Sparc::ICC;
698262261Sdim      RegKind = SparcOperand::rk_CCReg;
699262261Sdim      return true;
700262261Sdim    }
701262261Sdim
702262261Sdim    // %fcc0 - %fcc3
703262261Sdim    if (name.substr(0, 3).equals_lower("fcc")
704262261Sdim        && !name.substr(3).getAsInteger(10, intVal)
705262261Sdim        && intVal < 4) {
706262261Sdim      // FIXME: check 64bit and  handle %fcc1 - %fcc3
707262261Sdim      RegNo = Sparc::FCC;
708262261Sdim      RegKind = SparcOperand::rk_CCReg;
709262261Sdim      return true;
710262261Sdim    }
711262261Sdim
712262261Sdim    // %g0 - %g7
713262261Sdim    if (name.substr(0, 1).equals_lower("g")
714262261Sdim        && !name.substr(1).getAsInteger(10, intVal)
715262261Sdim        && intVal < 8) {
716262261Sdim      RegNo = IntRegs[intVal];
717262261Sdim      RegKind = SparcOperand::rk_IntReg;
718262261Sdim      return true;
719262261Sdim    }
720262261Sdim    // %o0 - %o7
721262261Sdim    if (name.substr(0, 1).equals_lower("o")
722262261Sdim        && !name.substr(1).getAsInteger(10, intVal)
723262261Sdim        && intVal < 8) {
724262261Sdim      RegNo = IntRegs[8 + intVal];
725262261Sdim      RegKind = SparcOperand::rk_IntReg;
726262261Sdim      return true;
727262261Sdim    }
728262261Sdim    if (name.substr(0, 1).equals_lower("l")
729262261Sdim        && !name.substr(1).getAsInteger(10, intVal)
730262261Sdim        && intVal < 8) {
731262261Sdim      RegNo = IntRegs[16 + intVal];
732262261Sdim      RegKind = SparcOperand::rk_IntReg;
733262261Sdim      return true;
734262261Sdim    }
735262261Sdim    if (name.substr(0, 1).equals_lower("i")
736262261Sdim        && !name.substr(1).getAsInteger(10, intVal)
737262261Sdim        && intVal < 8) {
738262261Sdim      RegNo = IntRegs[24 + intVal];
739262261Sdim      RegKind = SparcOperand::rk_IntReg;
740262261Sdim      return true;
741262261Sdim    }
742262261Sdim    // %f0 - %f31
743262261Sdim    if (name.substr(0, 1).equals_lower("f")
744262261Sdim        && !name.substr(1, 2).getAsInteger(10, intVal) && intVal < 32) {
745262261Sdim      RegNo = FloatRegs[intVal];
746262261Sdim      RegKind = SparcOperand::rk_FloatReg;
747262261Sdim      return true;
748262261Sdim    }
749262261Sdim    // %f32 - %f62
750262261Sdim    if (name.substr(0, 1).equals_lower("f")
751262261Sdim        && !name.substr(1, 2).getAsInteger(10, intVal)
752262261Sdim        && intVal >= 32 && intVal <= 62 && (intVal % 2 == 0)) {
753262261Sdim      // FIXME: Check V9
754262261Sdim      RegNo = DoubleRegs[intVal/2];
755262261Sdim      RegKind = SparcOperand::rk_DoubleReg;
756262261Sdim      return true;
757262261Sdim    }
758262261Sdim
759262261Sdim    // %r0 - %r31
760262261Sdim    if (name.substr(0, 1).equals_lower("r")
761262261Sdim        && !name.substr(1, 2).getAsInteger(10, intVal) && intVal < 31) {
762262261Sdim      RegNo = IntRegs[intVal];
763262261Sdim      RegKind = SparcOperand::rk_IntReg;
764262261Sdim      return true;
765262261Sdim    }
766262261Sdim  }
767262261Sdim  return false;
768262261Sdim}
769262261Sdim
770262261Sdim
771262261Sdimbool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal,
772262261Sdim                                            SMLoc &EndLoc)
773262261Sdim{
774262261Sdim  AsmToken Tok = Parser.getTok();
775262261Sdim  if (!Tok.is(AsmToken::Identifier))
776262261Sdim    return false;
777262261Sdim
778262261Sdim  StringRef name = Tok.getString();
779262261Sdim
780262261Sdim  SparcMCExpr::VariantKind VK = SparcMCExpr::parseVariantKind(name);
781262261Sdim
782262261Sdim  if (VK == SparcMCExpr::VK_Sparc_None)
783262261Sdim    return false;
784262261Sdim
785262261Sdim  Parser.Lex(); // Eat the identifier.
786262261Sdim  if (Parser.getTok().getKind() != AsmToken::LParen)
787262261Sdim    return false;
788262261Sdim
789262261Sdim  Parser.Lex(); // Eat the LParen token.
790262261Sdim  const MCExpr *subExpr;
791262261Sdim  if (Parser.parseParenExpression(subExpr, EndLoc))
792262261Sdim    return false;
793262261Sdim  EVal = SparcMCExpr::Create(VK, subExpr, getContext());
794262261Sdim  return true;
795262261Sdim}
796262261Sdim
797262261Sdim
798262261Sdimextern "C" void LLVMInitializeSparcAsmParser() {
799262261Sdim  RegisterMCAsmParser<SparcAsmParser> A(TheSparcTarget);
800262261Sdim  RegisterMCAsmParser<SparcAsmParser> B(TheSparcV9Target);
801262261Sdim}
802262261Sdim
803262261Sdim#define GET_REGISTER_MATCHER
804262261Sdim#define GET_MATCHER_IMPLEMENTATION
805262261Sdim#include "SparcGenAsmMatcher.inc"
806262261Sdim
807262261Sdim
808262261Sdim
809262261Sdimunsigned SparcAsmParser::
810262261SdimvalidateTargetOperandClass(MCParsedAsmOperand *GOp,
811262261Sdim                           unsigned Kind)
812262261Sdim{
813262261Sdim  SparcOperand *Op = (SparcOperand*)GOp;
814262261Sdim  if (Op->isFloatOrDoubleReg()) {
815262261Sdim    switch (Kind) {
816262261Sdim    default: break;
817262261Sdim    case MCK_DFPRegs:
818262261Sdim      if (!Op->isFloatReg() || SparcOperand::MorphToDoubleReg(Op))
819262261Sdim        return MCTargetAsmParser::Match_Success;
820262261Sdim      break;
821262261Sdim    case MCK_QFPRegs:
822262261Sdim      if (SparcOperand::MorphToQuadReg(Op))
823262261Sdim        return MCTargetAsmParser::Match_Success;
824262261Sdim      break;
825262261Sdim    }
826262261Sdim  }
827262261Sdim  return Match_InvalidOperand;
828262261Sdim}
829