forked from OSchip/llvm-project
[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:
parent
ba91ff4a86
commit
77611426e1
|
@ -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) {
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue