case ISD::Constant: {
unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
bool UseCP = true;
- if (Subtarget->isThumb()) {
- if (Subtarget->hasThumb2())
- // Thumb2 has the MOVT instruction, so all immediates can
- // be done with MOV + MOVT, at worst.
- UseCP = 0;
- else
+ if (Subtarget->hasThumb2())
+ // Thumb2-aware targets have the MOVT instruction, so all immediates can
+ // be done with MOV + MOVT, at worst.
+ UseCP = 0;
+ else {
+ if (Subtarget->isThumb()) {
UseCP = (Val > 255 && // MOV
~Val > 255 && // MOV + MVN
!ARM_AM::isThumbImmShiftedVal(Val)); // MOV + LSL
- } else
- UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV
- ARM_AM::getSOImmVal(~Val) == -1 && // MVN
- !ARM_AM::isSOImmTwoPartVal(Val)); // two instrs.
+ } else
+ UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV
+ ARM_AM::getSOImmVal(~Val) == -1 && // MVN
+ !ARM_AM::isSOImmTwoPartVal(Val)); // two instrs.
+ }
+
if (UseCP) {
SDValue CPIdx =
CurDAG->getTargetConstantPool(ConstantInt::get(
let PrintMethod = "printBitfieldInvMaskImmOperand";
}
+/// Split a 32-bit immediate into two 16 bit parts.
+def lo16 : SDNodeXForm<imm, [{
+ return CurDAG->getTargetConstant((uint32_t)N->getZExtValue() & 0xffff,
+ MVT::i32);
+}]>;
+
+def hi16 : SDNodeXForm<imm, [{
+ return CurDAG->getTargetConstant((uint32_t)N->getZExtValue() >> 16, MVT::i32);
+}]>;
+
+def lo16AllZero : PatLeaf<(i32 imm), [{
+ // Returns true if all low 16-bits are 0.
+ return (((uint32_t)N->getZExtValue()) & 0xFFFFUL) == 0;
+ }], hi16>;
+
+/// imm0_65535 predicate - True if the 32-bit immediate is in the range
+/// [0.65535].
+def imm0_65535 : PatLeaf<(i32 imm), [{
+ return (uint32_t)N->getZExtValue() < 65536;
+}]>;
+
class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
class UnOpFrag <dag res> : PatFrag<(ops node:$Src), res>;
let neverHasSideEffects = 1 in
def MOVr : AsI1<0b1101, (outs GPR:$dst), (ins GPR:$src), DPFrm, IIC_iMOVr,
- "mov", " $dst, $src", []>, UnaryDP;
+ "mov", " $dst, $src", []>, UnaryDP;
def MOVs : AsI1<0b1101, (outs GPR:$dst), (ins so_reg:$src),
- DPSoRegFrm, IIC_iMOVsr,
- "mov", " $dst, $src", [(set GPR:$dst, so_reg:$src)]>, UnaryDP;
+ DPSoRegFrm, IIC_iMOVsr,
+ "mov", " $dst, $src", [(set GPR:$dst, so_reg:$src)]>, UnaryDP;
let isReMaterializable = 1, isAsCheapAsAMove = 1 in
def MOVi : AsI1<0b1101, (outs GPR:$dst), (ins so_imm:$src), DPFrm, IIC_iMOVi,
- "mov", " $dst, $src", [(set GPR:$dst, so_imm:$src)]>, UnaryDP {
- let Inst{25} = 1;
+ "mov", " $dst, $src", [(set GPR:$dst, so_imm:$src)]>, UnaryDP {
+ let Inst{25} = 1;
+}
+
+let isReMaterializable = 1, isAsCheapAsAMove = 1 in
+def MOVi16 : AI1<0b1000, (outs GPR:$dst), (ins i32imm:$src),
+ DPFrm, IIC_iMOVi,
+ "movw", " $dst, $src",
+ [(set GPR:$dst, imm0_65535:$src)]>,
+ Requires<[IsARM, HasV6T2]> {
+ let Inst{25} = 1;
+}
+
+let isReMaterializable = 1, isAsCheapAsAMove = 1,
+ Constraints = "$src = $dst" in
+def MOVTi16 : AI1<0b1010, (outs GPR:$dst), (ins GPR:$src, i32imm:$imm),
+ DPFrm, IIC_iMOVi,
+ "movt", " $dst, $imm",
+ [(set GPR:$dst,
+ (or (and GPR:$src, 0xffff),
+ lo16AllZero:$imm))]>, UnaryDP,
+ Requires<[IsARM, HasV6T2]> {
+ let Inst{25} = 1;
}
let Uses = [CPSR] in
(EORri (EORri GPR:$LHS, (so_imm2part_1 imm:$RHS)),
(so_imm2part_2 imm:$RHS))>;
+def : ARMPat<(i32 imm:$src),
+ (MOVTi16 (MOVi16 (lo16 imm:$src)), (hi16 imm:$src))>,
+ Requires<[IsARM, HasV6T2]>;
+
// TODO: add,sub,and, 3-instr forms?
return (uint32_t)(-N->getZExtValue()) < 255;
}], imm_neg_XFORM>;
-/// imm0_65535 predicate - True if the 32-bit immediate is in the range
-/// [0.65535].
-def imm0_65535 : PatLeaf<(i32 imm), [{
- return (uint32_t)N->getZExtValue() < 65536;
-}]>;
-
-/// Split a 32-bit immediate into two 16 bit parts.
-def t2_lo16 : SDNodeXForm<imm, [{
- return CurDAG->getTargetConstant((uint32_t)N->getZExtValue() & 0xffff,
- MVT::i32);
-}]>;
-
-def t2_hi16 : SDNodeXForm<imm, [{
- return CurDAG->getTargetConstant((uint32_t)N->getZExtValue() >> 16, MVT::i32);
-}]>;
-
-def t2_lo16AllZero : PatLeaf<(i32 imm), [{
- // Returns true if all low 16-bits are 0.
- return (((uint32_t)N->getZExtValue()) & 0xFFFFUL) == 0;
- }], t2_hi16>;
-
-
// Define Thumb2 specific addressing modes.
// t2addrmode_imm12 := reg + imm12
"movw", " $dst, $src",
[(set GPR:$dst, imm0_65535:$src)]>;
-// FIXME: Also available in ARM mode.
let Constraints = "$src = $dst" in
def t2MOVTi16 : T2sI<(outs GPR:$dst), (ins GPR:$src, i32imm:$imm), IIC_iMOVi,
"movt", " $dst, $imm",
[(set GPR:$dst,
- (or (and GPR:$src, 0xffff), t2_lo16AllZero:$imm))]>;
+ (or (and GPR:$src, 0xffff), lo16AllZero:$imm))]>;
//===----------------------------------------------------------------------===//
// Extend Instructions.
// Large immediate handling.
def : T2Pat<(i32 imm:$src),
- (t2MOVTi16 (t2MOVi16 (t2_lo16 imm:$src)), (t2_hi16 imm:$src))>;
+ (t2MOVTi16 (t2MOVi16 (lo16 imm:$src)), (hi16 imm:$src))>;