mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-16 11:08:09 +00:00
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:
parent
7c32502a7f
commit
4e9a96d810
@ -4213,6 +4213,16 @@ def memb_opt : Operand<i32> {
|
||||
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
|
||||
let hasSideEffects = 1 in {
|
||||
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
|
||||
def ISB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary,
|
||||
def ISB : AInoP<(outs), (ins instsyncb_opt:$opt), MiscFrm, NoItinerary,
|
||||
"isb", "\t$opt", []>,
|
||||
Requires<[IsARM, HasDB]> {
|
||||
bits<4> opt;
|
||||
|
@ -3109,7 +3109,7 @@ def t2DSB : AInoP<(outs), (ins memb_opt:$opt), ThumbFrm, NoItinerary,
|
||||
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",
|
||||
[]>, Requires<[IsThumb, HasDB]> {
|
||||
bits<4> opt;
|
||||
|
@ -183,6 +183,8 @@ class ARMAsmParser : public MCTargetAsmParser {
|
||||
SmallVectorImpl<MCParsedAsmOperand*>&);
|
||||
OperandMatchResultTy parseMemBarrierOptOperand(
|
||||
SmallVectorImpl<MCParsedAsmOperand*>&);
|
||||
OperandMatchResultTy parseInstSyncBarrierOptOperand(
|
||||
SmallVectorImpl<MCParsedAsmOperand*>&);
|
||||
OperandMatchResultTy parseProcIFlagsOperand(
|
||||
SmallVectorImpl<MCParsedAsmOperand*>&);
|
||||
OperandMatchResultTy parseMSRMaskOperand(
|
||||
@ -315,6 +317,7 @@ class ARMOperand : public MCParsedAsmOperand {
|
||||
k_CoprocOption,
|
||||
k_Immediate,
|
||||
k_MemBarrierOpt,
|
||||
k_InstSyncBarrierOpt,
|
||||
k_Memory,
|
||||
k_PostIndexRegister,
|
||||
k_MSRMask,
|
||||
@ -358,6 +361,10 @@ class ARMOperand : public MCParsedAsmOperand {
|
||||
ARM_MB::MemBOpt Val;
|
||||
};
|
||||
|
||||
struct ISBOptOp {
|
||||
ARM_ISB::InstSyncBOpt Val;
|
||||
};
|
||||
|
||||
struct IFlagsOp {
|
||||
ARM_PROC::IFlags Val;
|
||||
};
|
||||
@ -444,6 +451,7 @@ class ARMOperand : public MCParsedAsmOperand {
|
||||
struct CopOp Cop;
|
||||
struct CoprocOptionOp CoprocOption;
|
||||
struct MBOptOp MBOpt;
|
||||
struct ISBOptOp ISBOpt;
|
||||
struct ITMaskOp ITMask;
|
||||
struct IFlagsOp IFlags;
|
||||
struct MMaskOp MMask;
|
||||
@ -504,6 +512,8 @@ public:
|
||||
case k_MemBarrierOpt:
|
||||
MBOpt = o.MBOpt;
|
||||
break;
|
||||
case k_InstSyncBarrierOpt:
|
||||
ISBOpt = o.ISBOpt;
|
||||
case k_Memory:
|
||||
Memory = o.Memory;
|
||||
break;
|
||||
@ -586,6 +596,11 @@ public:
|
||||
return MBOpt.Val;
|
||||
}
|
||||
|
||||
ARM_ISB::InstSyncBOpt getInstSyncBarrierOpt() const {
|
||||
assert(Kind == k_InstSyncBarrierOpt && "Invalid access!");
|
||||
return ISBOpt.Val;
|
||||
}
|
||||
|
||||
ARM_PROC::IFlags getProcIFlags() const {
|
||||
assert(Kind == k_ProcIFlags && "Invalid access!");
|
||||
return IFlags.Val;
|
||||
@ -925,6 +940,7 @@ public:
|
||||
bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
|
||||
bool isToken() const { return Kind == k_Token; }
|
||||
bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
|
||||
bool isInstSyncBarrierOpt() const { return Kind == k_InstSyncBarrierOpt; }
|
||||
bool isMem() const { return Kind == k_Memory; }
|
||||
bool isShifterImm() const { return Kind == k_ShifterImmediate; }
|
||||
bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
|
||||
@ -1702,6 +1718,11 @@ public:
|
||||
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 {
|
||||
assert(N == 1 && "Invalid number of operands!");
|
||||
Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
|
||||
@ -2367,6 +2388,15 @@ public:
|
||||
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) {
|
||||
ARMOperand *Op = new ARMOperand(k_ProcIFlags);
|
||||
Op->IFlags.Val = IFlags;
|
||||
@ -2421,6 +2451,9 @@ void ARMOperand::print(raw_ostream &OS) const {
|
||||
case k_MemBarrierOpt:
|
||||
OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
|
||||
break;
|
||||
case k_InstSyncBarrierOpt:
|
||||
OS << "<ARM_ISB::" << InstSyncBOptToString(getInstSyncBarrierOpt()) << ">";
|
||||
break;
|
||||
case k_Memory:
|
||||
OS << "<memory "
|
||||
<< " base:" << Memory.BaseRegNum;
|
||||
@ -3405,6 +3438,57 @@ parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||
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.
|
||||
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
|
||||
parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||
|
@ -279,6 +279,8 @@ static DecodeStatus DecodeCoprocessor(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void *Decoder);
|
||||
static DecodeStatus DecodeMemBarrierOption(MCInst &Inst, unsigned Insn,
|
||||
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,
|
||||
uint64_t Address, const void *Decoder);
|
||||
static DecodeStatus DecodeDoubleRegLoad(MCInst &Inst, unsigned Insn,
|
||||
@ -3553,6 +3555,15 @@ static DecodeStatus DecodeMemBarrierOption(MCInst &Inst, unsigned Val,
|
||||
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,
|
||||
uint64_t Address, const void *Decoder) {
|
||||
if (!Val) return MCDisassembler::Fail;
|
||||
|
@ -674,6 +674,12 @@ void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,
|
||||
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,
|
||||
raw_ostream &O) {
|
||||
unsigned ShiftOp = MI->getOperand(OpNum).getImm();
|
||||
|
@ -71,6 +71,7 @@ public:
|
||||
void printBitfieldInvMaskImmOperand(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 printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
void printPKHASRShiftImm(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
|
@ -161,6 +161,49 @@ 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).
|
||||
///
|
||||
static inline bool isARMLowRegister(unsigned Reg) {
|
||||
|
@ -778,9 +778,13 @@ Lforward:
|
||||
@------------------------------------------------------------------------------
|
||||
isb sy
|
||||
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 #0x1 @ encoding: [0x61,0xf0,0x7f,0xf5]
|
||||
|
||||
|
||||
@------------------------------------------------------------------------------
|
||||
|
@ -571,9 +571,13 @@ _func:
|
||||
@------------------------------------------------------------------------------
|
||||
isb sy
|
||||
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 #0x1 @ encoding: [0xbf,0xf3,0x61,0x8f]
|
||||
|
||||
|
||||
@------------------------------------------------------------------------------
|
||||
|
@ -371,3 +371,8 @@
|
||||
@ CHECK-ERRORS: error: invalid operand for instruction
|
||||
@ CHECK-ERRORS: msr foo, #0
|
||||
@ CHECK-ERRORS: ^
|
||||
|
||||
isb #-1
|
||||
isb #16
|
||||
@ CHECK-ERRORS: error: immediate value out of range
|
||||
@ CHECK-ERRORS: error: immediate value out of range
|
||||
|
@ -42,3 +42,8 @@
|
||||
@ 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]
|
||||
|
||||
isb #-1
|
||||
isb #16
|
||||
@ CHECK-ERRORS: error: immediate value out of range
|
||||
@ CHECK-ERRORS: error: immediate value out of range
|
||||
|
@ -613,8 +613,10 @@
|
||||
# ISB
|
||||
#------------------------------------------------------------------------------
|
||||
# CHECK: isb sy
|
||||
# CHECK: isb #0xa
|
||||
|
||||
0x6f 0xf0 0x7f 0xf5
|
||||
0x6a 0xf0 0x7f 0xf5
|
||||
|
||||
|
||||
|
||||
|
@ -447,8 +447,10 @@
|
||||
# ISB
|
||||
#------------------------------------------------------------------------------
|
||||
#CHECK: isb sy
|
||||
#CHECK: isb #0xa
|
||||
|
||||
0xbf 0xf3 0x6f 0x8f
|
||||
0xbf 0xf3 0x6a 0x8f
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# IT
|
||||
|
Loading…
x
Reference in New Issue
Block a user