ARM: ISB cannot be passed the same options as DMB

ISB should only accepts full system sync, other options are reserved

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@183656 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Amaury de la Vieuville
2013-06-10 14:17:08 +00:00
parent 7c32502a7f
commit 4e9a96d810
13 changed files with 179 additions and 2 deletions

View File

@ -4213,6 +4213,16 @@ def memb_opt : Operand<i32> {
let DecoderMethod = "DecodeMemBarrierOption"; let DecoderMethod = "DecodeMemBarrierOption";
} }
def InstSyncBarrierOptOperand : AsmOperandClass {
let Name = "InstSyncBarrierOpt";
let ParserMethod = "parseInstSyncBarrierOptOperand";
}
def instsyncb_opt : Operand<i32> {
let PrintMethod = "printInstSyncBOption";
let ParserMatchClass = InstSyncBarrierOptOperand;
let DecoderMethod = "DecodeInstSyncBarrierOption";
}
// memory barriers protect the atomic sequences // memory barriers protect the atomic sequences
let hasSideEffects = 1 in { let hasSideEffects = 1 in {
def DMB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary, def DMB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary,
@ -4233,7 +4243,7 @@ def DSB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary,
} }
// ISB has only full system option // ISB has only full system option
def ISB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary, def ISB : AInoP<(outs), (ins instsyncb_opt:$opt), MiscFrm, NoItinerary,
"isb", "\t$opt", []>, "isb", "\t$opt", []>,
Requires<[IsARM, HasDB]> { Requires<[IsARM, HasDB]> {
bits<4> opt; bits<4> opt;

View File

@ -3109,7 +3109,7 @@ def t2DSB : AInoP<(outs), (ins memb_opt:$opt), ThumbFrm, NoItinerary,
let Inst{3-0} = opt; let Inst{3-0} = opt;
} }
def t2ISB : AInoP<(outs), (ins memb_opt:$opt), ThumbFrm, NoItinerary, def t2ISB : AInoP<(outs), (ins instsyncb_opt:$opt), ThumbFrm, NoItinerary,
"isb", "\t$opt", "isb", "\t$opt",
[]>, Requires<[IsThumb, HasDB]> { []>, Requires<[IsThumb, HasDB]> {
bits<4> opt; bits<4> opt;

View File

@ -183,6 +183,8 @@ class ARMAsmParser : public MCTargetAsmParser {
SmallVectorImpl<MCParsedAsmOperand*>&); SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy parseMemBarrierOptOperand( OperandMatchResultTy parseMemBarrierOptOperand(
SmallVectorImpl<MCParsedAsmOperand*>&); SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy parseInstSyncBarrierOptOperand(
SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy parseProcIFlagsOperand( OperandMatchResultTy parseProcIFlagsOperand(
SmallVectorImpl<MCParsedAsmOperand*>&); SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy parseMSRMaskOperand( OperandMatchResultTy parseMSRMaskOperand(
@ -315,6 +317,7 @@ class ARMOperand : public MCParsedAsmOperand {
k_CoprocOption, k_CoprocOption,
k_Immediate, k_Immediate,
k_MemBarrierOpt, k_MemBarrierOpt,
k_InstSyncBarrierOpt,
k_Memory, k_Memory,
k_PostIndexRegister, k_PostIndexRegister,
k_MSRMask, k_MSRMask,
@ -358,6 +361,10 @@ class ARMOperand : public MCParsedAsmOperand {
ARM_MB::MemBOpt Val; ARM_MB::MemBOpt Val;
}; };
struct ISBOptOp {
ARM_ISB::InstSyncBOpt Val;
};
struct IFlagsOp { struct IFlagsOp {
ARM_PROC::IFlags Val; ARM_PROC::IFlags Val;
}; };
@ -444,6 +451,7 @@ class ARMOperand : public MCParsedAsmOperand {
struct CopOp Cop; struct CopOp Cop;
struct CoprocOptionOp CoprocOption; struct CoprocOptionOp CoprocOption;
struct MBOptOp MBOpt; struct MBOptOp MBOpt;
struct ISBOptOp ISBOpt;
struct ITMaskOp ITMask; struct ITMaskOp ITMask;
struct IFlagsOp IFlags; struct IFlagsOp IFlags;
struct MMaskOp MMask; struct MMaskOp MMask;
@ -504,6 +512,8 @@ public:
case k_MemBarrierOpt: case k_MemBarrierOpt:
MBOpt = o.MBOpt; MBOpt = o.MBOpt;
break; break;
case k_InstSyncBarrierOpt:
ISBOpt = o.ISBOpt;
case k_Memory: case k_Memory:
Memory = o.Memory; Memory = o.Memory;
break; break;
@ -586,6 +596,11 @@ public:
return MBOpt.Val; return MBOpt.Val;
} }
ARM_ISB::InstSyncBOpt getInstSyncBarrierOpt() const {
assert(Kind == k_InstSyncBarrierOpt && "Invalid access!");
return ISBOpt.Val;
}
ARM_PROC::IFlags getProcIFlags() const { ARM_PROC::IFlags getProcIFlags() const {
assert(Kind == k_ProcIFlags && "Invalid access!"); assert(Kind == k_ProcIFlags && "Invalid access!");
return IFlags.Val; return IFlags.Val;
@ -925,6 +940,7 @@ public:
bool isSPRRegList() const { return Kind == k_SPRRegisterList; } bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
bool isToken() const { return Kind == k_Token; } bool isToken() const { return Kind == k_Token; }
bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; } bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
bool isInstSyncBarrierOpt() const { return Kind == k_InstSyncBarrierOpt; }
bool isMem() const { return Kind == k_Memory; } bool isMem() const { return Kind == k_Memory; }
bool isShifterImm() const { return Kind == k_ShifterImmediate; } bool isShifterImm() const { return Kind == k_ShifterImmediate; }
bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; } bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
@ -1702,6 +1718,11 @@ public:
Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt()))); Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
} }
void addInstSyncBarrierOptOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::CreateImm(unsigned(getInstSyncBarrierOpt())));
}
void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const { void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!"); assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
@ -2367,6 +2388,15 @@ public:
return Op; return Op;
} }
static ARMOperand *CreateInstSyncBarrierOpt(ARM_ISB::InstSyncBOpt Opt,
SMLoc S) {
ARMOperand *Op = new ARMOperand(k_InstSyncBarrierOpt);
Op->ISBOpt.Val = Opt;
Op->StartLoc = S;
Op->EndLoc = S;
return Op;
}
static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) { static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
ARMOperand *Op = new ARMOperand(k_ProcIFlags); ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Op->IFlags.Val = IFlags; Op->IFlags.Val = IFlags;
@ -2421,6 +2451,9 @@ void ARMOperand::print(raw_ostream &OS) const {
case k_MemBarrierOpt: case k_MemBarrierOpt:
OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">"; OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
break; break;
case k_InstSyncBarrierOpt:
OS << "<ARM_ISB::" << InstSyncBOptToString(getInstSyncBarrierOpt()) << ">";
break;
case k_Memory: case k_Memory:
OS << "<memory " OS << "<memory "
<< " base:" << Memory.BaseRegNum; << " base:" << Memory.BaseRegNum;
@ -3405,6 +3438,57 @@ parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return MatchOperand_Success; return MatchOperand_Success;
} }
/// parseInstSyncBarrierOptOperand - Try to parse ISB inst sync barrier options.
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
parseInstSyncBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
SMLoc S = Parser.getTok().getLoc();
const AsmToken &Tok = Parser.getTok();
unsigned Opt;
if (Tok.is(AsmToken::Identifier)) {
StringRef OptStr = Tok.getString();
if (OptStr.lower() == "sy")
Opt = ARM_ISB::SY;
else
return MatchOperand_NoMatch;
Parser.Lex(); // Eat identifier token.
} else if (Tok.is(AsmToken::Hash) ||
Tok.is(AsmToken::Dollar) ||
Tok.is(AsmToken::Integer)) {
if (Parser.getTok().isNot(AsmToken::Integer))
Parser.Lex(); // Eat the '#'.
SMLoc Loc = Parser.getTok().getLoc();
const MCExpr *ISBarrierID;
if (getParser().parseExpression(ISBarrierID)) {
Error(Loc, "illegal expression");
return MatchOperand_ParseFail;
}
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ISBarrierID);
if (!CE) {
Error(Loc, "constant expression expected");
return MatchOperand_ParseFail;
}
int Val = CE->getValue();
if (Val & ~0xf) {
Error(Loc, "immediate value out of range");
return MatchOperand_ParseFail;
}
Opt = ARM_ISB::RESERVED_0 + Val;
} else
return MatchOperand_ParseFail;
Operands.push_back(ARMOperand::CreateInstSyncBarrierOpt(
(ARM_ISB::InstSyncBOpt)Opt, S));
return MatchOperand_Success;
}
/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction. /// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
ARMAsmParser::OperandMatchResultTy ARMAsmParser:: ARMAsmParser::OperandMatchResultTy ARMAsmParser::
parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {

View File

@ -279,6 +279,8 @@ static DecodeStatus DecodeCoprocessor(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder); uint64_t Address, const void *Decoder);
static DecodeStatus DecodeMemBarrierOption(MCInst &Inst, unsigned Insn, static DecodeStatus DecodeMemBarrierOption(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder); uint64_t Address, const void *Decoder);
static DecodeStatus DecodeInstSyncBarrierOption(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeMSRMask(MCInst &Inst, unsigned Insn, static DecodeStatus DecodeMSRMask(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder); uint64_t Address, const void *Decoder);
static DecodeStatus DecodeDoubleRegLoad(MCInst &Inst, unsigned Insn, static DecodeStatus DecodeDoubleRegLoad(MCInst &Inst, unsigned Insn,
@ -3553,6 +3555,15 @@ static DecodeStatus DecodeMemBarrierOption(MCInst &Inst, unsigned Val,
return MCDisassembler::Success; return MCDisassembler::Success;
} }
static DecodeStatus DecodeInstSyncBarrierOption(MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
if (Val & ~0xf)
return MCDisassembler::Fail;
Inst.addOperand(MCOperand::CreateImm(Val));
return MCDisassembler::Success;
}
static DecodeStatus DecodeMSRMask(MCInst &Inst, unsigned Val, static DecodeStatus DecodeMSRMask(MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) { uint64_t Address, const void *Decoder) {
if (!Val) return MCDisassembler::Fail; if (!Val) return MCDisassembler::Fail;

View File

@ -674,6 +674,12 @@ void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,
O << ARM_MB::MemBOptToString(val); O << ARM_MB::MemBOptToString(val);
} }
void ARMInstPrinter::printInstSyncBOption(const MCInst *MI, unsigned OpNum,
raw_ostream &O) {
unsigned val = MI->getOperand(OpNum).getImm();
O << ARM_ISB::InstSyncBOptToString(val);
}
void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum, void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum,
raw_ostream &O) { raw_ostream &O) {
unsigned ShiftOp = MI->getOperand(OpNum).getImm(); unsigned ShiftOp = MI->getOperand(OpNum).getImm();

View File

@ -71,6 +71,7 @@ public:
void printBitfieldInvMaskImmOperand(const MCInst *MI, unsigned OpNum, void printBitfieldInvMaskImmOperand(const MCInst *MI, unsigned OpNum,
raw_ostream &O); raw_ostream &O);
void printMemBOption(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printMemBOption(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printInstSyncBOption(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printShiftImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printShiftImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printPKHASRShiftImm(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printPKHASRShiftImm(const MCInst *MI, unsigned OpNum, raw_ostream &O);

View File

@ -161,6 +161,49 @@ namespace ARM_MB {
} }
} // namespace ARM_MB } // namespace ARM_MB
namespace ARM_ISB {
enum InstSyncBOpt {
RESERVED_0 = 0,
RESERVED_1 = 1,
RESERVED_2 = 2,
RESERVED_3 = 3,
RESERVED_4 = 4,
RESERVED_5 = 5,
RESERVED_6 = 6,
RESERVED_7 = 7,
RESERVED_8 = 8,
RESERVED_9 = 9,
RESERVED_10 = 10,
RESERVED_11 = 11,
RESERVED_12 = 12,
RESERVED_13 = 13,
RESERVED_14 = 14,
SY = 15
};
inline static const char *InstSyncBOptToString(unsigned val) {
switch (val) {
default: llvm_unreachable("Unkown memory operation");
case RESERVED_0: return "#0x0";
case RESERVED_1: return "#0x1";
case RESERVED_2: return "#0x2";
case RESERVED_3: return "#0x3";
case RESERVED_4: return "#0x4";
case RESERVED_5: return "#0x5";
case RESERVED_6: return "#0x6";
case RESERVED_7: return "#0x7";
case RESERVED_8: return "#0x8";
case RESERVED_9: return "#0x9";
case RESERVED_10: return "#0xa";
case RESERVED_11: return "#0xb";
case RESERVED_12: return "#0xc";
case RESERVED_13: return "#0xd";
case RESERVED_14: return "#0xe";
case SY: return "sy";
}
}
} // namespace ARM_ISB
/// isARMLowRegister - Returns true if the register is a low register (r0-r7). /// isARMLowRegister - Returns true if the register is a low register (r0-r7).
/// ///
static inline bool isARMLowRegister(unsigned Reg) { static inline bool isARMLowRegister(unsigned Reg) {

View File

@ -778,9 +778,13 @@ Lforward:
@------------------------------------------------------------------------------ @------------------------------------------------------------------------------
isb sy isb sy
isb isb
isb #15
isb #1
@ CHECK: isb sy @ encoding: [0x6f,0xf0,0x7f,0xf5] @ CHECK: isb sy @ encoding: [0x6f,0xf0,0x7f,0xf5]
@ CHECK: isb sy @ encoding: [0x6f,0xf0,0x7f,0xf5] @ CHECK: isb sy @ encoding: [0x6f,0xf0,0x7f,0xf5]
@ CHECK: isb sy @ encoding: [0x6f,0xf0,0x7f,0xf5]
@ CHECK: isb #0x1 @ encoding: [0x61,0xf0,0x7f,0xf5]
@------------------------------------------------------------------------------ @------------------------------------------------------------------------------

View File

@ -571,9 +571,13 @@ _func:
@------------------------------------------------------------------------------ @------------------------------------------------------------------------------
isb sy isb sy
isb isb
isb #15
isb #1
@ CHECK: isb sy @ encoding: [0xbf,0xf3,0x6f,0x8f] @ CHECK: isb sy @ encoding: [0xbf,0xf3,0x6f,0x8f]
@ CHECK: isb sy @ encoding: [0xbf,0xf3,0x6f,0x8f] @ CHECK: isb sy @ encoding: [0xbf,0xf3,0x6f,0x8f]
@ CHECK: isb sy @ encoding: [0xbf,0xf3,0x6f,0x8f]
@ CHECK: isb #0x1 @ encoding: [0xbf,0xf3,0x61,0x8f]
@------------------------------------------------------------------------------ @------------------------------------------------------------------------------

View File

@ -371,3 +371,8 @@
@ CHECK-ERRORS: error: invalid operand for instruction @ CHECK-ERRORS: error: invalid operand for instruction
@ CHECK-ERRORS: msr foo, #0 @ CHECK-ERRORS: msr foo, #0
@ CHECK-ERRORS: ^ @ CHECK-ERRORS: ^
isb #-1
isb #16
@ CHECK-ERRORS: error: immediate value out of range
@ CHECK-ERRORS: error: immediate value out of range

View File

@ -42,3 +42,8 @@
@ CHECK-ERRORS: error: invalid operand for instruction @ CHECK-ERRORS: error: invalid operand for instruction
@ CHECK-ERRORS: error: immediate operand must be in the range [0,15] @ CHECK-ERRORS: error: immediate operand must be in the range [0,15]
@ CHECK-ERRORS: error: immediate operand must be in the range [0,15] @ CHECK-ERRORS: error: immediate operand must be in the range [0,15]
isb #-1
isb #16
@ CHECK-ERRORS: error: immediate value out of range
@ CHECK-ERRORS: error: immediate value out of range

View File

@ -613,8 +613,10 @@
# ISB # ISB
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# CHECK: isb sy # CHECK: isb sy
# CHECK: isb #0xa
0x6f 0xf0 0x7f 0xf5 0x6f 0xf0 0x7f 0xf5
0x6a 0xf0 0x7f 0xf5

View File

@ -447,8 +447,10 @@
# ISB # ISB
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
#CHECK: isb sy #CHECK: isb sy
#CHECK: isb #0xa
0xbf 0xf3 0x6f 0x8f 0xbf 0xf3 0x6f 0x8f
0xbf 0xf3 0x6a 0x8f
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# IT # IT