mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-16 08:49:52 +00:00
[ARM] Add backend support for load/store intrinsics.
Added support to map intrinsics __builtin_arm_{ldc,ldcl,ldc2,ldc2l,stc,stcl,stc2,stc2l} to their ARM instructions. Differential Revision: http://reviews.llvm.org/D20564 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@271271 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a8a5e74bf9
commit
c146d1a1e5
@ -78,6 +78,24 @@ def int_arm_vcvtru : Intrinsic<[llvm_float_ty], [llvm_anyfloat_ty],
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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,
|
||||
|
@ -4853,21 +4853,21 @@ def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1,
|
||||
}
|
||||
|
||||
class ACI<dag oops, dag iops, string opc, string asm,
|
||||
IndexMode im = IndexModeNone>
|
||||
list<dag> pattern, IndexMode im = IndexModeNone>
|
||||
: I<oops, iops, AddrModeNone, 4, im, BrFrm, NoItinerary,
|
||||
opc, asm, "", []> {
|
||||
opc, asm, "", pattern> {
|
||||
let Inst{27-25} = 0b110;
|
||||
}
|
||||
class ACInoP<dag oops, dag iops, string opc, string asm,
|
||||
IndexMode im = IndexModeNone>
|
||||
list<dag> pattern, IndexMode im = IndexModeNone>
|
||||
: InoP<oops, iops, AddrModeNone, 4, im, BrFrm, NoItinerary,
|
||||
opc, asm, "", []> {
|
||||
opc, asm, "", pattern> {
|
||||
let Inst{31-28} = 0b1111;
|
||||
let Inst{27-25} = 0b110;
|
||||
}
|
||||
multiclass LdStCop<bit load, bit Dbit, string asm> {
|
||||
multiclass LdStCop<bit load, bit Dbit, string asm, list<dag> 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 @@ multiclass LdStCop<bit load, bit Dbit, string asm> {
|
||||
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 @@ multiclass LdStCop<bit load, bit Dbit, string asm> {
|
||||
}
|
||||
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 @@ multiclass LdStCop<bit load, bit Dbit, string asm> {
|
||||
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 @@ multiclass LdStCop<bit load, bit Dbit, string asm> {
|
||||
let DecoderMethod = "DecodeCopMemInstruction";
|
||||
}
|
||||
}
|
||||
multiclass LdSt2Cop<bit load, bit Dbit, string asm> {
|
||||
multiclass LdSt2Cop<bit load, bit Dbit, string asm, list<dag> 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 @@ multiclass LdSt2Cop<bit load, bit Dbit, string asm> {
|
||||
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 @@ multiclass LdSt2Cop<bit load, bit Dbit, string asm> {
|
||||
}
|
||||
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 @@ multiclass LdSt2Cop<bit load, bit Dbit, string asm> {
|
||||
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 @@ multiclass LdSt2Cop<bit load, bit Dbit, string asm> {
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
|
@ -3917,16 +3917,16 @@ def t2ABS : PseudoInst<(outs rGPR:$dst), (ins rGPR:$src),
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Coprocessor load/store -- for disassembly only
|
||||
//
|
||||
class T2CI<bits<4> op31_28, dag oops, dag iops, string opc, string asm>
|
||||
: T2I<oops, iops, NoItinerary, opc, asm, []> {
|
||||
class T2CI<bits<4> op31_28, dag oops, dag iops, string opc, string asm, list<dag> pattern>
|
||||
: T2I<oops, iops, NoItinerary, opc, asm, pattern> {
|
||||
let Inst{31-28} = op31_28;
|
||||
let Inst{27-25} = 0b110;
|
||||
}
|
||||
|
||||
multiclass t2LdStCop<bits<4> op31_28, bit load, bit Dbit, string asm> {
|
||||
multiclass t2LdStCop<bits<4> op31_28, bit load, bit Dbit, string asm, list<dag> pattern> {
|
||||
def _OFFSET : T2CI<op31_28,
|
||||
(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;
|
||||
@ -3943,7 +3943,7 @@ multiclass t2LdStCop<bits<4> op31_28, bit load, bit Dbit, string asm> {
|
||||
}
|
||||
def _PRE : T2CI<op31_28,
|
||||
(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5_pre:$addr),
|
||||
asm, "\t$cop, $CRd, $addr!"> {
|
||||
asm, "\t$cop, $CRd, $addr!", []> {
|
||||
bits<13> addr;
|
||||
bits<4> cop;
|
||||
bits<4> CRd;
|
||||
@ -3961,7 +3961,7 @@ multiclass t2LdStCop<bits<4> op31_28, bit load, bit Dbit, string asm> {
|
||||
def _POST: T2CI<op31_28,
|
||||
(outs), (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
|
||||
postidx_imm8s4:$offset),
|
||||
asm, "\t$cop, $CRd, $addr, $offset"> {
|
||||
asm, "\t$cop, $CRd, $addr, $offset", []> {
|
||||
bits<9> offset;
|
||||
bits<4> addr;
|
||||
bits<4> cop;
|
||||
@ -3980,7 +3980,7 @@ multiclass t2LdStCop<bits<4> op31_28, bit load, bit Dbit, string asm> {
|
||||
def _OPTION : T2CI<op31_28, (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;
|
||||
@ -3998,14 +3998,15 @@ multiclass t2LdStCop<bits<4> op31_28, bit load, bit Dbit, string asm> {
|
||||
}
|
||||
}
|
||||
|
||||
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]>;
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -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
|
||||
|
11
test/CodeGen/ARM/ldc2l.ll
Normal file
11
test/CodeGen/ARM/ldc2l.ll
Normal file
@ -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
|
11
test/CodeGen/ARM/stc2.ll
Normal file
11
test/CodeGen/ARM/stc2.ll
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user