Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp =================================================================== --- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -78,6 +78,8 @@ // Custom parse functions for Sparc specific operands. OperandMatchResultTy parseMEMOperand(OperandVector &Operands); + OperandMatchResultTy parseMembarTag(OperandVector &Operands); + OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Name); OperandMatchResultTy @@ -256,6 +258,7 @@ bool isMem() const override { return isMEMrr() || isMEMri(); } bool isMEMrr() const { return Kind == k_MemoryReg; } bool isMEMri() const { return Kind == k_MemoryImm; } + bool isMembarTag() const { return Kind == k_Immediate; } bool isIntReg() const { return (Kind == k_Register && Reg.Kind == rk_IntReg); @@ -366,6 +369,12 @@ addExpr(Inst, Expr); } + void addMembarTagOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + const MCExpr *Expr = getImm(); + addExpr(Inst, Expr); + } + static std::unique_ptr CreateToken(StringRef Str, SMLoc S) { auto Op = make_unique(k_Token); Op->Tok.Data = Str.data(); @@ -742,6 +751,46 @@ return MatchOperand_Success; } +OperandMatchResultTy SparcAsmParser::parseMembarTag(OperandVector &Operands) { + SMLoc S = Parser.getTok().getLoc(); + const MCExpr *EVal; + unsigned ImmVal = 0; + + while (getLexer().getKind() == AsmToken::Hash) { + SMLoc TagStart = getLexer().getLoc(); + Parser.Lex(); // Eat the '#'. + unsigned MaskVal = StringSwitch(Parser.getTok().getString()) + .Case("LoadLoad", 0x1) + .Case("StoreLoad", 0x2) + .Case("LoadStore", 0x4) + .Case("StoreStore", 0x8) + .Case("Lookaside", 0x10) + .Case("MemIssue", 0x20) + .Case("Sync", 0x40) + .Default(0); + + Parser.Lex(); // Eat the identifier token. + + if (!MaskVal) { + Error(TagStart, "unknown membar tag"); + return MatchOperand_ParseFail; + } + + ImmVal |= MaskVal; + + if (getLexer().getKind() == AsmToken::Pipe) + Parser.Lex(); // Eat the '|'. + } + + if (!ImmVal) + return MatchOperand_NoMatch; + + EVal = MCConstantExpr::create(ImmVal, getContext()); + SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + Operands.push_back(SparcOperand::CreateImm(EVal, S, E)); + return MatchOperand_Success; +} + OperandMatchResultTy SparcAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { Index: lib/Target/Sparc/InstPrinter/SparcInstPrinter.h =================================================================== --- lib/Target/Sparc/InstPrinter/SparcInstPrinter.h +++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.h @@ -49,6 +49,8 @@ raw_ostream &OS); bool printGetPCX(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &OS); + void printMembarTag(const MCInst *MI, int opNum, const MCSubtargetInfo &STI, + raw_ostream &O); }; } // end namespace llvm Index: lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp =================================================================== --- lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp +++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp @@ -195,3 +195,21 @@ llvm_unreachable("FIXME: Implement SparcInstPrinter::printGetPCX."); return true; } + +void SparcInstPrinter::printMembarTag(const MCInst *MI, int opNum, + const MCSubtargetInfo &STI, + raw_ostream &O) { + static const char *const TagNames[] = { + "#LoadLoad", "#StoreLoad", "#LoadStore", "#StoreStore", + "#Lookaside", "#MemIssue", "#Sync"}; + + unsigned Imm = MI->getOperand(opNum).getImm(); + + bool First = true; + for (unsigned i = 0; i < sizeof(TagNames) / sizeof(char *); i++) { + if (Imm & (1 << i)) { + O << (First ? "" : " | ") << TagNames[i]; + First = false; + } + } +} Index: lib/Target/Sparc/SparcInstrInfo.td =================================================================== --- lib/Target/Sparc/SparcInstrInfo.td +++ lib/Target/Sparc/SparcInstrInfo.td @@ -138,6 +138,16 @@ def TLSSym : Operand; +def SparcMembarTagAsmOperand : AsmOperandClass { + let Name = "MembarTag"; + let ParserMethod = "parseMembarTag"; +} + +def MembarTag : Operand { + let PrintMethod = "printMembarTag"; + let ParserMatchClass = SparcMembarTagAsmOperand; +} + // Branch targets have OtherVT type. def brtarget : Operand { let EncoderMethod = "getBranchTargetOpValue"; @@ -1503,8 +1513,8 @@ (POPCrr (SRLri $src, 0))>; let Predicates = [HasV9], hasSideEffects = 1, rd = 0, rs1 = 0b01111 in - def MEMBARi : F3_2<2, 0b101000, (outs), (ins simm13Op:$simm13), - "membar $simm13", []>; + def MEMBARi : F3_2<2, 0b101000, (outs), (ins MembarTag:$tag), + "membar $tag", []>; // The CAS instruction, unlike other instructions, only comes in a // form which requires an ASI be provided. The ASI value hardcoded Index: test/MC/Sparc/sparcv9-atomic-instructions.s =================================================================== --- test/MC/Sparc/sparcv9-atomic-instructions.s +++ test/MC/Sparc/sparcv9-atomic-instructions.s @@ -1,8 +1,17 @@ ! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s - ! CHECK: membar 15 ! encoding: [0x81,0x43,0xe0,0x0f] + ! CHECK: membar #LoadLoad | #StoreLoad | #LoadStore | #StoreStore ! encoding: [0x81,0x43,0xe0,0x0f] membar 15 + ! CHECK: membar #LoadLoad ! encoding: [0x81,0x43,0xe0,0x01] + membar #LoadLoad + + ! CHECK: membar #LoadLoad | #StoreStore ! encoding: [0x81,0x43,0xe0,0x09] + membar #LoadLoad | #StoreStore + + ! CHECK: membar #LoadLoad | #StoreLoad | #LoadStore | #StoreStore | #Lookaside | #MemIssue | #Sync ! encoding: [0x81,0x43,0xe0,0x7f] + membar #LoadLoad | #StoreLoad | #LoadStore | #StoreStore | #Lookaside | #MemIssue | #Sync + ! CHECK: cas [%i0], %l6, %o2 ! encoding: [0xd5,0xe6,0x10,0x16] cas [%i0], %l6, %o2