[Sparc] Add membar assembler tags

Summary: The Sparc V9 membar instruction can enforce different types of
memory orderings depending on the value in its immediate field.  In the
architectural manual the type is selected by combining different assembler
tags into a mask. This patch adds support for these tags.

Reviewers: jyknight, venkatra, brad

Reviewed By: jyknight

Subscribers: fedor.sergeev, jrtc27, jfb, llvm-commits

Differential Revision: https://reviews.llvm.org/D53491

llvm-svn: 349048
This commit is contained in:
Daniel Cederman 2018-12-13 15:29:12 +00:00
parent ba91ff4a86
commit 77611426e1
7 changed files with 127 additions and 5 deletions

View File

@ -78,6 +78,8 @@ class SparcAsmParser : public MCTargetAsmParser {
// 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 @@ public:
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 @@ public:
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<SparcOperand> CreateToken(StringRef Str, SMLoc S) {
auto Op = make_unique<SparcOperand>(k_Token);
Op->Tok.Data = Str.data();
@ -742,6 +751,52 @@ SparcAsmParser::parseMEMOperand(OperandVector &Operands) {
return MatchOperand_Success;
}
OperandMatchResultTy SparcAsmParser::parseMembarTag(OperandVector &Operands) {
SMLoc S = Parser.getTok().getLoc();
const MCExpr *EVal;
int64_t ImmVal = 0;
std::unique_ptr<SparcOperand> 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<unsigned>(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) {

View File

@ -195,3 +195,26 @@ bool SparcInstPrinter::printGetPCX(const MCInst *MI, unsigned opNum,
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;
}
}
}

View File

@ -49,6 +49,8 @@ public:
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

View File

@ -138,6 +138,16 @@ def MEMri : Operand<iPTR> {
def TLSSym : Operand<iPTR>;
def SparcMembarTagAsmOperand : AsmOperandClass {
let Name = "MembarTag";
let ParserMethod = "parseMembarTag";
}
def MembarTag : Operand<i32> {
let PrintMethod = "printMembarTag";
let ParserMatchClass = SparcMembarTagAsmOperand;
}
// Branch targets have OtherVT type.
def brtarget : Operand<OtherVT> {
let EncoderMethod = "getBranchTargetOpValue";
@ -1503,7 +1513,7 @@ def : Pat<(ctpop i32:$src),
(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

View File

@ -115,4 +115,19 @@
0x9f 0xd0 0x30 0x52
# CHECK: tvs %xcc, %g1 + %i2
0x8f 0xd0 0x50 0x1a
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

View File

@ -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

View File

@ -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