forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			569 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			569 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
//===-- MBlazeAsmParser.cpp - Parse MBlaze asm to MCInst instructions -----===//
 | 
						|
//
 | 
						|
//                     The LLVM Compiler Infrastructure
 | 
						|
//
 | 
						|
// This file is distributed under the University of Illinois Open Source
 | 
						|
// License. See LICENSE.TXT for details.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "MBlaze.h"
 | 
						|
#include "MBlazeSubtarget.h"
 | 
						|
#include "MBlazeRegisterInfo.h"
 | 
						|
#include "MBlazeISelLowering.h"
 | 
						|
#include "llvm/MC/MCParser/MCAsmLexer.h"
 | 
						|
#include "llvm/MC/MCParser/MCAsmParser.h"
 | 
						|
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
 | 
						|
#include "llvm/MC/MCStreamer.h"
 | 
						|
#include "llvm/MC/MCExpr.h"
 | 
						|
#include "llvm/MC/MCInst.h"
 | 
						|
#include "llvm/Target/TargetRegistry.h"
 | 
						|
#include "llvm/Target/TargetAsmParser.h"
 | 
						|
#include "llvm/Support/SourceMgr.h"
 | 
						|
#include "llvm/Support/raw_ostream.h"
 | 
						|
#include "llvm/ADT/OwningPtr.h"
 | 
						|
#include "llvm/ADT/SmallVector.h"
 | 
						|
#include "llvm/ADT/StringSwitch.h"
 | 
						|
#include "llvm/ADT/Twine.h"
 | 
						|
using namespace llvm;
 | 
						|
 | 
						|
namespace {
 | 
						|
struct MBlazeOperand;
 | 
						|
 | 
						|
class MBlazeAsmParser : public TargetAsmParser {
 | 
						|
  MCAsmParser &Parser;
 | 
						|
  TargetMachine &TM;
 | 
						|
 | 
						|
  MCAsmParser &getParser() const { return Parser; }
 | 
						|
  MCAsmLexer &getLexer() const { return Parser.getLexer(); }
 | 
						|
 | 
						|
  void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
 | 
						|
  bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
 | 
						|
 | 
						|
  MBlazeOperand *ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
 | 
						|
  MBlazeOperand *ParseRegister(unsigned &RegNo);
 | 
						|
  MBlazeOperand *ParseImmediate();
 | 
						|
  MBlazeOperand *ParseFsl();
 | 
						|
  MBlazeOperand* ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
 | 
						|
 | 
						|
  virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
 | 
						|
 | 
						|
  bool ParseDirectiveWord(unsigned Size, SMLoc L);
 | 
						|
 | 
						|
  bool MatchAndEmitInstruction(SMLoc IDLoc,
 | 
						|
                               SmallVectorImpl<MCParsedAsmOperand*> &Operands,
 | 
						|
                               MCStreamer &Out);
 | 
						|
 | 
						|
  /// @name Auto-generated Match Functions
 | 
						|
  /// {
 | 
						|
 | 
						|
#define GET_ASSEMBLER_HEADER
 | 
						|
#include "MBlazeGenAsmMatcher.inc"
 | 
						|
 | 
						|
  /// }
 | 
						|
 | 
						|
 | 
						|
public:
 | 
						|
  MBlazeAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
 | 
						|
    : TargetAsmParser(T), Parser(_Parser), TM(_TM) {}
 | 
						|
 | 
						|
  virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
 | 
						|
                                SmallVectorImpl<MCParsedAsmOperand*> &Operands);
 | 
						|
 | 
						|
  virtual bool ParseDirective(AsmToken DirectiveID);
 | 
						|
};
 | 
						|
 | 
						|
/// MBlazeOperand - Instances of this class represent a parsed MBlaze machine
 | 
						|
/// instruction.
 | 
						|
struct MBlazeOperand : public MCParsedAsmOperand {
 | 
						|
  enum KindTy {
 | 
						|
    Token,
 | 
						|
    Immediate,
 | 
						|
    Register,
 | 
						|
    Memory,
 | 
						|
    Fsl
 | 
						|
  } Kind;
 | 
						|
 | 
						|
  SMLoc StartLoc, EndLoc;
 | 
						|
 | 
						|
  union {
 | 
						|
    struct {
 | 
						|
      const char *Data;
 | 
						|
      unsigned Length;
 | 
						|
    } Tok;
 | 
						|
 | 
						|
    struct {
 | 
						|
      unsigned RegNum;
 | 
						|
    } Reg;
 | 
						|
 | 
						|
    struct {
 | 
						|
      const MCExpr *Val;
 | 
						|
    } Imm;
 | 
						|
 | 
						|
    struct {
 | 
						|
      unsigned Base;
 | 
						|
      unsigned OffReg;
 | 
						|
      const MCExpr *Off;
 | 
						|
    } Mem;
 | 
						|
 | 
						|
    struct {
 | 
						|
      const MCExpr *Val;
 | 
						|
    } FslImm;
 | 
						|
  };
 | 
						|
 | 
						|
  MBlazeOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
 | 
						|
public:
 | 
						|
  MBlazeOperand(const MBlazeOperand &o) : MCParsedAsmOperand() {
 | 
						|
    Kind = o.Kind;
 | 
						|
    StartLoc = o.StartLoc;
 | 
						|
    EndLoc = o.EndLoc;
 | 
						|
    switch (Kind) {
 | 
						|
    case Register:
 | 
						|
      Reg = o.Reg;
 | 
						|
      break;
 | 
						|
    case Immediate:
 | 
						|
      Imm = o.Imm;
 | 
						|
      break;
 | 
						|
    case Token:
 | 
						|
      Tok = o.Tok;
 | 
						|
      break;
 | 
						|
    case Memory:
 | 
						|
      Mem = o.Mem;
 | 
						|
      break;
 | 
						|
    case Fsl:
 | 
						|
      FslImm = o.FslImm;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /// getStartLoc - Get the location of the first token of this operand.
 | 
						|
  SMLoc getStartLoc() const { return StartLoc; }
 | 
						|
 | 
						|
  /// getEndLoc - Get the location of the last token of this operand.
 | 
						|
  SMLoc getEndLoc() const { return EndLoc; }
 | 
						|
 | 
						|
  unsigned getReg() const {
 | 
						|
    assert(Kind == Register && "Invalid access!");
 | 
						|
    return Reg.RegNum;
 | 
						|
  }
 | 
						|
 | 
						|
  const MCExpr *getImm() const {
 | 
						|
    assert(Kind == Immediate && "Invalid access!");
 | 
						|
    return Imm.Val;
 | 
						|
  }
 | 
						|
 | 
						|
  const MCExpr *getFslImm() const {
 | 
						|
    assert(Kind == Fsl && "Invalid access!");
 | 
						|
    return FslImm.Val;
 | 
						|
  }
 | 
						|
 | 
						|
  unsigned getMemBase() const {
 | 
						|
    assert(Kind == Memory && "Invalid access!");
 | 
						|
    return Mem.Base;
 | 
						|
  }
 | 
						|
 | 
						|
  const MCExpr* getMemOff() const {
 | 
						|
    assert(Kind == Memory && "Invalid access!");
 | 
						|
    return Mem.Off;
 | 
						|
  }
 | 
						|
 | 
						|
  unsigned getMemOffReg() const {
 | 
						|
    assert(Kind == Memory && "Invalid access!");
 | 
						|
    return Mem.OffReg;
 | 
						|
  }
 | 
						|
 | 
						|
  bool isToken() const { return Kind == Token; }
 | 
						|
  bool isImm() const { return Kind == Immediate; }
 | 
						|
  bool isMem() const { return Kind == Memory; }
 | 
						|
  bool isFsl() const { return Kind == Fsl; }
 | 
						|
  bool isReg() const { return Kind == Register; }
 | 
						|
 | 
						|
  void addExpr(MCInst &Inst, const MCExpr *Expr) const {
 | 
						|
    // Add as immediates when possible.  Null MCExpr = 0.
 | 
						|
    if (Expr == 0)
 | 
						|
      Inst.addOperand(MCOperand::CreateImm(0));
 | 
						|
    else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
 | 
						|
      Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
 | 
						|
    else
 | 
						|
      Inst.addOperand(MCOperand::CreateExpr(Expr));
 | 
						|
  }
 | 
						|
 | 
						|
  void addRegOperands(MCInst &Inst, unsigned N) const {
 | 
						|
    assert(N == 1 && "Invalid number of operands!");
 | 
						|
    Inst.addOperand(MCOperand::CreateReg(getReg()));
 | 
						|
  }
 | 
						|
 | 
						|
  void addImmOperands(MCInst &Inst, unsigned N) const {
 | 
						|
    assert(N == 1 && "Invalid number of operands!");
 | 
						|
    addExpr(Inst, getImm());
 | 
						|
  }
 | 
						|
 | 
						|
  void addFslOperands(MCInst &Inst, unsigned N) const {
 | 
						|
    assert(N == 1 && "Invalid number of operands!");
 | 
						|
    addExpr(Inst, getFslImm());
 | 
						|
  }
 | 
						|
 | 
						|
  void addMemOperands(MCInst &Inst, unsigned N) const {
 | 
						|
    assert(N == 2 && "Invalid number of operands!");
 | 
						|
 | 
						|
    Inst.addOperand(MCOperand::CreateReg(getMemBase()));
 | 
						|
 | 
						|
    unsigned RegOff = getMemOffReg();
 | 
						|
    if (RegOff)
 | 
						|
      Inst.addOperand(MCOperand::CreateReg(RegOff));
 | 
						|
    else
 | 
						|
      addExpr(Inst, getMemOff());
 | 
						|
  }
 | 
						|
 | 
						|
  StringRef getToken() const {
 | 
						|
    assert(Kind == Token && "Invalid access!");
 | 
						|
    return StringRef(Tok.Data, Tok.Length);
 | 
						|
  }
 | 
						|
 | 
						|
  virtual void dump(raw_ostream &OS) const;
 | 
						|
 | 
						|
  static MBlazeOperand *CreateToken(StringRef Str, SMLoc S) {
 | 
						|
    MBlazeOperand *Op = new MBlazeOperand(Token);
 | 
						|
    Op->Tok.Data = Str.data();
 | 
						|
    Op->Tok.Length = Str.size();
 | 
						|
    Op->StartLoc = S;
 | 
						|
    Op->EndLoc = S;
 | 
						|
    return Op;
 | 
						|
  }
 | 
						|
 | 
						|
  static MBlazeOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
 | 
						|
    MBlazeOperand *Op = new MBlazeOperand(Register);
 | 
						|
    Op->Reg.RegNum = RegNum;
 | 
						|
    Op->StartLoc = S;
 | 
						|
    Op->EndLoc = E;
 | 
						|
    return Op;
 | 
						|
  }
 | 
						|
 | 
						|
  static MBlazeOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
 | 
						|
    MBlazeOperand *Op = new MBlazeOperand(Immediate);
 | 
						|
    Op->Imm.Val = Val;
 | 
						|
    Op->StartLoc = S;
 | 
						|
    Op->EndLoc = E;
 | 
						|
    return Op;
 | 
						|
  }
 | 
						|
 | 
						|
  static MBlazeOperand *CreateFslImm(const MCExpr *Val, SMLoc S, SMLoc E) {
 | 
						|
    MBlazeOperand *Op = new MBlazeOperand(Fsl);
 | 
						|
    Op->Imm.Val = Val;
 | 
						|
    Op->StartLoc = S;
 | 
						|
    Op->EndLoc = E;
 | 
						|
    return Op;
 | 
						|
  }
 | 
						|
 | 
						|
  static MBlazeOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S,
 | 
						|
                                  SMLoc E) {
 | 
						|
    MBlazeOperand *Op = new MBlazeOperand(Memory);
 | 
						|
    Op->Mem.Base = Base;
 | 
						|
    Op->Mem.Off = Off;
 | 
						|
    Op->Mem.OffReg = 0;
 | 
						|
    Op->StartLoc = S;
 | 
						|
    Op->EndLoc = E;
 | 
						|
    return Op;
 | 
						|
  }
 | 
						|
 | 
						|
  static MBlazeOperand *CreateMem(unsigned Base, unsigned Off, SMLoc S,
 | 
						|
                                  SMLoc E) {
 | 
						|
    MBlazeOperand *Op = new MBlazeOperand(Memory);
 | 
						|
    Op->Mem.Base = Base;
 | 
						|
    Op->Mem.OffReg = Off;
 | 
						|
    Op->Mem.Off = 0;
 | 
						|
    Op->StartLoc = S;
 | 
						|
    Op->EndLoc = E;
 | 
						|
    return Op;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
} // end anonymous namespace.
 | 
						|
 | 
						|
void MBlazeOperand::dump(raw_ostream &OS) const {
 | 
						|
  switch (Kind) {
 | 
						|
  case Immediate:
 | 
						|
    getImm()->print(OS);
 | 
						|
    break;
 | 
						|
  case Register:
 | 
						|
    OS << "<register R";
 | 
						|
    OS << MBlazeRegisterInfo::getRegisterNumbering(getReg()) << ">";
 | 
						|
    break;
 | 
						|
  case Token:
 | 
						|
    OS << "'" << getToken() << "'";
 | 
						|
    break;
 | 
						|
  case Memory: {
 | 
						|
    OS << "<memory R";
 | 
						|
    OS << MBlazeRegisterInfo::getRegisterNumbering(getMemBase());
 | 
						|
    OS << ", ";
 | 
						|
 | 
						|
    unsigned RegOff = getMemOffReg();
 | 
						|
    if (RegOff)
 | 
						|
      OS << "R" << MBlazeRegisterInfo::getRegisterNumbering(RegOff);
 | 
						|
    else
 | 
						|
      OS << getMemOff();
 | 
						|
    OS << ">";
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case Fsl:
 | 
						|
    getFslImm()->print(OS);
 | 
						|
    break;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/// @name Auto-generated Match Functions
 | 
						|
/// {
 | 
						|
 | 
						|
static unsigned MatchRegisterName(StringRef Name);
 | 
						|
 | 
						|
/// }
 | 
						|
//
 | 
						|
bool MBlazeAsmParser::
 | 
						|
MatchAndEmitInstruction(SMLoc IDLoc,
 | 
						|
                        SmallVectorImpl<MCParsedAsmOperand*> &Operands,
 | 
						|
                        MCStreamer &Out) {
 | 
						|
  MCInst Inst;
 | 
						|
  SMLoc ErrorLoc;
 | 
						|
  unsigned ErrorInfo;
 | 
						|
 | 
						|
  switch (MatchInstructionImpl(Operands, Inst, ErrorInfo)) {
 | 
						|
  case Match_Success:
 | 
						|
    Out.EmitInstruction(Inst);
 | 
						|
    return false;
 | 
						|
  case Match_MissingFeature:
 | 
						|
    return Error(IDLoc, "instruction use requires an option to be enabled");
 | 
						|
  case Match_MnemonicFail:
 | 
						|
      return Error(IDLoc, "unrecognized instruction mnemonic");
 | 
						|
  case Match_ConversionFail:
 | 
						|
    return Error(IDLoc, "unable to convert operands to instruction");
 | 
						|
  case Match_InvalidOperand:
 | 
						|
    ErrorLoc = IDLoc;
 | 
						|
    if (ErrorInfo != ~0U) {
 | 
						|
      if (ErrorInfo >= Operands.size())
 | 
						|
        return Error(IDLoc, "too few operands for instruction");
 | 
						|
 | 
						|
      ErrorLoc = ((MBlazeOperand*)Operands[ErrorInfo])->getStartLoc();
 | 
						|
      if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
 | 
						|
    }
 | 
						|
 | 
						|
    return Error(ErrorLoc, "invalid operand for instruction");
 | 
						|
  }
 | 
						|
 | 
						|
  llvm_unreachable("Implement any new match types added!");
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
MBlazeOperand *MBlazeAsmParser::
 | 
						|
ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
 | 
						|
  if (Operands.size() != 4)
 | 
						|
    return 0;
 | 
						|
 | 
						|
  MBlazeOperand &Base = *(MBlazeOperand*)Operands[2];
 | 
						|
  MBlazeOperand &Offset = *(MBlazeOperand*)Operands[3];
 | 
						|
 | 
						|
  SMLoc S = Base.getStartLoc();
 | 
						|
  SMLoc O = Offset.getStartLoc();
 | 
						|
  SMLoc E = Offset.getEndLoc();
 | 
						|
 | 
						|
  if (!Base.isReg()) {
 | 
						|
    Error(S, "base address must be a register");
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!Offset.isReg() && !Offset.isImm()) {
 | 
						|
    Error(O, "offset must be a register or immediate");
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  MBlazeOperand *Op;
 | 
						|
  if (Offset.isReg())
 | 
						|
    Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getReg(), S, E);
 | 
						|
  else
 | 
						|
    Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getImm(), S, E);
 | 
						|
 | 
						|
  delete Operands.pop_back_val();
 | 
						|
  delete Operands.pop_back_val();
 | 
						|
  Operands.push_back(Op);
 | 
						|
 | 
						|
  return Op;
 | 
						|
}
 | 
						|
 | 
						|
bool MBlazeAsmParser::ParseRegister(unsigned &RegNo,
 | 
						|
                                    SMLoc &StartLoc, SMLoc &EndLoc) {
 | 
						|
  return (ParseRegister(RegNo) == 0);
 | 
						|
}
 | 
						|
 | 
						|
MBlazeOperand *MBlazeAsmParser::ParseRegister(unsigned &RegNo) {
 | 
						|
  SMLoc S = Parser.getTok().getLoc();
 | 
						|
  SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
 | 
						|
 | 
						|
  switch (getLexer().getKind()) {
 | 
						|
  default: return 0;
 | 
						|
  case AsmToken::Identifier:
 | 
						|
    RegNo = MatchRegisterName(getLexer().getTok().getIdentifier());
 | 
						|
    if (RegNo == 0)
 | 
						|
      return 0;
 | 
						|
 | 
						|
    getLexer().Lex();
 | 
						|
    return MBlazeOperand::CreateReg(RegNo, S, E);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
static unsigned MatchFslRegister(StringRef String) {
 | 
						|
  if (!String.startswith("rfsl"))
 | 
						|
    return -1;
 | 
						|
 | 
						|
  unsigned regNum;
 | 
						|
  if (String.substr(4).getAsInteger(10,regNum))
 | 
						|
    return -1;
 | 
						|
 | 
						|
  return regNum;
 | 
						|
}
 | 
						|
 | 
						|
MBlazeOperand *MBlazeAsmParser::ParseFsl() {
 | 
						|
  SMLoc S = Parser.getTok().getLoc();
 | 
						|
  SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
 | 
						|
 | 
						|
  switch (getLexer().getKind()) {
 | 
						|
  default: return 0;
 | 
						|
  case AsmToken::Identifier:
 | 
						|
    unsigned reg = MatchFslRegister(getLexer().getTok().getIdentifier());
 | 
						|
    if (reg >= 16)
 | 
						|
      return 0;
 | 
						|
 | 
						|
    getLexer().Lex();
 | 
						|
    const MCExpr *EVal = MCConstantExpr::Create(reg,getContext());
 | 
						|
    return MBlazeOperand::CreateFslImm(EVal,S,E);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
MBlazeOperand *MBlazeAsmParser::ParseImmediate() {
 | 
						|
  SMLoc S = Parser.getTok().getLoc();
 | 
						|
  SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
 | 
						|
 | 
						|
  const MCExpr *EVal;
 | 
						|
  switch (getLexer().getKind()) {
 | 
						|
  default: return 0;
 | 
						|
  case AsmToken::LParen:
 | 
						|
  case AsmToken::Plus:
 | 
						|
  case AsmToken::Minus:
 | 
						|
  case AsmToken::Integer:
 | 
						|
  case AsmToken::Identifier:
 | 
						|
    if (getParser().ParseExpression(EVal))
 | 
						|
      return 0;
 | 
						|
 | 
						|
    return MBlazeOperand::CreateImm(EVal, S, E);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
MBlazeOperand *MBlazeAsmParser::
 | 
						|
ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
 | 
						|
  MBlazeOperand *Op;
 | 
						|
 | 
						|
  // Attempt to parse the next token as a register name
 | 
						|
  unsigned RegNo;
 | 
						|
  Op = ParseRegister(RegNo);
 | 
						|
 | 
						|
  // Attempt to parse the next token as an FSL immediate
 | 
						|
  if (!Op)
 | 
						|
    Op = ParseFsl();
 | 
						|
 | 
						|
  // Attempt to parse the next token as an immediate
 | 
						|
  if (!Op)
 | 
						|
    Op = ParseImmediate();
 | 
						|
 | 
						|
  // If the token could not be parsed then fail
 | 
						|
  if (!Op) {
 | 
						|
    Error(Parser.getTok().getLoc(), "unknown operand");
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  // Push the parsed operand into the list of operands
 | 
						|
  Operands.push_back(Op);
 | 
						|
  return Op;
 | 
						|
}
 | 
						|
 | 
						|
/// Parse an mblaze instruction mnemonic followed by its operands.
 | 
						|
bool MBlazeAsmParser::
 | 
						|
ParseInstruction(StringRef Name, SMLoc NameLoc,
 | 
						|
                 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
 | 
						|
  // The first operands is the token for the instruction name
 | 
						|
  size_t dotLoc = Name.find('.');
 | 
						|
  Operands.push_back(MBlazeOperand::CreateToken(Name.substr(0,dotLoc),NameLoc));
 | 
						|
  if (dotLoc < Name.size())
 | 
						|
    Operands.push_back(MBlazeOperand::CreateToken(Name.substr(dotLoc),NameLoc));
 | 
						|
 | 
						|
  // If there are no more operands then finish
 | 
						|
  if (getLexer().is(AsmToken::EndOfStatement))
 | 
						|
    return false;
 | 
						|
 | 
						|
  // Parse the first operand
 | 
						|
  if (!ParseOperand(Operands))
 | 
						|
    return true;
 | 
						|
 | 
						|
  while (getLexer().isNot(AsmToken::EndOfStatement) &&
 | 
						|
         getLexer().is(AsmToken::Comma)) {
 | 
						|
    // Consume the comma token
 | 
						|
    getLexer().Lex();
 | 
						|
 | 
						|
    // Parse the next operand
 | 
						|
    if (!ParseOperand(Operands))
 | 
						|
      return true;
 | 
						|
  }
 | 
						|
 | 
						|
  // If the instruction requires a memory operand then we need to
 | 
						|
  // replace the last two operands (base+offset) with a single
 | 
						|
  // memory operand.
 | 
						|
  if (Name.startswith("lw") || Name.startswith("sw") ||
 | 
						|
      Name.startswith("lh") || Name.startswith("sh") ||
 | 
						|
      Name.startswith("lb") || Name.startswith("sb"))
 | 
						|
    return (ParseMemory(Operands) == NULL);
 | 
						|
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
/// ParseDirective parses the arm specific directives
 | 
						|
bool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) {
 | 
						|
  StringRef IDVal = DirectiveID.getIdentifier();
 | 
						|
  if (IDVal == ".word")
 | 
						|
    return ParseDirectiveWord(2, DirectiveID.getLoc());
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
/// ParseDirectiveWord
 | 
						|
///  ::= .word [ expression (, expression)* ]
 | 
						|
bool MBlazeAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
 | 
						|
  if (getLexer().isNot(AsmToken::EndOfStatement)) {
 | 
						|
    for (;;) {
 | 
						|
      const MCExpr *Value;
 | 
						|
      if (getParser().ParseExpression(Value))
 | 
						|
        return true;
 | 
						|
 | 
						|
      getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
 | 
						|
 | 
						|
      if (getLexer().is(AsmToken::EndOfStatement))
 | 
						|
        break;
 | 
						|
 | 
						|
      // FIXME: Improve diagnostic.
 | 
						|
      if (getLexer().isNot(AsmToken::Comma))
 | 
						|
        return Error(L, "unexpected token in directive");
 | 
						|
      Parser.Lex();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Parser.Lex();
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
extern "C" void LLVMInitializeMBlazeAsmLexer();
 | 
						|
 | 
						|
/// Force static initialization.
 | 
						|
extern "C" void LLVMInitializeMBlazeAsmParser() {
 | 
						|
  RegisterAsmParser<MBlazeAsmParser> X(TheMBlazeTarget);
 | 
						|
  LLVMInitializeMBlazeAsmLexer();
 | 
						|
}
 | 
						|
 | 
						|
#define GET_REGISTER_MATCHER
 | 
						|
#define GET_MATCHER_IMPLEMENTATION
 | 
						|
#include "MBlazeGenAsmMatcher.inc"
 |