Index: llvm/trunk/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ llvm/trunk/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,52 @@ return MatchOperand_Success; } +OperandMatchResultTy SparcAsmParser::parseMembarTag(OperandVector &Operands) { + SMLoc S = Parser.getTok().getLoc(); + const MCExpr *EVal; + int64_t ImmVal = 0; + + std::unique_ptr Mask; + if (parseSparcAsmOperand(Mask) == MatchOperand_Success) { + if (!Mask->isImm() || !Mask->getImm()->evaluateAsAbsolute(ImmVal) || + ImmVal < 0 || ImmVal > 127) { + Error(S, "invalid membar mask number"); + return MatchOperand_ParseFail; + } + } + + 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 '|'. + } + + 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: llvm/trunk/lib/Target/Sparc/InstPrinter/SparcInstPrinter.h =================================================================== --- llvm/trunk/lib/Target/Sparc/InstPrinter/SparcInstPrinter.h +++ llvm/trunk/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: llvm/trunk/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp =================================================================== --- llvm/trunk/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp +++ llvm/trunk/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp @@ -195,3 +195,26 @@ 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(); + + if (Imm > 127) { + O << Imm; + return; + } + + bool First = true; + for (unsigned i = 0; i < sizeof(TagNames) / sizeof(char *); i++) { + if (Imm & (1 << i)) { + O << (First ? "" : " | ") << TagNames[i]; + First = false; + } + } +} Index: llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td =================================================================== --- llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td +++ llvm/trunk/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,7 +1513,7 @@ (POPCrr (SRLri $src, 0))>; let Predicates = [HasV9], hasSideEffects = 1, rd = 0, rs1 = 0b01111 in - def MEMBARi : F3_2<2, 0b101000, (outs), (ins simm13Op:$simm13), + def MEMBARi : F3_2<2, 0b101000, (outs), (ins MembarTag:$simm13), "membar $simm13", []>; // The CAS instruction, unlike other instructions, only comes in a Index: llvm/trunk/test/MC/Disassembler/Sparc/sparc-v9.txt =================================================================== --- llvm/trunk/test/MC/Disassembler/Sparc/sparc-v9.txt +++ llvm/trunk/test/MC/Disassembler/Sparc/sparc-v9.txt @@ -115,4 +115,19 @@ 0x9f 0xd0 0x30 0x52 # CHECK: tvs %xcc, %g1 + %i2 -0x8f 0xd0 0x50 0x1a \ No newline at end of file +0x8f 0xd0 0x50 0x1a + +# CHECK: membar 5000 +0x81 0x43 0xf3 0x88 + +# CHECK: membar #LoadLoad | #StoreLoad | #LoadStore | #StoreStore +0x81 0x43 0xe0 0x0f + +# CHECK: membar #LoadLoad +0x81 0x43 0xe0 0x01 + +# CHECK: membar #LoadLoad | #StoreStore +0x81 0x43 0xe0 0x09 + +# CHECK: membar #LoadLoad | #StoreLoad | #LoadStore | #StoreStore | #Lookaside | #MemIssue | #Sync +0x81 0x43 0xe0 0x7f Index: llvm/trunk/test/MC/Sparc/sparc-asm-errors.s =================================================================== --- llvm/trunk/test/MC/Sparc/sparc-asm-errors.s +++ llvm/trunk/test/MC/Sparc/sparc-asm-errors.s @@ -1,8 +1,16 @@ -! RUN: not llvm-mc %s -arch=sparc -show-encoding 2>&1 | FileCheck %s -! RUN: not llvm-mc %s -arch=sparcv9 -show-encoding 2>&1 | FileCheck %s +! RUN: not llvm-mc %s -arch=sparc -show-encoding 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=V8 +! RUN: not llvm-mc %s -arch=sparcv9 -show-encoding 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=V9 ! Test the lower and upper bounds of 'set' ! CHECK: argument must be between set -2147483649, %o1 ! CHECK: argument must be between set 4294967296, %o1 + + ! V8: unexpected token + ! V9: unknown membar tag + membar #BadTag + + ! V8: instruction requires a CPU feature not currently enabled + ! V9: invalid membar mask number + membar -127 Index: llvm/trunk/test/MC/Sparc/sparcv9-atomic-instructions.s =================================================================== --- llvm/trunk/test/MC/Sparc/sparcv9-atomic-instructions.s +++ llvm/trunk/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