diff options
| author | Daniel Sanders <daniel.sanders@imgtec.com> | 2014-03-31 17:43:46 +0000 |
|---|---|---|
| committer | Daniel Sanders <daniel.sanders@imgtec.com> | 2014-03-31 17:43:46 +0000 |
| commit | 0c648ba5be7e2f770e826d5c4780347e789f9b90 (patch) | |
| tree | e4ed215a71ff437dcc098342bc4202c184001c1f /llvm/lib/Target/Mips/AsmParser | |
| parent | 7c99ec5b99f0a25838b9f27c0d3341b9e88d1531 (diff) | |
| download | bcm5719-llvm-0c648ba5be7e2f770e826d5c4780347e789f9b90.tar.gz bcm5719-llvm-0c648ba5be7e2f770e826d5c4780347e789f9b90.zip | |
[mips] Rewrite MipsAsmParser and MipsOperand.
Summary:
Highlights:
- Registers are resolved much later (by the render method).
Prior to that point, GPR32's/GPR64's are GPR's regardless of register
size. Similarly FGR32's/FGR64's/AFGR64's are FGR's regardless of register
size or FR mode. Numeric registers can be anything.
- All registers are parsed the same way everywhere (even when handling
symbol aliasing)
- One consequence is that all registers can be specified numerically
almost anywhere (e.g. $fccX, $wX). The exception is symbol aliasing
but that can be easily resolved.
- Removes the need for the hasConsumedDollar hack
- Parenthesis and Bracket suffixes are handled generically
- Micromips instructions are parsed directly instead of going through the
standard encodings first.
- rdhwr accepts all 32 registers, and the following instructions that previously
xfailed now work:
ddiv, ddivu, div, divu, cvt.l.[ds], se[bh], wsbh, floor.w.[ds], c.ngl.d,
c.sf.s, dsbh, dshd, madd.s, msub.s, nmadd.s, nmsub.s, swxc1
- Diagnostics involving registers point at the correct character (the $)
- There's only one kind of immediate in MipsOperand. LSA immediates are handled
by the predicate and renderer.
Lowlights:
- Hardcoded '$zero' in the div patterns is handled with a hack.
MipsOperand::isReg() will return true for a k_RegisterIndex token
with Index == 0 and getReg() will return ZERO for this case. Note that it
doesn't return ZERO_64 on isGP64() targets.
- I haven't cleaned up all of the now-unused functions.
Some more of the generic parser could be removed too (integers and relocs
for example).
- insve.df needed a custom decoder to handle the implicit fourth operand that
was needed to make it parse correctly. The difficulty was that the matcher
expected a Token<'0'> but gets an Imm<0>. Adding an implicit zero solved this.
Reviewers: matheusalmeida, vmedic
Reviewed By: matheusalmeida
Differential Revision: http://llvm-reviews.chandlerc.com/D3222
llvm-svn: 205229
Diffstat (limited to 'llvm/lib/Target/Mips/AsmParser')
| -rw-r--r-- | llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 1636 |
1 files changed, 704 insertions, 932 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 2b80d3f03de..95e7d09ce0c 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -23,6 +23,7 @@ #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" @@ -57,7 +58,6 @@ private: namespace { class MipsAsmParser : public MCTargetAsmParser { - MipsTargetStreamer &getTargetStreamer() { MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer(); return static_cast<MipsTargetStreamer &>(TS); @@ -66,7 +66,6 @@ class MipsAsmParser : public MCTargetAsmParser { MCSubtargetInfo &STI; MCAsmParser &Parser; MipsAssemblerOptions Options; - bool hasConsumedDollar; #define GET_ASSEMBLER_HEADER #include "MipsGenAsmMatcher.inc" @@ -76,8 +75,15 @@ class MipsAsmParser : public MCTargetAsmParser { 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); @@ -85,95 +91,36 @@ class MipsAsmParser : public MCTargetAsmParser { 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 MatchAnyRegisterNameWithoutDollar( + SmallVectorImpl<MCParsedAsmOperand *> &Operands, StringRef Identifier, + SMLoc S); MipsAsmParser::OperandMatchResultTy - parseHI32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + ParseAnyRegisterWithoutDollar(SmallVectorImpl<MCParsedAsmOperand *> &Operands, + SMLoc S); MipsAsmParser::OperandMatchResultTy - parseCOP2(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + ParseAnyRegister(SmallVectorImpl<MCParsedAsmOperand *> &Operands); MipsAsmParser::OperandMatchResultTy - parseMSA128BRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + ParseImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands); MipsAsmParser::OperandMatchResultTy - parseMSA128HRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); - - MipsAsmParser::OperandMatchResultTy - parseMSA128WRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); - - MipsAsmParser::OperandMatchResultTy - parseMSA128DRegs(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, @@ -235,8 +182,6 @@ class MipsAsmParser : public MCTargetAsmParser { bool eatComma(StringRef ErrorStr); - int matchRegisterName(StringRef Symbol, bool is64BitReg); - int matchCPURegisterName(StringRef Symbol); int matchRegisterByNumber(unsigned RegNum, unsigned RegClass); @@ -251,17 +196,12 @@ class MipsAsmParser : public MCTargetAsmParser { 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); @@ -287,8 +227,7 @@ class MipsAsmParser : public MCTargetAsmParser { 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())); @@ -301,6 +240,9 @@ public: 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); }; } @@ -309,53 +251,56 @@ namespace { /// 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 { @@ -363,30 +308,161 @@ private: }; 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) @@ -397,6 +473,85 @@ public: 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(); @@ -406,19 +561,38 @@ public: 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!"); @@ -426,26 +600,27 @@ public: } 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; } @@ -455,8 +630,9 @@ public: 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; @@ -464,43 +640,75 @@ public: 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); } - static MipsOperand *CreateLSAImm(const MCExpr *Val, SMLoc S, SMLoc E) { - MipsOperand *Op = new MipsOperand(k_LSAImm); + /// 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); + } + + /// 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; @@ -508,79 +716,33 @@ public: return Op; } - bool isGPR32Asm() const { - return Kind == k_Register && Reg.Kind == Kind_GPR32; + bool isGPRAsmReg() const { + return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31; } - void addRegAsmOperands(MCInst &Inst, unsigned N) const { - Inst.addOperand(MCOperand::CreateReg(Reg.RegNum)); + bool isFGRAsmReg() const { + // AFGR64 is $0-$15 but we handle this in getAFGR64() + return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31; } - - bool isGPR64Asm() const { - return Kind == k_Register && Reg.Kind == Kind_GPR64; + bool isHWRegsAsmReg() const { + return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31; } - - bool isHWRegsAsm() const { - assert((Kind == k_Register) && "Invalid access!"); - return Reg.Kind == Kind_HWRegs; + bool isCCRAsmReg() const { + return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31; } - - 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 isFCCAsmReg() const { + return isRegIdx() && RegIdx.Kind & RegKind_FCC && RegIdx.Index <= 7; } - - bool isFGR32Asm() const { - return (Kind == k_Register) && Reg.Kind == Kind_FGR32Regs; + bool isACCAsmReg() const { + return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3; } - - bool isFGRH32Asm() const { - return (Kind == k_Register) && Reg.Kind == Kind_FGRH32Regs; + bool isCOP2AsmReg() const { + return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31; } - - bool isFCCRegsAsm() const { - return (Kind == k_Register) && Reg.Kind == Kind_FCCRegs; + bool isMSA128AsmReg() const { + return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31; } - - bool isACC64DSPAsm() const { - return Kind == k_Register && Reg.Kind == Kind_ACC64DSP; - } - - bool isLO32DSPAsm() const { - return Kind == k_Register && Reg.Kind == Kind_LO32DSP; - } - - bool isHI32DSPAsm() const { - return Kind == k_Register && Reg.Kind == Kind_HI32DSP; - } - - bool isCOP2Asm() const { return Kind == k_Register && Reg.Kind == Kind_COP2; } - - bool isMSA128BAsm() const { - return Kind == k_Register && Reg.Kind == Kind_MSA128BRegs; - } - - bool isMSA128HAsm() const { - return Kind == k_Register && Reg.Kind == Kind_MSA128HRegs; - } - - bool isMSA128WAsm() const { - return Kind == k_Register && Reg.Kind == Kind_MSA128WRegs; - } - - bool isMSA128DAsm() const { - return Kind == k_Register && Reg.Kind == Kind_MSA128DRegs; - } - - 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. @@ -589,7 +751,29 @@ public: 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 @@ -616,6 +800,8 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, 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()) @@ -633,6 +819,14 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, 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()) @@ -996,14 +1190,13 @@ bool MipsAsmParser::MatchAndEmitInstruction( 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) + "\""); } } @@ -1064,8 +1257,6 @@ int MipsAsmParser::matchCPURegisterName(StringRef Name) { .Default(-1); } - warnIfAssemblerTemporary(CC); - return CC; } @@ -1140,59 +1331,6 @@ int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) { 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; @@ -1222,45 +1360,14 @@ int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) { 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); @@ -1272,6 +1379,8 @@ MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands, if (ResTy == MatchOperand_ParseFail) return true; + DEBUG(dbgs() << ".. Generic Parser\n"); + switch (getLexer().getKind()) { default: Error(Parser.getTok().getLoc(), "unexpected token in operand"); @@ -1279,29 +1388,15 @@ MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands, 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)) @@ -1313,47 +1408,18 @@ MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands, 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. @@ -1364,7 +1430,7 @@ MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands, 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()) @@ -1496,9 +1562,27 @@ bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) { 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); } @@ -1532,7 +1616,7 @@ bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) { MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( SmallVectorImpl<MCParsedAsmOperand *> &Operands) { - + DEBUG(dbgs() << "parseMemOperand\n"); const MCExpr *IdVal = 0; SMLoc S; bool isParenExpr = false; @@ -1555,7 +1639,7 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( 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)) { @@ -1563,8 +1647,9 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( 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"); @@ -1574,8 +1659,7 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( 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; @@ -1593,7 +1677,6 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( // 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. @@ -1606,599 +1689,220 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( 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; -} - -MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { - MipsOperand::RegisterKind RegKind = - isN64() ? MipsOperand::Kind_GPR64 : MipsOperand::Kind_GPR32; - - // 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; + return false; } 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(); - } +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; } - 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; + Index = matchFPURegisterName(Identifier); + if (Index != -1) { + Parser.Lex(); + Operands.push_back(MipsOperand::CreateFGRReg( + Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); + return MatchOperand_Success; } -} - -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; -} - -MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseGPR64(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { - - if (!isGP64()) - return MatchOperand_NoMatch; - return parseRegs(Operands, (int)MipsOperand::Kind_GPR64); + return MatchOperand_NoMatch; } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseGPR32(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { - return parseRegs(Operands, (int)MipsOperand::Kind_GPR32); -} - -MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseAFGR64Regs( - SmallVectorImpl<MCParsedAsmOperand *> &Operands) { - - if (isFP64()) - return MatchOperand_NoMatch; - return parseRegs(Operands, (int)MipsOperand::Kind_AFGR64Regs); -} +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; + } -MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { - if (!isFP64()) - return MatchOperand_NoMatch; - return parseRegs(Operands, (int)MipsOperand::Kind_FGR64Regs); -} + DEBUG(dbgs() << Parser.getTok().getKind() << "\n"); -MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { - return parseRegs(Operands, (int)MipsOperand::Kind_FGR32Regs); + return MatchOperand_NoMatch; } -MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseFGRH32Regs( +MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseAnyRegister( 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. + DEBUG(dbgs() << "ParseAnyRegister\n"); - if (Tok.isNot(AsmToken::Identifier)) - return MatchOperand_NoMatch; - - if (!Tok.getIdentifier().startswith("ac")) - return MatchOperand_NoMatch; + auto Token = Parser.getTok(); - StringRef NumString = Tok.getIdentifier().substr(2); + SMLoc S = Token.getLoc(); - 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(); - - unsigned Reg = matchRegisterByNumber(IntVal, Mips::COP2RegClassID); - - MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc()); - Op->setRegKind(MipsOperand::Kind_COP2); - Operands.push_back(Op); +MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseJumpTarget( + SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + DEBUG(dbgs() << "ParseJumpTarget\n"); - Parser.Lex(); // Eat the register number. - return MatchOperand_Success; -} + SMLoc S = getLexer().getLoc(); -MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128BRegs( - SmallVectorImpl<MCParsedAsmOperand *> &Operands) { - return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128BRegs); -} + // Integers and expressions are acceptable + OperandMatchResultTy ResTy = ParseImm(Operands); + if (ResTy != MatchOperand_NoMatch) + return ResTy; -MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128HRegs( - SmallVectorImpl<MCParsedAsmOperand *> &Operands) { - return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128HRegs); -} + // 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::parseMSA128WRegs( - SmallVectorImpl<MCParsedAsmOperand *> &Operands) { - return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128WRegs); -} + // 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::parseMSA128DRegs( - SmallVectorImpl<MCParsedAsmOperand *> &Operands) { - return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128DRegs); -} + StringRef Identifier; + if (Parser.parseIdentifier(Identifier)) + return hasConsumedDollar ? MatchOperand_ParseFail : MatchOperand_NoMatch; -MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128CtrlRegs( - SmallVectorImpl<MCParsedAsmOperand *> &Operands) { - return parseMSACtrlRegs(Operands, (int)MipsOperand::Kind_MSA128CtrlRegs); -} + if (hasConsumedDollar) + Identifier = StringRef("$" + Identifier.str()); -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 @@ -2215,12 +1919,12 @@ MipsAsmParser::parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { 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; @@ -2254,7 +1958,7 @@ MipsAsmParser::parseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { } Operands.push_back( - MipsOperand::CreateLSAImm(Expr, S, Parser.getTok().getLoc())); + MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this)); return MatchOperand_Success; } @@ -2292,16 +1996,74 @@ MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) { 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)) { @@ -2311,6 +2073,9 @@ bool MipsAsmParser::ParseInstruction( 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. @@ -2320,6 +2085,13 @@ bool MipsAsmParser::ParseInstruction( 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)) { |

