diff options
Diffstat (limited to 'contrib/llvm/patches/patch-r262261-llvm-r198484-sparc.diff')
-rw-r--r-- | contrib/llvm/patches/patch-r262261-llvm-r198484-sparc.diff | 844 |
1 files changed, 844 insertions, 0 deletions
diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198484-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198484-sparc.diff new file mode 100644 index 0000000..3bfb7d5 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198484-sparc.diff @@ -0,0 +1,844 @@ +Pull in r198484 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Add the initial implementation of an asm parser for sparc/sparcv9. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +@@ -123,13 +123,18 @@ extern "C" void LLVMInitializeSparcTargetMC() { + + // Register the MC instruction info. + TargetRegistry::RegisterMCInstrInfo(TheSparcTarget, createSparcMCInstrInfo); ++ TargetRegistry::RegisterMCInstrInfo(TheSparcV9Target, createSparcMCInstrInfo); + + // Register the MC register info. + TargetRegistry::RegisterMCRegInfo(TheSparcTarget, createSparcMCRegisterInfo); ++ TargetRegistry::RegisterMCRegInfo(TheSparcV9Target, ++ createSparcMCRegisterInfo); + + // Register the MC subtarget info. + TargetRegistry::RegisterMCSubtargetInfo(TheSparcTarget, + createSparcMCSubtargetInfo); ++ TargetRegistry::RegisterMCSubtargetInfo(TheSparcV9Target, ++ createSparcMCSubtargetInfo); + + TargetRegistry::RegisterAsmStreamer(TheSparcTarget, + createMCAsmStreamer); +Index: lib/Target/Sparc/LLVMBuild.txt +=================================================================== +--- lib/Target/Sparc/LLVMBuild.txt ++++ lib/Target/Sparc/LLVMBuild.txt +@@ -16,7 +16,7 @@ + ;===------------------------------------------------------------------------===; + + [common] +-subdirectories = InstPrinter MCTargetDesc TargetInfo ++subdirectories = AsmParser InstPrinter MCTargetDesc TargetInfo + + [component_0] + type = TargetGroup +Index: lib/Target/Sparc/SparcInstrInfo.td +=================================================================== +--- lib/Target/Sparc/SparcInstrInfo.td ++++ lib/Target/Sparc/SparcInstrInfo.td +@@ -76,13 +76,25 @@ def ADDRrr : ComplexPattern<iPTR, 2, "SelectADDRrr + def ADDRri : ComplexPattern<iPTR, 2, "SelectADDRri", [frameindex], []>; + + // Address operands ++def SparcMEMrrAsmOperand : AsmOperandClass { ++ let Name = "MEMrr"; ++ let ParserMethod = "parseMEMrrOperand"; ++} ++ ++def SparcMEMriAsmOperand : AsmOperandClass { ++ let Name = "MEMri"; ++ let ParserMethod = "parseMEMriOperand"; ++} ++ + def MEMrr : Operand<iPTR> { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops ptr_rc, ptr_rc); ++ let ParserMatchClass = SparcMEMrrAsmOperand; + } + def MEMri : Operand<iPTR> { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops ptr_rc, i32imm); ++ let ParserMatchClass = SparcMEMriAsmOperand; + } + + def TLSSym : Operand<iPTR>; +@@ -239,7 +251,10 @@ multiclass F3_12np<string OpcStr, bits<6> Op3Val> + + // Pseudo instructions. + class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern> +- : InstSP<outs, ins, asmstr, pattern>; ++ : InstSP<outs, ins, asmstr, pattern> { ++ let isCodeGenOnly = 1; ++ let isPseudo = 1; ++} + + // GETPCX for PIC + let Defs = [O7] in { +@@ -503,7 +518,7 @@ defm SRA : F3_12<"sra", 0b100111, sra, IntRegs, i3 + defm ADD : F3_12<"add", 0b000000, add, IntRegs, i32, i32imm>; + + // "LEA" forms of add (patterns to make tblgen happy) +-let Predicates = [Is32Bit] in ++let Predicates = [Is32Bit], isCodeGenOnly = 1 in + def LEA_ADDri : F3_2<2, 0b000000, + (outs IntRegs:$dst), (ins MEMri:$addr), + "add ${addr:arith}, $dst", +Index: lib/Target/Sparc/CMakeLists.txt +=================================================================== +--- lib/Target/Sparc/CMakeLists.txt ++++ lib/Target/Sparc/CMakeLists.txt +@@ -4,6 +4,7 @@ tablegen(LLVM SparcGenRegisterInfo.inc -gen-regist + tablegen(LLVM SparcGenInstrInfo.inc -gen-instr-info) + tablegen(LLVM SparcGenCodeEmitter.inc -gen-emitter) + tablegen(LLVM SparcGenAsmWriter.inc -gen-asm-writer) ++tablegen(LLVM SparcGenAsmMatcher.inc -gen-asm-matcher) + tablegen(LLVM SparcGenDAGISel.inc -gen-dag-isel) + tablegen(LLVM SparcGenSubtargetInfo.inc -gen-subtarget) + tablegen(LLVM SparcGenCallingConv.inc -gen-callingconv) +@@ -31,3 +32,4 @@ add_dependencies(LLVMSparcCodeGen SparcCommonTable + add_subdirectory(TargetInfo) + add_subdirectory(MCTargetDesc) + add_subdirectory(InstPrinter) ++add_subdirectory(AsmParser) +Index: lib/Target/Sparc/Makefile +=================================================================== +--- lib/Target/Sparc/Makefile ++++ lib/Target/Sparc/Makefile +@@ -13,11 +13,12 @@ TARGET = Sparc + + # Make sure that tblgen is run, first thing. + BUILT_SOURCES = SparcGenRegisterInfo.inc SparcGenInstrInfo.inc \ +- SparcGenAsmWriter.inc SparcGenDAGISel.inc \ ++ SparcGenAsmWriter.inc SparcGenAsmMatcher.inc \ ++ SparcGenDAGISel.inc \ + SparcGenSubtargetInfo.inc SparcGenCallingConv.inc \ + SparcGenCodeEmitter.inc + +-DIRS = InstPrinter TargetInfo MCTargetDesc ++DIRS = InstPrinter AsmParser TargetInfo MCTargetDesc + + include $(LEVEL)/Makefile.common + +Index: lib/Target/Sparc/Sparc.td +=================================================================== +--- lib/Target/Sparc/Sparc.td ++++ lib/Target/Sparc/Sparc.td +@@ -44,6 +44,10 @@ include "SparcInstrInfo.td" + + def SparcInstrInfo : InstrInfo; + ++def SparcAsmParser : AsmParser { ++ bit ShouldEmitMatchRegisterName = 0; ++} ++ + //===----------------------------------------------------------------------===// + // SPARC processors supported. + //===----------------------------------------------------------------------===// +@@ -77,6 +81,7 @@ def SparcAsmWriter : AsmWriter { + def Sparc : Target { + // Pull in Instruction Info: + let InstructionSet = SparcInstrInfo; ++ let AssemblyParsers = [SparcAsmParser]; + + let AssemblyWriters = [SparcAsmWriter]; + } +Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +=================================================================== +--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp ++++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +@@ -0,0 +1,614 @@ ++//===-- SparcAsmParser.cpp - Parse Sparc assembly to MCInst instructions --===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++ ++#include "MCTargetDesc/SparcMCTargetDesc.h" ++#include "llvm/ADT/STLExtras.h" ++#include "llvm/MC/MCContext.h" ++#include "llvm/MC/MCInst.h" ++#include "llvm/MC/MCParser/MCParsedAsmOperand.h" ++#include "llvm/MC/MCStreamer.h" ++#include "llvm/MC/MCSubtargetInfo.h" ++#include "llvm/MC/MCTargetAsmParser.h" ++#include "llvm/Support/TargetRegistry.h" ++ ++using namespace llvm; ++ ++// The generated AsmMatcher SparcGenAsmMatcher uses "Sparc" as the target ++// namespace. But SPARC backend uses "SP" as its namespace. ++namespace llvm { ++ namespace Sparc { ++ using namespace SP; ++ } ++} ++ ++namespace { ++class SparcAsmParser : public MCTargetAsmParser { ++ ++ MCSubtargetInfo &STI; ++ MCAsmParser &Parser; ++ ++ /// @name Auto-generated Match Functions ++ /// { ++ ++#define GET_ASSEMBLER_HEADER ++#include "SparcGenAsmMatcher.inc" ++ ++ /// } ++ ++ // public interface of the MCTargetAsmParser. ++ bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, ++ SmallVectorImpl<MCParsedAsmOperand*> &Operands, ++ MCStreamer &Out, unsigned &ErrorInfo, ++ bool MatchingInlineAsm); ++ bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); ++ bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, ++ SMLoc NameLoc, ++ SmallVectorImpl<MCParsedAsmOperand*> &Operands); ++ bool ParseDirective(AsmToken DirectiveID); ++ ++ ++ // Custom parse functions for Sparc specific operands. ++ OperandMatchResultTy ++ parseMEMrrOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands); ++ OperandMatchResultTy ++ parseMEMriOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands); ++ ++ OperandMatchResultTy ++ parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands, ++ int ImmOffsetOrReg); ++ ++ OperandMatchResultTy ++ parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands, ++ StringRef Name); ++ ++ // returns true if Tok is matched to a register and returns register in RegNo. ++ bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo, bool isDFP, ++ bool isQFP); ++ ++public: ++ SparcAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser, ++ const MCInstrInfo &MII) ++ : MCTargetAsmParser(), STI(sti), Parser(parser) { ++ // Initialize the set of available features. ++ setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); ++ } ++ ++}; ++ ++ static unsigned IntRegs[32] = { ++ Sparc::G0, Sparc::G1, Sparc::G2, Sparc::G3, ++ Sparc::G4, Sparc::G5, Sparc::G6, Sparc::G7, ++ Sparc::O0, Sparc::O1, Sparc::O2, Sparc::O3, ++ Sparc::O4, Sparc::O5, Sparc::O6, Sparc::O7, ++ Sparc::L0, Sparc::L1, Sparc::L2, Sparc::L3, ++ Sparc::L4, Sparc::L5, Sparc::L6, Sparc::L7, ++ Sparc::I0, Sparc::I1, Sparc::I2, Sparc::I3, ++ Sparc::I4, Sparc::I5, Sparc::I6, Sparc::I7 }; ++ ++ static unsigned FloatRegs[32] = { ++ Sparc::F0, Sparc::F1, Sparc::F2, Sparc::F3, ++ Sparc::F4, Sparc::F5, Sparc::F6, Sparc::F7, ++ Sparc::F8, Sparc::F9, Sparc::F10, Sparc::F11, ++ Sparc::F12, Sparc::F13, Sparc::F14, Sparc::F15, ++ Sparc::F16, Sparc::F17, Sparc::F18, Sparc::F19, ++ Sparc::F20, Sparc::F21, Sparc::F22, Sparc::F23, ++ Sparc::F24, Sparc::F25, Sparc::F26, Sparc::F27, ++ Sparc::F28, Sparc::F29, Sparc::F30, Sparc::F31 }; ++ ++ static unsigned DoubleRegs[32] = { ++ Sparc::D0, Sparc::D1, Sparc::D2, Sparc::D3, ++ Sparc::D4, Sparc::D5, Sparc::D6, Sparc::D7, ++ Sparc::D8, Sparc::D7, Sparc::D8, Sparc::D9, ++ Sparc::D12, Sparc::D13, Sparc::D14, Sparc::D15, ++ Sparc::D16, Sparc::D17, Sparc::D18, Sparc::D19, ++ Sparc::D20, Sparc::D21, Sparc::D22, Sparc::D23, ++ Sparc::D24, Sparc::D25, Sparc::D26, Sparc::D27, ++ Sparc::D28, Sparc::D29, Sparc::D30, Sparc::D31 }; ++ ++ static unsigned QuadFPRegs[32] = { ++ Sparc::Q0, Sparc::Q1, Sparc::Q2, Sparc::Q3, ++ Sparc::Q4, Sparc::Q5, Sparc::Q6, Sparc::Q7, ++ Sparc::Q8, Sparc::Q7, Sparc::Q8, Sparc::Q9, ++ Sparc::Q12, Sparc::Q13, Sparc::Q14, Sparc::Q15 }; ++ ++ ++/// SparcOperand - Instances of this class represent a parsed Sparc machine ++/// instruction. ++class SparcOperand : public MCParsedAsmOperand { ++public: ++ enum RegisterKind { ++ rk_None, ++ rk_IntReg, ++ rk_FloatReg, ++ rk_DoubleReg, ++ rk_QuadReg, ++ rk_CCReg, ++ rk_Y ++ }; ++private: ++ enum KindTy { ++ k_Token, ++ k_Register, ++ k_Immediate, ++ k_MemoryReg, ++ k_MemoryImm ++ } Kind; ++ ++ SMLoc StartLoc, EndLoc; ++ ++ SparcOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} ++ ++ struct Token { ++ const char *Data; ++ unsigned Length; ++ }; ++ ++ struct RegOp { ++ unsigned RegNum; ++ RegisterKind Kind; ++ }; ++ ++ struct ImmOp { ++ const MCExpr *Val; ++ }; ++ ++ struct MemOp { ++ unsigned Base; ++ unsigned OffsetReg; ++ const MCExpr *Off; ++ }; ++ ++ union { ++ struct Token Tok; ++ struct RegOp Reg; ++ struct ImmOp Imm; ++ struct MemOp Mem; ++ }; ++public: ++ bool isToken() const { return Kind == k_Token; } ++ bool isReg() const { return Kind == k_Register; } ++ bool isImm() const { return Kind == k_Immediate; } ++ bool isMem() const { return isMEMrr() || isMEMri(); } ++ bool isMEMrr() const { return Kind == k_MemoryReg; } ++ bool isMEMri() const { return Kind == k_MemoryImm; } ++ ++ StringRef getToken() const { ++ assert(Kind == k_Token && "Invalid access!"); ++ return StringRef(Tok.Data, Tok.Length); ++ } ++ ++ unsigned getReg() const { ++ assert((Kind == k_Register) && "Invalid access!"); ++ return Reg.RegNum; ++ } ++ ++ const MCExpr *getImm() const { ++ assert((Kind == k_Immediate) && "Invalid access!"); ++ return Imm.Val; ++ } ++ ++ unsigned getMemBase() const { ++ assert((Kind == k_MemoryReg || Kind == k_MemoryImm) && "Invalid access!"); ++ return Mem.Base; ++ } ++ ++ unsigned getMemOffsetReg() const { ++ assert((Kind == k_MemoryReg) && "Invalid access!"); ++ return Mem.OffsetReg; ++ } ++ ++ const MCExpr *getMemOff() const { ++ assert((Kind == k_MemoryImm) && "Invalid access!"); ++ return Mem.Off; ++ } ++ ++ /// getStartLoc - Get the location of the first token of this operand. ++ SMLoc getStartLoc() const { ++ return StartLoc; ++ } ++ /// getEndLoc - Get the location of the last token of this operand. ++ SMLoc getEndLoc() const { ++ return EndLoc; ++ } ++ ++ virtual void print(raw_ostream &OS) const { ++ switch (Kind) { ++ case k_Token: OS << "Token: " << getToken() << "\n"; break; ++ case k_Register: OS << "Reg: #" << getReg() << "\n"; break; ++ case k_Immediate: OS << "Imm: " << getImm() << "\n"; break; ++ case k_MemoryReg: OS << "Mem: " << getMemBase() << "+" ++ << getMemOffsetReg() << "\n"; break; ++ case k_MemoryImm: assert(getMemOff() != 0); ++ OS << "Mem: " << getMemBase() ++ << "+" << *getMemOff() ++ << "\n"; break; ++ } ++ } ++ ++ void addRegOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ Inst.addOperand(MCOperand::CreateReg(getReg())); ++ } ++ ++ void addImmOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ const MCExpr *Expr = getImm(); ++ addExpr(Inst, Expr); ++ } ++ ++ void addExpr(MCInst &Inst, const MCExpr *Expr) const{ ++ // Add as immediate when possible. Null MCExpr = 0. ++ if (Expr == 0) ++ Inst.addOperand(MCOperand::CreateImm(0)); ++ else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) ++ Inst.addOperand(MCOperand::CreateImm(CE->getValue())); ++ else ++ Inst.addOperand(MCOperand::CreateExpr(Expr)); ++ } ++ ++ void addMEMrrOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 2 && "Invalid number of operands!"); ++ ++ Inst.addOperand(MCOperand::CreateReg(getMemBase())); ++ ++ assert(getMemOffsetReg() != 0 && "Invalid offset"); ++ Inst.addOperand(MCOperand::CreateReg(getMemOffsetReg())); ++ } ++ ++ void addMEMriOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 2 && "Invalid number of operands!"); ++ ++ Inst.addOperand(MCOperand::CreateReg(getMemBase())); ++ ++ const MCExpr *Expr = getMemOff(); ++ addExpr(Inst, Expr); ++ } ++ ++ static SparcOperand *CreateToken(StringRef Str, SMLoc S) { ++ SparcOperand *Op = new SparcOperand(k_Token); ++ Op->Tok.Data = Str.data(); ++ Op->Tok.Length = Str.size(); ++ Op->StartLoc = S; ++ Op->EndLoc = S; ++ return Op; ++ } ++ ++ static SparcOperand *CreateReg(unsigned RegNum, ++ SparcOperand::RegisterKind Kind, ++ SMLoc S, SMLoc E) { ++ SparcOperand *Op = new SparcOperand(k_Register); ++ Op->Reg.RegNum = RegNum; ++ Op->Reg.Kind = Kind; ++ Op->StartLoc = S; ++ Op->EndLoc = E; ++ return Op; ++ } ++ ++ static SparcOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) { ++ SparcOperand *Op = new SparcOperand(k_Immediate); ++ Op->Imm.Val = Val; ++ Op->StartLoc = S; ++ Op->EndLoc = E; ++ return Op; ++ } ++ ++ ++}; ++ ++} // end namespace ++ ++bool SparcAsmParser:: ++MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, ++ SmallVectorImpl<MCParsedAsmOperand*> &Operands, ++ MCStreamer &Out, unsigned &ErrorInfo, ++ bool MatchingInlineAsm) { ++ MCInst Inst; ++ SmallVector<MCInst, 8> Instructions; ++ unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, ++ MatchingInlineAsm); ++ switch (MatchResult) { ++ default: ++ break; ++ ++ case Match_Success: { ++ Inst.setLoc(IDLoc); ++ Out.EmitInstruction(Inst); ++ return false; ++ } ++ ++ case Match_MissingFeature: ++ return Error(IDLoc, ++ "instruction requires a CPU feature not currently enabled"); ++ ++ case Match_InvalidOperand: { ++ SMLoc ErrorLoc = IDLoc; ++ if (ErrorInfo != ~0U) { ++ if (ErrorInfo >= Operands.size()) ++ return Error(IDLoc, "too few operands for instruction"); ++ ++ ErrorLoc = ((SparcOperand*) Operands[ErrorInfo])->getStartLoc(); ++ if (ErrorLoc == SMLoc()) ++ ErrorLoc = IDLoc; ++ } ++ ++ return Error(ErrorLoc, "invalid operand for instruction"); ++ } ++ case Match_MnemonicFail: ++ return Error(IDLoc, "invalid instruction"); ++ } ++ return true; ++} ++ ++bool SparcAsmParser:: ++ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) ++{ ++ const AsmToken &Tok = Parser.getTok(); ++ StartLoc = Tok.getLoc(); ++ EndLoc = Tok.getEndLoc(); ++ RegNo = 0; ++ if (getLexer().getKind() != AsmToken::Percent) ++ return false; ++ Parser.Lex(); ++ if (matchRegisterName(Tok, RegNo, false, false)) { ++ Parser.Lex(); ++ return false; ++ } ++ ++ return Error(StartLoc, "invalid register name"); ++} ++ ++bool SparcAsmParser:: ++ParseInstruction(ParseInstructionInfo &Info, StringRef Name, ++ SMLoc NameLoc, ++ SmallVectorImpl<MCParsedAsmOperand*> &Operands) ++{ ++ // 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(SparcOperand::CreateToken(Name, NameLoc)); ++ ++ if (getLexer().isNot(AsmToken::EndOfStatement)) { ++ // Read the first operand. ++ if (parseOperand(Operands, Name) != MatchOperand_Success) { ++ SMLoc Loc = getLexer().getLoc(); ++ Parser.eatToEndOfStatement(); ++ return Error(Loc, "unexpected token"); ++ } ++ ++ while (getLexer().is(AsmToken::Comma)) { ++ Parser.Lex(); // Eat the comma. ++ // Parse and remember the operand. ++ if (parseOperand(Operands, Name) != MatchOperand_Success) { ++ SMLoc Loc = getLexer().getLoc(); ++ Parser.eatToEndOfStatement(); ++ return Error(Loc, "unexpected token"); ++ } ++ } ++ } ++ if (getLexer().isNot(AsmToken::EndOfStatement)) { ++ SMLoc Loc = getLexer().getLoc(); ++ Parser.eatToEndOfStatement(); ++ return Error(Loc, "unexpected token"); ++ } ++ Parser.Lex(); // Consume the EndOfStatement. ++ return false; ++} ++ ++bool SparcAsmParser:: ++ParseDirective(AsmToken DirectiveID) ++{ ++ // Ignore all directives for now. ++ Parser.eatToEndOfStatement(); ++ return false; ++} ++ ++SparcAsmParser::OperandMatchResultTy SparcAsmParser:: ++parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands, ++ int ImmOffsetOrReg) ++{ ++ // FIXME: Implement memory operand parsing here. ++ return MatchOperand_NoMatch; ++} ++ ++SparcAsmParser::OperandMatchResultTy SparcAsmParser:: ++parseMEMrrOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) ++{ ++ return parseMEMOperand(Operands, 2); ++} ++ ++SparcAsmParser::OperandMatchResultTy SparcAsmParser:: ++parseMEMriOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) ++{ ++ return parseMEMOperand(Operands, 1); ++} ++ ++SparcAsmParser::OperandMatchResultTy SparcAsmParser:: ++parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands, ++ StringRef Mnemonic) ++{ ++ OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); ++ if (ResTy == MatchOperand_Success) ++ return ResTy; ++ // If there wasn't a custom match, try the generic matcher below. Otherwise, ++ // there was a match, but an error occurred, in which case, just return that ++ // the operand parsing failed. ++ if (ResTy == MatchOperand_ParseFail) ++ return ResTy; ++ ++ SMLoc S = Parser.getTok().getLoc(); ++ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); ++ const MCExpr *EVal; ++ SparcOperand *Op; ++ switch (getLexer().getKind()) { ++ case AsmToken::Percent: ++ Parser.Lex(); // Eat the '%'. ++ unsigned RegNo; ++ if (matchRegisterName(Parser.getTok(), RegNo, false, false)) { ++ Parser.Lex(); // Eat the identifier token. ++ Op = SparcOperand::CreateReg(RegNo, SparcOperand::rk_None, S, E); ++ break; ++ } ++ // FIXME: Handle modifiers like %hi, %lo etc., ++ return MatchOperand_ParseFail; ++ ++ case AsmToken::Minus: ++ case AsmToken::Integer: ++ if (getParser().parseExpression(EVal)) ++ return MatchOperand_ParseFail; ++ ++ Op = SparcOperand::CreateImm(EVal, S, E); ++ break; ++ ++ case AsmToken::Identifier: { ++ StringRef Identifier; ++ if (getParser().parseIdentifier(Identifier)) ++ return MatchOperand_ParseFail; ++ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); ++ MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier); ++ ++ // Otherwise create a symbol reference. ++ const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, ++ getContext()); ++ ++ Op = SparcOperand::CreateImm(Res, S, E); ++ break; ++ } ++ ++ case AsmToken::LBrac: // handle [ ++ return parseMEMOperand(Operands, 0); ++ ++ default: ++ return MatchOperand_ParseFail; ++ } ++ // Push the parsed operand into the list of operands ++ Operands.push_back(Op); ++ return MatchOperand_Success; ++} ++ ++bool SparcAsmParser::matchRegisterName(const AsmToken &Tok, ++ unsigned &RegNo, ++ bool isDFP, ++ bool isQFP) ++{ ++ int64_t intVal = 0; ++ RegNo = 0; ++ if (Tok.is(AsmToken::Identifier)) { ++ StringRef name = Tok.getString(); ++ ++ // %fp ++ if (name.equals("fp")) { ++ RegNo = Sparc::I6; ++ return true; ++ } ++ // %sp ++ if (name.equals("sp")) { ++ RegNo = Sparc::O6; ++ return true; ++ } ++ ++ if (name.equals("y")) { ++ RegNo = Sparc::Y; ++ return true; ++ } ++ ++ if (name.equals("icc")) { ++ RegNo = Sparc::ICC; ++ return true; ++ } ++ ++ if (name.equals("xcc")) { ++ // FIXME:: check 64bit. ++ RegNo = Sparc::ICC; ++ return true; ++ } ++ ++ // %fcc0 - %fcc3 ++ if (name.substr(0, 3).equals_lower("fcc") ++ && !name.substr(3).getAsInteger(10, intVal) ++ && intVal < 4) { ++ // FIXME: check 64bit and handle %fcc1 - %fcc3 ++ RegNo = Sparc::FCC; ++ return true; ++ } ++ ++ // %g0 - %g7 ++ if (name.substr(0, 1).equals_lower("g") ++ && !name.substr(1).getAsInteger(10, intVal) ++ && intVal < 8) { ++ RegNo = IntRegs[intVal]; ++ return true; ++ } ++ // %o0 - %o7 ++ if (name.substr(0, 1).equals_lower("o") ++ && !name.substr(1).getAsInteger(10, intVal) ++ && intVal < 8) { ++ RegNo = IntRegs[8 + intVal]; ++ return true; ++ } ++ if (name.substr(0, 1).equals_lower("l") ++ && !name.substr(1).getAsInteger(10, intVal) ++ && intVal < 8) { ++ RegNo = IntRegs[16 + intVal]; ++ return true; ++ } ++ if (name.substr(0, 1).equals_lower("i") ++ && !name.substr(1).getAsInteger(10, intVal) ++ && intVal < 8) { ++ RegNo = IntRegs[24 + intVal]; ++ return true; ++ } ++ // %f0 - %f31 ++ if (name.substr(0, 1).equals_lower("f") ++ && !name.substr(1, 2).getAsInteger(10, intVal) && intVal < 32) { ++ if (isDFP && (intVal%2 == 0)) { ++ RegNo = DoubleRegs[intVal/2]; ++ } else if (isQFP && (intVal%4 == 0)) { ++ RegNo = QuadFPRegs[intVal/4]; ++ } else { ++ RegNo = FloatRegs[intVal]; ++ } ++ return true; ++ } ++ // %f32 - %f62 ++ if (name.substr(0, 1).equals_lower("f") ++ && !name.substr(1, 2).getAsInteger(10, intVal) ++ && intVal >= 32 && intVal <= 62 && (intVal % 2 == 0)) { ++ if (isDFP) { ++ RegNo = DoubleRegs[16 + intVal/2]; ++ } else if (isQFP && (intVal % 4 == 0)) { ++ RegNo = QuadFPRegs[8 + intVal/4]; ++ } else { ++ return false; ++ } ++ return true; ++ } ++ ++ // %r0 - %r31 ++ if (name.substr(0, 1).equals_lower("r") ++ && !name.substr(1, 2).getAsInteger(10, intVal) && intVal < 31) { ++ RegNo = IntRegs[intVal]; ++ return true; ++ } ++ } ++ return false; ++} ++ ++ ++ ++extern "C" void LLVMInitializeSparcAsmParser() { ++ RegisterMCAsmParser<SparcAsmParser> A(TheSparcTarget); ++ RegisterMCAsmParser<SparcAsmParser> B(TheSparcV9Target); ++} ++ ++#define GET_REGISTER_MATCHER ++#define GET_MATCHER_IMPLEMENTATION ++#include "SparcGenAsmMatcher.inc" +Index: lib/Target/Sparc/AsmParser/LLVMBuild.txt +=================================================================== +--- lib/Target/Sparc/AsmParser/LLVMBuild.txt ++++ lib/Target/Sparc/AsmParser/LLVMBuild.txt +@@ -0,0 +1,23 @@ ++;===- ./lib/Target/Sparc/AsmParser/LLVMBuild.txt ---------------*- Conf -*--===; ++; ++; The LLVM Compiler Infrastructure ++; ++; This file is distributed under the University of Illinois Open Source ++; License. See LICENSE.TXT for details. ++; ++;===------------------------------------------------------------------------===; ++; ++; This is an LLVMBuild description file for the components in this subdirectory. ++; ++; For more information on the LLVMBuild system, please see: ++; ++; http://llvm.org/docs/LLVMBuild.html ++; ++;===------------------------------------------------------------------------===; ++ ++[component_0] ++type = Library ++name = SparcAsmParser ++parent = Sparc ++required_libraries = MC MCParser Support SparcDesc SparcInfo ++add_to_library_groups = Sparc +Index: lib/Target/Sparc/AsmParser/CMakeLists.txt +=================================================================== +--- lib/Target/Sparc/AsmParser/CMakeLists.txt ++++ lib/Target/Sparc/AsmParser/CMakeLists.txt +@@ -0,0 +1,3 @@ ++add_llvm_library(LLVMSparcAsmParser ++ SparcAsmParser.cpp ++ ) +Index: lib/Target/Sparc/AsmParser/Makefile +=================================================================== +--- lib/Target/Sparc/AsmParser/Makefile ++++ lib/Target/Sparc/AsmParser/Makefile +@@ -0,0 +1,15 @@ ++##===- lib/Target/Sparc/AsmParser/Makefile ------------------*- Makefile-*-===## ++# ++# The LLVM Compiler Infrastructure ++# ++# This file is distributed under the University of Illinois Open Source ++# License. See LICENSE.TXT for details. ++# ++##===----------------------------------------------------------------------===## ++LEVEL = ../../../.. ++LIBRARYNAME = LLVMSparcAsmParser ++ ++# Hack: we need to include 'main' Sparc target directory to grab private headers ++CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. ++ ++include $(LEVEL)/Makefile.common +Index: lib/Target/Sparc/SparcInstr64Bit.td +=================================================================== +--- lib/Target/Sparc/SparcInstr64Bit.td ++++ lib/Target/Sparc/SparcInstr64Bit.td +@@ -176,11 +176,11 @@ def : Pat<(SPcmpicc i64:$a, (i64 simm13:$b)), (CMP + def : Pat<(ctpop i64:$src), (POPCrr $src)>; + + // "LEA" form of add ++let isCodeGenOnly = 1 in + def LEAX_ADDri : F3_2<2, 0b000000, + (outs I64Regs:$dst), (ins MEMri:$addr), + "add ${addr:arith}, $dst", + [(set iPTR:$dst, ADDRri:$addr)]>; +- + } // Predicates = [Is64Bit] + + |