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