#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCTargetAsmParser.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/TargetRegistry.h"
namespace {
class MipsAsmParser : public MCTargetAsmParser {
-
MipsTargetStreamer &getTargetStreamer() {
MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer();
return static_cast<MipsTargetStreamer &>(TS);
MCSubtargetInfo &STI;
MCAsmParser &Parser;
MipsAssemblerOptions Options;
- bool hasConsumedDollar;
#define GET_ASSEMBLER_HEADER
#include "MipsGenAsmMatcher.inc"
MCStreamer &Out, unsigned &ErrorInfo,
bool MatchingInlineAsm);
+ /// Parse a register as used in CFI directives
bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
+ bool ParseParenSuffix(StringRef Name,
+ SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+
+ bool ParseBracketSuffix(StringRef Name,
+ SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+
bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand *> &Operands);
bool ParseDirective(AsmToken DirectiveID);
- MipsAsmParser::OperandMatchResultTy
- parseRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands, int RegKind);
-
- MipsAsmParser::OperandMatchResultTy
- parseMSARegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands, int RegKind);
-
- MipsAsmParser::OperandMatchResultTy
- parseMSACtrlRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
- int RegKind);
-
MipsAsmParser::OperandMatchResultTy
parseMemOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
- bool parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
- int RegKind);
-
- MipsAsmParser::OperandMatchResultTy
- parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
-
- MipsAsmParser::OperandMatchResultTy
- parseGPR32(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
-
- MipsAsmParser::OperandMatchResultTy
- parseGPR64(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
-
- MipsAsmParser::OperandMatchResultTy
- parseHWRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
-
- MipsAsmParser::OperandMatchResultTy
- parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
-
- MipsAsmParser::OperandMatchResultTy
- parseAFGR64Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
-
- MipsAsmParser::OperandMatchResultTy
- parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
-
- MipsAsmParser::OperandMatchResultTy
- parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
-
- MipsAsmParser::OperandMatchResultTy
- parseFGRH32Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
-
- MipsAsmParser::OperandMatchResultTy
- parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
-
- MipsAsmParser::OperandMatchResultTy
- parseACC64DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
-
- MipsAsmParser::OperandMatchResultTy
- parseLO32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
-
- MipsAsmParser::OperandMatchResultTy
- parseHI32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
-
- MipsAsmParser::OperandMatchResultTy
- parseCOP2(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
-
- MipsAsmParser::OperandMatchResultTy
- parseMSA128BRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+ MipsAsmParser::OperandMatchResultTy MatchAnyRegisterNameWithoutDollar(
+ SmallVectorImpl<MCParsedAsmOperand *> &Operands, StringRef Identifier,
+ SMLoc S);
MipsAsmParser::OperandMatchResultTy
- parseMSA128HRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+ ParseAnyRegisterWithoutDollar(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
+ SMLoc S);
MipsAsmParser::OperandMatchResultTy
- parseMSA128WRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+ ParseAnyRegister(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
MipsAsmParser::OperandMatchResultTy
- parseMSA128DRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+ ParseImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
MipsAsmParser::OperandMatchResultTy
- parseMSA128CtrlRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+ ParseJumpTarget(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
MipsAsmParser::OperandMatchResultTy
parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
MipsAsmParser::OperandMatchResultTy
- parseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+ ParseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
- bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
- unsigned RegKind);
+ bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &,
StringRef Mnemonic);
- int tryParseRegister(bool is64BitReg);
-
- bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
- bool is64BitReg);
-
bool needsExpansion(MCInst &Inst);
void expandInstruction(MCInst &Inst, SMLoc IDLoc,
bool eatComma(StringRef ErrorStr);
- int matchRegisterName(StringRef Symbol, bool is64BitReg);
-
int matchCPURegisterName(StringRef Symbol);
int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
int matchMSA128CtrlRegisterName(StringRef Name);
- int regKindToRegClass(int RegKind);
-
unsigned getReg(int RC, int RegNo);
unsigned getGPR(int RegNo);
int getATReg();
- // Warn if RegNo is the current assembler temporary.
- void warnIfAssemblerTemporary(int RegNo);
-
bool processInstruction(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions);
public:
MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
const MCInstrInfo &MII)
- : MCTargetAsmParser(), STI(sti), Parser(parser),
- hasConsumedDollar(false) {
+ : MCTargetAsmParser(), STI(sti), Parser(parser) {
// Initialize the set of available features.
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
MCAsmParser &getParser() const { return Parser; }
MCAsmLexer &getLexer() const { return Parser.getLexer(); }
+
+ /// Warn if RegNo is the current assembler temporary.
+ void WarnIfAssemblerTemporary(int RegNo, SMLoc Loc);
};
}
/// MipsOperand - Instances of this class represent a parsed Mips machine
/// instruction.
class MipsOperand : public MCParsedAsmOperand {
-
public:
- enum RegisterKind {
- Kind_None,
- Kind_GPR32,
- Kind_GPR64,
- Kind_HWRegs,
- Kind_FGR32Regs,
- Kind_FGRH32Regs,
- Kind_FGR64Regs,
- Kind_AFGR64Regs,
- Kind_CCRRegs,
- Kind_FCCRegs,
- Kind_ACC64DSP,
- Kind_LO32DSP,
- Kind_HI32DSP,
- Kind_COP2,
- Kind_MSA128BRegs,
- Kind_MSA128HRegs,
- Kind_MSA128WRegs,
- Kind_MSA128DRegs,
- Kind_MSA128CtrlRegs
+ /// Broad categories of register classes
+ /// The exact class is finalized by the render method.
+ enum RegKind {
+ RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64())
+ RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
+ /// isFP64())
+ RegKind_FCC = 4, /// FCC
+ RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
+ RegKind_MSACtrl = 16, /// MSA control registers
+ RegKind_COP2 = 32, /// COP2
+ RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
+ /// context).
+ RegKind_CCR = 128, /// CCR
+ RegKind_HWRegs = 256, /// HWRegs
+
+ /// Potentially any (e.g. $1)
+ RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
+ RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
+ RegKind_CCR | RegKind_HWRegs
};
private:
enum KindTy {
- k_CondCode,
- k_CoprocNum,
k_Immediate,
k_Memory,
- k_PostIndexRegister,
- k_Register,
- k_PtrReg,
- k_Token,
- k_LSAImm
+ k_PhysRegister,
+ k_RegisterIndex,
+ k_Token
} Kind;
- MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
+ MipsOperand(KindTy K, MipsAsmParser &Parser)
+ : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
+
+ /// For diagnostics, and checking the assembler temporary
+ MipsAsmParser &AsmParser;
struct Token {
const char *Data;
unsigned Length;
};
- struct RegOp {
- unsigned RegNum;
- RegisterKind Kind;
+ struct PhysRegOp {
+ unsigned Num; /// Register Number
+ };
+
+ struct RegIdxOp {
+ unsigned Index; /// Index into the register class
+ RegKind Kind; /// Bitfield of the kinds it could possibly be
+ const MCRegisterInfo *RegInfo;
};
struct ImmOp {
};
struct MemOp {
- unsigned Base;
+ MipsOperand *Base;
const MCExpr *Off;
};
union {
struct Token Tok;
- struct RegOp Reg;
+ struct PhysRegOp PhysReg;
+ struct RegIdxOp RegIdx;
struct ImmOp Imm;
struct MemOp Mem;
};
SMLoc StartLoc, EndLoc;
+ /// Internal constructor for register kinds
+ static MipsOperand *CreateReg(unsigned Index, RegKind RegKind,
+ const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
+ MipsAsmParser &Parser) {
+ MipsOperand *Op = new MipsOperand(k_RegisterIndex, Parser);
+ Op->RegIdx.Index = Index;
+ Op->RegIdx.RegInfo = RegInfo;
+ Op->RegIdx.Kind = RegKind;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
public:
- void addRegOperands(MCInst &Inst, unsigned N) const {
- assert(N == 1 && "Invalid number of operands!");
- Inst.addOperand(MCOperand::CreateReg(getReg()));
+ /// Coerce the register to GPR32 and return the real register for the current
+ /// target.
+ unsigned getGPR32Reg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
+ AsmParser.WarnIfAssemblerTemporary(RegIdx.Index, StartLoc);
+ unsigned ClassID = Mips::GPR32RegClassID;
+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
}
- void addPtrRegOperands(MCInst &Inst, unsigned N) const {
- assert(N == 1 && "Invalid number of operands!");
- Inst.addOperand(MCOperand::CreateReg(getPtrReg()));
+ /// Coerce the register to GPR64 and return the real register for the current
+ /// target.
+ unsigned getGPR64Reg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
+ unsigned ClassID = Mips::GPR64RegClassID;
+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
+ }
+
+private:
+ /// Coerce the register to AFGR64 and return the real register for the current
+ /// target.
+ unsigned getAFGR64Reg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
+ if (RegIdx.Index % 2 != 0)
+ AsmParser.Warning(StartLoc, "Float register should be even.");
+ return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
+ .getRegister(RegIdx.Index / 2);
+ }
+
+ /// Coerce the register to FGR64 and return the real register for the current
+ /// target.
+ unsigned getFGR64Reg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
+ return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
+ .getRegister(RegIdx.Index);
+ }
+
+ /// Coerce the register to FGR32 and return the real register for the current
+ /// target.
+ unsigned getFGR32Reg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
+ return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
+ .getRegister(RegIdx.Index);
+ }
+
+ /// Coerce the register to FGRH32 and return the real register for the current
+ /// target.
+ unsigned getFGRH32Reg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
+ return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
+ .getRegister(RegIdx.Index);
+ }
+
+ /// Coerce the register to FCC and return the real register for the current
+ /// target.
+ unsigned getFCCReg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
+ return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
+ .getRegister(RegIdx.Index);
+ }
+
+ /// Coerce the register to MSA128 and return the real register for the current
+ /// target.
+ unsigned getMSA128Reg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
+ // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
+ // identical
+ unsigned ClassID = Mips::MSA128BRegClassID;
+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
+ }
+
+ /// Coerce the register to MSACtrl and return the real register for the
+ /// current target.
+ unsigned getMSACtrlReg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
+ unsigned ClassID = Mips::MSACtrlRegClassID;
+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
+ }
+
+ /// Coerce the register to COP2 and return the real register for the
+ /// current target.
+ unsigned getCOP2Reg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
+ unsigned ClassID = Mips::COP2RegClassID;
+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
+ }
+
+ /// Coerce the register to ACC64DSP and return the real register for the
+ /// current target.
+ unsigned getACC64DSPReg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
+ unsigned ClassID = Mips::ACC64DSPRegClassID;
+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
+ }
+
+ /// Coerce the register to HI32DSP and return the real register for the
+ /// current target.
+ unsigned getHI32DSPReg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
+ unsigned ClassID = Mips::HI32DSPRegClassID;
+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
+ }
+
+ /// Coerce the register to LO32DSP and return the real register for the
+ /// current target.
+ unsigned getLO32DSPReg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
+ unsigned ClassID = Mips::LO32DSPRegClassID;
+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
+ }
+
+ /// Coerce the register to CCR and return the real register for the
+ /// current target.
+ unsigned getCCRReg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
+ unsigned ClassID = Mips::CCRRegClassID;
+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
+ }
+
+ /// Coerce the register to HWRegs and return the real register for the
+ /// current target.
+ unsigned getHWRegsReg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
+ unsigned ClassID = Mips::HWRegsRegClassID;
+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
}
+public:
void addExpr(MCInst &Inst, const MCExpr *Expr) const {
// Add as immediate when possible. Null MCExpr = 0.
if (Expr == 0)
Inst.addOperand(MCOperand::CreateExpr(Expr));
}
+ void addRegOperands(MCInst &Inst, unsigned N) const {
+ llvm_unreachable("Use a custom parser instead");
+ }
+
+ void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
+ }
+
+ void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
+ }
+
+ void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
+ }
+
+ void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
+ }
+
+ void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
+ }
+
+ void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
+ }
+
+ void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
+ }
+
+ void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
+ }
+
+ void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
+ }
+
+ void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
+ }
+
+ void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
+ }
+
+ void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
+ }
+
+ void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
+ }
+
+ void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
+ }
+
+ void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
+ }
+
void addImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
const MCExpr *Expr = getImm();
void addMemOperands(MCInst &Inst, unsigned N) const {
assert(N == 2 && "Invalid number of operands!");
- Inst.addOperand(MCOperand::CreateReg(getMemBase()));
+ Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
const MCExpr *Expr = getMemOff();
addExpr(Inst, Expr);
}
- bool isReg() const { return Kind == k_Register; }
+ bool isReg() const {
+ // As a special case until we sort out the definition of div/divu, pretend
+ // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
+ if (isGPRAsmReg() && RegIdx.Index == 0)
+ return true;
+
+ return Kind == k_PhysRegister;
+ }
+ bool isRegIdx() const { return Kind == k_RegisterIndex; }
bool isImm() const { return Kind == k_Immediate; }
- bool isToken() const { return Kind == k_Token; }
+ bool isConstantImm() const {
+ return isImm() && dyn_cast<MCConstantExpr>(getImm());
+ }
+ bool isToken() const {
+ // Note: It's not possible to pretend that other operand kinds are tokens.
+ // The matcher emitter checks tokens first.
+ return Kind == k_Token;
+ }
bool isMem() const { return Kind == k_Memory; }
- bool isPtrReg() const { return Kind == k_PtrReg; }
bool isInvNum() const { return Kind == k_Immediate; }
- bool isLSAImm() const { return Kind == k_LSAImm; }
+ bool isLSAImm() const {
+ if (!isConstantImm())
+ return false;
+ int64_t Val = getConstantImm();
+ return 1 <= Val && Val <= 4;
+ }
StringRef getToken() const {
assert(Kind == k_Token && "Invalid access!");
}
unsigned getReg() const {
- assert((Kind == k_Register) && "Invalid access!");
- return Reg.RegNum;
- }
-
- unsigned getPtrReg() const {
- assert((Kind == k_PtrReg) && "Invalid access!");
- return Reg.RegNum;
- }
+ // As a special case until we sort out the definition of div/divu, pretend
+ // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
+ if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
+ RegIdx.Kind & RegKind_GPR)
+ return getGPR32Reg(); // FIXME: GPR64 too
- void setRegKind(RegisterKind RegKind) {
- assert((Kind == k_Register || Kind == k_PtrReg) && "Invalid access!");
- Reg.Kind = RegKind;
+ assert(Kind == k_PhysRegister && "Invalid access!");
+ return PhysReg.Num;
}
const MCExpr *getImm() const {
- assert((Kind == k_Immediate || Kind == k_LSAImm) && "Invalid access!");
+ assert((Kind == k_Immediate) && "Invalid access!");
return Imm.Val;
}
- unsigned getMemBase() const {
+ int64_t getConstantImm() const {
+ const MCExpr *Val = getImm();
+ return static_cast<const MCConstantExpr *>(Val)->getValue();
+ }
+
+ MipsOperand *getMemBase() const {
assert((Kind == k_Memory) && "Invalid access!");
return Mem.Base;
}
return Mem.Off;
}
- static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
- MipsOperand *Op = new MipsOperand(k_Token);
+ static MipsOperand *CreateToken(StringRef Str, SMLoc S,
+ MipsAsmParser &Parser) {
+ MipsOperand *Op = new MipsOperand(k_Token, Parser);
Op->Tok.Data = Str.data();
Op->Tok.Length = Str.size();
Op->StartLoc = S;
return Op;
}
- static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
- MipsOperand *Op = new MipsOperand(k_Register);
- Op->Reg.RegNum = RegNum;
- Op->Reg.Kind = Kind_None;
- Op->StartLoc = S;
- Op->EndLoc = E;
- return Op;
+ /// Create a numeric register (e.g. $1). The exact register remains
+ /// unresolved until an instruction successfully matches
+ static MipsOperand *CreateNumericReg(unsigned Index,
+ const MCRegisterInfo *RegInfo, SMLoc S,
+ SMLoc E, MipsAsmParser &Parser) {
+ DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n");
+ return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
}
- static MipsOperand *CreatePtrReg(unsigned RegNum, SMLoc S, SMLoc E) {
- MipsOperand *Op = new MipsOperand(k_PtrReg);
- Op->Reg.RegNum = RegNum;
- Op->Reg.Kind = Kind_None;
- Op->StartLoc = S;
- Op->EndLoc = E;
- return Op;
+ /// Create a register that is definitely a GPR.
+ /// This is typically only used for named registers such as $gp.
+ static MipsOperand *CreateGPRReg(unsigned Index,
+ const MCRegisterInfo *RegInfo, SMLoc S,
+ SMLoc E, MipsAsmParser &Parser) {
+ return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
}
- static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
- MipsOperand *Op = new MipsOperand(k_Immediate);
- Op->Imm.Val = Val;
- Op->StartLoc = S;
- Op->EndLoc = E;
- return Op;
+ /// Create a register that is definitely a FGR.
+ /// This is typically only used for named registers such as $f0.
+ static MipsOperand *CreateFGRReg(unsigned Index,
+ const MCRegisterInfo *RegInfo, SMLoc S,
+ SMLoc E, MipsAsmParser &Parser) {
+ return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
+ }
+
+ /// Create a register that is definitely an FCC.
+ /// This is typically only used for named registers such as $fcc0.
+ static MipsOperand *CreateFCCReg(unsigned Index,
+ const MCRegisterInfo *RegInfo, SMLoc S,
+ SMLoc E, MipsAsmParser &Parser) {
+ return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
+ }
+
+ /// Create a register that is definitely an ACC.
+ /// This is typically only used for named registers such as $ac0.
+ static MipsOperand *CreateACCReg(unsigned Index,
+ const MCRegisterInfo *RegInfo, SMLoc S,
+ SMLoc E, MipsAsmParser &Parser) {
+ return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
}
- static MipsOperand *CreateLSAImm(const MCExpr *Val, SMLoc S, SMLoc E) {
- MipsOperand *Op = new MipsOperand(k_LSAImm);
+ /// Create a register that is definitely an MSA128.
+ /// This is typically only used for named registers such as $w0.
+ static MipsOperand *CreateMSA128Reg(unsigned Index,
+ const MCRegisterInfo *RegInfo, SMLoc S,
+ SMLoc E, MipsAsmParser &Parser) {
+ return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
+ }
+
+ /// Create a register that is definitely an MSACtrl.
+ /// This is typically only used for named registers such as $msaaccess.
+ static MipsOperand *CreateMSACtrlReg(unsigned Index,
+ const MCRegisterInfo *RegInfo, SMLoc S,
+ SMLoc E, MipsAsmParser &Parser) {
+ return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
+ }
+
+ static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E,
+ MipsAsmParser &Parser) {
+ MipsOperand *Op = new MipsOperand(k_Immediate, Parser);
Op->Imm.Val = Val;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
}
- static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S,
- SMLoc E) {
- MipsOperand *Op = new MipsOperand(k_Memory);
+ static MipsOperand *CreateMem(MipsOperand *Base, const MCExpr *Off, SMLoc S,
+ SMLoc E, MipsAsmParser &Parser) {
+ MipsOperand *Op = new MipsOperand(k_Memory, Parser);
Op->Mem.Base = Base;
Op->Mem.Off = Off;
Op->StartLoc = S;
return Op;
}
- bool isGPR32Asm() const {
- return Kind == k_Register && Reg.Kind == Kind_GPR32;
- }
- void addRegAsmOperands(MCInst &Inst, unsigned N) const {
- Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
- }
-
- bool isGPR64Asm() const {
- return Kind == k_Register && Reg.Kind == Kind_GPR64;
- }
-
- bool isHWRegsAsm() const {
- assert((Kind == k_Register) && "Invalid access!");
- return Reg.Kind == Kind_HWRegs;
- }
-
- bool isCCRAsm() const {
- assert((Kind == k_Register) && "Invalid access!");
- return Reg.Kind == Kind_CCRRegs;
- }
-
- bool isAFGR64Asm() const {
- return Kind == k_Register && Reg.Kind == Kind_AFGR64Regs;
- }
-
- bool isFGR64Asm() const {
- return Kind == k_Register && Reg.Kind == Kind_FGR64Regs;
- }
-
- bool isFGR32Asm() const {
- return (Kind == k_Register) && Reg.Kind == Kind_FGR32Regs;
- }
-
- bool isFGRH32Asm() const {
- return (Kind == k_Register) && Reg.Kind == Kind_FGRH32Regs;
- }
-
- bool isFCCRegsAsm() const {
- return (Kind == k_Register) && Reg.Kind == Kind_FCCRegs;
+ bool isGPRAsmReg() const {
+ return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
}
-
- bool isACC64DSPAsm() const {
- return Kind == k_Register && Reg.Kind == Kind_ACC64DSP;
+ bool isFGRAsmReg() const {
+ // AFGR64 is $0-$15 but we handle this in getAFGR64()
+ return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
}
-
- bool isLO32DSPAsm() const {
- return Kind == k_Register && Reg.Kind == Kind_LO32DSP;
+ bool isHWRegsAsmReg() const {
+ return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
}
-
- bool isHI32DSPAsm() const {
- return Kind == k_Register && Reg.Kind == Kind_HI32DSP;
+ bool isCCRAsmReg() const {
+ return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
}
-
- bool isCOP2Asm() const { return Kind == k_Register && Reg.Kind == Kind_COP2; }
-
- bool isMSA128BAsm() const {
- return Kind == k_Register && Reg.Kind == Kind_MSA128BRegs;
+ bool isFCCAsmReg() const {
+ return isRegIdx() && RegIdx.Kind & RegKind_FCC && RegIdx.Index <= 7;
}
-
- bool isMSA128HAsm() const {
- return Kind == k_Register && Reg.Kind == Kind_MSA128HRegs;
+ bool isACCAsmReg() const {
+ return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
}
-
- bool isMSA128WAsm() const {
- return Kind == k_Register && Reg.Kind == Kind_MSA128WRegs;
+ bool isCOP2AsmReg() const {
+ return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
}
-
- bool isMSA128DAsm() const {
- return Kind == k_Register && Reg.Kind == Kind_MSA128DRegs;
+ bool isMSA128AsmReg() const {
+ return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
}
-
- bool isMSA128CRAsm() const {
- return Kind == k_Register && Reg.Kind == Kind_MSA128CtrlRegs;
+ bool isMSACtrlAsmReg() const {
+ return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
}
/// getStartLoc - Get the location of the first token of this operand.
SMLoc getEndLoc() const { return EndLoc; }
virtual void print(raw_ostream &OS) const {
- llvm_unreachable("unimplemented!");
+ switch (Kind) {
+ case k_Immediate:
+ OS << "Imm<";
+ Imm.Val->print(OS);
+ OS << ">";
+ break;
+ case k_Memory:
+ OS << "Mem<";
+ Mem.Base->print(OS);
+ OS << ", ";
+ Mem.Off->print(OS);
+ OS << ">";
+ break;
+ case k_PhysRegister:
+ OS << "PhysReg<" << PhysReg.Num << ">";
+ break;
+ case k_RegisterIndex:
+ OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
+ break;
+ case k_Token:
+ OS << Tok.Data;
+ break;
+ }
}
}; // class MipsOperand
} // namespace
break;
case Mips::BEQ:
case Mips::BNE:
+ case Mips::BEQ_MM:
+ case Mips::BNE_MM:
assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Offset = Inst.getOperand(2);
if (!Offset.isImm())
case Mips::BLTZAL:
case Mips::BC1F:
case Mips::BC1T:
+ case Mips::BGEZ_MM:
+ case Mips::BGTZ_MM:
+ case Mips::BLEZ_MM:
+ case Mips::BLTZ_MM:
+ case Mips::BGEZAL_MM:
+ case Mips::BLTZAL_MM:
+ case Mips::BC1F_MM:
+ case Mips::BC1T_MM:
assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Offset = Inst.getOperand(1);
if (!Offset.isImm())
return true;
}
-void MipsAsmParser::warnIfAssemblerTemporary(int RegNo) {
- if ((RegNo != 0) && ((int)Options.getATRegNum() == RegNo)) {
- if (RegNo == 1)
- Warning(getLexer().getLoc(), "Used $at without \".set noat\"");
+void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
+ if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
+ if (RegIndex == 1)
+ Warning(Loc, "Used $at without \".set noat\"");
else
- Warning(getLexer().getLoc(), Twine("Used $") + Twine(RegNo) +
- " with \".set at=$" + Twine(RegNo) +
- "\"");
+ Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
+ Twine(RegIndex) + "\"");
}
}
.Default(-1);
}
- warnIfAssemblerTemporary(CC);
-
return CC;
}
return CC;
}
-int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
-
- int CC;
- CC = matchCPURegisterName(Name);
- if (CC != -1)
- return matchRegisterByNumber(CC, is64BitReg ? Mips::GPR64RegClassID
- : Mips::GPR32RegClassID);
- CC = matchFPURegisterName(Name);
- // TODO: decide about fpu register class
- if (CC != -1)
- return matchRegisterByNumber(CC, isFP64() ? Mips::FGR64RegClassID
- : Mips::FGR32RegClassID);
- return matchMSA128RegisterName(Name);
-}
-
-int MipsAsmParser::regKindToRegClass(int RegKind) {
-
- switch (RegKind) {
- case MipsOperand::Kind_GPR32:
- return Mips::GPR32RegClassID;
- case MipsOperand::Kind_GPR64:
- return Mips::GPR64RegClassID;
- case MipsOperand::Kind_HWRegs:
- return Mips::HWRegsRegClassID;
- case MipsOperand::Kind_FGR32Regs:
- return Mips::FGR32RegClassID;
- case MipsOperand::Kind_FGRH32Regs:
- return Mips::FGRH32RegClassID;
- case MipsOperand::Kind_FGR64Regs:
- return Mips::FGR64RegClassID;
- case MipsOperand::Kind_AFGR64Regs:
- return Mips::AFGR64RegClassID;
- case MipsOperand::Kind_CCRRegs:
- return Mips::CCRRegClassID;
- case MipsOperand::Kind_ACC64DSP:
- return Mips::ACC64DSPRegClassID;
- case MipsOperand::Kind_FCCRegs:
- return Mips::FCCRegClassID;
- case MipsOperand::Kind_MSA128BRegs:
- return Mips::MSA128BRegClassID;
- case MipsOperand::Kind_MSA128HRegs:
- return Mips::MSA128HRegClassID;
- case MipsOperand::Kind_MSA128WRegs:
- return Mips::MSA128WRegClassID;
- case MipsOperand::Kind_MSA128DRegs:
- return Mips::MSA128DRegClassID;
- case MipsOperand::Kind_MSA128CtrlRegs:
- return Mips::MSACtrlRegClassID;
- default:
- return -1;
- }
-}
-
bool MipsAssemblerOptions::setATReg(unsigned Reg) {
if (Reg > 31)
return false;
getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
return -1;
- if (RegClass == Mips::GPR32RegClassID || RegClass == Mips::GPR64RegClassID)
- warnIfAssemblerTemporary(RegNum);
-
return getReg(RegClass, RegNum);
}
-int MipsAsmParser::tryParseRegister(bool is64BitReg) {
- const AsmToken &Tok = Parser.getTok();
- int RegNum = -1;
-
- if (Tok.is(AsmToken::Identifier)) {
- std::string lowerCase = Tok.getString().lower();
- RegNum = matchRegisterName(lowerCase, is64BitReg);
- } else if (Tok.is(AsmToken::Integer))
- RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
- is64BitReg ? Mips::GPR64RegClassID
- : Mips::GPR32RegClassID);
- return RegNum;
-}
-
-bool MipsAsmParser::tryParseRegisterOperand(
- SmallVectorImpl<MCParsedAsmOperand *> &Operands, bool is64BitReg) {
-
- SMLoc S = Parser.getTok().getLoc();
- int RegNo = -1;
-
- RegNo = tryParseRegister(is64BitReg);
- if (RegNo == -1)
- return true;
-
- Operands.push_back(
- MipsOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
- Parser.Lex(); // Eat register token.
- return false;
-}
-
bool
MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
StringRef Mnemonic) {
+ DEBUG(dbgs() << "ParseOperand\n");
+
// Check if the current operand has a custom associated parser, if so, try to
// custom parse the operand, or fallback to the general approach.
OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
if (ResTy == MatchOperand_ParseFail)
return true;
+ DEBUG(dbgs() << ".. Generic Parser\n");
+
switch (getLexer().getKind()) {
default:
Error(Parser.getTok().getLoc(), "unexpected token in operand");
case AsmToken::Dollar: {
// Parse the register.
SMLoc S = Parser.getTok().getLoc();
- Parser.Lex(); // Eat dollar token.
- // Parse the register operand.
- if (!tryParseRegisterOperand(Operands, isGP64())) {
- if (getLexer().is(AsmToken::LParen)) {
- // Check if it is indexed addressing operand.
- Operands.push_back(MipsOperand::CreateToken("(", S));
- Parser.Lex(); // Eat the parenthesis.
- if (getLexer().isNot(AsmToken::Dollar))
- return true;
-
- Parser.Lex(); // Eat the dollar
- if (tryParseRegisterOperand(Operands, isGP64()))
- return true;
-
- if (!getLexer().is(AsmToken::RParen))
- return true;
- S = Parser.getTok().getLoc();
- Operands.push_back(MipsOperand::CreateToken(")", S));
- Parser.Lex();
- }
+ // Almost all registers have been parsed by custom parsers. There is only
+ // one exception to this. $zero (and it's alias $0) will reach this point
+ // for div, divu, and similar instructions because it is not an operand
+ // to the instruction definition but an explicit register. Special case
+ // this situation for now.
+ if (ParseAnyRegister(Operands) != MatchOperand_NoMatch)
return false;
- }
+
// Maybe it is a symbol reference.
StringRef Identifier;
if (Parser.parseIdentifier(Identifier))
const MCExpr *Res =
MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
- Operands.push_back(MipsOperand::CreateImm(Res, S, E));
+ Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
return false;
}
- case AsmToken::Identifier:
- // For instruction aliases like "bc1f $Label" dedicated parser will
- // eat the '$' sign before failing. So in order to look for appropriate
- // label we must check first if we have already consumed '$'.
- if (hasConsumedDollar) {
- hasConsumedDollar = false;
- SMLoc S = Parser.getTok().getLoc();
- StringRef Identifier;
- if (Parser.parseIdentifier(Identifier))
- return true;
- SMLoc E =
- SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
- MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
- // Create a symbol reference.
- const MCExpr *Res =
- MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
-
- Operands.push_back(MipsOperand::CreateImm(Res, S, E));
- return false;
- }
- // Look for the existing symbol, we should check if
- // we need to assign the proper RegisterKind.
- if (searchSymbolAlias(Operands, MipsOperand::Kind_None))
- return false;
// Else drop to expression parsing.
case AsmToken::LParen:
case AsmToken::Minus:
case AsmToken::Plus:
case AsmToken::Integer:
case AsmToken::String: {
- // Quoted label names.
- const MCExpr *IdVal;
- SMLoc S = Parser.getTok().getLoc();
- if (getParser().parseExpression(IdVal))
- return true;
- SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
- Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
- return false;
+ DEBUG(dbgs() << ".. generic integer\n");
+ OperandMatchResultTy ResTy = ParseImm(Operands);
+ return ResTy != MatchOperand_Success;
}
case AsmToken::Percent: {
// It is a symbol reference or constant expression.
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
- Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
+ Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
return false;
} // case AsmToken::Percent
} // switch(getLexer().getKind())
bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
SMLoc &EndLoc) {
- StartLoc = Parser.getTok().getLoc();
- RegNo = tryParseRegister(isGP64());
- EndLoc = Parser.getTok().getLoc();
+ SmallVector<MCParsedAsmOperand *, 1> Operands;
+ OperandMatchResultTy ResTy = ParseAnyRegister(Operands);
+ if (ResTy == MatchOperand_Success) {
+ assert(Operands.size() == 1);
+ MipsOperand &Operand = *static_cast<MipsOperand *>(Operands.front());
+ StartLoc = Operand.getStartLoc();
+ EndLoc = Operand.getEndLoc();
+
+ // AFAIK, we only support numeric registers and named GPR's in CFI
+ // directives.
+ // Don't worry about eating tokens before failing. Using an unrecognised
+ // register is a parse error.
+ if (Operand.isGPRAsmReg()) {
+ // Resolve to GPR32 or GPR64 appropriately.
+ RegNo = isGP64() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
+ }
+
+ return (RegNo == (unsigned)-1);
+ }
+
+ assert(Operands.size() == 0);
return (RegNo == (unsigned)-1);
}
MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
-
+ DEBUG(dbgs() << "parseMemOperand\n");
const MCExpr *IdVal = 0;
SMLoc S;
bool isParenExpr = false;
if (Mnemonic->getToken() == "la") {
SMLoc E =
SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
- Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
+ Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
return MatchOperand_Success;
}
if (Tok.is(AsmToken::EndOfStatement)) {
SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
// Zero register assumed, add a memory operand with ZERO as its base.
- Operands.push_back(MipsOperand::CreateMem(
- isGP64() ? Mips::ZERO_64 : Mips::ZERO, IdVal, S, E));
+ MipsOperand *Base = MipsOperand::CreateGPRReg(
+ 0, getContext().getRegisterInfo(), S, E, *this);
+ Operands.push_back(MipsOperand::CreateMem(Base, IdVal, S, E, *this));
return MatchOperand_Success;
}
Error(Parser.getTok().getLoc(), "'(' expected");
Parser.Lex(); // Eat the '(' token.
}
- Res = parseRegs(Operands, isGP64() ? (int)MipsOperand::Kind_GPR64
- : (int)MipsOperand::Kind_GPR32);
+ Res = ParseAnyRegister(Operands);
if (Res != MatchOperand_Success)
return Res;
// Replace the register operand with the memory operand.
MipsOperand *op = static_cast<MipsOperand *>(Operands.back());
- int RegNo = op->getReg();
// Remove the register from the operands.
Operands.pop_back();
// Add the memory operand.
getContext());
}
- Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
- delete op;
+ Operands.push_back(MipsOperand::CreateMem(op, IdVal, S, E, *this));
return MatchOperand_Success;
}
-bool MipsAsmParser::parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
- int RegKind) {
- // If the first token is not '$' we have an error.
- if (Parser.getTok().isNot(AsmToken::Dollar))
- return false;
-
- SMLoc S = Parser.getTok().getLoc();
- Parser.Lex();
- AsmToken::TokenKind TkKind = getLexer().getKind();
- int Reg;
+bool MipsAsmParser::searchSymbolAlias(
+ SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- if (TkKind == AsmToken::Integer) {
- Reg = matchRegisterByNumber(Parser.getTok().getIntVal(),
- regKindToRegClass(RegKind));
- if (Reg == -1)
- return false;
- } else if (TkKind == AsmToken::Identifier) {
- if ((Reg = matchCPURegisterName(Parser.getTok().getString().lower())) == -1)
+ MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
+ if (Sym) {
+ SMLoc S = Parser.getTok().getLoc();
+ const MCExpr *Expr;
+ if (Sym->isVariable())
+ Expr = Sym->getVariableValue();
+ else
return false;
- Reg = getReg(regKindToRegClass(RegKind), Reg);
- } else {
- return false;
+ if (Expr->getKind() == MCExpr::SymbolRef) {
+ const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
+ const StringRef DefSymbol = Ref->getSymbol().getName();
+ if (DefSymbol.startswith("$")) {
+ OperandMatchResultTy ResTy =
+ MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
+ if (ResTy == MatchOperand_Success)
+ return true;
+ else if (ResTy == MatchOperand_ParseFail)
+ llvm_unreachable("Should never ParseFail");
+ return false;
+ }
+ } else if (Expr->getKind() == MCExpr::Constant) {
+ Parser.Lex();
+ const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
+ MipsOperand *op =
+ MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this);
+ Operands.push_back(op);
+ return true;
+ }
}
-
- MipsOperand *Op = MipsOperand::CreatePtrReg(Reg, S, Parser.getTok().getLoc());
- Op->setRegKind((MipsOperand::RegisterKind)RegKind);
- Operands.push_back(Op);
- Parser.Lex();
- return true;
+ return false;
}
MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- MipsOperand::RegisterKind RegKind =
- isN64() ? MipsOperand::Kind_GPR64 : MipsOperand::Kind_GPR32;
+MipsAsmParser::MatchAnyRegisterNameWithoutDollar(
+ SmallVectorImpl<MCParsedAsmOperand *> &Operands, StringRef Identifier,
+ SMLoc S) {
+ int Index = matchCPURegisterName(Identifier);
+ if (Index != -1) {
+ Parser.Lex();
+ Operands.push_back(MipsOperand::CreateGPRReg(
+ Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
+ return MatchOperand_Success;
+ }
- // Parse index register.
- if (!parsePtrReg(Operands, RegKind))
- return MatchOperand_NoMatch;
-
- // Parse '('.
- if (Parser.getTok().isNot(AsmToken::LParen))
- return MatchOperand_NoMatch;
-
- Operands.push_back(MipsOperand::CreateToken("(", getLexer().getLoc()));
- Parser.Lex();
-
- // Parse base register.
- if (!parsePtrReg(Operands, RegKind))
- return MatchOperand_NoMatch;
-
- // Parse ')'.
- if (Parser.getTok().isNot(AsmToken::RParen))
- return MatchOperand_NoMatch;
-
- Operands.push_back(MipsOperand::CreateToken(")", getLexer().getLoc()));
- Parser.Lex();
-
- return MatchOperand_Success;
-}
-
-MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
- int RegKind) {
- MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
- if (getLexer().getKind() == AsmToken::Identifier && !hasConsumedDollar) {
- if (searchSymbolAlias(Operands, Kind))
- return MatchOperand_Success;
- return MatchOperand_NoMatch;
- }
- SMLoc S = Parser.getTok().getLoc();
- // If the first token is not '$', we have an error.
- if (Parser.getTok().isNot(AsmToken::Dollar) && !hasConsumedDollar)
- return MatchOperand_NoMatch;
- if (!hasConsumedDollar) {
- Parser.Lex(); // Eat the '$'
- hasConsumedDollar = true;
- }
- if (getLexer().getKind() == AsmToken::Identifier) {
- int RegNum = -1;
- std::string RegName = Parser.getTok().getString().lower();
- // Match register by name
- switch (RegKind) {
- case MipsOperand::Kind_GPR32:
- case MipsOperand::Kind_GPR64:
- RegNum = matchCPURegisterName(RegName);
- break;
- case MipsOperand::Kind_AFGR64Regs:
- case MipsOperand::Kind_FGR64Regs:
- case MipsOperand::Kind_FGR32Regs:
- case MipsOperand::Kind_FGRH32Regs:
- RegNum = matchFPURegisterName(RegName);
- if (RegKind == MipsOperand::Kind_AFGR64Regs)
- RegNum /= 2;
- else if (RegKind == MipsOperand::Kind_FGRH32Regs && !isFP64())
- if (RegNum != -1 && RegNum % 2 != 0)
- Warning(S, "Float register should be even.");
- break;
- case MipsOperand::Kind_FCCRegs:
- RegNum = matchFCCRegisterName(RegName);
- break;
- case MipsOperand::Kind_ACC64DSP:
- RegNum = matchACRegisterName(RegName);
- break;
- default:
- break; // No match, value is set to -1.
- }
- // No match found, return _NoMatch to give a chance to other round.
- if (RegNum < 0)
- return MatchOperand_NoMatch;
-
- int RegVal = getReg(regKindToRegClass(Kind), RegNum);
- if (RegVal == -1)
- return MatchOperand_NoMatch;
-
- MipsOperand *Op =
- MipsOperand::CreateReg(RegVal, S, Parser.getTok().getLoc());
- Op->setRegKind(Kind);
- Operands.push_back(Op);
- hasConsumedDollar = false;
- Parser.Lex(); // Eat the register name.
- return MatchOperand_Success;
- } else if (getLexer().getKind() == AsmToken::Integer) {
- unsigned RegNum = Parser.getTok().getIntVal();
- if (Kind == MipsOperand::Kind_HWRegs) {
- if (RegNum != 29)
- return MatchOperand_NoMatch;
- // Only hwreg 29 is supported, found at index 0.
- RegNum = 0;
- }
- int Reg = matchRegisterByNumber(RegNum, regKindToRegClass(Kind));
- if (Reg == -1)
- return MatchOperand_NoMatch;
- MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
- Op->setRegKind(Kind);
- Operands.push_back(Op);
- hasConsumedDollar = false;
- Parser.Lex(); // Eat the register number.
- if ((RegKind == MipsOperand::Kind_GPR32) &&
- (getLexer().is(AsmToken::LParen))) {
- // Check if it is indexed addressing operand.
- Operands.push_back(MipsOperand::CreateToken("(", getLexer().getLoc()));
- Parser.Lex(); // Eat the parenthesis.
- if (parseRegs(Operands, RegKind) != MatchOperand_Success)
- return MatchOperand_NoMatch;
- if (getLexer().isNot(AsmToken::RParen))
- return MatchOperand_NoMatch;
- Operands.push_back(MipsOperand::CreateToken(")", getLexer().getLoc()));
- Parser.Lex();
- }
+ Index = matchFPURegisterName(Identifier);
+ if (Index != -1) {
+ Parser.Lex();
+ Operands.push_back(MipsOperand::CreateFGRReg(
+ Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
return MatchOperand_Success;
}
- return MatchOperand_NoMatch;
-}
-bool MipsAsmParser::validateMSAIndex(int Val, int RegKind) {
- MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
-
- if (Val < 0)
- return false;
-
- switch (Kind) {
- default:
- return false;
- case MipsOperand::Kind_MSA128BRegs:
- return Val < 16;
- case MipsOperand::Kind_MSA128HRegs:
- return Val < 8;
- case MipsOperand::Kind_MSA128WRegs:
- return Val < 4;
- case MipsOperand::Kind_MSA128DRegs:
- return Val < 2;
- }
-}
-
-MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseMSARegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
- int RegKind) {
- MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
- SMLoc S = Parser.getTok().getLoc();
- std::string RegName;
-
- if (Parser.getTok().isNot(AsmToken::Dollar))
- return MatchOperand_NoMatch;
-
- switch (RegKind) {
- default:
- return MatchOperand_ParseFail;
- case MipsOperand::Kind_MSA128BRegs:
- case MipsOperand::Kind_MSA128HRegs:
- case MipsOperand::Kind_MSA128WRegs:
- case MipsOperand::Kind_MSA128DRegs:
- break;
+ Index = matchFCCRegisterName(Identifier);
+ if (Index != -1) {
+ Parser.Lex();
+ Operands.push_back(MipsOperand::CreateFCCReg(
+ Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
+ return MatchOperand_Success;
}
- Parser.Lex(); // Eat the '$'.
- if (getLexer().getKind() == AsmToken::Identifier)
- RegName = Parser.getTok().getString().lower();
- else
- return MatchOperand_ParseFail;
-
- int RegNum = matchMSA128RegisterName(RegName);
-
- if (RegNum < 0 || RegNum > 31)
- return MatchOperand_ParseFail;
-
- int RegVal = getReg(regKindToRegClass(Kind), RegNum);
- if (RegVal == -1)
- return MatchOperand_ParseFail;
-
- MipsOperand *Op = MipsOperand::CreateReg(RegVal, S, Parser.getTok().getLoc());
- Op->setRegKind(Kind);
- Operands.push_back(Op);
-
- Parser.Lex(); // Eat the register identifier.
-
- // MSA registers may be suffixed with an index in the form of:
- // 1) Immediate expression.
- // 2) General Purpose Register.
- // Examples:
- // 1) copy_s.b $29,$w0[0]
- // 2) sld.b $w0,$w1[$1]
-
- if (Parser.getTok().isNot(AsmToken::LBrac))
+ Index = matchACRegisterName(Identifier);
+ if (Index != -1) {
+ Parser.Lex();
+ Operands.push_back(MipsOperand::CreateACCReg(
+ Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
return MatchOperand_Success;
+ }
- MipsOperand *Mnemonic = static_cast<MipsOperand *>(Operands[0]);
-
- Operands.push_back(MipsOperand::CreateToken("[", Parser.getTok().getLoc()));
- Parser.Lex(); // Parse the '[' token.
-
- if (Parser.getTok().is(AsmToken::Dollar)) {
- // This must be a GPR.
- MipsOperand *RegOp;
- SMLoc VIdx = Parser.getTok().getLoc();
- Parser.Lex(); // Parse the '$' token.
-
- // GPR have aliases and we must account for that. Example: $30 == $fp
- if (getLexer().getKind() == AsmToken::Integer) {
- unsigned RegNum = Parser.getTok().getIntVal();
- int Reg = matchRegisterByNumber(
- RegNum, regKindToRegClass(MipsOperand::Kind_GPR32));
- if (Reg == -1) {
- Error(VIdx, "invalid general purpose register");
- return MatchOperand_ParseFail;
- }
-
- RegOp = MipsOperand::CreateReg(Reg, VIdx, Parser.getTok().getLoc());
- } else if (getLexer().getKind() == AsmToken::Identifier) {
- int RegNum = -1;
- std::string RegName = Parser.getTok().getString().lower();
-
- RegNum = matchCPURegisterName(RegName);
- if (RegNum == -1) {
- Error(VIdx, "general purpose register expected");
- return MatchOperand_ParseFail;
- }
- RegNum = getReg(regKindToRegClass(MipsOperand::Kind_GPR32), RegNum);
- RegOp = MipsOperand::CreateReg(RegNum, VIdx, Parser.getTok().getLoc());
- } else
- return MatchOperand_ParseFail;
-
- RegOp->setRegKind(MipsOperand::Kind_GPR32);
- Operands.push_back(RegOp);
- Parser.Lex(); // Eat the register identifier.
-
- if (Parser.getTok().isNot(AsmToken::RBrac))
- return MatchOperand_ParseFail;
-
- Operands.push_back(MipsOperand::CreateToken("]", Parser.getTok().getLoc()));
- Parser.Lex(); // Parse the ']' token.
-
+ Index = matchMSA128RegisterName(Identifier);
+ if (Index != -1) {
+ Parser.Lex();
+ Operands.push_back(MipsOperand::CreateMSA128Reg(
+ Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
return MatchOperand_Success;
}
- // The index must be a constant expression then.
- SMLoc VIdx = Parser.getTok().getLoc();
- const MCExpr *ImmVal;
-
- if (getParser().parseExpression(ImmVal))
- return MatchOperand_ParseFail;
-
- const MCConstantExpr *expr = dyn_cast<MCConstantExpr>(ImmVal);
- if (!expr || !validateMSAIndex((int)expr->getValue(), Kind)) {
- Error(VIdx, "invalid immediate value");
- return MatchOperand_ParseFail;
+ Index = matchMSA128CtrlRegisterName(Identifier);
+ if (Index != -1) {
+ Parser.Lex();
+ Operands.push_back(MipsOperand::CreateMSACtrlReg(
+ Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
+ return MatchOperand_Success;
}
- SMLoc E = Parser.getTok().getEndLoc();
-
- if (Parser.getTok().isNot(AsmToken::RBrac))
- return MatchOperand_ParseFail;
-
- bool insve =
- Mnemonic->getToken() == "insve.b" || Mnemonic->getToken() == "insve.h" ||
- Mnemonic->getToken() == "insve.w" || Mnemonic->getToken() == "insve.d";
-
- // The second vector index of insve instructions is always 0.
- if (insve && Operands.size() > 6) {
- if (expr->getValue() != 0) {
- Error(VIdx, "immediate value must be 0");
- return MatchOperand_ParseFail;
- }
- Operands.push_back(MipsOperand::CreateToken("0", VIdx));
- } else
- Operands.push_back(MipsOperand::CreateImm(expr, VIdx, E));
-
- Operands.push_back(MipsOperand::CreateToken("]", Parser.getTok().getLoc()));
-
- Parser.Lex(); // Parse the ']' token.
-
- return MatchOperand_Success;
-}
-
-MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseMSACtrlRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
- int RegKind) {
- MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
-
- if (Kind != MipsOperand::Kind_MSA128CtrlRegs)
- return MatchOperand_NoMatch;
-
- if (Parser.getTok().isNot(AsmToken::Dollar))
- return MatchOperand_ParseFail;
-
- SMLoc S = Parser.getTok().getLoc();
-
- Parser.Lex(); // Eat the '$' symbol.
-
- int RegNum = -1;
- if (getLexer().getKind() == AsmToken::Identifier)
- RegNum = matchMSA128CtrlRegisterName(Parser.getTok().getString().lower());
- else if (getLexer().getKind() == AsmToken::Integer)
- RegNum = Parser.getTok().getIntVal();
- else
- return MatchOperand_ParseFail;
-
- if (RegNum < 0 || RegNum > 7)
- return MatchOperand_ParseFail;
-
- int RegVal = getReg(regKindToRegClass(Kind), RegNum);
- if (RegVal == -1)
- return MatchOperand_ParseFail;
-
- MipsOperand *RegOp =
- MipsOperand::CreateReg(RegVal, S, Parser.getTok().getLoc());
- RegOp->setRegKind(MipsOperand::Kind_MSA128CtrlRegs);
- Operands.push_back(RegOp);
- Parser.Lex(); // Eat the register identifier.
-
- return MatchOperand_Success;
+ return MatchOperand_NoMatch;
}
MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseGPR64(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+MipsAsmParser::ParseAnyRegisterWithoutDollar(
+ SmallVectorImpl<MCParsedAsmOperand *> &Operands, SMLoc S) {
+ auto Token = Parser.getTok();
+
+ if (Token.is(AsmToken::Identifier)) {
+ DEBUG(dbgs() << ".. identifier\n");
+ StringRef Identifier = Token.getIdentifier();
+ return MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
+ } else if (Token.is(AsmToken::Integer)) {
+ DEBUG(dbgs() << ".. integer\n");
+ Operands.push_back(MipsOperand::CreateNumericReg(
+ Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
+ *this));
+ Parser.Lex();
+ return MatchOperand_Success;
+ }
- if (!isGP64())
- return MatchOperand_NoMatch;
- return parseRegs(Operands, (int)MipsOperand::Kind_GPR64);
-}
+ DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
-MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseGPR32(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseRegs(Operands, (int)MipsOperand::Kind_GPR32);
+ return MatchOperand_NoMatch;
}
-MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseAFGR64Regs(
+MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseAnyRegister(
SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+ DEBUG(dbgs() << "ParseAnyRegister\n");
- if (isFP64())
- return MatchOperand_NoMatch;
- return parseRegs(Operands, (int)MipsOperand::Kind_AFGR64Regs);
-}
+ auto Token = Parser.getTok();
-MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- if (!isFP64())
- return MatchOperand_NoMatch;
- return parseRegs(Operands, (int)MipsOperand::Kind_FGR64Regs);
-}
+ SMLoc S = Token.getLoc();
-MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseRegs(Operands, (int)MipsOperand::Kind_FGR32Regs);
-}
-
-MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseFGRH32Regs(
- SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseRegs(Operands, (int)MipsOperand::Kind_FGRH32Regs);
-}
-
-MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseRegs(Operands, (int)MipsOperand::Kind_FCCRegs);
-}
-
-MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseACC64DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseRegs(Operands, (int)MipsOperand::Kind_ACC64DSP);
-}
-
-MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseLO32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- // If the first token is not '$' we have an error.
- if (Parser.getTok().isNot(AsmToken::Dollar))
- return MatchOperand_NoMatch;
-
- SMLoc S = Parser.getTok().getLoc();
- Parser.Lex(); // Eat the '$'
-
- const AsmToken &Tok = Parser.getTok(); // Get next token.
-
- if (Tok.isNot(AsmToken::Identifier))
- return MatchOperand_NoMatch;
-
- if (!Tok.getIdentifier().startswith("ac"))
- return MatchOperand_NoMatch;
-
- StringRef NumString = Tok.getIdentifier().substr(2);
-
- unsigned IntVal;
- if (NumString.getAsInteger(10, IntVal))
+ if (Token.isNot(AsmToken::Dollar)) {
+ DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
+ if (Token.is(AsmToken::Identifier)) {
+ if (searchSymbolAlias(Operands))
+ return MatchOperand_Success;
+ }
+ DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
return MatchOperand_NoMatch;
+ }
+ DEBUG(dbgs() << ".. $\n");
+ Parser.Lex();
+ Token = Parser.getTok();
- unsigned Reg = matchRegisterByNumber(IntVal, Mips::LO32DSPRegClassID);
-
- MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
- Op->setRegKind(MipsOperand::Kind_LO32DSP);
- Operands.push_back(Op);
-
- Parser.Lex(); // Eat the register number.
- return MatchOperand_Success;
+ OperandMatchResultTy ResTy = ParseAnyRegisterWithoutDollar(Operands, S);
+ if (ResTy == MatchOperand_NoMatch)
+ return MatchOperand_ParseFail; // We ate the $ so NoMatch isn't valid
+ return ResTy;
}
MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseHI32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- // If the first token is not '$' we have an error.
- if (Parser.getTok().isNot(AsmToken::Dollar))
+MipsAsmParser::ParseImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+ switch (getLexer().getKind()) {
+ default:
return MatchOperand_NoMatch;
+ case AsmToken::LParen:
+ case AsmToken::Minus:
+ case AsmToken::Plus:
+ case AsmToken::Integer:
+ case AsmToken::String:
+ break;
+ }
+ const MCExpr *IdVal;
SMLoc S = Parser.getTok().getLoc();
- Parser.Lex(); // Eat the '$'
-
- const AsmToken &Tok = Parser.getTok(); // Get next token.
-
- if (Tok.isNot(AsmToken::Identifier))
- return MatchOperand_NoMatch;
-
- if (!Tok.getIdentifier().startswith("ac"))
- return MatchOperand_NoMatch;
-
- StringRef NumString = Tok.getIdentifier().substr(2);
-
- unsigned IntVal;
- if (NumString.getAsInteger(10, IntVal))
- return MatchOperand_NoMatch;
-
- unsigned Reg = matchRegisterByNumber(IntVal, Mips::HI32DSPRegClassID);
-
- MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
- Op->setRegKind(MipsOperand::Kind_HI32DSP);
- Operands.push_back(Op);
+ if (getParser().parseExpression(IdVal))
+ return MatchOperand_ParseFail;
- Parser.Lex(); // Eat the register number.
+ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+ Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
return MatchOperand_Success;
}
-MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseCOP2(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- // If the first token is not '$' we have an error.
- if (Parser.getTok().isNot(AsmToken::Dollar))
- return MatchOperand_NoMatch;
-
- SMLoc S = Parser.getTok().getLoc();
- Parser.Lex(); // Eat the '$'
-
- const AsmToken &Tok = Parser.getTok(); // Get next token.
-
- if (Tok.isNot(AsmToken::Integer))
- return MatchOperand_NoMatch;
-
- unsigned IntVal = Tok.getIntVal();
+MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseJumpTarget(
+ SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+ DEBUG(dbgs() << "ParseJumpTarget\n");
- unsigned Reg = matchRegisterByNumber(IntVal, Mips::COP2RegClassID);
+ SMLoc S = getLexer().getLoc();
- MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
- Op->setRegKind(MipsOperand::Kind_COP2);
- Operands.push_back(Op);
+ // Integers and expressions are acceptable
+ OperandMatchResultTy ResTy = ParseImm(Operands);
+ if (ResTy != MatchOperand_NoMatch)
+ return ResTy;
- Parser.Lex(); // Eat the register number.
- return MatchOperand_Success;
-}
-
-MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128BRegs(
- SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128BRegs);
-}
+ // Consume the $ if there is one. We'll add it to the symbol below.
+ bool hasConsumedDollar = false;
+ if (getLexer().is(AsmToken::Dollar)) {
+ Parser.Lex();
+ hasConsumedDollar = true;
-MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128HRegs(
- SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128HRegs);
-}
+ // We have an unfortunate conflict between '$sym' and '$reg' so give
+ // registers a chance before we try symbols.
+ // The conflict is between 'bc1t $offset', and 'bc1t $fcc, $offset'.
+ OperandMatchResultTy ResTy = ParseAnyRegisterWithoutDollar(Operands, S);
+ if (ResTy != MatchOperand_NoMatch)
+ return ResTy;
+ }
-MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128WRegs(
- SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128WRegs);
-}
+ StringRef Identifier;
+ if (Parser.parseIdentifier(Identifier))
+ return hasConsumedDollar ? MatchOperand_ParseFail : MatchOperand_NoMatch;
-MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128DRegs(
- SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128DRegs);
-}
+ if (hasConsumedDollar)
+ Identifier = StringRef("$" + Identifier.str());
-MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128CtrlRegs(
- SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseMSACtrlRegs(Operands, (int)MipsOperand::Kind_MSA128CtrlRegs);
-}
-
-bool MipsAsmParser::searchSymbolAlias(
- SmallVectorImpl<MCParsedAsmOperand *> &Operands, unsigned RegKind) {
+ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+ MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier);
- MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
- if (Sym) {
- SMLoc S = Parser.getTok().getLoc();
- const MCExpr *Expr;
- if (Sym->isVariable())
- Expr = Sym->getVariableValue();
- else
- return false;
- if (Expr->getKind() == MCExpr::SymbolRef) {
- MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
- const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
- const StringRef DefSymbol = Ref->getSymbol().getName();
- if (DefSymbol.startswith("$")) {
- int RegNum = -1;
- APInt IntVal(32, -1);
- if (!DefSymbol.substr(1).getAsInteger(10, IntVal))
- RegNum = matchRegisterByNumber(IntVal.getZExtValue(),
- isGP64() ? Mips::GPR64RegClassID
- : Mips::GPR32RegClassID);
- else {
- // Lookup for the register with the corresponding name.
- switch (Kind) {
- case MipsOperand::Kind_AFGR64Regs:
- case MipsOperand::Kind_FGR64Regs:
- RegNum = matchFPURegisterName(DefSymbol.substr(1));
- break;
- case MipsOperand::Kind_FGR32Regs:
- RegNum = matchFPURegisterName(DefSymbol.substr(1));
- break;
- case MipsOperand::Kind_GPR64:
- case MipsOperand::Kind_GPR32:
- default:
- RegNum = matchCPURegisterName(DefSymbol.substr(1));
- break;
- }
- if (RegNum > -1)
- RegNum = getReg(regKindToRegClass(Kind), RegNum);
- }
- if (RegNum > -1) {
- Parser.Lex();
- MipsOperand *op =
- MipsOperand::CreateReg(RegNum, S, Parser.getTok().getLoc());
- op->setRegKind(Kind);
- Operands.push_back(op);
- return true;
- }
- }
- } else if (Expr->getKind() == MCExpr::Constant) {
- Parser.Lex();
- const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
- MipsOperand *op =
- MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc());
- Operands.push_back(op);
- return true;
- }
- }
- return false;
-}
+ // Create a symbol reference.
+ const MCExpr *Res =
+ MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
-MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseRegs(Operands, (int)MipsOperand::Kind_HWRegs);
-}
+ Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
+ return MatchOperand_Success;
+ // // Look for the existing symbol, we should check if
+ // // we need to assign the proper RegisterKind.
+ // if (searchSymbolAlias(Operands))
+ // return false;
-MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseRegs(Operands, (int)MipsOperand::Kind_CCRRegs);
+ return MatchOperand_NoMatch;
}
MipsAsmParser::OperandMatchResultTy
int64_t Val = MCE->getValue();
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Operands.push_back(MipsOperand::CreateImm(
- MCConstantExpr::Create(0 - Val, getContext()), S, E));
+ MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
return MatchOperand_Success;
}
MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+MipsAsmParser::ParseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
switch (getLexer().getKind()) {
default:
return MatchOperand_NoMatch;
}
Operands.push_back(
- MipsOperand::CreateLSAImm(Expr, S, Parser.getTok().getLoc()));
+ MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
return MatchOperand_Success;
}
return VK;
}
+/// Sometimes (i.e. load/stores) the operand may be followed immediately by
+/// either this.
+/// ::= '(', register, ')'
+/// handle it before we iterate so we don't get tripped up by the lack of
+/// a comma.
+bool MipsAsmParser::ParseParenSuffix(
+ StringRef Name, SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+ if (getLexer().is(AsmToken::LParen)) {
+ Operands.push_back(
+ MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
+ Parser.Lex();
+ if (ParseOperand(Operands, Name)) {
+ SMLoc Loc = getLexer().getLoc();
+ Parser.eatToEndOfStatement();
+ return Error(Loc, "unexpected token in argument list");
+ }
+ if (Parser.getTok().isNot(AsmToken::RParen)) {
+ SMLoc Loc = getLexer().getLoc();
+ Parser.eatToEndOfStatement();
+ return Error(Loc, "unexpected token, expected ')'");
+ }
+ Operands.push_back(
+ MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
+ Parser.Lex();
+ }
+ return false;
+}
+
+/// Sometimes (i.e. in MSA) the operand may be followed immediately by
+/// either one of these.
+/// ::= '[', register, ']'
+/// ::= '[', integer, ']'
+/// handle it before we iterate so we don't get tripped up by the lack of
+/// a comma.
+bool MipsAsmParser::ParseBracketSuffix(
+ StringRef Name, SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+ if (getLexer().is(AsmToken::LBrac)) {
+ Operands.push_back(
+ MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
+ Parser.Lex();
+ if (ParseOperand(Operands, Name)) {
+ SMLoc Loc = getLexer().getLoc();
+ Parser.eatToEndOfStatement();
+ return Error(Loc, "unexpected token in argument list");
+ }
+ if (Parser.getTok().isNot(AsmToken::RBrac)) {
+ SMLoc Loc = getLexer().getLoc();
+ Parser.eatToEndOfStatement();
+ return Error(Loc, "unexpected token, expected ']'");
+ }
+ Operands.push_back(
+ MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
+ Parser.Lex();
+ }
+ return false;
+}
+
bool MipsAsmParser::ParseInstruction(
ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+ DEBUG(dbgs() << "ParseInstruction\n");
// Check if we have valid mnemonic
if (!mnemonicIsValid(Name, 0)) {
Parser.eatToEndOfStatement();
return Error(NameLoc, "Unknown instruction");
}
// First operand in MCInst is instruction mnemonic.
- Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
+ Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
// Read the remaining operands.
if (getLexer().isNot(AsmToken::EndOfStatement)) {
Parser.eatToEndOfStatement();
return Error(Loc, "unexpected token in argument list");
}
+ if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
+ return true;
+ // AFAIK, parenthesis suffixes are never on the first operand
while (getLexer().is(AsmToken::Comma)) {
Parser.Lex(); // Eat the comma.
Parser.eatToEndOfStatement();
return Error(Loc, "unexpected token in argument list");
}
+ // Parse bracket and parenthesis suffixes before we iterate
+ if (getLexer().is(AsmToken::LBrac)) {
+ if (ParseBracketSuffix(Name, Operands))
+ return true;
+ } else if (getLexer().is(AsmToken::LParen) &&
+ ParseParenSuffix(Name, Operands))
+ return true;
}
}
if (getLexer().isNot(AsmToken::EndOfStatement)) {