Newer
Older
Evan Cheng
committed
defm t2CMP : T2I_cmp_is<"cmp",
BinOpFrag<(ARMcmp node:$LHS, node:$RHS)>>;
David Goodwin
committed
defm t2CMPz : T2I_cmp_is<"cmp",
BinOpFrag<(ARMcmpZ node:$LHS, node:$RHS)>>;
Evan Cheng
committed
defm t2CMN : T2I_cmp_is<"cmn",
BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>;
David Goodwin
committed
defm t2CMNz : T2I_cmp_is<"cmn",
BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))>>;
Evan Cheng
committed
def : T2Pat<(ARMcmp GPR:$src, t2_so_imm_neg:$imm),
(t2CMNri GPR:$src, t2_so_imm_neg:$imm)>;
Evan Cheng
committed
David Goodwin
committed
def : T2Pat<(ARMcmpZ GPR:$src, t2_so_imm_neg:$imm),
Evan Cheng
committed
defm t2TST : T2I_cmp_is<"tst",
BinOpFrag<(ARMcmpZ (and node:$LHS, node:$RHS), 0)>>;
defm t2TEQ : T2I_cmp_is<"teq",
BinOpFrag<(ARMcmpZ (xor node:$LHS, node:$RHS), 0)>>;
Evan Cheng
committed
// A8.6.27 CBNZ, CBZ - Compare and branch on (non)zero.
// Short range conditional branch. Looks awesome for loops. Need to figure
// out how to use this one.
// Conditional moves
// FIXME: should be able to write a pattern for ARMcmov, but can't use
// a two-value operand where a dag node expects two operands. :(
David Goodwin
committed
def t2MOVCCr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true), IIC_iALU,
[/*(set GPR:$dst, (ARMcmov GPR:$false, GPR:$true, imm:$cc, CCR:$ccr))*/]>,
RegConstraint<"$false = $dst">;
David Goodwin
committed
def t2MOVCCi : T2I<(outs GPR:$dst), (ins GPR:$false, t2_so_imm:$true), IIC_iALU,
[/*(set GPR:$dst, (ARMcmov GPR:$false, t2_so_imm:$true, imm:$cc, CCR:$ccr))*/]>,
RegConstraint<"$false = $dst">;
Evan Cheng
committed
Evan Cheng
committed
def t2MOVCClsl : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs),
David Goodwin
committed
IIC_iALU, "lsl", ".w $dst, $true, $rhs", []>,
Evan Cheng
committed
RegConstraint<"$false = $dst">;
def t2MOVCClsr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs),
David Goodwin
committed
IIC_iALU, "lsr", ".w $dst, $true, $rhs", []>,
Evan Cheng
committed
RegConstraint<"$false = $dst">;
def t2MOVCCasr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs),
David Goodwin
committed
IIC_iALU, "asr", ".w $dst, $true, $rhs", []>,
Evan Cheng
committed
RegConstraint<"$false = $dst">;
def t2MOVCCror : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs),
David Goodwin
committed
IIC_iALU, "ror", ".w $dst, $true, $rhs", []>,
Evan Cheng
committed
RegConstraint<"$false = $dst">;
David Goodwin
committed
//===----------------------------------------------------------------------===//
// TLS Instructions
//
// __aeabi_read_tp preserves the registers r1-r3.
let isCall = 1,
Defs = [R0, R12, LR, CPSR] in {
David Goodwin
committed
def t2TPsoft : T2XI<(outs), (ins), IIC_Br,
David Goodwin
committed
"bl __aeabi_read_tp",
[(set R0, ARMthread_pointer)]>;
}
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
//===----------------------------------------------------------------------===//
// SJLJ Exception handling intrinsics
// eh_sjlj_setjmp() is a three instruction sequence to store the return
// address and save #0 in R0 for the non-longjmp case.
// Since by its nature we may be coming from some other function to get
// here, and we're using the stack frame for the containing function to
// save/restore registers, we can't keep anything live in regs across
// the eh_sjlj_setjmp(), else it will almost certainly have been tromped upon
// when we get here from a longjmp(). We force everthing out of registers
// except for our own input by listing the relevant registers in Defs. By
// doing so, we also cause the prologue/epilogue code to actively preserve
// all of the callee-saved resgisters, which is exactly what we want.
let Defs =
[ R0, R1, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR,
D0, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15,
D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30,
D31 ] in {
def t2Int_eh_sjlj_setjmp : Thumb2XI<(outs), (ins GPR:$src),
AddrModeNone, SizeSpecial, NoItinerary,
"str.w sp, [$src, #+8] @ eh_setjmp begin\n"
"\tadr ip, 0f\n"
"\torr ip, #1\n"
"\tstr.w ip, [$src, #+4]\n"
"\tmovs r0, #0\n"
"\tb 1f\n"
"0:\tmovs r0, #1 @ eh_setjmp end\n"
"1:\n", "",
[(set R0, (ARMeh_sjlj_setjmp GPR:$src))]>;
}
//===----------------------------------------------------------------------===//
// Control-Flow Instructions
//
// FIXME: remove when we have a way to marking a MI with these properties.
// FIXME: $dst1 should be a def. But the extra ops must be in the end of the
// operand list.
// FIXME: Should pc be an implicit operand like PICADD, etc?
let isReturn = 1, isTerminator = 1, mayLoad = 1 in
def t2LDM_RET : T2XI<(outs),
(ins addrmode4:$addr, pred:$p, reglist:$dst1, variable_ops),
IIC_iLoad, "ldm${addr:submode}${p}${addr:wide} $addr, $dst1",
let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
let isPredicable = 1 in
David Goodwin
committed
def t2B : T2XI<(outs), (ins brtarget:$target), IIC_Br,
[(br bb:$target)]>;
Evan Cheng
committed
let isNotDuplicable = 1, isIndirectBranch = 1 in {
def t2BR_JT :
Evan Cheng
committed
T2JTI<(outs),
(ins GPR:$target, GPR:$index, jt2block_operand:$jt, i32imm:$id),
David Goodwin
committed
IIC_Br, "mov pc, $target\n$jt",
Evan Cheng
committed
[(ARMbr2jt GPR:$target, GPR:$index, tjumptable:$jt, imm:$id)]>;
// FIXME: Add a non-pc based case that can be predicated.
Evan Cheng
committed
def t2TBB :
Evan Cheng
committed
(ins tb_addrmode:$index, jt2block_operand:$jt, i32imm:$id),
David Goodwin
committed
IIC_Br, "tbb $index\n$jt", []>;
Evan Cheng
committed
def t2TBH :
Evan Cheng
committed
(ins tb_addrmode:$index, jt2block_operand:$jt, i32imm:$id),
David Goodwin
committed
IIC_Br, "tbh $index\n$jt", []>;
Evan Cheng
committed
} // isNotDuplicable, isIndirectBranch
} // isBranch, isTerminator, isBarrier
// FIXME: should be able to write a pattern for ARMBrcond, but can't use
// a two-value operand where a dag node expects two operands. :(
let isBranch = 1, isTerminator = 1 in
David Goodwin
committed
def t2Bcc : T2I<(outs), (ins brtarget:$target), IIC_Br,
[/*(ARMbrcond bb:$target, imm:$cc)*/]>;
Evan Cheng
committed
// IT block
def t2IT : Thumb2XI<(outs), (ins it_pred:$cc, it_mask:$mask),
David Goodwin
committed
AddrModeNone, Size2Bytes, IIC_iALU,
Evan Cheng
committed
//===----------------------------------------------------------------------===//
// Non-Instruction Patterns
//
def : T2Pat<(ARMWrapper tglobaladdr :$dst), (t2LEApcrel tglobaladdr :$dst)>;
def : T2Pat<(ARMWrapper tconstpool :$dst), (t2LEApcrel tconstpool :$dst)>;
def : T2Pat<(ARMWrapperJT tjumptable:$dst, imm:$id),
(t2LEApcrelJT tjumptable:$dst, imm:$id)>;
Evan Cheng
committed
// Large immediate handling.
def : T2Pat<(i32 imm:$src),
(t2MOVTi16 (t2MOVi16 (t2_lo16 imm:$src)), (t2_hi16 imm:$src))>;