diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index 54231a7465a..39c0ba81732 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -801,6 +801,13 @@ class TIx2 opcod1, bits<2> opcod2, bit opcod3, let Inst{12} = opcod3; } +// Move to/from coprocessor instructions +class T1Cop pattern> + : ThumbI, + Encoding, Requires<[IsThumb, HasV6]> { + let Inst{31-28} = 0b1110; +} + // BR_JT instructions class TJTI pattern> diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 043254a3d42..406d8db792a 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -1322,6 +1322,61 @@ def tLEApcrelJT : tPseudoInst<(outs tGPR:$Rd), (ins i32imm:$label, nohash_imm:$id, pred:$p), Size2Bytes, IIC_iALUi, []>; +//===----------------------------------------------------------------------===// +// Move between coprocessor and ARM core register -- for disassembly only +// + +class tMovRCopro + : T1Cop<(outs), (ins p_imm:$cop, i32imm:$opc1, + GPR:$Rt, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), + !strconcat(opc, "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2"), + [/* For disassembly only; pattern left blank */]> { + let Inst{27-24} = 0b1110; + let Inst{20} = direction; + let Inst{4} = 1; + + bits<4> Rt; + bits<4> cop; + bits<3> opc1; + bits<3> opc2; + bits<4> CRm; + bits<4> CRn; + + let Inst{15-12} = Rt; + let Inst{11-8} = cop; + let Inst{23-21} = opc1; + let Inst{7-5} = opc2; + let Inst{3-0} = CRm; + let Inst{19-16} = CRn; +} + +def tMCR : tMovRCopro<"mcr", 0 /* from ARM core register to coprocessor */>; +def tMRC : tMovRCopro<"mrc", 1 /* from coprocessor to ARM core register */>; + +class tMovRRCopro + : T1Cop<(outs), (ins p_imm:$cop, i32imm:$opc1, GPR:$Rt, GPR:$Rt2, c_imm:$CRm), + !strconcat(opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm"), + [/* For disassembly only; pattern left blank */]> { + let Inst{27-24} = 0b1100; + let Inst{23-21} = 0b010; + let Inst{20} = direction; + + bits<4> Rt; + bits<4> Rt2; + bits<4> cop; + bits<4> opc1; + bits<4> CRm; + + let Inst{15-12} = Rt; + let Inst{19-16} = Rt2; + let Inst{11-8} = cop; + let Inst{7-4} = opc1; + let Inst{3-0} = CRm; +} + +def tMCRR : tMovRRCopro<"mcrr", 0 /* from ARM core register to coprocessor */>; +def tMRRC : tMovRRCopro<"mrrc", 1 /* from coprocessor to ARM core register */>; + //===----------------------------------------------------------------------===// // TLS Instructions // diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 6a8b6582157..ba42b1ec103 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -1193,12 +1193,16 @@ GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" || Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" || Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" || - Mnemonic == "dsb" || Mnemonic == "movs" || Mnemonic == "isb" || - (isThumb && Mnemonic == "bkpt")) { + Mnemonic == "dsb" || Mnemonic == "movs" || Mnemonic == "isb") { CanAcceptPredicationCode = false; } else { CanAcceptPredicationCode = true; } + + if (isThumb) + if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" || + Mnemonic == "mrc" || Mnemonic == "mrrc") + CanAcceptPredicationCode = false; } /// Parse an arm instruction mnemonic followed by its operands. diff --git a/test/MC/ARM/thumb.s b/test/MC/ARM/thumb.s index b34800a1162..f1af26ca9ed 100644 --- a/test/MC/ARM/thumb.s +++ b/test/MC/ARM/thumb.s @@ -38,3 +38,16 @@ @ CHECK: bkpt #2 @ encoding: [0x02,0xbe] bkpt #2 + +@ CHECK: mcr p7, #1, r5, c1, c1, #4 @ encoding: [0x21,0xee,0x91,0x57] + mcr p7, #1, r5, c1, c1, #4 + +@ CHECK: mrc p14, #0, r1, c1, c2, #4 @ encoding: [0x11,0xee,0x92,0x1e] + mrc p14, #0, r1, c1, c2, #4 + +@ CHECK: mcrr p7, #1, r5, r4, c1 @ encoding: [0x44,0xec,0x11,0x57] + mcrr p7, #1, r5, r4, c1 + +@ CHECK: mrrc p7, #1, r5, r4, c1 @ encoding: [0x54,0xec,0x11,0x57] + mrrc p7, #1, r5, r4, c1 +