Skip to content
This repository was archived by the owner on Sep 2, 2018. It is now read-only.

Commit dc05f3a

Browse files
author
Asiri Rathnayake
committed
Add support for ARM modified-immediate assembly syntax.
Certain ARM instructions accept 32-bit immediate operands encoded as a 8-bit integer value (0-255) and a 4-bit rotation (0-30, even). Current ARM assembly syntax support in LLVM allows the decoded (32-bit) immediate to be specified as a single immediate operand for such instructions: mov r0, #4278190080 The ARMARM defines an extended assembly syntax allowing the encoding to be made more explicit, as in: mov r0, #255, #8 ; (same 32-bit value as above) The behaviour of the two instructions can be different w.r.t flags, which is documented under "Modified immediate constants" in ARMARM. This patch enables support for this extended syntax at the MC layer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@223113 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent fc3aa4b commit dc05f3a

11 files changed

+690
-42
lines changed

lib/Target/ARM/ARMInstrInfo.td

+66-34
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,38 @@ def so_imm : Operand<i32>, ImmLeaf<i32, [{
587587
let DecoderMethod = "DecodeSOImmOperand";
588588
}
589589

590+
// mod_imm: match a 32-bit immediate operand, which is encoded as a 12-bit
591+
// immediate (See ARMARM - "Modified Immediate Constants"). Unlike so_imm,
592+
// mod_imm keeps the immediate in its encoded form (within the MC layer).
593+
def ModImmAsmOperand: AsmOperandClass {
594+
let Name = "ModImm";
595+
let ParserMethod = "parseModImm";
596+
}
597+
def mod_imm : Operand<i32>, ImmLeaf<i32, [{
598+
return ARM_AM::getSOImmVal(Imm) != -1;
599+
}]> {
600+
let EncoderMethod = "getModImmOpValue";
601+
let PrintMethod = "printModImmOperand";
602+
let ParserMatchClass = ModImmAsmOperand;
603+
}
604+
605+
// similar to so_imm_not, but keeps the immediate in its encoded form
606+
def ModImmNotAsmOperand : AsmOperandClass { let Name = "ModImmNot"; }
607+
def mod_imm_not : Operand<i32>, PatLeaf<(imm), [{
608+
return ARM_AM::getSOImmVal(~(uint32_t)N->getZExtValue()) != -1;
609+
}], imm_not_XFORM> {
610+
let ParserMatchClass = ModImmNotAsmOperand;
611+
}
612+
613+
// similar to so_imm_neg, but keeps the immediate in its encoded form
614+
def ModImmNegAsmOperand : AsmOperandClass { let Name = "ModImmNeg"; }
615+
def mod_imm_neg : Operand<i32>, PatLeaf<(imm), [{
616+
unsigned Value = -(unsigned)N->getZExtValue();
617+
return Value && ARM_AM::getSOImmVal(Value) != -1;
618+
}], imm_neg_XFORM> {
619+
let ParserMatchClass = ModImmNegAsmOperand;
620+
}
621+
590622
// Break so_imm's up into two pieces. This handles immediates with up to 16
591623
// bits set in them. This uses so_imm2part to match and so_imm2part_[12] to
592624
// get the first/second pieces.
@@ -1213,9 +1245,9 @@ multiclass AsI1_bin_irs<bits<4> opcod, string opc,
12131245
// The register-immediate version is re-materializable. This is useful
12141246
// in particular for taking the address of a local.
12151247
let isReMaterializable = 1 in {
1216-
def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm,
1248+
def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, mod_imm:$imm), DPFrm,
12171249
iii, opc, "\t$Rd, $Rn, $imm",
1218-
[(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]>,
1250+
[(set GPR:$Rd, (opnode GPR:$Rn, mod_imm:$imm))]>,
12191251
Sched<[WriteALU, ReadALU]> {
12201252
bits<4> Rd;
12211253
bits<4> Rn;
@@ -1286,9 +1318,9 @@ multiclass AsI1_rbin_irs<bits<4> opcod, string opc,
12861318
// The register-immediate version is re-materializable. This is useful
12871319
// in particular for taking the address of a local.
12881320
let isReMaterializable = 1 in {
1289-
def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm,
1321+
def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, mod_imm:$imm), DPFrm,
12901322
iii, opc, "\t$Rd, $Rn, $imm",
1291-
[(set GPR:$Rd, (opnode so_imm:$imm, GPR:$Rn))]>,
1323+
[(set GPR:$Rd, (opnode mod_imm:$imm, GPR:$Rn))]>,
12921324
Sched<[WriteALU, ReadALU]> {
12931325
bits<4> Rd;
12941326
bits<4> Rn;
@@ -1356,9 +1388,9 @@ let hasPostISelHook = 1, Defs = [CPSR] in {
13561388
multiclass AsI1_bin_s_irs<InstrItinClass iii, InstrItinClass iir,
13571389
InstrItinClass iis, PatFrag opnode,
13581390
bit Commutable = 0> {
1359-
def ri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm, pred:$p),
1391+
def ri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, mod_imm:$imm, pred:$p),
13601392
4, iii,
1361-
[(set GPR:$Rd, CPSR, (opnode GPR:$Rn, so_imm:$imm))]>,
1393+
[(set GPR:$Rd, CPSR, (opnode GPR:$Rn, mod_imm:$imm))]>,
13621394
Sched<[WriteALU, ReadALU]>;
13631395

13641396
def rr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, pred:$p),
@@ -1389,9 +1421,9 @@ let hasPostISelHook = 1, Defs = [CPSR] in {
13891421
multiclass AsI1_rbin_s_is<InstrItinClass iii, InstrItinClass iir,
13901422
InstrItinClass iis, PatFrag opnode,
13911423
bit Commutable = 0> {
1392-
def ri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm, pred:$p),
1424+
def ri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, mod_imm:$imm, pred:$p),
13931425
4, iii,
1394-
[(set GPR:$Rd, CPSR, (opnode so_imm:$imm, GPR:$Rn))]>,
1426+
[(set GPR:$Rd, CPSR, (opnode mod_imm:$imm, GPR:$Rn))]>,
13951427
Sched<[WriteALU, ReadALU]>;
13961428

13971429
def rsi : ARMPseudoInst<(outs GPR:$Rd),
@@ -1417,9 +1449,9 @@ let isCompare = 1, Defs = [CPSR] in {
14171449
multiclass AI1_cmp_irs<bits<4> opcod, string opc,
14181450
InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
14191451
PatFrag opnode, bit Commutable = 0> {
1420-
def ri : AI1<opcod, (outs), (ins GPR:$Rn, so_imm:$imm), DPFrm, iii,
1452+
def ri : AI1<opcod, (outs), (ins GPR:$Rn, mod_imm:$imm), DPFrm, iii,
14211453
opc, "\t$Rn, $imm",
1422-
[(opnode GPR:$Rn, so_imm:$imm)]>,
1454+
[(opnode GPR:$Rn, mod_imm:$imm)]>,
14231455
Sched<[WriteCMP, ReadALU]> {
14241456
bits<4> Rn;
14251457
bits<12> imm;
@@ -1547,9 +1579,9 @@ let TwoOperandAliasConstraint = "$Rn = $Rd" in
15471579
multiclass AI1_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
15481580
bit Commutable = 0> {
15491581
let hasPostISelHook = 1, Defs = [CPSR], Uses = [CPSR] in {
1550-
def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
1582+
def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, mod_imm:$imm),
15511583
DPFrm, IIC_iALUi, opc, "\t$Rd, $Rn, $imm",
1552-
[(set GPR:$Rd, CPSR, (opnode GPR:$Rn, so_imm:$imm, CPSR))]>,
1584+
[(set GPR:$Rd, CPSR, (opnode GPR:$Rn, mod_imm:$imm, CPSR))]>,
15531585
Requires<[IsARM]>,
15541586
Sched<[WriteALU, ReadALU]> {
15551587
bits<4> Rd;
@@ -1617,9 +1649,9 @@ multiclass AI1_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
16171649
let TwoOperandAliasConstraint = "$Rn = $Rd" in
16181650
multiclass AI1_rsc_irs<bits<4> opcod, string opc, PatFrag opnode> {
16191651
let hasPostISelHook = 1, Defs = [CPSR], Uses = [CPSR] in {
1620-
def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
1652+
def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, mod_imm:$imm),
16211653
DPFrm, IIC_iALUi, opc, "\t$Rd, $Rn, $imm",
1622-
[(set GPR:$Rd, CPSR, (opnode so_imm:$imm, GPR:$Rn, CPSR))]>,
1654+
[(set GPR:$Rd, CPSR, (opnode mod_imm:$imm, GPR:$Rn, CPSR))]>,
16231655
Requires<[IsARM]>,
16241656
Sched<[WriteALU, ReadALU]> {
16251657
bits<4> Rd;
@@ -3224,8 +3256,8 @@ def MOVsi : AsI1<0b1101, (outs GPR:$Rd), (ins shift_so_reg_imm:$src),
32243256
}
32253257

32263258
let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in
3227-
def MOVi : AsI1<0b1101, (outs GPR:$Rd), (ins so_imm:$imm), DPFrm, IIC_iMOVi,
3228-
"mov", "\t$Rd, $imm", [(set GPR:$Rd, so_imm:$imm)]>, UnaryDP,
3259+
def MOVi : AsI1<0b1101, (outs GPR:$Rd), (ins mod_imm:$imm), DPFrm, IIC_iMOVi,
3260+
"mov", "\t$Rd, $imm", [(set GPR:$Rd, mod_imm:$imm)]>, UnaryDP,
32293261
Sched<[WriteALU]> {
32303262
bits<4> Rd;
32313263
bits<12> imm;
@@ -3732,9 +3764,9 @@ def MVNsr : AsI1<0b1111, (outs GPR:$Rd), (ins so_reg_reg:$shift),
37323764
let Inst{3-0} = shift{3-0};
37333765
}
37343766
let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in
3735-
def MVNi : AsI1<0b1111, (outs GPR:$Rd), (ins so_imm:$imm), DPFrm,
3767+
def MVNi : AsI1<0b1111, (outs GPR:$Rd), (ins mod_imm:$imm), DPFrm,
37363768
IIC_iMVNi, "mvn", "\t$Rd, $imm",
3737-
[(set GPR:$Rd, so_imm_not:$imm)]>,UnaryDP, Sched<[WriteALU]> {
3769+
[(set GPR:$Rd, mod_imm_not:$imm)]>,UnaryDP, Sched<[WriteALU]> {
37383770
bits<4> Rd;
37393771
bits<12> imm;
37403772
let Inst{25} = 1;
@@ -4280,9 +4312,9 @@ def : ARMPat<(ARMcmpZ GPR:$src, so_reg_reg:$rhs),
42804312

42814313
// CMN register-integer
42824314
let isCompare = 1, Defs = [CPSR] in {
4283-
def CMNri : AI1<0b1011, (outs), (ins GPR:$Rn, so_imm:$imm), DPFrm, IIC_iCMPi,
4315+
def CMNri : AI1<0b1011, (outs), (ins GPR:$Rn, mod_imm:$imm), DPFrm, IIC_iCMPi,
42844316
"cmn", "\t$Rn, $imm",
4285-
[(ARMcmn GPR:$Rn, so_imm:$imm)]>,
4317+
[(ARMcmn GPR:$Rn, mod_imm:$imm)]>,
42864318
Sched<[WriteCMP, ReadALU]> {
42874319
bits<4> Rn;
42884320
bits<12> imm;
@@ -5130,17 +5162,17 @@ def MSR : ABI<0b0001, (outs), (ins msr_mask:$mask, GPR:$Rn), NoItinerary,
51305162
let Inst{3-0} = Rn;
51315163
}
51325164

5133-
def MSRi : ABI<0b0011, (outs), (ins msr_mask:$mask, so_imm:$a), NoItinerary,
5134-
"msr", "\t$mask, $a", []> {
5165+
def MSRi : ABI<0b0011, (outs), (ins msr_mask:$mask, mod_imm:$imm), NoItinerary,
5166+
"msr", "\t$mask, $imm", []> {
51355167
bits<5> mask;
5136-
bits<12> a;
5168+
bits<12> imm;
51375169

51385170
let Inst{23} = 0;
51395171
let Inst{22} = mask{4}; // R bit
51405172
let Inst{21-20} = 0b10;
51415173
let Inst{19-16} = mask{3-0};
51425174
let Inst{15-12} = 0b1111;
5143-
let Inst{11-0} = a;
5175+
let Inst{11-0} = imm;
51445176
}
51455177

51465178
// However, the MSR (banked register) system instruction (ARMv7VE) *does* have a
@@ -5549,33 +5581,33 @@ def : MnemonicAlias<"usubaddx", "usax">;
55495581
// "mov Rd, so_imm_not" can be handled via "mvn" in assembly, just like
55505582
// for isel.
55515583
def : ARMInstAlias<"mov${s}${p} $Rd, $imm",
5552-
(MVNi rGPR:$Rd, so_imm_not:$imm, pred:$p, cc_out:$s)>;
5584+
(MVNi rGPR:$Rd, mod_imm_not:$imm, pred:$p, cc_out:$s)>;
55535585
def : ARMInstAlias<"mvn${s}${p} $Rd, $imm",
5554-
(MOVi rGPR:$Rd, so_imm_not:$imm, pred:$p, cc_out:$s)>;
5586+
(MOVi rGPR:$Rd, mod_imm_not:$imm, pred:$p, cc_out:$s)>;
55555587
// Same for AND <--> BIC
55565588
def : ARMInstAlias<"bic${s}${p} $Rd, $Rn, $imm",
5557-
(ANDri rGPR:$Rd, rGPR:$Rn, so_imm_not:$imm,
5589+
(ANDri rGPR:$Rd, rGPR:$Rn, mod_imm_not:$imm,
55585590
pred:$p, cc_out:$s)>;
55595591
def : ARMInstAlias<"bic${s}${p} $Rdn, $imm",
5560-
(ANDri rGPR:$Rdn, rGPR:$Rdn, so_imm_not:$imm,
5592+
(ANDri rGPR:$Rdn, rGPR:$Rdn, mod_imm_not:$imm,
55615593
pred:$p, cc_out:$s)>;
55625594
def : ARMInstAlias<"and${s}${p} $Rd, $Rn, $imm",
5563-
(BICri rGPR:$Rd, rGPR:$Rn, so_imm_not:$imm,
5595+
(BICri rGPR:$Rd, rGPR:$Rn, mod_imm_not:$imm,
55645596
pred:$p, cc_out:$s)>;
55655597
def : ARMInstAlias<"and${s}${p} $Rdn, $imm",
5566-
(BICri rGPR:$Rdn, rGPR:$Rdn, so_imm_not:$imm,
5598+
(BICri rGPR:$Rdn, rGPR:$Rdn, mod_imm_not:$imm,
55675599
pred:$p, cc_out:$s)>;
55685600

55695601
// Likewise, "add Rd, so_imm_neg" -> sub
55705602
def : ARMInstAlias<"add${s}${p} $Rd, $Rn, $imm",
5571-
(SUBri GPR:$Rd, GPR:$Rn, so_imm_neg:$imm, pred:$p, cc_out:$s)>;
5603+
(SUBri GPR:$Rd, GPR:$Rn, mod_imm_neg:$imm, pred:$p, cc_out:$s)>;
55725604
def : ARMInstAlias<"add${s}${p} $Rd, $imm",
5573-
(SUBri GPR:$Rd, GPR:$Rd, so_imm_neg:$imm, pred:$p, cc_out:$s)>;
5605+
(SUBri GPR:$Rd, GPR:$Rd, mod_imm_neg:$imm, pred:$p, cc_out:$s)>;
55745606
// Same for CMP <--> CMN via so_imm_neg
55755607
def : ARMInstAlias<"cmp${p} $Rd, $imm",
5576-
(CMNri rGPR:$Rd, so_imm_neg:$imm, pred:$p)>;
5608+
(CMNri rGPR:$Rd, mod_imm_neg:$imm, pred:$p)>;
55775609
def : ARMInstAlias<"cmn${p} $Rd, $imm",
5578-
(CMPri rGPR:$Rd, so_imm_neg:$imm, pred:$p)>;
5610+
(CMPri rGPR:$Rd, mod_imm_neg:$imm, pred:$p)>;
55795611

55805612
// The shifter forms of the MOV instruction are aliased to the ASR, LSL,
55815613
// LSR, ROR, and RRX instructions.

lib/Target/ARM/ARMMCInstLower.cpp

+35-1
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,45 @@ void llvm::LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
119119
ARMAsmPrinter &AP) {
120120
OutMI.setOpcode(MI->getOpcode());
121121

122+
// In the MC layer, we keep modified immediates in their encoded form
123+
bool EncodeImms = false;
124+
switch (MI->getOpcode()) {
125+
default: break;
126+
case ARM::MOVi:
127+
case ARM::MVNi:
128+
case ARM::CMPri:
129+
case ARM::CMNri:
130+
case ARM::TSTri:
131+
case ARM::TEQri:
132+
case ARM::MSRi:
133+
case ARM::ADCri:
134+
case ARM::ADDri:
135+
case ARM::ADDSri:
136+
case ARM::SBCri:
137+
case ARM::SUBri:
138+
case ARM::SUBSri:
139+
case ARM::ANDri:
140+
case ARM::ORRri:
141+
case ARM::EORri:
142+
case ARM::BICri:
143+
case ARM::RSBri:
144+
case ARM::RSBSri:
145+
case ARM::RSCri:
146+
EncodeImms = true;
147+
break;
148+
}
149+
122150
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
123151
const MachineOperand &MO = MI->getOperand(i);
124152

125153
MCOperand MCOp;
126-
if (AP.lowerOperand(MO, MCOp))
154+
if (AP.lowerOperand(MO, MCOp)) {
155+
if (MCOp.isImm() && EncodeImms) {
156+
int32_t Enc = ARM_AM::getSOImmVal(MCOp.getImm());
157+
if (Enc != -1)
158+
MCOp.setImm(Enc);
159+
}
127160
OutMI.addOperand(MCOp);
161+
}
128162
}
129163
}

0 commit comments

Comments
 (0)