diff --git a/lib/Target/ARM/ARMBaseInfo.h b/lib/Target/ARM/ARMBaseInfo.h index 6054bb773e7..a56cc1a9f24 100644 --- a/lib/Target/ARM/ARMBaseInfo.h +++ b/lib/Target/ARM/ARMBaseInfo.h @@ -97,6 +97,36 @@ inline static const char *ARMCondCodeToString(ARMCC::CondCodes CC) { } } +namespace ARM_PROC { + enum IMod { + IE = 2, + ID = 3 + }; + + enum IFlags { + F = 1, + I = 2, + A = 4 + }; + + inline static const char *IFlagsToString(unsigned val) { + switch (val) { + default: llvm_unreachable("Unknown iflags operand"); + case F: return "f"; + case I: return "i"; + case A: return "a"; + } + } + + inline static const char *IModToString(unsigned val) { + switch (val) { + default: llvm_unreachable("Unknown imod operand"); + case IE: return "ie"; + case ID: return "id"; + } + } +} + namespace ARM_MB { // The Memory Barrier Option constants map directly to the 4-bit encoding of // the option field for memory barrier operations. diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index e018ab53ca4..b602712a23e 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -155,6 +155,22 @@ def MemBarrierOptOperand : AsmOperandClass { let ParserMethod = "tryParseMemBarrierOptOperand"; } +def ProcIFlagsOperand : AsmOperandClass { + let Name = "ProcIFlags"; + let SuperClasses = []; + let ParserMethod = "tryParseProcIFlagsOperand"; +} + +// ARM imod and iflag operands, used only by the CPS instruction. +def imod_op : Operand { + let PrintMethod = "printCPSIMod"; +} + +def iflags_op : Operand { + let PrintMethod = "printCPSIFlag"; + let ParserMatchClass = ProcIFlagsOperand; +} + // ARM Predicate operand. Default to 14 = always (AL). Second part is CC // register whose default is 0 (no register). def pred : PredicateOperand, - Requires<[IsARM]> { +// Change Processor State is a system instruction -- for disassembly and +// parsing only. +// FIXME: Since the asm parser has currently no clean way to handle optional +// operands, create 3 versions of the same instruction. Once there's a clean +// framework to represent optional operands, change this behavior. +class CPS + : AXI<(outs), iops, MiscFrm, NoItinerary, !strconcat("cps", asm_ops), + [/* For disassembly only; pattern left blank */]>, Requires<[IsARM]> { + bits<2> imod; + bits<3> iflags; + bits<5> mode; + bit M; + let Inst{31-28} = 0b1111; let Inst{27-20} = 0b00010000; - let Inst{16} = 0; - let Inst{5} = 0; + let Inst{19-18} = imod; + let Inst{17} = M; // Enabled if mode is set; + let Inst{16} = 0; + let Inst{8-6} = iflags; + let Inst{5} = 0; + let Inst{4-0} = mode; } +let M = 1 in + def CPS3p : CPS<(ins imod_op:$imod, iflags_op:$iflags, i32imm:$mode), + "$imod\t$iflags, $mode">; +let mode = 0, M = 0 in + def CPS2p : CPS<(ins imod_op:$imod, iflags_op:$iflags), "$imod\t$iflags">; + +let imod = 0, iflags = 0, M = 1 in + def CPS1p : CPS<(ins i32imm:$mode), "\t$mode">; + // Preload signals the memory system of possible future data/instruction access. // These are for disassembly only. multiclass APreLoad read, bits<1> data, string opc> { diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 6dc07eb7b67..826ef46bcdb 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -266,21 +266,17 @@ def tSETENDLE : T1I<(outs), (ins), NoItinerary, "setend\tle", } // Change Processor State is a system instruction -- for disassembly only. -// The singleton $opt operand contains the following information: -// -// opt{4-0} = mode ==> don't care -// opt{5} = changemode ==> 0 (false for 16-bit Thumb instr) -// opt{8-6} = AIF from Inst{2-0} -// opt{10-9} = 1:imod from Inst{4} with 0b10 as enable and 0b11 as disable -// -// The opt{4-0} and opt{5} sub-fields are to accommodate 32-bit Thumb and ARM -// CPS which has more options. -def tCPS : T1I<(outs), (ins cps_opt:$opt), NoItinerary, "cps$opt", - [/* For disassembly only; pattern left blank */]>, +def tCPS : T1I<(outs), (ins imod_op:$imod, iflags_op:$iflags), + NoItinerary, "cps$imod $iflags", + [/* For disassembly only; pattern left blank */]>, T1Misc<0b0110011> { // A8.6.38 & B6.1.1 - let Inst{3} = 0; - // FIXME: Finish encoding. + bit imod; + bits<3> iflags; + + let Inst{4} = imod; + let Inst{3} = 0; + let Inst{2-0} = iflags; } // For both thumb1 and thumb2. diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index c61c88f8cff..2c2cf46f960 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -3127,41 +3127,40 @@ def t2BXJ : T2I<(outs), (ins rGPR:$func), NoItinerary, "bxj", "\t$func", let Inst{19-16} = func; } -// Change Processor State is a system instruction -- for disassembly only. -// The singleton $opt operand contains the following information: -// opt{4-0} = mode from Inst{4-0} -// opt{5} = changemode from Inst{17} -// opt{8-6} = AIF from Inst{8-6} -// opt{10-9} = imod from Inst{19-18} with 0b10 as enable and 0b11 as disable -def t2CPS : T2XI<(outs),(ins cps_opt:$opt), NoItinerary, "cps$opt", - [/* For disassembly only; pattern left blank */]> { +// Change Processor State is a system instruction -- for disassembly and +// parsing only. +// FIXME: Since the asm parser has currently no clean way to handle optional +// operands, create 3 versions of the same instruction. Once there's a clean +// framework to represent optional operands, change this behavior. +class t2CPS : T2XI<(outs), iops, NoItinerary, + !strconcat("cps", asm_op), + [/* For disassembly only; pattern left blank */]> { + bits<2> imod; + bits<3> iflags; + bits<5> mode; + bit M; + let Inst{31-27} = 0b11110; - let Inst{26} = 0; + let Inst{26} = 0; let Inst{25-20} = 0b111010; + let Inst{19-16} = 0b1111; let Inst{15-14} = 0b10; - let Inst{12} = 0; - - bits<11> opt; - - // mode number - let Inst{4-0} = opt{4-0}; - - // M flag - let Inst{8} = opt{5}; - - // F flag - let Inst{5} = opt{6}; - - // I flag - let Inst{6} = opt{7}; - - // A flag - let Inst{7} = opt{8}; - - // imod flag - let Inst{10-9} = opt{10-9}; + let Inst{12} = 0; + let Inst{10-9} = imod; + let Inst{8} = M; + let Inst{7-5} = iflags; + let Inst{4-0} = mode; } +let M = 1 in + def t2CPS3p : t2CPS<(ins imod_op:$imod, iflags_op:$iflags, i32imm:$mode), + "$imod.w\t$iflags, $mode">; +let mode = 0, M = 0 in + def t2CPS2p : t2CPS<(ins imod_op:$imod, iflags_op:$iflags), + "$imod.w\t$iflags">; +let imod = 0, iflags = 0, M = 1 in + def t2CPS1p : t2CPS<(ins i32imm:$mode), "\t$mode">; + // A6.3.4 Branches and miscellaneous control // Table A6-14 Change Processor State, and hint instructions // Helper class for disassembly only. diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 089a08c405f..fd7e7734ad6 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -98,6 +98,8 @@ class ARMAsmParser : public TargetAsmParser { SmallVectorImpl&); OperandMatchResultTy tryParseMemBarrierOptOperand( SmallVectorImpl &); + OperandMatchResultTy tryParseProcIFlagsOperand( + SmallVectorImpl &); public: ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM) @@ -126,6 +128,7 @@ class ARMOperand : public MCParsedAsmOperand { Immediate, MemBarrierOpt, Memory, + ProcIFlags, Register, RegisterList, DPRRegisterList, @@ -149,6 +152,10 @@ class ARMOperand : public MCParsedAsmOperand { unsigned Val; } Cop; + struct { + ARM_PROC::IFlags Val; + } IFlags; + struct { const char *Data; unsigned Length; @@ -215,6 +222,8 @@ public: case Memory: Mem = o.Mem; break; + case ProcIFlags: + IFlags = o.IFlags; } } @@ -259,6 +268,11 @@ public: return MBOpt.Val; } + ARM_PROC::IFlags getProcIFlags() const { + assert(Kind == ProcIFlags && "Invalid access!"); + return IFlags.Val; + } + /// @name Memory Operand Accessors /// @{ @@ -333,6 +347,7 @@ public: uint64_t Value = CE->getValue(); return ((Value & 0x3) == 0 && Value <= 124); } + bool isProcIFlags() const { return Kind == ProcIFlags; } void addExpr(MCInst &Inst, const MCExpr *Expr) const { // Add as immediates when possible. Null MCExpr = 0. @@ -433,6 +448,11 @@ public: Inst.addOperand(MCOperand::CreateImm(CE->getValue())); } + void addProcIFlagsOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags()))); + } + virtual void dump(raw_ostream &OS) const; static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) { @@ -556,6 +576,14 @@ public: Op->EndLoc = S; return Op; } + + static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) { + ARMOperand *Op = new ARMOperand(ProcIFlags); + Op->IFlags.Val = IFlags; + Op->StartLoc = S; + Op->EndLoc = S; + return Op; + } }; } // end anonymous namespace. @@ -604,6 +632,15 @@ void ARMOperand::dump(raw_ostream &OS) const { OS << " (writeback)"; OS << ">"; break; + case ProcIFlags: { + OS << "= 0; --i) + if (IFlags & (1 << i)) + OS << ARM_PROC::IFlagsToString(1 << i); + OS << ">"; + break; + } case Register: OS << ""; break; @@ -885,6 +922,35 @@ tryParseMemBarrierOptOperand(SmallVectorImpl &Operands) { return MatchOperand_Success; } +/// ParseProcIFlagsOperand - Try to parse iflags from CPS instruction. +ARMAsmParser::OperandMatchResultTy ARMAsmParser:: +tryParseProcIFlagsOperand(SmallVectorImpl &Operands) { + SMLoc S = Parser.getTok().getLoc(); + const AsmToken &Tok = Parser.getTok(); + assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); + StringRef IFlagsStr = Tok.getString(); + + unsigned IFlags = 0; + for (int i = 0, e = IFlagsStr.size(); i != e; ++i) { + unsigned Flag = StringSwitch(IFlagsStr.substr(i, 1)) + .Case("a", ARM_PROC::A) + .Case("i", ARM_PROC::I) + .Case("f", ARM_PROC::F) + .Default(~0U); + + // If some specific iflag is already set, it means that some letter is + // present more than once, this is not acceptable. + if (Flag == ~0U || (IFlags & Flag)) + return MatchOperand_NoMatch; + + IFlags |= Flag; + } + + Parser.Lex(); // Eat identifier token. + Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S)); + return MatchOperand_Success; +} + /// Parse an ARM memory expression, return false if successful else return true /// or an error. The first token must be a '[' when called. /// @@ -1254,11 +1320,13 @@ ARMAsmParser::ApplyPrefixToExpr(const MCExpr *E, /// setting letters to form a canonical mnemonic and flags. // // FIXME: Would be nice to autogen this. -static StringRef SplitMnemonicAndCC(StringRef Mnemonic, - unsigned &PredicationCode, - bool &CarrySetting) { +static StringRef SplitMnemonic(StringRef Mnemonic, + unsigned &PredicationCode, + bool &CarrySetting, + unsigned &ProcessorIMod) { PredicationCode = ARMCC::AL; CarrySetting = false; + ProcessorIMod = 0; // Ignore some mnemonics we know aren't predicated forms. // @@ -1312,6 +1380,21 @@ static StringRef SplitMnemonicAndCC(StringRef Mnemonic, CarrySetting = true; } + // The "cps" instruction can have a interrupt mode operand which is glued into + // the mnemonic. Check if this is the case, split it and parse the imod op + if (Mnemonic.startswith("cps")) { + // Split out any imod code. + unsigned IMod = + StringSwitch(Mnemonic.substr(Mnemonic.size()-2, 2)) + .Case("ie", ARM_PROC::IE) + .Case("id", ARM_PROC::ID) + .Default(~0U); + if (IMod != ~0U) { + Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2); + ProcessorIMod = IMod; + } + } + return Mnemonic; } @@ -1342,7 +1425,7 @@ GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" || Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" || Mnemonic == "dsb" || Mnemonic == "movs" || Mnemonic == "isb" || - Mnemonic == "clrex") { + Mnemonic == "clrex" || Mnemonic.startswith("cps")) { CanAcceptPredicationCode = false; } else { CanAcceptPredicationCode = true; @@ -1363,8 +1446,10 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc, // Split out the predication code and carry setting flag from the mnemonic. unsigned PredicationCode; + unsigned ProcessorIMod; bool CarrySetting; - Head = SplitMnemonicAndCC(Head, PredicationCode, CarrySetting); + Head = SplitMnemonic(Head, PredicationCode, CarrySetting, + ProcessorIMod); Operands.push_back(ARMOperand::CreateToken(Head, NameLoc)); @@ -1404,13 +1489,25 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc, // FIXME: Issue a nice error. } + // Add the processor imod operand, if necessary. + if (ProcessorIMod) { + Operands.push_back(ARMOperand::CreateImm( + MCConstantExpr::Create(ProcessorIMod, getContext()), + NameLoc, NameLoc)); + } else { + // This mnemonic can't ever accept a imod, but the user wrote + // one (or misspelled another mnemonic). + + // FIXME: Issue a nice error. + } + // Add the remaining tokens in the mnemonic. while (Next != StringRef::npos) { Start = Next; Next = Name.find('.', Start + 1); - Head = Name.slice(Start, Next); + StringRef ExtraToken = Name.slice(Start, Next); - Operands.push_back(ARMOperand::CreateToken(Head, NameLoc)); + Operands.push_back(ARMOperand::CreateToken(ExtraToken, NameLoc)); } // Read the remaining operands. diff --git a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp index 45c6c300aa1..06ad61e9b35 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp @@ -2942,15 +2942,25 @@ static bool DisassembleMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, return true; } - // CPS has a singleton $opt operand that contains the following information: - // opt{4-0} = mode from Inst{4-0} - // opt{5} = changemode from Inst{17} - // opt{8-6} = AIF from Inst{8-6} - // opt{10-9} = imod from Inst{19-18} with 0b10 as enable and 0b11 as disable - if (Opcode == ARM::CPS) { - unsigned Option = slice(insn, 4, 0) | slice(insn, 17, 17) << 5 | - slice(insn, 8, 6) << 6 | slice(insn, 19, 18) << 9; - MI.addOperand(MCOperand::CreateImm(Option)); + // FIXME: To enable correct asm parsing and disasm of CPS we need 3 different + // opcodes which match the same real instruction. This is needed since there's + // no current handling of optional arguments. Fix here when a better handling + // of optional arguments is implemented. + if (Opcode == ARM::CPS3p) { + MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 18))); // imod + MI.addOperand(MCOperand::CreateImm(slice(insn, 8, 6))); // iflags + MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); // mode + NumOpsAdded = 3; + return true; + } + if (Opcode == ARM::CPS2p) { + MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 18))); // imod + MI.addOperand(MCOperand::CreateImm(slice(insn, 8, 6))); // iflags + NumOpsAdded = 2; + return true; + } + if (Opcode == ARM::CPS1p) { + MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); // mode NumOpsAdded = 1; return true; } diff --git a/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h b/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h index 8a38507a5a6..d1428169f7b 100644 --- a/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h +++ b/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h @@ -828,14 +828,13 @@ static bool DisassembleThumb1Misc(MCInst &MI, unsigned Opcode, uint32_t insn, } // CPS has a singleton $opt operand that contains the following information: - // opt{4-0} = don't care - // opt{5} = 0 (false) - // opt{8-6} = AIF from Inst{2-0} - // opt{10-9} = 1:imod from Inst{4} with 0b10 as enable and 0b11 as disable + // The first op would be 0b10 as enable and 0b11 as disable in regular ARM, + // but in Thumb it's is 0 as enable and 1 as disable. So map it to ARM's + // default one. The second get the AIF flags from Inst{2-0}. if (Opcode == ARM::tCPS) { - unsigned Option = slice(insn, 2, 0) << 6 | slice(insn, 4, 4) << 9 | 1 << 10; - MI.addOperand(MCOperand::CreateImm(Option)); - NumOpsAdded = 1; + MI.addOperand(MCOperand::CreateImm(2 + slice(insn, 4, 4))); + MI.addOperand(MCOperand::CreateImm(slice(insn, 2, 0))); + NumOpsAdded = 2; return true; } @@ -1659,15 +1658,25 @@ static bool DisassembleThumb2BrMiscCtrl(MCInst &MI, unsigned Opcode, break; } - // CPS has a singleton $opt operand that contains the following information: - // opt{4-0} = mode from Inst{4-0} - // opt{5} = changemode from Inst{8} - // opt{8-6} = AIF from Inst{7-5} - // opt{10-9} = imod from Inst{10-9} with 0b10 as enable and 0b11 as disable - if (Opcode == ARM::t2CPS) { - unsigned Option = slice(insn, 4, 0) | slice(insn, 8, 8) << 5 | - slice(insn, 7, 5) << 6 | slice(insn, 10, 9) << 9; - MI.addOperand(MCOperand::CreateImm(Option)); + // FIXME: To enable correct asm parsing and disasm of CPS we need 3 different + // opcodes which match the same real instruction. This is needed since there's + // no current handling of optional arguments. Fix here when a better handling + // of optional arguments is implemented. + if (Opcode == ARM::t2CPS3p) { + MI.addOperand(MCOperand::CreateImm(slice(insn, 10, 9))); // imod + MI.addOperand(MCOperand::CreateImm(slice(insn, 7, 5))); // iflags + MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); // mode + NumOpsAdded = 3; + return true; + } + if (Opcode == ARM::t2CPS2p) { + MI.addOperand(MCOperand::CreateImm(slice(insn, 10, 9))); // imod + MI.addOperand(MCOperand::CreateImm(slice(insn, 7, 5))); // iflags + NumOpsAdded = 2; + return true; + } + if (Opcode == ARM::t2CPS1p) { + MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); // mode NumOpsAdded = 1; return true; } diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp index 4f03b8497b9..aace2f97233 100644 --- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp +++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp @@ -379,27 +379,19 @@ void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum, O << "le"; } -void ARMInstPrinter::printCPSOptionOperand(const MCInst *MI, unsigned OpNum, - raw_ostream &O) { +void ARMInstPrinter::printCPSIMod(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { const MCOperand &Op = MI->getOperand(OpNum); - unsigned option = Op.getImm(); - unsigned mode = option & 31; - bool changemode = option >> 5 & 1; - unsigned AIF = option >> 6 & 7; - unsigned imod = option >> 9 & 3; - if (imod == 2) - O << "ie"; - else if (imod == 3) - O << "id"; - O << '\t'; - if (imod > 1) { - if (AIF & 4) O << 'a'; - if (AIF & 2) O << 'i'; - if (AIF & 1) O << 'f'; - if (AIF > 0 && changemode) O << ", "; - } - if (changemode) - O << '#' << mode; + O << ARM_PROC::IModToString(Op.getImm()); +} + +void ARMInstPrinter::printCPSIFlag(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { + const MCOperand &Op = MI->getOperand(OpNum); + unsigned IFlags = Op.getImm(); + for (int i=2; i >= 0; --i) + if (IFlags & (1 << i)) + O << ARM_PROC::IFlagsToString(1 << i); } void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum, diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h index 3c94b6eabac..679d3135ea6 100644 --- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h +++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h @@ -85,6 +85,8 @@ public: raw_ostream &O); void printSetendOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printCPSIMod(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printCPSIFlag(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printCPSOptionOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printMSRMaskOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printNegZeroOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); diff --git a/test/MC/ARM/arm_instructions.s b/test/MC/ARM/arm_instructions.s index f5bf236ab2d..291a76131c6 100644 --- a/test/MC/ARM/arm_instructions.s +++ b/test/MC/ARM/arm_instructions.s @@ -237,3 +237,12 @@ @ CHECK: dsb oshst @ encoding: [0x42,0xf0,0x7f,0xf5] dsb oshst +@ CHECK: cpsie aif @ encoding: [0xc0,0x01,0x08,0xf1] + cpsie aif + +@ CHECK: cps #15 @ encoding: [0x0f,0x00,0x02,0xf1] + cps #15 + +@ CHECK: cpsie if, #10 @ encoding: [0xca,0x00,0x0a,0xf1] + cpsie if, #10 + diff --git a/test/MC/ARM/thumb.s b/test/MC/ARM/thumb.s index 5d284c31fe5..342a390d81a 100644 --- a/test/MC/ARM/thumb.s +++ b/test/MC/ARM/thumb.s @@ -65,3 +65,6 @@ @ CHECK: wfi @ encoding: [0x30,0xbf] wfi + +@ CHECK: cpsie aif @ encoding: [0x67,0xb6] + cpsie aif diff --git a/test/MC/ARM/thumb2.s b/test/MC/ARM/thumb2.s index b8b068fd901..be4e555dc45 100644 --- a/test/MC/ARM/thumb2.s +++ b/test/MC/ARM/thumb2.s @@ -252,3 +252,10 @@ @ CHECK: dsb oshst @ encoding: [0xbf,0xf3,0x42,0x8f] dsb oshst +@ CHECK: cpsie.w aif @ encoding: [0xaf,0xf3,0xe0,0x84] + cpsie.w aif +@ CHECK: cps #15 @ encoding: [0xaf,0xf3,0x0f,0x81] + cps #15 +@ CHECK: cpsie.w if, #10 @ encoding: [0xaf,0xf3,0x6a,0x85] + cpsie.w if, #10 + diff --git a/test/MC/Disassembler/ARM/arm-tests.txt b/test/MC/Disassembler/ARM/arm-tests.txt index 07d349fc3b8..26bd182d78a 100644 --- a/test/MC/Disassembler/ARM/arm-tests.txt +++ b/test/MC/Disassembler/ARM/arm-tests.txt @@ -118,3 +118,12 @@ # CHECK: setend le 0x00 0x00 0x01 0xf1 + +# CHECK: cpsie aif +0xc0 0x01 0x08 0xf1 + +# CHECK: cps #15 +0x0f 0x00 0x02 0xf1 + +# CHECK: cpsie if, #10 +0xca 0x00 0x0a 0xf1 diff --git a/test/MC/Disassembler/ARM/thumb-tests.txt b/test/MC/Disassembler/ARM/thumb-tests.txt index 29c67e7a035..4e8bc9baa26 100644 --- a/test/MC/Disassembler/ARM/thumb-tests.txt +++ b/test/MC/Disassembler/ARM/thumb-tests.txt @@ -103,3 +103,15 @@ # IT block end # CHECK: rsbs r1, r2, #0 0x51 0x42 + +# CHECK: cpsid.w f +0xaf 0xf3 0x20 0x86 + +# CHECK: cps #15 +0xaf 0xf3 0x0f 0x81 + +# CHECK: cpsie.w if, #10 +0xaf 0xf3 0x6a 0x85 + +# CHECK: cpsie aif +0x67 0xb6 diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index f00f79d56a4..020a4a312d7 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -576,6 +576,8 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, IMM("nohash_imm"); IMM("p_imm"); IMM("c_imm"); + IMM("imod_op"); + IMM("iflags_op"); IMM("cpinst_operand"); IMM("setend_op"); IMM("cps_opt");