Index: include/llvm/IR/IntrinsicsARM.td =================================================================== --- include/llvm/IR/IntrinsicsARM.td +++ include/llvm/IR/IntrinsicsARM.td @@ -78,6 +78,24 @@ //===----------------------------------------------------------------------===// // Coprocessor +def int_arm_ldc : GCCBuiltin<"__builtin_arm_ldc">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>; +def int_arm_ldcl : GCCBuiltin<"__builtin_arm_ldcl">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>; +def int_arm_ldc2 : GCCBuiltin<"__builtin_arm_ldc2">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>; +def int_arm_ldc2l : GCCBuiltin<"__builtin_arm_ldc2l">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>; + +def int_arm_stc : GCCBuiltin<"__builtin_arm_stc">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>; +def int_arm_stcl : GCCBuiltin<"__builtin_arm_stcl">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>; +def int_arm_stc2 : GCCBuiltin<"__builtin_arm_stc2">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>; +def int_arm_stc2l : GCCBuiltin<"__builtin_arm_stc2l">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>; + // Move to coprocessor def int_arm_mcr : GCCBuiltin<"__builtin_arm_mcr">, Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, Index: lib/Target/ARM/ARMInstrInfo.td =================================================================== --- lib/Target/ARM/ARMInstrInfo.td +++ lib/Target/ARM/ARMInstrInfo.td @@ -4853,21 +4853,21 @@ } class ACI + list pattern, IndexMode im = IndexModeNone> : I { + opc, asm, "", pattern> { let Inst{27-25} = 0b110; } class ACInoP + list pattern, IndexMode im = IndexModeNone> : InoP { + opc, asm, "", pattern> { let Inst{31-28} = 0b1111; let Inst{27-25} = 0b110; } -multiclass LdStCop { +multiclass LdStCop pattern> { def _OFFSET : ACI<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr), - asm, "\t$cop, $CRd, $addr"> { + asm, "\t$cop, $CRd, $addr", pattern> { bits<13> addr; bits<4> cop; bits<4> CRd; @@ -4883,7 +4883,7 @@ let DecoderMethod = "DecodeCopMemInstruction"; } def _PRE : ACI<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5_pre:$addr), - asm, "\t$cop, $CRd, $addr!", IndexModePre> { + asm, "\t$cop, $CRd, $addr!", [], IndexModePre> { bits<13> addr; bits<4> cop; bits<4> CRd; @@ -4900,7 +4900,7 @@ } def _POST: ACI<(outs), (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr, postidx_imm8s4:$offset), - asm, "\t$cop, $CRd, $addr, $offset", IndexModePost> { + asm, "\t$cop, $CRd, $addr, $offset", [], IndexModePost> { bits<9> offset; bits<4> addr; bits<4> cop; @@ -4919,7 +4919,7 @@ def _OPTION : ACI<(outs), (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr, coproc_option_imm:$option), - asm, "\t$cop, $CRd, $addr, $option"> { + asm, "\t$cop, $CRd, $addr, $option", []> { bits<8> option; bits<4> addr; bits<4> cop; @@ -4936,9 +4936,9 @@ let DecoderMethod = "DecodeCopMemInstruction"; } } -multiclass LdSt2Cop { +multiclass LdSt2Cop pattern> { def _OFFSET : ACInoP<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr), - asm, "\t$cop, $CRd, $addr"> { + asm, "\t$cop, $CRd, $addr", pattern> { bits<13> addr; bits<4> cop; bits<4> CRd; @@ -4954,7 +4954,7 @@ let DecoderMethod = "DecodeCopMemInstruction"; } def _PRE : ACInoP<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5_pre:$addr), - asm, "\t$cop, $CRd, $addr!", IndexModePre> { + asm, "\t$cop, $CRd, $addr!", [], IndexModePre> { bits<13> addr; bits<4> cop; bits<4> CRd; @@ -4971,7 +4971,7 @@ } def _POST: ACInoP<(outs), (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr, postidx_imm8s4:$offset), - asm, "\t$cop, $CRd, $addr, $offset", IndexModePost> { + asm, "\t$cop, $CRd, $addr, $offset", [], IndexModePost> { bits<9> offset; bits<4> addr; bits<4> cop; @@ -4990,7 +4990,7 @@ def _OPTION : ACInoP<(outs), (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr, coproc_option_imm:$option), - asm, "\t$cop, $CRd, $addr, $option"> { + asm, "\t$cop, $CRd, $addr, $option", []> { bits<8> option; bits<4> addr; bits<4> cop; @@ -5008,14 +5008,15 @@ } } -defm LDC : LdStCop <1, 0, "ldc">; -defm LDCL : LdStCop <1, 1, "ldcl">; -defm STC : LdStCop <0, 0, "stc">; -defm STCL : LdStCop <0, 1, "stcl">; -defm LDC2 : LdSt2Cop<1, 0, "ldc2">, Requires<[PreV8]>; -defm LDC2L : LdSt2Cop<1, 1, "ldc2l">, Requires<[PreV8]>; -defm STC2 : LdSt2Cop<0, 0, "stc2">, Requires<[PreV8]>; -defm STC2L : LdSt2Cop<0, 1, "stc2l">, Requires<[PreV8]>; +defm LDC : LdStCop <1, 0, "ldc", [(int_arm_ldc imm:$cop, imm:$CRd, addrmode5:$addr)]>; +defm LDCL : LdStCop <1, 1, "ldcl", [(int_arm_ldcl imm:$cop, imm:$CRd, addrmode5:$addr)]>; +defm LDC2 : LdSt2Cop<1, 0, "ldc2", [(int_arm_ldc2 imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[PreV8]>; +defm LDC2L : LdSt2Cop<1, 1, "ldc2l", [(int_arm_ldc2l imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[PreV8]>; + +defm STC : LdStCop <0, 0, "stc", [(int_arm_stc imm:$cop, imm:$CRd, addrmode5:$addr)]>; +defm STCL : LdStCop <0, 1, "stcl", [(int_arm_stcl imm:$cop, imm:$CRd, addrmode5:$addr)]>; +defm STC2 : LdSt2Cop<0, 0, "stc2", [(int_arm_stc2 imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[PreV8]>; +defm STC2L : LdSt2Cop<0, 1, "stc2l", [(int_arm_stc2l imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[PreV8]>; //===----------------------------------------------------------------------===// // Move between coprocessor and ARM core register. Index: lib/Target/ARM/ARMInstrThumb2.td =================================================================== --- lib/Target/ARM/ARMInstrThumb2.td +++ lib/Target/ARM/ARMInstrThumb2.td @@ -3917,16 +3917,16 @@ //===----------------------------------------------------------------------===// // Coprocessor load/store -- for disassembly only // -class T2CI op31_28, dag oops, dag iops, string opc, string asm> - : T2I { +class T2CI op31_28, dag oops, dag iops, string opc, string asm, list pattern> + : T2I { let Inst{31-28} = op31_28; let Inst{27-25} = 0b110; } -multiclass t2LdStCop op31_28, bit load, bit Dbit, string asm> { +multiclass t2LdStCop op31_28, bit load, bit Dbit, string asm, list pattern> { def _OFFSET : T2CI { + asm, "\t$cop, $CRd, $addr", pattern> { bits<13> addr; bits<4> cop; bits<4> CRd; @@ -3943,7 +3943,7 @@ } def _PRE : T2CI { + asm, "\t$cop, $CRd, $addr!", []> { bits<13> addr; bits<4> cop; bits<4> CRd; @@ -3961,7 +3961,7 @@ def _POST: T2CI { + asm, "\t$cop, $CRd, $addr, $offset", []> { bits<9> offset; bits<4> addr; bits<4> cop; @@ -3980,7 +3980,7 @@ def _OPTION : T2CI { + asm, "\t$cop, $CRd, $addr, $option", []> { bits<8> option; bits<4> addr; bits<4> cop; @@ -3998,14 +3998,15 @@ } } -defm t2LDC : t2LdStCop<0b1110, 1, 0, "ldc">; -defm t2LDCL : t2LdStCop<0b1110, 1, 1, "ldcl">; -defm t2STC : t2LdStCop<0b1110, 0, 0, "stc">; -defm t2STCL : t2LdStCop<0b1110, 0, 1, "stcl">; -defm t2LDC2 : t2LdStCop<0b1111, 1, 0, "ldc2">, Requires<[PreV8,IsThumb2]>; -defm t2LDC2L : t2LdStCop<0b1111, 1, 1, "ldc2l">, Requires<[PreV8,IsThumb2]>; -defm t2STC2 : t2LdStCop<0b1111, 0, 0, "stc2">, Requires<[PreV8,IsThumb2]>; -defm t2STC2L : t2LdStCop<0b1111, 0, 1, "stc2l">, Requires<[PreV8,IsThumb2]>; +defm t2LDC : t2LdStCop<0b1110, 1, 0, "ldc", [(int_arm_ldc imm:$cop, imm:$CRd, addrmode5:$addr)]>; +defm t2LDCL : t2LdStCop<0b1110, 1, 1, "ldcl", [(int_arm_ldcl imm:$cop, imm:$CRd, addrmode5:$addr)]>; +defm t2LDC2 : t2LdStCop<0b1111, 1, 0, "ldc2", [(int_arm_ldc2 imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[PreV8,IsThumb2]>; +defm t2LDC2L : t2LdStCop<0b1111, 1, 1, "ldc2l", [(int_arm_ldc2l imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[PreV8,IsThumb2]>; + +defm t2STC : t2LdStCop<0b1110, 0, 0, "stc", [(int_arm_stc imm:$cop, imm:$CRd, addrmode5:$addr)]>; +defm t2STCL : t2LdStCop<0b1110, 0, 1, "stcl", [(int_arm_stcl imm:$cop, imm:$CRd, addrmode5:$addr)]>; +defm t2STC2 : t2LdStCop<0b1111, 0, 0, "stc2", [(int_arm_stc2 imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[PreV8,IsThumb2]>; +defm t2STC2L : t2LdStCop<0b1111, 0, 1, "stc2l", [(int_arm_stc2l imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[PreV8,IsThumb2]>; //===----------------------------------------------------------------------===// Index: test/CodeGen/ARM/intrinsics-coprocessor.ll =================================================================== --- test/CodeGen/ARM/intrinsics-coprocessor.ll +++ test/CodeGen/ARM/intrinsics-coprocessor.ll @@ -1,27 +1,59 @@ ; RUN: llc < %s -mtriple=armv7-eabi -mcpu=cortex-a8 | FileCheck %s ; RUN: llc < %s -march=thumb -mtriple=thumbv7-eabi -mcpu=cortex-a8 | FileCheck %s -define void @coproc() nounwind { +define void @coproc(i8* %i) nounwind { entry: - ; CHECK: mrc p7, #1, r0, c1, c1, #4 + ; CHECK: mrc p7, #1, r{{[0-9]+}}, c1, c1, #4 %0 = tail call i32 @llvm.arm.mrc(i32 7, i32 1, i32 1, i32 1, i32 4) nounwind - ; CHECK: mcr p7, #1, r0, c1, c1, #4 + ; CHECK: mcr p7, #1, r{{[0-9]+}}, c1, c1, #4 tail call void @llvm.arm.mcr(i32 7, i32 1, i32 %0, i32 1, i32 1, i32 4) nounwind - ; CHECK: mrc2 p7, #1, r1, c1, c1, #4 + ; CHECK: mrc2 p7, #1, r{{[0-9]+}}, c1, c1, #4 %1 = tail call i32 @llvm.arm.mrc2(i32 7, i32 1, i32 1, i32 1, i32 4) nounwind - ; CHECK: mcr2 p7, #1, r1, c1, c1, #4 + ; CHECK: mcr2 p7, #1, r{{[0-9]+}}, c1, c1, #4 tail call void @llvm.arm.mcr2(i32 7, i32 1, i32 %1, i32 1, i32 1, i32 4) nounwind - ; CHECK: mcrr p7, #1, r0, r1, c1 + ; CHECK: mcrr p7, #1, r{{[0-9]+}}, r{{[0-9]+}}, c1 tail call void @llvm.arm.mcrr(i32 7, i32 1, i32 %0, i32 %1, i32 1) nounwind - ; CHECK: mcrr2 p7, #1, r0, r1, c1 + ; CHECK: mcrr2 p7, #1, r{{[0-9]+}}, r{{[0-9]+}}, c1 tail call void @llvm.arm.mcrr2(i32 7, i32 1, i32 %0, i32 %1, i32 1) nounwind ; CHECK: cdp p7, #3, c1, c1, c1, #5 tail call void @llvm.arm.cdp(i32 7, i32 3, i32 1, i32 1, i32 1, i32 5) nounwind ; CHECK: cdp2 p7, #3, c1, c1, c1, #5 tail call void @llvm.arm.cdp2(i32 7, i32 3, i32 1, i32 1, i32 1, i32 5) nounwind + ; CHECK: ldc p7, c3, [r{{[0-9]+}}] + tail call void @llvm.arm.ldc(i32 7, i32 3, i8* %i) nounwind + ; CHECK: ldcl p7, c3, [r{{[0-9]+}}] + tail call void @llvm.arm.ldcl(i32 7, i32 3, i8* %i) nounwind + ; CHECK: ldc2 p7, c3, [r{{[0-9]+}}] + tail call void @llvm.arm.ldc2(i32 7, i32 3, i8* %i) nounwind + ; CHECK: ldc2l p7, c3, [r{{[0-9]+}}] + tail call void @llvm.arm.ldc2l(i32 7, i32 3, i8* %i) nounwind + ; CHECK: stc p7, c3, [r{{[0-9]+}}] + tail call void @llvm.arm.stc(i32 7, i32 3, i8* %i) nounwind + ; CHECK: stcl p7, c3, [r{{[0-9]+}}] + tail call void @llvm.arm.stcl(i32 7, i32 3, i8* %i) nounwind + ; CHECK: stc2 p7, c3, [r{{[0-9]+}}] + tail call void @llvm.arm.stc2(i32 7, i32 3, i8* %i) nounwind + ; CHECK: stc2l p7, c3, [r{{[0-9]+}}] + tail call void @llvm.arm.stc2l(i32 7, i32 3, i8* %i) nounwind ret void } +declare void @llvm.arm.ldc(i32, i32, i8*) nounwind + +declare void @llvm.arm.ldcl(i32, i32, i8*) nounwind + +declare void @llvm.arm.ldc2(i32, i32, i8*) nounwind + +declare void @llvm.arm.ldc2l(i32, i32, i8*) nounwind + +declare void @llvm.arm.stc(i32, i32, i8*) nounwind + +declare void @llvm.arm.stcl(i32, i32, i8*) nounwind + +declare void @llvm.arm.stc2(i32, i32, i8*) nounwind + +declare void @llvm.arm.stc2l(i32, i32, i8*) nounwind + declare void @llvm.arm.cdp2(i32, i32, i32, i32, i32, i32) nounwind declare void @llvm.arm.cdp(i32, i32, i32, i32, i32, i32) nounwind Index: test/CodeGen/ARM/ldc2l.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/ldc2l.ll @@ -0,0 +1,11 @@ +; RUN: not llc < %s -mtriple=armv8-eabi 2>&1 | FileCheck %s +; RUN: not llc < %s -mtriple=thumbv8-eabi 2>&1 | FileCheck %s + +; CHECK: LLVM ERROR: Cannot select: intrinsic %llvm.arm.ldc2l +define void @ldc2l(i8* %i) nounwind { +entry: + call void @llvm.arm.ldc2l(i32 1, i32 2, i8* %i) nounwind + ret void +} + +declare void @llvm.arm.ldc2l(i32, i32, i8*) nounwind Index: test/CodeGen/ARM/stc2.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/stc2.ll @@ -0,0 +1,11 @@ +; RUN: not llc < %s -mtriple=armv8-eabi 2>&1 | FileCheck %s +; RUN: not llc < %s -mtriple=thumbv8-eabi 2>&1 | FileCheck %s + +; CHECK: LLVM ERROR: Cannot select: intrinsic %llvm.arm.stc2 +define void @stc2(i8* %i) nounwind { +entry: + call void @llvm.arm.stc2(i32 1, i32 2, i8* %i) nounwind + ret void +} + +declare void @llvm.arm.stc2(i32, i32, i8*) nounwind