1193323Sed//===- ARMInstrInfo.td - Target Description for ARM Target -*- tablegen -*-===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// This file describes the ARM instructions in TableGen format.
11193323Sed//
12193323Sed//===----------------------------------------------------------------------===//
13193323Sed
14193323Sed//===----------------------------------------------------------------------===//
15193323Sed// ARM specific DAG Nodes.
16193323Sed//
17193323Sed
18193323Sed// Type profiles.
19193323Seddef SDT_ARMCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32> ]>;
20193323Seddef SDT_ARMCallSeqEnd   : SDCallSeqEnd<[ SDTCisVT<0, i32>, SDTCisVT<1, i32> ]>;
21245431Sdimdef SDT_ARMStructByVal : SDTypeProfile<0, 4,
22245431Sdim                                       [SDTCisVT<0, i32>, SDTCisVT<1, i32>,
23245431Sdim                                        SDTCisVT<2, i32>, SDTCisVT<3, i32>]>;
24193323Sed
25193323Seddef SDT_ARMSaveCallPC : SDTypeProfile<0, 1, []>;
26193323Sed
27204961Srdivackydef SDT_ARMcall    : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
28193323Sed
29193323Seddef SDT_ARMCMov    : SDTypeProfile<1, 3,
30193323Sed                                   [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
31193323Sed                                    SDTCisVT<3, i32>]>;
32193323Sed
33193323Seddef SDT_ARMBrcond  : SDTypeProfile<0, 2,
34193323Sed                                   [SDTCisVT<0, OtherVT>, SDTCisVT<1, i32>]>;
35193323Sed
36193323Seddef SDT_ARMBrJT    : SDTypeProfile<0, 3,
37193323Sed                                  [SDTCisPtrTy<0>, SDTCisVT<1, i32>,
38193323Sed                                   SDTCisVT<2, i32>]>;
39193323Sed
40198090Srdivackydef SDT_ARMBr2JT   : SDTypeProfile<0, 4,
41198090Srdivacky                                  [SDTCisPtrTy<0>, SDTCisVT<1, i32>,
42198090Srdivacky                                   SDTCisVT<2, i32>, SDTCisVT<3, i32>]>;
43198090Srdivacky
44210299Seddef SDT_ARMBCC_i64 : SDTypeProfile<0, 6,
45210299Sed                                  [SDTCisVT<0, i32>,
46210299Sed                                   SDTCisVT<1, i32>, SDTCisVT<2, i32>,
47210299Sed                                   SDTCisVT<3, i32>, SDTCisVT<4, i32>,
48210299Sed                                   SDTCisVT<5, OtherVT>]>;
49210299Sed
50212904Sdimdef SDT_ARMAnd     : SDTypeProfile<1, 2,
51212904Sdim                                   [SDTCisVT<0, i32>, SDTCisVT<1, i32>,
52212904Sdim                                    SDTCisVT<2, i32>]>;
53212904Sdim
54193323Seddef SDT_ARMCmp     : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>;
55193323Sed
56193323Seddef SDT_ARMPICAdd  : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>,
57193323Sed                                          SDTCisPtrTy<1>, SDTCisVT<2, i32>]>;
58193323Sed
59193323Seddef SDT_ARMThreadPointer : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>;
60203954Srdivackydef SDT_ARMEH_SJLJ_Setjmp : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisPtrTy<1>,
61203954Srdivacky                                                 SDTCisInt<2>]>;
62208599Srdivackydef SDT_ARMEH_SJLJ_Longjmp: SDTypeProfile<0, 2, [SDTCisPtrTy<0>, SDTCisInt<1>]>;
63193323Sed
64218893Sdimdef SDT_ARMMEMBARRIER     : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
65218893Sdim
66224145Sdimdef SDT_ARMPREFETCH : SDTypeProfile<0, 3, [SDTCisPtrTy<0>, SDTCisSameAs<1, 2>,
67224145Sdim                                           SDTCisInt<1>]>;
68224145Sdim
69210299Seddef SDT_ARMTCRET : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>;
70210299Sed
71212904Sdimdef SDT_ARMBFI : SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisVT<1, i32>,
72212904Sdim                                      SDTCisVT<2, i32>, SDTCisVT<3, i32>]>;
73212904Sdim
74263509Sdimdef SDT_ARMVMAXNM : SDTypeProfile<1, 2, [SDTCisFP<0>, SDTCisFP<1>, SDTCisFP<2>]>;
75263509Sdimdef SDT_ARMVMINNM : SDTypeProfile<1, 2, [SDTCisFP<0>, SDTCisFP<1>, SDTCisFP<2>]>;
76263509Sdim
77226890Sdimdef SDTBinaryArithWithFlags : SDTypeProfile<2, 2,
78226890Sdim                                            [SDTCisSameAs<0, 2>,
79226890Sdim                                             SDTCisSameAs<0, 3>,
80226890Sdim                                             SDTCisInt<0>, SDTCisVT<1, i32>]>;
81226890Sdim
82226890Sdim// SDTBinaryArithWithFlagsInOut - RES1, CPSR = op LHS, RHS, CPSR
83226890Sdimdef SDTBinaryArithWithFlagsInOut : SDTypeProfile<2, 3,
84226890Sdim                                            [SDTCisSameAs<0, 2>,
85226890Sdim                                             SDTCisSameAs<0, 3>,
86226890Sdim                                             SDTCisInt<0>,
87226890Sdim                                             SDTCisVT<1, i32>,
88226890Sdim                                             SDTCisVT<4, i32>]>;
89245431Sdim
90245431Sdimdef SDT_ARM64bitmlal : SDTypeProfile<2,4, [ SDTCisVT<0, i32>, SDTCisVT<1, i32>,
91245431Sdim                                        SDTCisVT<2, i32>, SDTCisVT<3, i32>,
92245431Sdim                                        SDTCisVT<4, i32>, SDTCisVT<5, i32> ] >;
93245431Sdimdef ARMUmlal         : SDNode<"ARMISD::UMLAL", SDT_ARM64bitmlal>;
94245431Sdimdef ARMSmlal         : SDNode<"ARMISD::SMLAL", SDT_ARM64bitmlal>;
95245431Sdim
96193323Sed// Node definitions.
97193323Seddef ARMWrapper       : SDNode<"ARMISD::Wrapper",     SDTIntUnaryOp>;
98218893Sdimdef ARMWrapperDYN    : SDNode<"ARMISD::WrapperDYN",  SDTIntUnaryOp>;
99218893Sdimdef ARMWrapperPIC    : SDNode<"ARMISD::WrapperPIC",  SDTIntUnaryOp>;
100193323Seddef ARMWrapperJT     : SDNode<"ARMISD::WrapperJT",   SDTIntBinOp>;
101193323Sed
102193323Seddef ARMcallseq_start : SDNode<"ISD::CALLSEQ_START", SDT_ARMCallSeqStart,
103245431Sdim                              [SDNPHasChain, SDNPSideEffect, SDNPOutGlue]>;
104193323Seddef ARMcallseq_end   : SDNode<"ISD::CALLSEQ_END",   SDT_ARMCallSeqEnd,
105245431Sdim                              [SDNPHasChain, SDNPSideEffect,
106245431Sdim                               SDNPOptInGlue, SDNPOutGlue]>;
107245431Sdimdef ARMcopystructbyval : SDNode<"ARMISD::COPY_STRUCT_BYVAL" ,
108245431Sdim                                SDT_ARMStructByVal,
109245431Sdim                                [SDNPHasChain, SDNPInGlue, SDNPOutGlue,
110245431Sdim                                 SDNPMayStore, SDNPMayLoad]>;
111193323Sed
112193323Seddef ARMcall          : SDNode<"ARMISD::CALL", SDT_ARMcall,
113218893Sdim                              [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
114205407Srdivacky                               SDNPVariadic]>;
115193323Seddef ARMcall_pred    : SDNode<"ARMISD::CALL_PRED", SDT_ARMcall,
116218893Sdim                              [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
117205407Srdivacky                               SDNPVariadic]>;
118193323Seddef ARMcall_nolink   : SDNode<"ARMISD::CALL_NOLINK", SDT_ARMcall,
119218893Sdim                              [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
120205407Srdivacky                               SDNPVariadic]>;
121193323Sed
122193323Seddef ARMretflag       : SDNode<"ARMISD::RET_FLAG", SDTNone,
123252723Sdim                              [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
124263509Sdimdef ARMintretflag    : SDNode<"ARMISD::INTRET_FLAG", SDT_ARMcall,
125263509Sdim                              [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
126193323Seddef ARMcmov          : SDNode<"ARMISD::CMOV", SDT_ARMCMov,
127218893Sdim                              [SDNPInGlue]>;
128193323Sed
129193323Seddef ARMbrcond        : SDNode<"ARMISD::BRCOND", SDT_ARMBrcond,
130218893Sdim                              [SDNPHasChain, SDNPInGlue, SDNPOutGlue]>;
131193323Sed
132193323Seddef ARMbrjt          : SDNode<"ARMISD::BR_JT", SDT_ARMBrJT,
133193323Sed                              [SDNPHasChain]>;
134198090Srdivackydef ARMbr2jt         : SDNode<"ARMISD::BR2_JT", SDT_ARMBr2JT,
135198090Srdivacky                              [SDNPHasChain]>;
136193323Sed
137210299Seddef ARMBcci64        : SDNode<"ARMISD::BCC_i64", SDT_ARMBCC_i64,
138210299Sed                              [SDNPHasChain]>;
139210299Sed
140193323Seddef ARMcmp           : SDNode<"ARMISD::CMP", SDT_ARMCmp,
141218893Sdim                              [SDNPOutGlue]>;
142193323Sed
143245431Sdimdef ARMcmn           : SDNode<"ARMISD::CMN", SDT_ARMCmp,
144245431Sdim                              [SDNPOutGlue]>;
145245431Sdim
146195340Seddef ARMcmpZ          : SDNode<"ARMISD::CMPZ", SDT_ARMCmp,
147218893Sdim                              [SDNPOutGlue, SDNPCommutative]>;
148193323Sed
149193323Seddef ARMpic_add       : SDNode<"ARMISD::PIC_ADD", SDT_ARMPICAdd>;
150193323Sed
151218893Sdimdef ARMsrl_flag      : SDNode<"ARMISD::SRL_FLAG", SDTIntUnaryOp, [SDNPOutGlue]>;
152218893Sdimdef ARMsra_flag      : SDNode<"ARMISD::SRA_FLAG", SDTIntUnaryOp, [SDNPOutGlue]>;
153218893Sdimdef ARMrrx           : SDNode<"ARMISD::RRX"     , SDTIntUnaryOp, [SDNPInGlue ]>;
154193323Sed
155226890Sdimdef ARMaddc          : SDNode<"ARMISD::ADDC",  SDTBinaryArithWithFlags,
156226890Sdim                              [SDNPCommutative]>;
157226890Sdimdef ARMsubc          : SDNode<"ARMISD::SUBC",  SDTBinaryArithWithFlags>;
158226890Sdimdef ARMadde          : SDNode<"ARMISD::ADDE",  SDTBinaryArithWithFlagsInOut>;
159226890Sdimdef ARMsube          : SDNode<"ARMISD::SUBE",  SDTBinaryArithWithFlagsInOut>;
160226890Sdim
161193323Seddef ARMthread_pointer: SDNode<"ARMISD::THREAD_POINTER", SDT_ARMThreadPointer>;
162208599Srdivackydef ARMeh_sjlj_setjmp: SDNode<"ARMISD::EH_SJLJ_SETJMP",
163245431Sdim                               SDT_ARMEH_SJLJ_Setjmp,
164245431Sdim                               [SDNPHasChain, SDNPSideEffect]>;
165208599Srdivackydef ARMeh_sjlj_longjmp: SDNode<"ARMISD::EH_SJLJ_LONGJMP",
166245431Sdim                               SDT_ARMEH_SJLJ_Longjmp,
167245431Sdim                               [SDNPHasChain, SDNPSideEffect]>;
168193323Sed
169218893Sdimdef ARMMemBarrierMCR  : SDNode<"ARMISD::MEMBARRIER_MCR", SDT_ARMMEMBARRIER,
170245431Sdim                               [SDNPHasChain, SDNPSideEffect]>;
171224145Sdimdef ARMPreload        : SDNode<"ARMISD::PRELOAD", SDT_ARMPREFETCH,
172218893Sdim                               [SDNPHasChain, SDNPMayLoad, SDNPMayStore]>;
173200581Srdivacky
174202878Srdivackydef ARMrbit          : SDNode<"ARMISD::RBIT", SDTIntUnaryOp>;
175202878Srdivacky
176218893Sdimdef ARMtcret         : SDNode<"ARMISD::TC_RETURN", SDT_ARMTCRET,
177218893Sdim                        [SDNPHasChain,  SDNPOptInGlue, SDNPVariadic]>;
178210299Sed
179212904Sdimdef ARMbfi           : SDNode<"ARMISD::BFI", SDT_ARMBFI>;
180212904Sdim
181263509Sdimdef ARMvmaxnm        : SDNode<"ARMISD::VMAXNM", SDT_ARMVMAXNM, []>;
182263509Sdimdef ARMvminnm        : SDNode<"ARMISD::VMINNM", SDT_ARMVMINNM, []>;
183263509Sdim
184193323Sed//===----------------------------------------------------------------------===//
185193323Sed// ARM Instruction Predicate Definitions.
186193323Sed//
187224145Sdimdef HasV4T           : Predicate<"Subtarget->hasV4TOps()">,
188245431Sdim                                 AssemblerPredicate<"HasV4TOps", "armv4t">;
189212904Sdimdef NoV4T            : Predicate<"!Subtarget->hasV4TOps()">;
190212904Sdimdef HasV5T           : Predicate<"Subtarget->hasV5TOps()">;
191224145Sdimdef HasV5TE          : Predicate<"Subtarget->hasV5TEOps()">,
192245431Sdim                                 AssemblerPredicate<"HasV5TEOps", "armv5te">;
193224145Sdimdef HasV6            : Predicate<"Subtarget->hasV6Ops()">,
194245431Sdim                                 AssemblerPredicate<"HasV6Ops", "armv6">;
195218893Sdimdef NoV6             : Predicate<"!Subtarget->hasV6Ops()">;
196263509Sdimdef HasV6M           : Predicate<"Subtarget->hasV6MOps()">,
197263509Sdim                                 AssemblerPredicate<"HasV6MOps",
198263509Sdim                                                    "armv6m or armv6t2">;
199224145Sdimdef HasV6T2          : Predicate<"Subtarget->hasV6T2Ops()">,
200245431Sdim                                 AssemblerPredicate<"HasV6T2Ops", "armv6t2">;
201212904Sdimdef NoV6T2           : Predicate<"!Subtarget->hasV6T2Ops()">;
202224145Sdimdef HasV7            : Predicate<"Subtarget->hasV7Ops()">,
203245431Sdim                                 AssemblerPredicate<"HasV7Ops", "armv7">;
204263509Sdimdef HasV8            : Predicate<"Subtarget->hasV8Ops()">,
205263509Sdim                                 AssemblerPredicate<"HasV8Ops", "armv8">;
206263509Sdimdef PreV8            : Predicate<"!Subtarget->hasV8Ops()">,
207263509Sdim                                 AssemblerPredicate<"!HasV8Ops", "armv7 or earlier">;
208212904Sdimdef NoVFP            : Predicate<"!Subtarget->hasVFP2()">;
209224145Sdimdef HasVFP2          : Predicate<"Subtarget->hasVFP2()">,
210245431Sdim                                 AssemblerPredicate<"FeatureVFP2", "VFP2">;
211224145Sdimdef HasVFP3          : Predicate<"Subtarget->hasVFP3()">,
212245431Sdim                                 AssemblerPredicate<"FeatureVFP3", "VFP3">;
213235633Sdimdef HasVFP4          : Predicate<"Subtarget->hasVFP4()">,
214245431Sdim                                 AssemblerPredicate<"FeatureVFP4", "VFP4">;
215263509Sdimdef HasDPVFP         : Predicate<"!Subtarget->isFPOnlySP()">,
216263509Sdim                                 AssemblerPredicate<"!FeatureVFPOnlySP",
217263509Sdim                                                    "double precision VFP">;
218263509Sdimdef HasFPARMv8       : Predicate<"Subtarget->hasFPARMv8()">,
219263509Sdim                                 AssemblerPredicate<"FeatureFPARMv8", "FPARMv8">;
220224145Sdimdef HasNEON          : Predicate<"Subtarget->hasNEON()">,
221245431Sdim                                 AssemblerPredicate<"FeatureNEON", "NEON">;
222263509Sdimdef HasCrypto        : Predicate<"Subtarget->hasCrypto()">,
223263509Sdim                                 AssemblerPredicate<"FeatureCrypto", "crypto">;
224263509Sdimdef HasCRC           : Predicate<"Subtarget->hasCRC()">,
225263509Sdim                                 AssemblerPredicate<"FeatureCRC", "crc">;
226224145Sdimdef HasFP16          : Predicate<"Subtarget->hasFP16()">,
227245431Sdim                                 AssemblerPredicate<"FeatureFP16","half-float">;
228224145Sdimdef HasDivide        : Predicate<"Subtarget->hasDivide()">,
229263509Sdim                                 AssemblerPredicate<"FeatureHWDiv", "divide in THUMB">;
230245431Sdimdef HasDivideInARM   : Predicate<"Subtarget->hasDivideInARMMode()">,
231263509Sdim                                 AssemblerPredicate<"FeatureHWDivARM", "divide in ARM">;
232218893Sdimdef HasT2ExtractPack : Predicate<"Subtarget->hasT2ExtractPack()">,
233245431Sdim                                 AssemblerPredicate<"FeatureT2XtPk",
234245431Sdim                                                     "pack/extract">;
235224145Sdimdef HasThumb2DSP     : Predicate<"Subtarget->hasThumb2DSP()">,
236245431Sdim                                 AssemblerPredicate<"FeatureDSPThumb2",
237245431Sdim                                                    "thumb2-dsp">;
238218893Sdimdef HasDB            : Predicate<"Subtarget->hasDataBarrier()">,
239245431Sdim                                 AssemblerPredicate<"FeatureDB",
240245431Sdim                                                    "data-barriers">;
241218893Sdimdef HasMP            : Predicate<"Subtarget->hasMPExtension()">,
242245431Sdim                                 AssemblerPredicate<"FeatureMP",
243245431Sdim                                                    "mp-extensions">;
244252723Sdimdef HasTrustZone     : Predicate<"Subtarget->hasTrustZone()">,
245252723Sdim                                 AssemblerPredicate<"FeatureTrustZone",
246252723Sdim                                                    "TrustZone">;
247212904Sdimdef UseNEONForFP     : Predicate<"Subtarget->useNEONForSinglePrecisionFP()">;
248198090Srdivackydef DontUseNEONForFP : Predicate<"!Subtarget->useNEONForSinglePrecisionFP()">;
249224145Sdimdef IsThumb          : Predicate<"Subtarget->isThumb()">,
250245431Sdim                                 AssemblerPredicate<"ModeThumb", "thumb">;
251212904Sdimdef IsThumb1Only     : Predicate<"Subtarget->isThumb1Only()">;
252224145Sdimdef IsThumb2         : Predicate<"Subtarget->isThumb2()">,
253245431Sdim                                 AssemblerPredicate<"ModeThumb,FeatureThumb2",
254245431Sdim                                                    "thumb2">;
255226890Sdimdef IsMClass         : Predicate<"Subtarget->isMClass()">,
256263509Sdim                                 AssemblerPredicate<"FeatureMClass", "armv*m">;
257263509Sdimdef IsNotMClass      : Predicate<"!Subtarget->isMClass()">,
258245431Sdim                                 AssemblerPredicate<"!FeatureMClass",
259263509Sdim                                                    "!armv*m">;
260224145Sdimdef IsARM            : Predicate<"!Subtarget->isThumb()">,
261245431Sdim                                 AssemblerPredicate<"!ModeThumb", "arm-mode">;
262235633Sdimdef IsIOS            : Predicate<"Subtarget->isTargetIOS()">;
263235633Sdimdef IsNotIOS         : Predicate<"!Subtarget->isTargetIOS()">;
264235633Sdimdef IsNaCl           : Predicate<"Subtarget->isTargetNaCl()">;
265252723Sdimdef UseNaClTrap      : Predicate<"Subtarget->useNaClTrap()">,
266252723Sdim                                 AssemblerPredicate<"FeatureNaClTrap", "NaCl">;
267252723Sdimdef DontUseNaClTrap  : Predicate<"!Subtarget->useNaClTrap()">;
268193323Sed
269199989Srdivacky// FIXME: Eventually this will be just "hasV6T2Ops".
270212904Sdimdef UseMovt          : Predicate<"Subtarget->useMovt()">;
271212904Sdimdef DontUseMovt      : Predicate<"!Subtarget->useMovt()">;
272218893Sdimdef UseFPVMLx        : Predicate<"Subtarget->useFPVMLx()">;
273245431Sdimdef UseMulOps        : Predicate<"Subtarget->useMulOps()">;
274199989Srdivacky
275235633Sdim// Prefer fused MAC for fp mul + add over fp VMLA / VMLS if they are available.
276235633Sdim// But only select them if more precision in FP computation is allowed.
277235633Sdim// Do not use them for Darwin platforms.
278245431Sdimdef UseFusedMAC      : Predicate<"(TM.Options.AllowFPOpFusion =="
279245431Sdim                                 " FPOpFusion::Fast) && "
280235633Sdim                                 "!Subtarget->isTargetDarwin()">;
281263509Sdimdef DontUseFusedMAC  : Predicate<"!(TM.Options.AllowFPOpFusion =="
282263509Sdim                                 " FPOpFusion::Fast &&"
283263509Sdim                                 " Subtarget->hasVFP4()) || "
284235633Sdim                                 "Subtarget->isTargetDarwin()">;
285235633Sdim
286245431Sdim// VGETLNi32 is microcoded on Swift - prefer VMOV.
287245431Sdimdef HasFastVGETLNi32 : Predicate<"!Subtarget->isSwift()">;
288245431Sdimdef HasSlowVGETLNi32 : Predicate<"Subtarget->isSwift()">;
289245431Sdim
290245431Sdim// VDUP.32 is microcoded on Swift - prefer VMOV.
291245431Sdimdef HasFastVDUP32 : Predicate<"!Subtarget->isSwift()">;
292245431Sdimdef HasSlowVDUP32 : Predicate<"Subtarget->isSwift()">;
293245431Sdim
294245431Sdim// Cortex-A9 prefers VMOVSR to VMOVDRR even when using NEON for scalar FP, as
295245431Sdim// this allows more effective execution domain optimization. See
296245431Sdim// setExecutionDomain().
297245431Sdimdef UseVMOVSR : Predicate<"Subtarget->isCortexA9() || !Subtarget->useNEONForSinglePrecisionFP()">;
298245431Sdimdef DontUseVMOVSR : Predicate<"!Subtarget->isCortexA9() && Subtarget->useNEONForSinglePrecisionFP()">;
299245431Sdim
300263509Sdimdef IsLE             : Predicate<"getTargetLowering()->isLittleEndian()">;
301263509Sdimdef IsBE             : Predicate<"getTargetLowering()->isBigEndian()">;
302245431Sdim
303193323Sed//===----------------------------------------------------------------------===//
304193323Sed// ARM Flag Definitions.
305193323Sed
306193323Sedclass RegConstraint<string C> {
307193323Sed  string Constraints = C;
308193323Sed}
309193323Sed
310193323Sed//===----------------------------------------------------------------------===//
311193323Sed//  ARM specific transformation functions and pattern fragments.
312193323Sed//
313193323Sed
314245431Sdim// imm_neg_XFORM - Return the negation of an i32 immediate value.
315245431Sdimdef imm_neg_XFORM : SDNodeXForm<imm, [{
316198090Srdivacky  return CurDAG->getTargetConstant(-(int)N->getZExtValue(), MVT::i32);
317193323Sed}]>;
318193323Sed
319245431Sdim// imm_not_XFORM - Return the complement of a i32 immediate value.
320245431Sdimdef imm_not_XFORM : SDNodeXForm<imm, [{
321198090Srdivacky  return CurDAG->getTargetConstant(~(int)N->getZExtValue(), MVT::i32);
322193323Sed}]>;
323193323Sed
324193323Sed/// imm16_31 predicate - True if the 32-bit immediate is in the range [16,31].
325221345Sdimdef imm16_31 : ImmLeaf<i32, [{
326221345Sdim  return (int32_t)Imm >= 16 && (int32_t)Imm < 32;
327193323Sed}]>;
328193323Sed
329235633Sdimdef so_imm_neg_asmoperand : AsmOperandClass { let Name = "ARMSOImmNeg"; }
330235633Sdimdef so_imm_neg : Operand<i32>, PatLeaf<(imm), [{
331245431Sdim    unsigned Value = -(unsigned)N->getZExtValue();
332235633Sdim    return Value && ARM_AM::getSOImmVal(Value) != -1;
333245431Sdim  }], imm_neg_XFORM> {
334235633Sdim  let ParserMatchClass = so_imm_neg_asmoperand;
335235633Sdim}
336193323Sed
337235633Sdim// Note: this pattern doesn't require an encoder method and such, as it's
338235633Sdim// only used on aliases (Pat<> and InstAlias<>). The actual encoding
339235633Sdim// is handled by the destination instructions, which use so_imm.
340235633Sdimdef so_imm_not_asmoperand : AsmOperandClass { let Name = "ARMSOImmNot"; }
341235633Sdimdef so_imm_not : Operand<i32>, PatLeaf<(imm), [{
342218893Sdim    return ARM_AM::getSOImmVal(~(uint32_t)N->getZExtValue()) != -1;
343245431Sdim  }], imm_not_XFORM> {
344235633Sdim  let ParserMatchClass = so_imm_not_asmoperand;
345235633Sdim}
346193323Sed
347193323Sed// sext_16_node predicate - True if the SDNode is sign-extended 16 or more bits.
348193323Seddef sext_16_node : PatLeaf<(i32 GPR:$a), [{
349193323Sed  return CurDAG->ComputeNumSignBits(SDValue(N,0)) >= 17;
350193323Sed}]>;
351193323Sed
352198090Srdivacky/// Split a 32-bit immediate into two 16 bit parts.
353198090Srdivackydef hi16 : SDNodeXForm<imm, [{
354198090Srdivacky  return CurDAG->getTargetConstant((uint32_t)N->getZExtValue() >> 16, MVT::i32);
355198090Srdivacky}]>;
356198090Srdivacky
357198090Srdivackydef lo16AllZero : PatLeaf<(i32 imm), [{
358198090Srdivacky  // Returns true if all low 16-bits are 0.
359198090Srdivacky  return (((uint32_t)N->getZExtValue()) & 0xFFFFUL) == 0;
360199989Srdivacky}], hi16>;
361198090Srdivacky
362226890Sdimclass BinOpWithFlagFrag<dag res> :
363226890Sdim      PatFrag<(ops node:$LHS, node:$RHS, node:$FLAG), res>;
364193323Sedclass BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
365193323Sedclass UnOpFrag <dag res> : PatFrag<(ops node:$Src), res>;
366193323Sed
367218893Sdim// An 'and' node with a single use.
368218893Sdimdef and_su : PatFrag<(ops node:$lhs, node:$rhs), (and node:$lhs, node:$rhs), [{
369218893Sdim  return N->hasOneUse();
370218893Sdim}]>;
371218893Sdim
372218893Sdim// An 'xor' node with a single use.
373218893Sdimdef xor_su : PatFrag<(ops node:$lhs, node:$rhs), (xor node:$lhs, node:$rhs), [{
374218893Sdim  return N->hasOneUse();
375218893Sdim}]>;
376218893Sdim
377218893Sdim// An 'fmul' node with a single use.
378218893Sdimdef fmul_su : PatFrag<(ops node:$lhs, node:$rhs), (fmul node:$lhs, node:$rhs),[{
379218893Sdim  return N->hasOneUse();
380218893Sdim}]>;
381218893Sdim
382218893Sdim// An 'fadd' node which checks for single non-hazardous use.
383218893Sdimdef fadd_mlx : PatFrag<(ops node:$lhs, node:$rhs),(fadd node:$lhs, node:$rhs),[{
384218893Sdim  return hasNoVMLxHazardUse(N);
385218893Sdim}]>;
386218893Sdim
387218893Sdim// An 'fsub' node which checks for single non-hazardous use.
388218893Sdimdef fsub_mlx : PatFrag<(ops node:$lhs, node:$rhs),(fsub node:$lhs, node:$rhs),[{
389218893Sdim  return hasNoVMLxHazardUse(N);
390218893Sdim}]>;
391218893Sdim
392193323Sed//===----------------------------------------------------------------------===//
393193323Sed// Operand Definitions.
394193323Sed//
395193323Sed
396235633Sdim// Immediate operands with a shared generic asm render method.
397235633Sdimclass ImmAsmOperand : AsmOperandClass { let RenderMethod = "addImmOperands"; }
398235633Sdim
399193323Sed// Branch target.
400218893Sdim// FIXME: rename brtarget to t2_brtarget
401218893Sdimdef brtarget : Operand<OtherVT> {
402218893Sdim  let EncoderMethod = "getBranchTargetOpValue";
403224145Sdim  let OperandType = "OPERAND_PCREL";
404226890Sdim  let DecoderMethod = "DecodeT2BROperand";
405218893Sdim}
406193323Sed
407218893Sdim// FIXME: get rid of this one?
408218893Sdimdef uncondbrtarget : Operand<OtherVT> {
409218893Sdim  let EncoderMethod = "getUnconditionalBranchTargetOpValue";
410224145Sdim  let OperandType = "OPERAND_PCREL";
411218893Sdim}
412218893Sdim
413218893Sdim// Branch target for ARM. Handles conditional/unconditional
414218893Sdimdef br_target : Operand<OtherVT> {
415218893Sdim  let EncoderMethod = "getARMBranchTargetOpValue";
416224145Sdim  let OperandType = "OPERAND_PCREL";
417218893Sdim}
418218893Sdim
419218893Sdim// Call target.
420218893Sdim// FIXME: rename bltarget to t2_bl_target?
421218893Sdimdef bltarget : Operand<i32> {
422218893Sdim  // Encoded the same as branch targets.
423218893Sdim  let EncoderMethod = "getBranchTargetOpValue";
424224145Sdim  let OperandType = "OPERAND_PCREL";
425218893Sdim}
426218893Sdim
427218893Sdim// Call target for ARM. Handles conditional/unconditional
428218893Sdim// FIXME: rename bl_target to t2_bltarget?
429218893Sdimdef bl_target : Operand<i32> {
430235633Sdim  let EncoderMethod = "getARMBLTargetOpValue";
431224145Sdim  let OperandType = "OPERAND_PCREL";
432218893Sdim}
433218893Sdim
434226890Sdimdef blx_target : Operand<i32> {
435226890Sdim  let EncoderMethod = "getARMBLXTargetOpValue";
436226890Sdim  let OperandType = "OPERAND_PCREL";
437226890Sdim}
438218893Sdim
439193323Sed// A list of registers separated by comma. Used by load/store multiple.
440226890Sdimdef RegListAsmOperand : AsmOperandClass { let Name = "RegList"; }
441193323Seddef reglist : Operand<i32> {
442218893Sdim  let EncoderMethod = "getRegisterListOpValue";
443218893Sdim  let ParserMatchClass = RegListAsmOperand;
444193323Sed  let PrintMethod = "printRegisterList";
445226890Sdim  let DecoderMethod = "DecodeRegListOperand";
446193323Sed}
447193323Sed
448252723Sdimdef GPRPairOp : RegisterOperand<GPRPair, "printGPRPairOperand">;
449252723Sdim
450226890Sdimdef DPRRegListAsmOperand : AsmOperandClass { let Name = "DPRRegList"; }
451218893Sdimdef dpr_reglist : Operand<i32> {
452218893Sdim  let EncoderMethod = "getRegisterListOpValue";
453218893Sdim  let ParserMatchClass = DPRRegListAsmOperand;
454218893Sdim  let PrintMethod = "printRegisterList";
455226890Sdim  let DecoderMethod = "DecodeDPRRegListOperand";
456218893Sdim}
457218893Sdim
458226890Sdimdef SPRRegListAsmOperand : AsmOperandClass { let Name = "SPRRegList"; }
459218893Sdimdef spr_reglist : Operand<i32> {
460218893Sdim  let EncoderMethod = "getRegisterListOpValue";
461218893Sdim  let ParserMatchClass = SPRRegListAsmOperand;
462218893Sdim  let PrintMethod = "printRegisterList";
463226890Sdim  let DecoderMethod = "DecodeSPRRegListOperand";
464218893Sdim}
465218893Sdim
466193323Sed// An operand for the CONSTPOOL_ENTRY pseudo-instruction.
467193323Seddef cpinst_operand : Operand<i32> {
468193323Sed  let PrintMethod = "printCPInstOperand";
469193323Sed}
470193323Sed
471193323Sed// Local PC labels.
472193323Seddef pclabel : Operand<i32> {
473193323Sed  let PrintMethod = "printPCLabel";
474193323Sed}
475193323Sed
476218893Sdim// ADR instruction labels.
477245431Sdimdef AdrLabelAsmOperand : AsmOperandClass { let Name = "AdrLabel"; }
478218893Sdimdef adrlabel : Operand<i32> {
479218893Sdim  let EncoderMethod = "getAdrLabelOpValue";
480245431Sdim  let ParserMatchClass = AdrLabelAsmOperand;
481263509Sdim  let PrintMethod = "printAdrLabelOperand<0>";
482218893Sdim}
483218893Sdim
484218893Sdimdef neon_vcvt_imm32 : Operand<i32> {
485218893Sdim  let EncoderMethod = "getNEONVcvtImm32OpValue";
486226890Sdim  let DecoderMethod = "DecodeVCVTImmOperand";
487218893Sdim}
488218893Sdim
489218893Sdim// rot_imm: An integer that encodes a rotate amount. Must be 8, 16, or 24.
490226890Sdimdef rot_imm_XFORM: SDNodeXForm<imm, [{
491226890Sdim  switch (N->getZExtValue()){
492226890Sdim  default: assert(0);
493226890Sdim  case 0:  return CurDAG->getTargetConstant(0, MVT::i32);
494226890Sdim  case 8:  return CurDAG->getTargetConstant(1, MVT::i32);
495226890Sdim  case 16: return CurDAG->getTargetConstant(2, MVT::i32);
496226890Sdim  case 24: return CurDAG->getTargetConstant(3, MVT::i32);
497226890Sdim  }
498226890Sdim}]>;
499226890Sdimdef RotImmAsmOperand : AsmOperandClass {
500226890Sdim  let Name = "RotImm";
501226890Sdim  let ParserMethod = "parseRotImm";
502218893Sdim}
503226890Sdimdef rot_imm : Operand<i32>, PatLeaf<(i32 imm), [{
504226890Sdim    int32_t v = N->getZExtValue();
505226890Sdim    return v == 8 || v == 16 || v == 24; }],
506226890Sdim    rot_imm_XFORM> {
507226890Sdim  let PrintMethod = "printRotImmOperand";
508226890Sdim  let ParserMatchClass = RotImmAsmOperand;
509221345Sdim}
510221345Sdim
511212904Sdim// shift_imm: An integer that encodes a shift amount and the type of shift
512226890Sdim// (asr or lsl). The 6-bit immediate encodes as:
513226890Sdim//    {5}     0 ==> lsl
514226890Sdim//            1     asr
515226890Sdim//    {4-0}   imm5 shift amount.
516226890Sdim//            asr #32 encoded as imm5 == 0.
517226890Sdimdef ShifterImmAsmOperand : AsmOperandClass {
518226890Sdim  let Name = "ShifterImm";
519226890Sdim  let ParserMethod = "parseShifterImm";
520226890Sdim}
521212904Sdimdef shift_imm : Operand<i32> {
522212904Sdim  let PrintMethod = "printShiftImmOperand";
523226890Sdim  let ParserMatchClass = ShifterImmAsmOperand;
524212904Sdim}
525212904Sdim
526226890Sdim// shifter_operand operands: so_reg_reg, so_reg_imm, and so_imm.
527226890Sdimdef ShiftedRegAsmOperand : AsmOperandClass { let Name = "RegShiftedReg"; }
528226890Sdimdef so_reg_reg : Operand<i32>,  // reg reg imm
529226890Sdim                 ComplexPattern<i32, 3, "SelectRegShifterOperand",
530226890Sdim                                [shl, srl, sra, rotr]> {
531226890Sdim  let EncoderMethod = "getSORegRegOpValue";
532226890Sdim  let PrintMethod = "printSORegRegOperand";
533226890Sdim  let DecoderMethod = "DecodeSORegRegOperand";
534226890Sdim  let ParserMatchClass = ShiftedRegAsmOperand;
535226890Sdim  let MIOperandInfo = (ops GPRnopc, GPRnopc, i32imm);
536224145Sdim}
537224145Sdim
538226890Sdimdef ShiftedImmAsmOperand : AsmOperandClass { let Name = "RegShiftedImm"; }
539226890Sdimdef so_reg_imm : Operand<i32>, // reg imm
540226890Sdim                 ComplexPattern<i32, 2, "SelectImmShifterOperand",
541226890Sdim                                [shl, srl, sra, rotr]> {
542226890Sdim  let EncoderMethod = "getSORegImmOpValue";
543226890Sdim  let PrintMethod = "printSORegImmOperand";
544226890Sdim  let DecoderMethod = "DecodeSORegImmOperand";
545226890Sdim  let ParserMatchClass = ShiftedImmAsmOperand;
546226890Sdim  let MIOperandInfo = (ops GPR, i32imm);
547193323Sed}
548226890Sdim
549224145Sdim// FIXME: Does this need to be distinct from so_reg?
550226890Sdimdef shift_so_reg_reg : Operand<i32>,    // reg reg imm
551226890Sdim                   ComplexPattern<i32, 3, "SelectShiftRegShifterOperand",
552218893Sdim                                  [shl,srl,sra,rotr]> {
553226890Sdim  let EncoderMethod = "getSORegRegOpValue";
554226890Sdim  let PrintMethod = "printSORegRegOperand";
555226890Sdim  let DecoderMethod = "DecodeSORegRegOperand";
556235633Sdim  let ParserMatchClass = ShiftedRegAsmOperand;
557226890Sdim  let MIOperandInfo = (ops GPR, GPR, i32imm);
558218893Sdim}
559193323Sed
560226890Sdim// FIXME: Does this need to be distinct from so_reg?
561226890Sdimdef shift_so_reg_imm : Operand<i32>,    // reg reg imm
562226890Sdim                   ComplexPattern<i32, 2, "SelectShiftImmShifterOperand",
563226890Sdim                                  [shl,srl,sra,rotr]> {
564226890Sdim  let EncoderMethod = "getSORegImmOpValue";
565226890Sdim  let PrintMethod = "printSORegImmOperand";
566226890Sdim  let DecoderMethod = "DecodeSORegImmOperand";
567235633Sdim  let ParserMatchClass = ShiftedImmAsmOperand;
568226890Sdim  let MIOperandInfo = (ops GPR, i32imm);
569226890Sdim}
570226890Sdim
571226890Sdim
572193323Sed// so_imm - Match a 32-bit shifter_operand immediate operand, which is an
573218893Sdim// 8-bit immediate rotated by an arbitrary number of bits.
574235633Sdimdef SOImmAsmOperand: ImmAsmOperand { let Name = "ARMSOImm"; }
575221345Sdimdef so_imm : Operand<i32>, ImmLeaf<i32, [{
576221345Sdim    return ARM_AM::getSOImmVal(Imm) != -1;
577221345Sdim  }]> {
578218893Sdim  let EncoderMethod = "getSOImmOpValue";
579226890Sdim  let ParserMatchClass = SOImmAsmOperand;
580226890Sdim  let DecoderMethod = "DecodeSOImmOperand";
581193323Sed}
582193323Sed
583193323Sed// Break so_imm's up into two pieces.  This handles immediates with up to 16
584193323Sed// bits set in them.  This uses so_imm2part to match and so_imm2part_[12] to
585193323Sed// get the first/second pieces.
586218893Sdimdef so_imm2part : PatLeaf<(imm), [{
587193323Sed      return ARM_AM::isSOImmTwoPartVal((unsigned)N->getZExtValue());
588218893Sdim}]>;
589193323Sed
590218893Sdim/// arm_i32imm - True for +V6T2, or true only if so_imm2part is true.
591218893Sdim///
592218893Sdimdef arm_i32imm : PatLeaf<(imm), [{
593218893Sdim  if (Subtarget->hasV6T2Ops())
594218893Sdim    return true;
595218893Sdim  return ARM_AM::isSOImmTwoPartVal((unsigned)N->getZExtValue());
596193323Sed}]>;
597193323Sed
598235633Sdim/// imm0_1 predicate - Immediate in the range [0,1].
599235633Sdimdef Imm0_1AsmOperand: ImmAsmOperand { let Name = "Imm0_1"; }
600235633Sdimdef imm0_1 : Operand<i32> { let ParserMatchClass = Imm0_1AsmOperand; }
601235633Sdim
602235633Sdim/// imm0_3 predicate - Immediate in the range [0,3].
603235633Sdimdef Imm0_3AsmOperand: ImmAsmOperand { let Name = "Imm0_3"; }
604235633Sdimdef imm0_3 : Operand<i32> { let ParserMatchClass = Imm0_3AsmOperand; }
605235633Sdim
606226890Sdim/// imm0_7 predicate - Immediate in the range [0,7].
607235633Sdimdef Imm0_7AsmOperand: ImmAsmOperand { let Name = "Imm0_7"; }
608224145Sdimdef imm0_7 : Operand<i32>, ImmLeaf<i32, [{
609224145Sdim  return Imm >= 0 && Imm < 8;
610224145Sdim}]> {
611224145Sdim  let ParserMatchClass = Imm0_7AsmOperand;
612224145Sdim}
613224145Sdim
614235633Sdim/// imm8 predicate - Immediate is exactly 8.
615235633Sdimdef Imm8AsmOperand: ImmAsmOperand { let Name = "Imm8"; }
616235633Sdimdef imm8 : Operand<i32>, ImmLeaf<i32, [{ return Imm == 8; }]> {
617235633Sdim  let ParserMatchClass = Imm8AsmOperand;
618235633Sdim}
619235633Sdim
620235633Sdim/// imm16 predicate - Immediate is exactly 16.
621235633Sdimdef Imm16AsmOperand: ImmAsmOperand { let Name = "Imm16"; }
622235633Sdimdef imm16 : Operand<i32>, ImmLeaf<i32, [{ return Imm == 16; }]> {
623235633Sdim  let ParserMatchClass = Imm16AsmOperand;
624235633Sdim}
625235633Sdim
626235633Sdim/// imm32 predicate - Immediate is exactly 32.
627235633Sdimdef Imm32AsmOperand: ImmAsmOperand { let Name = "Imm32"; }
628235633Sdimdef imm32 : Operand<i32>, ImmLeaf<i32, [{ return Imm == 32; }]> {
629235633Sdim  let ParserMatchClass = Imm32AsmOperand;
630235633Sdim}
631235633Sdim
632235633Sdim/// imm1_7 predicate - Immediate in the range [1,7].
633235633Sdimdef Imm1_7AsmOperand: ImmAsmOperand { let Name = "Imm1_7"; }
634235633Sdimdef imm1_7 : Operand<i32>, ImmLeaf<i32, [{ return Imm > 0 && Imm < 8; }]> {
635235633Sdim  let ParserMatchClass = Imm1_7AsmOperand;
636235633Sdim}
637235633Sdim
638235633Sdim/// imm1_15 predicate - Immediate in the range [1,15].
639235633Sdimdef Imm1_15AsmOperand: ImmAsmOperand { let Name = "Imm1_15"; }
640235633Sdimdef imm1_15 : Operand<i32>, ImmLeaf<i32, [{ return Imm > 0 && Imm < 16; }]> {
641235633Sdim  let ParserMatchClass = Imm1_15AsmOperand;
642235633Sdim}
643235633Sdim
644235633Sdim/// imm1_31 predicate - Immediate in the range [1,31].
645235633Sdimdef Imm1_31AsmOperand: ImmAsmOperand { let Name = "Imm1_31"; }
646235633Sdimdef imm1_31 : Operand<i32>, ImmLeaf<i32, [{ return Imm > 0 && Imm < 32; }]> {
647235633Sdim  let ParserMatchClass = Imm1_31AsmOperand;
648235633Sdim}
649235633Sdim
650226890Sdim/// imm0_15 predicate - Immediate in the range [0,15].
651245431Sdimdef Imm0_15AsmOperand: ImmAsmOperand {
652245431Sdim  let Name = "Imm0_15";
653245431Sdim  let DiagnosticType = "ImmRange0_15";
654245431Sdim}
655224145Sdimdef imm0_15 : Operand<i32>, ImmLeaf<i32, [{
656224145Sdim  return Imm >= 0 && Imm < 16;
657224145Sdim}]> {
658224145Sdim  let ParserMatchClass = Imm0_15AsmOperand;
659224145Sdim}
660224145Sdim
661218893Sdim/// imm0_31 predicate - True if the 32-bit immediate is in the range [0,31].
662235633Sdimdef Imm0_31AsmOperand: ImmAsmOperand { let Name = "Imm0_31"; }
663221345Sdimdef imm0_31 : Operand<i32>, ImmLeaf<i32, [{
664221345Sdim  return Imm >= 0 && Imm < 32;
665218893Sdim}]> {
666226890Sdim  let ParserMatchClass = Imm0_31AsmOperand;
667199989Srdivacky}
668199989Srdivacky
669235633Sdim/// imm0_32 predicate - True if the 32-bit immediate is in the range [0,32].
670235633Sdimdef Imm0_32AsmOperand: ImmAsmOperand { let Name = "Imm0_32"; }
671235633Sdimdef imm0_32 : Operand<i32>, ImmLeaf<i32, [{
672235633Sdim  return Imm >= 0 && Imm < 32;
673235633Sdim}]> {
674235633Sdim  let ParserMatchClass = Imm0_32AsmOperand;
675235633Sdim}
676235633Sdim
677235633Sdim/// imm0_63 predicate - True if the 32-bit immediate is in the range [0,63].
678235633Sdimdef Imm0_63AsmOperand: ImmAsmOperand { let Name = "Imm0_63"; }
679235633Sdimdef imm0_63 : Operand<i32>, ImmLeaf<i32, [{
680235633Sdim  return Imm >= 0 && Imm < 64;
681235633Sdim}]> {
682235633Sdim  let ParserMatchClass = Imm0_63AsmOperand;
683235633Sdim}
684235633Sdim
685263509Sdim/// imm0_239 predicate - Immediate in the range [0,239].
686263509Sdimdef Imm0_239AsmOperand : ImmAsmOperand {
687263509Sdim  let Name = "Imm0_239";
688263509Sdim  let DiagnosticType = "ImmRange0_239";
689263509Sdim}
690263509Sdimdef imm0_239 : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 240; }]> {
691263509Sdim  let ParserMatchClass = Imm0_239AsmOperand;
692263509Sdim}
693263509Sdim
694226890Sdim/// imm0_255 predicate - Immediate in the range [0,255].
695235633Sdimdef Imm0_255AsmOperand : ImmAsmOperand { let Name = "Imm0_255"; }
696226890Sdimdef imm0_255 : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 256; }]> {
697226890Sdim  let ParserMatchClass = Imm0_255AsmOperand;
698226890Sdim}
699226890Sdim
700235633Sdim/// imm0_65535 - An immediate is in the range [0.65535].
701235633Sdimdef Imm0_65535AsmOperand: ImmAsmOperand { let Name = "Imm0_65535"; }
702235633Sdimdef imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
703235633Sdim  return Imm >= 0 && Imm < 65536;
704235633Sdim}]> {
705235633Sdim  let ParserMatchClass = Imm0_65535AsmOperand;
706235633Sdim}
707235633Sdim
708245431Sdim// imm0_65535_neg - An immediate whose negative value is in the range [0.65535].
709245431Sdimdef imm0_65535_neg : Operand<i32>, ImmLeaf<i32, [{
710245431Sdim  return -Imm >= 0 && -Imm < 65536;
711245431Sdim}]>;
712245431Sdim
713226890Sdim// imm0_65535_expr - For movt/movw - 16-bit immediate that can also reference
714226890Sdim// a relocatable expression.
715218893Sdim//
716226890Sdim// FIXME: This really needs a Thumb version separate from the ARM version.
717226890Sdim// While the range is the same, and can thus use the same match class,
718226890Sdim// the encoding is different so it should have a different encoder method.
719235633Sdimdef Imm0_65535ExprAsmOperand: ImmAsmOperand { let Name = "Imm0_65535Expr"; }
720226890Sdimdef imm0_65535_expr : Operand<i32> {
721218893Sdim  let EncoderMethod = "getHiLo16ImmOpValue";
722226890Sdim  let ParserMatchClass = Imm0_65535ExprAsmOperand;
723218893Sdim}
724199989Srdivacky
725263509Sdimdef Imm256_65535ExprAsmOperand: ImmAsmOperand { let Name = "Imm256_65535Expr"; }
726263509Sdimdef imm256_65535_expr : Operand<i32> {
727263509Sdim  let ParserMatchClass = Imm256_65535ExprAsmOperand;
728263509Sdim}
729263509Sdim
730226890Sdim/// imm24b - True if the 32-bit immediate is encodable in 24 bits.
731235633Sdimdef Imm24bitAsmOperand: ImmAsmOperand { let Name = "Imm24bit"; }
732226890Sdimdef imm24b : Operand<i32>, ImmLeaf<i32, [{
733226890Sdim  return Imm >= 0 && Imm <= 0xffffff;
734226890Sdim}]> {
735226890Sdim  let ParserMatchClass = Imm24bitAsmOperand;
736226890Sdim}
737226890Sdim
738226890Sdim
739218893Sdim/// bf_inv_mask_imm predicate - An AND mask to clear an arbitrary width bitfield
740218893Sdim/// e.g., 0xf000ffff
741226890Sdimdef BitfieldAsmOperand : AsmOperandClass {
742226890Sdim  let Name = "Bitfield";
743226890Sdim  let ParserMethod = "parseBitfield";
744226890Sdim}
745235633Sdim
746218893Sdimdef bf_inv_mask_imm : Operand<i32>,
747218893Sdim                      PatLeaf<(imm), [{
748218893Sdim  return ARM::isBitFieldInvertedMask(N->getZExtValue());
749218893Sdim}] > {
750218893Sdim  let EncoderMethod = "getBitfieldInvertedMaskOpValue";
751218893Sdim  let PrintMethod = "printBitfieldInvMaskImmOperand";
752226890Sdim  let DecoderMethod = "DecodeBitfieldMaskOperand";
753226890Sdim  let ParserMatchClass = BitfieldAsmOperand;
754218893Sdim}
755199989Srdivacky
756226890Sdimdef imm1_32_XFORM: SDNodeXForm<imm, [{
757226890Sdim  return CurDAG->getTargetConstant((int)N->getZExtValue() - 1, MVT::i32);
758198090Srdivacky}]>;
759226890Sdimdef Imm1_32AsmOperand: AsmOperandClass { let Name = "Imm1_32"; }
760226890Sdimdef imm1_32 : Operand<i32>, PatLeaf<(imm), [{
761226890Sdim   uint64_t Imm = N->getZExtValue();
762226890Sdim   return Imm > 0 && Imm <= 32;
763226890Sdim }],
764226890Sdim    imm1_32_XFORM> {
765226890Sdim  let PrintMethod = "printImmPlusOneOperand";
766226890Sdim  let ParserMatchClass = Imm1_32AsmOperand;
767218893Sdim}
768218893Sdim
769226890Sdimdef imm1_16_XFORM: SDNodeXForm<imm, [{
770226890Sdim  return CurDAG->getTargetConstant((int)N->getZExtValue() - 1, MVT::i32);
771226890Sdim}]>;
772226890Sdimdef Imm1_16AsmOperand: AsmOperandClass { let Name = "Imm1_16"; }
773226890Sdimdef imm1_16 : Operand<i32>, PatLeaf<(imm), [{ return Imm > 0 && Imm <= 16; }],
774226890Sdim    imm1_16_XFORM> {
775226890Sdim  let PrintMethod = "printImmPlusOneOperand";
776226890Sdim  let ParserMatchClass = Imm1_16AsmOperand;
777223017Sdim}
778223017Sdim
779193323Sed// Define ARM specific addressing modes.
780218893Sdim// addrmode_imm12 := reg +/- imm12
781218893Sdim//
782226890Sdimdef MemImm12OffsetAsmOperand : AsmOperandClass { let Name = "MemImm12Offset"; }
783252723Sdimclass AddrMode_Imm12 : Operand<i32>,
784218893Sdim                     ComplexPattern<i32, 2, "SelectAddrModeImm12", []> {
785218893Sdim  // 12-bit immediate operand. Note that instructions using this encode
786218893Sdim  // #0 and #-0 differently. We flag #-0 as the magic value INT32_MIN. All other
787218893Sdim  // immediate values are as normal.
788218893Sdim
789218893Sdim  let EncoderMethod = "getAddrModeImm12OpValue";
790226890Sdim  let DecoderMethod = "DecodeAddrModeImm12Operand";
791226890Sdim  let ParserMatchClass = MemImm12OffsetAsmOperand;
792218893Sdim  let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
793218893Sdim}
794252723Sdim
795252723Sdimdef addrmode_imm12 : AddrMode_Imm12 {
796252723Sdim  let PrintMethod = "printAddrModeImm12Operand<false>";
797252723Sdim}
798252723Sdim
799252723Sdimdef addrmode_imm12_pre : AddrMode_Imm12 {
800252723Sdim  let PrintMethod = "printAddrModeImm12Operand<true>";
801252723Sdim}
802252723Sdim
803218893Sdim// ldst_so_reg := reg +/- reg shop imm
804218893Sdim//
805226890Sdimdef MemRegOffsetAsmOperand : AsmOperandClass { let Name = "MemRegOffset"; }
806218893Sdimdef ldst_so_reg : Operand<i32>,
807218893Sdim                  ComplexPattern<i32, 3, "SelectLdStSOReg", []> {
808218893Sdim  let EncoderMethod = "getLdStSORegOpValue";
809218893Sdim  // FIXME: Simplify the printer
810218893Sdim  let PrintMethod = "printAddrMode2Operand";
811226890Sdim  let DecoderMethod = "DecodeSORegMemOperand";
812226890Sdim  let ParserMatchClass = MemRegOffsetAsmOperand;
813226890Sdim  let MIOperandInfo = (ops GPR:$base, GPRnopc:$offsreg, i32imm:$shift);
814218893Sdim}
815218893Sdim
816226890Sdim// postidx_imm8 := +/- [0,255]
817226890Sdim//
818226890Sdim// 9 bit value:
819226890Sdim//  {8}       1 is imm8 is non-negative. 0 otherwise.
820226890Sdim//  {7-0}     [0,255] imm8 value.
821226890Sdimdef PostIdxImm8AsmOperand : AsmOperandClass { let Name = "PostIdxImm8"; }
822226890Sdimdef postidx_imm8 : Operand<i32> {
823226890Sdim  let PrintMethod = "printPostIdxImm8Operand";
824226890Sdim  let ParserMatchClass = PostIdxImm8AsmOperand;
825226890Sdim  let MIOperandInfo = (ops i32imm);
826226890Sdim}
827226890Sdim
828226890Sdim// postidx_imm8s4 := +/- [0,1020]
829226890Sdim//
830226890Sdim// 9 bit value:
831226890Sdim//  {8}       1 is imm8 is non-negative. 0 otherwise.
832226890Sdim//  {7-0}     [0,255] imm8 value, scaled by 4.
833226890Sdimdef PostIdxImm8s4AsmOperand : AsmOperandClass { let Name = "PostIdxImm8s4"; }
834226890Sdimdef postidx_imm8s4 : Operand<i32> {
835226890Sdim  let PrintMethod = "printPostIdxImm8s4Operand";
836226890Sdim  let ParserMatchClass = PostIdxImm8s4AsmOperand;
837226890Sdim  let MIOperandInfo = (ops i32imm);
838226890Sdim}
839226890Sdim
840226890Sdim
841226890Sdim// postidx_reg := +/- reg
842226890Sdim//
843226890Sdimdef PostIdxRegAsmOperand : AsmOperandClass {
844226890Sdim  let Name = "PostIdxReg";
845226890Sdim  let ParserMethod = "parsePostIdxReg";
846226890Sdim}
847226890Sdimdef postidx_reg : Operand<i32> {
848226890Sdim  let EncoderMethod = "getPostIdxRegOpValue";
849226890Sdim  let DecoderMethod = "DecodePostIdxReg";
850226890Sdim  let PrintMethod = "printPostIdxRegOperand";
851226890Sdim  let ParserMatchClass = PostIdxRegAsmOperand;
852235633Sdim  let MIOperandInfo = (ops GPRnopc, i32imm);
853226890Sdim}
854226890Sdim
855226890Sdim
856193323Sed// addrmode2 := reg +/- imm12
857218893Sdim//           := reg +/- reg shop imm
858193323Sed//
859226890Sdim// FIXME: addrmode2 should be refactored the rest of the way to always
860226890Sdim// use explicit imm vs. reg versions above (addrmode_imm12 and ldst_so_reg).
861226890Sdimdef AddrMode2AsmOperand : AsmOperandClass { let Name = "AddrMode2"; }
862193323Seddef addrmode2 : Operand<i32>,
863193323Sed                ComplexPattern<i32, 3, "SelectAddrMode2", []> {
864218893Sdim  let EncoderMethod = "getAddrMode2OpValue";
865193323Sed  let PrintMethod = "printAddrMode2Operand";
866226890Sdim  let ParserMatchClass = AddrMode2AsmOperand;
867193323Sed  let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
868193323Sed}
869193323Sed
870226890Sdimdef PostIdxRegShiftedAsmOperand : AsmOperandClass {
871226890Sdim  let Name = "PostIdxRegShifted";
872226890Sdim  let ParserMethod = "parsePostIdxReg";
873226890Sdim}
874226890Sdimdef am2offset_reg : Operand<i32>,
875226890Sdim                ComplexPattern<i32, 2, "SelectAddrMode2OffsetReg",
876218893Sdim                [], [SDNPWantRoot]> {
877218893Sdim  let EncoderMethod = "getAddrMode2OffsetOpValue";
878193323Sed  let PrintMethod = "printAddrMode2OffsetOperand";
879226890Sdim  // When using this for assembly, it's always as a post-index offset.
880226890Sdim  let ParserMatchClass = PostIdxRegShiftedAsmOperand;
881235633Sdim  let MIOperandInfo = (ops GPRnopc, i32imm);
882193323Sed}
883193323Sed
884226890Sdim// FIXME: am2offset_imm should only need the immediate, not the GPR. Having
885226890Sdim// the GPR is purely vestigal at this point.
886226890Sdimdef AM2OffsetImmAsmOperand : AsmOperandClass { let Name = "AM2OffsetImm"; }
887226890Sdimdef am2offset_imm : Operand<i32>,
888226890Sdim                ComplexPattern<i32, 2, "SelectAddrMode2OffsetImm",
889226890Sdim                [], [SDNPWantRoot]> {
890226890Sdim  let EncoderMethod = "getAddrMode2OffsetOpValue";
891226890Sdim  let PrintMethod = "printAddrMode2OffsetOperand";
892226890Sdim  let ParserMatchClass = AM2OffsetImmAsmOperand;
893235633Sdim  let MIOperandInfo = (ops GPRnopc, i32imm);
894226890Sdim}
895226890Sdim
896226890Sdim
897193323Sed// addrmode3 := reg +/- reg
898193323Sed// addrmode3 := reg +/- imm8
899193323Sed//
900226890Sdim// FIXME: split into imm vs. reg versions.
901226890Sdimdef AddrMode3AsmOperand : AsmOperandClass { let Name = "AddrMode3"; }
902252723Sdimclass AddrMode3 : Operand<i32>,
903252723Sdim                  ComplexPattern<i32, 3, "SelectAddrMode3", []> {
904218893Sdim  let EncoderMethod = "getAddrMode3OpValue";
905226890Sdim  let ParserMatchClass = AddrMode3AsmOperand;
906193323Sed  let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
907193323Sed}
908193323Sed
909252723Sdimdef addrmode3 : AddrMode3
910252723Sdim{
911252723Sdim  let PrintMethod = "printAddrMode3Operand<false>";
912252723Sdim}
913252723Sdim
914252723Sdimdef addrmode3_pre : AddrMode3
915252723Sdim{
916252723Sdim  let PrintMethod = "printAddrMode3Operand<true>";
917252723Sdim}
918252723Sdim
919226890Sdim// FIXME: split into imm vs. reg versions.
920226890Sdim// FIXME: parser method to handle +/- register.
921226890Sdimdef AM3OffsetAsmOperand : AsmOperandClass {
922226890Sdim  let Name = "AM3Offset";
923226890Sdim  let ParserMethod = "parseAM3Offset";
924226890Sdim}
925193323Seddef am3offset : Operand<i32>,
926218893Sdim                ComplexPattern<i32, 2, "SelectAddrMode3Offset",
927218893Sdim                               [], [SDNPWantRoot]> {
928218893Sdim  let EncoderMethod = "getAddrMode3OffsetOpValue";
929193323Sed  let PrintMethod = "printAddrMode3OffsetOperand";
930226890Sdim  let ParserMatchClass = AM3OffsetAsmOperand;
931193323Sed  let MIOperandInfo = (ops GPR, i32imm);
932193323Sed}
933193323Sed
934218893Sdim// ldstm_mode := {ia, ib, da, db}
935193323Sed//
936218893Sdimdef ldstm_mode : OptionalDefOperand<OtherVT, (ops i32), (ops (i32 1))> {
937218893Sdim  let EncoderMethod = "getLdStmModeOpValue";
938218893Sdim  let PrintMethod = "printLdStmModeOperand";
939193323Sed}
940193323Sed
941193323Sed// addrmode5 := reg +/- imm8*4
942193323Sed//
943226890Sdimdef AddrMode5AsmOperand : AsmOperandClass { let Name = "AddrMode5"; }
944252723Sdimclass AddrMode5 : Operand<i32>,
945252723Sdim                  ComplexPattern<i32, 2, "SelectAddrMode5", []> {
946226890Sdim  let EncoderMethod = "getAddrMode5OpValue";
947226890Sdim  let DecoderMethod = "DecodeAddrMode5Operand";
948226890Sdim  let ParserMatchClass = AddrMode5AsmOperand;
949205218Srdivacky  let MIOperandInfo = (ops GPR:$base, i32imm);
950193323Sed}
951193323Sed
952252723Sdimdef addrmode5 : AddrMode5 {
953252723Sdim   let PrintMethod = "printAddrMode5Operand<false>";
954252723Sdim}
955252723Sdim
956252723Sdimdef addrmode5_pre : AddrMode5 {
957252723Sdim   let PrintMethod = "printAddrMode5Operand<true>";
958252723Sdim}
959252723Sdim
960218893Sdim// addrmode6 := reg with optional alignment
961195340Sed//
962226890Sdimdef AddrMode6AsmOperand : AsmOperandClass { let Name = "AlignedMemory"; }
963195340Seddef addrmode6 : Operand<i32>,
964218893Sdim                ComplexPattern<i32, 2, "SelectAddrMode6", [], [SDNPWantParent]>{
965195340Sed  let PrintMethod = "printAddrMode6Operand";
966226890Sdim  let MIOperandInfo = (ops GPR:$addr, i32imm:$align);
967218893Sdim  let EncoderMethod = "getAddrMode6AddressOpValue";
968226890Sdim  let DecoderMethod = "DecodeAddrMode6Operand";
969226890Sdim  let ParserMatchClass = AddrMode6AsmOperand;
970195340Sed}
971195340Sed
972219077Sdimdef am6offset : Operand<i32>,
973219077Sdim                ComplexPattern<i32, 1, "SelectAddrMode6Offset",
974219077Sdim                               [], [SDNPWantRoot]> {
975205407Srdivacky  let PrintMethod = "printAddrMode6OffsetOperand";
976205407Srdivacky  let MIOperandInfo = (ops GPR);
977218893Sdim  let EncoderMethod = "getAddrMode6OffsetOpValue";
978226890Sdim  let DecoderMethod = "DecodeGPRRegisterClass";
979205407Srdivacky}
980205407Srdivacky
981223017Sdim// Special version of addrmode6 to handle alignment encoding for VST1/VLD1
982223017Sdim// (single element from one lane) for size 32.
983223017Sdimdef addrmode6oneL32 : Operand<i32>,
984223017Sdim                ComplexPattern<i32, 2, "SelectAddrMode6", [], [SDNPWantParent]>{
985223017Sdim  let PrintMethod = "printAddrMode6Operand";
986223017Sdim  let MIOperandInfo = (ops GPR:$addr, i32imm);
987223017Sdim  let EncoderMethod = "getAddrMode6OneLane32AddressOpValue";
988223017Sdim}
989223017Sdim
990218893Sdim// Special version of addrmode6 to handle alignment encoding for VLD-dup
991218893Sdim// instructions, specifically VLD4-dup.
992218893Sdimdef addrmode6dup : Operand<i32>,
993218893Sdim                ComplexPattern<i32, 2, "SelectAddrMode6", [], [SDNPWantParent]>{
994218893Sdim  let PrintMethod = "printAddrMode6Operand";
995218893Sdim  let MIOperandInfo = (ops GPR:$addr, i32imm);
996218893Sdim  let EncoderMethod = "getAddrMode6DupAddressOpValue";
997235633Sdim  // FIXME: This is close, but not quite right. The alignment specifier is
998235633Sdim  // different.
999235633Sdim  let ParserMatchClass = AddrMode6AsmOperand;
1000218893Sdim}
1001218893Sdim
1002193323Sed// addrmodepc := pc + reg
1003193323Sed//
1004193323Seddef addrmodepc : Operand<i32>,
1005193323Sed                 ComplexPattern<i32, 2, "SelectAddrModePC", []> {
1006193323Sed  let PrintMethod = "printAddrModePCOperand";
1007193323Sed  let MIOperandInfo = (ops GPR, i32imm);
1008193323Sed}
1009193323Sed
1010226890Sdim// addr_offset_none := reg
1011221345Sdim//
1012226890Sdimdef MemNoOffsetAsmOperand : AsmOperandClass { let Name = "MemNoOffset"; }
1013226890Sdimdef addr_offset_none : Operand<i32>,
1014226890Sdim                       ComplexPattern<i32, 1, "SelectAddrOffsetNone", []> {
1015221345Sdim  let PrintMethod = "printAddrMode7Operand";
1016226890Sdim  let DecoderMethod = "DecodeAddrMode7Operand";
1017226890Sdim  let ParserMatchClass = MemNoOffsetAsmOperand;
1018226890Sdim  let MIOperandInfo = (ops GPR:$base);
1019221345Sdim}
1020221345Sdim
1021198090Srdivackydef nohash_imm : Operand<i32> {
1022198090Srdivacky  let PrintMethod = "printNoHashImmediate";
1023193323Sed}
1024193323Sed
1025218893Sdimdef CoprocNumAsmOperand : AsmOperandClass {
1026218893Sdim  let Name = "CoprocNum";
1027226890Sdim  let ParserMethod = "parseCoprocNumOperand";
1028218893Sdim}
1029218893Sdimdef p_imm : Operand<i32> {
1030218893Sdim  let PrintMethod = "printPImmediate";
1031218893Sdim  let ParserMatchClass = CoprocNumAsmOperand;
1032226890Sdim  let DecoderMethod = "DecodeCoprocessor";
1033218893Sdim}
1034218893Sdim
1035226890Sdimdef CoprocRegAsmOperand : AsmOperandClass {
1036226890Sdim  let Name = "CoprocReg";
1037226890Sdim  let ParserMethod = "parseCoprocRegOperand";
1038226890Sdim}
1039218893Sdimdef c_imm : Operand<i32> {
1040218893Sdim  let PrintMethod = "printCImmediate";
1041218893Sdim  let ParserMatchClass = CoprocRegAsmOperand;
1042218893Sdim}
1043226890Sdimdef CoprocOptionAsmOperand : AsmOperandClass {
1044226890Sdim  let Name = "CoprocOption";
1045226890Sdim  let ParserMethod = "parseCoprocOptionOperand";
1046226890Sdim}
1047226890Sdimdef coproc_option_imm : Operand<i32> {
1048226890Sdim  let PrintMethod = "printCoprocOptionImm";
1049226890Sdim  let ParserMatchClass = CoprocOptionAsmOperand;
1050226890Sdim}
1051218893Sdim
1052193323Sed//===----------------------------------------------------------------------===//
1053193323Sed
1054193323Sedinclude "ARMInstrFormats.td"
1055193323Sed
1056193323Sed//===----------------------------------------------------------------------===//
1057193323Sed// Multiclass helpers...
1058193323Sed//
1059193323Sed
1060193323Sed/// AsI1_bin_irs - Defines a set of (op r, {so_imm|r|so_reg}) patterns for a
1061193323Sed/// binop that produces a value.
1062245431Sdimlet TwoOperandAliasConstraint = "$Rn = $Rd" in
1063218893Sdimmulticlass AsI1_bin_irs<bits<4> opcod, string opc,
1064218893Sdim                     InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
1065245431Sdim                        PatFrag opnode, bit Commutable = 0> {
1066212904Sdim  // The register-immediate version is re-materializable. This is useful
1067212904Sdim  // in particular for taking the address of a local.
1068212904Sdim  let isReMaterializable = 1 in {
1069218893Sdim  def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm,
1070218893Sdim               iii, opc, "\t$Rd, $Rn, $imm",
1071252723Sdim               [(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]>,
1072252723Sdim           Sched<[WriteALU, ReadALU]> {
1073218893Sdim    bits<4> Rd;
1074218893Sdim    bits<4> Rn;
1075218893Sdim    bits<12> imm;
1076198090Srdivacky    let Inst{25} = 1;
1077218893Sdim    let Inst{19-16} = Rn;
1078218893Sdim    let Inst{15-12} = Rd;
1079218893Sdim    let Inst{11-0} = imm;
1080198090Srdivacky  }
1081212904Sdim  }
1082218893Sdim  def rr : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm,
1083218893Sdim               iir, opc, "\t$Rd, $Rn, $Rm",
1084252723Sdim               [(set GPR:$Rd, (opnode GPR:$Rn, GPR:$Rm))]>,
1085252723Sdim           Sched<[WriteALU, ReadALU, ReadALU]> {
1086218893Sdim    bits<4> Rd;
1087218893Sdim    bits<4> Rn;
1088218893Sdim    bits<4> Rm;
1089198090Srdivacky    let Inst{25} = 0;
1090195098Sed    let isCommutable = Commutable;
1091218893Sdim    let Inst{19-16} = Rn;
1092218893Sdim    let Inst{15-12} = Rd;
1093218893Sdim    let Inst{11-4} = 0b00000000;
1094218893Sdim    let Inst{3-0} = Rm;
1095195098Sed  }
1096226890Sdim
1097226890Sdim  def rsi : AsI1<opcod, (outs GPR:$Rd),
1098226890Sdim               (ins GPR:$Rn, so_reg_imm:$shift), DPSoRegImmFrm,
1099218893Sdim               iis, opc, "\t$Rd, $Rn, $shift",
1100252723Sdim               [(set GPR:$Rd, (opnode GPR:$Rn, so_reg_imm:$shift))]>,
1101252723Sdim            Sched<[WriteALUsi, ReadALU]> {
1102218893Sdim    bits<4> Rd;
1103218893Sdim    bits<4> Rn;
1104218893Sdim    bits<12> shift;
1105198090Srdivacky    let Inst{25} = 0;
1106218893Sdim    let Inst{19-16} = Rn;
1107218893Sdim    let Inst{15-12} = Rd;
1108226890Sdim    let Inst{11-5} = shift{11-5};
1109226890Sdim    let Inst{4} = 0;
1110226890Sdim    let Inst{3-0} = shift{3-0};
1111198090Srdivacky  }
1112224145Sdim
1113226890Sdim  def rsr : AsI1<opcod, (outs GPR:$Rd),
1114226890Sdim               (ins GPR:$Rn, so_reg_reg:$shift), DPSoRegRegFrm,
1115226890Sdim               iis, opc, "\t$Rd, $Rn, $shift",
1116252723Sdim               [(set GPR:$Rd, (opnode GPR:$Rn, so_reg_reg:$shift))]>,
1117252723Sdim            Sched<[WriteALUsr, ReadALUsr]> {
1118226890Sdim    bits<4> Rd;
1119226890Sdim    bits<4> Rn;
1120226890Sdim    bits<12> shift;
1121226890Sdim    let Inst{25} = 0;
1122226890Sdim    let Inst{19-16} = Rn;
1123226890Sdim    let Inst{15-12} = Rd;
1124226890Sdim    let Inst{11-8} = shift{11-8};
1125226890Sdim    let Inst{7} = 0;
1126226890Sdim    let Inst{6-5} = shift{6-5};
1127226890Sdim    let Inst{4} = 1;
1128226890Sdim    let Inst{3-0} = shift{3-0};
1129226890Sdim  }
1130193323Sed}
1131193323Sed
1132226890Sdim/// AsI1_rbin_irs - Same as AsI1_bin_irs except the order of operands are
1133226890Sdim/// reversed.  The 'rr' form is only defined for the disassembler; for codegen
1134226890Sdim/// it is equivalent to the AsI1_bin_irs counterpart.
1135245431Sdimlet TwoOperandAliasConstraint = "$Rn = $Rd" in
1136226890Sdimmulticlass AsI1_rbin_irs<bits<4> opcod, string opc,
1137218893Sdim                     InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
1138245431Sdim                        PatFrag opnode, bit Commutable = 0> {
1139226890Sdim  // The register-immediate version is re-materializable. This is useful
1140226890Sdim  // in particular for taking the address of a local.
1141226890Sdim  let isReMaterializable = 1 in {
1142226890Sdim  def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm,
1143218893Sdim               iii, opc, "\t$Rd, $Rn, $imm",
1144252723Sdim               [(set GPR:$Rd, (opnode so_imm:$imm, GPR:$Rn))]>,
1145252723Sdim           Sched<[WriteALU, ReadALU]> {
1146218893Sdim    bits<4> Rd;
1147218893Sdim    bits<4> Rn;
1148218893Sdim    bits<12> imm;
1149218893Sdim    let Inst{25} = 1;
1150218893Sdim    let Inst{19-16} = Rn;
1151218893Sdim    let Inst{15-12} = Rd;
1152218893Sdim    let Inst{11-0} = imm;
1153198090Srdivacky  }
1154226890Sdim  }
1155226890Sdim  def rr : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm,
1156218893Sdim               iir, opc, "\t$Rd, $Rn, $Rm",
1157252723Sdim               [/* pattern left blank */]>,
1158252723Sdim           Sched<[WriteALU, ReadALU, ReadALU]> {
1159218893Sdim    bits<4> Rd;
1160218893Sdim    bits<4> Rn;
1161218893Sdim    bits<4> Rm;
1162226890Sdim    let Inst{11-4} = 0b00000000;
1163218893Sdim    let Inst{25} = 0;
1164226890Sdim    let Inst{3-0} = Rm;
1165226890Sdim    let Inst{15-12} = Rd;
1166218893Sdim    let Inst{19-16} = Rn;
1167226890Sdim  }
1168226890Sdim
1169226890Sdim  def rsi : AsI1<opcod, (outs GPR:$Rd),
1170226890Sdim               (ins GPR:$Rn, so_reg_imm:$shift), DPSoRegImmFrm,
1171226890Sdim               iis, opc, "\t$Rd, $Rn, $shift",
1172252723Sdim               [(set GPR:$Rd, (opnode so_reg_imm:$shift, GPR:$Rn))]>,
1173252723Sdim            Sched<[WriteALUsi, ReadALU]> {
1174226890Sdim    bits<4> Rd;
1175226890Sdim    bits<4> Rn;
1176226890Sdim    bits<12> shift;
1177226890Sdim    let Inst{25} = 0;
1178226890Sdim    let Inst{19-16} = Rn;
1179218893Sdim    let Inst{15-12} = Rd;
1180226890Sdim    let Inst{11-5} = shift{11-5};
1181226890Sdim    let Inst{4} = 0;
1182226890Sdim    let Inst{3-0} = shift{3-0};
1183218893Sdim  }
1184226890Sdim
1185226890Sdim  def rsr : AsI1<opcod, (outs GPR:$Rd),
1186226890Sdim               (ins GPR:$Rn, so_reg_reg:$shift), DPSoRegRegFrm,
1187218893Sdim               iis, opc, "\t$Rd, $Rn, $shift",
1188252723Sdim               [(set GPR:$Rd, (opnode so_reg_reg:$shift, GPR:$Rn))]>,
1189252723Sdim            Sched<[WriteALUsr, ReadALUsr]> {
1190218893Sdim    bits<4> Rd;
1191218893Sdim    bits<4> Rn;
1192218893Sdim    bits<12> shift;
1193198090Srdivacky    let Inst{25} = 0;
1194218893Sdim    let Inst{19-16} = Rn;
1195218893Sdim    let Inst{15-12} = Rd;
1196226890Sdim    let Inst{11-8} = shift{11-8};
1197226890Sdim    let Inst{7} = 0;
1198226890Sdim    let Inst{6-5} = shift{6-5};
1199226890Sdim    let Inst{4} = 1;
1200226890Sdim    let Inst{3-0} = shift{3-0};
1201198090Srdivacky  }
1202193323Sed}
1203226890Sdim
1204235633Sdim/// AsI1_bin_s_irs - Same as AsI1_bin_irs except it sets the 's' bit by default.
1205226890Sdim///
1206226890Sdim/// These opcodes will be converted to the real non-S opcodes by
1207235633Sdim/// AdjustInstrPostInstrSelection after giving them an optional CPSR operand.
1208235633Sdimlet hasPostISelHook = 1, Defs = [CPSR] in {
1209235633Sdimmulticlass AsI1_bin_s_irs<InstrItinClass iii, InstrItinClass iir,
1210235633Sdim                          InstrItinClass iis, PatFrag opnode,
1211235633Sdim                          bit Commutable = 0> {
1212235633Sdim  def ri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm, pred:$p),
1213235633Sdim                         4, iii,
1214252723Sdim                         [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, so_imm:$imm))]>,
1215252723Sdim                         Sched<[WriteALU, ReadALU]>;
1216226890Sdim
1217235633Sdim  def rr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, pred:$p),
1218235633Sdim                         4, iir,
1219252723Sdim                         [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, GPR:$Rm))]>,
1220252723Sdim                         Sched<[WriteALU, ReadALU, ReadALU]> {
1221235633Sdim    let isCommutable = Commutable;
1222235633Sdim  }
1223235633Sdim  def rsi : ARMPseudoInst<(outs GPR:$Rd),
1224235633Sdim                          (ins GPR:$Rn, so_reg_imm:$shift, pred:$p),
1225235633Sdim                          4, iis,
1226235633Sdim                          [(set GPR:$Rd, CPSR, (opnode GPR:$Rn,
1227252723Sdim                                                so_reg_imm:$shift))]>,
1228252723Sdim                          Sched<[WriteALUsi, ReadALU]>;
1229226890Sdim
1230235633Sdim  def rsr : ARMPseudoInst<(outs GPR:$Rd),
1231235633Sdim                          (ins GPR:$Rn, so_reg_reg:$shift, pred:$p),
1232235633Sdim                          4, iis,
1233235633Sdim                          [(set GPR:$Rd, CPSR, (opnode GPR:$Rn,
1234252723Sdim                                                so_reg_reg:$shift))]>,
1235252723Sdim                          Sched<[WriteALUSsr, ReadALUsr]>;
1236193323Sed}
1237226890Sdim}
1238193323Sed
1239235633Sdim/// AsI1_rbin_s_is - Same as AsI1_bin_s_irs, except selection DAG
1240235633Sdim/// operands are reversed.
1241235633Sdimlet hasPostISelHook = 1, Defs = [CPSR] in {
1242235633Sdimmulticlass AsI1_rbin_s_is<InstrItinClass iii, InstrItinClass iir,
1243235633Sdim                          InstrItinClass iis, PatFrag opnode,
1244235633Sdim                          bit Commutable = 0> {
1245235633Sdim  def ri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm, pred:$p),
1246235633Sdim                         4, iii,
1247252723Sdim                         [(set GPR:$Rd, CPSR, (opnode so_imm:$imm, GPR:$Rn))]>,
1248252723Sdim           Sched<[WriteALU, ReadALU]>;
1249226890Sdim
1250235633Sdim  def rsi : ARMPseudoInst<(outs GPR:$Rd),
1251235633Sdim                          (ins GPR:$Rn, so_reg_imm:$shift, pred:$p),
1252235633Sdim                          4, iis,
1253235633Sdim                          [(set GPR:$Rd, CPSR, (opnode so_reg_imm:$shift,
1254252723Sdim                                             GPR:$Rn))]>,
1255252723Sdim            Sched<[WriteALUsi, ReadALU]>;
1256235633Sdim
1257235633Sdim  def rsr : ARMPseudoInst<(outs GPR:$Rd),
1258235633Sdim                          (ins GPR:$Rn, so_reg_reg:$shift, pred:$p),
1259235633Sdim                          4, iis,
1260235633Sdim                          [(set GPR:$Rd, CPSR, (opnode so_reg_reg:$shift,
1261252723Sdim                                             GPR:$Rn))]>,
1262252723Sdim            Sched<[WriteALUSsr, ReadALUsr]>;
1263226890Sdim}
1264226890Sdim}
1265226890Sdim
1266193323Sed/// AI1_cmp_irs - Defines a set of (op r, {so_imm|r|so_reg}) cmp / test
1267193323Sed/// patterns. Similar to AsI1_bin_irs except the instruction does not produce
1268193323Sed/// a explicit result, only implicitly set CPSR.
1269212904Sdimlet isCompare = 1, Defs = [CPSR] in {
1270218893Sdimmulticlass AI1_cmp_irs<bits<4> opcod, string opc,
1271218893Sdim                     InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
1272218893Sdim                       PatFrag opnode, bit Commutable = 0> {
1273218893Sdim  def ri : AI1<opcod, (outs), (ins GPR:$Rn, so_imm:$imm), DPFrm, iii,
1274218893Sdim               opc, "\t$Rn, $imm",
1275252723Sdim               [(opnode GPR:$Rn, so_imm:$imm)]>,
1276252723Sdim           Sched<[WriteCMP, ReadALU]> {
1277218893Sdim    bits<4> Rn;
1278218893Sdim    bits<12> imm;
1279218893Sdim    let Inst{25} = 1;
1280198090Srdivacky    let Inst{20} = 1;
1281218893Sdim    let Inst{19-16} = Rn;
1282218893Sdim    let Inst{15-12} = 0b0000;
1283218893Sdim    let Inst{11-0} = imm;
1284235633Sdim
1285235633Sdim    let Unpredictable{15-12} = 0b1111;
1286198090Srdivacky  }
1287218893Sdim  def rr : AI1<opcod, (outs), (ins GPR:$Rn, GPR:$Rm), DPFrm, iir,
1288218893Sdim               opc, "\t$Rn, $Rm",
1289252723Sdim               [(opnode GPR:$Rn, GPR:$Rm)]>,
1290252723Sdim           Sched<[WriteCMP, ReadALU, ReadALU]> {
1291218893Sdim    bits<4> Rn;
1292218893Sdim    bits<4> Rm;
1293218893Sdim    let isCommutable = Commutable;
1294218893Sdim    let Inst{25} = 0;
1295218893Sdim    let Inst{20} = 1;
1296218893Sdim    let Inst{19-16} = Rn;
1297218893Sdim    let Inst{15-12} = 0b0000;
1298199481Srdivacky    let Inst{11-4} = 0b00000000;
1299218893Sdim    let Inst{3-0} = Rm;
1300235633Sdim
1301235633Sdim    let Unpredictable{15-12} = 0b1111;
1302218893Sdim  }
1303226890Sdim  def rsi : AI1<opcod, (outs),
1304226890Sdim               (ins GPR:$Rn, so_reg_imm:$shift), DPSoRegImmFrm, iis,
1305218893Sdim               opc, "\t$Rn, $shift",
1306252723Sdim               [(opnode GPR:$Rn, so_reg_imm:$shift)]>,
1307252723Sdim            Sched<[WriteCMPsi, ReadALU]> {
1308218893Sdim    bits<4> Rn;
1309218893Sdim    bits<12> shift;
1310198090Srdivacky    let Inst{25} = 0;
1311198090Srdivacky    let Inst{20} = 1;
1312218893Sdim    let Inst{19-16} = Rn;
1313218893Sdim    let Inst{15-12} = 0b0000;
1314226890Sdim    let Inst{11-5} = shift{11-5};
1315226890Sdim    let Inst{4} = 0;
1316226890Sdim    let Inst{3-0} = shift{3-0};
1317235633Sdim
1318235633Sdim    let Unpredictable{15-12} = 0b1111;
1319198090Srdivacky  }
1320226890Sdim  def rsr : AI1<opcod, (outs),
1321235633Sdim               (ins GPRnopc:$Rn, so_reg_reg:$shift), DPSoRegRegFrm, iis,
1322226890Sdim               opc, "\t$Rn, $shift",
1323252723Sdim               [(opnode GPRnopc:$Rn, so_reg_reg:$shift)]>,
1324252723Sdim            Sched<[WriteCMPsr, ReadALU]> {
1325226890Sdim    bits<4> Rn;
1326226890Sdim    bits<12> shift;
1327226890Sdim    let Inst{25} = 0;
1328226890Sdim    let Inst{20} = 1;
1329226890Sdim    let Inst{19-16} = Rn;
1330226890Sdim    let Inst{15-12} = 0b0000;
1331226890Sdim    let Inst{11-8} = shift{11-8};
1332226890Sdim    let Inst{7} = 0;
1333226890Sdim    let Inst{6-5} = shift{6-5};
1334226890Sdim    let Inst{4} = 1;
1335226890Sdim    let Inst{3-0} = shift{3-0};
1336235633Sdim
1337235633Sdim    let Unpredictable{15-12} = 0b1111;
1338226890Sdim  }
1339226890Sdim
1340193323Sed}
1341193323Sed}
1342193323Sed
1343218893Sdim/// AI_ext_rrot - A unary operation with two forms: one whose operand is a
1344193323Sed/// register and one whose operand is a register rotated by 8/16/24.
1345193323Sed/// FIXME: Remove the 'r' variant. Its rot_imm is zero.
1346226890Sdimclass AI_ext_rrot<bits<8> opcod, string opc, PatFrag opnode>
1347226890Sdim  : AExtI<opcod, (outs GPRnopc:$Rd), (ins GPRnopc:$Rm, rot_imm:$rot),
1348226890Sdim          IIC_iEXTr, opc, "\t$Rd, $Rm$rot",
1349226890Sdim          [(set GPRnopc:$Rd, (opnode (rotr GPRnopc:$Rm, rot_imm:$rot)))]>,
1350263509Sdim       Requires<[IsARM, HasV6]>, Sched<[WriteALUsi]> {
1351226890Sdim  bits<4> Rd;
1352226890Sdim  bits<4> Rm;
1353226890Sdim  bits<2> rot;
1354226890Sdim  let Inst{19-16} = 0b1111;
1355226890Sdim  let Inst{15-12} = Rd;
1356226890Sdim  let Inst{11-10} = rot;
1357226890Sdim  let Inst{3-0}   = Rm;
1358193323Sed}
1359193323Sed
1360226890Sdimclass AI_ext_rrot_np<bits<8> opcod, string opc>
1361226890Sdim  : AExtI<opcod, (outs GPRnopc:$Rd), (ins GPRnopc:$Rm, rot_imm:$rot),
1362226890Sdim          IIC_iEXTr, opc, "\t$Rd, $Rm$rot", []>,
1363263509Sdim       Requires<[IsARM, HasV6]>, Sched<[WriteALUsi]> {
1364226890Sdim  bits<2> rot;
1365226890Sdim  let Inst{19-16} = 0b1111;
1366226890Sdim  let Inst{11-10} = rot;
1367263509Sdim }
1368204642Srdivacky
1369218893Sdim/// AI_exta_rrot - A binary operation with two forms: one whose operand is a
1370193323Sed/// register and one whose operand is a register rotated by 8/16/24.
1371226890Sdimclass AI_exta_rrot<bits<8> opcod, string opc, PatFrag opnode>
1372226890Sdim  : AExtI<opcod, (outs GPRnopc:$Rd), (ins GPR:$Rn, GPRnopc:$Rm, rot_imm:$rot),
1373226890Sdim          IIC_iEXTAr, opc, "\t$Rd, $Rn, $Rm$rot",
1374226890Sdim          [(set GPRnopc:$Rd, (opnode GPR:$Rn,
1375226890Sdim                                     (rotr GPRnopc:$Rm, rot_imm:$rot)))]>,
1376263509Sdim        Requires<[IsARM, HasV6]>, Sched<[WriteALUsr]> {
1377226890Sdim  bits<4> Rd;
1378226890Sdim  bits<4> Rm;
1379226890Sdim  bits<4> Rn;
1380226890Sdim  bits<2> rot;
1381226890Sdim  let Inst{19-16} = Rn;
1382226890Sdim  let Inst{15-12} = Rd;
1383226890Sdim  let Inst{11-10} = rot;
1384226890Sdim  let Inst{9-4}   = 0b000111;
1385226890Sdim  let Inst{3-0}   = Rm;
1386226890Sdim}
1387226890Sdim
1388226890Sdimclass AI_exta_rrot_np<bits<8> opcod, string opc>
1389226890Sdim  : AExtI<opcod, (outs GPRnopc:$Rd), (ins GPR:$Rn, GPRnopc:$Rm, rot_imm:$rot),
1390226890Sdim          IIC_iEXTAr, opc, "\t$Rd, $Rn, $Rm$rot", []>,
1391263509Sdim       Requires<[IsARM, HasV6]>, Sched<[WriteALUsr]> {
1392226890Sdim  bits<4> Rn;
1393226890Sdim  bits<2> rot;
1394226890Sdim  let Inst{19-16} = Rn;
1395226890Sdim  let Inst{11-10} = rot;
1396226890Sdim}
1397226890Sdim
1398226890Sdim/// AI1_adde_sube_irs - Define instructions and patterns for adde and sube.
1399245431Sdimlet TwoOperandAliasConstraint = "$Rn = $Rd" in
1400226890Sdimmulticlass AI1_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
1401245431Sdim                             bit Commutable = 0> {
1402226890Sdim  let hasPostISelHook = 1, Defs = [CPSR], Uses = [CPSR] in {
1403226890Sdim  def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
1404226890Sdim                DPFrm, IIC_iALUi, opc, "\t$Rd, $Rn, $imm",
1405226890Sdim               [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, so_imm:$imm, CPSR))]>,
1406252723Sdim               Requires<[IsARM]>,
1407252723Sdim           Sched<[WriteALU, ReadALU]> {
1408218893Sdim    bits<4> Rd;
1409218893Sdim    bits<4> Rn;
1410226890Sdim    bits<12> imm;
1411226890Sdim    let Inst{25} = 1;
1412226890Sdim    let Inst{15-12} = Rd;
1413218893Sdim    let Inst{19-16} = Rn;
1414226890Sdim    let Inst{11-0} = imm;
1415226890Sdim  }
1416226890Sdim  def rr : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
1417226890Sdim                DPFrm, IIC_iALUr, opc, "\t$Rd, $Rn, $Rm",
1418226890Sdim               [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, GPR:$Rm, CPSR))]>,
1419252723Sdim               Requires<[IsARM]>,
1420252723Sdim           Sched<[WriteALU, ReadALU, ReadALU]> {
1421226890Sdim    bits<4> Rd;
1422226890Sdim    bits<4> Rn;
1423226890Sdim    bits<4> Rm;
1424226890Sdim    let Inst{11-4} = 0b00000000;
1425226890Sdim    let Inst{25} = 0;
1426226890Sdim    let isCommutable = Commutable;
1427226890Sdim    let Inst{3-0} = Rm;
1428218893Sdim    let Inst{15-12} = Rd;
1429226890Sdim    let Inst{19-16} = Rn;
1430198892Srdivacky  }
1431226890Sdim  def rsi : AsI1<opcod, (outs GPR:$Rd),
1432226890Sdim                (ins GPR:$Rn, so_reg_imm:$shift),
1433226890Sdim                DPSoRegImmFrm, IIC_iALUsr, opc, "\t$Rd, $Rn, $shift",
1434226890Sdim              [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, so_reg_imm:$shift, CPSR))]>,
1435252723Sdim               Requires<[IsARM]>,
1436252723Sdim            Sched<[WriteALUsi, ReadALU]> {
1437218893Sdim    bits<4> Rd;
1438218893Sdim    bits<4> Rn;
1439226890Sdim    bits<12> shift;
1440226890Sdim    let Inst{25} = 0;
1441218893Sdim    let Inst{19-16} = Rn;
1442218893Sdim    let Inst{15-12} = Rd;
1443226890Sdim    let Inst{11-5} = shift{11-5};
1444226890Sdim    let Inst{4} = 0;
1445226890Sdim    let Inst{3-0} = shift{3-0};
1446218893Sdim  }
1447235633Sdim  def rsr : AsI1<opcod, (outs GPRnopc:$Rd),
1448235633Sdim                (ins GPRnopc:$Rn, so_reg_reg:$shift),
1449226890Sdim                DPSoRegRegFrm, IIC_iALUsr, opc, "\t$Rd, $Rn, $shift",
1450245431Sdim              [(set GPRnopc:$Rd, CPSR,
1451245431Sdim                    (opnode GPRnopc:$Rn, so_reg_reg:$shift, CPSR))]>,
1452252723Sdim               Requires<[IsARM]>,
1453252723Sdim            Sched<[WriteALUsr, ReadALUsr]> {
1454226890Sdim    bits<4> Rd;
1455218893Sdim    bits<4> Rn;
1456226890Sdim    bits<12> shift;
1457226890Sdim    let Inst{25} = 0;
1458218893Sdim    let Inst{19-16} = Rn;
1459226890Sdim    let Inst{15-12} = Rd;
1460226890Sdim    let Inst{11-8} = shift{11-8};
1461226890Sdim    let Inst{7} = 0;
1462226890Sdim    let Inst{6-5} = shift{6-5};
1463226890Sdim    let Inst{4} = 1;
1464226890Sdim    let Inst{3-0} = shift{3-0};
1465218893Sdim  }
1466226890Sdim  }
1467204642Srdivacky}
1468204642Srdivacky
1469226890Sdim/// AI1_rsc_irs - Define instructions and patterns for rsc
1470245431Sdimlet TwoOperandAliasConstraint = "$Rn = $Rd" in
1471245431Sdimmulticlass AI1_rsc_irs<bits<4> opcod, string opc, PatFrag opnode> {
1472226890Sdim  let hasPostISelHook = 1, Defs = [CPSR], Uses = [CPSR] in {
1473218893Sdim  def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
1474218893Sdim                DPFrm, IIC_iALUi, opc, "\t$Rd, $Rn, $imm",
1475226890Sdim               [(set GPR:$Rd, CPSR, (opnode so_imm:$imm, GPR:$Rn, CPSR))]>,
1476252723Sdim               Requires<[IsARM]>,
1477252723Sdim           Sched<[WriteALU, ReadALU]> {
1478218893Sdim    bits<4> Rd;
1479218893Sdim    bits<4> Rn;
1480218893Sdim    bits<12> imm;
1481198090Srdivacky    let Inst{25} = 1;
1482218893Sdim    let Inst{15-12} = Rd;
1483218893Sdim    let Inst{19-16} = Rn;
1484218893Sdim    let Inst{11-0} = imm;
1485198090Srdivacky  }
1486218893Sdim  def rr : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
1487218893Sdim                DPFrm, IIC_iALUr, opc, "\t$Rd, $Rn, $Rm",
1488252723Sdim               [/* pattern left blank */]>,
1489252723Sdim           Sched<[WriteALU, ReadALU, ReadALU]> {
1490218893Sdim    bits<4> Rd;
1491218893Sdim    bits<4> Rn;
1492218893Sdim    bits<4> Rm;
1493199481Srdivacky    let Inst{11-4} = 0b00000000;
1494198090Srdivacky    let Inst{25} = 0;
1495218893Sdim    let Inst{3-0} = Rm;
1496218893Sdim    let Inst{15-12} = Rd;
1497218893Sdim    let Inst{19-16} = Rn;
1498195098Sed  }
1499226890Sdim  def rsi : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_reg_imm:$shift),
1500226890Sdim                DPSoRegImmFrm, IIC_iALUsr, opc, "\t$Rd, $Rn, $shift",
1501226890Sdim              [(set GPR:$Rd, CPSR, (opnode so_reg_imm:$shift, GPR:$Rn, CPSR))]>,
1502252723Sdim               Requires<[IsARM]>,
1503252723Sdim            Sched<[WriteALUsi, ReadALU]> {
1504218893Sdim    bits<4> Rd;
1505218893Sdim    bits<4> Rn;
1506218893Sdim    bits<12> shift;
1507198090Srdivacky    let Inst{25} = 0;
1508226890Sdim    let Inst{19-16} = Rn;
1509218893Sdim    let Inst{15-12} = Rd;
1510226890Sdim    let Inst{11-5} = shift{11-5};
1511226890Sdim    let Inst{4} = 0;
1512226890Sdim    let Inst{3-0} = shift{3-0};
1513226890Sdim  }
1514226890Sdim  def rsr : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_reg_reg:$shift),
1515226890Sdim                DPSoRegRegFrm, IIC_iALUsr, opc, "\t$Rd, $Rn, $shift",
1516226890Sdim              [(set GPR:$Rd, CPSR, (opnode so_reg_reg:$shift, GPR:$Rn, CPSR))]>,
1517252723Sdim               Requires<[IsARM]>,
1518252723Sdim            Sched<[WriteALUsr, ReadALUsr]> {
1519226890Sdim    bits<4> Rd;
1520226890Sdim    bits<4> Rn;
1521226890Sdim    bits<12> shift;
1522226890Sdim    let Inst{25} = 0;
1523218893Sdim    let Inst{19-16} = Rn;
1524226890Sdim    let Inst{15-12} = Rd;
1525226890Sdim    let Inst{11-8} = shift{11-8};
1526226890Sdim    let Inst{7} = 0;
1527226890Sdim    let Inst{6-5} = shift{6-5};
1528226890Sdim    let Inst{4} = 1;
1529226890Sdim    let Inst{3-0} = shift{3-0};
1530198090Srdivacky  }
1531224145Sdim  }
1532199481Srdivacky}
1533221345Sdim
1534218893Sdimlet canFoldAsLoad = 1, isReMaterializable = 1 in {
1535218893Sdimmulticlass AI_ldr1<bit isByte, string opc, InstrItinClass iii,
1536218893Sdim           InstrItinClass iir, PatFrag opnode> {
1537218893Sdim  // Note: We use the complex addrmode_imm12 rather than just an input
1538218893Sdim  // GPR and a constrained immediate so that we can use this to match
1539218893Sdim  // frame index references and avoid matching constant pool references.
1540218893Sdim  def i12: AI2ldst<0b010, 1, isByte, (outs GPR:$Rt), (ins addrmode_imm12:$addr),
1541218893Sdim                   AddrMode_i12, LdFrm, iii, opc, "\t$Rt, $addr",
1542218893Sdim                  [(set GPR:$Rt, (opnode addrmode_imm12:$addr))]> {
1543218893Sdim    bits<4>  Rt;
1544218893Sdim    bits<17> addr;
1545218893Sdim    let Inst{23}    = addr{12};     // U (add = ('U' == 1))
1546218893Sdim    let Inst{19-16} = addr{16-13};  // Rn
1547218893Sdim    let Inst{15-12} = Rt;
1548218893Sdim    let Inst{11-0}  = addr{11-0};   // imm12
1549218893Sdim  }
1550218893Sdim  def rs : AI2ldst<0b011, 1, isByte, (outs GPR:$Rt), (ins ldst_so_reg:$shift),
1551218893Sdim                  AddrModeNone, LdFrm, iir, opc, "\t$Rt, $shift",
1552218893Sdim                 [(set GPR:$Rt, (opnode ldst_so_reg:$shift))]> {
1553218893Sdim    bits<4>  Rt;
1554218893Sdim    bits<17> shift;
1555221345Sdim    let shift{4}    = 0;            // Inst{4} = 0
1556218893Sdim    let Inst{23}    = shift{12};    // U (add = ('U' == 1))
1557218893Sdim    let Inst{19-16} = shift{16-13}; // Rn
1558218893Sdim    let Inst{15-12} = Rt;
1559218893Sdim    let Inst{11-0}  = shift{11-0};
1560218893Sdim  }
1561218893Sdim}
1562218893Sdim}
1563218893Sdim
1564226890Sdimlet canFoldAsLoad = 1, isReMaterializable = 1 in {
1565226890Sdimmulticlass AI_ldr1nopc<bit isByte, string opc, InstrItinClass iii,
1566226890Sdim           InstrItinClass iir, PatFrag opnode> {
1567226890Sdim  // Note: We use the complex addrmode_imm12 rather than just an input
1568226890Sdim  // GPR and a constrained immediate so that we can use this to match
1569226890Sdim  // frame index references and avoid matching constant pool references.
1570245431Sdim  def i12: AI2ldst<0b010, 1, isByte, (outs GPRnopc:$Rt),
1571245431Sdim                   (ins addrmode_imm12:$addr),
1572226890Sdim                   AddrMode_i12, LdFrm, iii, opc, "\t$Rt, $addr",
1573245431Sdim                   [(set GPRnopc:$Rt, (opnode addrmode_imm12:$addr))]> {
1574226890Sdim    bits<4>  Rt;
1575226890Sdim    bits<17> addr;
1576226890Sdim    let Inst{23}    = addr{12};     // U (add = ('U' == 1))
1577226890Sdim    let Inst{19-16} = addr{16-13};  // Rn
1578226890Sdim    let Inst{15-12} = Rt;
1579226890Sdim    let Inst{11-0}  = addr{11-0};   // imm12
1580226890Sdim  }
1581245431Sdim  def rs : AI2ldst<0b011, 1, isByte, (outs GPRnopc:$Rt),
1582245431Sdim                   (ins ldst_so_reg:$shift),
1583245431Sdim                   AddrModeNone, LdFrm, iir, opc, "\t$Rt, $shift",
1584245431Sdim                   [(set GPRnopc:$Rt, (opnode ldst_so_reg:$shift))]> {
1585226890Sdim    bits<4>  Rt;
1586226890Sdim    bits<17> shift;
1587226890Sdim    let shift{4}    = 0;            // Inst{4} = 0
1588226890Sdim    let Inst{23}    = shift{12};    // U (add = ('U' == 1))
1589226890Sdim    let Inst{19-16} = shift{16-13}; // Rn
1590226890Sdim    let Inst{15-12} = Rt;
1591226890Sdim    let Inst{11-0}  = shift{11-0};
1592226890Sdim  }
1593226890Sdim}
1594226890Sdim}
1595226890Sdim
1596226890Sdim
1597218893Sdimmulticlass AI_str1<bit isByte, string opc, InstrItinClass iii,
1598218893Sdim           InstrItinClass iir, PatFrag opnode> {
1599218893Sdim  // Note: We use the complex addrmode_imm12 rather than just an input
1600218893Sdim  // GPR and a constrained immediate so that we can use this to match
1601218893Sdim  // frame index references and avoid matching constant pool references.
1602218893Sdim  def i12 : AI2ldst<0b010, 0, isByte, (outs),
1603218893Sdim                   (ins GPR:$Rt, addrmode_imm12:$addr),
1604218893Sdim                   AddrMode_i12, StFrm, iii, opc, "\t$Rt, $addr",
1605218893Sdim                  [(opnode GPR:$Rt, addrmode_imm12:$addr)]> {
1606218893Sdim    bits<4> Rt;
1607218893Sdim    bits<17> addr;
1608218893Sdim    let Inst{23}    = addr{12};     // U (add = ('U' == 1))
1609218893Sdim    let Inst{19-16} = addr{16-13};  // Rn
1610218893Sdim    let Inst{15-12} = Rt;
1611218893Sdim    let Inst{11-0}  = addr{11-0};   // imm12
1612218893Sdim  }
1613218893Sdim  def rs : AI2ldst<0b011, 0, isByte, (outs), (ins GPR:$Rt, ldst_so_reg:$shift),
1614218893Sdim                  AddrModeNone, StFrm, iir, opc, "\t$Rt, $shift",
1615218893Sdim                 [(opnode GPR:$Rt, ldst_so_reg:$shift)]> {
1616218893Sdim    bits<4> Rt;
1617218893Sdim    bits<17> shift;
1618221345Sdim    let shift{4}    = 0;            // Inst{4} = 0
1619218893Sdim    let Inst{23}    = shift{12};    // U (add = ('U' == 1))
1620218893Sdim    let Inst{19-16} = shift{16-13}; // Rn
1621218893Sdim    let Inst{15-12} = Rt;
1622218893Sdim    let Inst{11-0}  = shift{11-0};
1623218893Sdim  }
1624218893Sdim}
1625226890Sdim
1626226890Sdimmulticlass AI_str1nopc<bit isByte, string opc, InstrItinClass iii,
1627226890Sdim           InstrItinClass iir, PatFrag opnode> {
1628226890Sdim  // Note: We use the complex addrmode_imm12 rather than just an input
1629226890Sdim  // GPR and a constrained immediate so that we can use this to match
1630226890Sdim  // frame index references and avoid matching constant pool references.
1631226890Sdim  def i12 : AI2ldst<0b010, 0, isByte, (outs),
1632226890Sdim                   (ins GPRnopc:$Rt, addrmode_imm12:$addr),
1633226890Sdim                   AddrMode_i12, StFrm, iii, opc, "\t$Rt, $addr",
1634226890Sdim                  [(opnode GPRnopc:$Rt, addrmode_imm12:$addr)]> {
1635226890Sdim    bits<4> Rt;
1636226890Sdim    bits<17> addr;
1637226890Sdim    let Inst{23}    = addr{12};     // U (add = ('U' == 1))
1638226890Sdim    let Inst{19-16} = addr{16-13};  // Rn
1639226890Sdim    let Inst{15-12} = Rt;
1640226890Sdim    let Inst{11-0}  = addr{11-0};   // imm12
1641226890Sdim  }
1642245431Sdim  def rs : AI2ldst<0b011, 0, isByte, (outs),
1643245431Sdim                   (ins GPRnopc:$Rt, ldst_so_reg:$shift),
1644245431Sdim                   AddrModeNone, StFrm, iir, opc, "\t$Rt, $shift",
1645245431Sdim                   [(opnode GPRnopc:$Rt, ldst_so_reg:$shift)]> {
1646226890Sdim    bits<4> Rt;
1647226890Sdim    bits<17> shift;
1648226890Sdim    let shift{4}    = 0;            // Inst{4} = 0
1649226890Sdim    let Inst{23}    = shift{12};    // U (add = ('U' == 1))
1650226890Sdim    let Inst{19-16} = shift{16-13}; // Rn
1651226890Sdim    let Inst{15-12} = Rt;
1652226890Sdim    let Inst{11-0}  = shift{11-0};
1653226890Sdim  }
1654226890Sdim}
1655226890Sdim
1656226890Sdim
1657193323Sed//===----------------------------------------------------------------------===//
1658193323Sed// Instructions
1659193323Sed//===----------------------------------------------------------------------===//
1660193323Sed
1661193323Sed//===----------------------------------------------------------------------===//
1662193323Sed//  Miscellaneous Instructions.
1663193323Sed//
1664193323Sed
1665193323Sed/// CONSTPOOL_ENTRY - This instruction represents a floating constant pool in
1666193323Sed/// the function.  The first operand is the ID# for this instruction, the second
1667193323Sed/// is the index into the MachineConstantPool that this is, the third is the
1668193323Sed/// size in bytes of this constant pool entry.
1669194178Sedlet neverHasSideEffects = 1, isNotDuplicable = 1 in
1670193323Seddef CONSTPOOL_ENTRY :
1671193323SedPseudoInst<(outs), (ins cpinst_operand:$instid, cpinst_operand:$cpidx,
1672218893Sdim                    i32imm:$size), NoItinerary, []>;
1673193323Sed
1674204642Srdivacky// FIXME: Marking these as hasSideEffects is necessary to prevent machine DCE
1675204642Srdivacky// from removing one half of the matched pairs. That breaks PEI, which assumes
1676204642Srdivacky// these will always be in pairs, and asserts if it finds otherwise. Better way?
1677204642Srdivackylet Defs = [SP], Uses = [SP], hasSideEffects = 1 in {
1678193323Seddef ADJCALLSTACKUP :
1679198090SrdivackyPseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2, pred:$p), NoItinerary,
1680193323Sed           [(ARMcallseq_end timm:$amt1, timm:$amt2)]>;
1681193323Sed
1682204642Srdivackydef ADJCALLSTACKDOWN :
1683198090SrdivackyPseudoInst<(outs), (ins i32imm:$amt, pred:$p), NoItinerary,
1684193323Sed           [(ARMcallseq_start timm:$amt)]>;
1685193323Sed}
1686193323Sed
1687263509Sdimdef HINT : AI<(outs), (ins imm0_239:$imm), MiscFrm, NoItinerary,
1688245431Sdim              "hint", "\t$imm", []>, Requires<[IsARM, HasV6]> {
1689263509Sdim  bits<8> imm;
1690263509Sdim  let Inst{27-8} = 0b00110010000011110000;
1691263509Sdim  let Inst{7-0} = imm;
1692203954Srdivacky}
1693203954Srdivacky
1694245431Sdimdef : InstAlias<"nop$p", (HINT 0, pred:$p)>, Requires<[IsARM, HasV6T2]>;
1695245431Sdimdef : InstAlias<"yield$p", (HINT 1, pred:$p)>, Requires<[IsARM, HasV6T2]>;
1696245431Sdimdef : InstAlias<"wfe$p", (HINT 2, pred:$p)>, Requires<[IsARM, HasV6T2]>;
1697245431Sdimdef : InstAlias<"wfi$p", (HINT 3, pred:$p)>, Requires<[IsARM, HasV6T2]>;
1698245431Sdimdef : InstAlias<"sev$p", (HINT 4, pred:$p)>, Requires<[IsARM, HasV6T2]>;
1699263509Sdimdef : InstAlias<"sevl$p", (HINT 5, pred:$p)>, Requires<[IsARM, HasV8]>;
1700203954Srdivacky
1701263509Sdimdef : Pat<(int_arm_sevl), (HINT 5)>;
1702263509Sdim
1703226890Sdimdef SEL : AI<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm, NoItinerary, "sel",
1704226890Sdim             "\t$Rd, $Rn, $Rm", []>, Requires<[IsARM, HasV6]> {
1705218893Sdim  bits<4> Rd;
1706218893Sdim  bits<4> Rn;
1707218893Sdim  bits<4> Rm;
1708218893Sdim  let Inst{3-0} = Rm;
1709218893Sdim  let Inst{15-12} = Rd;
1710218893Sdim  let Inst{19-16} = Rn;
1711204642Srdivacky  let Inst{27-20} = 0b01101000;
1712204642Srdivacky  let Inst{7-4} = 0b1011;
1713218893Sdim  let Inst{11-8} = 0b1111;
1714245431Sdim  let Unpredictable{11-8} = 0b1111;
1715204642Srdivacky}
1716204642Srdivacky
1717245431Sdim// The 16-bit operand $val can be used by a debugger to store more information
1718203954Srdivacky// about the breakpoint.
1719263509Sdimdef BKPT : AInoP<(outs), (ins imm0_65535:$val), MiscFrm, NoItinerary,
1720263509Sdim                 "bkpt", "\t$val", []>, Requires<[IsARM]> {
1721218893Sdim  bits<16> val;
1722218893Sdim  let Inst{3-0} = val{3-0};
1723218893Sdim  let Inst{19-8} = val{15-4};
1724203954Srdivacky  let Inst{27-20} = 0b00010010;
1725263509Sdim  let Inst{31-28} = 0xe; // AL
1726203954Srdivacky  let Inst{7-4} = 0b0111;
1727203954Srdivacky}
1728203954Srdivacky
1729263509Sdimdef HLT : AInoP<(outs), (ins imm0_65535:$val), MiscFrm, NoItinerary,
1730263509Sdim                 "hlt", "\t$val", []>, Requires<[IsARM, HasV8]> {
1731263509Sdim  bits<16> val;
1732263509Sdim  let Inst{3-0} = val{3-0};
1733263509Sdim  let Inst{19-8} = val{15-4};
1734263509Sdim  let Inst{27-20} = 0b00010000;
1735263509Sdim  let Inst{31-28} = 0xe; // AL
1736263509Sdim  let Inst{7-4} = 0b0111;
1737263509Sdim}
1738263509Sdim
1739226890Sdim// Change Processor State
1740226890Sdim// FIXME: We should use InstAlias to handle the optional operands.
1741218893Sdimclass CPS<dag iops, string asm_ops>
1742218893Sdim  : AXI<(outs), iops, MiscFrm, NoItinerary, !strconcat("cps", asm_ops),
1743226890Sdim        []>, Requires<[IsARM]> {
1744218893Sdim  bits<2> imod;
1745218893Sdim  bits<3> iflags;
1746218893Sdim  bits<5> mode;
1747218893Sdim  bit M;
1748218893Sdim
1749203954Srdivacky  let Inst{31-28} = 0b1111;
1750203954Srdivacky  let Inst{27-20} = 0b00010000;
1751218893Sdim  let Inst{19-18} = imod;
1752218893Sdim  let Inst{17}    = M; // Enabled if mode is set;
1753235633Sdim  let Inst{16-9}  = 0b00000000;
1754218893Sdim  let Inst{8-6}   = iflags;
1755218893Sdim  let Inst{5}     = 0;
1756218893Sdim  let Inst{4-0}   = mode;
1757203954Srdivacky}
1758203954Srdivacky
1759226890Sdimlet DecoderMethod = "DecodeCPSInstruction" in {
1760218893Sdimlet M = 1 in
1761226890Sdim  def CPS3p : CPS<(ins imod_op:$imod, iflags_op:$iflags, imm0_31:$mode),
1762218893Sdim                  "$imod\t$iflags, $mode">;
1763218893Sdimlet mode = 0, M = 0 in
1764218893Sdim  def CPS2p : CPS<(ins imod_op:$imod, iflags_op:$iflags), "$imod\t$iflags">;
1765218893Sdim
1766218893Sdimlet imod = 0, iflags = 0, M = 1 in
1767226890Sdim  def CPS1p : CPS<(ins imm0_31:$mode), "\t$mode">;
1768226890Sdim}
1769218893Sdim
1770204642Srdivacky// Preload signals the memory system of possible future data/instruction access.
1771218893Sdimmulticlass APreLoad<bits<1> read, bits<1> data, string opc> {
1772204642Srdivacky
1773218893Sdim  def i12 : AXI<(outs), (ins addrmode_imm12:$addr), MiscFrm, IIC_Preload,
1774218893Sdim                !strconcat(opc, "\t$addr"),
1775263509Sdim                [(ARMPreload addrmode_imm12:$addr, (i32 read), (i32 data))]>,
1776263509Sdim                Sched<[WritePreLd]> {
1777218893Sdim    bits<4> Rt;
1778218893Sdim    bits<17> addr;
1779204642Srdivacky    let Inst{31-26} = 0b111101;
1780204642Srdivacky    let Inst{25} = 0; // 0 for immediate form
1781204642Srdivacky    let Inst{24} = data;
1782218893Sdim    let Inst{23} = addr{12};        // U (add = ('U' == 1))
1783204642Srdivacky    let Inst{22} = read;
1784204642Srdivacky    let Inst{21-20} = 0b01;
1785218893Sdim    let Inst{19-16} = addr{16-13};  // Rn
1786218893Sdim    let Inst{15-12} = 0b1111;
1787218893Sdim    let Inst{11-0}  = addr{11-0};   // imm12
1788204642Srdivacky  }
1789204642Srdivacky
1790218893Sdim  def rs : AXI<(outs), (ins ldst_so_reg:$shift), MiscFrm, IIC_Preload,
1791218893Sdim               !strconcat(opc, "\t$shift"),
1792263509Sdim               [(ARMPreload ldst_so_reg:$shift, (i32 read), (i32 data))]>,
1793263509Sdim               Sched<[WritePreLd]> {
1794218893Sdim    bits<17> shift;
1795204642Srdivacky    let Inst{31-26} = 0b111101;
1796204642Srdivacky    let Inst{25} = 1; // 1 for register form
1797204642Srdivacky    let Inst{24} = data;
1798218893Sdim    let Inst{23} = shift{12};    // U (add = ('U' == 1))
1799204642Srdivacky    let Inst{22} = read;
1800204642Srdivacky    let Inst{21-20} = 0b01;
1801218893Sdim    let Inst{19-16} = shift{16-13}; // Rn
1802218893Sdim    let Inst{15-12} = 0b1111;
1803218893Sdim    let Inst{11-0}  = shift{11-0};
1804226890Sdim    let Inst{4} = 0;
1805204642Srdivacky  }
1806204642Srdivacky}
1807204642Srdivacky
1808218893Sdimdefm PLD  : APreLoad<1, 1, "pld">,  Requires<[IsARM]>;
1809218893Sdimdefm PLDW : APreLoad<0, 1, "pldw">, Requires<[IsARM,HasV7,HasMP]>;
1810218893Sdimdefm PLI  : APreLoad<1, 0, "pli">,  Requires<[IsARM,HasV7]>;
1811204642Srdivacky
1812226890Sdimdef SETEND : AXI<(outs), (ins setend_op:$end), MiscFrm, NoItinerary,
1813263509Sdim                 "setend\t$end", []>, Requires<[IsARM]>, Deprecated<HasV8Ops> {
1814218893Sdim  bits<1> end;
1815218893Sdim  let Inst{31-10} = 0b1111000100000001000000;
1816218893Sdim  let Inst{9} = end;
1817218893Sdim  let Inst{8-0} = 0;
1818203954Srdivacky}
1819203954Srdivacky
1820224145Sdimdef DBG : AI<(outs), (ins imm0_15:$opt), MiscFrm, NoItinerary, "dbg", "\t$opt",
1821224145Sdim             []>, Requires<[IsARM, HasV7]> {
1822218893Sdim  bits<4> opt;
1823218893Sdim  let Inst{27-4} = 0b001100100000111100001111;
1824218893Sdim  let Inst{3-0} = opt;
1825203954Srdivacky}
1826203954Srdivacky
1827252723Sdim/*
1828252723Sdim * A5.4 Permanently UNDEFINED instructions.
1829252723Sdim *
1830252723Sdim * For most targets use UDF #65006, for which the OS will generate SIGTRAP.
1831252723Sdim * Other UDF encodings generate SIGILL.
1832252723Sdim *
1833252723Sdim * NaCl's OS instead chooses an ARM UDF encoding that's also a UDF in Thumb.
1834252723Sdim * Encoding A1:
1835252723Sdim *  1110 0111 1111 iiii iiii iiii 1111 iiii
1836252723Sdim * Encoding T1:
1837252723Sdim *  1101 1110 iiii iiii
1838252723Sdim * It uses the following encoding:
1839252723Sdim *  1110 0111 1111 1110 1101 1110 1111 0000
1840252723Sdim *  - In ARM: UDF #60896;
1841252723Sdim *  - In Thumb: UDF #254 followed by a branch-to-self.
1842252723Sdim */
1843208599Srdivackylet isBarrier = 1, isTerminator = 1 in
1844252723Sdimdef TRAPNaCl : AXI<(outs), (ins), MiscFrm, NoItinerary,
1845252723Sdim               "trap", [(trap)]>,
1846252723Sdim           Requires<[IsARM,UseNaClTrap]> {
1847252723Sdim  let Inst = 0xe7fedef0;
1848252723Sdim}
1849252723Sdimlet isBarrier = 1, isTerminator = 1 in
1850218893Sdimdef TRAP : AXI<(outs), (ins), MiscFrm, NoItinerary,
1851218893Sdim               "trap", [(trap)]>,
1852252723Sdim           Requires<[IsARM,DontUseNaClTrap]> {
1853218893Sdim  let Inst = 0xe7ffdefe;
1854203954Srdivacky}
1855203954Srdivacky
1856193323Sed// Address computation and loads and stores in PIC mode.
1857193323Sedlet isNotDuplicable = 1 in {
1858218893Sdimdef PICADD  : ARMPseudoInst<(outs GPR:$dst), (ins GPR:$a, pclabel:$cp, pred:$p),
1859224145Sdim                            4, IIC_iALUr,
1860263509Sdim                            [(set GPR:$dst, (ARMpic_add GPR:$a, imm:$cp))]>,
1861263509Sdim                            Sched<[WriteALU, ReadALU]>;
1862193323Sed
1863193323Sedlet AddedComplexity = 10 in {
1864218893Sdimdef PICLDR  : ARMPseudoInst<(outs GPR:$dst), (ins addrmodepc:$addr, pred:$p),
1865224145Sdim                            4, IIC_iLoad_r,
1866218893Sdim                            [(set GPR:$dst, (load addrmodepc:$addr))]>;
1867193323Sed
1868218893Sdimdef PICLDRH : ARMPseudoInst<(outs GPR:$Rt), (ins addrmodepc:$addr, pred:$p),
1869224145Sdim                            4, IIC_iLoad_bh_r,
1870218893Sdim                            [(set GPR:$Rt, (zextloadi16 addrmodepc:$addr))]>;
1871193323Sed
1872218893Sdimdef PICLDRB : ARMPseudoInst<(outs GPR:$Rt), (ins addrmodepc:$addr, pred:$p),
1873224145Sdim                            4, IIC_iLoad_bh_r,
1874218893Sdim                            [(set GPR:$Rt, (zextloadi8 addrmodepc:$addr))]>;
1875193323Sed
1876218893Sdimdef PICLDRSH : ARMPseudoInst<(outs GPR:$Rt), (ins addrmodepc:$addr, pred:$p),
1877224145Sdim                            4, IIC_iLoad_bh_r,
1878218893Sdim                            [(set GPR:$Rt, (sextloadi16 addrmodepc:$addr))]>;
1879193323Sed
1880218893Sdimdef PICLDRSB : ARMPseudoInst<(outs GPR:$Rt), (ins addrmodepc:$addr, pred:$p),
1881224145Sdim                            4, IIC_iLoad_bh_r,
1882218893Sdim                            [(set GPR:$Rt, (sextloadi8 addrmodepc:$addr))]>;
1883193323Sed}
1884193323Sedlet AddedComplexity = 10 in {
1885218893Sdimdef PICSTR  : ARMPseudoInst<(outs), (ins GPR:$src, addrmodepc:$addr, pred:$p),
1886224145Sdim      4, IIC_iStore_r, [(store GPR:$src, addrmodepc:$addr)]>;
1887193323Sed
1888218893Sdimdef PICSTRH : ARMPseudoInst<(outs), (ins GPR:$src, addrmodepc:$addr, pred:$p),
1889224145Sdim      4, IIC_iStore_bh_r, [(truncstorei16 GPR:$src,
1890218893Sdim                                                   addrmodepc:$addr)]>;
1891193323Sed
1892218893Sdimdef PICSTRB : ARMPseudoInst<(outs), (ins GPR:$src, addrmodepc:$addr, pred:$p),
1893224145Sdim      4, IIC_iStore_bh_r, [(truncstorei8 GPR:$src, addrmodepc:$addr)]>;
1894193323Sed}
1895193323Sed} // isNotDuplicable = 1
1896193323Sed
1897194710Sed
1898194710Sed// LEApcrel - Load a pc-relative address into a register without offending the
1899194710Sed// assembler.
1900218893Sdimlet neverHasSideEffects = 1, isReMaterializable = 1 in
1901218893Sdim// The 'adr' mnemonic encodes differently if the label is before or after
1902218893Sdim// the instruction. The {24-21} opcode bits are set by the fixup, as we don't
1903218893Sdim// know until then which form of the instruction will be used.
1904221345Sdimdef ADR : AI1<{0,?,?,0}, (outs GPR:$Rd), (ins adrlabel:$label),
1905252723Sdim                 MiscFrm, IIC_iALUi, "adr", "\t$Rd, $label", []>,
1906252723Sdim                 Sched<[WriteALU, ReadALU]> {
1907218893Sdim  bits<4> Rd;
1908226890Sdim  bits<14> label;
1909218893Sdim  let Inst{27-25} = 0b001;
1910226890Sdim  let Inst{24} = 0;
1911226890Sdim  let Inst{23-22} = label{13-12};
1912226890Sdim  let Inst{21} = 0;
1913218893Sdim  let Inst{20} = 0;
1914218893Sdim  let Inst{19-16} = 0b1111;
1915218893Sdim  let Inst{15-12} = Rd;
1916226890Sdim  let Inst{11-0} = label{11-0};
1917198090Srdivacky}
1918245431Sdim
1919245431Sdimlet hasSideEffects = 1 in {
1920218893Sdimdef LEApcrel : ARMPseudoInst<(outs GPR:$Rd), (ins i32imm:$label, pred:$p),
1921263509Sdim                    4, IIC_iALUi, []>, Sched<[WriteALU, ReadALU]>;
1922194710Sed
1923218893Sdimdef LEApcrelJT : ARMPseudoInst<(outs GPR:$Rd),
1924218893Sdim                      (ins i32imm:$label, nohash_imm:$id, pred:$p),
1925263509Sdim                      4, IIC_iALUi, []>, Sched<[WriteALU, ReadALU]>;
1926245431Sdim}
1927218893Sdim
1928193323Sed//===----------------------------------------------------------------------===//
1929193323Sed//  Control Flow Instructions.
1930193323Sed//
1931193323Sed
1932204961Srdivackylet isReturn = 1, isTerminator = 1, isBarrier = 1 in {
1933204961Srdivacky  // ARMV4T and above
1934204642Srdivacky  def BX_RET : AI<(outs), (ins), BrMiscFrm, IIC_Br,
1935204961Srdivacky                  "bx", "\tlr", [(ARMretflag)]>,
1936263509Sdim               Requires<[IsARM, HasV4T]>, Sched<[WriteBr]> {
1937218893Sdim    let Inst{27-0}  = 0b0001001011111111111100011110;
1938204961Srdivacky  }
1939204961Srdivacky
1940204961Srdivacky  // ARMV4 only
1941218893Sdim  def MOVPCLR : AI<(outs), (ins), BrMiscFrm, IIC_Br,
1942204961Srdivacky                  "mov", "\tpc, lr", [(ARMretflag)]>,
1943263509Sdim               Requires<[IsARM, NoV4T]>, Sched<[WriteBr]> {
1944218893Sdim    let Inst{27-0} = 0b0001101000001111000000001110;
1945204961Srdivacky  }
1946263509Sdim
1947263509Sdim  // Exception return: N.b. doesn't set CPSR as far as we're concerned (it sets
1948263509Sdim  // the user-space one).
1949263509Sdim  def SUBS_PC_LR : ARMPseudoInst<(outs), (ins i32imm:$offset, pred:$p),
1950263509Sdim                                 4, IIC_Br,
1951263509Sdim                                 [(ARMintretflag imm:$offset)]>;
1952193323Sed}
1953193323Sed
1954198892Srdivacky// Indirect branches
1955198892Srdivackylet isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
1956204961Srdivacky  // ARMV4T and above
1957218893Sdim  def BX : AXI<(outs), (ins GPR:$dst), BrMiscFrm, IIC_Br, "bx\t$dst",
1958204961Srdivacky                  [(brind GPR:$dst)]>,
1959263509Sdim              Requires<[IsARM, HasV4T]>, Sched<[WriteBr]> {
1960218893Sdim    bits<4> dst;
1961218893Sdim    let Inst{31-4} = 0b1110000100101111111111110001;
1962218893Sdim    let Inst{3-0}  = dst;
1963198892Srdivacky  }
1964204961Srdivacky
1965224145Sdim  def BX_pred : AI<(outs), (ins GPR:$dst), BrMiscFrm, IIC_Br,
1966224145Sdim                  "bx", "\t$dst", [/* pattern left blank */]>,
1967263509Sdim              Requires<[IsARM, HasV4T]>, Sched<[WriteBr]> {
1968223017Sdim    bits<4> dst;
1969223017Sdim    let Inst{27-4} = 0b000100101111111111110001;
1970223017Sdim    let Inst{3-0}  = dst;
1971223017Sdim  }
1972198892Srdivacky}
1973198892Srdivacky
1974235633Sdim// SP is marked as a use to prevent stack-pointer assignments that appear
1975235633Sdim// immediately before calls from potentially appearing dead.
1976198090Srdivackylet isCall = 1,
1977221345Sdim  // FIXME:  Do we really need a non-predicated version? If so, it should
1978221345Sdim  // at least be a pseudo instruction expanding to the predicated version
1979221345Sdim  // at MC lowering time.
1980235633Sdim  Defs = [LR], Uses = [SP] in {
1981245431Sdim  def BL  : ABXI<0b1011, (outs), (ins bl_target:$func),
1982218893Sdim                IIC_Br, "bl\t$func",
1983198090Srdivacky                [(ARMcall tglobaladdr:$func)]>,
1984263509Sdim            Requires<[IsARM]>, Sched<[WriteBrL]> {
1985198892Srdivacky    let Inst{31-28} = 0b1110;
1986218893Sdim    bits<24> func;
1987218893Sdim    let Inst{23-0} = func;
1988226890Sdim    let DecoderMethod = "DecodeBranchImmInstruction";
1989198892Srdivacky  }
1990193323Sed
1991245431Sdim  def BL_pred : ABI<0b1011, (outs), (ins bl_target:$func),
1992218893Sdim                   IIC_Br, "bl", "\t$func",
1993198090Srdivacky                   [(ARMcall_pred tglobaladdr:$func)]>,
1994263509Sdim                Requires<[IsARM]>, Sched<[WriteBrL]> {
1995218893Sdim    bits<24> func;
1996218893Sdim    let Inst{23-0} = func;
1997226890Sdim    let DecoderMethod = "DecodeBranchImmInstruction";
1998218893Sdim  }
1999193323Sed
2000193323Sed  // ARMv5T and above
2001245431Sdim  def BLX : AXI<(outs), (ins GPR:$func), BrMiscFrm,
2002198892Srdivacky                IIC_Br, "blx\t$func",
2003198090Srdivacky                [(ARMcall GPR:$func)]>,
2004263509Sdim            Requires<[IsARM, HasV5T]>, Sched<[WriteBrL]> {
2005218893Sdim    bits<4> func;
2006218893Sdim    let Inst{31-4} = 0b1110000100101111111111110011;
2007221345Sdim    let Inst{3-0}  = func;
2008193323Sed  }
2009193323Sed
2010245431Sdim  def BLX_pred : AI<(outs), (ins GPR:$func), BrMiscFrm,
2011221345Sdim                    IIC_Br, "blx", "\t$func",
2012221345Sdim                    [(ARMcall_pred GPR:$func)]>,
2013263509Sdim                 Requires<[IsARM, HasV5T]>, Sched<[WriteBrL]> {
2014221345Sdim    bits<4> func;
2015221345Sdim    let Inst{27-4} = 0b000100101111111111110011;
2016221345Sdim    let Inst{3-0}  = func;
2017221345Sdim  }
2018221345Sdim
2019198090Srdivacky  // ARMv4T
2020204642Srdivacky  // Note: Restrict $func to the tGPR regclass to prevent it being in LR.
2021245431Sdim  def BX_CALL : ARMPseudoInst<(outs), (ins tGPR:$func),
2022224145Sdim                   8, IIC_Br, [(ARMcall_nolink tGPR:$func)]>,
2023263509Sdim                   Requires<[IsARM, HasV4T]>, Sched<[WriteBr]>;
2024204961Srdivacky
2025204961Srdivacky  // ARMv4
2026245431Sdim  def BMOVPCRX_CALL : ARMPseudoInst<(outs), (ins tGPR:$func),
2027224145Sdim                   8, IIC_Br, [(ARMcall_nolink tGPR:$func)]>,
2028263509Sdim                   Requires<[IsARM, NoV4T]>, Sched<[WriteBr]>;
2029193323Sed
2030235633Sdim  // mov lr, pc; b if callee is marked noreturn to avoid confusing the
2031235633Sdim  // return stack predictor.
2032245431Sdim  def BMOVPCB_CALL : ARMPseudoInst<(outs), (ins bl_target:$func),
2033235633Sdim                               8, IIC_Br, [(ARMcall_nolink tglobaladdr:$func)]>,
2034263509Sdim                      Requires<[IsARM]>, Sched<[WriteBr]>;
2035194710Sed}
2036194710Sed
2037224145Sdimlet isBranch = 1, isTerminator = 1 in {
2038224145Sdim  // FIXME: should be able to write a pattern for ARMBrcond, but can't use
2039224145Sdim  // a two-value operand where a dag node expects two operands. :(
2040224145Sdim  def Bcc : ABI<0b1010, (outs), (ins br_target:$target),
2041224145Sdim               IIC_Br, "b", "\t$target",
2042263509Sdim               [/*(ARMbrcond bb:$target, imm:$cc, CCR:$ccr)*/]>,
2043263509Sdim               Sched<[WriteBr]>  {
2044224145Sdim    bits<24> target;
2045224145Sdim    let Inst{23-0} = target;
2046226890Sdim    let DecoderMethod = "DecodeBranchImmInstruction";
2047210299Sed  }
2048210299Sed
2049193323Sed  let isBarrier = 1 in {
2050224145Sdim    // B is "predicable" since it's just a Bcc with an 'always' condition.
2051193323Sed    let isPredicable = 1 in
2052221345Sdim    // FIXME: We shouldn't need this pseudo at all. Just using Bcc directly
2053221345Sdim    // should be sufficient.
2054224145Sdim    // FIXME: Is B really a Barrier? That doesn't seem right.
2055224145Sdim    def B : ARMPseudoExpand<(outs), (ins br_target:$target), 4, IIC_Br,
2056263509Sdim                [(br bb:$target)], (Bcc br_target:$target, (ops 14, zero_reg))>,
2057263509Sdim                Sched<[WriteBr]>;
2058193323Sed
2059218893Sdim    let isNotDuplicable = 1, isIndirectBranch = 1 in {
2060218893Sdim    def BR_JTr : ARMPseudoInst<(outs),
2061218893Sdim                      (ins GPR:$target, i32imm:$jt, i32imm:$id),
2062224145Sdim                      0, IIC_Br,
2063263509Sdim                      [(ARMbrjt GPR:$target, tjumptable:$jt, imm:$id)]>,
2064263509Sdim                      Sched<[WriteBr]>;
2065218893Sdim    // FIXME: This shouldn't use the generic "addrmode2," but rather be split
2066218893Sdim    // into i12 and rs suffixed versions.
2067218893Sdim    def BR_JTm : ARMPseudoInst<(outs),
2068218893Sdim                     (ins addrmode2:$target, i32imm:$jt, i32imm:$id),
2069224145Sdim                     0, IIC_Br,
2070218893Sdim                     [(ARMbrjt (i32 (load addrmode2:$target)), tjumptable:$jt,
2071263509Sdim                       imm:$id)]>, Sched<[WriteBrTbl]>;
2072218893Sdim    def BR_JTadd : ARMPseudoInst<(outs),
2073218893Sdim                   (ins GPR:$target, GPR:$idx, i32imm:$jt, i32imm:$id),
2074224145Sdim                   0, IIC_Br,
2075218893Sdim                   [(ARMbrjt (add GPR:$target, GPR:$idx), tjumptable:$jt,
2076263509Sdim                     imm:$id)]>, Sched<[WriteBrTbl]>;
2077218893Sdim    } // isNotDuplicable = 1, isIndirectBranch = 1
2078193323Sed  } // isBarrier = 1
2079193323Sed
2080193323Sed}
2081193323Sed
2082226890Sdim// BLX (immediate)
2083226890Sdimdef BLXi : AXI<(outs), (ins blx_target:$target), BrMiscFrm, NoItinerary,
2084226890Sdim               "blx\t$target", []>,
2085263509Sdim           Requires<[IsARM, HasV5T]>, Sched<[WriteBrL]> {
2086221345Sdim  let Inst{31-25} = 0b1111101;
2087221345Sdim  bits<25> target;
2088221345Sdim  let Inst{23-0} = target{24-1};
2089221345Sdim  let Inst{24} = target{0};
2090221345Sdim}
2091221345Sdim
2092224145Sdim// Branch and Exchange Jazelle
2093203954Srdivackydef BXJ : ABI<0b0001, (outs), (ins GPR:$func), NoItinerary, "bxj", "\t$func",
2094263509Sdim              [/* pattern left blank */]>, Sched<[WriteBr]> {
2095224145Sdim  bits<4> func;
2096203954Srdivacky  let Inst{23-20} = 0b0010;
2097224145Sdim  let Inst{19-8} = 0xfff;
2098203954Srdivacky  let Inst{7-4} = 0b0010;
2099224145Sdim  let Inst{3-0} = func;
2100203954Srdivacky}
2101203954Srdivacky
2102224145Sdim// Tail calls.
2103224145Sdim
2104235633Sdimlet isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [SP] in {
2105263509Sdim  def TCRETURNdi : PseudoInst<(outs), (ins i32imm:$dst), IIC_Br, []>,
2106263509Sdim                   Sched<[WriteBr]>;
2107224145Sdim
2108263509Sdim  def TCRETURNri : PseudoInst<(outs), (ins tcGPR:$dst), IIC_Br, []>,
2109263509Sdim                   Sched<[WriteBr]>;
2110224145Sdim
2111245431Sdim  def TAILJMPd : ARMPseudoExpand<(outs), (ins br_target:$dst),
2112235633Sdim                                 4, IIC_Br, [],
2113235633Sdim                                 (Bcc br_target:$dst, (ops 14, zero_reg))>,
2114263509Sdim                                 Requires<[IsARM]>, Sched<[WriteBr]>;
2115224145Sdim
2116245431Sdim  def TAILJMPr : ARMPseudoExpand<(outs), (ins tcGPR:$dst),
2117235633Sdim                                 4, IIC_Br, [],
2118263509Sdim                                 (BX GPR:$dst)>, Sched<[WriteBr]>,
2119235633Sdim                                 Requires<[IsARM]>;
2120224145Sdim}
2121224145Sdim
2122226890Sdim// Secure Monitor Call is a system instruction.
2123226890Sdimdef SMC : ABI<0b0001, (outs), (ins imm0_15:$opt), NoItinerary, "smc", "\t$opt",
2124252723Sdim              []>, Requires<[IsARM, HasTrustZone]> {
2125218893Sdim  bits<4> opt;
2126218893Sdim  let Inst{23-4} = 0b01100000000000000111;
2127218893Sdim  let Inst{3-0} = opt;
2128204642Srdivacky}
2129204642Srdivacky
2130226890Sdim// Supervisor Call (Software Interrupt)
2131218893Sdimlet isCall = 1, Uses = [SP] in {
2132263509Sdimdef SVC : ABI<0b1111, (outs), (ins imm24b:$svc), IIC_Br, "svc", "\t$svc", []>,
2133263509Sdim          Sched<[WriteBr]> {
2134218893Sdim  bits<24> svc;
2135218893Sdim  let Inst{23-0} = svc;
2136203954Srdivacky}
2137218893Sdim}
2138203954Srdivacky
2139226890Sdim// Store Return State
2140226890Sdimclass SRSI<bit wb, string asm>
2141226890Sdim  : XI<(outs), (ins imm0_31:$mode), AddrModeNone, 4, IndexModeNone, BrFrm,
2142226890Sdim       NoItinerary, asm, "", []> {
2143226890Sdim  bits<5> mode;
2144204642Srdivacky  let Inst{31-28} = 0b1111;
2145226890Sdim  let Inst{27-25} = 0b100;
2146226890Sdim  let Inst{22} = 1;
2147226890Sdim  let Inst{21} = wb;
2148226890Sdim  let Inst{20} = 0;
2149226890Sdim  let Inst{19-16} = 0b1101;  // SP
2150226890Sdim  let Inst{15-5} = 0b00000101000;
2151226890Sdim  let Inst{4-0} = mode;
2152204642Srdivacky}
2153204642Srdivacky
2154226890Sdimdef SRSDA : SRSI<0, "srsda\tsp, $mode"> {
2155226890Sdim  let Inst{24-23} = 0;
2156204642Srdivacky}
2157226890Sdimdef SRSDA_UPD : SRSI<1, "srsda\tsp!, $mode"> {
2158226890Sdim  let Inst{24-23} = 0;
2159226890Sdim}
2160226890Sdimdef SRSDB : SRSI<0, "srsdb\tsp, $mode"> {
2161226890Sdim  let Inst{24-23} = 0b10;
2162226890Sdim}
2163226890Sdimdef SRSDB_UPD : SRSI<1, "srsdb\tsp!, $mode"> {
2164226890Sdim  let Inst{24-23} = 0b10;
2165226890Sdim}
2166226890Sdimdef SRSIA : SRSI<0, "srsia\tsp, $mode"> {
2167226890Sdim  let Inst{24-23} = 0b01;
2168226890Sdim}
2169226890Sdimdef SRSIA_UPD : SRSI<1, "srsia\tsp!, $mode"> {
2170226890Sdim  let Inst{24-23} = 0b01;
2171226890Sdim}
2172226890Sdimdef SRSIB : SRSI<0, "srsib\tsp, $mode"> {
2173226890Sdim  let Inst{24-23} = 0b11;
2174226890Sdim}
2175226890Sdimdef SRSIB_UPD : SRSI<1, "srsib\tsp!, $mode"> {
2176226890Sdim  let Inst{24-23} = 0b11;
2177226890Sdim}
2178204642Srdivacky
2179252723Sdimdef : ARMInstAlias<"srsda $mode", (SRSDA imm0_31:$mode)>;
2180252723Sdimdef : ARMInstAlias<"srsda $mode!", (SRSDA_UPD imm0_31:$mode)>;
2181252723Sdim
2182252723Sdimdef : ARMInstAlias<"srsdb $mode", (SRSDB imm0_31:$mode)>;
2183252723Sdimdef : ARMInstAlias<"srsdb $mode!", (SRSDB_UPD imm0_31:$mode)>;
2184252723Sdim
2185252723Sdimdef : ARMInstAlias<"srsia $mode", (SRSIA imm0_31:$mode)>;
2186252723Sdimdef : ARMInstAlias<"srsia $mode!", (SRSIA_UPD imm0_31:$mode)>;
2187252723Sdim
2188252723Sdimdef : ARMInstAlias<"srsib $mode", (SRSIB imm0_31:$mode)>;
2189252723Sdimdef : ARMInstAlias<"srsib $mode!", (SRSIB_UPD imm0_31:$mode)>;
2190252723Sdim
2191226890Sdim// Return From Exception
2192226890Sdimclass RFEI<bit wb, string asm>
2193226890Sdim  : XI<(outs), (ins GPR:$Rn), AddrModeNone, 4, IndexModeNone, BrFrm,
2194226890Sdim       NoItinerary, asm, "", []> {
2195226890Sdim  bits<4> Rn;
2196204642Srdivacky  let Inst{31-28} = 0b1111;
2197226890Sdim  let Inst{27-25} = 0b100;
2198226890Sdim  let Inst{22} = 0;
2199226890Sdim  let Inst{21} = wb;
2200226890Sdim  let Inst{20} = 1;
2201226890Sdim  let Inst{19-16} = Rn;
2202226890Sdim  let Inst{15-0} = 0xa00;
2203204642Srdivacky}
2204204642Srdivacky
2205226890Sdimdef RFEDA : RFEI<0, "rfeda\t$Rn"> {
2206226890Sdim  let Inst{24-23} = 0;
2207204642Srdivacky}
2208226890Sdimdef RFEDA_UPD : RFEI<1, "rfeda\t$Rn!"> {
2209226890Sdim  let Inst{24-23} = 0;
2210226890Sdim}
2211226890Sdimdef RFEDB : RFEI<0, "rfedb\t$Rn"> {
2212226890Sdim  let Inst{24-23} = 0b10;
2213226890Sdim}
2214226890Sdimdef RFEDB_UPD : RFEI<1, "rfedb\t$Rn!"> {
2215226890Sdim  let Inst{24-23} = 0b10;
2216226890Sdim}
2217226890Sdimdef RFEIA : RFEI<0, "rfeia\t$Rn"> {
2218226890Sdim  let Inst{24-23} = 0b01;
2219226890Sdim}
2220226890Sdimdef RFEIA_UPD : RFEI<1, "rfeia\t$Rn!"> {
2221226890Sdim  let Inst{24-23} = 0b01;
2222226890Sdim}
2223226890Sdimdef RFEIB : RFEI<0, "rfeib\t$Rn"> {
2224226890Sdim  let Inst{24-23} = 0b11;
2225226890Sdim}
2226226890Sdimdef RFEIB_UPD : RFEI<1, "rfeib\t$Rn!"> {
2227226890Sdim  let Inst{24-23} = 0b11;
2228226890Sdim}
2229204642Srdivacky
2230193323Sed//===----------------------------------------------------------------------===//
2231235633Sdim//  Load / Store Instructions.
2232193323Sed//
2233193323Sed
2234193323Sed// Load
2235193323Sed
2236218893Sdim
2237218893Sdimdefm LDR  : AI_ldr1<0, "ldr", IIC_iLoad_r, IIC_iLoad_si,
2238218893Sdim                    UnOpFrag<(load node:$Src)>>;
2239226890Sdimdefm LDRB : AI_ldr1nopc<1, "ldrb", IIC_iLoad_bh_r, IIC_iLoad_bh_si,
2240218893Sdim                    UnOpFrag<(zextloadi8 node:$Src)>>;
2241218893Sdimdefm STR  : AI_str1<0, "str", IIC_iStore_r, IIC_iStore_si,
2242218893Sdim                   BinOpFrag<(store node:$LHS, node:$RHS)>>;
2243226890Sdimdefm STRB : AI_str1nopc<1, "strb", IIC_iStore_bh_r, IIC_iStore_bh_si,
2244218893Sdim                   BinOpFrag<(truncstorei8 node:$LHS, node:$RHS)>>;
2245218893Sdim
2246193323Sed// Special LDR for loads from non-pc-relative constpools.
2247208599Srdivackylet canFoldAsLoad = 1, mayLoad = 1, neverHasSideEffects = 1,
2248226890Sdim    isReMaterializable = 1, isCodeGenOnly = 1 in
2249218893Sdimdef LDRcp : AI2ldst<0b010, 1, 0, (outs GPR:$Rt), (ins addrmode_imm12:$addr),
2250218893Sdim                 AddrMode_i12, LdFrm, IIC_iLoad_r, "ldr", "\t$Rt, $addr",
2251218893Sdim                 []> {
2252218893Sdim  bits<4> Rt;
2253218893Sdim  bits<17> addr;
2254218893Sdim  let Inst{23}    = addr{12};     // U (add = ('U' == 1))
2255218893Sdim  let Inst{19-16} = 0b1111;
2256218893Sdim  let Inst{15-12} = Rt;
2257218893Sdim  let Inst{11-0}  = addr{11-0};   // imm12
2258218893Sdim}
2259193323Sed
2260193323Sed// Loads with zero extension
2261218893Sdimdef LDRH  : AI3ld<0b1011, 1, (outs GPR:$Rt), (ins addrmode3:$addr), LdMiscFrm,
2262218893Sdim                  IIC_iLoad_bh_r, "ldrh", "\t$Rt, $addr",
2263218893Sdim                  [(set GPR:$Rt, (zextloadi16 addrmode3:$addr))]>;
2264193323Sed
2265193323Sed// Loads with sign extension
2266218893Sdimdef LDRSH : AI3ld<0b1111, 1, (outs GPR:$Rt), (ins addrmode3:$addr), LdMiscFrm,
2267218893Sdim                   IIC_iLoad_bh_r, "ldrsh", "\t$Rt, $addr",
2268218893Sdim                   [(set GPR:$Rt, (sextloadi16 addrmode3:$addr))]>;
2269193323Sed
2270218893Sdimdef LDRSB : AI3ld<0b1101, 1, (outs GPR:$Rt), (ins addrmode3:$addr), LdMiscFrm,
2271218893Sdim                   IIC_iLoad_bh_r, "ldrsb", "\t$Rt, $addr",
2272218893Sdim                   [(set GPR:$Rt, (sextloadi8 addrmode3:$addr))]>;
2273193323Sed
2274221345Sdimlet mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 in {
2275193323Sed// Load doubleword
2276218893Sdimdef LDRD : AI3ld<0b1101, 0, (outs GPR:$Rd, GPR:$dst2),
2277218893Sdim                 (ins addrmode3:$addr), LdMiscFrm,
2278221345Sdim                 IIC_iLoad_d_r, "ldrd", "\t$Rd, $dst2, $addr",
2279198090Srdivacky                 []>, Requires<[IsARM, HasV5TE]>;
2280218893Sdim}
2281193323Sed
2282263509Sdimdef LDA : AIldracq<0b00, (outs GPR:$Rt), (ins addr_offset_none:$addr),
2283263509Sdim                    NoItinerary, "lda", "\t$Rt, $addr", []>;
2284263509Sdimdef LDAB : AIldracq<0b10, (outs GPR:$Rt), (ins addr_offset_none:$addr),
2285263509Sdim                    NoItinerary, "ldab", "\t$Rt, $addr", []>;
2286263509Sdimdef LDAH : AIldracq<0b11, (outs GPR:$Rt), (ins addr_offset_none:$addr),
2287263509Sdim                    NoItinerary, "ldah", "\t$Rt, $addr", []>;
2288263509Sdim
2289193323Sed// Indexed loads
2290235633Sdimmulticlass AI2_ldridx<bit isByte, string opc,
2291235633Sdim                      InstrItinClass iii, InstrItinClass iir> {
2292226890Sdim  def _PRE_IMM  : AI2ldstidx<1, isByte, 1, (outs GPR:$Rt, GPR:$Rn_wb),
2293252723Sdim                      (ins addrmode_imm12_pre:$addr), IndexModePre, LdFrm, iii,
2294218893Sdim                      opc, "\t$Rt, $addr!", "$addr.base = $Rn_wb", []> {
2295226890Sdim    bits<17> addr;
2296226890Sdim    let Inst{25} = 0;
2297218893Sdim    let Inst{23} = addr{12};
2298226890Sdim    let Inst{19-16} = addr{16-13};
2299218893Sdim    let Inst{11-0} = addr{11-0};
2300226890Sdim    let DecoderMethod = "DecodeLDRPreImm";
2301218893Sdim  }
2302226890Sdim
2303226890Sdim  def _PRE_REG  : AI2ldstidx<1, isByte, 1, (outs GPR:$Rt, GPR:$Rn_wb),
2304235633Sdim                      (ins ldst_so_reg:$addr), IndexModePre, LdFrm, iir,
2305226890Sdim                      opc, "\t$Rt, $addr!", "$addr.base = $Rn_wb", []> {
2306226890Sdim    bits<17> addr;
2307226890Sdim    let Inst{25} = 1;
2308226890Sdim    let Inst{23} = addr{12};
2309226890Sdim    let Inst{19-16} = addr{16-13};
2310226890Sdim    let Inst{11-0} = addr{11-0};
2311226890Sdim    let Inst{4} = 0;
2312226890Sdim    let DecoderMethod = "DecodeLDRPreReg";
2313226890Sdim  }
2314226890Sdim
2315226890Sdim  def _POST_REG : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb),
2316226890Sdim                       (ins addr_offset_none:$addr, am2offset_reg:$offset),
2317235633Sdim                       IndexModePost, LdFrm, iir,
2318226890Sdim                       opc, "\t$Rt, $addr, $offset",
2319226890Sdim                       "$addr.base = $Rn_wb", []> {
2320226890Sdim     // {12}     isAdd
2321226890Sdim     // {11-0}   imm12/Rm
2322226890Sdim     bits<14> offset;
2323226890Sdim     bits<4> addr;
2324226890Sdim     let Inst{25} = 1;
2325226890Sdim     let Inst{23} = offset{12};
2326226890Sdim     let Inst{19-16} = addr;
2327226890Sdim     let Inst{11-0} = offset{11-0};
2328252723Sdim     let Inst{4} = 0;
2329226890Sdim
2330226890Sdim    let DecoderMethod = "DecodeAddrMode2IdxInstruction";
2331226890Sdim   }
2332226890Sdim
2333226890Sdim   def _POST_IMM : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb),
2334226890Sdim                       (ins addr_offset_none:$addr, am2offset_imm:$offset),
2335235633Sdim                      IndexModePost, LdFrm, iii,
2336226890Sdim                      opc, "\t$Rt, $addr, $offset",
2337226890Sdim                      "$addr.base = $Rn_wb", []> {
2338218893Sdim    // {12}     isAdd
2339218893Sdim    // {11-0}   imm12/Rm
2340218893Sdim    bits<14> offset;
2341226890Sdim    bits<4> addr;
2342226890Sdim    let Inst{25} = 0;
2343218893Sdim    let Inst{23} = offset{12};
2344226890Sdim    let Inst{19-16} = addr;
2345218893Sdim    let Inst{11-0} = offset{11-0};
2346226890Sdim
2347226890Sdim    let DecoderMethod = "DecodeAddrMode2IdxInstruction";
2348218893Sdim  }
2349226890Sdim
2350218893Sdim}
2351193323Sed
2352218893Sdimlet mayLoad = 1, neverHasSideEffects = 1 in {
2353235633Sdim// FIXME: for LDR_PRE_REG etc. the itineray should be either IIC_iLoad_ru or
2354235633Sdim// IIC_iLoad_siu depending on whether it the offset register is shifted.
2355235633Sdimdefm LDR  : AI2_ldridx<0, "ldr", IIC_iLoad_iu, IIC_iLoad_ru>;
2356235633Sdimdefm LDRB : AI2_ldridx<1, "ldrb", IIC_iLoad_bh_iu, IIC_iLoad_bh_ru>;
2357218893Sdim}
2358193323Sed
2359226890Sdimmulticlass AI3_ldridx<bits<4> op, string opc, InstrItinClass itin> {
2360226890Sdim  def _PRE  : AI3ldstidx<op, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
2361252723Sdim                        (ins addrmode3_pre:$addr), IndexModePre,
2362218893Sdim                        LdMiscFrm, itin,
2363218893Sdim                        opc, "\t$Rt, $addr!", "$addr.base = $Rn_wb", []> {
2364218893Sdim    bits<14> addr;
2365218893Sdim    let Inst{23}    = addr{8};      // U bit
2366218893Sdim    let Inst{22}    = addr{13};     // 1 == imm8, 0 == Rm
2367218893Sdim    let Inst{19-16} = addr{12-9};   // Rn
2368218893Sdim    let Inst{11-8}  = addr{7-4};    // imm7_4/zero
2369218893Sdim    let Inst{3-0}   = addr{3-0};    // imm3_0/Rm
2370226890Sdim    let DecoderMethod = "DecodeAddrMode3Instruction";
2371218893Sdim  }
2372226890Sdim  def _POST : AI3ldstidx<op, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
2373226890Sdim                        (ins addr_offset_none:$addr, am3offset:$offset),
2374226890Sdim                        IndexModePost, LdMiscFrm, itin,
2375226890Sdim                        opc, "\t$Rt, $addr, $offset", "$addr.base = $Rn_wb",
2376226890Sdim                        []> {
2377218893Sdim    bits<10> offset;
2378226890Sdim    bits<4> addr;
2379218893Sdim    let Inst{23}    = offset{8};      // U bit
2380218893Sdim    let Inst{22}    = offset{9};      // 1 == imm8, 0 == Rm
2381226890Sdim    let Inst{19-16} = addr;
2382218893Sdim    let Inst{11-8}  = offset{7-4};    // imm7_4/zero
2383218893Sdim    let Inst{3-0}   = offset{3-0};    // imm3_0/Rm
2384226890Sdim    let DecoderMethod = "DecodeAddrMode3Instruction";
2385218893Sdim  }
2386218893Sdim}
2387193323Sed
2388218893Sdimlet mayLoad = 1, neverHasSideEffects = 1 in {
2389226890Sdimdefm LDRH  : AI3_ldridx<0b1011, "ldrh", IIC_iLoad_bh_ru>;
2390226890Sdimdefm LDRSH : AI3_ldridx<0b1111, "ldrsh", IIC_iLoad_bh_ru>;
2391226890Sdimdefm LDRSB : AI3_ldridx<0b1101, "ldrsb", IIC_iLoad_bh_ru>;
2392221345Sdimlet hasExtraDefRegAllocReq = 1 in {
2393226890Sdimdef LDRD_PRE : AI3ldstidx<0b1101, 0, 1, (outs GPR:$Rt, GPR:$Rt2, GPR:$Rn_wb),
2394252723Sdim                          (ins addrmode3_pre:$addr), IndexModePre,
2395221345Sdim                          LdMiscFrm, IIC_iLoad_d_ru,
2396221345Sdim                          "ldrd", "\t$Rt, $Rt2, $addr!",
2397221345Sdim                          "$addr.base = $Rn_wb", []> {
2398221345Sdim  bits<14> addr;
2399221345Sdim  let Inst{23}    = addr{8};      // U bit
2400221345Sdim  let Inst{22}    = addr{13};     // 1 == imm8, 0 == Rm
2401221345Sdim  let Inst{19-16} = addr{12-9};   // Rn
2402221345Sdim  let Inst{11-8}  = addr{7-4};    // imm7_4/zero
2403221345Sdim  let Inst{3-0}   = addr{3-0};    // imm3_0/Rm
2404226890Sdim  let DecoderMethod = "DecodeAddrMode3Instruction";
2405221345Sdim}
2406226890Sdimdef LDRD_POST: AI3ldstidx<0b1101, 0, 0, (outs GPR:$Rt, GPR:$Rt2, GPR:$Rn_wb),
2407226890Sdim                          (ins addr_offset_none:$addr, am3offset:$offset),
2408226890Sdim                          IndexModePost, LdMiscFrm, IIC_iLoad_d_ru,
2409226890Sdim                          "ldrd", "\t$Rt, $Rt2, $addr, $offset",
2410226890Sdim                          "$addr.base = $Rn_wb", []> {
2411221345Sdim  bits<10> offset;
2412226890Sdim  bits<4> addr;
2413221345Sdim  let Inst{23}    = offset{8};      // U bit
2414221345Sdim  let Inst{22}    = offset{9};      // 1 == imm8, 0 == Rm
2415226890Sdim  let Inst{19-16} = addr;
2416221345Sdim  let Inst{11-8}  = offset{7-4};    // imm7_4/zero
2417221345Sdim  let Inst{3-0}   = offset{3-0};    // imm3_0/Rm
2418226890Sdim  let DecoderMethod = "DecodeAddrMode3Instruction";
2419221345Sdim}
2420221345Sdim} // hasExtraDefRegAllocReq = 1
2421218893Sdim} // mayLoad = 1, neverHasSideEffects = 1
2422193323Sed
2423226890Sdim// LDRT, LDRBT, LDRSBT, LDRHT, LDRSHT.
2424218893Sdimlet mayLoad = 1, neverHasSideEffects = 1 in {
2425226890Sdimdef LDRT_POST_REG : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$Rn_wb),
2426226890Sdim                    (ins addr_offset_none:$addr, am2offset_reg:$offset),
2427226890Sdim                    IndexModePost, LdFrm, IIC_iLoad_ru,
2428226890Sdim                    "ldrt", "\t$Rt, $addr, $offset",
2429226890Sdim                    "$addr.base = $Rn_wb", []> {
2430221345Sdim  // {12}     isAdd
2431221345Sdim  // {11-0}   imm12/Rm
2432226890Sdim  bits<14> offset;
2433226890Sdim  bits<4> addr;
2434226890Sdim  let Inst{25} = 1;
2435226890Sdim  let Inst{23} = offset{12};
2436203954Srdivacky  let Inst{21} = 1; // overwrite
2437226890Sdim  let Inst{19-16} = addr;
2438226890Sdim  let Inst{11-5} = offset{11-5};
2439226890Sdim  let Inst{4} = 0;
2440226890Sdim  let Inst{3-0} = offset{3-0};
2441226890Sdim  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
2442203954Srdivacky}
2443226890Sdim
2444226890Sdimdef LDRT_POST_IMM : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$Rn_wb),
2445226890Sdim                    (ins addr_offset_none:$addr, am2offset_imm:$offset),
2446226890Sdim                   IndexModePost, LdFrm, IIC_iLoad_ru,
2447226890Sdim                   "ldrt", "\t$Rt, $addr, $offset",
2448226890Sdim                   "$addr.base = $Rn_wb", []> {
2449221345Sdim  // {12}     isAdd
2450221345Sdim  // {11-0}   imm12/Rm
2451226890Sdim  bits<14> offset;
2452226890Sdim  bits<4> addr;
2453226890Sdim  let Inst{25} = 0;
2454226890Sdim  let Inst{23} = offset{12};
2455203954Srdivacky  let Inst{21} = 1; // overwrite
2456226890Sdim  let Inst{19-16} = addr;
2457226890Sdim  let Inst{11-0} = offset{11-0};
2458226890Sdim  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
2459203954Srdivacky}
2460226890Sdim
2461226890Sdimdef LDRBT_POST_REG : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
2462226890Sdim                     (ins addr_offset_none:$addr, am2offset_reg:$offset),
2463226890Sdim                     IndexModePost, LdFrm, IIC_iLoad_bh_ru,
2464226890Sdim                     "ldrbt", "\t$Rt, $addr, $offset",
2465226890Sdim                     "$addr.base = $Rn_wb", []> {
2466226890Sdim  // {12}     isAdd
2467226890Sdim  // {11-0}   imm12/Rm
2468226890Sdim  bits<14> offset;
2469226890Sdim  bits<4> addr;
2470226890Sdim  let Inst{25} = 1;
2471226890Sdim  let Inst{23} = offset{12};
2472204642Srdivacky  let Inst{21} = 1; // overwrite
2473226890Sdim  let Inst{19-16} = addr;
2474226890Sdim  let Inst{11-5} = offset{11-5};
2475226890Sdim  let Inst{4} = 0;
2476226890Sdim  let Inst{3-0} = offset{3-0};
2477226890Sdim  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
2478204642Srdivacky}
2479226890Sdim
2480226890Sdimdef LDRBT_POST_IMM : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
2481226890Sdim                     (ins addr_offset_none:$addr, am2offset_imm:$offset),
2482226890Sdim                    IndexModePost, LdFrm, IIC_iLoad_bh_ru,
2483226890Sdim                    "ldrbt", "\t$Rt, $addr, $offset",
2484226890Sdim                    "$addr.base = $Rn_wb", []> {
2485226890Sdim  // {12}     isAdd
2486226890Sdim  // {11-0}   imm12/Rm
2487226890Sdim  bits<14> offset;
2488226890Sdim  bits<4> addr;
2489226890Sdim  let Inst{25} = 0;
2490226890Sdim  let Inst{23} = offset{12};
2491204642Srdivacky  let Inst{21} = 1; // overwrite
2492226890Sdim  let Inst{19-16} = addr;
2493226890Sdim  let Inst{11-0} = offset{11-0};
2494226890Sdim  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
2495204642Srdivacky}
2496226890Sdim
2497226890Sdimmulticlass AI3ldrT<bits<4> op, string opc> {
2498226890Sdim  def i : AI3ldstidxT<op, 1, (outs GPR:$Rt, GPR:$base_wb),
2499226890Sdim                      (ins addr_offset_none:$addr, postidx_imm8:$offset),
2500226890Sdim                      IndexModePost, LdMiscFrm, IIC_iLoad_bh_ru, opc,
2501226890Sdim                      "\t$Rt, $addr, $offset", "$addr.base = $base_wb", []> {
2502226890Sdim    bits<9> offset;
2503226890Sdim    let Inst{23} = offset{8};
2504226890Sdim    let Inst{22} = 1;
2505226890Sdim    let Inst{11-8} = offset{7-4};
2506226890Sdim    let Inst{3-0} = offset{3-0};
2507226890Sdim  }
2508235633Sdim  def r : AI3ldstidxT<op, 1, (outs GPRnopc:$Rt, GPRnopc:$base_wb),
2509226890Sdim                      (ins addr_offset_none:$addr, postidx_reg:$Rm),
2510226890Sdim                      IndexModePost, LdMiscFrm, IIC_iLoad_bh_ru, opc,
2511226890Sdim                      "\t$Rt, $addr, $Rm", "$addr.base = $base_wb", []> {
2512226890Sdim    bits<5> Rm;
2513226890Sdim    let Inst{23} = Rm{4};
2514226890Sdim    let Inst{22} = 0;
2515226890Sdim    let Inst{11-8} = 0;
2516235633Sdim    let Unpredictable{11-8} = 0b1111;
2517226890Sdim    let Inst{3-0} = Rm{3-0};
2518235633Sdim    let DecoderMethod = "DecodeLDR";
2519226890Sdim  }
2520204642Srdivacky}
2521226890Sdim
2522226890Sdimdefm LDRSBT : AI3ldrT<0b1101, "ldrsbt">;
2523226890Sdimdefm LDRHT  : AI3ldrT<0b1011, "ldrht">;
2524226890Sdimdefm LDRSHT : AI3ldrT<0b1111, "ldrsht">;
2525218893Sdim}
2526204642Srdivacky
2527193323Sed// Store
2528193323Sed
2529193323Sed// Stores with truncate
2530218893Sdimdef STRH : AI3str<0b1011, (outs), (ins GPR:$Rt, addrmode3:$addr), StMiscFrm,
2531218893Sdim               IIC_iStore_bh_r, "strh", "\t$Rt, $addr",
2532218893Sdim               [(truncstorei16 GPR:$Rt, addrmode3:$addr)]>;
2533193323Sed
2534193323Sed// Store doubleword
2535221345Sdimlet mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in
2536221345Sdimdef STRD : AI3str<0b1111, (outs), (ins GPR:$Rt, GPR:$src2, addrmode3:$addr),
2537218893Sdim               StMiscFrm, IIC_iStore_d_r,
2538226890Sdim               "strd", "\t$Rt, $src2, $addr", []>,
2539226890Sdim           Requires<[IsARM, HasV5TE]> {
2540226890Sdim  let Inst{21} = 0;
2541226890Sdim}
2542193323Sed
2543193323Sed// Indexed stores
2544235633Sdimmulticlass AI2_stridx<bit isByte, string opc,
2545235633Sdim                      InstrItinClass iii, InstrItinClass iir> {
2546226890Sdim  def _PRE_IMM : AI2ldstidx<0, isByte, 1, (outs GPR:$Rn_wb),
2547252723Sdim                            (ins GPR:$Rt, addrmode_imm12_pre:$addr), IndexModePre,
2548235633Sdim                            StFrm, iii,
2549226890Sdim                            opc, "\t$Rt, $addr!", "$addr.base = $Rn_wb", []> {
2550226890Sdim    bits<17> addr;
2551226890Sdim    let Inst{25} = 0;
2552226890Sdim    let Inst{23}    = addr{12};     // U (add = ('U' == 1))
2553226890Sdim    let Inst{19-16} = addr{16-13};  // Rn
2554226890Sdim    let Inst{11-0}  = addr{11-0};   // imm12
2555226890Sdim    let DecoderMethod = "DecodeSTRPreImm";
2556226890Sdim  }
2557193323Sed
2558226890Sdim  def _PRE_REG  : AI2ldstidx<0, isByte, 1, (outs GPR:$Rn_wb),
2559226890Sdim                      (ins GPR:$Rt, ldst_so_reg:$addr),
2560235633Sdim                      IndexModePre, StFrm, iir,
2561226890Sdim                      opc, "\t$Rt, $addr!", "$addr.base = $Rn_wb", []> {
2562226890Sdim    bits<17> addr;
2563226890Sdim    let Inst{25} = 1;
2564226890Sdim    let Inst{23}    = addr{12};    // U (add = ('U' == 1))
2565226890Sdim    let Inst{19-16} = addr{16-13}; // Rn
2566226890Sdim    let Inst{11-0}  = addr{11-0};
2567226890Sdim    let Inst{4}     = 0;           // Inst{4} = 0
2568226890Sdim    let DecoderMethod = "DecodeSTRPreReg";
2569226890Sdim  }
2570226890Sdim  def _POST_REG : AI2ldstidx<0, isByte, 0, (outs GPR:$Rn_wb),
2571226890Sdim                (ins GPR:$Rt, addr_offset_none:$addr, am2offset_reg:$offset),
2572235633Sdim                IndexModePost, StFrm, iir,
2573226890Sdim                opc, "\t$Rt, $addr, $offset",
2574226890Sdim                "$addr.base = $Rn_wb", []> {
2575226890Sdim     // {12}     isAdd
2576226890Sdim     // {11-0}   imm12/Rm
2577226890Sdim     bits<14> offset;
2578226890Sdim     bits<4> addr;
2579226890Sdim     let Inst{25} = 1;
2580226890Sdim     let Inst{23} = offset{12};
2581226890Sdim     let Inst{19-16} = addr;
2582226890Sdim     let Inst{11-0} = offset{11-0};
2583245431Sdim     let Inst{4} = 0;
2584193323Sed
2585226890Sdim    let DecoderMethod = "DecodeAddrMode2IdxInstruction";
2586226890Sdim   }
2587193323Sed
2588226890Sdim   def _POST_IMM : AI2ldstidx<0, isByte, 0, (outs GPR:$Rn_wb),
2589226890Sdim                (ins GPR:$Rt, addr_offset_none:$addr, am2offset_imm:$offset),
2590235633Sdim                IndexModePost, StFrm, iii,
2591226890Sdim                opc, "\t$Rt, $addr, $offset",
2592226890Sdim                "$addr.base = $Rn_wb", []> {
2593226890Sdim    // {12}     isAdd
2594226890Sdim    // {11-0}   imm12/Rm
2595226890Sdim    bits<14> offset;
2596226890Sdim    bits<4> addr;
2597226890Sdim    let Inst{25} = 0;
2598226890Sdim    let Inst{23} = offset{12};
2599226890Sdim    let Inst{19-16} = addr;
2600226890Sdim    let Inst{11-0} = offset{11-0};
2601193323Sed
2602226890Sdim    let DecoderMethod = "DecodeAddrMode2IdxInstruction";
2603226890Sdim  }
2604226890Sdim}
2605193323Sed
2606226890Sdimlet mayStore = 1, neverHasSideEffects = 1 in {
2607235633Sdim// FIXME: for STR_PRE_REG etc. the itineray should be either IIC_iStore_ru or
2608235633Sdim// IIC_iStore_siu depending on whether it the offset register is shifted.
2609235633Sdimdefm STR  : AI2_stridx<0, "str", IIC_iStore_iu, IIC_iStore_ru>;
2610235633Sdimdefm STRB : AI2_stridx<1, "strb", IIC_iStore_bh_iu, IIC_iStore_bh_ru>;
2611226890Sdim}
2612226890Sdim
2613226890Sdimdef : ARMPat<(post_store GPR:$Rt, addr_offset_none:$addr,
2614226890Sdim                         am2offset_reg:$offset),
2615226890Sdim             (STR_POST_REG GPR:$Rt, addr_offset_none:$addr,
2616226890Sdim                           am2offset_reg:$offset)>;
2617226890Sdimdef : ARMPat<(post_store GPR:$Rt, addr_offset_none:$addr,
2618226890Sdim                         am2offset_imm:$offset),
2619226890Sdim             (STR_POST_IMM GPR:$Rt, addr_offset_none:$addr,
2620226890Sdim                           am2offset_imm:$offset)>;
2621226890Sdimdef : ARMPat<(post_truncsti8 GPR:$Rt, addr_offset_none:$addr,
2622226890Sdim                             am2offset_reg:$offset),
2623226890Sdim             (STRB_POST_REG GPR:$Rt, addr_offset_none:$addr,
2624226890Sdim                            am2offset_reg:$offset)>;
2625226890Sdimdef : ARMPat<(post_truncsti8 GPR:$Rt, addr_offset_none:$addr,
2626226890Sdim                             am2offset_imm:$offset),
2627226890Sdim             (STRB_POST_IMM GPR:$Rt, addr_offset_none:$addr,
2628226890Sdim                            am2offset_imm:$offset)>;
2629226890Sdim
2630226890Sdim// Pseudo-instructions for pattern matching the pre-indexed stores. We can't
2631226890Sdim// put the patterns on the instruction definitions directly as ISel wants
2632226890Sdim// the address base and offset to be separate operands, not a single
2633226890Sdim// complex operand like we represent the instructions themselves. The
2634226890Sdim// pseudos map between the two.
2635226890Sdimlet usesCustomInserter = 1,
2636226890Sdim    Constraints = "$Rn = $Rn_wb,@earlyclobber $Rn_wb" in {
2637226890Sdimdef STRi_preidx: ARMPseudoInst<(outs GPR:$Rn_wb),
2638226890Sdim               (ins GPR:$Rt, GPR:$Rn, am2offset_imm:$offset, pred:$p),
2639226890Sdim               4, IIC_iStore_ru,
2640226890Sdim            [(set GPR:$Rn_wb,
2641226890Sdim                  (pre_store GPR:$Rt, GPR:$Rn, am2offset_imm:$offset))]>;
2642226890Sdimdef STRr_preidx: ARMPseudoInst<(outs GPR:$Rn_wb),
2643226890Sdim               (ins GPR:$Rt, GPR:$Rn, am2offset_reg:$offset, pred:$p),
2644226890Sdim               4, IIC_iStore_ru,
2645226890Sdim            [(set GPR:$Rn_wb,
2646226890Sdim                  (pre_store GPR:$Rt, GPR:$Rn, am2offset_reg:$offset))]>;
2647226890Sdimdef STRBi_preidx: ARMPseudoInst<(outs GPR:$Rn_wb),
2648226890Sdim               (ins GPR:$Rt, GPR:$Rn, am2offset_imm:$offset, pred:$p),
2649226890Sdim               4, IIC_iStore_ru,
2650226890Sdim            [(set GPR:$Rn_wb,
2651226890Sdim                  (pre_truncsti8 GPR:$Rt, GPR:$Rn, am2offset_imm:$offset))]>;
2652226890Sdimdef STRBr_preidx: ARMPseudoInst<(outs GPR:$Rn_wb),
2653226890Sdim               (ins GPR:$Rt, GPR:$Rn, am2offset_reg:$offset, pred:$p),
2654226890Sdim               4, IIC_iStore_ru,
2655226890Sdim            [(set GPR:$Rn_wb,
2656226890Sdim                  (pre_truncsti8 GPR:$Rt, GPR:$Rn, am2offset_reg:$offset))]>;
2657226890Sdimdef STRH_preidx: ARMPseudoInst<(outs GPR:$Rn_wb),
2658226890Sdim               (ins GPR:$Rt, GPR:$Rn, am3offset:$offset, pred:$p),
2659226890Sdim               4, IIC_iStore_ru,
2660226890Sdim            [(set GPR:$Rn_wb,
2661226890Sdim                  (pre_truncsti16 GPR:$Rt, GPR:$Rn, am3offset:$offset))]>;
2662226890Sdim}
2663226890Sdim
2664226890Sdim
2665226890Sdim
2666226890Sdimdef STRH_PRE  : AI3ldstidx<0b1011, 0, 1, (outs GPR:$Rn_wb),
2667252723Sdim                           (ins GPR:$Rt, addrmode3_pre:$addr), IndexModePre,
2668226890Sdim                           StMiscFrm, IIC_iStore_bh_ru,
2669226890Sdim                           "strh", "\t$Rt, $addr!", "$addr.base = $Rn_wb", []> {
2670226890Sdim  bits<14> addr;
2671226890Sdim  let Inst{23}    = addr{8};      // U bit
2672226890Sdim  let Inst{22}    = addr{13};     // 1 == imm8, 0 == Rm
2673226890Sdim  let Inst{19-16} = addr{12-9};   // Rn
2674226890Sdim  let Inst{11-8}  = addr{7-4};    // imm7_4/zero
2675226890Sdim  let Inst{3-0}   = addr{3-0};    // imm3_0/Rm
2676226890Sdim  let DecoderMethod = "DecodeAddrMode3Instruction";
2677226890Sdim}
2678226890Sdim
2679226890Sdimdef STRH_POST : AI3ldstidx<0b1011, 0, 0, (outs GPR:$Rn_wb),
2680226890Sdim                       (ins GPR:$Rt, addr_offset_none:$addr, am3offset:$offset),
2681226890Sdim                       IndexModePost, StMiscFrm, IIC_iStore_bh_ru,
2682226890Sdim                       "strh", "\t$Rt, $addr, $offset", "$addr.base = $Rn_wb",
2683226890Sdim                   [(set GPR:$Rn_wb, (post_truncsti16 GPR:$Rt,
2684226890Sdim                                                      addr_offset_none:$addr,
2685226890Sdim                                                      am3offset:$offset))]> {
2686226890Sdim  bits<10> offset;
2687226890Sdim  bits<4> addr;
2688226890Sdim  let Inst{23}    = offset{8};      // U bit
2689226890Sdim  let Inst{22}    = offset{9};      // 1 == imm8, 0 == Rm
2690226890Sdim  let Inst{19-16} = addr;
2691226890Sdim  let Inst{11-8}  = offset{7-4};    // imm7_4/zero
2692226890Sdim  let Inst{3-0}   = offset{3-0};    // imm3_0/Rm
2693226890Sdim  let DecoderMethod = "DecodeAddrMode3Instruction";
2694226890Sdim}
2695226890Sdim
2696221345Sdimlet mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in {
2697226890Sdimdef STRD_PRE : AI3ldstidx<0b1111, 0, 1, (outs GPR:$Rn_wb),
2698252723Sdim                          (ins GPR:$Rt, GPR:$Rt2, addrmode3_pre:$addr),
2699226890Sdim                          IndexModePre, StMiscFrm, IIC_iStore_d_ru,
2700226890Sdim                          "strd", "\t$Rt, $Rt2, $addr!",
2701226890Sdim                          "$addr.base = $Rn_wb", []> {
2702226890Sdim  bits<14> addr;
2703226890Sdim  let Inst{23}    = addr{8};      // U bit
2704226890Sdim  let Inst{22}    = addr{13};     // 1 == imm8, 0 == Rm
2705226890Sdim  let Inst{19-16} = addr{12-9};   // Rn
2706226890Sdim  let Inst{11-8}  = addr{7-4};    // imm7_4/zero
2707226890Sdim  let Inst{3-0}   = addr{3-0};    // imm3_0/Rm
2708226890Sdim  let DecoderMethod = "DecodeAddrMode3Instruction";
2709226890Sdim}
2710203954Srdivacky
2711226890Sdimdef STRD_POST: AI3ldstidx<0b1111, 0, 0, (outs GPR:$Rn_wb),
2712226890Sdim                          (ins GPR:$Rt, GPR:$Rt2, addr_offset_none:$addr,
2713226890Sdim                               am3offset:$offset),
2714226890Sdim                          IndexModePost, StMiscFrm, IIC_iStore_d_ru,
2715226890Sdim                          "strd", "\t$Rt, $Rt2, $addr, $offset",
2716226890Sdim                          "$addr.base = $Rn_wb", []> {
2717226890Sdim  bits<10> offset;
2718226890Sdim  bits<4> addr;
2719226890Sdim  let Inst{23}    = offset{8};      // U bit
2720226890Sdim  let Inst{22}    = offset{9};      // 1 == imm8, 0 == Rm
2721226890Sdim  let Inst{19-16} = addr;
2722226890Sdim  let Inst{11-8}  = offset{7-4};    // imm7_4/zero
2723226890Sdim  let Inst{3-0}   = offset{3-0};    // imm3_0/Rm
2724226890Sdim  let DecoderMethod = "DecodeAddrMode3Instruction";
2725226890Sdim}
2726221345Sdim} // mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1
2727204642Srdivacky
2728226890Sdim// STRT, STRBT, and STRHT
2729204642Srdivacky
2730226890Sdimdef STRBT_POST_REG : AI2ldstidx<0, 1, 0, (outs GPR:$Rn_wb),
2731226890Sdim                   (ins GPR:$Rt, addr_offset_none:$addr, am2offset_reg:$offset),
2732226890Sdim                   IndexModePost, StFrm, IIC_iStore_bh_ru,
2733226890Sdim                   "strbt", "\t$Rt, $addr, $offset",
2734226890Sdim                   "$addr.base = $Rn_wb", []> {
2735226890Sdim  // {12}     isAdd
2736226890Sdim  // {11-0}   imm12/Rm
2737226890Sdim  bits<14> offset;
2738226890Sdim  bits<4> addr;
2739226890Sdim  let Inst{25} = 1;
2740226890Sdim  let Inst{23} = offset{12};
2741203954Srdivacky  let Inst{21} = 1; // overwrite
2742226890Sdim  let Inst{19-16} = addr;
2743226890Sdim  let Inst{11-5} = offset{11-5};
2744226890Sdim  let Inst{4} = 0;
2745226890Sdim  let Inst{3-0} = offset{3-0};
2746226890Sdim  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
2747203954Srdivacky}
2748203954Srdivacky
2749226890Sdimdef STRBT_POST_IMM : AI2ldstidx<0, 1, 0, (outs GPR:$Rn_wb),
2750226890Sdim                   (ins GPR:$Rt, addr_offset_none:$addr, am2offset_imm:$offset),
2751226890Sdim                   IndexModePost, StFrm, IIC_iStore_bh_ru,
2752226890Sdim                   "strbt", "\t$Rt, $addr, $offset",
2753226890Sdim                   "$addr.base = $Rn_wb", []> {
2754226890Sdim  // {12}     isAdd
2755226890Sdim  // {11-0}   imm12/Rm
2756226890Sdim  bits<14> offset;
2757226890Sdim  bits<4> addr;
2758226890Sdim  let Inst{25} = 0;
2759226890Sdim  let Inst{23} = offset{12};
2760203954Srdivacky  let Inst{21} = 1; // overwrite
2761226890Sdim  let Inst{19-16} = addr;
2762226890Sdim  let Inst{11-0} = offset{11-0};
2763226890Sdim  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
2764203954Srdivacky}
2765203954Srdivacky
2766226890Sdimlet mayStore = 1, neverHasSideEffects = 1 in {
2767226890Sdimdef STRT_POST_REG : AI2ldstidx<0, 0, 0, (outs GPR:$Rn_wb),
2768226890Sdim                   (ins GPR:$Rt, addr_offset_none:$addr, am2offset_reg:$offset),
2769226890Sdim                   IndexModePost, StFrm, IIC_iStore_ru,
2770226890Sdim                   "strt", "\t$Rt, $addr, $offset",
2771226890Sdim                   "$addr.base = $Rn_wb", []> {
2772226890Sdim  // {12}     isAdd
2773226890Sdim  // {11-0}   imm12/Rm
2774226890Sdim  bits<14> offset;
2775226890Sdim  bits<4> addr;
2776226890Sdim  let Inst{25} = 1;
2777226890Sdim  let Inst{23} = offset{12};
2778204642Srdivacky  let Inst{21} = 1; // overwrite
2779226890Sdim  let Inst{19-16} = addr;
2780226890Sdim  let Inst{11-5} = offset{11-5};
2781226890Sdim  let Inst{4} = 0;
2782226890Sdim  let Inst{3-0} = offset{3-0};
2783226890Sdim  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
2784204642Srdivacky}
2785204642Srdivacky
2786226890Sdimdef STRT_POST_IMM : AI2ldstidx<0, 0, 0, (outs GPR:$Rn_wb),
2787226890Sdim                   (ins GPR:$Rt, addr_offset_none:$addr, am2offset_imm:$offset),
2788226890Sdim                   IndexModePost, StFrm, IIC_iStore_ru,
2789226890Sdim                   "strt", "\t$Rt, $addr, $offset",
2790226890Sdim                   "$addr.base = $Rn_wb", []> {
2791226890Sdim  // {12}     isAdd
2792226890Sdim  // {11-0}   imm12/Rm
2793226890Sdim  bits<14> offset;
2794226890Sdim  bits<4> addr;
2795226890Sdim  let Inst{25} = 0;
2796226890Sdim  let Inst{23} = offset{12};
2797226890Sdim  let Inst{21} = 1; // overwrite
2798226890Sdim  let Inst{19-16} = addr;
2799226890Sdim  let Inst{11-0} = offset{11-0};
2800226890Sdim  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
2801226890Sdim}
2802226890Sdim}
2803226890Sdim
2804226890Sdim
2805226890Sdimmulticlass AI3strT<bits<4> op, string opc> {
2806226890Sdim  def i : AI3ldstidxT<op, 0, (outs GPR:$base_wb),
2807226890Sdim                    (ins GPR:$Rt, addr_offset_none:$addr, postidx_imm8:$offset),
2808226890Sdim                    IndexModePost, StMiscFrm, IIC_iStore_bh_ru, opc,
2809226890Sdim                    "\t$Rt, $addr, $offset", "$addr.base = $base_wb", []> {
2810226890Sdim    bits<9> offset;
2811226890Sdim    let Inst{23} = offset{8};
2812226890Sdim    let Inst{22} = 1;
2813226890Sdim    let Inst{11-8} = offset{7-4};
2814226890Sdim    let Inst{3-0} = offset{3-0};
2815226890Sdim  }
2816226890Sdim  def r : AI3ldstidxT<op, 0, (outs GPR:$base_wb),
2817226890Sdim                      (ins GPR:$Rt, addr_offset_none:$addr, postidx_reg:$Rm),
2818226890Sdim                      IndexModePost, StMiscFrm, IIC_iStore_bh_ru, opc,
2819226890Sdim                      "\t$Rt, $addr, $Rm", "$addr.base = $base_wb", []> {
2820226890Sdim    bits<5> Rm;
2821226890Sdim    let Inst{23} = Rm{4};
2822226890Sdim    let Inst{22} = 0;
2823226890Sdim    let Inst{11-8} = 0;
2824226890Sdim    let Inst{3-0} = Rm{3-0};
2825226890Sdim  }
2826226890Sdim}
2827226890Sdim
2828226890Sdim
2829226890Sdimdefm STRHT : AI3strT<0b1011, "strht">;
2830226890Sdim
2831263509Sdimdef STL : AIstrrel<0b00, (outs), (ins GPR:$Rt, addr_offset_none:$addr),
2832263509Sdim                   NoItinerary, "stl", "\t$Rt, $addr", []>;
2833263509Sdimdef STLB : AIstrrel<0b10, (outs), (ins GPR:$Rt, addr_offset_none:$addr),
2834263509Sdim                    NoItinerary, "stlb", "\t$Rt, $addr", []>;
2835263509Sdimdef STLH : AIstrrel<0b11, (outs), (ins GPR:$Rt, addr_offset_none:$addr),
2836263509Sdim                    NoItinerary, "stlh", "\t$Rt, $addr", []>;
2837226890Sdim
2838193323Sed//===----------------------------------------------------------------------===//
2839193323Sed//  Load / store multiple Instructions.
2840193323Sed//
2841193323Sed
2842235633Sdimmulticlass arm_ldst_mult<string asm, string sfx, bit L_bit, bit P_bit, Format f,
2843218893Sdim                         InstrItinClass itin, InstrItinClass itin_upd> {
2844224145Sdim  // IA is the default, so no need for an explicit suffix on the
2845245431Sdim  // mnemonic here. Without it is the canonical spelling.
2846218893Sdim  def IA :
2847218893Sdim    AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
2848218893Sdim         IndexModeNone, f, itin,
2849235633Sdim         !strconcat(asm, "${p}\t$Rn, $regs", sfx), "", []> {
2850218893Sdim    let Inst{24-23} = 0b01;       // Increment After
2851235633Sdim    let Inst{22}    = P_bit;
2852218893Sdim    let Inst{21}    = 0;          // No writeback
2853218893Sdim    let Inst{20}    = L_bit;
2854218893Sdim  }
2855218893Sdim  def IA_UPD :
2856218893Sdim    AXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
2857218893Sdim         IndexModeUpd, f, itin_upd,
2858235633Sdim         !strconcat(asm, "${p}\t$Rn!, $regs", sfx), "$Rn = $wb", []> {
2859218893Sdim    let Inst{24-23} = 0b01;       // Increment After
2860235633Sdim    let Inst{22}    = P_bit;
2861218893Sdim    let Inst{21}    = 1;          // Writeback
2862218893Sdim    let Inst{20}    = L_bit;
2863226890Sdim
2864226890Sdim    let DecoderMethod = "DecodeMemMultipleWritebackInstruction";
2865218893Sdim  }
2866218893Sdim  def DA :
2867218893Sdim    AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
2868218893Sdim         IndexModeNone, f, itin,
2869235633Sdim         !strconcat(asm, "da${p}\t$Rn, $regs", sfx), "", []> {
2870218893Sdim    let Inst{24-23} = 0b00;       // Decrement After
2871235633Sdim    let Inst{22}    = P_bit;
2872218893Sdim    let Inst{21}    = 0;          // No writeback
2873218893Sdim    let Inst{20}    = L_bit;
2874218893Sdim  }
2875218893Sdim  def DA_UPD :
2876218893Sdim    AXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
2877218893Sdim         IndexModeUpd, f, itin_upd,
2878235633Sdim         !strconcat(asm, "da${p}\t$Rn!, $regs", sfx), "$Rn = $wb", []> {
2879218893Sdim    let Inst{24-23} = 0b00;       // Decrement After
2880235633Sdim    let Inst{22}    = P_bit;
2881218893Sdim    let Inst{21}    = 1;          // Writeback
2882218893Sdim    let Inst{20}    = L_bit;
2883226890Sdim
2884226890Sdim    let DecoderMethod = "DecodeMemMultipleWritebackInstruction";
2885218893Sdim  }
2886218893Sdim  def DB :
2887218893Sdim    AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
2888218893Sdim         IndexModeNone, f, itin,
2889235633Sdim         !strconcat(asm, "db${p}\t$Rn, $regs", sfx), "", []> {
2890218893Sdim    let Inst{24-23} = 0b10;       // Decrement Before
2891235633Sdim    let Inst{22}    = P_bit;
2892218893Sdim    let Inst{21}    = 0;          // No writeback
2893218893Sdim    let Inst{20}    = L_bit;
2894218893Sdim  }
2895218893Sdim  def DB_UPD :
2896218893Sdim    AXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
2897218893Sdim         IndexModeUpd, f, itin_upd,
2898235633Sdim         !strconcat(asm, "db${p}\t$Rn!, $regs", sfx), "$Rn = $wb", []> {
2899218893Sdim    let Inst{24-23} = 0b10;       // Decrement Before
2900235633Sdim    let Inst{22}    = P_bit;
2901218893Sdim    let Inst{21}    = 1;          // Writeback
2902218893Sdim    let Inst{20}    = L_bit;
2903226890Sdim
2904226890Sdim    let DecoderMethod = "DecodeMemMultipleWritebackInstruction";
2905218893Sdim  }
2906218893Sdim  def IB :
2907218893Sdim    AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
2908218893Sdim         IndexModeNone, f, itin,
2909235633Sdim         !strconcat(asm, "ib${p}\t$Rn, $regs", sfx), "", []> {
2910218893Sdim    let Inst{24-23} = 0b11;       // Increment Before
2911235633Sdim    let Inst{22}    = P_bit;
2912218893Sdim    let Inst{21}    = 0;          // No writeback
2913218893Sdim    let Inst{20}    = L_bit;
2914218893Sdim  }
2915218893Sdim  def IB_UPD :
2916218893Sdim    AXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
2917218893Sdim         IndexModeUpd, f, itin_upd,
2918235633Sdim         !strconcat(asm, "ib${p}\t$Rn!, $regs", sfx), "$Rn = $wb", []> {
2919218893Sdim    let Inst{24-23} = 0b11;       // Increment Before
2920235633Sdim    let Inst{22}    = P_bit;
2921218893Sdim    let Inst{21}    = 1;          // Writeback
2922218893Sdim    let Inst{20}    = L_bit;
2923226890Sdim
2924226890Sdim    let DecoderMethod = "DecodeMemMultipleWritebackInstruction";
2925218893Sdim  }
2926221345Sdim}
2927193323Sed
2928218893Sdimlet neverHasSideEffects = 1 in {
2929193323Sed
2930218893Sdimlet mayLoad = 1, hasExtraDefRegAllocReq = 1 in
2931235633Sdimdefm LDM : arm_ldst_mult<"ldm", "", 1, 0, LdStMulFrm, IIC_iLoad_m,
2932235633Sdim                         IIC_iLoad_mu>;
2933205218Srdivacky
2934218893Sdimlet mayStore = 1, hasExtraSrcRegAllocReq = 1 in
2935235633Sdimdefm STM : arm_ldst_mult<"stm", "", 0, 0, LdStMulFrm, IIC_iStore_m,
2936235633Sdim                         IIC_iStore_mu>;
2937205218Srdivacky
2938218893Sdim} // neverHasSideEffects
2939218893Sdim
2940218893Sdim// FIXME: remove when we have a way to marking a MI with these properties.
2941218893Sdim// FIXME: Should pc be an implicit operand like PICADD, etc?
2942218893Sdimlet isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1,
2943218893Sdim    hasExtraDefRegAllocReq = 1, isCodeGenOnly = 1 in
2944224145Sdimdef LDMIA_RET : ARMPseudoExpand<(outs GPR:$wb), (ins GPR:$Rn, pred:$p,
2945224145Sdim                                                 reglist:$regs, variable_ops),
2946224145Sdim                     4, IIC_iLoad_mBr, [],
2947224145Sdim                     (LDMIA_UPD GPR:$wb, GPR:$Rn, pred:$p, reglist:$regs)>,
2948221345Sdim      RegConstraint<"$Rn = $wb">;
2949218893Sdim
2950235633Sdimlet mayLoad = 1, hasExtraDefRegAllocReq = 1 in
2951235633Sdimdefm sysLDM : arm_ldst_mult<"ldm", " ^", 1, 1, LdStMulFrm, IIC_iLoad_m,
2952235633Sdim                               IIC_iLoad_mu>;
2953235633Sdim
2954235633Sdimlet mayStore = 1, hasExtraSrcRegAllocReq = 1 in
2955235633Sdimdefm sysSTM : arm_ldst_mult<"stm", " ^", 0, 1, LdStMulFrm, IIC_iStore_m,
2956235633Sdim                               IIC_iStore_mu>;
2957235633Sdim
2958235633Sdim
2959235633Sdim
2960193323Sed//===----------------------------------------------------------------------===//
2961193323Sed//  Move Instructions.
2962193323Sed//
2963193323Sed
2964194178Sedlet neverHasSideEffects = 1 in
2965218893Sdimdef MOVr : AsI1<0b1101, (outs GPR:$Rd), (ins GPR:$Rm), DPFrm, IIC_iMOVr,
2966263509Sdim                "mov", "\t$Rd, $Rm", []>, UnaryDP, Sched<[WriteALU]> {
2967218893Sdim  bits<4> Rd;
2968218893Sdim  bits<4> Rm;
2969218893Sdim
2970221345Sdim  let Inst{19-16} = 0b0000;
2971199481Srdivacky  let Inst{11-4} = 0b00000000;
2972198113Srdivacky  let Inst{25} = 0;
2973218893Sdim  let Inst{3-0} = Rm;
2974218893Sdim  let Inst{15-12} = Rd;
2975198113Srdivacky}
2976198113Srdivacky
2977210299Sed// A version for the smaller set of tail call registers.
2978210299Sedlet neverHasSideEffects = 1 in
2979218893Sdimdef MOVr_TC : AsI1<0b1101, (outs tcGPR:$Rd), (ins tcGPR:$Rm), DPFrm,
2980263509Sdim                IIC_iMOVr, "mov", "\t$Rd, $Rm", []>, UnaryDP, Sched<[WriteALU]> {
2981218893Sdim  bits<4> Rd;
2982218893Sdim  bits<4> Rm;
2983218893Sdim
2984210299Sed  let Inst{11-4} = 0b00000000;
2985210299Sed  let Inst{25} = 0;
2986218893Sdim  let Inst{3-0} = Rm;
2987218893Sdim  let Inst{15-12} = Rd;
2988210299Sed}
2989210299Sed
2990226890Sdimdef MOVsr : AsI1<0b1101, (outs GPRnopc:$Rd), (ins shift_so_reg_reg:$src),
2991226890Sdim                DPSoRegRegFrm, IIC_iMOVsr,
2992226890Sdim                "mov", "\t$Rd, $src",
2993263509Sdim                [(set GPRnopc:$Rd, shift_so_reg_reg:$src)]>, UnaryDP,
2994263509Sdim                Sched<[WriteALU]> {
2995226890Sdim  bits<4> Rd;
2996226890Sdim  bits<12> src;
2997226890Sdim  let Inst{15-12} = Rd;
2998226890Sdim  let Inst{19-16} = 0b0000;
2999226890Sdim  let Inst{11-8} = src{11-8};
3000226890Sdim  let Inst{7} = 0;
3001226890Sdim  let Inst{6-5} = src{6-5};
3002226890Sdim  let Inst{4} = 1;
3003226890Sdim  let Inst{3-0} = src{3-0};
3004226890Sdim  let Inst{25} = 0;
3005226890Sdim}
3006226890Sdim
3007226890Sdimdef MOVsi : AsI1<0b1101, (outs GPR:$Rd), (ins shift_so_reg_imm:$src),
3008226890Sdim                DPSoRegImmFrm, IIC_iMOVsr,
3009226890Sdim                "mov", "\t$Rd, $src", [(set GPR:$Rd, shift_so_reg_imm:$src)]>,
3010263509Sdim                UnaryDP, Sched<[WriteALU]> {
3011218893Sdim  bits<4> Rd;
3012218893Sdim  bits<12> src;
3013218893Sdim  let Inst{15-12} = Rd;
3014221345Sdim  let Inst{19-16} = 0b0000;
3015226890Sdim  let Inst{11-5} = src{11-5};
3016226890Sdim  let Inst{4} = 0;
3017226890Sdim  let Inst{3-0} = src{3-0};
3018198113Srdivacky  let Inst{25} = 0;
3019198113Srdivacky}
3020193323Sed
3021218893Sdimlet isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in
3022218893Sdimdef MOVi : AsI1<0b1101, (outs GPR:$Rd), (ins so_imm:$imm), DPFrm, IIC_iMOVi,
3023263509Sdim                "mov", "\t$Rd, $imm", [(set GPR:$Rd, so_imm:$imm)]>, UnaryDP,
3024263509Sdim                Sched<[WriteALU]> {
3025218893Sdim  bits<4> Rd;
3026218893Sdim  bits<12> imm;
3027198090Srdivacky  let Inst{25} = 1;
3028218893Sdim  let Inst{15-12} = Rd;
3029218893Sdim  let Inst{19-16} = 0b0000;
3030218893Sdim  let Inst{11-0} = imm;
3031198090Srdivacky}
3032193323Sed
3033218893Sdimlet isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in
3034226890Sdimdef MOVi16 : AI1<0b1000, (outs GPR:$Rd), (ins imm0_65535_expr:$imm),
3035198090Srdivacky                 DPFrm, IIC_iMOVi,
3036218893Sdim                 "movw", "\t$Rd, $imm",
3037218893Sdim                 [(set GPR:$Rd, imm0_65535:$imm)]>,
3038263509Sdim                 Requires<[IsARM, HasV6T2]>, UnaryDP, Sched<[WriteALU]> {
3039218893Sdim  bits<4> Rd;
3040218893Sdim  bits<16> imm;
3041218893Sdim  let Inst{15-12} = Rd;
3042218893Sdim  let Inst{11-0}  = imm{11-0};
3043218893Sdim  let Inst{19-16} = imm{15-12};
3044198090Srdivacky  let Inst{20} = 0;
3045198090Srdivacky  let Inst{25} = 1;
3046226890Sdim  let DecoderMethod = "DecodeArmMOVTWInstruction";
3047198090Srdivacky}
3048198090Srdivacky
3049226890Sdimdef : InstAlias<"mov${p} $Rd, $imm",
3050226890Sdim                (MOVi16 GPR:$Rd, imm0_65535_expr:$imm, pred:$p)>,
3051226890Sdim        Requires<[IsARM]>;
3052226890Sdim
3053218893Sdimdef MOVi16_ga_pcrel : PseudoInst<(outs GPR:$Rd),
3054263509Sdim                                (ins i32imm:$addr, pclabel:$id), IIC_iMOVi, []>,
3055263509Sdim                      Sched<[WriteALU]>;
3056218893Sdim
3057218893Sdimlet Constraints = "$src = $Rd" in {
3058226890Sdimdef MOVTi16 : AI1<0b1010, (outs GPRnopc:$Rd),
3059226890Sdim                  (ins GPR:$src, imm0_65535_expr:$imm),
3060198090Srdivacky                  DPFrm, IIC_iMOVi,
3061218893Sdim                  "movt", "\t$Rd, $imm",
3062226890Sdim                  [(set GPRnopc:$Rd,
3063204642Srdivacky                        (or (and GPR:$src, 0xffff),
3064198090Srdivacky                            lo16AllZero:$imm))]>, UnaryDP,
3065263509Sdim                  Requires<[IsARM, HasV6T2]>, Sched<[WriteALU]> {
3066218893Sdim  bits<4> Rd;
3067218893Sdim  bits<16> imm;
3068218893Sdim  let Inst{15-12} = Rd;
3069218893Sdim  let Inst{11-0}  = imm{11-0};
3070218893Sdim  let Inst{19-16} = imm{15-12};
3071198090Srdivacky  let Inst{20} = 0;
3072198090Srdivacky  let Inst{25} = 1;
3073226890Sdim  let DecoderMethod = "DecodeArmMOVTWInstruction";
3074198090Srdivacky}
3075198090Srdivacky
3076218893Sdimdef MOVTi16_ga_pcrel : PseudoInst<(outs GPR:$Rd),
3077263509Sdim                      (ins GPR:$src, i32imm:$addr, pclabel:$id), IIC_iMOVi, []>,
3078263509Sdim                      Sched<[WriteALU]>;
3079218893Sdim
3080218893Sdim} // Constraints
3081218893Sdim
3082198396Srdivackydef : ARMPat<(or GPR:$src, 0xffff0000), (MOVTi16 GPR:$src, 0xffff)>,
3083198396Srdivacky      Requires<[IsARM, HasV6T2]>;
3084198396Srdivacky
3085198090Srdivackylet Uses = [CPSR] in
3086218893Sdimdef RRX: PseudoInst<(outs GPR:$Rd), (ins GPR:$Rm), IIC_iMOVsi,
3087218893Sdim                    [(set GPR:$Rd, (ARMrrx GPR:$Rm))]>, UnaryDP,
3088263509Sdim                    Requires<[IsARM]>, Sched<[WriteALU]>;
3089193323Sed
3090193323Sed// These aren't really mov instructions, but we have to define them this way
3091193323Sed// due to flag operands.
3092193323Sed
3093193323Sedlet Defs = [CPSR] in {
3094218893Sdimdef MOVsrl_flag : PseudoInst<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi,
3095218893Sdim                      [(set GPR:$dst, (ARMsrl_flag GPR:$src))]>, UnaryDP,
3096263509Sdim                      Sched<[WriteALU]>, Requires<[IsARM]>;
3097218893Sdimdef MOVsra_flag : PseudoInst<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi,
3098218893Sdim                      [(set GPR:$dst, (ARMsra_flag GPR:$src))]>, UnaryDP,
3099263509Sdim                      Sched<[WriteALU]>, Requires<[IsARM]>;
3100193323Sed}
3101193323Sed
3102193323Sed//===----------------------------------------------------------------------===//
3103193323Sed//  Extend Instructions.
3104193323Sed//
3105193323Sed
3106193323Sed// Sign extenders
3107193323Sed
3108226890Sdimdef SXTB  : AI_ext_rrot<0b01101010,
3109218893Sdim                         "sxtb", UnOpFrag<(sext_inreg node:$Src, i8)>>;
3110226890Sdimdef SXTH  : AI_ext_rrot<0b01101011,
3111218893Sdim                         "sxth", UnOpFrag<(sext_inreg node:$Src, i16)>>;
3112193323Sed
3113226890Sdimdef SXTAB : AI_exta_rrot<0b01101010,
3114193323Sed               "sxtab", BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS, i8))>>;
3115226890Sdimdef SXTAH : AI_exta_rrot<0b01101011,
3116193323Sed               "sxtah", BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS,i16))>>;
3117193323Sed
3118226890Sdimdef SXTB16  : AI_ext_rrot_np<0b01101000, "sxtb16">;
3119193323Sed
3120226890Sdimdef SXTAB16 : AI_exta_rrot_np<0b01101000, "sxtab16">;
3121204642Srdivacky
3122193323Sed// Zero extenders
3123193323Sed
3124193323Sedlet AddedComplexity = 16 in {
3125226890Sdimdef UXTB   : AI_ext_rrot<0b01101110,
3126218893Sdim                          "uxtb"  , UnOpFrag<(and node:$Src, 0x000000FF)>>;
3127226890Sdimdef UXTH   : AI_ext_rrot<0b01101111,
3128218893Sdim                          "uxth"  , UnOpFrag<(and node:$Src, 0x0000FFFF)>>;
3129226890Sdimdef UXTB16 : AI_ext_rrot<0b01101100,
3130218893Sdim                          "uxtb16", UnOpFrag<(and node:$Src, 0x00FF00FF)>>;
3131193323Sed
3132212904Sdim// FIXME: This pattern incorrectly assumes the shl operator is a rotate.
3133212904Sdim//        The transformation should probably be done as a combiner action
3134212904Sdim//        instead so we can include a check for masking back in the upper
3135212904Sdim//        eight bits of the source into the lower eight bits of the result.
3136212904Sdim//def : ARMV6Pat<(and (shl GPR:$Src, (i32 8)), 0xFF00FF),
3137226890Sdim//               (UXTB16r_rot GPR:$Src, 3)>;
3138194710Seddef : ARMV6Pat<(and (srl GPR:$Src, (i32 8)), 0xFF00FF),
3139226890Sdim               (UXTB16 GPR:$Src, 1)>;
3140193323Sed
3141226890Sdimdef UXTAB : AI_exta_rrot<0b01101110, "uxtab",
3142193323Sed                        BinOpFrag<(add node:$LHS, (and node:$RHS, 0x00FF))>>;
3143226890Sdimdef UXTAH : AI_exta_rrot<0b01101111, "uxtah",
3144193323Sed                        BinOpFrag<(add node:$LHS, (and node:$RHS, 0xFFFF))>>;
3145193323Sed}
3146193323Sed
3147193323Sed// This isn't safe in general, the add is two 16-bit units, not a 32-bit add.
3148226890Sdimdef UXTAB16 : AI_exta_rrot_np<0b01101100, "uxtab16">;
3149193323Sed
3150193323Sed
3151226890Sdimdef SBFX  : I<(outs GPRnopc:$Rd),
3152226890Sdim              (ins GPRnopc:$Rn, imm0_31:$lsb, imm1_32:$width),
3153224145Sdim               AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi,
3154218893Sdim               "sbfx", "\t$Rd, $Rn, $lsb, $width", "", []>,
3155198090Srdivacky               Requires<[IsARM, HasV6T2]> {
3156218893Sdim  bits<4> Rd;
3157218893Sdim  bits<4> Rn;
3158218893Sdim  bits<5> lsb;
3159218893Sdim  bits<5> width;
3160198090Srdivacky  let Inst{27-21} = 0b0111101;
3161198090Srdivacky  let Inst{6-4}   = 0b101;
3162218893Sdim  let Inst{20-16} = width;
3163218893Sdim  let Inst{15-12} = Rd;
3164218893Sdim  let Inst{11-7}  = lsb;
3165218893Sdim  let Inst{3-0}   = Rn;
3166198090Srdivacky}
3167198090Srdivacky
3168218893Sdimdef UBFX  : I<(outs GPR:$Rd),
3169226890Sdim              (ins GPR:$Rn, imm0_31:$lsb, imm1_32:$width),
3170224145Sdim               AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi,
3171218893Sdim               "ubfx", "\t$Rd, $Rn, $lsb, $width", "", []>,
3172198090Srdivacky               Requires<[IsARM, HasV6T2]> {
3173218893Sdim  bits<4> Rd;
3174218893Sdim  bits<4> Rn;
3175218893Sdim  bits<5> lsb;
3176218893Sdim  bits<5> width;
3177198090Srdivacky  let Inst{27-21} = 0b0111111;
3178198090Srdivacky  let Inst{6-4}   = 0b101;
3179218893Sdim  let Inst{20-16} = width;
3180218893Sdim  let Inst{15-12} = Rd;
3181218893Sdim  let Inst{11-7}  = lsb;
3182218893Sdim  let Inst{3-0}   = Rn;
3183198090Srdivacky}
3184198090Srdivacky
3185193323Sed//===----------------------------------------------------------------------===//
3186193323Sed//  Arithmetic Instructions.
3187193323Sed//
3188193323Sed
3189193323Seddefm ADD  : AsI1_bin_irs<0b0100, "add",
3190218893Sdim                         IIC_iALUi, IIC_iALUr, IIC_iALUsr,
3191245431Sdim                         BinOpFrag<(add  node:$LHS, node:$RHS)>, 1>;
3192193323Seddefm SUB  : AsI1_bin_irs<0b0010, "sub",
3193218893Sdim                         IIC_iALUi, IIC_iALUr, IIC_iALUsr,
3194245431Sdim                         BinOpFrag<(sub  node:$LHS, node:$RHS)>>;
3195193323Sed
3196193323Sed// ADD and SUB with 's' bit set.
3197226890Sdim//
3198235633Sdim// Currently, ADDS/SUBS are pseudo opcodes that exist only in the
3199235633Sdim// selection DAG. They are "lowered" to real ADD/SUB opcodes by
3200226890Sdim// AdjustInstrPostInstrSelection where we determine whether or not to
3201226890Sdim// set the "s" bit based on CPSR liveness.
3202226890Sdim//
3203235633Sdim// FIXME: Eliminate ADDS/SUBS pseudo opcodes after adding tablegen
3204226890Sdim// support for an optional CPSR definition that corresponds to the DAG
3205226890Sdim// node's second value. We can then eliminate the implicit def of CPSR.
3206235633Sdimdefm ADDS : AsI1_bin_s_irs<IIC_iALUi, IIC_iALUr, IIC_iALUsr,
3207235633Sdim                           BinOpFrag<(ARMaddc node:$LHS, node:$RHS)>, 1>;
3208235633Sdimdefm SUBS : AsI1_bin_s_irs<IIC_iALUi, IIC_iALUr, IIC_iALUsr,
3209235633Sdim                           BinOpFrag<(ARMsubc node:$LHS, node:$RHS)>>;
3210193323Sed
3211195098Seddefm ADC : AI1_adde_sube_irs<0b0101, "adc",
3212245431Sdim              BinOpWithFlagFrag<(ARMadde node:$LHS, node:$RHS, node:$FLAG)>, 1>;
3213195098Seddefm SBC : AI1_adde_sube_irs<0b0110, "sbc",
3214245431Sdim              BinOpWithFlagFrag<(ARMsube node:$LHS, node:$RHS, node:$FLAG)>>;
3215218893Sdim
3216245431Sdimdefm RSB  : AsI1_rbin_irs<0b0011, "rsb",
3217245431Sdim                          IIC_iALUi, IIC_iALUr, IIC_iALUsr,
3218245431Sdim                          BinOpFrag<(sub node:$LHS, node:$RHS)>>;
3219193323Sed
3220226890Sdim// FIXME: Eliminate them if we can write def : Pat patterns which defines
3221226890Sdim// CPSR and the implicit def of CPSR is not needed.
3222235633Sdimdefm RSBS : AsI1_rbin_s_is<IIC_iALUi, IIC_iALUr, IIC_iALUsr,
3223235633Sdim                           BinOpFrag<(ARMsubc node:$LHS, node:$RHS)>>;
3224193323Sed
3225226890Sdimdefm RSC : AI1_rsc_irs<0b0111, "rsc",
3226245431Sdim                BinOpWithFlagFrag<(ARMsube node:$LHS, node:$RHS, node:$FLAG)>>;
3227212904Sdim
3228193323Sed// (sub X, imm) gets canonicalized to (add X, -imm).  Match this form.
3229210299Sed// The assume-no-carry-in form uses the negation of the input since add/sub
3230210299Sed// assume opposite meanings of the carry flag (i.e., carry == !borrow).
3231210299Sed// See the definition of AddWithCarry() in the ARM ARM A2.2.1 for the gory
3232210299Sed// details.
3233226890Sdimdef : ARMPat<(add     GPR:$src, so_imm_neg:$imm),
3234226890Sdim             (SUBri   GPR:$src, so_imm_neg:$imm)>;
3235226890Sdimdef : ARMPat<(ARMaddc GPR:$src, so_imm_neg:$imm),
3236226890Sdim             (SUBSri  GPR:$src, so_imm_neg:$imm)>;
3237226890Sdim
3238245431Sdimdef : ARMPat<(add     GPR:$src, imm0_65535_neg:$imm),
3239245431Sdim             (SUBrr   GPR:$src, (MOVi16 (imm_neg_XFORM imm:$imm)))>,
3240245431Sdim             Requires<[IsARM, HasV6T2]>;
3241245431Sdimdef : ARMPat<(ARMaddc GPR:$src, imm0_65535_neg:$imm),
3242245431Sdim             (SUBSrr  GPR:$src, (MOVi16 (imm_neg_XFORM imm:$imm)))>,
3243245431Sdim             Requires<[IsARM, HasV6T2]>;
3244245431Sdim
3245210299Sed// The with-carry-in form matches bitwise not instead of the negation.
3246210299Sed// Effectively, the inverse interpretation of the carry flag already accounts
3247210299Sed// for part of the negation.
3248226890Sdimdef : ARMPat<(ARMadde GPR:$src, so_imm_not:$imm, CPSR),
3249226890Sdim             (SBCri   GPR:$src, so_imm_not:$imm)>;
3250245431Sdimdef : ARMPat<(ARMadde GPR:$src, imm0_65535_neg:$imm, CPSR),
3251245431Sdim             (SBCrr   GPR:$src, (MOVi16 (imm_not_XFORM imm:$imm)))>;
3252193323Sed
3253193323Sed// Note: These are implemented in C++ code, because they have to generate
3254193323Sed// ADD/SUBrs instructions, which use a complex pattern that a xform function
3255193323Sed// cannot produce.
3256193323Sed// (mul X, 2^n+1) -> (add (X << n), X)
3257193323Sed// (mul X, 2^n-1) -> (rsb X, (X << n))
3258193323Sed
3259226890Sdim// ARM Arithmetic Instruction
3260203954Srdivacky// GPR:$dst = GPR:$a op GPR:$b
3261218893Sdimclass AAI<bits<8> op27_20, bits<8> op11_4, string opc,
3262226890Sdim          list<dag> pattern = [],
3263226890Sdim          dag iops = (ins GPRnopc:$Rn, GPRnopc:$Rm),
3264226890Sdim          string asm = "\t$Rd, $Rn, $Rm">
3265263509Sdim  : AI<(outs GPRnopc:$Rd), iops, DPFrm, IIC_iALUr, opc, asm, pattern>,
3266263509Sdim    Sched<[WriteALU, ReadALU, ReadALU]> {
3267218893Sdim  bits<4> Rn;
3268218893Sdim  bits<4> Rd;
3269218893Sdim  bits<4> Rm;
3270203954Srdivacky  let Inst{27-20} = op27_20;
3271218893Sdim  let Inst{11-4} = op11_4;
3272218893Sdim  let Inst{19-16} = Rn;
3273218893Sdim  let Inst{15-12} = Rd;
3274218893Sdim  let Inst{3-0}   = Rm;
3275245431Sdim
3276235633Sdim  let Unpredictable{11-8} = 0b1111;
3277203954Srdivacky}
3278203954Srdivacky
3279226890Sdim// Saturating add/subtract
3280203954Srdivacky
3281263509Sdimlet DecoderMethod = "DecodeQADDInstruction" in
3282218893Sdimdef QADD    : AAI<0b00010000, 0b00000101, "qadd",
3283226890Sdim                  [(set GPRnopc:$Rd, (int_arm_qadd GPRnopc:$Rm, GPRnopc:$Rn))],
3284226890Sdim                  (ins GPRnopc:$Rm, GPRnopc:$Rn), "\t$Rd, $Rm, $Rn">;
3285263509Sdim
3286218893Sdimdef QSUB    : AAI<0b00010010, 0b00000101, "qsub",
3287226890Sdim                  [(set GPRnopc:$Rd, (int_arm_qsub GPRnopc:$Rm, GPRnopc:$Rn))],
3288226890Sdim                  (ins GPRnopc:$Rm, GPRnopc:$Rn), "\t$Rd, $Rm, $Rn">;
3289226890Sdimdef QDADD   : AAI<0b00010100, 0b00000101, "qdadd", [],
3290226890Sdim                  (ins GPRnopc:$Rm, GPRnopc:$Rn),
3291218893Sdim                  "\t$Rd, $Rm, $Rn">;
3292226890Sdimdef QDSUB   : AAI<0b00010110, 0b00000101, "qdsub", [],
3293226890Sdim                  (ins GPRnopc:$Rm, GPRnopc:$Rn),
3294218893Sdim                  "\t$Rd, $Rm, $Rn">;
3295204642Srdivacky
3296218893Sdimdef QADD16  : AAI<0b01100010, 0b11110001, "qadd16">;
3297218893Sdimdef QADD8   : AAI<0b01100010, 0b11111001, "qadd8">;
3298218893Sdimdef QASX    : AAI<0b01100010, 0b11110011, "qasx">;
3299218893Sdimdef QSAX    : AAI<0b01100010, 0b11110101, "qsax">;
3300218893Sdimdef QSUB16  : AAI<0b01100010, 0b11110111, "qsub16">;
3301218893Sdimdef QSUB8   : AAI<0b01100010, 0b11111111, "qsub8">;
3302218893Sdimdef UQADD16 : AAI<0b01100110, 0b11110001, "uqadd16">;
3303218893Sdimdef UQADD8  : AAI<0b01100110, 0b11111001, "uqadd8">;
3304218893Sdimdef UQASX   : AAI<0b01100110, 0b11110011, "uqasx">;
3305218893Sdimdef UQSAX   : AAI<0b01100110, 0b11110101, "uqsax">;
3306218893Sdimdef UQSUB16 : AAI<0b01100110, 0b11110111, "uqsub16">;
3307218893Sdimdef UQSUB8  : AAI<0b01100110, 0b11111111, "uqsub8">;
3308218893Sdim
3309226890Sdim// Signed/Unsigned add/subtract
3310204642Srdivacky
3311218893Sdimdef SASX   : AAI<0b01100001, 0b11110011, "sasx">;
3312218893Sdimdef SADD16 : AAI<0b01100001, 0b11110001, "sadd16">;
3313218893Sdimdef SADD8  : AAI<0b01100001, 0b11111001, "sadd8">;
3314218893Sdimdef SSAX   : AAI<0b01100001, 0b11110101, "ssax">;
3315218893Sdimdef SSUB16 : AAI<0b01100001, 0b11110111, "ssub16">;
3316218893Sdimdef SSUB8  : AAI<0b01100001, 0b11111111, "ssub8">;
3317218893Sdimdef UASX   : AAI<0b01100101, 0b11110011, "uasx">;
3318218893Sdimdef UADD16 : AAI<0b01100101, 0b11110001, "uadd16">;
3319218893Sdimdef UADD8  : AAI<0b01100101, 0b11111001, "uadd8">;
3320218893Sdimdef USAX   : AAI<0b01100101, 0b11110101, "usax">;
3321218893Sdimdef USUB16 : AAI<0b01100101, 0b11110111, "usub16">;
3322218893Sdimdef USUB8  : AAI<0b01100101, 0b11111111, "usub8">;
3323204642Srdivacky
3324226890Sdim// Signed/Unsigned halving add/subtract
3325204642Srdivacky
3326218893Sdimdef SHASX   : AAI<0b01100011, 0b11110011, "shasx">;
3327218893Sdimdef SHADD16 : AAI<0b01100011, 0b11110001, "shadd16">;
3328218893Sdimdef SHADD8  : AAI<0b01100011, 0b11111001, "shadd8">;
3329218893Sdimdef SHSAX   : AAI<0b01100011, 0b11110101, "shsax">;
3330218893Sdimdef SHSUB16 : AAI<0b01100011, 0b11110111, "shsub16">;
3331218893Sdimdef SHSUB8  : AAI<0b01100011, 0b11111111, "shsub8">;
3332218893Sdimdef UHASX   : AAI<0b01100111, 0b11110011, "uhasx">;
3333218893Sdimdef UHADD16 : AAI<0b01100111, 0b11110001, "uhadd16">;
3334218893Sdimdef UHADD8  : AAI<0b01100111, 0b11111001, "uhadd8">;
3335218893Sdimdef UHSAX   : AAI<0b01100111, 0b11110101, "uhsax">;
3336218893Sdimdef UHSUB16 : AAI<0b01100111, 0b11110111, "uhsub16">;
3337218893Sdimdef UHSUB8  : AAI<0b01100111, 0b11111111, "uhsub8">;
3338204642Srdivacky
3339226890Sdim// Unsigned Sum of Absolute Differences [and Accumulate].
3340204642Srdivacky
3341218893Sdimdef USAD8  : AI<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
3342204642Srdivacky                MulFrm /* for convenience */, NoItinerary, "usad8",
3343218893Sdim                "\t$Rd, $Rn, $Rm", []>,
3344263509Sdim             Requires<[IsARM, HasV6]>, Sched<[WriteALU, ReadALU, ReadALU]> {
3345218893Sdim  bits<4> Rd;
3346218893Sdim  bits<4> Rn;
3347218893Sdim  bits<4> Rm;
3348204642Srdivacky  let Inst{27-20} = 0b01111000;
3349204642Srdivacky  let Inst{15-12} = 0b1111;
3350204642Srdivacky  let Inst{7-4} = 0b0001;
3351218893Sdim  let Inst{19-16} = Rd;
3352218893Sdim  let Inst{11-8} = Rm;
3353218893Sdim  let Inst{3-0} = Rn;
3354204642Srdivacky}
3355218893Sdimdef USADA8 : AI<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
3356204642Srdivacky                MulFrm /* for convenience */, NoItinerary, "usada8",
3357218893Sdim                "\t$Rd, $Rn, $Rm, $Ra", []>,
3358263509Sdim             Requires<[IsARM, HasV6]>, Sched<[WriteALU, ReadALU, ReadALU]>{
3359218893Sdim  bits<4> Rd;
3360218893Sdim  bits<4> Rn;
3361218893Sdim  bits<4> Rm;
3362218893Sdim  bits<4> Ra;
3363204642Srdivacky  let Inst{27-20} = 0b01111000;
3364204642Srdivacky  let Inst{7-4} = 0b0001;
3365218893Sdim  let Inst{19-16} = Rd;
3366218893Sdim  let Inst{15-12} = Ra;
3367218893Sdim  let Inst{11-8} = Rm;
3368218893Sdim  let Inst{3-0} = Rn;
3369204642Srdivacky}
3370204642Srdivacky
3371226890Sdim// Signed/Unsigned saturate
3372204642Srdivacky
3373226890Sdimdef SSAT : AI<(outs GPRnopc:$Rd),
3374226890Sdim              (ins imm1_32:$sat_imm, GPRnopc:$Rn, shift_imm:$sh),
3375226890Sdim              SatFrm, NoItinerary, "ssat", "\t$Rd, $sat_imm, $Rn$sh", []> {
3376218893Sdim  bits<4> Rd;
3377218893Sdim  bits<5> sat_imm;
3378218893Sdim  bits<4> Rn;
3379218893Sdim  bits<8> sh;
3380204642Srdivacky  let Inst{27-21} = 0b0110101;
3381212904Sdim  let Inst{5-4} = 0b01;
3382218893Sdim  let Inst{20-16} = sat_imm;
3383218893Sdim  let Inst{15-12} = Rd;
3384226890Sdim  let Inst{11-7} = sh{4-0};
3385226890Sdim  let Inst{6} = sh{5};
3386218893Sdim  let Inst{3-0} = Rn;
3387204642Srdivacky}
3388204642Srdivacky
3389226890Sdimdef SSAT16 : AI<(outs GPRnopc:$Rd),
3390226890Sdim                (ins imm1_16:$sat_imm, GPRnopc:$Rn), SatFrm,
3391226890Sdim                NoItinerary, "ssat16", "\t$Rd, $sat_imm, $Rn", []> {
3392218893Sdim  bits<4> Rd;
3393218893Sdim  bits<4> sat_imm;
3394218893Sdim  bits<4> Rn;
3395204642Srdivacky  let Inst{27-20} = 0b01101010;
3396218893Sdim  let Inst{11-4} = 0b11110011;
3397218893Sdim  let Inst{15-12} = Rd;
3398218893Sdim  let Inst{19-16} = sat_imm;
3399218893Sdim  let Inst{3-0} = Rn;
3400204642Srdivacky}
3401204642Srdivacky
3402226890Sdimdef USAT : AI<(outs GPRnopc:$Rd),
3403226890Sdim              (ins imm0_31:$sat_imm, GPRnopc:$Rn, shift_imm:$sh),
3404226890Sdim              SatFrm, NoItinerary, "usat", "\t$Rd, $sat_imm, $Rn$sh", []> {
3405218893Sdim  bits<4> Rd;
3406218893Sdim  bits<5> sat_imm;
3407218893Sdim  bits<4> Rn;
3408218893Sdim  bits<8> sh;
3409204642Srdivacky  let Inst{27-21} = 0b0110111;
3410212904Sdim  let Inst{5-4} = 0b01;
3411218893Sdim  let Inst{15-12} = Rd;
3412226890Sdim  let Inst{11-7} = sh{4-0};
3413226890Sdim  let Inst{6} = sh{5};
3414218893Sdim  let Inst{20-16} = sat_imm;
3415218893Sdim  let Inst{3-0} = Rn;
3416204642Srdivacky}
3417204642Srdivacky
3418226890Sdimdef USAT16 : AI<(outs GPRnopc:$Rd),
3419226890Sdim                (ins imm0_15:$sat_imm, GPRnopc:$Rn), SatFrm,
3420226890Sdim                NoItinerary, "usat16", "\t$Rd, $sat_imm, $Rn", []> {
3421218893Sdim  bits<4> Rd;
3422218893Sdim  bits<4> sat_imm;
3423218893Sdim  bits<4> Rn;
3424204642Srdivacky  let Inst{27-20} = 0b01101110;
3425218893Sdim  let Inst{11-4} = 0b11110011;
3426218893Sdim  let Inst{15-12} = Rd;
3427218893Sdim  let Inst{19-16} = sat_imm;
3428218893Sdim  let Inst{3-0} = Rn;
3429204642Srdivacky}
3430204642Srdivacky
3431226890Sdimdef : ARMV6Pat<(int_arm_ssat GPRnopc:$a, imm:$pos),
3432226890Sdim               (SSAT imm:$pos, GPRnopc:$a, 0)>;
3433226890Sdimdef : ARMV6Pat<(int_arm_usat GPRnopc:$a, imm:$pos),
3434226890Sdim               (USAT imm:$pos, GPRnopc:$a, 0)>;
3435212904Sdim
3436193323Sed//===----------------------------------------------------------------------===//
3437193323Sed//  Bitwise Instructions.
3438193323Sed//
3439193323Sed
3440193323Seddefm AND   : AsI1_bin_irs<0b0000, "and",
3441218893Sdim                          IIC_iBITi, IIC_iBITr, IIC_iBITsr,
3442245431Sdim                          BinOpFrag<(and node:$LHS, node:$RHS)>, 1>;
3443193323Seddefm ORR   : AsI1_bin_irs<0b1100, "orr",
3444218893Sdim                          IIC_iBITi, IIC_iBITr, IIC_iBITsr,
3445245431Sdim                          BinOpFrag<(or  node:$LHS, node:$RHS)>, 1>;
3446193323Seddefm EOR   : AsI1_bin_irs<0b0001, "eor",
3447218893Sdim                          IIC_iBITi, IIC_iBITr, IIC_iBITsr,
3448245431Sdim                          BinOpFrag<(xor node:$LHS, node:$RHS)>, 1>;
3449193323Seddefm BIC   : AsI1_bin_irs<0b1110, "bic",
3450218893Sdim                          IIC_iBITi, IIC_iBITr, IIC_iBITsr,
3451245431Sdim                          BinOpFrag<(and node:$LHS, (not node:$RHS))>>;
3452193323Sed
3453226890Sdim// FIXME: bf_inv_mask_imm should be two operands, the lsb and the msb, just
3454226890Sdim// like in the actual instruction encoding. The complexity of mapping the mask
3455226890Sdim// to the lsb/msb pair should be handled by ISel, not encapsulated in the
3456226890Sdim// instruction description.
3457218893Sdimdef BFC    : I<(outs GPR:$Rd), (ins GPR:$src, bf_inv_mask_imm:$imm),
3458224145Sdim               AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi,
3459218893Sdim               "bfc", "\t$Rd, $imm", "$src = $Rd",
3460218893Sdim               [(set GPR:$Rd, (and GPR:$src, bf_inv_mask_imm:$imm))]>,
3461198090Srdivacky               Requires<[IsARM, HasV6T2]> {
3462218893Sdim  bits<4> Rd;
3463218893Sdim  bits<10> imm;
3464198090Srdivacky  let Inst{27-21} = 0b0111110;
3465198090Srdivacky  let Inst{6-0}   = 0b0011111;
3466218893Sdim  let Inst{15-12} = Rd;
3467218893Sdim  let Inst{11-7}  = imm{4-0}; // lsb
3468226890Sdim  let Inst{20-16} = imm{9-5}; // msb
3469198090Srdivacky}
3470198090Srdivacky
3471204642Srdivacky// A8.6.18  BFI - Bitfield insert (Encoding A1)
3472226890Sdimdef BFI:I<(outs GPRnopc:$Rd), (ins GPRnopc:$src, GPR:$Rn, bf_inv_mask_imm:$imm),
3473226890Sdim          AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi,
3474226890Sdim          "bfi", "\t$Rd, $Rn, $imm", "$src = $Rd",
3475226890Sdim          [(set GPRnopc:$Rd, (ARMbfi GPRnopc:$src, GPR:$Rn,
3476226890Sdim                           bf_inv_mask_imm:$imm))]>,
3477226890Sdim          Requires<[IsARM, HasV6T2]> {
3478218893Sdim  bits<4> Rd;
3479218893Sdim  bits<4> Rn;
3480218893Sdim  bits<10> imm;
3481204642Srdivacky  let Inst{27-21} = 0b0111110;
3482204642Srdivacky  let Inst{6-4}   = 0b001; // Rn: Inst{3-0} != 15
3483218893Sdim  let Inst{15-12} = Rd;
3484218893Sdim  let Inst{11-7}  = imm{4-0}; // lsb
3485218893Sdim  let Inst{20-16} = imm{9-5}; // width
3486218893Sdim  let Inst{3-0}   = Rn;
3487204642Srdivacky}
3488204642Srdivacky
3489218893Sdimdef  MVNr  : AsI1<0b1111, (outs GPR:$Rd), (ins GPR:$Rm), DPFrm, IIC_iMVNr,
3490218893Sdim                  "mvn", "\t$Rd, $Rm",
3491263509Sdim                  [(set GPR:$Rd, (not GPR:$Rm))]>, UnaryDP, Sched<[WriteALU]> {
3492218893Sdim  bits<4> Rd;
3493218893Sdim  bits<4> Rm;
3494203954Srdivacky  let Inst{25} = 0;
3495218893Sdim  let Inst{19-16} = 0b0000;
3496199481Srdivacky  let Inst{11-4} = 0b00000000;
3497218893Sdim  let Inst{15-12} = Rd;
3498218893Sdim  let Inst{3-0} = Rm;
3499198113Srdivacky}
3500226890Sdimdef  MVNsi  : AsI1<0b1111, (outs GPR:$Rd), (ins so_reg_imm:$shift),
3501226890Sdim                  DPSoRegImmFrm, IIC_iMVNsr, "mvn", "\t$Rd, $shift",
3502263509Sdim                  [(set GPR:$Rd, (not so_reg_imm:$shift))]>, UnaryDP,
3503263509Sdim                  Sched<[WriteALU]> {
3504218893Sdim  bits<4> Rd;
3505218893Sdim  bits<12> shift;
3506203954Srdivacky  let Inst{25} = 0;
3507218893Sdim  let Inst{19-16} = 0b0000;
3508218893Sdim  let Inst{15-12} = Rd;
3509226890Sdim  let Inst{11-5} = shift{11-5};
3510226890Sdim  let Inst{4} = 0;
3511226890Sdim  let Inst{3-0} = shift{3-0};
3512203954Srdivacky}
3513226890Sdimdef  MVNsr  : AsI1<0b1111, (outs GPR:$Rd), (ins so_reg_reg:$shift),
3514226890Sdim                  DPSoRegRegFrm, IIC_iMVNsr, "mvn", "\t$Rd, $shift",
3515263509Sdim                  [(set GPR:$Rd, (not so_reg_reg:$shift))]>, UnaryDP,
3516263509Sdim                  Sched<[WriteALU]> {
3517226890Sdim  bits<4> Rd;
3518226890Sdim  bits<12> shift;
3519226890Sdim  let Inst{25} = 0;
3520226890Sdim  let Inst{19-16} = 0b0000;
3521226890Sdim  let Inst{15-12} = Rd;
3522226890Sdim  let Inst{11-8} = shift{11-8};
3523226890Sdim  let Inst{7} = 0;
3524226890Sdim  let Inst{6-5} = shift{6-5};
3525226890Sdim  let Inst{4} = 1;
3526226890Sdim  let Inst{3-0} = shift{3-0};
3527226890Sdim}
3528218893Sdimlet isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in
3529218893Sdimdef  MVNi  : AsI1<0b1111, (outs GPR:$Rd), (ins so_imm:$imm), DPFrm,
3530218893Sdim                  IIC_iMVNi, "mvn", "\t$Rd, $imm",
3531263509Sdim                  [(set GPR:$Rd, so_imm_not:$imm)]>,UnaryDP, Sched<[WriteALU]> {
3532218893Sdim  bits<4> Rd;
3533218893Sdim  bits<12> imm;
3534218893Sdim  let Inst{25} = 1;
3535218893Sdim  let Inst{19-16} = 0b0000;
3536218893Sdim  let Inst{15-12} = Rd;
3537218893Sdim  let Inst{11-0} = imm;
3538198090Srdivacky}
3539193323Sed
3540193323Seddef : ARMPat<(and   GPR:$src, so_imm_not:$imm),
3541193323Sed             (BICri GPR:$src, so_imm_not:$imm)>;
3542193323Sed
3543193323Sed//===----------------------------------------------------------------------===//
3544193323Sed//  Multiply Instructions.
3545193323Sed//
3546218893Sdimclass AsMul1I32<bits<7> opcod, dag oops, dag iops, InstrItinClass itin,
3547218893Sdim             string opc, string asm, list<dag> pattern>
3548218893Sdim  : AsMul1I<opcod, oops, iops, itin, opc, asm, pattern> {
3549218893Sdim  bits<4> Rd;
3550218893Sdim  bits<4> Rm;
3551218893Sdim  bits<4> Rn;
3552218893Sdim  let Inst{19-16} = Rd;
3553218893Sdim  let Inst{11-8}  = Rm;
3554218893Sdim  let Inst{3-0}   = Rn;
3555218893Sdim}
3556218893Sdimclass AsMul1I64<bits<7> opcod, dag oops, dag iops, InstrItinClass itin,
3557218893Sdim             string opc, string asm, list<dag> pattern>
3558218893Sdim  : AsMul1I<opcod, oops, iops, itin, opc, asm, pattern> {
3559218893Sdim  bits<4> RdLo;
3560218893Sdim  bits<4> RdHi;
3561218893Sdim  bits<4> Rm;
3562218893Sdim  bits<4> Rn;
3563218893Sdim  let Inst{19-16} = RdHi;
3564218893Sdim  let Inst{15-12} = RdLo;
3565218893Sdim  let Inst{11-8}  = Rm;
3566218893Sdim  let Inst{3-0}   = Rn;
3567218893Sdim}
3568245431Sdimclass AsMla1I64<bits<7> opcod, dag oops, dag iops, InstrItinClass itin,
3569245431Sdim             string opc, string asm, list<dag> pattern>
3570245431Sdim  : AsMul1I<opcod, oops, iops, itin, opc, asm, pattern> {
3571245431Sdim  bits<4> RdLo;
3572245431Sdim  bits<4> RdHi;
3573245431Sdim  bits<4> Rm;
3574245431Sdim  bits<4> Rn;
3575245431Sdim  let Inst{19-16} = RdHi;
3576245431Sdim  let Inst{15-12} = RdLo;
3577245431Sdim  let Inst{11-8}  = Rm;
3578245431Sdim  let Inst{3-0}   = Rn;
3579245431Sdim}
3580193323Sed
3581224145Sdim// FIXME: The v5 pseudos are only necessary for the additional Constraint
3582224145Sdim//        property. Remove them when it's possible to add those properties
3583245431Sdim//        on an individual MachineInstr, not just an instruction description.
3584245431Sdimlet isCommutable = 1, TwoOperandAliasConstraint = "$Rn = $Rd" in {
3585245431Sdimdef MUL : AsMul1I32<0b0000000, (outs GPRnopc:$Rd),
3586245431Sdim                    (ins GPRnopc:$Rn, GPRnopc:$Rm),
3587245431Sdim                    IIC_iMUL32, "mul", "\t$Rd, $Rn, $Rm",
3588245431Sdim                  [(set GPRnopc:$Rd, (mul GPRnopc:$Rn, GPRnopc:$Rm))]>,
3589245431Sdim                  Requires<[IsARM, HasV6]> {
3590221345Sdim  let Inst{15-12} = 0b0000;
3591235633Sdim  let Unpredictable{15-12} = 0b1111;
3592218893Sdim}
3593193323Sed
3594218893Sdimlet Constraints = "@earlyclobber $Rd" in
3595235633Sdimdef MULv5: ARMPseudoExpand<(outs GPRnopc:$Rd), (ins GPRnopc:$Rn, GPRnopc:$Rm,
3596245431Sdim                                                    pred:$p, cc_out:$s),
3597245431Sdim                           4, IIC_iMUL32,
3598245431Sdim               [(set GPRnopc:$Rd, (mul GPRnopc:$Rn, GPRnopc:$Rm))],
3599245431Sdim               (MUL GPRnopc:$Rd, GPRnopc:$Rn, GPRnopc:$Rm, pred:$p, cc_out:$s)>,
3600245431Sdim               Requires<[IsARM, NoV6, UseMulOps]>;
3601218893Sdim}
3602224145Sdim
3603218893Sdimdef MLA  : AsMul1I32<0b0000001, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
3604245431Sdim                     IIC_iMAC32, "mla", "\t$Rd, $Rn, $Rm, $Ra",
3605218893Sdim                   [(set GPR:$Rd, (add (mul GPR:$Rn, GPR:$Rm), GPR:$Ra))]>,
3606245431Sdim                   Requires<[IsARM, HasV6, UseMulOps]> {
3607218893Sdim  bits<4> Ra;
3608218893Sdim  let Inst{15-12} = Ra;
3609218893Sdim}
3610198090Srdivacky
3611224145Sdimlet Constraints = "@earlyclobber $Rd" in
3612224145Sdimdef MLAv5: ARMPseudoExpand<(outs GPR:$Rd),
3613245431Sdim                           (ins GPR:$Rn, GPR:$Rm, GPR:$Ra, pred:$p, cc_out:$s),
3614245431Sdim                           4, IIC_iMAC32,
3615224145Sdim                        [(set GPR:$Rd, (add (mul GPR:$Rn, GPR:$Rm), GPR:$Ra))],
3616224145Sdim                  (MLA GPR:$Rd, GPR:$Rn, GPR:$Rm, GPR:$Ra, pred:$p, cc_out:$s)>,
3617224145Sdim                        Requires<[IsARM, NoV6]>;
3618224145Sdim
3619218893Sdimdef MLS  : AMul1I<0b0000011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
3620218893Sdim                   IIC_iMAC32, "mls", "\t$Rd, $Rn, $Rm, $Ra",
3621218893Sdim                   [(set GPR:$Rd, (sub GPR:$Ra, (mul GPR:$Rn, GPR:$Rm)))]>,
3622245431Sdim                   Requires<[IsARM, HasV6T2, UseMulOps]> {
3623218893Sdim  bits<4> Rd;
3624218893Sdim  bits<4> Rm;
3625218893Sdim  bits<4> Rn;
3626218893Sdim  bits<4> Ra;
3627218893Sdim  let Inst{19-16} = Rd;
3628218893Sdim  let Inst{15-12} = Ra;
3629218893Sdim  let Inst{11-8}  = Rm;
3630218893Sdim  let Inst{3-0}   = Rn;
3631218893Sdim}
3632218893Sdim
3633193323Sed// Extra precision multiplies with low / high results
3634194178Sedlet neverHasSideEffects = 1 in {
3635195098Sedlet isCommutable = 1 in {
3636218893Sdimdef SMULL : AsMul1I64<0b0000110, (outs GPR:$RdLo, GPR:$RdHi),
3637224145Sdim                                 (ins GPR:$Rn, GPR:$Rm), IIC_iMUL64,
3638218893Sdim                    "smull", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
3639218893Sdim                    Requires<[IsARM, HasV6]>;
3640218893Sdim
3641218893Sdimdef UMULL : AsMul1I64<0b0000100, (outs GPR:$RdLo, GPR:$RdHi),
3642224145Sdim                                 (ins GPR:$Rn, GPR:$Rm), IIC_iMUL64,
3643218893Sdim                    "umull", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
3644218893Sdim                    Requires<[IsARM, HasV6]>;
3645218893Sdim
3646218893Sdimlet Constraints = "@earlyclobber $RdLo,@earlyclobber $RdHi" in {
3647224145Sdimdef SMULLv5 : ARMPseudoExpand<(outs GPR:$RdLo, GPR:$RdHi),
3648221345Sdim                            (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s),
3649224145Sdim                            4, IIC_iMUL64, [],
3650224145Sdim          (SMULL GPR:$RdLo, GPR:$RdHi, GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s)>,
3651218893Sdim                           Requires<[IsARM, NoV6]>;
3652224145Sdim
3653224145Sdimdef UMULLv5 : ARMPseudoExpand<(outs GPR:$RdLo, GPR:$RdHi),
3654221345Sdim                            (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s),
3655224145Sdim                            4, IIC_iMUL64, [],
3656224145Sdim          (UMULL GPR:$RdLo, GPR:$RdHi, GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s)>,
3657218893Sdim                           Requires<[IsARM, NoV6]>;
3658218893Sdim}
3659224145Sdim}
3660193323Sed
3661224145Sdim// Multiply + accumulate
3662245431Sdimdef SMLAL : AsMla1I64<0b0000111, (outs GPR:$RdLo, GPR:$RdHi),
3663245431Sdim                        (ins GPR:$Rn, GPR:$Rm, GPR:$RLo, GPR:$RHi), IIC_iMAC64,
3664218893Sdim                    "smlal", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
3665245431Sdim         RegConstraint<"$RLo = $RdLo, $RHi = $RdHi">, Requires<[IsARM, HasV6]>;
3666245431Sdimdef UMLAL : AsMla1I64<0b0000101, (outs GPR:$RdLo, GPR:$RdHi),
3667245431Sdim                        (ins GPR:$Rn, GPR:$Rm, GPR:$RLo, GPR:$RHi), IIC_iMAC64,
3668218893Sdim                    "umlal", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
3669245431Sdim         RegConstraint<"$RLo = $RdLo, $RHi = $RdHi">, Requires<[IsARM, HasV6]>;
3670218893Sdim
3671218893Sdimdef UMAAL : AMul1I <0b0000010, (outs GPR:$RdLo, GPR:$RdHi),
3672218893Sdim                               (ins GPR:$Rn, GPR:$Rm), IIC_iMAC64,
3673218893Sdim                    "umaal", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
3674218893Sdim                    Requires<[IsARM, HasV6]> {
3675218893Sdim  bits<4> RdLo;
3676218893Sdim  bits<4> RdHi;
3677218893Sdim  bits<4> Rm;
3678218893Sdim  bits<4> Rn;
3679226890Sdim  let Inst{19-16} = RdHi;
3680226890Sdim  let Inst{15-12} = RdLo;
3681218893Sdim  let Inst{11-8}  = Rm;
3682218893Sdim  let Inst{3-0}   = Rn;
3683218893Sdim}
3684224145Sdim
3685245431Sdimlet Constraints = "$RLo = $RdLo,$RHi = $RdHi" in {
3686224145Sdimdef SMLALv5 : ARMPseudoExpand<(outs GPR:$RdLo, GPR:$RdHi),
3687245431Sdim                (ins GPR:$Rn, GPR:$Rm, GPR:$RLo, GPR:$RHi, pred:$p, cc_out:$s),
3688224145Sdim                              4, IIC_iMAC64, [],
3689245431Sdim             (SMLAL GPR:$RdLo, GPR:$RdHi, GPR:$Rn, GPR:$Rm, GPR:$RLo, GPR:$RHi,
3690245431Sdim                           pred:$p, cc_out:$s)>,
3691224145Sdim                           Requires<[IsARM, NoV6]>;
3692224145Sdimdef UMLALv5 : ARMPseudoExpand<(outs GPR:$RdLo, GPR:$RdHi),
3693245431Sdim                (ins GPR:$Rn, GPR:$Rm, GPR:$RLo, GPR:$RHi, pred:$p, cc_out:$s),
3694224145Sdim                              4, IIC_iMAC64, [],
3695245431Sdim             (UMLAL GPR:$RdLo, GPR:$RdHi, GPR:$Rn, GPR:$Rm, GPR:$RLo, GPR:$RHi,
3696245431Sdim                           pred:$p, cc_out:$s)>,
3697224145Sdim                           Requires<[IsARM, NoV6]>;
3698245431Sdim}
3699245431Sdim
3700245431Sdimlet Constraints = "@earlyclobber $RdLo,@earlyclobber $RdHi" in {
3701224145Sdimdef UMAALv5 : ARMPseudoExpand<(outs GPR:$RdLo, GPR:$RdHi),
3702224145Sdim                              (ins GPR:$Rn, GPR:$Rm, pred:$p),
3703224145Sdim                              4, IIC_iMAC64, [],
3704224145Sdim          (UMAAL GPR:$RdLo, GPR:$RdHi, GPR:$Rn, GPR:$Rm, pred:$p)>,
3705224145Sdim                           Requires<[IsARM, NoV6]>;
3706224145Sdim}
3707224145Sdim
3708194178Sed} // neverHasSideEffects
3709193323Sed
3710193323Sed// Most significant word multiply
3711218893Sdimdef SMMUL : AMul2I <0b0111010, 0b0001, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
3712218893Sdim               IIC_iMUL32, "smmul", "\t$Rd, $Rn, $Rm",
3713218893Sdim               [(set GPR:$Rd, (mulhs GPR:$Rn, GPR:$Rm))]>,
3714193323Sed            Requires<[IsARM, HasV6]> {
3715193323Sed  let Inst{15-12} = 0b1111;
3716193323Sed}
3717193323Sed
3718218893Sdimdef SMMULR : AMul2I <0b0111010, 0b0011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
3719226890Sdim               IIC_iMUL32, "smmulr", "\t$Rd, $Rn, $Rm", []>,
3720204642Srdivacky            Requires<[IsARM, HasV6]> {
3721204642Srdivacky  let Inst{15-12} = 0b1111;
3722204642Srdivacky}
3723204642Srdivacky
3724218893Sdimdef SMMLA : AMul2Ia <0b0111010, 0b0001, (outs GPR:$Rd),
3725218893Sdim               (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
3726218893Sdim               IIC_iMAC32, "smmla", "\t$Rd, $Rn, $Rm, $Ra",
3727218893Sdim               [(set GPR:$Rd, (add (mulhs GPR:$Rn, GPR:$Rm), GPR:$Ra))]>,
3728245431Sdim            Requires<[IsARM, HasV6, UseMulOps]>;
3729193323Sed
3730218893Sdimdef SMMLAR : AMul2Ia <0b0111010, 0b0011, (outs GPR:$Rd),
3731218893Sdim               (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
3732226890Sdim               IIC_iMAC32, "smmlar", "\t$Rd, $Rn, $Rm, $Ra", []>,
3733218893Sdim            Requires<[IsARM, HasV6]>;
3734193323Sed
3735218893Sdimdef SMMLS : AMul2Ia <0b0111010, 0b1101, (outs GPR:$Rd),
3736218893Sdim               (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
3737245431Sdim               IIC_iMAC32, "smmls", "\t$Rd, $Rn, $Rm, $Ra", []>,
3738245431Sdim            Requires<[IsARM, HasV6, UseMulOps]>;
3739193323Sed
3740218893Sdimdef SMMLSR : AMul2Ia <0b0111010, 0b1111, (outs GPR:$Rd),
3741218893Sdim               (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
3742226890Sdim               IIC_iMAC32, "smmlsr", "\t$Rd, $Rn, $Rm, $Ra", []>,
3743218893Sdim            Requires<[IsARM, HasV6]>;
3744204642Srdivacky
3745193323Sedmulticlass AI_smul<string opc, PatFrag opnode> {
3746218893Sdim  def BB : AMulxyI<0b0001011, 0b00, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
3747218893Sdim              IIC_iMUL16, !strconcat(opc, "bb"), "\t$Rd, $Rn, $Rm",
3748218893Sdim              [(set GPR:$Rd, (opnode (sext_inreg GPR:$Rn, i16),
3749218893Sdim                                      (sext_inreg GPR:$Rm, i16)))]>,
3750218893Sdim           Requires<[IsARM, HasV5TE]>;
3751193323Sed
3752218893Sdim  def BT : AMulxyI<0b0001011, 0b10, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
3753218893Sdim              IIC_iMUL16, !strconcat(opc, "bt"), "\t$Rd, $Rn, $Rm",
3754218893Sdim              [(set GPR:$Rd, (opnode (sext_inreg GPR:$Rn, i16),
3755218893Sdim                                      (sra GPR:$Rm, (i32 16))))]>,
3756218893Sdim           Requires<[IsARM, HasV5TE]>;
3757193323Sed
3758218893Sdim  def TB : AMulxyI<0b0001011, 0b01, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
3759218893Sdim              IIC_iMUL16, !strconcat(opc, "tb"), "\t$Rd, $Rn, $Rm",
3760218893Sdim              [(set GPR:$Rd, (opnode (sra GPR:$Rn, (i32 16)),
3761218893Sdim                                      (sext_inreg GPR:$Rm, i16)))]>,
3762218893Sdim           Requires<[IsARM, HasV5TE]>;
3763193323Sed
3764218893Sdim  def TT : AMulxyI<0b0001011, 0b11, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
3765218893Sdim              IIC_iMUL16, !strconcat(opc, "tt"), "\t$Rd, $Rn, $Rm",
3766218893Sdim              [(set GPR:$Rd, (opnode (sra GPR:$Rn, (i32 16)),
3767218893Sdim                                      (sra GPR:$Rm, (i32 16))))]>,
3768218893Sdim            Requires<[IsARM, HasV5TE]>;
3769193323Sed
3770218893Sdim  def WB : AMulxyI<0b0001001, 0b01, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
3771218893Sdim              IIC_iMUL16, !strconcat(opc, "wb"), "\t$Rd, $Rn, $Rm",
3772218893Sdim              [(set GPR:$Rd, (sra (opnode GPR:$Rn,
3773218893Sdim                                    (sext_inreg GPR:$Rm, i16)), (i32 16)))]>,
3774218893Sdim           Requires<[IsARM, HasV5TE]>;
3775193323Sed
3776218893Sdim  def WT : AMulxyI<0b0001001, 0b11, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
3777218893Sdim              IIC_iMUL16, !strconcat(opc, "wt"), "\t$Rd, $Rn, $Rm",
3778218893Sdim              [(set GPR:$Rd, (sra (opnode GPR:$Rn,
3779218893Sdim                                    (sra GPR:$Rm, (i32 16))), (i32 16)))]>,
3780218893Sdim            Requires<[IsARM, HasV5TE]>;
3781193323Sed}
3782193323Sed
3783193323Sed
3784193323Sedmulticlass AI_smla<string opc, PatFrag opnode> {
3785226890Sdim  let DecoderMethod = "DecodeSMLAInstruction" in {
3786226890Sdim  def BB : AMulxyIa<0b0001000, 0b00, (outs GPRnopc:$Rd),
3787226890Sdim              (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra),
3788218893Sdim              IIC_iMAC16, !strconcat(opc, "bb"), "\t$Rd, $Rn, $Rm, $Ra",
3789226890Sdim              [(set GPRnopc:$Rd, (add GPR:$Ra,
3790226890Sdim                               (opnode (sext_inreg GPRnopc:$Rn, i16),
3791226890Sdim                                       (sext_inreg GPRnopc:$Rm, i16))))]>,
3792245431Sdim           Requires<[IsARM, HasV5TE, UseMulOps]>;
3793193323Sed
3794226890Sdim  def BT : AMulxyIa<0b0001000, 0b10, (outs GPRnopc:$Rd),
3795226890Sdim              (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra),
3796218893Sdim              IIC_iMAC16, !strconcat(opc, "bt"), "\t$Rd, $Rn, $Rm, $Ra",
3797226890Sdim              [(set GPRnopc:$Rd,
3798226890Sdim                    (add GPR:$Ra, (opnode (sext_inreg GPRnopc:$Rn, i16),
3799226890Sdim                                          (sra GPRnopc:$Rm, (i32 16)))))]>,
3800245431Sdim           Requires<[IsARM, HasV5TE, UseMulOps]>;
3801193323Sed
3802226890Sdim  def TB : AMulxyIa<0b0001000, 0b01, (outs GPRnopc:$Rd),
3803226890Sdim              (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra),
3804218893Sdim              IIC_iMAC16, !strconcat(opc, "tb"), "\t$Rd, $Rn, $Rm, $Ra",
3805226890Sdim              [(set GPRnopc:$Rd,
3806226890Sdim                    (add GPR:$Ra, (opnode (sra GPRnopc:$Rn, (i32 16)),
3807226890Sdim                                          (sext_inreg GPRnopc:$Rm, i16))))]>,
3808245431Sdim           Requires<[IsARM, HasV5TE, UseMulOps]>;
3809193323Sed
3810226890Sdim  def TT : AMulxyIa<0b0001000, 0b11, (outs GPRnopc:$Rd),
3811226890Sdim              (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra),
3812218893Sdim              IIC_iMAC16, !strconcat(opc, "tt"), "\t$Rd, $Rn, $Rm, $Ra",
3813226890Sdim             [(set GPRnopc:$Rd,
3814226890Sdim                   (add GPR:$Ra, (opnode (sra GPRnopc:$Rn, (i32 16)),
3815226890Sdim                                         (sra GPRnopc:$Rm, (i32 16)))))]>,
3816245431Sdim            Requires<[IsARM, HasV5TE, UseMulOps]>;
3817193323Sed
3818226890Sdim  def WB : AMulxyIa<0b0001001, 0b00, (outs GPRnopc:$Rd),
3819226890Sdim              (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra),
3820218893Sdim              IIC_iMAC16, !strconcat(opc, "wb"), "\t$Rd, $Rn, $Rm, $Ra",
3821226890Sdim              [(set GPRnopc:$Rd,
3822226890Sdim                    (add GPR:$Ra, (sra (opnode GPRnopc:$Rn,
3823226890Sdim                                  (sext_inreg GPRnopc:$Rm, i16)), (i32 16))))]>,
3824245431Sdim           Requires<[IsARM, HasV5TE, UseMulOps]>;
3825193323Sed
3826226890Sdim  def WT : AMulxyIa<0b0001001, 0b10, (outs GPRnopc:$Rd),
3827226890Sdim              (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra),
3828218893Sdim              IIC_iMAC16, !strconcat(opc, "wt"), "\t$Rd, $Rn, $Rm, $Ra",
3829226890Sdim              [(set GPRnopc:$Rd,
3830226890Sdim                 (add GPR:$Ra, (sra (opnode GPRnopc:$Rn,
3831226890Sdim                                    (sra GPRnopc:$Rm, (i32 16))), (i32 16))))]>,
3832245431Sdim            Requires<[IsARM, HasV5TE, UseMulOps]>;
3833226890Sdim  }
3834193323Sed}
3835193323Sed
3836193323Seddefm SMUL : AI_smul<"smul", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
3837193323Seddefm SMLA : AI_smla<"smla", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
3838193323Sed
3839226890Sdim// Halfword multiply accumulate long: SMLAL<x><y>.
3840226890Sdimdef SMLALBB : AMulxyI64<0b0001010, 0b00, (outs GPRnopc:$RdLo, GPRnopc:$RdHi),
3841226890Sdim                      (ins GPRnopc:$Rn, GPRnopc:$Rm),
3842226890Sdim                      IIC_iMAC64, "smlalbb", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
3843218893Sdim              Requires<[IsARM, HasV5TE]>;
3844203954Srdivacky
3845226890Sdimdef SMLALBT : AMulxyI64<0b0001010, 0b10, (outs GPRnopc:$RdLo, GPRnopc:$RdHi),
3846226890Sdim                      (ins GPRnopc:$Rn, GPRnopc:$Rm),
3847226890Sdim                      IIC_iMAC64, "smlalbt", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
3848218893Sdim              Requires<[IsARM, HasV5TE]>;
3849203954Srdivacky
3850226890Sdimdef SMLALTB : AMulxyI64<0b0001010, 0b01, (outs GPRnopc:$RdLo, GPRnopc:$RdHi),
3851226890Sdim                      (ins GPRnopc:$Rn, GPRnopc:$Rm),
3852226890Sdim                      IIC_iMAC64, "smlaltb", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
3853218893Sdim              Requires<[IsARM, HasV5TE]>;
3854203954Srdivacky
3855226890Sdimdef SMLALTT : AMulxyI64<0b0001010, 0b11, (outs GPRnopc:$RdLo, GPRnopc:$RdHi),
3856226890Sdim                      (ins GPRnopc:$Rn, GPRnopc:$Rm),
3857226890Sdim                      IIC_iMAC64, "smlaltt", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
3858218893Sdim              Requires<[IsARM, HasV5TE]>;
3859203954Srdivacky
3860226890Sdim// Helper class for AI_smld.
3861218893Sdimclass AMulDualIbase<bit long, bit sub, bit swap, dag oops, dag iops,
3862218893Sdim                    InstrItinClass itin, string opc, string asm>
3863204642Srdivacky  : AI<oops, iops, MulFrm, itin, opc, asm, []>, Requires<[IsARM, HasV6]> {
3864218893Sdim  bits<4> Rn;
3865218893Sdim  bits<4> Rm;
3866226890Sdim  let Inst{27-23} = 0b01110;
3867226890Sdim  let Inst{22}    = long;
3868204642Srdivacky  let Inst{21-20} = 0b00;
3869218893Sdim  let Inst{11-8}  = Rm;
3870226890Sdim  let Inst{7}     = 0;
3871226890Sdim  let Inst{6}     = sub;
3872226890Sdim  let Inst{5}     = swap;
3873226890Sdim  let Inst{4}     = 1;
3874218893Sdim  let Inst{3-0}   = Rn;
3875204642Srdivacky}
3876218893Sdimclass AMulDualI<bit long, bit sub, bit swap, dag oops, dag iops,
3877218893Sdim                InstrItinClass itin, string opc, string asm>
3878218893Sdim  : AMulDualIbase<long, sub, swap, oops, iops, itin, opc, asm> {
3879218893Sdim  bits<4> Rd;
3880218893Sdim  let Inst{15-12} = 0b1111;
3881218893Sdim  let Inst{19-16} = Rd;
3882218893Sdim}
3883218893Sdimclass AMulDualIa<bit long, bit sub, bit swap, dag oops, dag iops,
3884218893Sdim                InstrItinClass itin, string opc, string asm>
3885218893Sdim  : AMulDualIbase<long, sub, swap, oops, iops, itin, opc, asm> {
3886218893Sdim  bits<4> Ra;
3887226890Sdim  bits<4> Rd;
3888226890Sdim  let Inst{19-16} = Rd;
3889218893Sdim  let Inst{15-12} = Ra;
3890218893Sdim}
3891218893Sdimclass AMulDualI64<bit long, bit sub, bit swap, dag oops, dag iops,
3892218893Sdim                  InstrItinClass itin, string opc, string asm>
3893218893Sdim  : AMulDualIbase<long, sub, swap, oops, iops, itin, opc, asm> {
3894218893Sdim  bits<4> RdLo;
3895218893Sdim  bits<4> RdHi;
3896218893Sdim  let Inst{19-16} = RdHi;
3897218893Sdim  let Inst{15-12} = RdLo;
3898218893Sdim}
3899193323Sed
3900204642Srdivackymulticlass AI_smld<bit sub, string opc> {
3901204642Srdivacky
3902226890Sdim  def D : AMulDualIa<0, sub, 0, (outs GPRnopc:$Rd),
3903226890Sdim                  (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra),
3904218893Sdim                  NoItinerary, !strconcat(opc, "d"), "\t$Rd, $Rn, $Rm, $Ra">;
3905204642Srdivacky
3906226890Sdim  def DX: AMulDualIa<0, sub, 1, (outs GPRnopc:$Rd),
3907226890Sdim                  (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra),
3908218893Sdim                  NoItinerary, !strconcat(opc, "dx"), "\t$Rd, $Rn, $Rm, $Ra">;
3909204642Srdivacky
3910226890Sdim  def LD: AMulDualI64<1, sub, 0, (outs GPRnopc:$RdLo, GPRnopc:$RdHi),
3911226890Sdim                  (ins GPRnopc:$Rn, GPRnopc:$Rm), NoItinerary,
3912218893Sdim                  !strconcat(opc, "ld"), "\t$RdLo, $RdHi, $Rn, $Rm">;
3913204642Srdivacky
3914226890Sdim  def LDX : AMulDualI64<1, sub, 1, (outs GPRnopc:$RdLo, GPRnopc:$RdHi),
3915226890Sdim                  (ins GPRnopc:$Rn, GPRnopc:$Rm), NoItinerary,
3916218893Sdim                  !strconcat(opc, "ldx"),"\t$RdLo, $RdHi, $Rn, $Rm">;
3917204642Srdivacky
3918204642Srdivacky}
3919204642Srdivacky
3920204642Srdivackydefm SMLA : AI_smld<0, "smla">;
3921204642Srdivackydefm SMLS : AI_smld<1, "smls">;
3922204642Srdivacky
3923204642Srdivackymulticlass AI_sdml<bit sub, string opc> {
3924204642Srdivacky
3925226890Sdim  def D:AMulDualI<0, sub, 0, (outs GPRnopc:$Rd), (ins GPRnopc:$Rn, GPRnopc:$Rm),
3926226890Sdim                  NoItinerary, !strconcat(opc, "d"), "\t$Rd, $Rn, $Rm">;
3927226890Sdim  def DX:AMulDualI<0, sub, 1, (outs GPRnopc:$Rd),(ins GPRnopc:$Rn, GPRnopc:$Rm),
3928226890Sdim                  NoItinerary, !strconcat(opc, "dx"), "\t$Rd, $Rn, $Rm">;
3929204642Srdivacky}
3930204642Srdivacky
3931204642Srdivackydefm SMUA : AI_sdml<0, "smua">;
3932204642Srdivackydefm SMUS : AI_sdml<1, "smus">;
3933204642Srdivacky
3934193323Sed//===----------------------------------------------------------------------===//
3935245431Sdim//  Division Instructions (ARMv7-A with virtualization extension)
3936245431Sdim//
3937245431Sdimdef SDIV : ADivA1I<0b001, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), IIC_iDIV,
3938245431Sdim                   "sdiv", "\t$Rd, $Rn, $Rm",
3939245431Sdim                   [(set GPR:$Rd, (sdiv GPR:$Rn, GPR:$Rm))]>,
3940245431Sdim           Requires<[IsARM, HasDivideInARM]>;
3941245431Sdim
3942245431Sdimdef UDIV : ADivA1I<0b011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), IIC_iDIV,
3943245431Sdim                   "udiv", "\t$Rd, $Rn, $Rm",
3944245431Sdim                   [(set GPR:$Rd, (udiv GPR:$Rn, GPR:$Rm))]>,
3945245431Sdim           Requires<[IsARM, HasDivideInARM]>;
3946245431Sdim
3947245431Sdim//===----------------------------------------------------------------------===//
3948193323Sed//  Misc. Arithmetic Instructions.
3949193323Sed//
3950193323Sed
3951218893Sdimdef CLZ  : AMiscA1I<0b000010110, 0b0001, (outs GPR:$Rd), (ins GPR:$Rm),
3952218893Sdim              IIC_iUNAr, "clz", "\t$Rd, $Rm",
3953252723Sdim              [(set GPR:$Rd, (ctlz GPR:$Rm))]>, Requires<[IsARM, HasV5T]>,
3954252723Sdim           Sched<[WriteALU]>;
3955193323Sed
3956218893Sdimdef RBIT : AMiscA1I<0b01101111, 0b0011, (outs GPR:$Rd), (ins GPR:$Rm),
3957218893Sdim              IIC_iUNAr, "rbit", "\t$Rd, $Rm",
3958218893Sdim              [(set GPR:$Rd, (ARMrbit GPR:$Rm))]>,
3959252723Sdim           Requires<[IsARM, HasV6T2]>,
3960252723Sdim           Sched<[WriteALU]>;
3961202878Srdivacky
3962218893Sdimdef REV  : AMiscA1I<0b01101011, 0b0011, (outs GPR:$Rd), (ins GPR:$Rm),
3963218893Sdim              IIC_iUNAr, "rev", "\t$Rd, $Rm",
3964252723Sdim              [(set GPR:$Rd, (bswap GPR:$Rm))]>, Requires<[IsARM, HasV6]>,
3965252723Sdim           Sched<[WriteALU]>;
3966193323Sed
3967224145Sdimlet AddedComplexity = 5 in
3968218893Sdimdef REV16 : AMiscA1I<0b01101011, 0b1011, (outs GPR:$Rd), (ins GPR:$Rm),
3969218893Sdim               IIC_iUNAr, "rev16", "\t$Rd, $Rm",
3970224145Sdim               [(set GPR:$Rd, (rotr (bswap GPR:$Rm), (i32 16)))]>,
3971252723Sdim               Requires<[IsARM, HasV6]>,
3972252723Sdim           Sched<[WriteALU]>;
3973193323Sed
3974224145Sdimlet AddedComplexity = 5 in
3975218893Sdimdef REVSH : AMiscA1I<0b01101111, 0b1011, (outs GPR:$Rd), (ins GPR:$Rm),
3976218893Sdim               IIC_iUNAr, "revsh", "\t$Rd, $Rm",
3977224145Sdim               [(set GPR:$Rd, (sra (bswap GPR:$Rm), (i32 16)))]>,
3978252723Sdim               Requires<[IsARM, HasV6]>,
3979252723Sdim           Sched<[WriteALU]>;
3980193323Sed
3981224145Sdimdef : ARMV6Pat<(or (sra (shl GPR:$Rm, (i32 24)), (i32 16)),
3982224145Sdim                   (and (srl GPR:$Rm, (i32 8)), 0xFF)),
3983221345Sdim               (REVSH GPR:$Rm)>;
3984221345Sdim
3985226890Sdimdef PKHBT : APKHI<0b01101000, 0, (outs GPRnopc:$Rd),
3986226890Sdim                              (ins GPRnopc:$Rn, GPRnopc:$Rm, pkh_lsl_amt:$sh),
3987218893Sdim               IIC_iALUsi, "pkhbt", "\t$Rd, $Rn, $Rm$sh",
3988226890Sdim               [(set GPRnopc:$Rd, (or (and GPRnopc:$Rn, 0xFFFF),
3989226890Sdim                                      (and (shl GPRnopc:$Rm, pkh_lsl_amt:$sh),
3990226890Sdim                                           0xFFFF0000)))]>,
3991252723Sdim               Requires<[IsARM, HasV6]>,
3992252723Sdim           Sched<[WriteALUsi, ReadALU]>;
3993193323Sed
3994193323Sed// Alternate cases for PKHBT where identities eliminate some nodes.
3995226890Sdimdef : ARMV6Pat<(or (and GPRnopc:$Rn, 0xFFFF), (and GPRnopc:$Rm, 0xFFFF0000)),
3996226890Sdim               (PKHBT GPRnopc:$Rn, GPRnopc:$Rm, 0)>;
3997226890Sdimdef : ARMV6Pat<(or (and GPRnopc:$Rn, 0xFFFF), (shl GPRnopc:$Rm, imm16_31:$sh)),
3998226890Sdim               (PKHBT GPRnopc:$Rn, GPRnopc:$Rm, imm16_31:$sh)>;
3999193323Sed
4000212904Sdim// Note: Shifts of 1-15 bits will be transformed to srl instead of sra and
4001212904Sdim// will match the pattern below.
4002226890Sdimdef PKHTB : APKHI<0b01101000, 1, (outs GPRnopc:$Rd),
4003226890Sdim                              (ins GPRnopc:$Rn, GPRnopc:$Rm, pkh_asr_amt:$sh),
4004218893Sdim               IIC_iBITsi, "pkhtb", "\t$Rd, $Rn, $Rm$sh",
4005226890Sdim               [(set GPRnopc:$Rd, (or (and GPRnopc:$Rn, 0xFFFF0000),
4006226890Sdim                                      (and (sra GPRnopc:$Rm, pkh_asr_amt:$sh),
4007226890Sdim                                           0xFFFF)))]>,
4008252723Sdim               Requires<[IsARM, HasV6]>,
4009252723Sdim           Sched<[WriteALUsi, ReadALU]>;
4010193323Sed
4011193323Sed// Alternate cases for PKHTB where identities eliminate some nodes.  Note that
4012193323Sed// a shift amount of 0 is *not legal* here, it is PKHBT instead.
4013263509Sdim// We also can not replace a srl (17..31) by an arithmetic shift we would use in
4014263509Sdim// pkhtb src1, src2, asr (17..31).
4015226890Sdimdef : ARMV6Pat<(or (and GPRnopc:$src1, 0xFFFF0000),
4016263509Sdim                   (srl GPRnopc:$src2, imm16:$sh)),
4017263509Sdim               (PKHTB GPRnopc:$src1, GPRnopc:$src2, imm16:$sh)>;
4018263509Sdimdef : ARMV6Pat<(or (and GPRnopc:$src1, 0xFFFF0000),
4019263509Sdim                   (sra GPRnopc:$src2, imm16_31:$sh)),
4020226890Sdim               (PKHTB GPRnopc:$src1, GPRnopc:$src2, imm16_31:$sh)>;
4021226890Sdimdef : ARMV6Pat<(or (and GPRnopc:$src1, 0xFFFF0000),
4022226890Sdim                   (and (srl GPRnopc:$src2, imm1_15:$sh), 0xFFFF)),
4023226890Sdim               (PKHTB GPRnopc:$src1, GPRnopc:$src2, imm1_15:$sh)>;
4024193323Sed
4025193323Sed//===----------------------------------------------------------------------===//
4026263509Sdim// CRC Instructions
4027263509Sdim//
4028263509Sdim// Polynomials:
4029263509Sdim// + CRC32{B,H,W}       0x04C11DB7
4030263509Sdim// + CRC32C{B,H,W}      0x1EDC6F41
4031263509Sdim//
4032263509Sdim
4033263509Sdimclass AI_crc32<bit C, bits<2> sz, string suffix, SDPatternOperator builtin>
4034263509Sdim  : AInoP<(outs GPRnopc:$Rd), (ins GPRnopc:$Rn, GPRnopc:$Rm), MiscFrm, NoItinerary,
4035263509Sdim               !strconcat("crc32", suffix), "\t$Rd, $Rn, $Rm",
4036263509Sdim               [(set GPRnopc:$Rd, (builtin GPRnopc:$Rn, GPRnopc:$Rm))]>,
4037263509Sdim               Requires<[IsARM, HasV8, HasCRC]> {
4038263509Sdim  bits<4> Rd;
4039263509Sdim  bits<4> Rn;
4040263509Sdim  bits<4> Rm;
4041263509Sdim
4042263509Sdim  let Inst{31-28} = 0b1110;
4043263509Sdim  let Inst{27-23} = 0b00010;
4044263509Sdim  let Inst{22-21} = sz;
4045263509Sdim  let Inst{20}    = 0;
4046263509Sdim  let Inst{19-16} = Rn;
4047263509Sdim  let Inst{15-12} = Rd;
4048263509Sdim  let Inst{11-10} = 0b00;
4049263509Sdim  let Inst{9}     = C;
4050263509Sdim  let Inst{8}     = 0;
4051263509Sdim  let Inst{7-4}   = 0b0100;
4052263509Sdim  let Inst{3-0}   = Rm;
4053263509Sdim
4054263509Sdim  let Unpredictable{11-8} = 0b1101;
4055263509Sdim}
4056263509Sdim
4057263509Sdimdef CRC32B  : AI_crc32<0, 0b00, "b", int_arm_crc32b>;
4058263509Sdimdef CRC32CB : AI_crc32<1, 0b00, "cb", int_arm_crc32cb>;
4059263509Sdimdef CRC32H  : AI_crc32<0, 0b01, "h", int_arm_crc32h>;
4060263509Sdimdef CRC32CH : AI_crc32<1, 0b01, "ch", int_arm_crc32ch>;
4061263509Sdimdef CRC32W  : AI_crc32<0, 0b10, "w", int_arm_crc32w>;
4062263509Sdimdef CRC32CW : AI_crc32<1, 0b10, "cw", int_arm_crc32cw>;
4063263509Sdim
4064263509Sdim//===----------------------------------------------------------------------===//
4065193323Sed//  Comparison Instructions...
4066193323Sed//
4067193323Sed
4068193323Seddefm CMP  : AI1_cmp_irs<0b1010, "cmp",
4069218893Sdim                        IIC_iCMPi, IIC_iCMPr, IIC_iCMPsr,
4070193323Sed                        BinOpFrag<(ARMcmp node:$LHS, node:$RHS)>>;
4071212904Sdim
4072218893Sdim// ARMcmpZ can re-use the above instruction definitions.
4073218893Sdimdef : ARMPat<(ARMcmpZ GPR:$src, so_imm:$imm),
4074218893Sdim             (CMPri   GPR:$src, so_imm:$imm)>;
4075218893Sdimdef : ARMPat<(ARMcmpZ GPR:$src, GPR:$rhs),
4076218893Sdim             (CMPrr   GPR:$src, GPR:$rhs)>;
4077226890Sdimdef : ARMPat<(ARMcmpZ GPR:$src, so_reg_imm:$rhs),
4078226890Sdim             (CMPrsi   GPR:$src, so_reg_imm:$rhs)>;
4079226890Sdimdef : ARMPat<(ARMcmpZ GPR:$src, so_reg_reg:$rhs),
4080226890Sdim             (CMPrsr   GPR:$src, so_reg_reg:$rhs)>;
4081218893Sdim
4082245431Sdim// CMN register-integer
4083245431Sdimlet isCompare = 1, Defs = [CPSR] in {
4084245431Sdimdef CMNri : AI1<0b1011, (outs), (ins GPR:$Rn, so_imm:$imm), DPFrm, IIC_iCMPi,
4085245431Sdim                "cmn", "\t$Rn, $imm",
4086263509Sdim                [(ARMcmn GPR:$Rn, so_imm:$imm)]>,
4087263509Sdim                Sched<[WriteCMP, ReadALU]> {
4088245431Sdim  bits<4> Rn;
4089245431Sdim  bits<12> imm;
4090245431Sdim  let Inst{25} = 1;
4091245431Sdim  let Inst{20} = 1;
4092245431Sdim  let Inst{19-16} = Rn;
4093245431Sdim  let Inst{15-12} = 0b0000;
4094245431Sdim  let Inst{11-0} = imm;
4095193323Sed
4096245431Sdim  let Unpredictable{15-12} = 0b1111;
4097245431Sdim}
4098245431Sdim
4099245431Sdim// CMN register-register/shift
4100245431Sdimdef CMNzrr : AI1<0b1011, (outs), (ins GPR:$Rn, GPR:$Rm), DPFrm, IIC_iCMPr,
4101245431Sdim                 "cmn", "\t$Rn, $Rm",
4102245431Sdim                 [(BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))>
4103263509Sdim                   GPR:$Rn, GPR:$Rm)]>, Sched<[WriteCMP, ReadALU, ReadALU]> {
4104245431Sdim  bits<4> Rn;
4105245431Sdim  bits<4> Rm;
4106245431Sdim  let isCommutable = 1;
4107245431Sdim  let Inst{25} = 0;
4108245431Sdim  let Inst{20} = 1;
4109245431Sdim  let Inst{19-16} = Rn;
4110245431Sdim  let Inst{15-12} = 0b0000;
4111245431Sdim  let Inst{11-4} = 0b00000000;
4112245431Sdim  let Inst{3-0} = Rm;
4113245431Sdim
4114245431Sdim  let Unpredictable{15-12} = 0b1111;
4115245431Sdim}
4116245431Sdim
4117245431Sdimdef CMNzrsi : AI1<0b1011, (outs),
4118245431Sdim                  (ins GPR:$Rn, so_reg_imm:$shift), DPSoRegImmFrm, IIC_iCMPsr,
4119245431Sdim                  "cmn", "\t$Rn, $shift",
4120245431Sdim                  [(BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))>
4121263509Sdim                    GPR:$Rn, so_reg_imm:$shift)]>,
4122263509Sdim                    Sched<[WriteCMPsi, ReadALU]> {
4123245431Sdim  bits<4> Rn;
4124245431Sdim  bits<12> shift;
4125245431Sdim  let Inst{25} = 0;
4126245431Sdim  let Inst{20} = 1;
4127245431Sdim  let Inst{19-16} = Rn;
4128245431Sdim  let Inst{15-12} = 0b0000;
4129245431Sdim  let Inst{11-5} = shift{11-5};
4130245431Sdim  let Inst{4} = 0;
4131245431Sdim  let Inst{3-0} = shift{3-0};
4132245431Sdim
4133245431Sdim  let Unpredictable{15-12} = 0b1111;
4134245431Sdim}
4135245431Sdim
4136245431Sdimdef CMNzrsr : AI1<0b1011, (outs),
4137245431Sdim                  (ins GPRnopc:$Rn, so_reg_reg:$shift), DPSoRegRegFrm, IIC_iCMPsr,
4138245431Sdim                  "cmn", "\t$Rn, $shift",
4139245431Sdim                  [(BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))>
4140263509Sdim                    GPRnopc:$Rn, so_reg_reg:$shift)]>,
4141263509Sdim                    Sched<[WriteCMPsr, ReadALU]> {
4142245431Sdim  bits<4> Rn;
4143245431Sdim  bits<12> shift;
4144245431Sdim  let Inst{25} = 0;
4145245431Sdim  let Inst{20} = 1;
4146245431Sdim  let Inst{19-16} = Rn;
4147245431Sdim  let Inst{15-12} = 0b0000;
4148245431Sdim  let Inst{11-8} = shift{11-8};
4149245431Sdim  let Inst{7} = 0;
4150245431Sdim  let Inst{6-5} = shift{6-5};
4151245431Sdim  let Inst{4} = 1;
4152245431Sdim  let Inst{3-0} = shift{3-0};
4153245431Sdim
4154245431Sdim  let Unpredictable{15-12} = 0b1111;
4155245431Sdim}
4156245431Sdim
4157245431Sdim}
4158245431Sdim
4159245431Sdimdef : ARMPat<(ARMcmp  GPR:$src, so_imm_neg:$imm),
4160245431Sdim             (CMNri   GPR:$src, so_imm_neg:$imm)>;
4161245431Sdim
4162245431Sdimdef : ARMPat<(ARMcmpZ GPR:$src, so_imm_neg:$imm),
4163245431Sdim             (CMNri   GPR:$src, so_imm_neg:$imm)>;
4164245431Sdim
4165193323Sed// Note that TST/TEQ don't set all the same flags that CMP does!
4166193323Seddefm TST  : AI1_cmp_irs<0b1000, "tst",
4167218893Sdim                        IIC_iTSTi, IIC_iTSTr, IIC_iTSTsr,
4168218893Sdim                      BinOpFrag<(ARMcmpZ (and_su node:$LHS, node:$RHS), 0)>, 1>;
4169193323Seddefm TEQ  : AI1_cmp_irs<0b1001, "teq",
4170218893Sdim                        IIC_iTSTi, IIC_iTSTr, IIC_iTSTsr,
4171218893Sdim                      BinOpFrag<(ARMcmpZ (xor_su node:$LHS, node:$RHS), 0)>, 1>;
4172193323Sed
4173210299Sed// Pseudo i64 compares for some floating point compares.
4174210299Sedlet usesCustomInserter = 1, isBranch = 1, isTerminator = 1,
4175210299Sed    Defs = [CPSR] in {
4176210299Seddef BCCi64 : PseudoInst<(outs),
4177212904Sdim    (ins i32imm:$cc, GPR:$lhs1, GPR:$lhs2, GPR:$rhs1, GPR:$rhs2, brtarget:$dst),
4178212904Sdim     IIC_Br,
4179263509Sdim    [(ARMBcci64 imm:$cc, GPR:$lhs1, GPR:$lhs2, GPR:$rhs1, GPR:$rhs2, bb:$dst)]>,
4180263509Sdim    Sched<[WriteBr]>;
4181193323Sed
4182210299Seddef BCCZi64 : PseudoInst<(outs),
4183218893Sdim     (ins i32imm:$cc, GPR:$lhs1, GPR:$lhs2, brtarget:$dst), IIC_Br,
4184263509Sdim    [(ARMBcci64 imm:$cc, GPR:$lhs1, GPR:$lhs2, 0, 0, bb:$dst)]>,
4185263509Sdim    Sched<[WriteBr]>;
4186210299Sed} // usesCustomInserter
4187210299Sed
4188210299Sed
4189193323Sed// Conditional moves
4190208599Srdivackylet neverHasSideEffects = 1 in {
4191235633Sdim
4192245431Sdimlet isCommutable = 1, isSelect = 1 in
4193263509Sdimdef MOVCCr : ARMPseudoInst<(outs GPR:$Rd),
4194263509Sdim                           (ins GPR:$false, GPR:$Rm, cmovpred:$p),
4195224145Sdim                           4, IIC_iCMOVr,
4196263509Sdim                           [(set GPR:$Rd, (ARMcmov GPR:$false, GPR:$Rm,
4197263509Sdim                                                   cmovpred:$p))]>,
4198263509Sdim             RegConstraint<"$false = $Rd">, Sched<[WriteALU]>;
4199235633Sdim
4200226890Sdimdef MOVCCsi : ARMPseudoInst<(outs GPR:$Rd),
4201263509Sdim                            (ins GPR:$false, so_reg_imm:$shift, cmovpred:$p),
4202263509Sdim                            4, IIC_iCMOVsr,
4203263509Sdim                            [(set GPR:$Rd,
4204263509Sdim                                  (ARMcmov GPR:$false, so_reg_imm:$shift,
4205263509Sdim                                           cmovpred:$p))]>,
4206263509Sdim      RegConstraint<"$false = $Rd">, Sched<[WriteALU]>;
4207226890Sdimdef MOVCCsr : ARMPseudoInst<(outs GPR:$Rd),
4208263509Sdim                            (ins GPR:$false, so_reg_reg:$shift, cmovpred:$p),
4209226890Sdim                           4, IIC_iCMOVsr,
4210263509Sdim  [(set GPR:$Rd, (ARMcmov GPR:$false, so_reg_reg:$shift,
4211263509Sdim                            cmovpred:$p))]>,
4212263509Sdim      RegConstraint<"$false = $Rd">, Sched<[WriteALU]>;
4213193323Sed
4214226890Sdim
4215218893Sdimlet isMoveImm = 1 in
4216263509Sdimdef MOVCCi16
4217263509Sdim    : ARMPseudoInst<(outs GPR:$Rd),
4218263509Sdim                    (ins GPR:$false, imm0_65535_expr:$imm, cmovpred:$p),
4219263509Sdim                    4, IIC_iMOVi,
4220263509Sdim                    [(set GPR:$Rd, (ARMcmov GPR:$false, imm0_65535:$imm,
4221263509Sdim                                            cmovpred:$p))]>,
4222263509Sdim      RegConstraint<"$false = $Rd">, Requires<[IsARM, HasV6T2]>,
4223263509Sdim      Sched<[WriteALU]>;
4224218893Sdim
4225218893Sdimlet isMoveImm = 1 in
4226221345Sdimdef MOVCCi : ARMPseudoInst<(outs GPR:$Rd),
4227263509Sdim                           (ins GPR:$false, so_imm:$imm, cmovpred:$p),
4228224145Sdim                           4, IIC_iCMOVi,
4229263509Sdim                           [(set GPR:$Rd, (ARMcmov GPR:$false, so_imm:$imm,
4230263509Sdim                                                   cmovpred:$p))]>,
4231263509Sdim      RegConstraint<"$false = $Rd">, Sched<[WriteALU]>;
4232218893Sdim
4233218893Sdim// Two instruction predicate mov immediate.
4234218893Sdimlet isMoveImm = 1 in
4235263509Sdimdef MOVCCi32imm
4236263509Sdim    : ARMPseudoInst<(outs GPR:$Rd),
4237263509Sdim                    (ins GPR:$false, i32imm:$src, cmovpred:$p),
4238263509Sdim                    8, IIC_iCMOVix2,
4239263509Sdim                    [(set GPR:$Rd, (ARMcmov GPR:$false, imm:$src,
4240263509Sdim                                            cmovpred:$p))]>,
4241263509Sdim      RegConstraint<"$false = $Rd">, Requires<[IsARM, HasV6T2]>;
4242218893Sdim
4243218893Sdimlet isMoveImm = 1 in
4244221345Sdimdef MVNCCi : ARMPseudoInst<(outs GPR:$Rd),
4245263509Sdim                           (ins GPR:$false, so_imm:$imm, cmovpred:$p),
4246224145Sdim                           4, IIC_iCMOVi,
4247263509Sdim                           [(set GPR:$Rd, (ARMcmov GPR:$false, so_imm_not:$imm,
4248263509Sdim                                                   cmovpred:$p))]>,
4249263509Sdim                RegConstraint<"$false = $Rd">, Sched<[WriteALU]>;
4250235633Sdim
4251208599Srdivacky} // neverHasSideEffects
4252193323Sed
4253235633Sdim
4254200581Srdivacky//===----------------------------------------------------------------------===//
4255200581Srdivacky// Atomic operations intrinsics
4256200581Srdivacky//
4257193323Sed
4258226890Sdimdef MemBarrierOptOperand : AsmOperandClass {
4259226890Sdim  let Name = "MemBarrierOpt";
4260226890Sdim  let ParserMethod = "parseMemBarrierOptOperand";
4261226890Sdim}
4262218893Sdimdef memb_opt : Operand<i32> {
4263218893Sdim  let PrintMethod = "printMemBOption";
4264218893Sdim  let ParserMatchClass = MemBarrierOptOperand;
4265226890Sdim  let DecoderMethod = "DecodeMemBarrierOption";
4266218893Sdim}
4267218893Sdim
4268263509Sdimdef InstSyncBarrierOptOperand : AsmOperandClass {
4269263509Sdim  let Name = "InstSyncBarrierOpt";
4270263509Sdim  let ParserMethod = "parseInstSyncBarrierOptOperand";
4271263509Sdim}
4272263509Sdimdef instsyncb_opt : Operand<i32> {
4273263509Sdim  let PrintMethod = "printInstSyncBOption";
4274263509Sdim  let ParserMatchClass = InstSyncBarrierOptOperand;
4275263509Sdim  let DecoderMethod = "DecodeInstSyncBarrierOption";
4276263509Sdim}
4277263509Sdim
4278200581Srdivacky// memory barriers protect the atomic sequences
4279200581Srdivackylet hasSideEffects = 1 in {
4280218893Sdimdef DMB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary,
4281263509Sdim                "dmb", "\t$opt", [(int_arm_dmb (i32 imm0_15:$opt))]>,
4282218893Sdim                Requires<[IsARM, HasDB]> {
4283218893Sdim  bits<4> opt;
4284200581Srdivacky  let Inst{31-4} = 0xf57ff05;
4285218893Sdim  let Inst{3-0} = opt;
4286200581Srdivacky}
4287200581Srdivacky}
4288200581Srdivacky
4289218893Sdimdef DSB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary,
4290263509Sdim                "dsb", "\t$opt", [(int_arm_dsb (i32 imm0_15:$opt))]>,
4291218893Sdim                Requires<[IsARM, HasDB]> {
4292218893Sdim  bits<4> opt;
4293218893Sdim  let Inst{31-4} = 0xf57ff04;
4294218893Sdim  let Inst{3-0} = opt;
4295204642Srdivacky}
4296204642Srdivacky
4297224145Sdim// ISB has only full system option
4298263509Sdimdef ISB : AInoP<(outs), (ins instsyncb_opt:$opt), MiscFrm, NoItinerary,
4299224145Sdim                "isb", "\t$opt", []>,
4300218893Sdim                Requires<[IsARM, HasDB]> {
4301224145Sdim  bits<4> opt;
4302212904Sdim  let Inst{31-4} = 0xf57ff06;
4303224145Sdim  let Inst{3-0} = opt;
4304204642Srdivacky}
4305204642Srdivacky
4306263509Sdimlet usesCustomInserter = 1, Defs = [CPSR] in {
4307263509Sdim
4308235633Sdim// Pseudo instruction that combines movs + predicated rsbmi
4309226890Sdim// to implement integer ABS
4310263509Sdim  def ABS : ARMPseudoInst<(outs GPR:$dst), (ins GPR:$src), 8, NoItinerary, []>;
4311226890Sdim
4312263509Sdim// Atomic pseudo-insts which will be lowered to ldrex/strex loops.
4313263509Sdim// (64-bit pseudos use a hand-written selection code).
4314263509Sdim  let mayLoad = 1, mayStore = 1 in {
4315200581Srdivacky    def ATOMIC_LOAD_ADD_I8 : PseudoInst<
4316263509Sdim      (outs GPR:$dst),
4317263509Sdim      (ins GPR:$ptr, GPR:$incr, i32imm:$ordering),
4318263509Sdim      NoItinerary, []>;
4319200581Srdivacky    def ATOMIC_LOAD_SUB_I8 : PseudoInst<
4320263509Sdim      (outs GPR:$dst),
4321263509Sdim      (ins GPR:$ptr, GPR:$incr, i32imm:$ordering),
4322263509Sdim      NoItinerary, []>;
4323200581Srdivacky    def ATOMIC_LOAD_AND_I8 : PseudoInst<
4324263509Sdim      (outs GPR:$dst),
4325263509Sdim      (ins GPR:$ptr, GPR:$incr, i32imm:$ordering),
4326263509Sdim      NoItinerary, []>;
4327200581Srdivacky    def ATOMIC_LOAD_OR_I8 : PseudoInst<
4328263509Sdim      (outs GPR:$dst),
4329263509Sdim      (ins GPR:$ptr, GPR:$incr, i32imm:$ordering),
4330263509Sdim      NoItinerary, []>;
4331200581Srdivacky    def ATOMIC_LOAD_XOR_I8 : PseudoInst<
4332263509Sdim      (outs GPR:$dst),
4333263509Sdim      (ins GPR:$ptr, GPR:$incr, i32imm:$ordering),
4334263509Sdim      NoItinerary, []>;
4335200581Srdivacky    def ATOMIC_LOAD_NAND_I8 : PseudoInst<
4336263509Sdim      (outs GPR:$dst),
4337263509Sdim      (ins GPR:$ptr, GPR:$incr, i32imm:$ordering),
4338263509Sdim      NoItinerary, []>;
4339221345Sdim    def ATOMIC_LOAD_MIN_I8 : PseudoInst<
4340263509Sdim      (outs GPR:$dst),
4341263509Sdim      (ins GPR:$ptr, GPR:$val, i32imm:$ordering),
4342263509Sdim      NoItinerary, []>;
4343221345Sdim    def ATOMIC_LOAD_MAX_I8 : PseudoInst<
4344263509Sdim      (outs GPR:$dst),
4345263509Sdim      (ins GPR:$ptr, GPR:$val, i32imm:$ordering),
4346263509Sdim      NoItinerary, []>;
4347221345Sdim    def ATOMIC_LOAD_UMIN_I8 : PseudoInst<
4348263509Sdim      (outs GPR:$dst),
4349263509Sdim      (ins GPR:$ptr, GPR:$val, i32imm:$ordering),
4350263509Sdim      NoItinerary, []>;
4351221345Sdim    def ATOMIC_LOAD_UMAX_I8 : PseudoInst<
4352263509Sdim      (outs GPR:$dst),
4353263509Sdim      (ins GPR:$ptr, GPR:$val, i32imm:$ordering),
4354263509Sdim      NoItinerary, []>;
4355263509Sdim    def ATOMIC_SWAP_I8 : PseudoInst<
4356263509Sdim      (outs GPR:$dst),
4357263509Sdim      (ins GPR:$ptr, GPR:$new, i32imm:$ordering),
4358263509Sdim      NoItinerary, []>;
4359263509Sdim    def ATOMIC_CMP_SWAP_I8 : PseudoInst<
4360263509Sdim      (outs GPR:$dst),
4361263509Sdim      (ins GPR:$ptr, GPR:$old, GPR:$new, i32imm:$ordering),
4362263509Sdim      NoItinerary, []>;
4363200581Srdivacky    def ATOMIC_LOAD_ADD_I16 : PseudoInst<
4364263509Sdim      (outs GPR:$dst),
4365263509Sdim      (ins GPR:$ptr, GPR:$incr, i32imm:$ordering),
4366263509Sdim      NoItinerary, []>;
4367200581Srdivacky    def ATOMIC_LOAD_SUB_I16 : PseudoInst<
4368263509Sdim      (outs GPR:$dst),
4369263509Sdim      (ins GPR:$ptr, GPR:$incr, i32imm:$ordering),
4370263509Sdim      NoItinerary, []>;
4371200581Srdivacky    def ATOMIC_LOAD_AND_I16 : PseudoInst<
4372263509Sdim      (outs GPR:$dst),
4373263509Sdim      (ins GPR:$ptr, GPR:$incr, i32imm:$ordering),
4374263509Sdim      NoItinerary, []>;
4375200581Srdivacky    def ATOMIC_LOAD_OR_I16 : PseudoInst<
4376263509Sdim      (outs GPR:$dst),
4377263509Sdim      (ins GPR:$ptr, GPR:$incr, i32imm:$ordering),
4378263509Sdim      NoItinerary, []>;
4379200581Srdivacky    def ATOMIC_LOAD_XOR_I16 : PseudoInst<
4380263509Sdim      (outs GPR:$dst),
4381263509Sdim      (ins GPR:$ptr, GPR:$incr, i32imm:$ordering),
4382263509Sdim      NoItinerary, []>;
4383200581Srdivacky    def ATOMIC_LOAD_NAND_I16 : PseudoInst<
4384263509Sdim      (outs GPR:$dst),
4385263509Sdim      (ins GPR:$ptr, GPR:$incr, i32imm:$ordering),
4386263509Sdim      NoItinerary, []>;
4387221345Sdim    def ATOMIC_LOAD_MIN_I16 : PseudoInst<
4388263509Sdim      (outs GPR:$dst),
4389263509Sdim      (ins GPR:$ptr, GPR:$val, i32imm:$ordering),
4390263509Sdim      NoItinerary, []>;
4391221345Sdim    def ATOMIC_LOAD_MAX_I16 : PseudoInst<
4392263509Sdim      (outs GPR:$dst),
4393263509Sdim      (ins GPR:$ptr, GPR:$val, i32imm:$ordering),
4394263509Sdim      NoItinerary, []>;
4395221345Sdim    def ATOMIC_LOAD_UMIN_I16 : PseudoInst<
4396263509Sdim      (outs GPR:$dst),
4397263509Sdim      (ins GPR:$ptr, GPR:$val, i32imm:$ordering),
4398263509Sdim      NoItinerary, []>;
4399221345Sdim    def ATOMIC_LOAD_UMAX_I16 : PseudoInst<
4400263509Sdim      (outs GPR:$dst),
4401263509Sdim      (ins GPR:$ptr, GPR:$val, i32imm:$ordering),
4402263509Sdim      NoItinerary, []>;
4403263509Sdim    def ATOMIC_SWAP_I16 : PseudoInst<
4404263509Sdim      (outs GPR:$dst),
4405263509Sdim      (ins GPR:$ptr, GPR:$new, i32imm:$ordering),
4406263509Sdim      NoItinerary, []>;
4407263509Sdim    def ATOMIC_CMP_SWAP_I16 : PseudoInst<
4408263509Sdim      (outs GPR:$dst),
4409263509Sdim      (ins GPR:$ptr, GPR:$old, GPR:$new, i32imm:$ordering),
4410263509Sdim      NoItinerary, []>;
4411200581Srdivacky    def ATOMIC_LOAD_ADD_I32 : PseudoInst<
4412263509Sdim      (outs GPR:$dst),
4413263509Sdim      (ins GPR:$ptr, GPR:$incr, i32imm:$ordering),
4414263509Sdim      NoItinerary, []>;
4415200581Srdivacky    def ATOMIC_LOAD_SUB_I32 : PseudoInst<
4416263509Sdim      (outs GPR:$dst),
4417263509Sdim      (ins GPR:$ptr, GPR:$incr, i32imm:$ordering),
4418263509Sdim      NoItinerary, []>;
4419200581Srdivacky    def ATOMIC_LOAD_AND_I32 : PseudoInst<
4420263509Sdim      (outs GPR:$dst),
4421263509Sdim      (ins GPR:$ptr, GPR:$incr, i32imm:$ordering),
4422263509Sdim      NoItinerary, []>;
4423200581Srdivacky    def ATOMIC_LOAD_OR_I32 : PseudoInst<
4424263509Sdim      (outs GPR:$dst),
4425263509Sdim      (ins GPR:$ptr, GPR:$incr, i32imm:$ordering),
4426263509Sdim      NoItinerary, []>;
4427200581Srdivacky    def ATOMIC_LOAD_XOR_I32 : PseudoInst<
4428263509Sdim      (outs GPR:$dst),
4429263509Sdim      (ins GPR:$ptr, GPR:$incr, i32imm:$ordering),
4430263509Sdim      NoItinerary, []>;
4431200581Srdivacky    def ATOMIC_LOAD_NAND_I32 : PseudoInst<
4432263509Sdim      (outs GPR:$dst),
4433263509Sdim      (ins GPR:$ptr, GPR:$incr, i32imm:$ordering),
4434263509Sdim      NoItinerary, []>;
4435221345Sdim    def ATOMIC_LOAD_MIN_I32 : PseudoInst<
4436263509Sdim      (outs GPR:$dst),
4437263509Sdim      (ins GPR:$ptr, GPR:$val, i32imm:$ordering),
4438263509Sdim      NoItinerary, []>;
4439221345Sdim    def ATOMIC_LOAD_MAX_I32 : PseudoInst<
4440263509Sdim      (outs GPR:$dst),
4441263509Sdim      (ins GPR:$ptr, GPR:$val, i32imm:$ordering),
4442263509Sdim      NoItinerary, []>;
4443221345Sdim    def ATOMIC_LOAD_UMIN_I32 : PseudoInst<
4444263509Sdim      (outs GPR:$dst),
4445263509Sdim      (ins GPR:$ptr, GPR:$val, i32imm:$ordering),
4446263509Sdim      NoItinerary, []>;
4447221345Sdim    def ATOMIC_LOAD_UMAX_I32 : PseudoInst<
4448263509Sdim      (outs GPR:$dst),
4449263509Sdim      (ins GPR:$ptr, GPR:$val, i32imm:$ordering),
4450263509Sdim      NoItinerary, []>;
4451200581Srdivacky    def ATOMIC_SWAP_I32 : PseudoInst<
4452263509Sdim      (outs GPR:$dst),
4453263509Sdim      (ins GPR:$ptr, GPR:$new, i32imm:$ordering),
4454263509Sdim      NoItinerary, []>;
4455200581Srdivacky    def ATOMIC_CMP_SWAP_I32 : PseudoInst<
4456263509Sdim      (outs GPR:$dst),
4457263509Sdim      (ins GPR:$ptr, GPR:$old, GPR:$new, i32imm:$ordering),
4458263509Sdim      NoItinerary, []>;
4459263509Sdim    def ATOMIC_LOAD_ADD_I64 : PseudoInst<
4460263509Sdim      (outs GPR:$dst1, GPR:$dst2),
4461263509Sdim      (ins GPR:$addr, GPR:$src1, GPR:$src2, i32imm:$ordering),
4462263509Sdim      NoItinerary, []>;
4463263509Sdim    def ATOMIC_LOAD_SUB_I64 : PseudoInst<
4464263509Sdim      (outs GPR:$dst1, GPR:$dst2),
4465263509Sdim      (ins GPR:$addr, GPR:$src1, GPR:$src2, i32imm:$ordering),
4466263509Sdim      NoItinerary, []>;
4467263509Sdim    def ATOMIC_LOAD_AND_I64 : PseudoInst<
4468263509Sdim      (outs GPR:$dst1, GPR:$dst2),
4469263509Sdim      (ins GPR:$addr, GPR:$src1, GPR:$src2, i32imm:$ordering),
4470263509Sdim      NoItinerary, []>;
4471263509Sdim    def ATOMIC_LOAD_OR_I64 :  PseudoInst<
4472263509Sdim      (outs GPR:$dst1, GPR:$dst2),
4473263509Sdim      (ins GPR:$addr, GPR:$src1, GPR:$src2, i32imm:$ordering),
4474263509Sdim      NoItinerary, []>;
4475263509Sdim    def ATOMIC_LOAD_XOR_I64 : PseudoInst<
4476263509Sdim      (outs GPR:$dst1, GPR:$dst2),
4477263509Sdim      (ins GPR:$addr, GPR:$src1, GPR:$src2, i32imm:$ordering),
4478263509Sdim      NoItinerary, []>;
4479263509Sdim    def ATOMIC_LOAD_NAND_I64 : PseudoInst<
4480263509Sdim      (outs GPR:$dst1, GPR:$dst2),
4481263509Sdim      (ins GPR:$addr, GPR:$src1, GPR:$src2, i32imm:$ordering),
4482263509Sdim      NoItinerary, []>;
4483263509Sdim    def ATOMIC_LOAD_MIN_I64 : PseudoInst<
4484263509Sdim      (outs GPR:$dst1, GPR:$dst2),
4485263509Sdim      (ins GPR:$addr, GPR:$src1, GPR:$src2, i32imm:$ordering),
4486263509Sdim      NoItinerary, []>;
4487263509Sdim    def ATOMIC_LOAD_MAX_I64 : PseudoInst<
4488263509Sdim      (outs GPR:$dst1, GPR:$dst2),
4489263509Sdim      (ins GPR:$addr, GPR:$src1, GPR:$src2, i32imm:$ordering),
4490263509Sdim      NoItinerary, []>;
4491263509Sdim    def ATOMIC_LOAD_UMIN_I64 : PseudoInst<
4492263509Sdim      (outs GPR:$dst1, GPR:$dst2),
4493263509Sdim      (ins GPR:$addr, GPR:$src1, GPR:$src2, i32imm:$ordering),
4494263509Sdim      NoItinerary, []>;
4495263509Sdim    def ATOMIC_LOAD_UMAX_I64 : PseudoInst<
4496263509Sdim      (outs GPR:$dst1, GPR:$dst2),
4497263509Sdim      (ins GPR:$addr, GPR:$src1, GPR:$src2, i32imm:$ordering),
4498263509Sdim      NoItinerary, []>;
4499263509Sdim    def ATOMIC_SWAP_I64 : PseudoInst<
4500263509Sdim      (outs GPR:$dst1, GPR:$dst2),
4501263509Sdim      (ins GPR:$addr, GPR:$src1, GPR:$src2, i32imm:$ordering),
4502263509Sdim      NoItinerary, []>;
4503263509Sdim    def ATOMIC_CMP_SWAP_I64 : PseudoInst<
4504263509Sdim      (outs GPR:$dst1, GPR:$dst2),
4505263509Sdim      (ins GPR:$addr, GPR:$cmp1, GPR:$cmp2,
4506263509Sdim           GPR:$set1, GPR:$set2, i32imm:$ordering),
4507263509Sdim      NoItinerary, []>;
4508263509Sdim  }
4509263509Sdim  let mayLoad = 1 in
4510263509Sdim    def ATOMIC_LOAD_I64 : PseudoInst<
4511263509Sdim      (outs GPR:$dst1, GPR:$dst2),
4512263509Sdim      (ins GPR:$addr, i32imm:$ordering),
4513263509Sdim      NoItinerary, []>;
4514263509Sdim  let mayStore = 1 in
4515263509Sdim    def ATOMIC_STORE_I64 : PseudoInst<
4516263509Sdim      (outs GPR:$dst1, GPR:$dst2),
4517263509Sdim      (ins GPR:$addr, GPR:$src1, GPR:$src2, i32imm:$ordering),
4518263509Sdim      NoItinerary, []>;
4519200581Srdivacky}
4520200581Srdivacky
4521245431Sdimlet usesCustomInserter = 1 in {
4522245431Sdim    def COPY_STRUCT_BYVAL_I32 : PseudoInst<
4523245431Sdim      (outs), (ins GPR:$dst, GPR:$src, i32imm:$size, i32imm:$alignment),
4524245431Sdim      NoItinerary,
4525245431Sdim      [(ARMcopystructbyval GPR:$dst, GPR:$src, imm:$size, imm:$alignment)]>;
4526245431Sdim}
4527245431Sdim
4528263509Sdimdef ldrex_1 : PatFrag<(ops node:$ptr), (int_arm_ldrex node:$ptr), [{
4529263509Sdim  return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i8;
4530263509Sdim}]>;
4531263509Sdim
4532263509Sdimdef ldrex_2 : PatFrag<(ops node:$ptr), (int_arm_ldrex node:$ptr), [{
4533263509Sdim  return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i16;
4534263509Sdim}]>;
4535263509Sdim
4536263509Sdimdef ldrex_4 : PatFrag<(ops node:$ptr), (int_arm_ldrex node:$ptr), [{
4537263509Sdim  return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i32;
4538263509Sdim}]>;
4539263509Sdim
4540263509Sdimdef strex_1 : PatFrag<(ops node:$val, node:$ptr),
4541263509Sdim                      (int_arm_strex node:$val, node:$ptr), [{
4542263509Sdim  return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i8;
4543263509Sdim}]>;
4544263509Sdim
4545263509Sdimdef strex_2 : PatFrag<(ops node:$val, node:$ptr),
4546263509Sdim                      (int_arm_strex node:$val, node:$ptr), [{
4547263509Sdim  return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i16;
4548263509Sdim}]>;
4549263509Sdim
4550263509Sdimdef strex_4 : PatFrag<(ops node:$val, node:$ptr),
4551263509Sdim                      (int_arm_strex node:$val, node:$ptr), [{
4552263509Sdim  return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i32;
4553263509Sdim}]>;
4554263509Sdim
4555200581Srdivackylet mayLoad = 1 in {
4556226890Sdimdef LDREXB : AIldrex<0b10, (outs GPR:$Rt), (ins addr_offset_none:$addr),
4557263509Sdim                     NoItinerary, "ldrexb", "\t$Rt, $addr",
4558263509Sdim                     [(set GPR:$Rt, (ldrex_1 addr_offset_none:$addr))]>;
4559226890Sdimdef LDREXH : AIldrex<0b11, (outs GPR:$Rt), (ins addr_offset_none:$addr),
4560263509Sdim                     NoItinerary, "ldrexh", "\t$Rt, $addr",
4561263509Sdim                     [(set GPR:$Rt, (ldrex_2 addr_offset_none:$addr))]>;
4562226890Sdimdef LDREX  : AIldrex<0b00, (outs GPR:$Rt), (ins addr_offset_none:$addr),
4563263509Sdim                     NoItinerary, "ldrex", "\t$Rt, $addr",
4564263509Sdim                     [(set GPR:$Rt, (ldrex_4 addr_offset_none:$addr))]>;
4565223017Sdimlet hasExtraDefRegAllocReq = 1 in
4566263509Sdimdef LDREXD : AIldrex<0b01, (outs GPRPairOp:$Rt),(ins addr_offset_none:$addr),
4567252723Sdim                      NoItinerary, "ldrexd", "\t$Rt, $addr", []> {
4568226890Sdim  let DecoderMethod = "DecodeDoubleRegLoad";
4569200581Srdivacky}
4570263509Sdim
4571263509Sdimdef LDAEXB : AIldaex<0b10, (outs GPR:$Rt), (ins addr_offset_none:$addr),
4572263509Sdim                     NoItinerary, "ldaexb", "\t$Rt, $addr", []>;
4573263509Sdimdef LDAEXH : AIldaex<0b11, (outs GPR:$Rt), (ins addr_offset_none:$addr),
4574263509Sdim                     NoItinerary, "ldaexh", "\t$Rt, $addr", []>;
4575263509Sdimdef LDAEX  : AIldaex<0b00, (outs GPR:$Rt), (ins addr_offset_none:$addr),
4576263509Sdim                     NoItinerary, "ldaex", "\t$Rt, $addr", []>;
4577263509Sdimlet hasExtraDefRegAllocReq = 1 in
4578263509Sdimdef LDAEXD : AIldaex<0b01, (outs GPRPairOp:$Rt),(ins addr_offset_none:$addr),
4579263509Sdim                      NoItinerary, "ldaexd", "\t$Rt, $addr", []> {
4580263509Sdim  let DecoderMethod = "DecodeDoubleRegLoad";
4581226890Sdim}
4582263509Sdim}
4583200581Srdivacky
4584218893Sdimlet mayStore = 1, Constraints = "@earlyclobber $Rd" in {
4585226890Sdimdef STREXB: AIstrex<0b10, (outs GPR:$Rd), (ins GPR:$Rt, addr_offset_none:$addr),
4586263509Sdim                    NoItinerary, "strexb", "\t$Rd, $Rt, $addr",
4587263509Sdim                    [(set GPR:$Rd, (strex_1 GPR:$Rt, addr_offset_none:$addr))]>;
4588226890Sdimdef STREXH: AIstrex<0b11, (outs GPR:$Rd), (ins GPR:$Rt, addr_offset_none:$addr),
4589263509Sdim                    NoItinerary, "strexh", "\t$Rd, $Rt, $addr",
4590263509Sdim                    [(set GPR:$Rd, (strex_2 GPR:$Rt, addr_offset_none:$addr))]>;
4591226890Sdimdef STREX : AIstrex<0b00, (outs GPR:$Rd), (ins GPR:$Rt, addr_offset_none:$addr),
4592263509Sdim                    NoItinerary, "strex", "\t$Rd, $Rt, $addr",
4593263509Sdim                    [(set GPR:$Rd, (strex_4 GPR:$Rt, addr_offset_none:$addr))]>;
4594235633Sdimlet hasExtraSrcRegAllocReq = 1 in
4595218893Sdimdef STREXD : AIstrex<0b01, (outs GPR:$Rd),
4596252723Sdim                    (ins GPRPairOp:$Rt, addr_offset_none:$addr),
4597252723Sdim                    NoItinerary, "strexd", "\t$Rd, $Rt, $addr", []> {
4598226890Sdim  let DecoderMethod = "DecodeDoubleRegStore";
4599226890Sdim}
4600263509Sdimdef STLEXB: AIstlex<0b10, (outs GPR:$Rd), (ins GPR:$Rt, addr_offset_none:$addr),
4601263509Sdim                    NoItinerary, "stlexb", "\t$Rd, $Rt, $addr",
4602263509Sdim                    []>;
4603263509Sdimdef STLEXH: AIstlex<0b11, (outs GPR:$Rd), (ins GPR:$Rt, addr_offset_none:$addr),
4604263509Sdim                    NoItinerary, "stlexh", "\t$Rd, $Rt, $addr",
4605263509Sdim                    []>;
4606263509Sdimdef STLEX : AIstlex<0b00, (outs GPR:$Rd), (ins GPR:$Rt, addr_offset_none:$addr),
4607263509Sdim                    NoItinerary, "stlex", "\t$Rd, $Rt, $addr",
4608263509Sdim                    []>;
4609263509Sdimlet hasExtraSrcRegAllocReq = 1 in
4610263509Sdimdef STLEXD : AIstlex<0b01, (outs GPR:$Rd),
4611263509Sdim                    (ins GPRPairOp:$Rt, addr_offset_none:$addr),
4612263509Sdim                    NoItinerary, "stlexd", "\t$Rd, $Rt, $addr", []> {
4613263509Sdim  let DecoderMethod = "DecodeDoubleRegStore";
4614235633Sdim}
4615263509Sdim}
4616200581Srdivacky
4617263509Sdimdef CLREX : AXI<(outs), (ins), MiscFrm, NoItinerary, "clrex",
4618263509Sdim                [(int_arm_clrex)]>,
4619204642Srdivacky            Requires<[IsARM, HasV7]>  {
4620218893Sdim  let Inst{31-0} = 0b11110101011111111111000000011111;
4621204642Srdivacky}
4622204642Srdivacky
4623263509Sdimdef : ARMPat<(and (ldrex_1 addr_offset_none:$addr), 0xff),
4624263509Sdim             (LDREXB addr_offset_none:$addr)>;
4625263509Sdimdef : ARMPat<(and (ldrex_2 addr_offset_none:$addr), 0xffff),
4626263509Sdim             (LDREXH addr_offset_none:$addr)>;
4627263509Sdimdef : ARMPat<(strex_1 (and GPR:$Rt, 0xff), addr_offset_none:$addr),
4628263509Sdim             (STREXB GPR:$Rt, addr_offset_none:$addr)>;
4629263509Sdimdef : ARMPat<(strex_2 (and GPR:$Rt, 0xffff), addr_offset_none:$addr),
4630263509Sdim             (STREXH GPR:$Rt, addr_offset_none:$addr)>;
4631263509Sdim
4632263509Sdimclass acquiring_load<PatFrag base>
4633263509Sdim  : PatFrag<(ops node:$ptr), (base node:$ptr), [{
4634263509Sdim  AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getOrdering();
4635263509Sdim  return Ordering == Acquire || Ordering == SequentiallyConsistent;
4636263509Sdim}]>;
4637263509Sdim
4638263509Sdimdef atomic_load_acquire_8  : acquiring_load<atomic_load_8>;
4639263509Sdimdef atomic_load_acquire_16 : acquiring_load<atomic_load_16>;
4640263509Sdimdef atomic_load_acquire_32 : acquiring_load<atomic_load_32>;
4641263509Sdim
4642263509Sdimclass releasing_store<PatFrag base>
4643263509Sdim  : PatFrag<(ops node:$ptr, node:$val), (base node:$ptr, node:$val), [{
4644263509Sdim  AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getOrdering();
4645263509Sdim  return Ordering == Release || Ordering == SequentiallyConsistent;
4646263509Sdim}]>;
4647263509Sdim
4648263509Sdimdef atomic_store_release_8  : releasing_store<atomic_store_8>;
4649263509Sdimdef atomic_store_release_16 : releasing_store<atomic_store_16>;
4650263509Sdimdef atomic_store_release_32 : releasing_store<atomic_store_32>;
4651263509Sdim
4652263509Sdimlet AddedComplexity = 8 in {
4653263509Sdim  def : ARMPat<(atomic_load_acquire_8 addr_offset_none:$addr),  (LDAB addr_offset_none:$addr)>;
4654263509Sdim  def : ARMPat<(atomic_load_acquire_16 addr_offset_none:$addr), (LDAH addr_offset_none:$addr)>;
4655263509Sdim  def : ARMPat<(atomic_load_acquire_32 addr_offset_none:$addr), (LDA  addr_offset_none:$addr)>;
4656263509Sdim  def : ARMPat<(atomic_store_release_8 addr_offset_none:$addr, GPR:$val),  (STLB GPR:$val, addr_offset_none:$addr)>;
4657263509Sdim  def : ARMPat<(atomic_store_release_16 addr_offset_none:$addr, GPR:$val), (STLH GPR:$val, addr_offset_none:$addr)>;
4658263509Sdim  def : ARMPat<(atomic_store_release_32 addr_offset_none:$addr, GPR:$val), (STL  GPR:$val, addr_offset_none:$addr)>;
4659263509Sdim}
4660263509Sdim
4661226890Sdim// SWP/SWPB are deprecated in V6/V7.
4662226890Sdimlet mayLoad = 1, mayStore = 1 in {
4663245431Sdimdef SWP : AIswp<0, (outs GPRnopc:$Rt),
4664263509Sdim                (ins GPRnopc:$Rt2, addr_offset_none:$addr), "swp", []>,
4665263509Sdim                Requires<[PreV8]>;
4666245431Sdimdef SWPB: AIswp<1, (outs GPRnopc:$Rt),
4667263509Sdim                (ins GPRnopc:$Rt2, addr_offset_none:$addr), "swpb", []>,
4668263509Sdim                Requires<[PreV8]>;
4669203954Srdivacky}
4670203954Srdivacky
4671193323Sed//===----------------------------------------------------------------------===//
4672221345Sdim// Coprocessor Instructions.
4673193323Sed//
4674193323Sed
4675224145Sdimdef CDP : ABI<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1,
4676224145Sdim            c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, imm0_7:$opc2),
4677218893Sdim            NoItinerary, "cdp", "\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2",
4678223017Sdim            [(int_arm_cdp imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn,
4679263509Sdim                          imm:$CRm, imm:$opc2)]>,
4680263509Sdim            Requires<[PreV8]> {
4681218893Sdim  bits<4> opc1;
4682218893Sdim  bits<4> CRn;
4683218893Sdim  bits<4> CRd;
4684218893Sdim  bits<4> cop;
4685218893Sdim  bits<3> opc2;
4686218893Sdim  bits<4> CRm;
4687218893Sdim
4688218893Sdim  let Inst{3-0}   = CRm;
4689218893Sdim  let Inst{4}     = 0;
4690218893Sdim  let Inst{7-5}   = opc2;
4691218893Sdim  let Inst{11-8}  = cop;
4692218893Sdim  let Inst{15-12} = CRd;
4693218893Sdim  let Inst{19-16} = CRn;
4694218893Sdim  let Inst{23-20} = opc1;
4695203954Srdivacky}
4696203954Srdivacky
4697263509Sdimdef CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1,
4698224145Sdim               c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, imm0_7:$opc2),
4699218893Sdim               NoItinerary, "cdp2\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2",
4700223017Sdim               [(int_arm_cdp2 imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn,
4701263509Sdim                              imm:$CRm, imm:$opc2)]>,
4702263509Sdim               Requires<[PreV8]> {
4703203954Srdivacky  let Inst{31-28} = 0b1111;
4704218893Sdim  bits<4> opc1;
4705218893Sdim  bits<4> CRn;
4706218893Sdim  bits<4> CRd;
4707218893Sdim  bits<4> cop;
4708218893Sdim  bits<3> opc2;
4709218893Sdim  bits<4> CRm;
4710218893Sdim
4711218893Sdim  let Inst{3-0}   = CRm;
4712218893Sdim  let Inst{4}     = 0;
4713218893Sdim  let Inst{7-5}   = opc2;
4714218893Sdim  let Inst{11-8}  = cop;
4715218893Sdim  let Inst{15-12} = CRd;
4716218893Sdim  let Inst{19-16} = CRn;
4717218893Sdim  let Inst{23-20} = opc1;
4718203954Srdivacky}
4719203954Srdivacky
4720221345Sdimclass ACI<dag oops, dag iops, string opc, string asm,
4721221345Sdim          IndexMode im = IndexModeNone>
4722226890Sdim  : I<oops, iops, AddrModeNone, 4, im, BrFrm, NoItinerary,
4723226890Sdim      opc, asm, "", []> {
4724226890Sdim  let Inst{27-25} = 0b110;
4725226890Sdim}
4726226890Sdimclass ACInoP<dag oops, dag iops, string opc, string asm,
4727226890Sdim          IndexMode im = IndexModeNone>
4728224145Sdim  : InoP<oops, iops, AddrModeNone, 4, im, BrFrm, NoItinerary,
4729226890Sdim         opc, asm, "", []> {
4730226890Sdim  let Inst{31-28} = 0b1111;
4731204642Srdivacky  let Inst{27-25} = 0b110;
4732204642Srdivacky}
4733226890Sdimmulticlass LdStCop<bit load, bit Dbit, string asm> {
4734226890Sdim  def _OFFSET : ACI<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr),
4735226890Sdim                    asm, "\t$cop, $CRd, $addr"> {
4736226890Sdim    bits<13> addr;
4737226890Sdim    bits<4> cop;
4738226890Sdim    bits<4> CRd;
4739204642Srdivacky    let Inst{24} = 1; // P = 1
4740226890Sdim    let Inst{23} = addr{8};
4741226890Sdim    let Inst{22} = Dbit;
4742204642Srdivacky    let Inst{21} = 0; // W = 0
4743204642Srdivacky    let Inst{20} = load;
4744226890Sdim    let Inst{19-16} = addr{12-9};
4745226890Sdim    let Inst{15-12} = CRd;
4746226890Sdim    let Inst{11-8} = cop;
4747226890Sdim    let Inst{7-0} = addr{7-0};
4748226890Sdim    let DecoderMethod = "DecodeCopMemInstruction";
4749204642Srdivacky  }
4750252723Sdim  def _PRE : ACI<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5_pre:$addr),
4751226890Sdim                 asm, "\t$cop, $CRd, $addr!", IndexModePre> {
4752226890Sdim    bits<13> addr;
4753226890Sdim    bits<4> cop;
4754226890Sdim    bits<4> CRd;
4755204642Srdivacky    let Inst{24} = 1; // P = 1
4756226890Sdim    let Inst{23} = addr{8};
4757226890Sdim    let Inst{22} = Dbit;
4758204642Srdivacky    let Inst{21} = 1; // W = 1
4759204642Srdivacky    let Inst{20} = load;
4760226890Sdim    let Inst{19-16} = addr{12-9};
4761226890Sdim    let Inst{15-12} = CRd;
4762226890Sdim    let Inst{11-8} = cop;
4763226890Sdim    let Inst{7-0} = addr{7-0};
4764226890Sdim    let DecoderMethod = "DecodeCopMemInstruction";
4765204642Srdivacky  }
4766226890Sdim  def _POST: ACI<(outs), (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
4767226890Sdim                              postidx_imm8s4:$offset),
4768226890Sdim                 asm, "\t$cop, $CRd, $addr, $offset", IndexModePost> {
4769226890Sdim    bits<9> offset;
4770226890Sdim    bits<4> addr;
4771226890Sdim    bits<4> cop;
4772226890Sdim    bits<4> CRd;
4773204642Srdivacky    let Inst{24} = 0; // P = 0
4774226890Sdim    let Inst{23} = offset{8};
4775226890Sdim    let Inst{22} = Dbit;
4776204642Srdivacky    let Inst{21} = 1; // W = 1
4777204642Srdivacky    let Inst{20} = load;
4778226890Sdim    let Inst{19-16} = addr;
4779226890Sdim    let Inst{15-12} = CRd;
4780226890Sdim    let Inst{11-8} = cop;
4781226890Sdim    let Inst{7-0} = offset{7-0};
4782226890Sdim    let DecoderMethod = "DecodeCopMemInstruction";
4783204642Srdivacky  }
4784204642Srdivacky  def _OPTION : ACI<(outs),
4785226890Sdim                    (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
4786226890Sdim                         coproc_option_imm:$option),
4787226890Sdim      asm, "\t$cop, $CRd, $addr, $option"> {
4788226890Sdim    bits<8> option;
4789226890Sdim    bits<4> addr;
4790226890Sdim    bits<4> cop;
4791226890Sdim    bits<4> CRd;
4792204642Srdivacky    let Inst{24} = 0; // P = 0
4793204642Srdivacky    let Inst{23} = 1; // U = 1
4794226890Sdim    let Inst{22} = Dbit;
4795204642Srdivacky    let Inst{21} = 0; // W = 0
4796204642Srdivacky    let Inst{20} = load;
4797226890Sdim    let Inst{19-16} = addr;
4798226890Sdim    let Inst{15-12} = CRd;
4799226890Sdim    let Inst{11-8} = cop;
4800226890Sdim    let Inst{7-0} = option;
4801226890Sdim    let DecoderMethod = "DecodeCopMemInstruction";
4802204642Srdivacky  }
4803226890Sdim}
4804226890Sdimmulticlass LdSt2Cop<bit load, bit Dbit, string asm> {
4805226890Sdim  def _OFFSET : ACInoP<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr),
4806226890Sdim                       asm, "\t$cop, $CRd, $addr"> {
4807226890Sdim    bits<13> addr;
4808226890Sdim    bits<4> cop;
4809226890Sdim    bits<4> CRd;
4810204642Srdivacky    let Inst{24} = 1; // P = 1
4811226890Sdim    let Inst{23} = addr{8};
4812226890Sdim    let Inst{22} = Dbit;
4813204642Srdivacky    let Inst{21} = 0; // W = 0
4814204642Srdivacky    let Inst{20} = load;
4815226890Sdim    let Inst{19-16} = addr{12-9};
4816226890Sdim    let Inst{15-12} = CRd;
4817226890Sdim    let Inst{11-8} = cop;
4818226890Sdim    let Inst{7-0} = addr{7-0};
4819226890Sdim    let DecoderMethod = "DecodeCopMemInstruction";
4820204642Srdivacky  }
4821252723Sdim  def _PRE : ACInoP<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5_pre:$addr),
4822226890Sdim                    asm, "\t$cop, $CRd, $addr!", IndexModePre> {
4823226890Sdim    bits<13> addr;
4824226890Sdim    bits<4> cop;
4825226890Sdim    bits<4> CRd;
4826204642Srdivacky    let Inst{24} = 1; // P = 1
4827226890Sdim    let Inst{23} = addr{8};
4828226890Sdim    let Inst{22} = Dbit;
4829204642Srdivacky    let Inst{21} = 1; // W = 1
4830204642Srdivacky    let Inst{20} = load;
4831226890Sdim    let Inst{19-16} = addr{12-9};
4832226890Sdim    let Inst{15-12} = CRd;
4833226890Sdim    let Inst{11-8} = cop;
4834226890Sdim    let Inst{7-0} = addr{7-0};
4835226890Sdim    let DecoderMethod = "DecodeCopMemInstruction";
4836204642Srdivacky  }
4837226890Sdim  def _POST: ACInoP<(outs), (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
4838226890Sdim                                 postidx_imm8s4:$offset),
4839226890Sdim                 asm, "\t$cop, $CRd, $addr, $offset", IndexModePost> {
4840226890Sdim    bits<9> offset;
4841226890Sdim    bits<4> addr;
4842226890Sdim    bits<4> cop;
4843226890Sdim    bits<4> CRd;
4844204642Srdivacky    let Inst{24} = 0; // P = 0
4845226890Sdim    let Inst{23} = offset{8};
4846226890Sdim    let Inst{22} = Dbit;
4847204642Srdivacky    let Inst{21} = 1; // W = 1
4848204642Srdivacky    let Inst{20} = load;
4849226890Sdim    let Inst{19-16} = addr;
4850226890Sdim    let Inst{15-12} = CRd;
4851226890Sdim    let Inst{11-8} = cop;
4852226890Sdim    let Inst{7-0} = offset{7-0};
4853226890Sdim    let DecoderMethod = "DecodeCopMemInstruction";
4854204642Srdivacky  }
4855226890Sdim  def _OPTION : ACInoP<(outs),
4856226890Sdim                       (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
4857226890Sdim                            coproc_option_imm:$option),
4858226890Sdim      asm, "\t$cop, $CRd, $addr, $option"> {
4859226890Sdim    bits<8> option;
4860226890Sdim    bits<4> addr;
4861226890Sdim    bits<4> cop;
4862226890Sdim    bits<4> CRd;
4863204642Srdivacky    let Inst{24} = 0; // P = 0
4864204642Srdivacky    let Inst{23} = 1; // U = 1
4865226890Sdim    let Inst{22} = Dbit;
4866204642Srdivacky    let Inst{21} = 0; // W = 0
4867204642Srdivacky    let Inst{20} = load;
4868226890Sdim    let Inst{19-16} = addr;
4869226890Sdim    let Inst{15-12} = CRd;
4870226890Sdim    let Inst{11-8} = cop;
4871226890Sdim    let Inst{7-0} = option;
4872226890Sdim    let DecoderMethod = "DecodeCopMemInstruction";
4873204642Srdivacky  }
4874204642Srdivacky}
4875204642Srdivacky
4876226890Sdimdefm LDC   : LdStCop <1, 0, "ldc">;
4877226890Sdimdefm LDCL  : LdStCop <1, 1, "ldcl">;
4878226890Sdimdefm STC   : LdStCop <0, 0, "stc">;
4879226890Sdimdefm STCL  : LdStCop <0, 1, "stcl">;
4880263509Sdimdefm LDC2  : LdSt2Cop<1, 0, "ldc2">, Requires<[PreV8]>;
4881263509Sdimdefm LDC2L : LdSt2Cop<1, 1, "ldc2l">, Requires<[PreV8]>;
4882263509Sdimdefm STC2  : LdSt2Cop<0, 0, "stc2">, Requires<[PreV8]>;
4883263509Sdimdefm STC2L : LdSt2Cop<0, 1, "stc2l">, Requires<[PreV8]>;
4884204642Srdivacky
4885218893Sdim//===----------------------------------------------------------------------===//
4886226890Sdim// Move between coprocessor and ARM core register.
4887218893Sdim//
4888218893Sdim
4889223017Sdimclass MovRCopro<string opc, bit direction, dag oops, dag iops,
4890223017Sdim                list<dag> pattern>
4891221345Sdim  : ABI<0b1110, oops, iops, NoItinerary, opc,
4892223017Sdim        "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2", pattern> {
4893218893Sdim  let Inst{20} = direction;
4894203954Srdivacky  let Inst{4} = 1;
4895218893Sdim
4896218893Sdim  bits<4> Rt;
4897218893Sdim  bits<4> cop;
4898218893Sdim  bits<3> opc1;
4899218893Sdim  bits<3> opc2;
4900218893Sdim  bits<4> CRm;
4901218893Sdim  bits<4> CRn;
4902218893Sdim
4903218893Sdim  let Inst{15-12} = Rt;
4904218893Sdim  let Inst{11-8}  = cop;
4905218893Sdim  let Inst{23-21} = opc1;
4906218893Sdim  let Inst{7-5}   = opc2;
4907218893Sdim  let Inst{3-0}   = CRm;
4908218893Sdim  let Inst{19-16} = CRn;
4909203954Srdivacky}
4910203954Srdivacky
4911221345Sdimdef MCR : MovRCopro<"mcr", 0 /* from ARM core register to coprocessor */,
4912223017Sdim                    (outs),
4913224145Sdim                    (ins p_imm:$cop, imm0_7:$opc1, GPR:$Rt, c_imm:$CRn,
4914224145Sdim                         c_imm:$CRm, imm0_7:$opc2),
4915223017Sdim                    [(int_arm_mcr imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn,
4916263509Sdim                                  imm:$CRm, imm:$opc2)]>,
4917263509Sdim                    ComplexDeprecationPredicate<"MCR">;
4918235633Sdimdef : ARMInstAlias<"mcr${p} $cop, $opc1, $Rt, $CRn, $CRm",
4919235633Sdim                   (MCR p_imm:$cop, imm0_7:$opc1, GPR:$Rt, c_imm:$CRn,
4920235633Sdim                        c_imm:$CRm, 0, pred:$p)>;
4921221345Sdimdef MRC : MovRCopro<"mrc", 1 /* from coprocessor to ARM core register */,
4922263509Sdim                    (outs GPRwithAPSR:$Rt),
4923226890Sdim                    (ins p_imm:$cop, imm0_7:$opc1, c_imm:$CRn, c_imm:$CRm,
4924226890Sdim                         imm0_7:$opc2), []>;
4925235633Sdimdef : ARMInstAlias<"mrc${p} $cop, $opc1, $Rt, $CRn, $CRm",
4926263509Sdim                   (MRC GPRwithAPSR:$Rt, p_imm:$cop, imm0_7:$opc1, c_imm:$CRn,
4927235633Sdim                        c_imm:$CRm, 0, pred:$p)>;
4928218893Sdim
4929223017Sdimdef : ARMPat<(int_arm_mrc imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2),
4930223017Sdim             (MRC imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2)>;
4931223017Sdim
4932223017Sdimclass MovRCopro2<string opc, bit direction, dag oops, dag iops,
4933223017Sdim                 list<dag> pattern>
4934221345Sdim  : ABXI<0b1110, oops, iops, NoItinerary,
4935223017Sdim         !strconcat(opc, "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2"), pattern> {
4936263509Sdim  let Inst{31-24} = 0b11111110;
4937218893Sdim  let Inst{20} = direction;
4938203954Srdivacky  let Inst{4} = 1;
4939203954Srdivacky
4940218893Sdim  bits<4> Rt;
4941218893Sdim  bits<4> cop;
4942218893Sdim  bits<3> opc1;
4943218893Sdim  bits<3> opc2;
4944218893Sdim  bits<4> CRm;
4945218893Sdim  bits<4> CRn;
4946203954Srdivacky
4947218893Sdim  let Inst{15-12} = Rt;
4948218893Sdim  let Inst{11-8}  = cop;
4949218893Sdim  let Inst{23-21} = opc1;
4950218893Sdim  let Inst{7-5}   = opc2;
4951218893Sdim  let Inst{3-0}   = CRm;
4952218893Sdim  let Inst{19-16} = CRn;
4953203954Srdivacky}
4954203954Srdivacky
4955221345Sdimdef MCR2 : MovRCopro2<"mcr2", 0 /* from ARM core register to coprocessor */,
4956223017Sdim                      (outs),
4957224145Sdim                      (ins p_imm:$cop, imm0_7:$opc1, GPR:$Rt, c_imm:$CRn,
4958224145Sdim                           c_imm:$CRm, imm0_7:$opc2),
4959223017Sdim                      [(int_arm_mcr2 imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn,
4960263509Sdim                                     imm:$CRm, imm:$opc2)]>,
4961263509Sdim                      Requires<[PreV8]>;
4962235633Sdimdef : ARMInstAlias<"mcr2$ $cop, $opc1, $Rt, $CRn, $CRm",
4963235633Sdim                   (MCR2 p_imm:$cop, imm0_7:$opc1, GPR:$Rt, c_imm:$CRn,
4964235633Sdim                         c_imm:$CRm, 0)>;
4965221345Sdimdef MRC2 : MovRCopro2<"mrc2", 1 /* from coprocessor to ARM core register */,
4966263509Sdim                      (outs GPRwithAPSR:$Rt),
4967226890Sdim                      (ins p_imm:$cop, imm0_7:$opc1, c_imm:$CRn, c_imm:$CRm,
4968263509Sdim                           imm0_7:$opc2), []>,
4969263509Sdim                      Requires<[PreV8]>;
4970235633Sdimdef : ARMInstAlias<"mrc2$ $cop, $opc1, $Rt, $CRn, $CRm",
4971263509Sdim                   (MRC2 GPRwithAPSR:$Rt, p_imm:$cop, imm0_7:$opc1, c_imm:$CRn,
4972235633Sdim                         c_imm:$CRm, 0)>;
4973218893Sdim
4974223017Sdimdef : ARMV5TPat<(int_arm_mrc2 imm:$cop, imm:$opc1, imm:$CRn,
4975223017Sdim                              imm:$CRm, imm:$opc2),
4976223017Sdim                (MRC2 imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2)>;
4977223017Sdim
4978226890Sdimclass MovRRCopro<string opc, bit direction, list<dag> pattern = []>
4979224145Sdim  : ABI<0b1100, (outs), (ins p_imm:$cop, imm0_15:$opc1,
4980235633Sdim        GPRnopc:$Rt, GPRnopc:$Rt2, c_imm:$CRm),
4981223017Sdim        NoItinerary, opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm", pattern> {
4982218893Sdim  let Inst{23-21} = 0b010;
4983218893Sdim  let Inst{20} = direction;
4984218893Sdim
4985218893Sdim  bits<4> Rt;
4986218893Sdim  bits<4> Rt2;
4987218893Sdim  bits<4> cop;
4988218893Sdim  bits<4> opc1;
4989218893Sdim  bits<4> CRm;
4990218893Sdim
4991218893Sdim  let Inst{15-12} = Rt;
4992218893Sdim  let Inst{19-16} = Rt2;
4993218893Sdim  let Inst{11-8}  = cop;
4994218893Sdim  let Inst{7-4}   = opc1;
4995218893Sdim  let Inst{3-0}   = CRm;
4996203954Srdivacky}
4997203954Srdivacky
4998223017Sdimdef MCRR : MovRRCopro<"mcrr", 0 /* from ARM core register to coprocessor */,
4999245431Sdim                      [(int_arm_mcrr imm:$cop, imm:$opc1, GPRnopc:$Rt,
5000245431Sdim                                     GPRnopc:$Rt2, imm:$CRm)]>;
5001218893Sdimdef MRRC : MovRRCopro<"mrrc", 1 /* from coprocessor to ARM core register */>;
5002218893Sdim
5003226890Sdimclass MovRRCopro2<string opc, bit direction, list<dag> pattern = []>
5004224145Sdim  : ABXI<0b1100, (outs), (ins p_imm:$cop, imm0_15:$opc1,
5005235633Sdim         GPRnopc:$Rt, GPRnopc:$Rt2, c_imm:$CRm), NoItinerary,
5006263509Sdim         !strconcat(opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm"), pattern>,
5007263509Sdim    Requires<[PreV8]> {
5008203954Srdivacky  let Inst{31-28} = 0b1111;
5009218893Sdim  let Inst{23-21} = 0b010;
5010218893Sdim  let Inst{20} = direction;
5011203954Srdivacky
5012218893Sdim  bits<4> Rt;
5013218893Sdim  bits<4> Rt2;
5014218893Sdim  bits<4> cop;
5015218893Sdim  bits<4> opc1;
5016218893Sdim  bits<4> CRm;
5017203954Srdivacky
5018218893Sdim  let Inst{15-12} = Rt;
5019218893Sdim  let Inst{19-16} = Rt2;
5020218893Sdim  let Inst{11-8}  = cop;
5021218893Sdim  let Inst{7-4}   = opc1;
5022218893Sdim  let Inst{3-0}   = CRm;
5023235633Sdim
5024235633Sdim  let DecoderMethod = "DecodeMRRC2";
5025203954Srdivacky}
5026203954Srdivacky
5027223017Sdimdef MCRR2 : MovRRCopro2<"mcrr2", 0 /* from ARM core register to coprocessor */,
5028245431Sdim                        [(int_arm_mcrr2 imm:$cop, imm:$opc1, GPRnopc:$Rt,
5029245431Sdim                                        GPRnopc:$Rt2, imm:$CRm)]>;
5030218893Sdimdef MRRC2 : MovRRCopro2<"mrrc2", 1 /* from coprocessor to ARM core register */>;
5031218893Sdim
5032203954Srdivacky//===----------------------------------------------------------------------===//
5033226890Sdim// Move between special register and ARM core register
5034203954Srdivacky//
5035203954Srdivacky
5036218893Sdim// Move to ARM core register from Special Register
5037235633Sdimdef MRS : ABI<0b0001, (outs GPRnopc:$Rd), (ins), NoItinerary,
5038226890Sdim              "mrs", "\t$Rd, apsr", []> {
5039218893Sdim  bits<4> Rd;
5040218893Sdim  let Inst{23-16} = 0b00001111;
5041235633Sdim  let Unpredictable{19-17} = 0b111;
5042235633Sdim
5043218893Sdim  let Inst{15-12} = Rd;
5044235633Sdim
5045235633Sdim  let Inst{11-0} = 0b000000000000;
5046235633Sdim  let Unpredictable{11-0} = 0b110100001111;
5047203954Srdivacky}
5048203954Srdivacky
5049245431Sdimdef : InstAlias<"mrs${p} $Rd, cpsr", (MRS GPRnopc:$Rd, pred:$p)>,
5050245431Sdim         Requires<[IsARM]>;
5051226890Sdim
5052235633Sdim// The MRSsys instruction is the MRS instruction from the ARM ARM,
5053235633Sdim// section B9.3.9, with the R bit set to 1.
5054235633Sdimdef MRSsys : ABI<0b0001, (outs GPRnopc:$Rd), (ins), NoItinerary,
5055226890Sdim                 "mrs", "\t$Rd, spsr", []> {
5056218893Sdim  bits<4> Rd;
5057218893Sdim  let Inst{23-16} = 0b01001111;
5058235633Sdim  let Unpredictable{19-16} = 0b1111;
5059235633Sdim
5060218893Sdim  let Inst{15-12} = Rd;
5061235633Sdim
5062235633Sdim  let Inst{11-0} = 0b000000000000;
5063235633Sdim  let Unpredictable{11-0} = 0b110100001111;
5064203954Srdivacky}
5065203954Srdivacky
5066218893Sdim// Move from ARM core register to Special Register
5067218893Sdim//
5068218893Sdim// No need to have both system and application versions, the encodings are the
5069218893Sdim// same and the assembly parser has no way to distinguish between them. The mask
5070218893Sdim// operand contains the special register (R Bit) in bit 4 and bits 3-0 contains
5071218893Sdim// the mask with the fields to be accessed in the special register.
5072218893Sdimdef MSR : ABI<0b0001, (outs), (ins msr_mask:$mask, GPR:$Rn), NoItinerary,
5073226890Sdim              "msr", "\t$mask, $Rn", []> {
5074218893Sdim  bits<5> mask;
5075218893Sdim  bits<4> Rn;
5076203954Srdivacky
5077218893Sdim  let Inst{23} = 0;
5078218893Sdim  let Inst{22} = mask{4}; // R bit
5079218893Sdim  let Inst{21-20} = 0b10;
5080218893Sdim  let Inst{19-16} = mask{3-0};
5081218893Sdim  let Inst{15-12} = 0b1111;
5082218893Sdim  let Inst{11-4} = 0b00000000;
5083218893Sdim  let Inst{3-0} = Rn;
5084204642Srdivacky}
5085204642Srdivacky
5086218893Sdimdef MSRi : ABI<0b0011, (outs), (ins msr_mask:$mask,  so_imm:$a), NoItinerary,
5087226890Sdim               "msr", "\t$mask, $a", []> {
5088218893Sdim  bits<5> mask;
5089218893Sdim  bits<12> a;
5090204642Srdivacky
5091218893Sdim  let Inst{23} = 0;
5092218893Sdim  let Inst{22} = mask{4}; // R bit
5093218893Sdim  let Inst{21-20} = 0b10;
5094218893Sdim  let Inst{19-16} = mask{3-0};
5095218893Sdim  let Inst{15-12} = 0b1111;
5096218893Sdim  let Inst{11-0} = a;
5097204642Srdivacky}
5098221345Sdim
5099221345Sdim//===----------------------------------------------------------------------===//
5100221345Sdim// TLS Instructions
5101221345Sdim//
5102221345Sdim
5103221345Sdim// __aeabi_read_tp preserves the registers r1-r3.
5104221345Sdim// This is a pseudo inst so that we can get the encoding right,
5105221345Sdim// complete with fixup for the aeabi_read_tp function.
5106221345Sdimlet isCall = 1,
5107221345Sdim  Defs = [R0, R12, LR, CPSR], Uses = [SP] in {
5108221345Sdim  def TPsoft : PseudoInst<(outs), (ins), IIC_Br,
5109263509Sdim               [(set R0, ARMthread_pointer)]>, Sched<[WriteBr]>;
5110221345Sdim}
5111221345Sdim
5112221345Sdim//===----------------------------------------------------------------------===//
5113221345Sdim// SJLJ Exception handling intrinsics
5114221345Sdim//   eh_sjlj_setjmp() is an instruction sequence to store the return
5115221345Sdim//   address and save #0 in R0 for the non-longjmp case.
5116221345Sdim//   Since by its nature we may be coming from some other function to get
5117221345Sdim//   here, and we're using the stack frame for the containing function to
5118221345Sdim//   save/restore registers, we can't keep anything live in regs across
5119221345Sdim//   the eh_sjlj_setjmp(), else it will almost certainly have been tromped upon
5120221345Sdim//   when we get here from a longjmp(). We force everything out of registers
5121221345Sdim//   except for our own input by listing the relevant registers in Defs. By
5122221345Sdim//   doing so, we also cause the prologue/epilogue code to actively preserve
5123221345Sdim//   all of the callee-saved resgisters, which is exactly what we want.
5124221345Sdim//   A constant value is passed in $val, and we use the location as a scratch.
5125221345Sdim//
5126221345Sdim// These are pseudo-instructions and are lowered to individual MC-insts, so
5127221345Sdim// no encoding information is necessary.
5128221345Sdimlet Defs =
5129223017Sdim  [ R0,  R1,  R2,  R3,  R4,  R5,  R6,  R7,  R8,  R9,  R10, R11, R12, LR, CPSR,
5130235633Sdim    Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15 ],
5131235633Sdim  hasSideEffects = 1, isBarrier = 1, usesCustomInserter = 1 in {
5132221345Sdim  def Int_eh_sjlj_setjmp : PseudoInst<(outs), (ins GPR:$src, GPR:$val),
5133221345Sdim                               NoItinerary,
5134221345Sdim                         [(set R0, (ARMeh_sjlj_setjmp GPR:$src, GPR:$val))]>,
5135221345Sdim                           Requires<[IsARM, HasVFP2]>;
5136221345Sdim}
5137221345Sdim
5138221345Sdimlet Defs =
5139223017Sdim  [ R0,  R1,  R2,  R3,  R4,  R5,  R6,  R7,  R8,  R9,  R10, R11, R12, LR, CPSR ],
5140235633Sdim  hasSideEffects = 1, isBarrier = 1, usesCustomInserter = 1 in {
5141221345Sdim  def Int_eh_sjlj_setjmp_nofp : PseudoInst<(outs), (ins GPR:$src, GPR:$val),
5142221345Sdim                                   NoItinerary,
5143221345Sdim                         [(set R0, (ARMeh_sjlj_setjmp GPR:$src, GPR:$val))]>,
5144221345Sdim                                Requires<[IsARM, NoVFP]>;
5145221345Sdim}
5146221345Sdim
5147235633Sdim// FIXME: Non-IOS version(s)
5148221345Sdimlet isBarrier = 1, hasSideEffects = 1, isTerminator = 1,
5149221345Sdim    Defs = [ R7, LR, SP ] in {
5150221345Sdimdef Int_eh_sjlj_longjmp : PseudoInst<(outs), (ins GPR:$src, GPR:$scratch),
5151221345Sdim                             NoItinerary,
5152221345Sdim                         [(ARMeh_sjlj_longjmp GPR:$src, GPR:$scratch)]>,
5153235633Sdim                                Requires<[IsARM, IsIOS]>;
5154221345Sdim}
5155221345Sdim
5156245431Sdim// eh.sjlj.dispatchsetup pseudo-instruction.
5157245431Sdim// This pseudo is used for both ARM and Thumb. Any differences are handled when
5158245431Sdim// the pseudo is expanded (which happens before any passes that need the
5159245431Sdim// instruction size).
5160245431Sdimlet isBarrier = 1 in
5161235633Sdimdef Int_eh_sjlj_dispatchsetup : PseudoInst<(outs), (ins), NoItinerary, []>;
5162221345Sdim
5163235633Sdim
5164221345Sdim//===----------------------------------------------------------------------===//
5165221345Sdim// Non-Instruction Patterns
5166221345Sdim//
5167221345Sdim
5168224145Sdim// ARMv4 indirect branch using (MOVr PC, dst)
5169224145Sdimlet isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in
5170224145Sdim  def MOVPCRX : ARMPseudoExpand<(outs), (ins GPR:$dst),
5171224145Sdim                    4, IIC_Br, [(brind GPR:$dst)],
5172224145Sdim                    (MOVr PC, GPR:$dst, (ops 14, zero_reg), zero_reg)>,
5173263509Sdim                  Requires<[IsARM, NoV4T]>, Sched<[WriteBr]>;
5174224145Sdim
5175221345Sdim// Large immediate handling.
5176221345Sdim
5177221345Sdim// 32-bit immediate using two piece so_imms or movw + movt.
5178221345Sdim// This is a single pseudo instruction, the benefit is that it can be remat'd
5179221345Sdim// as a single unit instead of having to handle reg inputs.
5180221345Sdim// FIXME: Remove this when we can do generalized remat.
5181221345Sdimlet isReMaterializable = 1, isMoveImm = 1 in
5182221345Sdimdef MOVi32imm : PseudoInst<(outs GPR:$dst), (ins i32imm:$src), IIC_iMOVix2,
5183221345Sdim                           [(set GPR:$dst, (arm_i32imm:$src))]>,
5184221345Sdim                           Requires<[IsARM]>;
5185221345Sdim
5186221345Sdim// Pseudo instruction that combines movw + movt + add pc (if PIC).
5187221345Sdim// It also makes it possible to rematerialize the instructions.
5188221345Sdim// FIXME: Remove this when we can do generalized remat and when machine licm
5189221345Sdim// can properly the instructions.
5190221345Sdimlet isReMaterializable = 1 in {
5191221345Sdimdef MOV_ga_pcrel : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr),
5192221345Sdim                              IIC_iMOVix2addpc,
5193221345Sdim                        [(set GPR:$dst, (ARMWrapperPIC tglobaladdr:$addr))]>,
5194221345Sdim                        Requires<[IsARM, UseMovt]>;
5195221345Sdim
5196221345Sdimdef MOV_ga_dyn : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr),
5197221345Sdim                             IIC_iMOVix2,
5198221345Sdim                        [(set GPR:$dst, (ARMWrapperDYN tglobaladdr:$addr))]>,
5199221345Sdim                        Requires<[IsARM, UseMovt]>;
5200221345Sdim
5201221345Sdimlet AddedComplexity = 10 in
5202221345Sdimdef MOV_ga_pcrel_ldr : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr),
5203221345Sdim                                IIC_iMOVix2ld,
5204221345Sdim                    [(set GPR:$dst, (load (ARMWrapperPIC tglobaladdr:$addr)))]>,
5205221345Sdim                    Requires<[IsARM, UseMovt]>;
5206221345Sdim} // isReMaterializable
5207221345Sdim
5208221345Sdim// ConstantPool, GlobalAddress, and JumpTable
5209221345Sdimdef : ARMPat<(ARMWrapper  tglobaladdr :$dst), (LEApcrel tglobaladdr :$dst)>,
5210221345Sdim            Requires<[IsARM, DontUseMovt]>;
5211221345Sdimdef : ARMPat<(ARMWrapper  tconstpool  :$dst), (LEApcrel tconstpool  :$dst)>;
5212221345Sdimdef : ARMPat<(ARMWrapper  tglobaladdr :$dst), (MOVi32imm tglobaladdr :$dst)>,
5213221345Sdim            Requires<[IsARM, UseMovt]>;
5214221345Sdimdef : ARMPat<(ARMWrapperJT tjumptable:$dst, imm:$id),
5215221345Sdim             (LEApcrelJT tjumptable:$dst, imm:$id)>;
5216221345Sdim
5217221345Sdim// TODO: add,sub,and, 3-instr forms?
5218221345Sdim
5219235633Sdim// Tail calls. These patterns also apply to Thumb mode.
5220235633Sdimdef : Pat<(ARMtcret tcGPR:$dst), (TCRETURNri tcGPR:$dst)>;
5221235633Sdimdef : Pat<(ARMtcret (i32 tglobaladdr:$dst)), (TCRETURNdi texternalsym:$dst)>;
5222235633Sdimdef : Pat<(ARMtcret (i32 texternalsym:$dst)), (TCRETURNdi texternalsym:$dst)>;
5223221345Sdim
5224221345Sdim// Direct calls
5225235633Sdimdef : ARMPat<(ARMcall texternalsym:$func), (BL texternalsym:$func)>;
5226235633Sdimdef : ARMPat<(ARMcall_nolink texternalsym:$func),
5227235633Sdim             (BMOVPCB_CALL texternalsym:$func)>;
5228221345Sdim
5229221345Sdim// zextload i1 -> zextload i8
5230221345Sdimdef : ARMPat<(zextloadi1 addrmode_imm12:$addr), (LDRBi12 addrmode_imm12:$addr)>;
5231221345Sdimdef : ARMPat<(zextloadi1 ldst_so_reg:$addr),    (LDRBrs ldst_so_reg:$addr)>;
5232221345Sdim
5233221345Sdim// extload -> zextload
5234221345Sdimdef : ARMPat<(extloadi1 addrmode_imm12:$addr),  (LDRBi12 addrmode_imm12:$addr)>;
5235221345Sdimdef : ARMPat<(extloadi1 ldst_so_reg:$addr),     (LDRBrs ldst_so_reg:$addr)>;
5236221345Sdimdef : ARMPat<(extloadi8 addrmode_imm12:$addr),  (LDRBi12 addrmode_imm12:$addr)>;
5237221345Sdimdef : ARMPat<(extloadi8 ldst_so_reg:$addr),     (LDRBrs ldst_so_reg:$addr)>;
5238221345Sdim
5239221345Sdimdef : ARMPat<(extloadi16 addrmode3:$addr),  (LDRH addrmode3:$addr)>;
5240221345Sdim
5241221345Sdimdef : ARMPat<(extloadi8  addrmodepc:$addr), (PICLDRB addrmodepc:$addr)>;
5242221345Sdimdef : ARMPat<(extloadi16 addrmodepc:$addr), (PICLDRH addrmodepc:$addr)>;
5243221345Sdim
5244221345Sdim// smul* and smla*
5245221345Sdimdef : ARMV5TEPat<(mul (sra (shl GPR:$a, (i32 16)), (i32 16)),
5246221345Sdim                      (sra (shl GPR:$b, (i32 16)), (i32 16))),
5247221345Sdim                 (SMULBB GPR:$a, GPR:$b)>;
5248221345Sdimdef : ARMV5TEPat<(mul sext_16_node:$a, sext_16_node:$b),
5249221345Sdim                 (SMULBB GPR:$a, GPR:$b)>;
5250221345Sdimdef : ARMV5TEPat<(mul (sra (shl GPR:$a, (i32 16)), (i32 16)),
5251221345Sdim                      (sra GPR:$b, (i32 16))),
5252221345Sdim                 (SMULBT GPR:$a, GPR:$b)>;
5253221345Sdimdef : ARMV5TEPat<(mul sext_16_node:$a, (sra GPR:$b, (i32 16))),
5254221345Sdim                 (SMULBT GPR:$a, GPR:$b)>;
5255221345Sdimdef : ARMV5TEPat<(mul (sra GPR:$a, (i32 16)),
5256221345Sdim                      (sra (shl GPR:$b, (i32 16)), (i32 16))),
5257221345Sdim                 (SMULTB GPR:$a, GPR:$b)>;
5258221345Sdimdef : ARMV5TEPat<(mul (sra GPR:$a, (i32 16)), sext_16_node:$b),
5259221345Sdim                (SMULTB GPR:$a, GPR:$b)>;
5260221345Sdimdef : ARMV5TEPat<(sra (mul GPR:$a, (sra (shl GPR:$b, (i32 16)), (i32 16))),
5261221345Sdim                      (i32 16)),
5262221345Sdim                 (SMULWB GPR:$a, GPR:$b)>;
5263221345Sdimdef : ARMV5TEPat<(sra (mul GPR:$a, sext_16_node:$b), (i32 16)),
5264221345Sdim                 (SMULWB GPR:$a, GPR:$b)>;
5265221345Sdim
5266245431Sdimdef : ARMV5MOPat<(add GPR:$acc,
5267221345Sdim                      (mul (sra (shl GPR:$a, (i32 16)), (i32 16)),
5268221345Sdim                           (sra (shl GPR:$b, (i32 16)), (i32 16)))),
5269221345Sdim                 (SMLABB GPR:$a, GPR:$b, GPR:$acc)>;
5270245431Sdimdef : ARMV5MOPat<(add GPR:$acc,
5271221345Sdim                      (mul sext_16_node:$a, sext_16_node:$b)),
5272221345Sdim                 (SMLABB GPR:$a, GPR:$b, GPR:$acc)>;
5273245431Sdimdef : ARMV5MOPat<(add GPR:$acc,
5274221345Sdim                      (mul (sra (shl GPR:$a, (i32 16)), (i32 16)),
5275221345Sdim                           (sra GPR:$b, (i32 16)))),
5276221345Sdim                 (SMLABT GPR:$a, GPR:$b, GPR:$acc)>;
5277245431Sdimdef : ARMV5MOPat<(add GPR:$acc,
5278221345Sdim                      (mul sext_16_node:$a, (sra GPR:$b, (i32 16)))),
5279221345Sdim                 (SMLABT GPR:$a, GPR:$b, GPR:$acc)>;
5280245431Sdimdef : ARMV5MOPat<(add GPR:$acc,
5281221345Sdim                      (mul (sra GPR:$a, (i32 16)),
5282221345Sdim                           (sra (shl GPR:$b, (i32 16)), (i32 16)))),
5283221345Sdim                 (SMLATB GPR:$a, GPR:$b, GPR:$acc)>;
5284245431Sdimdef : ARMV5MOPat<(add GPR:$acc,
5285221345Sdim                      (mul (sra GPR:$a, (i32 16)), sext_16_node:$b)),
5286221345Sdim                 (SMLATB GPR:$a, GPR:$b, GPR:$acc)>;
5287245431Sdimdef : ARMV5MOPat<(add GPR:$acc,
5288221345Sdim                      (sra (mul GPR:$a, (sra (shl GPR:$b, (i32 16)), (i32 16))),
5289221345Sdim                           (i32 16))),
5290221345Sdim                 (SMLAWB GPR:$a, GPR:$b, GPR:$acc)>;
5291245431Sdimdef : ARMV5MOPat<(add GPR:$acc,
5292221345Sdim                      (sra (mul GPR:$a, sext_16_node:$b), (i32 16))),
5293221345Sdim                 (SMLAWB GPR:$a, GPR:$b, GPR:$acc)>;
5294221345Sdim
5295221345Sdim
5296221345Sdim// Pre-v7 uses MCR for synchronization barriers.
5297221345Sdimdef : ARMPat<(ARMMemBarrierMCR GPR:$zero), (MCR 15, 0, GPR:$zero, 7, 10, 5)>,
5298221345Sdim         Requires<[IsARM, HasV6]>;
5299221345Sdim
5300226890Sdim// SXT/UXT with no rotate
5301226890Sdimlet AddedComplexity = 16 in {
5302226890Sdimdef : ARMV6Pat<(and GPR:$Src, 0x000000FF), (UXTB GPR:$Src, 0)>;
5303226890Sdimdef : ARMV6Pat<(and GPR:$Src, 0x0000FFFF), (UXTH GPR:$Src, 0)>;
5304226890Sdimdef : ARMV6Pat<(and GPR:$Src, 0x00FF00FF), (UXTB16 GPR:$Src, 0)>;
5305226890Sdimdef : ARMV6Pat<(add GPR:$Rn, (and GPR:$Rm, 0x00FF)),
5306226890Sdim               (UXTAB GPR:$Rn, GPR:$Rm, 0)>;
5307226890Sdimdef : ARMV6Pat<(add GPR:$Rn, (and GPR:$Rm, 0xFFFF)),
5308226890Sdim               (UXTAH GPR:$Rn, GPR:$Rm, 0)>;
5309226890Sdim}
5310221345Sdim
5311226890Sdimdef : ARMV6Pat<(sext_inreg GPR:$Src, i8),  (SXTB GPR:$Src, 0)>;
5312226890Sdimdef : ARMV6Pat<(sext_inreg GPR:$Src, i16), (SXTH GPR:$Src, 0)>;
5313226890Sdim
5314226890Sdimdef : ARMV6Pat<(add GPR:$Rn, (sext_inreg GPRnopc:$Rm, i8)),
5315226890Sdim               (SXTAB GPR:$Rn, GPRnopc:$Rm, 0)>;
5316226890Sdimdef : ARMV6Pat<(add GPR:$Rn, (sext_inreg GPRnopc:$Rm, i16)),
5317226890Sdim               (SXTAH GPR:$Rn, GPRnopc:$Rm, 0)>;
5318226890Sdim
5319226890Sdim// Atomic load/store patterns
5320226890Sdimdef : ARMPat<(atomic_load_8 ldst_so_reg:$src),
5321226890Sdim             (LDRBrs ldst_so_reg:$src)>;
5322226890Sdimdef : ARMPat<(atomic_load_8 addrmode_imm12:$src),
5323226890Sdim             (LDRBi12 addrmode_imm12:$src)>;
5324226890Sdimdef : ARMPat<(atomic_load_16 addrmode3:$src),
5325226890Sdim             (LDRH addrmode3:$src)>;
5326226890Sdimdef : ARMPat<(atomic_load_32 ldst_so_reg:$src),
5327226890Sdim             (LDRrs ldst_so_reg:$src)>;
5328226890Sdimdef : ARMPat<(atomic_load_32 addrmode_imm12:$src),
5329226890Sdim             (LDRi12 addrmode_imm12:$src)>;
5330226890Sdimdef : ARMPat<(atomic_store_8 ldst_so_reg:$ptr, GPR:$val),
5331226890Sdim             (STRBrs GPR:$val, ldst_so_reg:$ptr)>;
5332226890Sdimdef : ARMPat<(atomic_store_8 addrmode_imm12:$ptr, GPR:$val),
5333226890Sdim             (STRBi12 GPR:$val, addrmode_imm12:$ptr)>;
5334226890Sdimdef : ARMPat<(atomic_store_16 addrmode3:$ptr, GPR:$val),
5335226890Sdim             (STRH GPR:$val, addrmode3:$ptr)>;
5336226890Sdimdef : ARMPat<(atomic_store_32 ldst_so_reg:$ptr, GPR:$val),
5337226890Sdim             (STRrs GPR:$val, ldst_so_reg:$ptr)>;
5338226890Sdimdef : ARMPat<(atomic_store_32 addrmode_imm12:$ptr, GPR:$val),
5339226890Sdim             (STRi12 GPR:$val, addrmode_imm12:$ptr)>;
5340226890Sdim
5341226890Sdim
5342221345Sdim//===----------------------------------------------------------------------===//
5343221345Sdim// Thumb Support
5344221345Sdim//
5345221345Sdim
5346221345Sdiminclude "ARMInstrThumb.td"
5347221345Sdim
5348221345Sdim//===----------------------------------------------------------------------===//
5349221345Sdim// Thumb2 Support
5350221345Sdim//
5351221345Sdim
5352221345Sdiminclude "ARMInstrThumb2.td"
5353221345Sdim
5354221345Sdim//===----------------------------------------------------------------------===//
5355221345Sdim// Floating Point Support
5356221345Sdim//
5357221345Sdim
5358221345Sdiminclude "ARMInstrVFP.td"
5359221345Sdim
5360221345Sdim//===----------------------------------------------------------------------===//
5361221345Sdim// Advanced SIMD (NEON) Support
5362221345Sdim//
5363221345Sdim
5364221345Sdiminclude "ARMInstrNEON.td"
5365221345Sdim
5366224145Sdim//===----------------------------------------------------------------------===//
5367224145Sdim// Assembler aliases
5368224145Sdim//
5369224145Sdim
5370224145Sdim// Memory barriers
5371224145Sdimdef : InstAlias<"dmb", (DMB 0xf)>, Requires<[IsARM, HasDB]>;
5372224145Sdimdef : InstAlias<"dsb", (DSB 0xf)>, Requires<[IsARM, HasDB]>;
5373224145Sdimdef : InstAlias<"isb", (ISB 0xf)>, Requires<[IsARM, HasDB]>;
5374224145Sdim
5375224145Sdim// System instructions
5376224145Sdimdef : MnemonicAlias<"swi", "svc">;
5377224145Sdim
5378224145Sdim// Load / Store Multiple
5379224145Sdimdef : MnemonicAlias<"ldmfd", "ldm">;
5380224145Sdimdef : MnemonicAlias<"ldmia", "ldm">;
5381226890Sdimdef : MnemonicAlias<"ldmea", "ldmdb">;
5382224145Sdimdef : MnemonicAlias<"stmfd", "stmdb">;
5383224145Sdimdef : MnemonicAlias<"stmia", "stm">;
5384224145Sdimdef : MnemonicAlias<"stmea", "stm">;
5385224145Sdim
5386226890Sdim// PKHBT/PKHTB with default shift amount. PKHTB is equivalent to PKHBT when the
5387226890Sdim// shift amount is zero (i.e., unspecified).
5388226890Sdimdef : InstAlias<"pkhbt${p} $Rd, $Rn, $Rm",
5389226890Sdim                (PKHBT GPRnopc:$Rd, GPRnopc:$Rn, GPRnopc:$Rm, 0, pred:$p)>,
5390226890Sdim        Requires<[IsARM, HasV6]>;
5391226890Sdimdef : InstAlias<"pkhtb${p} $Rd, $Rn, $Rm",
5392226890Sdim                (PKHBT GPRnopc:$Rd, GPRnopc:$Rn, GPRnopc:$Rm, 0, pred:$p)>,
5393226890Sdim        Requires<[IsARM, HasV6]>;
5394226890Sdim
5395226890Sdim// PUSH/POP aliases for STM/LDM
5396226890Sdimdef : ARMInstAlias<"push${p} $regs", (STMDB_UPD SP, pred:$p, reglist:$regs)>;
5397226890Sdimdef : ARMInstAlias<"pop${p} $regs", (LDMIA_UPD SP, pred:$p, reglist:$regs)>;
5398226890Sdim
5399226890Sdim// SSAT/USAT optional shift operand.
5400226890Sdimdef : ARMInstAlias<"ssat${p} $Rd, $sat_imm, $Rn",
5401226890Sdim                (SSAT GPRnopc:$Rd, imm1_32:$sat_imm, GPRnopc:$Rn, 0, pred:$p)>;
5402226890Sdimdef : ARMInstAlias<"usat${p} $Rd, $sat_imm, $Rn",
5403226890Sdim                (USAT GPRnopc:$Rd, imm0_31:$sat_imm, GPRnopc:$Rn, 0, pred:$p)>;
5404226890Sdim
5405226890Sdim
5406226890Sdim// Extend instruction optional rotate operand.
5407226890Sdimdef : ARMInstAlias<"sxtab${p} $Rd, $Rn, $Rm",
5408226890Sdim                (SXTAB GPRnopc:$Rd, GPR:$Rn, GPRnopc:$Rm, 0, pred:$p)>;
5409226890Sdimdef : ARMInstAlias<"sxtah${p} $Rd, $Rn, $Rm",
5410226890Sdim                (SXTAH GPRnopc:$Rd, GPR:$Rn, GPRnopc:$Rm, 0, pred:$p)>;
5411226890Sdimdef : ARMInstAlias<"sxtab16${p} $Rd, $Rn, $Rm",
5412226890Sdim                (SXTAB16 GPRnopc:$Rd, GPR:$Rn, GPRnopc:$Rm, 0, pred:$p)>;
5413226890Sdimdef : ARMInstAlias<"sxtb${p} $Rd, $Rm",
5414226890Sdim                (SXTB GPRnopc:$Rd, GPRnopc:$Rm, 0, pred:$p)>;
5415226890Sdimdef : ARMInstAlias<"sxtb16${p} $Rd, $Rm",
5416226890Sdim                (SXTB16 GPRnopc:$Rd, GPRnopc:$Rm, 0, pred:$p)>;
5417226890Sdimdef : ARMInstAlias<"sxth${p} $Rd, $Rm",
5418226890Sdim                (SXTH GPRnopc:$Rd, GPRnopc:$Rm, 0, pred:$p)>;
5419226890Sdim
5420226890Sdimdef : ARMInstAlias<"uxtab${p} $Rd, $Rn, $Rm",
5421226890Sdim                (UXTAB GPRnopc:$Rd, GPR:$Rn, GPRnopc:$Rm, 0, pred:$p)>;
5422226890Sdimdef : ARMInstAlias<"uxtah${p} $Rd, $Rn, $Rm",
5423226890Sdim                (UXTAH GPRnopc:$Rd, GPR:$Rn, GPRnopc:$Rm, 0, pred:$p)>;
5424226890Sdimdef : ARMInstAlias<"uxtab16${p} $Rd, $Rn, $Rm",
5425226890Sdim                (UXTAB16 GPRnopc:$Rd, GPR:$Rn, GPRnopc:$Rm, 0, pred:$p)>;
5426226890Sdimdef : ARMInstAlias<"uxtb${p} $Rd, $Rm",
5427226890Sdim                (UXTB GPRnopc:$Rd, GPRnopc:$Rm, 0, pred:$p)>;
5428226890Sdimdef : ARMInstAlias<"uxtb16${p} $Rd, $Rm",
5429226890Sdim                (UXTB16 GPRnopc:$Rd, GPRnopc:$Rm, 0, pred:$p)>;
5430226890Sdimdef : ARMInstAlias<"uxth${p} $Rd, $Rm",
5431226890Sdim                (UXTH GPRnopc:$Rd, GPRnopc:$Rm, 0, pred:$p)>;
5432226890Sdim
5433226890Sdim
5434226890Sdim// RFE aliases
5435226890Sdimdef : MnemonicAlias<"rfefa", "rfeda">;
5436226890Sdimdef : MnemonicAlias<"rfeea", "rfedb">;
5437226890Sdimdef : MnemonicAlias<"rfefd", "rfeia">;
5438226890Sdimdef : MnemonicAlias<"rfeed", "rfeib">;
5439226890Sdimdef : MnemonicAlias<"rfe", "rfeia">;
5440226890Sdim
5441226890Sdim// SRS aliases
5442263509Sdimdef : MnemonicAlias<"srsfa", "srsib">;
5443263509Sdimdef : MnemonicAlias<"srsea", "srsia">;
5444263509Sdimdef : MnemonicAlias<"srsfd", "srsdb">;
5445263509Sdimdef : MnemonicAlias<"srsed", "srsda">;
5446226890Sdimdef : MnemonicAlias<"srs", "srsia">;
5447226890Sdim
5448226890Sdim// QSAX == QSUBADDX
5449226890Sdimdef : MnemonicAlias<"qsubaddx", "qsax">;
5450226890Sdim// SASX == SADDSUBX
5451226890Sdimdef : MnemonicAlias<"saddsubx", "sasx">;
5452226890Sdim// SHASX == SHADDSUBX
5453226890Sdimdef : MnemonicAlias<"shaddsubx", "shasx">;
5454226890Sdim// SHSAX == SHSUBADDX
5455226890Sdimdef : MnemonicAlias<"shsubaddx", "shsax">;
5456226890Sdim// SSAX == SSUBADDX
5457226890Sdimdef : MnemonicAlias<"ssubaddx", "ssax">;
5458226890Sdim// UASX == UADDSUBX
5459226890Sdimdef : MnemonicAlias<"uaddsubx", "uasx">;
5460226890Sdim// UHASX == UHADDSUBX
5461226890Sdimdef : MnemonicAlias<"uhaddsubx", "uhasx">;
5462226890Sdim// UHSAX == UHSUBADDX
5463226890Sdimdef : MnemonicAlias<"uhsubaddx", "uhsax">;
5464226890Sdim// UQASX == UQADDSUBX
5465226890Sdimdef : MnemonicAlias<"uqaddsubx", "uqasx">;
5466226890Sdim// UQSAX == UQSUBADDX
5467226890Sdimdef : MnemonicAlias<"uqsubaddx", "uqsax">;
5468226890Sdim// USAX == USUBADDX
5469226890Sdimdef : MnemonicAlias<"usubaddx", "usax">;
5470226890Sdim
5471235633Sdim// "mov Rd, so_imm_not" can be handled via "mvn" in assembly, just like
5472235633Sdim// for isel.
5473235633Sdimdef : ARMInstAlias<"mov${s}${p} $Rd, $imm",
5474235633Sdim                   (MVNi rGPR:$Rd, so_imm_not:$imm, pred:$p, cc_out:$s)>;
5475235633Sdimdef : ARMInstAlias<"mvn${s}${p} $Rd, $imm",
5476235633Sdim                   (MOVi rGPR:$Rd, so_imm_not:$imm, pred:$p, cc_out:$s)>;
5477235633Sdim// Same for AND <--> BIC
5478235633Sdimdef : ARMInstAlias<"bic${s}${p} $Rd, $Rn, $imm",
5479235633Sdim                   (ANDri rGPR:$Rd, rGPR:$Rn, so_imm_not:$imm,
5480235633Sdim                          pred:$p, cc_out:$s)>;
5481235633Sdimdef : ARMInstAlias<"bic${s}${p} $Rdn, $imm",
5482235633Sdim                   (ANDri rGPR:$Rdn, rGPR:$Rdn, so_imm_not:$imm,
5483235633Sdim                          pred:$p, cc_out:$s)>;
5484235633Sdimdef : ARMInstAlias<"and${s}${p} $Rd, $Rn, $imm",
5485235633Sdim                   (BICri rGPR:$Rd, rGPR:$Rn, so_imm_not:$imm,
5486235633Sdim                          pred:$p, cc_out:$s)>;
5487235633Sdimdef : ARMInstAlias<"and${s}${p} $Rdn, $imm",
5488235633Sdim                   (BICri rGPR:$Rdn, rGPR:$Rdn, so_imm_not:$imm,
5489235633Sdim                          pred:$p, cc_out:$s)>;
5490235633Sdim
5491235633Sdim// Likewise, "add Rd, so_imm_neg" -> sub
5492235633Sdimdef : ARMInstAlias<"add${s}${p} $Rd, $Rn, $imm",
5493235633Sdim                 (SUBri GPR:$Rd, GPR:$Rn, so_imm_neg:$imm, pred:$p, cc_out:$s)>;
5494235633Sdimdef : ARMInstAlias<"add${s}${p} $Rd, $imm",
5495235633Sdim                 (SUBri GPR:$Rd, GPR:$Rd, so_imm_neg:$imm, pred:$p, cc_out:$s)>;
5496235633Sdim// Same for CMP <--> CMN via so_imm_neg
5497235633Sdimdef : ARMInstAlias<"cmp${p} $Rd, $imm",
5498245431Sdim                   (CMNri rGPR:$Rd, so_imm_neg:$imm, pred:$p)>;
5499235633Sdimdef : ARMInstAlias<"cmn${p} $Rd, $imm",
5500235633Sdim                   (CMPri rGPR:$Rd, so_imm_neg:$imm, pred:$p)>;
5501235633Sdim
5502235633Sdim// The shifter forms of the MOV instruction are aliased to the ASR, LSL,
5503235633Sdim// LSR, ROR, and RRX instructions.
5504235633Sdim// FIXME: We need C++ parser hooks to map the alias to the MOV
5505235633Sdim//        encoding. It seems we should be able to do that sort of thing
5506235633Sdim//        in tblgen, but it could get ugly.
5507245431Sdimlet TwoOperandAliasConstraint = "$Rm = $Rd" in {
5508235633Sdimdef ASRi : ARMAsmPseudo<"asr${s}${p} $Rd, $Rm, $imm",
5509235633Sdim                        (ins GPR:$Rd, GPR:$Rm, imm0_32:$imm, pred:$p,
5510235633Sdim                             cc_out:$s)>;
5511235633Sdimdef LSRi : ARMAsmPseudo<"lsr${s}${p} $Rd, $Rm, $imm",
5512235633Sdim                        (ins GPR:$Rd, GPR:$Rm, imm0_32:$imm, pred:$p,
5513235633Sdim                             cc_out:$s)>;
5514235633Sdimdef LSLi : ARMAsmPseudo<"lsl${s}${p} $Rd, $Rm, $imm",
5515235633Sdim                        (ins GPR:$Rd, GPR:$Rm, imm0_31:$imm, pred:$p,
5516235633Sdim                             cc_out:$s)>;
5517235633Sdimdef RORi : ARMAsmPseudo<"ror${s}${p} $Rd, $Rm, $imm",
5518235633Sdim                        (ins GPR:$Rd, GPR:$Rm, imm0_31:$imm, pred:$p,
5519235633Sdim                             cc_out:$s)>;
5520245431Sdim}
5521235633Sdimdef RRXi : ARMAsmPseudo<"rrx${s}${p} $Rd, $Rm",
5522263509Sdim                        (ins GPR:$Rd, GPR:$Rm, pred:$p, cc_out:$s)>;
5523245431Sdimlet TwoOperandAliasConstraint = "$Rn = $Rd" in {
5524235633Sdimdef ASRr : ARMAsmPseudo<"asr${s}${p} $Rd, $Rn, $Rm",
5525235633Sdim                        (ins GPRnopc:$Rd, GPRnopc:$Rn, GPRnopc:$Rm, pred:$p,
5526235633Sdim                             cc_out:$s)>;
5527235633Sdimdef LSRr : ARMAsmPseudo<"lsr${s}${p} $Rd, $Rn, $Rm",
5528235633Sdim                        (ins GPRnopc:$Rd, GPRnopc:$Rn, GPRnopc:$Rm, pred:$p,
5529235633Sdim                             cc_out:$s)>;
5530235633Sdimdef LSLr : ARMAsmPseudo<"lsl${s}${p} $Rd, $Rn, $Rm",
5531235633Sdim                        (ins GPRnopc:$Rd, GPRnopc:$Rn, GPRnopc:$Rm, pred:$p,
5532235633Sdim                             cc_out:$s)>;
5533235633Sdimdef RORr : ARMAsmPseudo<"ror${s}${p} $Rd, $Rn, $Rm",
5534235633Sdim                        (ins GPRnopc:$Rd, GPRnopc:$Rn, GPRnopc:$Rm, pred:$p,
5535235633Sdim                             cc_out:$s)>;
5536245431Sdim}
5537235633Sdim
5538235633Sdim// "neg" is and alias for "rsb rd, rn, #0"
5539235633Sdimdef : ARMInstAlias<"neg${s}${p} $Rd, $Rm",
5540235633Sdim                   (RSBri GPR:$Rd, GPR:$Rm, 0, pred:$p, cc_out:$s)>;
5541235633Sdim
5542235633Sdim// Pre-v6, 'mov r0, r0' was used as a NOP encoding.
5543235633Sdimdef : InstAlias<"nop${p}", (MOVr R0, R0, pred:$p, zero_reg)>,
5544235633Sdim         Requires<[IsARM, NoV6]>;
5545235633Sdim
5546235633Sdim// UMULL/SMULL are available on all arches, but the instruction definitions
5547235633Sdim// need difference constraints pre-v6. Use these aliases for the assembly
5548235633Sdim// parsing on pre-v6.
5549235633Sdimdef : InstAlias<"smull${s}${p} $RdLo, $RdHi, $Rn, $Rm",
5550235633Sdim            (SMULL GPR:$RdLo, GPR:$RdHi, GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s)>,
5551235633Sdim         Requires<[IsARM, NoV6]>;
5552235633Sdimdef : InstAlias<"umull${s}${p} $RdLo, $RdHi, $Rn, $Rm",
5553235633Sdim            (UMULL GPR:$RdLo, GPR:$RdHi, GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s)>,
5554235633Sdim         Requires<[IsARM, NoV6]>;
5555235633Sdim
5556235633Sdim// 'it' blocks in ARM mode just validate the predicates. The IT itself
5557235633Sdim// is discarded.
5558263509Sdimdef ITasm : ARMAsmPseudo<"it$mask $cc", (ins it_pred:$cc, it_mask:$mask)>,
5559263509Sdim         ComplexDeprecationPredicate<"IT">;
5560