Index: llvm/trunk/lib/Target/ARM/ARM.td =================================================================== --- llvm/trunk/lib/Target/ARM/ARM.td +++ llvm/trunk/lib/Target/ARM/ARM.td @@ -261,6 +261,12 @@ "Don't use movt/movw pairs for 32-bit " "imms">; +def FeatureNoNegativeImmediates : SubtargetFeature<"no-neg-immediates", + "NegativeImmediates", "false", + "Convert immediates and instructions " + "to their negated or complemented " + "equivalent when the immediate does " + "not fit in the encoding.">; //===----------------------------------------------------------------------===// // ARM ISAa. Index: llvm/trunk/lib/Target/ARM/ARMInstrFormats.td =================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrFormats.td +++ llvm/trunk/lib/Target/ARM/ARMInstrFormats.td @@ -261,10 +261,19 @@ // Note: When EmitPriority == 1, the alias will be used for printing class ARMInstAlias : InstAlias, Requires<[IsARM]>; +class ARMInstSubst + : InstAlias, + Requires<[IsARM,UseNegativeImmediates]>; class tInstAlias : InstAlias, Requires<[IsThumb]>; +class tInstSubst + : InstAlias, + Requires<[IsThumb,UseNegativeImmediates]>; class t2InstAlias : InstAlias, Requires<[IsThumb2]>; +class t2InstSubst + : InstAlias, + Requires<[IsThumb2,UseNegativeImmediates]>; class VFP2InstAlias : InstAlias, Requires<[HasVFP2]>; class VFP2DPInstAlias Index: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td =================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td @@ -311,6 +311,11 @@ AssemblerPredicate<"FeatureNaClTrap", "NaCl">; def DontUseNaClTrap : Predicate<"!Subtarget->useNaClTrap()">; +def UseNegativeImmediates : + Predicate<"false">, + AssemblerPredicate<"!FeatureNoNegativeImmediates", + "NegativeImmediates">; + // FIXME: Eventually this will be just "hasV6T2Ops". def UseMovt : Predicate<"Subtarget->useMovt(*MF)">; def DontUseMovt : Predicate<"!Subtarget->useMovt(*MF)">; @@ -5790,33 +5795,49 @@ // "mov Rd, mod_imm_not" can be handled via "mvn" in assembly, just like // for isel. -def : ARMInstAlias<"mov${s}${p} $Rd, $imm", +def : ARMInstSubst<"mov${s}${p} $Rd, $imm", (MVNi rGPR:$Rd, mod_imm_not:$imm, pred:$p, cc_out:$s)>; -def : ARMInstAlias<"mvn${s}${p} $Rd, $imm", +def : ARMInstSubst<"mvn${s}${p} $Rd, $imm", (MOVi rGPR:$Rd, mod_imm_not:$imm, pred:$p, cc_out:$s)>; // Same for AND <--> BIC -def : ARMInstAlias<"bic${s}${p} $Rd, $Rn, $imm", +def : ARMInstSubst<"bic${s}${p} $Rd, $Rn, $imm", (ANDri GPR:$Rd, GPR:$Rn, mod_imm_not:$imm, pred:$p, cc_out:$s)>; -def : ARMInstAlias<"bic${s}${p} $Rdn, $imm", +def : ARMInstSubst<"bic${s}${p} $Rdn, $imm", (ANDri GPR:$Rdn, GPR:$Rdn, mod_imm_not:$imm, pred:$p, cc_out:$s)>; -def : ARMInstAlias<"and${s}${p} $Rd, $Rn, $imm", +def : ARMInstSubst<"and${s}${p} $Rd, $Rn, $imm", (BICri GPR:$Rd, GPR:$Rn, mod_imm_not:$imm, pred:$p, cc_out:$s)>; -def : ARMInstAlias<"and${s}${p} $Rdn, $imm", +def : ARMInstSubst<"and${s}${p} $Rdn, $imm", (BICri GPR:$Rdn, GPR:$Rdn, mod_imm_not:$imm, pred:$p, cc_out:$s)>; // Likewise, "add Rd, mod_imm_neg" -> sub -def : ARMInstAlias<"add${s}${p} $Rd, $Rn, $imm", +def : ARMInstSubst<"add${s}${p} $Rd, $Rn, $imm", (SUBri GPR:$Rd, GPR:$Rn, mod_imm_neg:$imm, pred:$p, cc_out:$s)>; -def : ARMInstAlias<"add${s}${p} $Rd, $imm", +def : ARMInstSubst<"add${s}${p} $Rd, $imm", (SUBri GPR:$Rd, GPR:$Rd, mod_imm_neg:$imm, pred:$p, cc_out:$s)>; +// Likewise, "sub Rd, mod_imm_neg" -> add +def : ARMInstSubst<"sub${s}${p} $Rd, $Rn, $imm", + (ADDri GPR:$Rd, GPR:$Rn, mod_imm_neg:$imm, pred:$p, cc_out:$s)>; +def : ARMInstSubst<"sub${s}${p} $Rd, $imm", + (ADDri GPR:$Rd, GPR:$Rd, mod_imm_neg:$imm, pred:$p, cc_out:$s)>; + + +def : ARMInstSubst<"adc${s}${p} $Rd, $Rn, $imm", + (SBCri GPR:$Rd, GPR:$Rn, mod_imm_not:$imm, pred:$p, cc_out:$s)>; +def : ARMInstSubst<"adc${s}${p} $Rdn, $imm", + (SBCri GPR:$Rdn, GPR:$Rdn, mod_imm_not:$imm, pred:$p, cc_out:$s)>; +def : ARMInstSubst<"sbc${s}${p} $Rd, $Rn, $imm", + (ADCri GPR:$Rd, GPR:$Rn, mod_imm_not:$imm, pred:$p, cc_out:$s)>; +def : ARMInstSubst<"sbc${s}${p} $Rdn, $imm", + (ADCri GPR:$Rdn, GPR:$Rdn, mod_imm_not:$imm, pred:$p, cc_out:$s)>; + // Same for CMP <--> CMN via mod_imm_neg -def : ARMInstAlias<"cmp${p} $Rd, $imm", +def : ARMInstSubst<"cmp${p} $Rd, $imm", (CMNri rGPR:$Rd, mod_imm_neg:$imm, pred:$p)>; -def : ARMInstAlias<"cmn${p} $Rd, $imm", +def : ARMInstSubst<"cmn${p} $Rd, $imm", (CMPri rGPR:$Rd, mod_imm_neg:$imm, pred:$p)>; // The shifter forms of the MOV instruction are aliased to the ASR, LSL, Index: llvm/trunk/lib/Target/ARM/ARMInstrThumb.td =================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb.td +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb.td @@ -32,6 +32,23 @@ return (uint32_t)-N->getZExtValue() < 8; }], imm_neg_XFORM>; +def ThumbModImmNeg1_7AsmOperand : AsmOperandClass { let Name = "ThumbModImmNeg1_7"; } +def mod_imm1_7_neg : Operand, PatLeaf<(imm), [{ + unsigned Value = -(unsigned)N->getZExtValue(); + return 0 < Value && Value < 8; + }], imm_neg_XFORM> { + let ParserMatchClass = ThumbModImmNeg1_7AsmOperand; +} + +def ThumbModImmNeg8_255AsmOperand : AsmOperandClass { let Name = "ThumbModImmNeg8_255"; } +def mod_imm8_255_neg : Operand, PatLeaf<(imm), [{ + unsigned Value = -(unsigned)N->getZExtValue(); + return 7 < Value && Value < 256; + }], imm_neg_XFORM> { + let ParserMatchClass = ThumbModImmNeg8_255AsmOperand; +} + + def imm0_255_comp : PatLeaf<(i32 imm), [{ return ~((uint32_t)N->getZExtValue()) < 256; }]>; @@ -402,9 +419,9 @@ let DecoderMethod = "DecodeThumbAddSPImm"; } -def : tInstAlias<"add${p} sp, $imm", +def : tInstSubst<"add${p} sp, $imm", (tSUBspi SP, t_imm0_508s4_neg:$imm, pred:$p)>; -def : tInstAlias<"add${p} sp, sp, $imm", +def : tInstSubst<"add${p} sp, sp, $imm", (tSUBspi SP, t_imm0_508s4_neg:$imm, pred:$p)>; // Can optionally specify SP as a three operand instruction. @@ -946,6 +963,12 @@ } } +def : tInstSubst<"sub${s}${p} $rd, $rn, $imm", + (tADDi3 tGPR:$rd, s_cc_out:$s, tGPR:$rn, mod_imm1_7_neg:$imm, pred:$p)>; +def : tInstSubst<"sub${s}${p} $rdn, $imm", + (tADDi8 tGPR:$rdn, s_cc_out:$s, mod_imm8_255_neg:$imm, pred:$p)>; + + // AND register let isCommutable = 1 in def tAND : // A8.6.12 @@ -1213,6 +1236,14 @@ [(set tGPR:$Rdn, (add tGPR:$Rn, imm8_255_neg:$imm8))]>, Sched<[WriteALU]>; +def : tInstSubst<"add${s}${p} $rd, $rn, $imm", + (tSUBi3 tGPR:$rd, s_cc_out:$s, tGPR:$rn, mod_imm1_7_neg:$imm, pred:$p)>; + + +def : tInstSubst<"add${s}${p} $rdn, $imm", + (tSUBi8 tGPR:$rdn, s_cc_out:$s, mod_imm8_255_neg:$imm, pred:$p)>; + + // Subtract register def tSUBrr : // A8.6.212 T1sIGenEncode<0b01101, (outs tGPR:$Rd), (ins tGPR:$Rn, tGPR:$Rm), Index: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td =================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td @@ -2079,6 +2079,19 @@ defm t2SBC : T2I_adde_sube_irs<0b1011, "sbc", ARMsube>; } +def : t2InstSubst<"adc${s}${p} $rd, $rn, $imm", + (t2SBCri rGPR:$rd, rGPR:$rn, t2_so_imm_not:$imm, pred:$p, s_cc_out:$s)>; +def : t2InstSubst<"sbc${s}${p} $rd, $rn, $imm", + (t2ADCri rGPR:$rd, rGPR:$rn, t2_so_imm_not:$imm, pred:$p, s_cc_out:$s)>; + +def : t2InstSubst<"add${s}${p}.w $rd, $rn, $imm", + (t2SUBri GPRnopc:$rd, GPRnopc:$rn, t2_so_imm_neg:$imm, pred:$p, s_cc_out:$s)>; +def : t2InstSubst<"addw${p} $rd, $rn, $imm", + (t2SUBri12 GPRnopc:$rd, GPR:$rn, t2_so_imm_neg:$imm, pred:$p)>; +def : t2InstSubst<"sub${s}${p}.w $rd, $rn, $imm", + (t2ADDri GPRnopc:$rd, GPRnopc:$rn, t2_so_imm_neg:$imm, pred:$p, s_cc_out:$s)>; +def : t2InstSubst<"subw${p} $rd, $rn, $imm", + (t2ADDri12 GPRnopc:$rd, GPR:$rn, t2_so_imm_neg:$imm, pred:$p)>; // RSB defm t2RSB : T2I_rbin_irs <0b1110, "rsb", sub>; @@ -4375,26 +4388,26 @@ pred:$p, cc_out:$s)>; // add w/ negative immediates is just a sub. -def : t2InstAlias<"add${s}${p} $Rd, $Rn, $imm", +def : t2InstSubst<"add${s}${p} $Rd, $Rn, $imm", (t2SUBri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm_neg:$imm, pred:$p, cc_out:$s)>; -def : t2InstAlias<"add${p} $Rd, $Rn, $imm", +def : t2InstSubst<"add${p} $Rd, $Rn, $imm", (t2SUBri12 GPRnopc:$Rd, GPR:$Rn, imm0_4095_neg:$imm, pred:$p)>; -def : t2InstAlias<"add${s}${p} $Rdn, $imm", +def : t2InstSubst<"add${s}${p} $Rdn, $imm", (t2SUBri GPRnopc:$Rdn, GPRnopc:$Rdn, t2_so_imm_neg:$imm, pred:$p, cc_out:$s)>; -def : t2InstAlias<"add${p} $Rdn, $imm", +def : t2InstSubst<"add${p} $Rdn, $imm", (t2SUBri12 GPRnopc:$Rdn, GPRnopc:$Rdn, imm0_4095_neg:$imm, pred:$p)>; -def : t2InstAlias<"add${s}${p}.w $Rd, $Rn, $imm", +def : t2InstSubst<"add${s}${p}.w $Rd, $Rn, $imm", (t2SUBri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm_neg:$imm, pred:$p, cc_out:$s)>; -def : t2InstAlias<"addw${p} $Rd, $Rn, $imm", +def : t2InstSubst<"addw${p} $Rd, $Rn, $imm", (t2SUBri12 GPRnopc:$Rd, GPR:$Rn, imm0_4095_neg:$imm, pred:$p)>; -def : t2InstAlias<"add${s}${p}.w $Rdn, $imm", +def : t2InstSubst<"add${s}${p}.w $Rdn, $imm", (t2SUBri GPRnopc:$Rdn, GPRnopc:$Rdn, t2_so_imm_neg:$imm, pred:$p, cc_out:$s)>; -def : t2InstAlias<"addw${p} $Rdn, $imm", +def : t2InstSubst<"addw${p} $Rdn, $imm", (t2SUBri12 GPRnopc:$Rdn, GPRnopc:$Rdn, imm0_4095_neg:$imm, pred:$p)>; @@ -4625,34 +4638,34 @@ // "mov Rd, t2_so_imm_not" can be handled via "mvn" in assembly, just like // for isel. -def : t2InstAlias<"mov${p} $Rd, $imm", +def : t2InstSubst<"mov${p} $Rd, $imm", (t2MVNi rGPR:$Rd, t2_so_imm_not:$imm, pred:$p, zero_reg)>; -def : t2InstAlias<"mvn${p} $Rd, $imm", - (t2MOVi rGPR:$Rd, t2_so_imm_not:$imm, pred:$p, zero_reg)>; +def : t2InstSubst<"mvn${s}${p} $Rd, $imm", + (t2MOVi rGPR:$Rd, t2_so_imm_not:$imm, pred:$p, s_cc_out:$s)>; // Same for AND <--> BIC -def : t2InstAlias<"bic${s}${p} $Rd, $Rn, $imm", +def : t2InstSubst<"bic${s}${p} $Rd, $Rn, $imm", (t2ANDri rGPR:$Rd, rGPR:$Rn, t2_so_imm_not:$imm, pred:$p, cc_out:$s)>; -def : t2InstAlias<"bic${s}${p} $Rdn, $imm", +def : t2InstSubst<"bic${s}${p} $Rdn, $imm", (t2ANDri rGPR:$Rdn, rGPR:$Rdn, t2_so_imm_not:$imm, pred:$p, cc_out:$s)>; -def : t2InstAlias<"and${s}${p} $Rd, $Rn, $imm", +def : t2InstSubst<"and${s}${p} $Rd, $Rn, $imm", (t2BICri rGPR:$Rd, rGPR:$Rn, t2_so_imm_not:$imm, pred:$p, cc_out:$s)>; -def : t2InstAlias<"and${s}${p} $Rdn, $imm", +def : t2InstSubst<"and${s}${p} $Rdn, $imm", (t2BICri rGPR:$Rdn, rGPR:$Rdn, t2_so_imm_not:$imm, pred:$p, cc_out:$s)>; // Likewise, "add Rd, t2_so_imm_neg" -> sub -def : t2InstAlias<"add${s}${p} $Rd, $Rn, $imm", +def : t2InstSubst<"add${s}${p} $Rd, $Rn, $imm", (t2SUBri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm_neg:$imm, pred:$p, cc_out:$s)>; -def : t2InstAlias<"add${s}${p} $Rd, $imm", +def : t2InstSubst<"add${s}${p} $Rd, $imm", (t2SUBri GPRnopc:$Rd, GPRnopc:$Rd, t2_so_imm_neg:$imm, pred:$p, cc_out:$s)>; // Same for CMP <--> CMN via t2_so_imm_neg -def : t2InstAlias<"cmp${p} $Rd, $imm", +def : t2InstSubst<"cmp${p} $Rd, $imm", (t2CMNri rGPR:$Rd, t2_so_imm_neg:$imm, pred:$p)>; -def : t2InstAlias<"cmn${p} $Rd, $imm", +def : t2InstSubst<"cmn${p} $Rd, $imm", (t2CMPri rGPR:$Rd, t2_so_imm_neg:$imm, pred:$p)>; Index: llvm/trunk/lib/Target/ARM/ARMSubtarget.h =================================================================== --- llvm/trunk/lib/Target/ARM/ARMSubtarget.h +++ llvm/trunk/lib/Target/ARM/ARMSubtarget.h @@ -351,6 +351,10 @@ /// UseSjLjEH - If true, the target uses SjLj exception handling (e.g. iOS). bool UseSjLjEH = false; + /// Implicitly convert an instruction to a different one if its immediates + /// cannot be encoded. For example, ADD r0, r1, #FFFFFFFF -> SUB r0, r1, #1. + bool NegativeImmediates = true; + /// stackAlignment - The minimum alignment known to hold of the stack frame on /// entry to the function and which must be maintained by every function. unsigned stackAlignment = 4; Index: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -1245,6 +1245,20 @@ return ARM_AM::getSOImmVal(Value) == -1 && ARM_AM::getSOImmVal(-Value) != -1; } + bool isThumbModImmNeg1_7() const { + if (!isImm()) return false; + const MCConstantExpr *CE = dyn_cast(getImm()); + if (!CE) return false; + int32_t Value = -(int32_t)CE->getValue(); + return 0 < Value && Value < 8; + } + bool isThumbModImmNeg8_255() const { + if (!isImm()) return false; + const MCConstantExpr *CE = dyn_cast(getImm()); + if (!CE) return false; + int32_t Value = -(int32_t)CE->getValue(); + return 7 < Value && Value < 256; + } bool isConstantPoolImm() const { return Kind == k_ConstantPoolImmediate; } bool isBitfield() const { return Kind == k_BitfieldDescriptor; } bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; } @@ -2035,6 +2049,20 @@ Inst.addOperand(MCOperand::createImm(Enc)); } + void addThumbModImmNeg8_255Operands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + const MCConstantExpr *CE = dyn_cast(getImm()); + uint32_t Val = -CE->getValue(); + Inst.addOperand(MCOperand::createImm(Val)); + } + + void addThumbModImmNeg1_7Operands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + const MCConstantExpr *CE = dyn_cast(getImm()); + uint32_t Val = -CE->getValue(); + Inst.addOperand(MCOperand::createImm(Val)); + } + void addBitfieldOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); // Munge the lsb/width into a bitfield mask. @@ -2141,7 +2169,7 @@ // The operand is actually a t2_so_imm, but we have its bitwise // negation in the assembly source, so twiddle it here. const MCConstantExpr *CE = dyn_cast(getImm()); - Inst.addOperand(MCOperand::createImm(~CE->getValue())); + Inst.addOperand(MCOperand::createImm(~(uint32_t)CE->getValue())); } void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const { @@ -2149,7 +2177,7 @@ // The operand is actually a t2_so_imm, but we have its // negation in the assembly source, so twiddle it here. const MCConstantExpr *CE = dyn_cast(getImm()); - Inst.addOperand(MCOperand::createImm(-CE->getValue())); + Inst.addOperand(MCOperand::createImm(-(uint32_t)CE->getValue())); } void addImm0_4095NegOperands(MCInst &Inst, unsigned N) const { Index: llvm/trunk/test/MC/ARM/negative-immediates-fail.s =================================================================== --- llvm/trunk/test/MC/ARM/negative-immediates-fail.s +++ llvm/trunk/test/MC/ARM/negative-immediates-fail.s @@ -0,0 +1,13 @@ +# RUN: not llvm-mc -triple armv7 %s 2>&1| FileCheck %s + +.arm + +ADC r0, r1, #0xFFFFFEEE +# CHECK: error: invalid operand for instruction +ADC r0, r1, #0xABFEABFF +# CHECK: error: invalid operand for instruction +ADC r0, r1, #0xFFFFFE02 +# CHECK: error: invalid operand for instruction + +ADD.W r0, r0, #0xFF01FF01 +# CHECK: error: invalid operand for instruction Index: llvm/trunk/test/MC/ARM/negative-immediates-thumb1-fail.s =================================================================== --- llvm/trunk/test/MC/ARM/negative-immediates-thumb1-fail.s +++ llvm/trunk/test/MC/ARM/negative-immediates-thumb1-fail.s @@ -0,0 +1,15 @@ +# RUN: not llvm-mc -triple thumbv7 -mcpu=cortex-m0 %s 2>&1 | FileCheck %s + +.thumb + +ADDs r1, r0, #0xFFFFFFF5 +# CHECK: error: instruction requires: arm-mode + +ADDs r0, #0xFFFFFEFF +# CHECK: error: invalid operand for instruction + +SUBs r1, r0, #0xFFFFFFF5 +# CHECK: error: instruction requires: arm-mode + +SUBs r0, #0xFFFFFEFF +# CHECK: error: invalid operand for instruction Index: llvm/trunk/test/MC/ARM/negative-immediates-thumb1.s =================================================================== --- llvm/trunk/test/MC/ARM/negative-immediates-thumb1.s +++ llvm/trunk/test/MC/ARM/negative-immediates-thumb1.s @@ -0,0 +1,19 @@ +# RUN: llvm-mc -triple thumbv7 -mcpu=cortex-m0 %s -show-encoding | FileCheck %s +# RUN: not llvm-mc -triple thumbv7 -mcpu=cortex-m0 %s -show-encoding -mattr=+no-neg-immediates 2>&1 | FileCheck %s -check-prefix=CHECK-DISABLED + +.thumb + + ADDs r1, r0, #0xFFFFFFF9 +# CHECK: subs r1, r0, #7 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates + ADDs r0, #0xFFFFFF01 +# CHECK: subs r0, #255 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates + + SUBs r0, #0xFFFFFF01 +# CHECK: adds r0, #255 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates + + SUBs r1, r0, #0xFFFFFFF9 +# CHECK: adds r1, r0, #7 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates Index: llvm/trunk/test/MC/ARM/negative-immediates.s =================================================================== --- llvm/trunk/test/MC/ARM/negative-immediates.s +++ llvm/trunk/test/MC/ARM/negative-immediates.s @@ -0,0 +1,128 @@ +# RUN: llvm-mc -triple armv7 %s -show-encoding | FileCheck %s +# RUN: not llvm-mc -triple armv7 %s -show-encoding -mattr=+no-neg-immediates 2>&1 | FileCheck %s -check-prefix=CHECK-DISABLED + +.arm + + ADC r0, r1, #0xFFFFFF00 +# CHECK: sbc r0, r1, #255 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: ADC + ADC r0, r1, #0xFFFFFE03 +# CHECK: sbc r0, r1, #508 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: ADC + ADD r0, r1, #0xFFFFFF01 +# CHECK: sub r0, r1, #255 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: ADD + AND r0, r1, #0xFFFFFF00 +# CHECK: bic r0, r1, #255 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: AND + BIC r0, r1, #0xFFFFFF00 +# CHECK: and r0, r1, #255 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: BIC + CMP r0, #0xFFFFFF01 +# CHECK: cmn r0, #255 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: CMP + CMN r0, #0xFFFFFF01 +# CHECK: cmp r0, #255 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: CMN + MOV r0, #0xFFFFFF00 +# CHECK: mvn r0, #255 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: MOV + MVN r0, #0xFFFFFF00 +# CHECK: mov r0, #255 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: MVN + SBC r0, r1, #0xFFFFFF00 +# CHECK: adc r0, r1, #255 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: SBC + SUB r0, r1, #0xFFFFFF01 +# CHECK: add r0, r1, #255 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: SUB + +.thumb + + ADC r0, r1, #0xFFFFFF00 +# CHECK: sbc r0, r1, #255 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: ADC + ADC r0, r1, #0xFFFF00FF +# CHECK: sbc r0, r1, #65280 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: ADC + ADC r0, r1, #0xFFFEFFFE +# CHECK: sbc r0, r1, #65537 @ encoding: [0x61,0xf1,0x01,0x10] +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: ADC + ADC r0, r1, #0xFEFFFEFF +# CHECK: sbc r0, r1, #16777472 @ encoding: [0x61,0xf1,0x01,0x20] +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: ADC + ADD.W r0, r0, #0xFFFFFF01 +# CHECK: sub.w r0, r0, #255 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: ADD.W + ADD.W r0, r0, #0xFF01FF02 +# CHECK: sub.w r0, r0, #16646398 @ encoding: [0xa0,0xf1,0xfe,0x10] +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: ADD.W + ADDW r0, r1, #0xFFFFFF01 +# CHECK: subw r0, r1, #255 @ encoding: [0xa1,0xf2,0xff,0x00] +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: ADDW + ADD.W r0, r1, #0xFFFFFF01 +# CHECK: sub.w r0, r1, #255 @ encoding: [0xa1,0xf1,0xff,0x00] +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: ADD.W + AND r0, r1, #0xFFFFFF00 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: AND +# CHECK: bic r0, r1, #255 + AND r0, r1, #0xFEFFFEFF +# CHECK: bic r0, r1, #16777472 @ encoding: [0x21,0xf0,0x01,0x20] +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: AND + BIC r0, r1, #0xFFFFFF00 +# CHECK: and r0, r1, #255 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: BIC + BIC r0, r1, #0xFEFFFEFF +# CHECK: and r0, r1, #16777472 @ encoding: [0x01,0xf0,0x01,0x20] +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: BIC + CMP r0, #0xFFFFFF01 +# CHECK: cmn.w r0, #255 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: CMP + CMN r0, #0xFFFFFF01 +# CHECK: cmp.w r0, #255 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: CMN + MOV r0, #0xFFFFFF00 +# CHECK: mvn r0, #255 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: MOV + MVN r0, #0xFFFFFF00 +# CHECK: mov.w r0, #255 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: MVN + SBC r0, r1, #0xFFFFFF00 +# CHECK: adc r0, r1, #255 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: SBC + SUBW r0, r1, #0xFFFFFF01 +# CHECK: addw r0, r1, #255 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: SUBW + SUB.W r0, r1, #0xFFFFFF01 +# CHECK: add.w r0, r1, #255 +# CHECK-DISABLED: error: instruction requires: NegativeImmediates +# CHECK-DISABLED: SUB.W