Index: lib/Target/ARM/ARMInstrThumb2.td =================================================================== --- lib/Target/ARM/ARMInstrThumb2.td +++ lib/Target/ARM/ARMInstrThumb2.td @@ -2104,6 +2104,12 @@ (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)>; +def : t2InstSubst<"subw${p} $Rd, $Rn, $imm", + (t2ADDri12 GPRnopc:$Rd, GPR:$Rn, imm0_4095_neg:$imm, pred:$p)>; +def : t2InstSubst<"sub${s}${p} $rd, $rn, $imm", + (t2ADDri GPRnopc:$rd, GPRnopc:$rn, t2_so_imm_neg:$imm, pred:$p, s_cc_out:$s)>; +def : t2InstSubst<"sub${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>; @@ -4758,12 +4764,24 @@ def : t2InstSubst<"bic${s}${p} $Rdn, $imm", (t2ANDri rGPR:$Rdn, rGPR:$Rdn, t2_so_imm_not:$imm, pred:$p, cc_out:$s)>; +def : t2InstSubst<"bic${s}${p}.w $Rd, $Rn, $imm", + (t2ANDri rGPR:$Rd, rGPR:$Rn, t2_so_imm_not:$imm, + pred:$p, cc_out:$s)>; +def : t2InstSubst<"bic${s}${p}.w $Rdn, $imm", + (t2ANDri rGPR:$Rdn, rGPR:$Rdn, t2_so_imm_not:$imm, + pred:$p, cc_out:$s)>; def : t2InstSubst<"and${s}${p} $Rd, $Rn, $imm", (t2BICri rGPR:$Rd, rGPR:$Rn, t2_so_imm_not:$imm, pred:$p, cc_out:$s)>; def : t2InstSubst<"and${s}${p} $Rdn, $imm", (t2BICri rGPR:$Rdn, rGPR:$Rdn, t2_so_imm_not:$imm, pred:$p, cc_out:$s)>; +def : t2InstSubst<"and${s}${p}.w $Rd, $Rn, $imm", + (t2BICri rGPR:$Rd, rGPR:$Rn, t2_so_imm_not:$imm, + pred:$p, cc_out:$s)>; +def : t2InstSubst<"and${s}${p}.w $Rdn, $imm", + (t2BICri rGPR:$Rdn, rGPR:$Rdn, t2_so_imm_not:$imm, + pred:$p, cc_out:$s)>; // And ORR <--> ORN def : t2InstSubst<"orn${s}${p} $Rd, $Rn, $imm", (t2ORRri rGPR:$Rd, rGPR:$Rn, t2_so_imm_not:$imm, Index: lib/Target/ARM/AsmParser/ARMAsmParser.cpp =================================================================== --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -1042,7 +1042,12 @@ if (!isImm()) return false; const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; - int64_t Value = -CE->getValue(); + // isImm0_4095Neg is used with 32-bit immediates only. + // 32-bit immediates are zero extended to 64-bit when parsed, + // thus simple -CE->getValue() results in a big negative number, + // not a small positive number as intended + if ((CE->getValue() >> 32) > 0) return false; + uint32_t Value = -static_cast(CE->getValue()); return Value > 0 && Value < 4096; } @@ -2255,7 +2260,7 @@ // The operand is actually an imm0_4095, 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 addUnsignedOffset_b8s2Operands(MCInst &Inst, unsigned N) const { Index: test/MC/ARM/negative-immediates.s =================================================================== --- test/MC/ARM/negative-immediates.s +++ test/MC/ARM/negative-immediates.s @@ -50,6 +50,18 @@ .thumb + ADD r0, r1, #0xFFFFFF00 +# CHECK: subw r0, r1, #256 +# CHECK-DISABLED: note: instruction requires: NegativeImmediates +# CHECK-DISABLED: ADD + ADDS r0, r1, #0xFFFFFF00 +# CHECK: subs.w r0, r1, #256 +# CHECK-DISABLED: note: instruction requires: NegativeImmediates +# CHECK-DISABLED: ADDS + ADDS.W r0, r1, #0xFFFFFF00 +# CHECK: subs.w r0, r1, #256 +# CHECK-DISABLED: note: instruction requires: NegativeImmediates +# CHECK-DISABLED: ADDS.W ADC r0, r1, #0xFFFFFF00 # CHECK: sbc r0, r1, #255 # CHECK-DISABLED: note: instruction requires: NegativeImmediates @@ -90,10 +102,30 @@ # CHECK: bic r0, r1, #16777472 @ encoding: [0x21,0xf0,0x01,0x20] # CHECK-DISABLED: note: instruction requires: NegativeImmediates # CHECK-DISABLED: AND + AND.W r0, r1, #0xFFFFFF00 +# CHECK: bic r0, r1, #255 +# CHECK-DISABLED: note: instruction requires: NegativeImmediates +# CHECK-DISABLED: AND.W + ANDS r0, r1, #0xFFFFFF00 +# CHECK: bics r0, r1, #255 +# CHECK-DISABLED: note: instruction requires: NegativeImmediates +# CHECK-DISABLED: ANDS BIC r0, r1, #0xFFFFFF00 # CHECK: and r0, r1, #255 # CHECK-DISABLED: note: instruction requires: NegativeImmediates # CHECK-DISABLED: BIC + BIC.W r0, r1, #0xFFFFFF00 +# CHECK: and r0, r1, #255 +# CHECK-DISABLED: note: instruction requires: NegativeImmediates +# CHECK-DISABLED: BIC.W + BICS r0, r1, #0xFFFFFF00 +# CHECK: ands r0, r1, #255 +# CHECK-DISABLED: note: instruction requires: NegativeImmediates +# CHECK-DISABLED: BICS + BICS.W r0, r1, #0xFFFFFF00 +# CHECK: ands r0, r1, #255 +# CHECK-DISABLED: note: instruction requires: NegativeImmediates +# CHECK-DISABLED: BICS.W BIC r0, r1, #0xFEFFFEFF # CHECK: and r0, r1, #16777472 @ encoding: [0x01,0xf0,0x01,0x20] # CHECK-DISABLED: note: instruction requires: NegativeImmediates @@ -142,3 +174,20 @@ # CHECK: add.w r0, r1, #255 # CHECK-DISABLED: note: instruction requires: NegativeImmediates # CHECK-DISABLED: SUB.W + SUB r0, r1, #0xFFFFFF00 +# CHECK: addw r0, r1, #256 +# CHECK-DISABLED: note: instruction requires: NegativeImmediates +# CHECK-DISABLED: SUB + SUBS r0, r1, #0xFFFFFF00 +# CHECK: adds.w r0, r1, #256 +# CHECK-DISABLED: note: instruction requires: NegativeImmediates +# CHECK-DISABLED: SUBS + SUBS.W r0, r1, #0xFFFFFF00 +# CHECK: adds.w r0, r1, #256 +# CHECK-DISABLED: note: instruction requires: NegativeImmediates +# CHECK-DISABLED: SUBS.W + + ADD r0, r1, #-13 +# CHECK: subw r0, r1, #13 +# CHECK-DISABLED: note: instruction requires: NegativeImmediates +# CHECK-DISABLED: ADD