diff options
author | Amaury de la Vieuville <amaury.dlv@gmail.com> | 2013-06-10 14:17:08 +0000 |
---|---|---|
committer | Amaury de la Vieuville <amaury.dlv@gmail.com> | 2013-06-10 14:17:08 +0000 |
commit | 4e9a96d810eb0cc126ebe6f18e536b474c84940c (patch) | |
tree | 764a3391728582c3d113f3e80a713c16045e7cff /lib/Target/ARM/AsmParser | |
parent | 7c32502a7f81dfaddb79c9c8e5b1acc759e19af9 (diff) | |
download | external_llvm-4e9a96d810eb0cc126ebe6f18e536b474c84940c.zip external_llvm-4e9a96d810eb0cc126ebe6f18e536b474c84940c.tar.gz external_llvm-4e9a96d810eb0cc126ebe6f18e536b474c84940c.tar.bz2 |
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
Diffstat (limited to 'lib/Target/ARM/AsmParser')
-rw-r--r-- | lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index c287150..91de199 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -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) { |