Skip to content

Commit 94612f1

Browse files
committed
[ARM] [Assembler] Support negative immediates for A32, T32 and T16
Summary: To support negative immediates for certain arithmetic instructions, the instruction is converted to the inverse instruction with a negated (or inverted) immediate. For example, "ADD r0, r1, #FFFFFFFF" cannot be encoded as an ADD instruction. However, "SUB r0, r1, #1" is equivalent. These conversions are different from instruction aliases. An alias maps several assembler instructions onto one encoding. A conversion, however, maps an *invalid* instruction--e.g. with an immediate that cannot be represented in the encoding--to a different (but equivalent) instruction. Several instructions with negative immediates were being converted already, but this was not systematically tested, nor did it cover all instructions. This patch implements all possible substitutions for ARM, Thumb1 and Thumb2 assembler and adds tests. It also adds a feature flag (-mattr=+no-neg-immediates) to turn these substitutions off. This is helpful for users who want their code to assemble to exactly what they wrote. Reviewers: t.p.northover, rovka, samparker, javed.absar, peter.smith, rengolin Reviewed By: javed.absar Subscribers: aadg, aemerson, llvm-commits Differential Revision: https://reviews.llvm.org/D30571 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@298380 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 656673e commit 94612f1

11 files changed

+320
-33
lines changed

lib/Target/ARM/ARM.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,12 @@ def FeatureNoMovt : SubtargetFeature<"no-movt", "NoMovt", "true",
261261
"Don't use movt/movw pairs for 32-bit "
262262
"imms">;
263263

264+
def FeatureNoNegativeImmediates : SubtargetFeature<"no-neg-immediates",
265+
"NegativeImmediates", "false",
266+
"Convert immediates and instructions "
267+
"to their negated or complemented "
268+
"equivalent when the immediate does "
269+
"not fit in the encoding.">;
264270

265271
//===----------------------------------------------------------------------===//
266272
// ARM ISAa.

lib/Target/ARM/ARMInstrFormats.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,10 +261,19 @@ def const_pool_asm_imm : Operand<i32> {
261261
// Note: When EmitPriority == 1, the alias will be used for printing
262262
class ARMInstAlias<string Asm, dag Result, bit EmitPriority = 0>
263263
: InstAlias<Asm, Result, EmitPriority>, Requires<[IsARM]>;
264+
class ARMInstSubst<string Asm, dag Result, bit EmitPriority = 0>
265+
: InstAlias<Asm, Result, EmitPriority>,
266+
Requires<[IsARM,UseNegativeImmediates]>;
264267
class tInstAlias<string Asm, dag Result, bit EmitPriority = 0>
265268
: InstAlias<Asm, Result, EmitPriority>, Requires<[IsThumb]>;
269+
class tInstSubst<string Asm, dag Result, bit EmitPriority = 0>
270+
: InstAlias<Asm, Result, EmitPriority>,
271+
Requires<[IsThumb,UseNegativeImmediates]>;
266272
class t2InstAlias<string Asm, dag Result, bit EmitPriority = 0>
267273
: InstAlias<Asm, Result, EmitPriority>, Requires<[IsThumb2]>;
274+
class t2InstSubst<string Asm, dag Result, bit EmitPriority = 0>
275+
: InstAlias<Asm, Result, EmitPriority>,
276+
Requires<[IsThumb2,UseNegativeImmediates]>;
268277
class VFP2InstAlias<string Asm, dag Result, bit EmitPriority = 0>
269278
: InstAlias<Asm, Result, EmitPriority>, Requires<[HasVFP2]>;
270279
class VFP2DPInstAlias<string Asm, dag Result, bit EmitPriority = 0>

lib/Target/ARM/ARMInstrInfo.td

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,11 @@ def UseNaClTrap : Predicate<"Subtarget->useNaClTrap()">,
311311
AssemblerPredicate<"FeatureNaClTrap", "NaCl">;
312312
def DontUseNaClTrap : Predicate<"!Subtarget->useNaClTrap()">;
313313

314+
def UseNegativeImmediates :
315+
Predicate<"false">,
316+
AssemblerPredicate<"!FeatureNoNegativeImmediates",
317+
"NegativeImmediates">;
318+
314319
// FIXME: Eventually this will be just "hasV6T2Ops".
315320
def UseMovt : Predicate<"Subtarget->useMovt(*MF)">;
316321
def DontUseMovt : Predicate<"!Subtarget->useMovt(*MF)">;
@@ -5790,33 +5795,49 @@ def : MnemonicAlias<"usubaddx", "usax">;
57905795

57915796
// "mov Rd, mod_imm_not" can be handled via "mvn" in assembly, just like
57925797
// for isel.
5793-
def : ARMInstAlias<"mov${s}${p} $Rd, $imm",
5798+
def : ARMInstSubst<"mov${s}${p} $Rd, $imm",
57945799
(MVNi rGPR:$Rd, mod_imm_not:$imm, pred:$p, cc_out:$s)>;
5795-
def : ARMInstAlias<"mvn${s}${p} $Rd, $imm",
5800+
def : ARMInstSubst<"mvn${s}${p} $Rd, $imm",
57965801
(MOVi rGPR:$Rd, mod_imm_not:$imm, pred:$p, cc_out:$s)>;
57975802
// Same for AND <--> BIC
5798-
def : ARMInstAlias<"bic${s}${p} $Rd, $Rn, $imm",
5803+
def : ARMInstSubst<"bic${s}${p} $Rd, $Rn, $imm",
57995804
(ANDri GPR:$Rd, GPR:$Rn, mod_imm_not:$imm,
58005805
pred:$p, cc_out:$s)>;
5801-
def : ARMInstAlias<"bic${s}${p} $Rdn, $imm",
5806+
def : ARMInstSubst<"bic${s}${p} $Rdn, $imm",
58025807
(ANDri GPR:$Rdn, GPR:$Rdn, mod_imm_not:$imm,
58035808
pred:$p, cc_out:$s)>;
5804-
def : ARMInstAlias<"and${s}${p} $Rd, $Rn, $imm",
5809+
def : ARMInstSubst<"and${s}${p} $Rd, $Rn, $imm",
58055810
(BICri GPR:$Rd, GPR:$Rn, mod_imm_not:$imm,
58065811
pred:$p, cc_out:$s)>;
5807-
def : ARMInstAlias<"and${s}${p} $Rdn, $imm",
5812+
def : ARMInstSubst<"and${s}${p} $Rdn, $imm",
58085813
(BICri GPR:$Rdn, GPR:$Rdn, mod_imm_not:$imm,
58095814
pred:$p, cc_out:$s)>;
58105815

58115816
// Likewise, "add Rd, mod_imm_neg" -> sub
5812-
def : ARMInstAlias<"add${s}${p} $Rd, $Rn, $imm",
5817+
def : ARMInstSubst<"add${s}${p} $Rd, $Rn, $imm",
58135818
(SUBri GPR:$Rd, GPR:$Rn, mod_imm_neg:$imm, pred:$p, cc_out:$s)>;
5814-
def : ARMInstAlias<"add${s}${p} $Rd, $imm",
5819+
def : ARMInstSubst<"add${s}${p} $Rd, $imm",
58155820
(SUBri GPR:$Rd, GPR:$Rd, mod_imm_neg:$imm, pred:$p, cc_out:$s)>;
5821+
// Likewise, "sub Rd, mod_imm_neg" -> add
5822+
def : ARMInstSubst<"sub${s}${p} $Rd, $Rn, $imm",
5823+
(ADDri GPR:$Rd, GPR:$Rn, mod_imm_neg:$imm, pred:$p, cc_out:$s)>;
5824+
def : ARMInstSubst<"sub${s}${p} $Rd, $imm",
5825+
(ADDri GPR:$Rd, GPR:$Rd, mod_imm_neg:$imm, pred:$p, cc_out:$s)>;
5826+
5827+
5828+
def : ARMInstSubst<"adc${s}${p} $Rd, $Rn, $imm",
5829+
(SBCri GPR:$Rd, GPR:$Rn, mod_imm_not:$imm, pred:$p, cc_out:$s)>;
5830+
def : ARMInstSubst<"adc${s}${p} $Rdn, $imm",
5831+
(SBCri GPR:$Rdn, GPR:$Rdn, mod_imm_not:$imm, pred:$p, cc_out:$s)>;
5832+
def : ARMInstSubst<"sbc${s}${p} $Rd, $Rn, $imm",
5833+
(ADCri GPR:$Rd, GPR:$Rn, mod_imm_not:$imm, pred:$p, cc_out:$s)>;
5834+
def : ARMInstSubst<"sbc${s}${p} $Rdn, $imm",
5835+
(ADCri GPR:$Rdn, GPR:$Rdn, mod_imm_not:$imm, pred:$p, cc_out:$s)>;
5836+
58165837
// Same for CMP <--> CMN via mod_imm_neg
5817-
def : ARMInstAlias<"cmp${p} $Rd, $imm",
5838+
def : ARMInstSubst<"cmp${p} $Rd, $imm",
58185839
(CMNri rGPR:$Rd, mod_imm_neg:$imm, pred:$p)>;
5819-
def : ARMInstAlias<"cmn${p} $Rd, $imm",
5840+
def : ARMInstSubst<"cmn${p} $Rd, $imm",
58205841
(CMPri rGPR:$Rd, mod_imm_neg:$imm, pred:$p)>;
58215842

58225843
// The shifter forms of the MOV instruction are aliased to the ASR, LSL,

lib/Target/ARM/ARMInstrThumb.td

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,23 @@ def imm0_7_neg : PatLeaf<(i32 imm), [{
3232
return (uint32_t)-N->getZExtValue() < 8;
3333
}], imm_neg_XFORM>;
3434

35+
def ThumbModImmNeg1_7AsmOperand : AsmOperandClass { let Name = "ThumbModImmNeg1_7"; }
36+
def mod_imm1_7_neg : Operand<i32>, PatLeaf<(imm), [{
37+
unsigned Value = -(unsigned)N->getZExtValue();
38+
return 0 < Value && Value < 8;
39+
}], imm_neg_XFORM> {
40+
let ParserMatchClass = ThumbModImmNeg1_7AsmOperand;
41+
}
42+
43+
def ThumbModImmNeg8_255AsmOperand : AsmOperandClass { let Name = "ThumbModImmNeg8_255"; }
44+
def mod_imm8_255_neg : Operand<i32>, PatLeaf<(imm), [{
45+
unsigned Value = -(unsigned)N->getZExtValue();
46+
return 7 < Value && Value < 256;
47+
}], imm_neg_XFORM> {
48+
let ParserMatchClass = ThumbModImmNeg8_255AsmOperand;
49+
}
50+
51+
3552
def imm0_255_comp : PatLeaf<(i32 imm), [{
3653
return ~((uint32_t)N->getZExtValue()) < 256;
3754
}]>;
@@ -402,9 +419,9 @@ def tSUBspi : T1pIt<(outs GPRsp:$Rdn), (ins GPRsp:$Rn, t_imm0_508s4:$imm),
402419
let DecoderMethod = "DecodeThumbAddSPImm";
403420
}
404421

405-
def : tInstAlias<"add${p} sp, $imm",
422+
def : tInstSubst<"add${p} sp, $imm",
406423
(tSUBspi SP, t_imm0_508s4_neg:$imm, pred:$p)>;
407-
def : tInstAlias<"add${p} sp, sp, $imm",
424+
def : tInstSubst<"add${p} sp, sp, $imm",
408425
(tSUBspi SP, t_imm0_508s4_neg:$imm, pred:$p)>;
409426

410427
// Can optionally specify SP as a three operand instruction.
@@ -946,6 +963,12 @@ let isAdd = 1 in {
946963
}
947964
}
948965

966+
def : tInstSubst<"sub${s}${p} $rd, $rn, $imm",
967+
(tADDi3 tGPR:$rd, s_cc_out:$s, tGPR:$rn, mod_imm1_7_neg:$imm, pred:$p)>;
968+
def : tInstSubst<"sub${s}${p} $rdn, $imm",
969+
(tADDi8 tGPR:$rdn, s_cc_out:$s, mod_imm8_255_neg:$imm, pred:$p)>;
970+
971+
949972
// AND register
950973
let isCommutable = 1 in
951974
def tAND : // A8.6.12
@@ -1213,6 +1236,14 @@ def tSUBi8 : // A8.6.210 T2
12131236
[(set tGPR:$Rdn, (add tGPR:$Rn, imm8_255_neg:$imm8))]>,
12141237
Sched<[WriteALU]>;
12151238

1239+
def : tInstSubst<"add${s}${p} $rd, $rn, $imm",
1240+
(tSUBi3 tGPR:$rd, s_cc_out:$s, tGPR:$rn, mod_imm1_7_neg:$imm, pred:$p)>;
1241+
1242+
1243+
def : tInstSubst<"add${s}${p} $rdn, $imm",
1244+
(tSUBi8 tGPR:$rdn, s_cc_out:$s, mod_imm8_255_neg:$imm, pred:$p)>;
1245+
1246+
12161247
// Subtract register
12171248
def tSUBrr : // A8.6.212
12181249
T1sIGenEncode<0b01101, (outs tGPR:$Rd), (ins tGPR:$Rn, tGPR:$Rm),

lib/Target/ARM/ARMInstrThumb2.td

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2079,6 +2079,19 @@ defm t2ADC : T2I_adde_sube_irs<0b1010, "adc", ARMadde, 1>;
20792079
defm t2SBC : T2I_adde_sube_irs<0b1011, "sbc", ARMsube>;
20802080
}
20812081

2082+
def : t2InstSubst<"adc${s}${p} $rd, $rn, $imm",
2083+
(t2SBCri rGPR:$rd, rGPR:$rn, t2_so_imm_not:$imm, pred:$p, s_cc_out:$s)>;
2084+
def : t2InstSubst<"sbc${s}${p} $rd, $rn, $imm",
2085+
(t2ADCri rGPR:$rd, rGPR:$rn, t2_so_imm_not:$imm, pred:$p, s_cc_out:$s)>;
2086+
2087+
def : t2InstSubst<"add${s}${p}.w $rd, $rn, $imm",
2088+
(t2SUBri GPRnopc:$rd, GPRnopc:$rn, t2_so_imm_neg:$imm, pred:$p, s_cc_out:$s)>;
2089+
def : t2InstSubst<"addw${p} $rd, $rn, $imm",
2090+
(t2SUBri12 GPRnopc:$rd, GPR:$rn, t2_so_imm_neg:$imm, pred:$p)>;
2091+
def : t2InstSubst<"sub${s}${p}.w $rd, $rn, $imm",
2092+
(t2ADDri GPRnopc:$rd, GPRnopc:$rn, t2_so_imm_neg:$imm, pred:$p, s_cc_out:$s)>;
2093+
def : t2InstSubst<"subw${p} $rd, $rn, $imm",
2094+
(t2ADDri12 GPRnopc:$rd, GPR:$rn, t2_so_imm_neg:$imm, pred:$p)>;
20822095
// RSB
20832096
defm t2RSB : T2I_rbin_irs <0b1110, "rsb", sub>;
20842097

@@ -4375,26 +4388,26 @@ def : t2InstAlias<"add${s}${p} $Rdn, $ShiftedRm",
43754388
pred:$p, cc_out:$s)>;
43764389

43774390
// add w/ negative immediates is just a sub.
4378-
def : t2InstAlias<"add${s}${p} $Rd, $Rn, $imm",
4391+
def : t2InstSubst<"add${s}${p} $Rd, $Rn, $imm",
43794392
(t2SUBri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm_neg:$imm, pred:$p,
43804393
cc_out:$s)>;
4381-
def : t2InstAlias<"add${p} $Rd, $Rn, $imm",
4394+
def : t2InstSubst<"add${p} $Rd, $Rn, $imm",
43824395
(t2SUBri12 GPRnopc:$Rd, GPR:$Rn, imm0_4095_neg:$imm, pred:$p)>;
4383-
def : t2InstAlias<"add${s}${p} $Rdn, $imm",
4396+
def : t2InstSubst<"add${s}${p} $Rdn, $imm",
43844397
(t2SUBri GPRnopc:$Rdn, GPRnopc:$Rdn, t2_so_imm_neg:$imm, pred:$p,
43854398
cc_out:$s)>;
4386-
def : t2InstAlias<"add${p} $Rdn, $imm",
4399+
def : t2InstSubst<"add${p} $Rdn, $imm",
43874400
(t2SUBri12 GPRnopc:$Rdn, GPRnopc:$Rdn, imm0_4095_neg:$imm, pred:$p)>;
43884401

4389-
def : t2InstAlias<"add${s}${p}.w $Rd, $Rn, $imm",
4402+
def : t2InstSubst<"add${s}${p}.w $Rd, $Rn, $imm",
43904403
(t2SUBri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm_neg:$imm, pred:$p,
43914404
cc_out:$s)>;
4392-
def : t2InstAlias<"addw${p} $Rd, $Rn, $imm",
4405+
def : t2InstSubst<"addw${p} $Rd, $Rn, $imm",
43934406
(t2SUBri12 GPRnopc:$Rd, GPR:$Rn, imm0_4095_neg:$imm, pred:$p)>;
4394-
def : t2InstAlias<"add${s}${p}.w $Rdn, $imm",
4407+
def : t2InstSubst<"add${s}${p}.w $Rdn, $imm",
43954408
(t2SUBri GPRnopc:$Rdn, GPRnopc:$Rdn, t2_so_imm_neg:$imm, pred:$p,
43964409
cc_out:$s)>;
4397-
def : t2InstAlias<"addw${p} $Rdn, $imm",
4410+
def : t2InstSubst<"addw${p} $Rdn, $imm",
43984411
(t2SUBri12 GPRnopc:$Rdn, GPRnopc:$Rdn, imm0_4095_neg:$imm, pred:$p)>;
43994412

44004413

@@ -4625,34 +4638,34 @@ def : t2InstAlias<"sxth${p} $Rd, $Rm$rot",
46254638

46264639
// "mov Rd, t2_so_imm_not" can be handled via "mvn" in assembly, just like
46274640
// for isel.
4628-
def : t2InstAlias<"mov${p} $Rd, $imm",
4641+
def : t2InstSubst<"mov${p} $Rd, $imm",
46294642
(t2MVNi rGPR:$Rd, t2_so_imm_not:$imm, pred:$p, zero_reg)>;
4630-
def : t2InstAlias<"mvn${p} $Rd, $imm",
4631-
(t2MOVi rGPR:$Rd, t2_so_imm_not:$imm, pred:$p, zero_reg)>;
4643+
def : t2InstSubst<"mvn${s}${p} $Rd, $imm",
4644+
(t2MOVi rGPR:$Rd, t2_so_imm_not:$imm, pred:$p, s_cc_out:$s)>;
46324645
// Same for AND <--> BIC
4633-
def : t2InstAlias<"bic${s}${p} $Rd, $Rn, $imm",
4646+
def : t2InstSubst<"bic${s}${p} $Rd, $Rn, $imm",
46344647
(t2ANDri rGPR:$Rd, rGPR:$Rn, t2_so_imm_not:$imm,
46354648
pred:$p, cc_out:$s)>;
4636-
def : t2InstAlias<"bic${s}${p} $Rdn, $imm",
4649+
def : t2InstSubst<"bic${s}${p} $Rdn, $imm",
46374650
(t2ANDri rGPR:$Rdn, rGPR:$Rdn, t2_so_imm_not:$imm,
46384651
pred:$p, cc_out:$s)>;
4639-
def : t2InstAlias<"and${s}${p} $Rd, $Rn, $imm",
4652+
def : t2InstSubst<"and${s}${p} $Rd, $Rn, $imm",
46404653
(t2BICri rGPR:$Rd, rGPR:$Rn, t2_so_imm_not:$imm,
46414654
pred:$p, cc_out:$s)>;
4642-
def : t2InstAlias<"and${s}${p} $Rdn, $imm",
4655+
def : t2InstSubst<"and${s}${p} $Rdn, $imm",
46434656
(t2BICri rGPR:$Rdn, rGPR:$Rdn, t2_so_imm_not:$imm,
46444657
pred:$p, cc_out:$s)>;
46454658
// Likewise, "add Rd, t2_so_imm_neg" -> sub
4646-
def : t2InstAlias<"add${s}${p} $Rd, $Rn, $imm",
4659+
def : t2InstSubst<"add${s}${p} $Rd, $Rn, $imm",
46474660
(t2SUBri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm_neg:$imm,
46484661
pred:$p, cc_out:$s)>;
4649-
def : t2InstAlias<"add${s}${p} $Rd, $imm",
4662+
def : t2InstSubst<"add${s}${p} $Rd, $imm",
46504663
(t2SUBri GPRnopc:$Rd, GPRnopc:$Rd, t2_so_imm_neg:$imm,
46514664
pred:$p, cc_out:$s)>;
46524665
// Same for CMP <--> CMN via t2_so_imm_neg
4653-
def : t2InstAlias<"cmp${p} $Rd, $imm",
4666+
def : t2InstSubst<"cmp${p} $Rd, $imm",
46544667
(t2CMNri rGPR:$Rd, t2_so_imm_neg:$imm, pred:$p)>;
4655-
def : t2InstAlias<"cmn${p} $Rd, $imm",
4668+
def : t2InstSubst<"cmn${p} $Rd, $imm",
46564669
(t2CMPri rGPR:$Rd, t2_so_imm_neg:$imm, pred:$p)>;
46574670

46584671

lib/Target/ARM/ARMSubtarget.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,10 @@ class ARMSubtarget : public ARMGenSubtargetInfo {
351351
/// UseSjLjEH - If true, the target uses SjLj exception handling (e.g. iOS).
352352
bool UseSjLjEH = false;
353353

354+
/// Implicitly convert an instruction to a different one if its immediates
355+
/// cannot be encoded. For example, ADD r0, r1, #FFFFFFFF -> SUB r0, r1, #1.
356+
bool NegativeImmediates = true;
357+
354358
/// stackAlignment - The minimum alignment known to hold of the stack frame on
355359
/// entry to the function and which must be maintained by every function.
356360
unsigned stackAlignment = 4;

lib/Target/ARM/AsmParser/ARMAsmParser.cpp

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,6 +1245,20 @@ class ARMOperand : public MCParsedAsmOperand {
12451245
return ARM_AM::getSOImmVal(Value) == -1 &&
12461246
ARM_AM::getSOImmVal(-Value) != -1;
12471247
}
1248+
bool isThumbModImmNeg1_7() const {
1249+
if (!isImm()) return false;
1250+
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1251+
if (!CE) return false;
1252+
int32_t Value = -(int32_t)CE->getValue();
1253+
return 0 < Value && Value < 8;
1254+
}
1255+
bool isThumbModImmNeg8_255() const {
1256+
if (!isImm()) return false;
1257+
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1258+
if (!CE) return false;
1259+
int32_t Value = -(int32_t)CE->getValue();
1260+
return 7 < Value && Value < 256;
1261+
}
12481262
bool isConstantPoolImm() const { return Kind == k_ConstantPoolImmediate; }
12491263
bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
12501264
bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
@@ -2035,6 +2049,20 @@ class ARMOperand : public MCParsedAsmOperand {
20352049
Inst.addOperand(MCOperand::createImm(Enc));
20362050
}
20372051

2052+
void addThumbModImmNeg8_255Operands(MCInst &Inst, unsigned N) const {
2053+
assert(N == 1 && "Invalid number of operands!");
2054+
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2055+
uint32_t Val = -CE->getValue();
2056+
Inst.addOperand(MCOperand::createImm(Val));
2057+
}
2058+
2059+
void addThumbModImmNeg1_7Operands(MCInst &Inst, unsigned N) const {
2060+
assert(N == 1 && "Invalid number of operands!");
2061+
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2062+
uint32_t Val = -CE->getValue();
2063+
Inst.addOperand(MCOperand::createImm(Val));
2064+
}
2065+
20382066
void addBitfieldOperands(MCInst &Inst, unsigned N) const {
20392067
assert(N == 1 && "Invalid number of operands!");
20402068
// Munge the lsb/width into a bitfield mask.
@@ -2141,15 +2169,15 @@ class ARMOperand : public MCParsedAsmOperand {
21412169
// The operand is actually a t2_so_imm, but we have its bitwise
21422170
// negation in the assembly source, so twiddle it here.
21432171
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2144-
Inst.addOperand(MCOperand::createImm(~CE->getValue()));
2172+
Inst.addOperand(MCOperand::createImm(~(uint32_t)CE->getValue()));
21452173
}
21462174

21472175
void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
21482176
assert(N == 1 && "Invalid number of operands!");
21492177
// The operand is actually a t2_so_imm, but we have its
21502178
// negation in the assembly source, so twiddle it here.
21512179
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2152-
Inst.addOperand(MCOperand::createImm(-CE->getValue()));
2180+
Inst.addOperand(MCOperand::createImm(-(uint32_t)CE->getValue()));
21532181
}
21542182

21552183
void addImm0_4095NegOperands(MCInst &Inst, unsigned N) const {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# RUN: not llvm-mc -triple armv7 %s 2>&1| FileCheck %s
2+
3+
.arm
4+
5+
ADC r0, r1, #0xFFFFFEEE
6+
# CHECK: error: invalid operand for instruction
7+
ADC r0, r1, #0xABFEABFF
8+
# CHECK: error: invalid operand for instruction
9+
ADC r0, r1, #0xFFFFFE02
10+
# CHECK: error: invalid operand for instruction
11+
12+
ADD.W r0, r0, #0xFF01FF01
13+
# CHECK: error: invalid operand for instruction
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# RUN: not llvm-mc -triple thumbv7 -mcpu=cortex-m0 %s 2>&1 | FileCheck %s
2+
3+
.thumb
4+
5+
ADDs r1, r0, #0xFFFFFFF5
6+
# CHECK: error: instruction requires: arm-mode
7+
8+
ADDs r0, #0xFFFFFEFF
9+
# CHECK: error: invalid operand for instruction
10+
11+
SUBs r1, r0, #0xFFFFFFF5
12+
# CHECK: error: instruction requires: arm-mode
13+
14+
SUBs r0, #0xFFFFFEFF
15+
# CHECK: error: invalid operand for instruction
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# RUN: llvm-mc -triple thumbv7 -mcpu=cortex-m0 %s -show-encoding | FileCheck %s
2+
# RUN: not llvm-mc -triple thumbv7 -mcpu=cortex-m0 %s -show-encoding -mattr=+no-neg-immediates 2>&1 | FileCheck %s -check-prefix=CHECK-DISABLED
3+
4+
.thumb
5+
6+
ADDs r1, r0, #0xFFFFFFF9
7+
# CHECK: subs r1, r0, #7
8+
# CHECK-DISABLED: error: instruction requires: NegativeImmediates
9+
ADDs r0, #0xFFFFFF01
10+
# CHECK: subs r0, #255
11+
# CHECK-DISABLED: error: instruction requires: NegativeImmediates
12+
13+
SUBs r0, #0xFFFFFF01
14+
# CHECK: adds r0, #255
15+
# CHECK-DISABLED: error: instruction requires: NegativeImmediates
16+
17+
SUBs r1, r0, #0xFFFFFFF9
18+
# CHECK: adds r1, r0, #7
19+
# CHECK-DISABLED: error: instruction requires: NegativeImmediates

0 commit comments

Comments
 (0)