AArch64InstrInfo.td revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
1//===----- AArch64InstrInfo.td - AArch64 Instruction Info ----*- tablegen -*-=//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file describes the AArch64 scalar instructions in TableGen format.
11//
12//===----------------------------------------------------------------------===//
13
14//===----------------------------------------------------------------------===//
15// ARM Instruction Predicate Definitions.
16//
17def HasFPARMv8       : Predicate<"Subtarget->hasFPARMv8()">,
18                               AssemblerPredicate<"FeatureFPARMv8", "fp-armv8">;
19def HasNEON          : Predicate<"Subtarget->hasNEON()">,
20                                 AssemblerPredicate<"FeatureNEON", "neon">;
21def HasCrypto        : Predicate<"Subtarget->hasCrypto()">,
22                                 AssemblerPredicate<"FeatureCrypto","crypto">;
23
24// Use fused MAC if more precision in FP computation is allowed.
25def UseFusedMAC      : Predicate<"(TM.Options.AllowFPOpFusion =="
26                                 " FPOpFusion::Fast)">;
27include "AArch64InstrFormats.td"
28
29//===----------------------------------------------------------------------===//
30//  AArch64 specific pattern fragments.
31//
32// An 'fmul' node with a single use.
33def fmul_su : PatFrag<(ops node:$lhs, node:$rhs), (fmul node:$lhs, node:$rhs),[{
34  return N->hasOneUse();
35}]>;
36
37
38//===----------------------------------------------------------------------===//
39// Target-specific ISD nodes and profiles
40//===----------------------------------------------------------------------===//
41
42def SDT_A64ret : SDTypeProfile<0, 0, []>;
43def A64ret : SDNode<"AArch64ISD::Ret", SDT_A64ret, [SDNPHasChain,
44                                                    SDNPOptInGlue,
45                                                    SDNPVariadic]>;
46
47// (ins NZCV, Condition, Dest)
48def SDT_A64br_cc : SDTypeProfile<0, 3, [SDTCisVT<0, i32>]>;
49def A64br_cc : SDNode<"AArch64ISD::BR_CC", SDT_A64br_cc, [SDNPHasChain]>;
50
51// (outs Result), (ins NZCV, IfTrue, IfFalse, Condition)
52def SDT_A64select_cc : SDTypeProfile<1, 4, [SDTCisVT<1, i32>,
53                                            SDTCisSameAs<0, 2>,
54                                            SDTCisSameAs<2, 3>]>;
55def A64select_cc : SDNode<"AArch64ISD::SELECT_CC", SDT_A64select_cc>;
56
57// (outs NZCV), (ins LHS, RHS, Condition)
58def SDT_A64setcc : SDTypeProfile<1, 3, [SDTCisVT<0, i32>,
59                                        SDTCisSameAs<1, 2>]>;
60def A64setcc : SDNode<"AArch64ISD::SETCC", SDT_A64setcc>;
61
62
63// (outs GPR64), (ins)
64def A64threadpointer : SDNode<"AArch64ISD::THREAD_POINTER", SDTPtrLeaf>;
65
66// A64 compares don't care about the cond really (they set all flags) so a
67// simple binary operator is useful.
68def A64cmp : PatFrag<(ops node:$lhs, node:$rhs),
69                     (A64setcc node:$lhs, node:$rhs, cond)>;
70
71
72// When matching a notional (CMP op1, (sub 0, op2)), we'd like to use a CMN
73// instruction on the grounds that "op1 - (-op2) == op1 + op2". However, the C
74// and V flags can be set differently by this operation. It comes down to
75// whether "SInt(~op2)+1 == SInt(~op2+1)" (and the same for UInt). If they are
76// then everything is fine. If not then the optimization is wrong. Thus general
77// comparisons are only valid if op2 != 0.
78
79// So, finally, the only LLVM-native comparisons that don't mention C and V are
80// SETEQ and SETNE. They're the only ones we can safely use CMN for in the
81// absence of information about op2.
82def equality_cond : PatLeaf<(cond), [{
83  return N->get() == ISD::SETEQ || N->get() == ISD::SETNE;
84}]>;
85
86def A64cmn : PatFrag<(ops node:$lhs, node:$rhs),
87                     (A64setcc node:$lhs, (sub 0, node:$rhs), equality_cond)>;
88
89// There are two layers of indirection here, driven by the following
90// considerations.
91//     + TableGen does not know CodeModel or Reloc so that decision should be
92//       made for a variable/address at ISelLowering.
93//     + The output of ISelLowering should be selectable (hence the Wrapper,
94//       rather than a bare target opcode)
95def SDTAArch64WrapperLarge : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>,
96                                                  SDTCisSameAs<0, 2>,
97                                                  SDTCisSameAs<0, 3>,
98                                                  SDTCisSameAs<0, 4>,
99                                                  SDTCisPtrTy<0>]>;
100
101def A64WrapperLarge :SDNode<"AArch64ISD::WrapperLarge", SDTAArch64WrapperLarge>;
102
103def SDTAArch64WrapperSmall : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>,
104                                                  SDTCisSameAs<1, 2>,
105                                                  SDTCisVT<3, i32>,
106                                                  SDTCisPtrTy<0>]>;
107
108def A64WrapperSmall :SDNode<"AArch64ISD::WrapperSmall", SDTAArch64WrapperSmall>;
109
110
111def SDTAArch64GOTLoad : SDTypeProfile<1, 1, [SDTCisPtrTy<0>, SDTCisPtrTy<1>]>;
112def A64GOTLoad : SDNode<"AArch64ISD::GOTLoad", SDTAArch64GOTLoad,
113                        [SDNPHasChain]>;
114
115
116// (A64BFI LHS, RHS, LSB, Width)
117def SDTA64BFI : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>,
118                                     SDTCisSameAs<1, 2>,
119                                     SDTCisVT<3, i64>,
120                                     SDTCisVT<4, i64>]>;
121
122def A64Bfi : SDNode<"AArch64ISD::BFI", SDTA64BFI>;
123
124// (A64EXTR HiReg, LoReg, LSB)
125def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>,
126                                      SDTCisVT<3, i64>]>;
127def A64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
128
129// (A64[SU]BFX Field, ImmR, ImmS).
130//
131// Note that ImmR and ImmS are already encoded for the actual instructions. The
132// more natural LSB and Width mix together to form ImmR and ImmS, something
133// which TableGen can't handle.
134def SDTA64BFX : SDTypeProfile<1, 3, [SDTCisVT<2, i64>, SDTCisVT<3, i64>]>;
135def A64Sbfx : SDNode<"AArch64ISD::SBFX", SDTA64BFX>;
136
137def A64Ubfx : SDNode<"AArch64ISD::UBFX", SDTA64BFX>;
138
139class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
140
141//===----------------------------------------------------------------------===//
142// Call sequence pseudo-instructions
143//===----------------------------------------------------------------------===//
144
145
146def SDT_AArch64Call : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
147def AArch64Call : SDNode<"AArch64ISD::Call", SDT_AArch64Call,
148                     [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, SDNPVariadic]>;
149
150def AArch64tcret : SDNode<"AArch64ISD::TC_RETURN", SDT_AArch64Call,
151                          [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
152
153// The TLSDESCCALL node is a variant call which goes to an indirectly calculated
154// destination but needs a relocation against a fixed symbol. As such it has two
155// certain operands: the callee and the relocated variable.
156//
157// The TLS ABI only allows it to be selected to a BLR instructin (with
158// appropriate relocation).
159def SDTTLSDescCall : SDTypeProfile<0, -2, [SDTCisPtrTy<0>, SDTCisPtrTy<1>]>;
160
161def A64tlsdesc_blr : SDNode<"AArch64ISD::TLSDESCCALL", SDTTLSDescCall,
162                            [SDNPInGlue, SDNPOutGlue, SDNPHasChain,
163                             SDNPVariadic]>;
164
165
166def SDT_AArch64CallSeqStart : SDCallSeqStart<[ SDTCisPtrTy<0> ]>;
167def AArch64callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_AArch64CallSeqStart,
168                                  [SDNPHasChain, SDNPOutGlue]>;
169
170def SDT_AArch64CallSeqEnd   : SDCallSeqEnd<[ SDTCisPtrTy<0>, SDTCisPtrTy<1> ]>;
171def AArch64callseq_end : SDNode<"ISD::CALLSEQ_END",   SDT_AArch64CallSeqEnd,
172                                [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
173
174
175
176// These pseudo-instructions have special semantics by virtue of being passed to
177// the InstrInfo constructor. CALLSEQ_START/CALLSEQ_END are produced by
178// LowerCall to (in our case) tell the back-end about stack adjustments for
179// arguments passed on the stack. Here we select those markers to
180// pseudo-instructions which explicitly set the stack, and finally in the
181// RegisterInfo we convert them to a true stack adjustment.
182let Defs = [XSP], Uses = [XSP] in {
183  def ADJCALLSTACKDOWN : PseudoInst<(outs), (ins i64imm:$amt),
184                                    [(AArch64callseq_start timm:$amt)]>;
185
186  def ADJCALLSTACKUP : PseudoInst<(outs), (ins i64imm:$amt1, i64imm:$amt2),
187                                 [(AArch64callseq_end timm:$amt1, timm:$amt2)]>;
188}
189
190//===----------------------------------------------------------------------===//
191// Atomic operation pseudo-instructions
192//===----------------------------------------------------------------------===//
193
194// These get selected from C++ code as a pretty much direct translation from the
195// generic DAG nodes. The one exception is the AtomicOrdering is added as an
196// operand so that the eventual lowering can make use of it and choose
197// acquire/release operations when required.
198
199let usesCustomInserter = 1, hasCtrlDep = 1, mayLoad = 1, mayStore = 1 in {
200multiclass AtomicSizes {
201  def _I8 : PseudoInst<(outs GPR32:$dst),
202                       (ins GPR64xsp:$ptr, GPR32:$incr, i32imm:$ordering), []>;
203  def _I16 : PseudoInst<(outs GPR32:$dst),
204                        (ins GPR64xsp:$ptr, GPR32:$incr, i32imm:$ordering), []>;
205  def _I32 : PseudoInst<(outs GPR32:$dst),
206                        (ins GPR64xsp:$ptr, GPR32:$incr, i32imm:$ordering), []>;
207  def _I64 : PseudoInst<(outs GPR64:$dst),
208                        (ins GPR64xsp:$ptr, GPR64:$incr, i32imm:$ordering), []>;
209}
210}
211
212defm ATOMIC_LOAD_ADD  : AtomicSizes;
213defm ATOMIC_LOAD_SUB  : AtomicSizes;
214defm ATOMIC_LOAD_AND  : AtomicSizes;
215defm ATOMIC_LOAD_OR   : AtomicSizes;
216defm ATOMIC_LOAD_XOR  : AtomicSizes;
217defm ATOMIC_LOAD_NAND : AtomicSizes;
218defm ATOMIC_SWAP      : AtomicSizes;
219let Defs = [NZCV] in {
220  // These operations need a CMP to calculate the correct value
221  defm ATOMIC_LOAD_MIN  : AtomicSizes;
222  defm ATOMIC_LOAD_MAX  : AtomicSizes;
223  defm ATOMIC_LOAD_UMIN : AtomicSizes;
224  defm ATOMIC_LOAD_UMAX : AtomicSizes;
225}
226
227class AtomicCmpSwap<RegisterClass GPRData>
228  : PseudoInst<(outs GPRData:$dst),
229               (ins GPR64xsp:$ptr, GPRData:$old, GPRData:$new,
230                    i32imm:$ordering), []> {
231  let usesCustomInserter = 1;
232  let hasCtrlDep = 1;
233  let mayLoad = 1;
234  let mayStore = 1;
235  let Defs = [NZCV];
236}
237
238def ATOMIC_CMP_SWAP_I8  : AtomicCmpSwap<GPR32>;
239def ATOMIC_CMP_SWAP_I16 : AtomicCmpSwap<GPR32>;
240def ATOMIC_CMP_SWAP_I32 : AtomicCmpSwap<GPR32>;
241def ATOMIC_CMP_SWAP_I64 : AtomicCmpSwap<GPR64>;
242
243//===----------------------------------------------------------------------===//
244// Add-subtract (extended register) instructions
245//===----------------------------------------------------------------------===//
246// Contains: ADD, ADDS, SUB, SUBS + aliases CMN, CMP
247
248// The RHS of these operations is conceptually a sign/zero-extended
249// register, optionally shifted left by 1-4. The extension can be a
250// NOP (e.g. "sxtx" sign-extending a 64-bit register to 64-bits) but
251// must be specified with one exception:
252
253// If one of the registers is sp/wsp then LSL is an alias for UXTW in
254// 32-bit instructions and UXTX in 64-bit versions, the shift amount
255// is not optional in that case (but can explicitly be 0), and the
256// entire suffix can be skipped (e.g. "add sp, x3, x2").
257
258multiclass extend_operands<string PREFIX, string Diag> {
259     def _asmoperand : AsmOperandClass {
260         let Name = PREFIX;
261         let RenderMethod = "addRegExtendOperands";
262         let PredicateMethod = "isRegExtend<A64SE::" # PREFIX # ">";
263         let DiagnosticType = "AddSubRegExtend" # Diag;
264     }
265
266     def _operand : Operand<i64>,
267                    ImmLeaf<i64, [{ return Imm >= 0 && Imm <= 4; }]> {
268         let PrintMethod = "printRegExtendOperand<A64SE::" # PREFIX # ">";
269         let DecoderMethod = "DecodeRegExtendOperand";
270         let ParserMatchClass = !cast<AsmOperandClass>(PREFIX # "_asmoperand");
271     }
272}
273
274defm UXTB : extend_operands<"UXTB", "Small">;
275defm UXTH : extend_operands<"UXTH", "Small">;
276defm UXTW : extend_operands<"UXTW", "Small">;
277defm UXTX : extend_operands<"UXTX", "Large">;
278defm SXTB : extend_operands<"SXTB", "Small">;
279defm SXTH : extend_operands<"SXTH", "Small">;
280defm SXTW : extend_operands<"SXTW", "Small">;
281defm SXTX : extend_operands<"SXTX", "Large">;
282
283def LSL_extasmoperand : AsmOperandClass {
284    let Name = "RegExtendLSL";
285    let RenderMethod = "addRegExtendOperands";
286    let DiagnosticType = "AddSubRegExtendLarge";
287}
288
289def LSL_extoperand : Operand<i64> {
290    let ParserMatchClass = LSL_extasmoperand;
291}
292
293
294// The patterns for various sign-extensions are a little ugly and
295// non-uniform because everything has already been promoted to the
296// legal i64 and i32 types. We'll wrap the various variants up in a
297// class for use later.
298class extend_types {
299    dag uxtb; dag uxth; dag uxtw; dag uxtx;
300    dag sxtb; dag sxth; dag sxtw; dag sxtx;
301    ValueType ty;
302    RegisterClass GPR;
303}
304
305def extends_to_i64 : extend_types {
306    let uxtb = (and (anyext i32:$Rm), 255);
307    let uxth = (and (anyext i32:$Rm), 65535);
308    let uxtw = (zext i32:$Rm);
309    let uxtx = (i64 $Rm);
310
311    let sxtb = (sext_inreg (anyext i32:$Rm), i8);
312    let sxth = (sext_inreg (anyext i32:$Rm), i16);
313    let sxtw = (sext i32:$Rm);
314    let sxtx = (i64 $Rm);
315
316    let ty = i64;
317    let GPR = GPR64xsp;
318}
319
320
321def extends_to_i32 : extend_types {
322    let uxtb = (and i32:$Rm, 255);
323    let uxth = (and i32:$Rm, 65535);
324    let uxtw = (i32 i32:$Rm);
325    let uxtx = (i32 i32:$Rm);
326
327    let sxtb = (sext_inreg i32:$Rm, i8);
328    let sxth = (sext_inreg i32:$Rm, i16);
329    let sxtw = (i32 i32:$Rm);
330    let sxtx = (i32 i32:$Rm);
331
332    let ty = i32;
333    let GPR = GPR32wsp;
334}
335
336// Now, six of the extensions supported are easy and uniform: if the source size
337// is 32-bits or less, then Rm is always a 32-bit register. We'll instantiate
338// those instructions in one block.
339
340// The uxtx/sxtx could potentially be merged in, but three facts dissuaded me:
341//     + It would break the naming scheme: either ADDxx_uxtx or ADDww_uxtx would
342//       be impossible.
343//     + Patterns are very different as well.
344//     + Passing different registers would be ugly (more fields in extend_types
345//       would probably be the best option).
346multiclass addsub_exts<bit sf, bit op, bit S, string asmop,
347                       SDPatternOperator opfrag,
348                       dag outs, extend_types exts> {
349    def w_uxtb : A64I_addsubext<sf, op, S, 0b00, 0b000,
350                    outs, (ins exts.GPR:$Rn, GPR32:$Rm, UXTB_operand:$Imm3),
351                    !strconcat(asmop, "$Rn, $Rm, $Imm3"),
352                    [(opfrag exts.ty:$Rn, (shl exts.uxtb, UXTB_operand:$Imm3))],
353                    NoItinerary>,
354                 Sched<[WriteALU, ReadALU, ReadALU]>;
355    def w_uxth : A64I_addsubext<sf, op, S, 0b00, 0b001,
356                    outs, (ins exts.GPR:$Rn, GPR32:$Rm, UXTH_operand:$Imm3),
357                    !strconcat(asmop, "$Rn, $Rm, $Imm3"),
358                    [(opfrag exts.ty:$Rn, (shl exts.uxth, UXTH_operand:$Imm3))],
359                    NoItinerary>,
360                 Sched<[WriteALU, ReadALU, ReadALU]>;
361    def w_uxtw : A64I_addsubext<sf, op, S, 0b00, 0b010,
362                    outs, (ins exts.GPR:$Rn, GPR32:$Rm, UXTW_operand:$Imm3),
363                    !strconcat(asmop, "$Rn, $Rm, $Imm3"),
364                    [(opfrag exts.ty:$Rn, (shl exts.uxtw, UXTW_operand:$Imm3))],
365                    NoItinerary>,
366                 Sched<[WriteALU, ReadALU, ReadALU]>;
367
368    def w_sxtb : A64I_addsubext<sf, op, S, 0b00, 0b100,
369                    outs, (ins exts.GPR:$Rn, GPR32:$Rm, SXTB_operand:$Imm3),
370                    !strconcat(asmop, "$Rn, $Rm, $Imm3"),
371                    [(opfrag exts.ty:$Rn, (shl exts.sxtb, SXTB_operand:$Imm3))],
372                    NoItinerary>,
373                 Sched<[WriteALU, ReadALU, ReadALU]>;
374    def w_sxth : A64I_addsubext<sf, op, S, 0b00, 0b101,
375                    outs, (ins exts.GPR:$Rn, GPR32:$Rm, SXTH_operand:$Imm3),
376                    !strconcat(asmop, "$Rn, $Rm, $Imm3"),
377                    [(opfrag exts.ty:$Rn, (shl exts.sxth, SXTH_operand:$Imm3))],
378                    NoItinerary>,
379                 Sched<[WriteALU, ReadALU, ReadALU]>;
380    def w_sxtw : A64I_addsubext<sf, op, S, 0b00, 0b110,
381                    outs, (ins exts.GPR:$Rn, GPR32:$Rm, SXTW_operand:$Imm3),
382                    !strconcat(asmop, "$Rn, $Rm, $Imm3"),
383                    [(opfrag exts.ty:$Rn, (shl exts.sxtw, SXTW_operand:$Imm3))],
384                    NoItinerary>,
385                 Sched<[WriteALU, ReadALU, ReadALU]>;
386}
387
388// These two could be merge in with the above, but their patterns aren't really
389// necessary and the naming-scheme would necessarily break:
390multiclass addsub_xxtx<bit op, bit S, string asmop, SDPatternOperator opfrag,
391                       dag outs> {
392    def x_uxtx : A64I_addsubext<0b1, op, S, 0b00, 0b011,
393                   outs,
394                   (ins GPR64xsp:$Rn, GPR64:$Rm, UXTX_operand:$Imm3),
395                   !strconcat(asmop, "$Rn, $Rm, $Imm3"),
396                   [(opfrag i64:$Rn, (shl i64:$Rm, UXTX_operand:$Imm3))],
397                   NoItinerary>,
398                 Sched<[WriteALU, ReadALU, ReadALU]>;
399
400    def x_sxtx : A64I_addsubext<0b1, op, S, 0b00, 0b111,
401                   outs,
402                   (ins GPR64xsp:$Rn, GPR64:$Rm, SXTX_operand:$Imm3),
403                   !strconcat(asmop, "$Rn, $Rm, $Imm3"),
404                   [/* No Pattern: same as uxtx */],
405                   NoItinerary>,
406                 Sched<[WriteALU, ReadALU, ReadALU]>;
407}
408
409multiclass addsub_wxtx<bit op, bit S, string asmop, dag outs> {
410    def w_uxtx : A64I_addsubext<0b0, op, S, 0b00, 0b011,
411                   outs, (ins GPR32wsp:$Rn, GPR32:$Rm, UXTX_operand:$Imm3),
412                   !strconcat(asmop, "$Rn, $Rm, $Imm3"),
413                   [/* No pattern: probably same as uxtw */],
414                   NoItinerary>,
415                 Sched<[WriteALU, ReadALU, ReadALU]>;
416
417    def w_sxtx : A64I_addsubext<0b0, op, S, 0b00, 0b111,
418                   outs, (ins GPR32wsp:$Rn, GPR32:$Rm, SXTX_operand:$Imm3),
419                   !strconcat(asmop, "$Rn, $Rm, $Imm3"),
420                   [/* No Pattern: probably same as uxtw */],
421                   NoItinerary>,
422                 Sched<[WriteALU, ReadALU, ReadALU]>;
423}
424
425class SetRD<RegisterClass RC, SDPatternOperator op>
426 : PatFrag<(ops node:$lhs, node:$rhs), (set RC:$Rd, (op node:$lhs, node:$rhs))>;
427class SetNZCV<SDPatternOperator op>
428  : PatFrag<(ops node:$lhs, node:$rhs), (set NZCV, (op node:$lhs, node:$rhs))>;
429
430defm ADDxx :addsub_exts<0b1, 0b0, 0b0, "add\t$Rd, ", SetRD<GPR64xsp, add>,
431                        (outs GPR64xsp:$Rd), extends_to_i64>,
432            addsub_xxtx<     0b0, 0b0, "add\t$Rd, ", SetRD<GPR64xsp, add>,
433                        (outs GPR64xsp:$Rd)>;
434defm ADDww :addsub_exts<0b0, 0b0, 0b0, "add\t$Rd, ", SetRD<GPR32wsp, add>,
435                        (outs GPR32wsp:$Rd), extends_to_i32>,
436            addsub_wxtx<     0b0, 0b0, "add\t$Rd, ",
437                        (outs GPR32wsp:$Rd)>;
438defm SUBxx :addsub_exts<0b1, 0b1, 0b0, "sub\t$Rd, ", SetRD<GPR64xsp, sub>,
439                        (outs GPR64xsp:$Rd), extends_to_i64>,
440            addsub_xxtx<     0b1, 0b0, "sub\t$Rd, ", SetRD<GPR64xsp, sub>,
441                        (outs GPR64xsp:$Rd)>;
442defm SUBww :addsub_exts<0b0, 0b1, 0b0, "sub\t$Rd, ", SetRD<GPR32wsp, sub>,
443                        (outs GPR32wsp:$Rd), extends_to_i32>,
444            addsub_wxtx<     0b1, 0b0, "sub\t$Rd, ",
445                        (outs GPR32wsp:$Rd)>;
446
447let Defs = [NZCV] in {
448defm ADDSxx :addsub_exts<0b1, 0b0, 0b1, "adds\t$Rd, ", SetRD<GPR64, addc>,
449                         (outs GPR64:$Rd), extends_to_i64>,
450             addsub_xxtx<     0b0, 0b1, "adds\t$Rd, ", SetRD<GPR64, addc>,
451                         (outs GPR64:$Rd)>;
452defm ADDSww :addsub_exts<0b0, 0b0, 0b1, "adds\t$Rd, ", SetRD<GPR32, addc>,
453                         (outs GPR32:$Rd), extends_to_i32>,
454             addsub_wxtx<     0b0, 0b1, "adds\t$Rd, ",
455                         (outs GPR32:$Rd)>;
456defm SUBSxx :addsub_exts<0b1, 0b1, 0b1, "subs\t$Rd, ", SetRD<GPR64, subc>,
457                         (outs GPR64:$Rd), extends_to_i64>,
458             addsub_xxtx<     0b1, 0b1, "subs\t$Rd, ", SetRD<GPR64, subc>,
459                         (outs GPR64:$Rd)>;
460defm SUBSww :addsub_exts<0b0, 0b1, 0b1, "subs\t$Rd, ", SetRD<GPR32, subc>,
461                         (outs GPR32:$Rd), extends_to_i32>,
462             addsub_wxtx<     0b1, 0b1, "subs\t$Rd, ",
463                         (outs GPR32:$Rd)>;
464
465
466let SchedRW = [WriteCMP, ReadCMP, ReadCMP], Rd = 0b11111, isCompare = 1 in {
467defm CMNx : addsub_exts<0b1, 0b0, 0b1, "cmn\t", SetNZCV<A64cmn>,
468                        (outs), extends_to_i64>,
469            addsub_xxtx<     0b0, 0b1, "cmn\t", SetNZCV<A64cmn>, (outs)>;
470defm CMNw : addsub_exts<0b0, 0b0, 0b1, "cmn\t", SetNZCV<A64cmn>,
471                        (outs), extends_to_i32>,
472            addsub_wxtx<     0b0, 0b1, "cmn\t", (outs)>;
473defm CMPx : addsub_exts<0b1, 0b1, 0b1, "cmp\t", SetNZCV<A64cmp>,
474                        (outs), extends_to_i64>,
475            addsub_xxtx<     0b1, 0b1, "cmp\t", SetNZCV<A64cmp>, (outs)>;
476defm CMPw : addsub_exts<0b0, 0b1, 0b1, "cmp\t", SetNZCV<A64cmp>,
477                        (outs), extends_to_i32>,
478            addsub_wxtx<     0b1, 0b1, "cmp\t", (outs)>;
479}
480}
481
482// Now patterns for the operation without a shift being needed. No patterns are
483// created for uxtx/sxtx since they're non-uniform and it's expected that
484// add/sub (shifted register) will handle those cases anyway.
485multiclass addsubext_noshift_patterns<string prefix, SDPatternOperator nodeop,
486                                      extend_types exts> {
487    def : Pat<(nodeop exts.ty:$Rn, exts.uxtb),
488              (!cast<Instruction>(prefix # "w_uxtb") $Rn, $Rm, 0)>;
489    def : Pat<(nodeop exts.ty:$Rn, exts.uxth),
490              (!cast<Instruction>(prefix # "w_uxth") $Rn, $Rm, 0)>;
491    def : Pat<(nodeop exts.ty:$Rn, exts.uxtw),
492              (!cast<Instruction>(prefix # "w_uxtw") $Rn, $Rm, 0)>;
493
494    def : Pat<(nodeop exts.ty:$Rn, exts.sxtb),
495              (!cast<Instruction>(prefix # "w_sxtb") $Rn, $Rm, 0)>;
496    def : Pat<(nodeop exts.ty:$Rn, exts.sxth),
497              (!cast<Instruction>(prefix # "w_sxth") $Rn, $Rm, 0)>;
498    def : Pat<(nodeop exts.ty:$Rn, exts.sxtw),
499              (!cast<Instruction>(prefix # "w_sxtw") $Rn, $Rm, 0)>;
500}
501
502defm : addsubext_noshift_patterns<"ADDxx", add, extends_to_i64>;
503defm : addsubext_noshift_patterns<"ADDww", add, extends_to_i32>;
504defm : addsubext_noshift_patterns<"SUBxx", sub, extends_to_i64>;
505defm : addsubext_noshift_patterns<"SUBww", sub, extends_to_i32>;
506
507defm : addsubext_noshift_patterns<"CMNx", A64cmn, extends_to_i64>;
508defm : addsubext_noshift_patterns<"CMNw", A64cmn, extends_to_i32>;
509defm : addsubext_noshift_patterns<"CMPx", A64cmp, extends_to_i64>;
510defm : addsubext_noshift_patterns<"CMPw", A64cmp, extends_to_i32>;
511
512// An extend of "lsl #imm" is valid if and only if one of Rn and Rd is
513// sp/wsp. It is synonymous with uxtx/uxtw depending on the size of the
514// operation. Also permitted in this case is complete omission of the argument,
515// which implies "lsl #0".
516multiclass lsl_aliases<string asmop, Instruction inst, RegisterClass GPR_Rd,
517                       RegisterClass GPR_Rn, RegisterClass GPR_Rm> {
518    def : InstAlias<!strconcat(asmop, " $Rd, $Rn, $Rm"),
519                    (inst GPR_Rd:$Rd, GPR_Rn:$Rn, GPR_Rm:$Rm, 0)>;
520
521    def : InstAlias<!strconcat(asmop, " $Rd, $Rn, $Rm, $LSL"),
522                (inst GPR_Rd:$Rd, GPR_Rn:$Rn, GPR_Rm:$Rm, LSL_extoperand:$LSL)>;
523
524}
525
526defm : lsl_aliases<"add",  ADDxxx_uxtx,  Rxsp, GPR64xsp, GPR64>;
527defm : lsl_aliases<"add",  ADDxxx_uxtx,  GPR64xsp, Rxsp, GPR64>;
528defm : lsl_aliases<"add",  ADDwww_uxtw,  Rwsp, GPR32wsp, GPR32>;
529defm : lsl_aliases<"add",  ADDwww_uxtw,  GPR32wsp, Rwsp, GPR32>;
530defm : lsl_aliases<"sub",  SUBxxx_uxtx,  Rxsp, GPR64xsp, GPR64>;
531defm : lsl_aliases<"sub",  SUBxxx_uxtx,  GPR64xsp, Rxsp, GPR64>;
532defm : lsl_aliases<"sub",  SUBwww_uxtw,  Rwsp, GPR32wsp, GPR32>;
533defm : lsl_aliases<"sub",  SUBwww_uxtw,  GPR32wsp, Rwsp, GPR32>;
534
535// Rd cannot be sp for flag-setting variants so only half of the aliases are
536// needed.
537defm : lsl_aliases<"adds", ADDSxxx_uxtx, GPR64, Rxsp, GPR64>;
538defm : lsl_aliases<"adds", ADDSwww_uxtw, GPR32, Rwsp, GPR32>;
539defm : lsl_aliases<"subs", SUBSxxx_uxtx, GPR64, Rxsp, GPR64>;
540defm : lsl_aliases<"subs", SUBSwww_uxtw, GPR32, Rwsp, GPR32>;
541
542// CMP unfortunately has to be different because the instruction doesn't have a
543// dest register.
544multiclass cmp_lsl_aliases<string asmop, Instruction inst,
545                       RegisterClass GPR_Rn, RegisterClass GPR_Rm> {
546    def : InstAlias<!strconcat(asmop, " $Rn, $Rm"),
547                    (inst GPR_Rn:$Rn, GPR_Rm:$Rm, 0)>;
548
549    def : InstAlias<!strconcat(asmop, " $Rn, $Rm, $LSL"),
550                    (inst GPR_Rn:$Rn, GPR_Rm:$Rm, LSL_extoperand:$LSL)>;
551}
552
553defm : cmp_lsl_aliases<"cmp", CMPxx_uxtx, Rxsp, GPR64>;
554defm : cmp_lsl_aliases<"cmp", CMPww_uxtw, Rwsp, GPR32>;
555defm : cmp_lsl_aliases<"cmn", CMNxx_uxtx, Rxsp, GPR64>;
556defm : cmp_lsl_aliases<"cmn", CMNww_uxtw, Rwsp, GPR32>;
557
558//===----------------------------------------------------------------------===//
559// Add-subtract (immediate) instructions
560//===----------------------------------------------------------------------===//
561// Contains: ADD, ADDS, SUB, SUBS + aliases CMN, CMP, MOV
562
563// These instructions accept a 12-bit unsigned immediate, optionally shifted
564// left by 12 bits. Official assembly format specifies a 12 bit immediate with
565// one of "", "LSL #0", "LSL #12" supplementary operands.
566
567// There are surprisingly few ways to make this work with TableGen, so this
568// implementation has separate instructions for the "LSL #0" and "LSL #12"
569// variants.
570
571// If the MCInst retained a single combined immediate (which could be 0x123000,
572// for example) then both components (imm & shift) would have to be delegated to
573// a single assembly operand. This would entail a separate operand parser
574// (because the LSL would have to live in the same AArch64Operand as the
575// immediate to be accessible); assembly parsing is rather complex and
576// error-prone C++ code.
577//
578// By splitting the immediate, we can delegate handling this optional operand to
579// an InstAlias. Supporting functions to generate the correct MCInst are still
580// required, but these are essentially trivial and parsing can remain generic.
581//
582// Rejected plans with rationale:
583// ------------------------------
584//
585// In an ideal world you'de have two first class immediate operands (in
586// InOperandList, specifying imm12 and shift). Unfortunately this is not
587// selectable by any means I could discover.
588//
589// An Instruction with two MCOperands hidden behind a single entry in
590// InOperandList (expanded by ComplexPatterns and MIOperandInfo) was functional,
591// but required more C++ code to handle encoding/decoding. Parsing (the intended
592// main beneficiary) ended up equally complex because of the optional nature of
593// "LSL #0".
594//
595// Attempting to circumvent the need for a custom OperandParser above by giving
596// InstAliases without the "lsl #0" failed. add/sub could be accommodated but
597// the cmp/cmn aliases didn't use the MIOperandInfo to determine how operands
598// should be parsed: there was no way to accommodate an "lsl #12".
599
600let ParserMethod = "ParseImmWithLSLOperand",
601    RenderMethod = "addImmWithLSLOperands" in {
602  // Derived PredicateMethod fields are different for each
603  def addsubimm_lsl0_asmoperand : AsmOperandClass {
604    let Name = "AddSubImmLSL0";
605    // If an error is reported against this operand, instruction could also be a
606    // register variant.
607    let DiagnosticType = "AddSubSecondSource";
608  }
609
610  def addsubimm_lsl12_asmoperand : AsmOperandClass {
611    let Name = "AddSubImmLSL12";
612    let DiagnosticType = "AddSubSecondSource";
613  }
614}
615
616def shr_12_XFORM : SDNodeXForm<imm, [{
617  return CurDAG->getTargetConstant(N->getSExtValue() >> 12, MVT::i32);
618}]>;
619
620def shr_12_neg_XFORM : SDNodeXForm<imm, [{
621  return CurDAG->getTargetConstant((-N->getSExtValue()) >> 12, MVT::i32);
622}]>;
623
624def neg_XFORM : SDNodeXForm<imm, [{
625  return CurDAG->getTargetConstant(-N->getSExtValue(), MVT::i32);
626}]>;
627
628
629multiclass addsub_imm_operands<ValueType ty> {
630 let PrintMethod = "printAddSubImmLSL0Operand",
631      EncoderMethod = "getAddSubImmOpValue",
632      ParserMatchClass = addsubimm_lsl0_asmoperand in {
633    def _posimm_lsl0 : Operand<ty>,
634        ImmLeaf<ty, [{ return Imm >= 0 && (Imm & ~0xfff) == 0; }]>;
635    def _negimm_lsl0 : Operand<ty>,
636        ImmLeaf<ty, [{ return Imm < 0 && (-Imm & ~0xfff) == 0; }],
637                neg_XFORM>;
638  }
639
640  let PrintMethod = "printAddSubImmLSL12Operand",
641      EncoderMethod = "getAddSubImmOpValue",
642      ParserMatchClass = addsubimm_lsl12_asmoperand in {
643    def _posimm_lsl12 : Operand<ty>,
644        ImmLeaf<ty, [{ return Imm >= 0 && (Imm & ~0xfff000) == 0; }],
645                shr_12_XFORM>;
646
647    def _negimm_lsl12 : Operand<ty>,
648        ImmLeaf<ty, [{ return Imm < 0 && (-Imm & ~0xfff000) == 0; }],
649                shr_12_neg_XFORM>;
650  }
651}
652
653// The add operands don't need any transformation
654defm addsubimm_operand_i32 : addsub_imm_operands<i32>;
655defm addsubimm_operand_i64 : addsub_imm_operands<i64>;
656
657multiclass addsubimm_varieties<string prefix, bit sf, bit op, bits<2> shift,
658                               string asmop, string cmpasmop,
659                               Operand imm_operand, Operand cmp_imm_operand,
660                               RegisterClass GPR, RegisterClass GPRsp,
661                               AArch64Reg ZR, ValueType Ty> {
662    // All registers for non-S variants allow SP
663  def _s : A64I_addsubimm<sf, op, 0b0, shift,
664                         (outs GPRsp:$Rd),
665                         (ins GPRsp:$Rn, imm_operand:$Imm12),
666                         !strconcat(asmop, "\t$Rd, $Rn, $Imm12"),
667                         [(set Ty:$Rd, (add Ty:$Rn, imm_operand:$Imm12))],
668                         NoItinerary>,
669           Sched<[WriteALU, ReadALU]>;
670
671
672  // S variants can read SP but would write to ZR
673  def _S : A64I_addsubimm<sf, op, 0b1, shift,
674                         (outs GPR:$Rd),
675                         (ins GPRsp:$Rn, imm_operand:$Imm12),
676                         !strconcat(asmop, "s\t$Rd, $Rn, $Imm12"),
677                         [(set Ty:$Rd, (addc Ty:$Rn, imm_operand:$Imm12))],
678                         NoItinerary>,
679           Sched<[WriteALU, ReadALU]> {
680    let Defs = [NZCV];
681  }
682
683  // Note that the pattern here for ADDS is subtle. Canonically CMP
684  // a, b becomes SUBS a, b. If b < 0 then this is equivalent to
685  // ADDS a, (-b). This is not true in general.
686  def _cmp : A64I_addsubimm<sf, op, 0b1, shift,
687                            (outs), (ins GPRsp:$Rn, imm_operand:$Imm12),
688                            !strconcat(cmpasmop, " $Rn, $Imm12"),
689                            [(set NZCV,
690                                  (A64cmp Ty:$Rn, cmp_imm_operand:$Imm12))],
691                            NoItinerary>,
692           Sched<[WriteCMP, ReadCMP]> {
693    let Rd = 0b11111;
694    let Defs = [NZCV];
695    let isCompare = 1;
696  }
697}
698
699
700multiclass addsubimm_shifts<string prefix, bit sf, bit op,
701           string asmop, string cmpasmop, string operand, string cmpoperand,
702           RegisterClass GPR, RegisterClass GPRsp, AArch64Reg ZR,
703           ValueType Ty> {
704  defm _lsl0 : addsubimm_varieties<prefix # "_lsl0", sf, op, 0b00,
705                                   asmop, cmpasmop,
706                                   !cast<Operand>(operand # "_lsl0"),
707                                   !cast<Operand>(cmpoperand # "_lsl0"),
708                                   GPR, GPRsp, ZR, Ty>;
709
710  defm _lsl12 : addsubimm_varieties<prefix # "_lsl12", sf, op, 0b01,
711                                    asmop, cmpasmop,
712                                    !cast<Operand>(operand # "_lsl12"),
713                                    !cast<Operand>(cmpoperand # "_lsl12"),
714                                    GPR, GPRsp, ZR, Ty>;
715}
716
717defm ADDwwi : addsubimm_shifts<"ADDwi", 0b0, 0b0, "add", "cmn",
718                              "addsubimm_operand_i32_posimm",
719                              "addsubimm_operand_i32_negimm",
720                              GPR32, GPR32wsp, WZR, i32>;
721defm ADDxxi : addsubimm_shifts<"ADDxi", 0b1, 0b0, "add", "cmn",
722                              "addsubimm_operand_i64_posimm",
723                              "addsubimm_operand_i64_negimm",
724                              GPR64, GPR64xsp, XZR, i64>;
725defm SUBwwi : addsubimm_shifts<"SUBwi", 0b0, 0b1, "sub", "cmp",
726                              "addsubimm_operand_i32_negimm",
727                              "addsubimm_operand_i32_posimm",
728                              GPR32, GPR32wsp, WZR, i32>;
729defm SUBxxi : addsubimm_shifts<"SUBxi", 0b1, 0b1, "sub", "cmp",
730                              "addsubimm_operand_i64_negimm",
731                              "addsubimm_operand_i64_posimm",
732                              GPR64, GPR64xsp, XZR, i64>;
733
734multiclass MOVsp<RegisterClass GPRsp, RegisterClass SP, Instruction addop> {
735  def _fromsp : InstAlias<"mov $Rd, $Rn",
736                          (addop GPRsp:$Rd, SP:$Rn, 0),
737                          0b1>;
738
739  def _tosp : InstAlias<"mov $Rd, $Rn",
740                        (addop SP:$Rd, GPRsp:$Rn, 0),
741                        0b1>;
742}
743
744// Recall Rxsp is a RegisterClass containing *just* xsp.
745defm MOVxx : MOVsp<GPR64xsp, Rxsp, ADDxxi_lsl0_s>;
746defm MOVww : MOVsp<GPR32wsp, Rwsp, ADDwwi_lsl0_s>;
747
748//===----------------------------------------------------------------------===//
749// Add-subtract (shifted register) instructions
750//===----------------------------------------------------------------------===//
751// Contains: ADD, ADDS, SUB, SUBS + aliases CMN, CMP, NEG, NEGS
752
753//===-------------------------------
754// 1. The "shifted register" operands. Shared with logical insts.
755//===-------------------------------
756
757multiclass shift_operands<string prefix, string form> {
758  def _asmoperand_i32 : AsmOperandClass {
759    let Name = "Shift" # form # "i32";
760    let RenderMethod = "addShiftOperands";
761    let PredicateMethod = "isShift<A64SE::" # form # ", false>";
762    let DiagnosticType = "AddSubRegShift32";
763  }
764
765  // Note that the operand type is intentionally i64 because the DAGCombiner
766  // puts these into a canonical form.
767  def _i32 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm <= 31; }]> {
768    let ParserMatchClass
769          = !cast<AsmOperandClass>(prefix # "_asmoperand_i32");
770    let PrintMethod = "printShiftOperand<A64SE::" # form # ">";
771    let DecoderMethod = "Decode32BitShiftOperand";
772  }
773
774  def _asmoperand_i64 : AsmOperandClass {
775      let Name = "Shift" # form # "i64";
776      let RenderMethod = "addShiftOperands";
777      let PredicateMethod = "isShift<A64SE::" # form # ", true>";
778      let DiagnosticType = "AddSubRegShift64";
779  }
780
781  def _i64 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm <= 63; }]> {
782    let ParserMatchClass
783          = !cast<AsmOperandClass>(prefix # "_asmoperand_i64");
784    let PrintMethod = "printShiftOperand<A64SE::" # form # ">";
785  }
786}
787
788defm lsl_operand : shift_operands<"lsl_operand", "LSL">;
789defm lsr_operand : shift_operands<"lsr_operand", "LSR">;
790defm asr_operand : shift_operands<"asr_operand", "ASR">;
791
792// Not used for add/sub, but defined here for completeness. The "logical
793// (shifted register)" instructions *do* have an ROR variant.
794defm ror_operand : shift_operands<"ror_operand", "ROR">;
795
796//===-------------------------------
797// 2. The basic 3.5-operand ADD/SUB/ADDS/SUBS instructions.
798//===-------------------------------
799
800// N.b. the commutable parameter is just !N. It will be first against the wall
801// when the revolution comes.
802multiclass addsub_shifts<string prefix, bit sf, bit op, bit s, bit commutable,
803                         string asmop, SDPatternOperator opfrag, ValueType ty,
804                         RegisterClass GPR, list<Register> defs> {
805  let isCommutable = commutable, Defs = defs in {
806  def _lsl : A64I_addsubshift<sf, op, s, 0b00,
807                       (outs GPR:$Rd),
808                       (ins GPR:$Rn, GPR:$Rm,
809                            !cast<Operand>("lsl_operand_" # ty):$Imm6),
810                       !strconcat(asmop, "\t$Rd, $Rn, $Rm, $Imm6"),
811                       [(set GPR:$Rd, (opfrag ty:$Rn, (shl ty:$Rm,
812                            !cast<Operand>("lsl_operand_" # ty):$Imm6))
813                       )],
814                       NoItinerary>,
815             Sched<[WriteALU, ReadALU]>;
816
817  def _lsr : A64I_addsubshift<sf, op, s, 0b01,
818                       (outs GPR:$Rd),
819                       (ins GPR:$Rn, GPR:$Rm,
820                            !cast<Operand>("lsr_operand_" # ty):$Imm6),
821                       !strconcat(asmop, "\t$Rd, $Rn, $Rm, $Imm6"),
822                       [(set ty:$Rd, (opfrag ty:$Rn, (srl ty:$Rm,
823                            !cast<Operand>("lsr_operand_" # ty):$Imm6))
824                       )],
825                       NoItinerary>,
826             Sched<[WriteALU, ReadALU]>;
827
828  def _asr : A64I_addsubshift<sf, op, s, 0b10,
829                       (outs GPR:$Rd),
830                       (ins GPR:$Rn, GPR:$Rm,
831                            !cast<Operand>("asr_operand_" # ty):$Imm6),
832                       !strconcat(asmop, "\t$Rd, $Rn, $Rm, $Imm6"),
833                       [(set ty:$Rd, (opfrag ty:$Rn, (sra ty:$Rm,
834                            !cast<Operand>("asr_operand_" # ty):$Imm6))
835                       )],
836                       NoItinerary>,
837             Sched<[WriteALU, ReadALU]>;
838  }
839
840  def _noshift
841      : InstAlias<!strconcat(asmop, " $Rd, $Rn, $Rm"),
842                 (!cast<Instruction>(prefix # "_lsl") GPR:$Rd, GPR:$Rn,
843                                                      GPR:$Rm, 0)>;
844
845  def : Pat<(opfrag ty:$Rn, ty:$Rm),
846            (!cast<Instruction>(prefix # "_lsl") $Rn, $Rm, 0)>;
847}
848
849multiclass addsub_sizes<string prefix, bit op, bit s, bit commutable,
850                         string asmop, SDPatternOperator opfrag,
851                         list<Register> defs> {
852  defm xxx : addsub_shifts<prefix # "xxx", 0b1, op, s,
853                           commutable, asmop, opfrag, i64, GPR64, defs>;
854  defm www : addsub_shifts<prefix # "www", 0b0, op, s,
855                           commutable, asmop, opfrag, i32, GPR32, defs>;
856}
857
858
859defm ADD : addsub_sizes<"ADD", 0b0, 0b0, 0b1, "add", add, []>;
860defm SUB : addsub_sizes<"SUB", 0b1, 0b0, 0b0, "sub", sub, []>;
861
862defm ADDS : addsub_sizes<"ADDS", 0b0, 0b1, 0b1, "adds", addc, [NZCV]>;
863defm SUBS : addsub_sizes<"SUBS", 0b1, 0b1, 0b0, "subs", subc, [NZCV]>;
864
865//===-------------------------------
866// 1. The NEG/NEGS aliases
867//===-------------------------------
868
869multiclass neg_alias<Instruction INST, RegisterClass GPR, Register ZR,
870                     ValueType ty, Operand shift_operand, SDNode shiftop> {
871   def : InstAlias<"neg $Rd, $Rm, $Imm6",
872                   (INST GPR:$Rd, ZR, GPR:$Rm, shift_operand:$Imm6)>;
873
874   def : Pat<(sub 0, (shiftop ty:$Rm, shift_operand:$Imm6)),
875             (INST ZR, $Rm, shift_operand:$Imm6)>;
876}
877
878defm : neg_alias<SUBwww_lsl, GPR32, WZR, i32, lsl_operand_i32, shl>;
879defm : neg_alias<SUBwww_lsr, GPR32, WZR, i32, lsr_operand_i32, srl>;
880defm : neg_alias<SUBwww_asr, GPR32, WZR, i32, asr_operand_i32, sra>;
881def : InstAlias<"neg $Rd, $Rm", (SUBwww_lsl GPR32:$Rd, WZR, GPR32:$Rm, 0)>;
882def : Pat<(sub 0, i32:$Rm), (SUBwww_lsl WZR, $Rm, 0)>;
883
884defm : neg_alias<SUBxxx_lsl, GPR64, XZR, i64, lsl_operand_i64, shl>;
885defm : neg_alias<SUBxxx_lsr, GPR64, XZR, i64, lsr_operand_i64, srl>;
886defm : neg_alias<SUBxxx_asr, GPR64, XZR, i64, asr_operand_i64, sra>;
887def : InstAlias<"neg $Rd, $Rm", (SUBxxx_lsl GPR64:$Rd, XZR, GPR64:$Rm, 0)>;
888def : Pat<(sub 0, i64:$Rm), (SUBxxx_lsl XZR, $Rm, 0)>;
889
890// NEGS doesn't get any patterns yet: defining multiple outputs means C++ has to
891// be involved.
892class negs_alias<Instruction INST, RegisterClass GPR,
893                 Register ZR, Operand shift_operand, SDNode shiftop>
894  : InstAlias<"negs $Rd, $Rm, $Imm6",
895              (INST GPR:$Rd, ZR, GPR:$Rm, shift_operand:$Imm6)>;
896
897def : negs_alias<SUBSwww_lsl, GPR32, WZR, lsl_operand_i32, shl>;
898def : negs_alias<SUBSwww_lsr, GPR32, WZR, lsr_operand_i32, srl>;
899def : negs_alias<SUBSwww_asr, GPR32, WZR, asr_operand_i32, sra>;
900def : InstAlias<"negs $Rd, $Rm", (SUBSwww_lsl GPR32:$Rd, WZR, GPR32:$Rm, 0)>;
901
902def : negs_alias<SUBSxxx_lsl, GPR64, XZR, lsl_operand_i64, shl>;
903def : negs_alias<SUBSxxx_lsr, GPR64, XZR, lsr_operand_i64, srl>;
904def : negs_alias<SUBSxxx_asr, GPR64, XZR, asr_operand_i64, sra>;
905def : InstAlias<"negs $Rd, $Rm", (SUBSxxx_lsl GPR64:$Rd, XZR, GPR64:$Rm, 0)>;
906
907//===-------------------------------
908// 1. The CMP/CMN aliases
909//===-------------------------------
910
911multiclass cmp_shifts<string prefix, bit sf, bit op, bit commutable,
912                      string asmop, SDPatternOperator opfrag, ValueType ty,
913                      RegisterClass GPR> {
914  let isCommutable = commutable, Rd = 0b11111, Defs = [NZCV] in {
915  def _lsl : A64I_addsubshift<sf, op, 0b1, 0b00,
916                       (outs),
917                       (ins GPR:$Rn, GPR:$Rm,
918                            !cast<Operand>("lsl_operand_" # ty):$Imm6),
919                       !strconcat(asmop, "\t$Rn, $Rm, $Imm6"),
920                       [(set NZCV, (opfrag ty:$Rn, (shl ty:$Rm,
921                            !cast<Operand>("lsl_operand_" # ty):$Imm6))
922                       )],
923                       NoItinerary>,
924             Sched<[WriteCMP, ReadCMP, ReadCMP]>;
925
926  def _lsr : A64I_addsubshift<sf, op, 0b1, 0b01,
927                       (outs),
928                       (ins GPR:$Rn, GPR:$Rm,
929                            !cast<Operand>("lsr_operand_" # ty):$Imm6),
930                       !strconcat(asmop, "\t$Rn, $Rm, $Imm6"),
931                       [(set NZCV, (opfrag ty:$Rn, (srl ty:$Rm,
932                            !cast<Operand>("lsr_operand_" # ty):$Imm6))
933                       )],
934                       NoItinerary>,
935             Sched<[WriteCMP, ReadCMP, ReadCMP]>;
936
937  def _asr : A64I_addsubshift<sf, op, 0b1, 0b10,
938                       (outs),
939                       (ins GPR:$Rn, GPR:$Rm,
940                            !cast<Operand>("asr_operand_" # ty):$Imm6),
941                       !strconcat(asmop, "\t$Rn, $Rm, $Imm6"),
942                       [(set NZCV, (opfrag ty:$Rn, (sra ty:$Rm,
943                            !cast<Operand>("asr_operand_" # ty):$Imm6))
944                       )],
945                       NoItinerary>,
946             Sched<[WriteCMP, ReadCMP, ReadCMP]>;
947  }
948
949  def _noshift
950      : InstAlias<!strconcat(asmop, " $Rn, $Rm"),
951                 (!cast<Instruction>(prefix # "_lsl") GPR:$Rn, GPR:$Rm, 0)>;
952
953  def : Pat<(opfrag ty:$Rn, ty:$Rm),
954            (!cast<Instruction>(prefix # "_lsl") $Rn, $Rm, 0)>;
955}
956
957defm CMPww : cmp_shifts<"CMPww", 0b0, 0b1, 0b0, "cmp", A64cmp, i32, GPR32>;
958defm CMPxx : cmp_shifts<"CMPxx", 0b1, 0b1, 0b0, "cmp", A64cmp, i64, GPR64>;
959
960defm CMNww : cmp_shifts<"CMNww", 0b0, 0b0, 0b1, "cmn", A64cmn, i32, GPR32>;
961defm CMNxx : cmp_shifts<"CMNxx", 0b1, 0b0, 0b1, "cmn", A64cmn, i64, GPR64>;
962
963//===----------------------------------------------------------------------===//
964// Add-subtract (with carry) instructions
965//===----------------------------------------------------------------------===//
966// Contains: ADC, ADCS, SBC, SBCS + aliases NGC, NGCS
967
968multiclass A64I_addsubcarrySizes<bit op, bit s, string asmop> {
969  let Uses = [NZCV] in {
970    def www : A64I_addsubcarry<0b0, op, s, 0b000000,
971                               (outs GPR32:$Rd), (ins GPR32:$Rn, GPR32:$Rm),
972                               !strconcat(asmop, "\t$Rd, $Rn, $Rm"),
973                               [], NoItinerary>,
974              Sched<[WriteALU, ReadALU, ReadALU]>;
975
976    def xxx : A64I_addsubcarry<0b1, op, s, 0b000000,
977                               (outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
978                               !strconcat(asmop, "\t$Rd, $Rn, $Rm"),
979                               [], NoItinerary>,
980              Sched<[WriteALU, ReadALU, ReadALU]>;
981  }
982}
983
984let isCommutable = 1 in {
985  defm ADC : A64I_addsubcarrySizes<0b0, 0b0, "adc">;
986}
987
988defm SBC : A64I_addsubcarrySizes<0b1, 0b0, "sbc">;
989
990let Defs = [NZCV] in {
991  let isCommutable = 1 in {
992    defm ADCS : A64I_addsubcarrySizes<0b0, 0b1, "adcs">;
993  }
994
995  defm SBCS : A64I_addsubcarrySizes<0b1, 0b1, "sbcs">;
996}
997
998def : InstAlias<"ngc $Rd, $Rm", (SBCwww GPR32:$Rd, WZR, GPR32:$Rm)>;
999def : InstAlias<"ngc $Rd, $Rm", (SBCxxx GPR64:$Rd, XZR, GPR64:$Rm)>;
1000def : InstAlias<"ngcs $Rd, $Rm", (SBCSwww GPR32:$Rd, WZR, GPR32:$Rm)>;
1001def : InstAlias<"ngcs $Rd, $Rm", (SBCSxxx GPR64:$Rd, XZR, GPR64:$Rm)>;
1002
1003// Note that adde and sube can form a chain longer than two (e.g. for 256-bit
1004// addition). So the flag-setting instructions are appropriate.
1005def : Pat<(adde i32:$Rn, i32:$Rm), (ADCSwww $Rn, $Rm)>;
1006def : Pat<(adde i64:$Rn, i64:$Rm), (ADCSxxx $Rn, $Rm)>;
1007def : Pat<(sube i32:$Rn, i32:$Rm), (SBCSwww $Rn, $Rm)>;
1008def : Pat<(sube i64:$Rn, i64:$Rm), (SBCSxxx $Rn, $Rm)>;
1009
1010//===----------------------------------------------------------------------===//
1011// Bitfield
1012//===----------------------------------------------------------------------===//
1013// Contains: SBFM, BFM, UBFM, [SU]XT[BHW], ASR, LSR, LSL, SBFI[ZX], BFI, BFXIL,
1014//     UBFIZ, UBFX
1015
1016// Because of the rather complicated nearly-overlapping aliases, the decoding of
1017// this range of instructions is handled manually. The architectural
1018// instructions are BFM, SBFM and UBFM but a disassembler should never produce
1019// these.
1020//
1021// In the end, the best option was to use BFM instructions for decoding under
1022// almost all circumstances, but to create aliasing *Instructions* for each of
1023// the canonical forms and specify a completely custom decoder which would
1024// substitute the correct MCInst as needed.
1025//
1026// This also simplifies instruction selection, parsing etc because the MCInsts
1027// have a shape that's closer to their use in code.
1028
1029//===-------------------------------
1030// 1. The architectural BFM instructions
1031//===-------------------------------
1032
1033def uimm5_asmoperand : AsmOperandClass {
1034  let Name = "UImm5";
1035  let PredicateMethod = "isUImm<5>";
1036  let RenderMethod = "addImmOperands";
1037  let DiagnosticType = "UImm5";
1038}
1039
1040def uimm6_asmoperand : AsmOperandClass {
1041  let Name = "UImm6";
1042  let PredicateMethod = "isUImm<6>";
1043  let RenderMethod = "addImmOperands";
1044  let DiagnosticType = "UImm6";
1045}
1046
1047def bitfield32_imm : Operand<i64>,
1048                     ImmLeaf<i64, [{ return Imm >= 0 && Imm < 32; }]> {
1049  let ParserMatchClass = uimm5_asmoperand;
1050
1051  let DecoderMethod = "DecodeBitfield32ImmOperand";
1052}
1053
1054
1055def bitfield64_imm : Operand<i64>,
1056                     ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
1057  let ParserMatchClass = uimm6_asmoperand;
1058
1059  // Default decoder works in 64-bit case: the 6-bit field can take any value.
1060}
1061
1062multiclass A64I_bitfieldSizes<bits<2> opc, string asmop> {
1063  def wwii : A64I_bitfield<0b0, opc, 0b0, (outs GPR32:$Rd),
1064                    (ins GPR32:$Rn, bitfield32_imm:$ImmR, bitfield32_imm:$ImmS),
1065                    !strconcat(asmop, "\t$Rd, $Rn, $ImmR, $ImmS"),
1066                    [], NoItinerary>,
1067             Sched<[WriteALU, ReadALU]> {
1068    let DecoderMethod = "DecodeBitfieldInstruction";
1069  }
1070
1071  def xxii : A64I_bitfield<0b1, opc, 0b1, (outs GPR64:$Rd),
1072                    (ins GPR64:$Rn, bitfield64_imm:$ImmR, bitfield64_imm:$ImmS),
1073                    !strconcat(asmop, "\t$Rd, $Rn, $ImmR, $ImmS"),
1074                    [], NoItinerary>,
1075             Sched<[WriteALU, ReadALU]> {
1076    let DecoderMethod = "DecodeBitfieldInstruction";
1077  }
1078}
1079
1080defm SBFM : A64I_bitfieldSizes<0b00, "sbfm">;
1081defm UBFM : A64I_bitfieldSizes<0b10, "ubfm">;
1082
1083// BFM instructions modify the destination register rather than defining it
1084// completely.
1085def BFMwwii :
1086  A64I_bitfield<0b0, 0b01, 0b0, (outs GPR32:$Rd),
1087        (ins GPR32:$src, GPR32:$Rn, bitfield32_imm:$ImmR, bitfield32_imm:$ImmS),
1088        "bfm\t$Rd, $Rn, $ImmR, $ImmS", [], NoItinerary>,
1089  Sched<[WriteALU, ReadALU, ReadALU]> {
1090  let DecoderMethod = "DecodeBitfieldInstruction";
1091  let Constraints = "$src = $Rd";
1092}
1093
1094def BFMxxii :
1095  A64I_bitfield<0b1, 0b01, 0b1, (outs GPR64:$Rd),
1096        (ins GPR64:$src, GPR64:$Rn, bitfield64_imm:$ImmR, bitfield64_imm:$ImmS),
1097        "bfm\t$Rd, $Rn, $ImmR, $ImmS", [], NoItinerary>,
1098  Sched<[WriteALU, ReadALU, ReadALU]> {
1099  let DecoderMethod = "DecodeBitfieldInstruction";
1100  let Constraints = "$src = $Rd";
1101}
1102
1103
1104//===-------------------------------
1105// 2. Extend aliases to 64-bit dest
1106//===-------------------------------
1107
1108// Unfortunately the extensions that end up as 64-bits cannot be handled by an
1109// instruction alias: their syntax is (for example) "SXTB x0, w0", which needs
1110// to be mapped to "SBFM x0, x0, #0, 7" (changing the class of Rn). InstAlias is
1111// not capable of such a map as far as I'm aware
1112
1113// Note that these instructions are strictly more specific than the
1114// BFM ones (in ImmR) so they can handle their own decoding.
1115class A64I_bf_ext<bit sf, bits<2> opc, RegisterClass GPRDest, ValueType dty,
1116                    string asmop, bits<6> imms, dag pattern>
1117  : A64I_bitfield<sf, opc, sf,
1118                  (outs GPRDest:$Rd), (ins GPR32:$Rn),
1119                  !strconcat(asmop, "\t$Rd, $Rn"),
1120                  [(set dty:$Rd, pattern)], NoItinerary>,
1121    Sched<[WriteALU, ReadALU]> {
1122  let ImmR = 0b000000;
1123  let ImmS = imms;
1124}
1125
1126// Signed extensions
1127def SXTBxw : A64I_bf_ext<0b1, 0b00, GPR64, i64, "sxtb", 7,
1128                         (sext_inreg (anyext i32:$Rn), i8)>;
1129def SXTBww : A64I_bf_ext<0b0, 0b00, GPR32, i32, "sxtb", 7,
1130                         (sext_inreg i32:$Rn, i8)>;
1131def SXTHxw : A64I_bf_ext<0b1, 0b00, GPR64, i64, "sxth", 15,
1132                         (sext_inreg (anyext i32:$Rn), i16)>;
1133def SXTHww : A64I_bf_ext<0b0, 0b00, GPR32, i32, "sxth", 15,
1134                         (sext_inreg i32:$Rn, i16)>;
1135def SXTWxw : A64I_bf_ext<0b1, 0b00, GPR64, i64, "sxtw", 31, (sext i32:$Rn)>;
1136
1137// Unsigned extensions
1138def UXTBww : A64I_bf_ext<0b0, 0b10, GPR32, i32, "uxtb", 7,
1139                         (and i32:$Rn, 255)>;
1140def UXTHww : A64I_bf_ext<0b0, 0b10, GPR32, i32, "uxth", 15,
1141                         (and i32:$Rn, 65535)>;
1142
1143// The 64-bit unsigned variants are not strictly architectural but recommended
1144// for consistency.
1145let isAsmParserOnly = 1 in {
1146  def UXTBxw : A64I_bf_ext<0b0, 0b10, GPR64, i64, "uxtb", 7,
1147                           (and (anyext i32:$Rn), 255)>;
1148  def UXTHxw : A64I_bf_ext<0b0, 0b10, GPR64, i64, "uxth", 15,
1149                           (and (anyext i32:$Rn), 65535)>;
1150}
1151
1152// Extra patterns for when the source register is actually 64-bits
1153// too. There's no architectural difference here, it's just LLVM
1154// shinanigans. There's no need for equivalent zero-extension patterns
1155// because they'll already be caught by logical (immediate) matching.
1156def : Pat<(sext_inreg i64:$Rn, i8),
1157          (SXTBxw (EXTRACT_SUBREG $Rn, sub_32))>;
1158def : Pat<(sext_inreg i64:$Rn, i16),
1159          (SXTHxw (EXTRACT_SUBREG $Rn, sub_32))>;
1160def : Pat<(sext_inreg i64:$Rn, i32),
1161          (SXTWxw (EXTRACT_SUBREG $Rn, sub_32))>;
1162
1163
1164//===-------------------------------
1165// 3. Aliases for ASR and LSR (the simple shifts)
1166//===-------------------------------
1167
1168// These also handle their own decoding because ImmS being set makes
1169// them take precedence over BFM.
1170multiclass A64I_shift<bits<2> opc, string asmop, SDNode opnode> {
1171  def wwi : A64I_bitfield<0b0, opc, 0b0,
1172                    (outs GPR32:$Rd), (ins GPR32:$Rn, bitfield32_imm:$ImmR),
1173                    !strconcat(asmop, "\t$Rd, $Rn, $ImmR"),
1174                    [(set i32:$Rd, (opnode i32:$Rn, bitfield32_imm:$ImmR))],
1175                    NoItinerary>,
1176            Sched<[WriteALU, ReadALU]> {
1177    let ImmS = 31;
1178  }
1179
1180  def xxi : A64I_bitfield<0b1, opc, 0b1,
1181                    (outs GPR64:$Rd), (ins GPR64:$Rn, bitfield64_imm:$ImmR),
1182                    !strconcat(asmop, "\t$Rd, $Rn, $ImmR"),
1183                    [(set i64:$Rd, (opnode i64:$Rn, bitfield64_imm:$ImmR))],
1184                    NoItinerary>,
1185            Sched<[WriteALU, ReadALU]> {
1186    let ImmS = 63;
1187  }
1188
1189}
1190
1191defm ASR : A64I_shift<0b00, "asr", sra>;
1192defm LSR : A64I_shift<0b10, "lsr", srl>;
1193
1194//===-------------------------------
1195// 4. Aliases for LSL
1196//===-------------------------------
1197
1198// Unfortunately LSL and subsequent aliases are much more complicated. We need
1199// to be able to say certain output instruction fields depend in a complex
1200// manner on combinations of input assembly fields).
1201//
1202// MIOperandInfo *might* have been able to do it, but at the cost of
1203// significantly more C++ code.
1204
1205// N.b. contrary to usual practice these operands store the shift rather than
1206// the machine bits in an MCInst. The complexity overhead of consistency
1207// outweighed the benefits in this case (custom asmparser, printer and selection
1208// vs custom encoder).
1209def bitfield32_lsl_imm : Operand<i64>,
1210                         ImmLeaf<i64, [{ return Imm >= 0 && Imm <= 31; }]> {
1211  let ParserMatchClass = uimm5_asmoperand;
1212  let EncoderMethod = "getBitfield32LSLOpValue";
1213}
1214
1215def bitfield64_lsl_imm : Operand<i64>,
1216                         ImmLeaf<i64, [{ return Imm >= 0 && Imm <= 63; }]> {
1217  let ParserMatchClass = uimm6_asmoperand;
1218  let EncoderMethod = "getBitfield64LSLOpValue";
1219}
1220
1221class A64I_bitfield_lsl<bit sf, RegisterClass GPR, ValueType ty,
1222                        Operand operand>
1223  : A64I_bitfield<sf, 0b10, sf, (outs GPR:$Rd), (ins GPR:$Rn, operand:$FullImm),
1224                  "lsl\t$Rd, $Rn, $FullImm",
1225                  [(set ty:$Rd, (shl ty:$Rn, operand:$FullImm))],
1226                  NoItinerary>,
1227    Sched<[WriteALU, ReadALU]> {
1228  bits<12> FullImm;
1229  let ImmR = FullImm{5-0};
1230  let ImmS = FullImm{11-6};
1231
1232  // No disassembler allowed because it would overlap with BFM which does the
1233  // actual work.
1234  let isAsmParserOnly = 1;
1235}
1236
1237def LSLwwi : A64I_bitfield_lsl<0b0, GPR32, i32, bitfield32_lsl_imm>;
1238def LSLxxi : A64I_bitfield_lsl<0b1, GPR64, i64, bitfield64_lsl_imm>;
1239
1240//===-------------------------------
1241// 5. Aliases for bitfield extract instructions
1242//===-------------------------------
1243
1244def bfx32_width_asmoperand : AsmOperandClass {
1245  let Name = "BFX32Width";
1246  let PredicateMethod = "isBitfieldWidth<32>";
1247  let RenderMethod = "addBFXWidthOperands";
1248  let DiagnosticType = "Width32";
1249}
1250
1251def bfx32_width : Operand<i64>, ImmLeaf<i64, [{ return true; }]> {
1252  let PrintMethod = "printBFXWidthOperand";
1253  let ParserMatchClass = bfx32_width_asmoperand;
1254}
1255
1256def bfx64_width_asmoperand : AsmOperandClass {
1257  let Name = "BFX64Width";
1258  let PredicateMethod = "isBitfieldWidth<64>";
1259  let RenderMethod = "addBFXWidthOperands";
1260  let DiagnosticType = "Width64";
1261}
1262
1263def bfx64_width : Operand<i64> {
1264  let PrintMethod = "printBFXWidthOperand";
1265  let ParserMatchClass = bfx64_width_asmoperand;
1266}
1267
1268
1269multiclass A64I_bitfield_extract<bits<2> opc, string asmop, SDNode op> {
1270  def wwii : A64I_bitfield<0b0, opc, 0b0, (outs GPR32:$Rd),
1271                       (ins GPR32:$Rn, bitfield32_imm:$ImmR, bfx32_width:$ImmS),
1272                       !strconcat(asmop, "\t$Rd, $Rn, $ImmR, $ImmS"),
1273                       [(set i32:$Rd, (op i32:$Rn, imm:$ImmR, imm:$ImmS))],
1274                       NoItinerary>,
1275             Sched<[WriteALU, ReadALU]> {
1276    // As above, no disassembler allowed.
1277    let isAsmParserOnly = 1;
1278  }
1279
1280  def xxii : A64I_bitfield<0b1, opc, 0b1, (outs GPR64:$Rd),
1281                       (ins GPR64:$Rn, bitfield64_imm:$ImmR, bfx64_width:$ImmS),
1282                       !strconcat(asmop, "\t$Rd, $Rn, $ImmR, $ImmS"),
1283                       [(set i64:$Rd, (op i64:$Rn, imm:$ImmR, imm:$ImmS))],
1284                       NoItinerary>,
1285             Sched<[WriteALU, ReadALU]> {
1286    // As above, no disassembler allowed.
1287    let isAsmParserOnly = 1;
1288  }
1289}
1290
1291defm SBFX :  A64I_bitfield_extract<0b00, "sbfx", A64Sbfx>;
1292defm UBFX :  A64I_bitfield_extract<0b10, "ubfx", A64Ubfx>;
1293
1294// Again, variants based on BFM modify Rd so need it as an input too.
1295def BFXILwwii : A64I_bitfield<0b0, 0b01, 0b0, (outs GPR32:$Rd),
1296                          (ins GPR32:$src, GPR32:$Rn, bitfield32_imm:$ImmR, bfx32_width:$ImmS),
1297                          "bfxil\t$Rd, $Rn, $ImmR, $ImmS", [], NoItinerary>,
1298                Sched<[WriteALU, ReadALU, ReadALU]> {
1299  // As above, no disassembler allowed.
1300  let isAsmParserOnly = 1;
1301  let Constraints = "$src = $Rd";
1302}
1303
1304def BFXILxxii : A64I_bitfield<0b1, 0b01, 0b1, (outs GPR64:$Rd),
1305                          (ins GPR64:$src, GPR64:$Rn, bitfield64_imm:$ImmR, bfx64_width:$ImmS),
1306                          "bfxil\t$Rd, $Rn, $ImmR, $ImmS", [], NoItinerary>,
1307                Sched<[WriteALU, ReadALU, ReadALU]> {
1308  // As above, no disassembler allowed.
1309  let isAsmParserOnly = 1;
1310  let Constraints = "$src = $Rd";
1311}
1312
1313// SBFX instructions can do a 1-instruction sign-extension of boolean values.
1314def : Pat<(sext_inreg i64:$Rn, i1), (SBFXxxii $Rn, 0, 0)>;
1315def : Pat<(sext_inreg i32:$Rn, i1), (SBFXwwii $Rn, 0, 0)>;
1316def : Pat<(i64 (sext_inreg (anyext i32:$Rn), i1)),
1317          (SBFXxxii (SUBREG_TO_REG (i64 0), $Rn, sub_32), 0, 0)>;
1318
1319// UBFX makes sense as an implementation of a 64-bit zero-extension too. Could
1320// use either 64-bit or 32-bit variant, but 32-bit might be more efficient.
1321def : Pat<(i64 (zext i32:$Rn)), (SUBREG_TO_REG (i64 0), (UBFXwwii $Rn, 0, 31),
1322                                         sub_32)>;
1323
1324//===-------------------------------
1325// 6. Aliases for bitfield insert instructions
1326//===-------------------------------
1327
1328def bfi32_lsb_asmoperand : AsmOperandClass {
1329  let Name = "BFI32LSB";
1330  let PredicateMethod = "isUImm<5>";
1331  let RenderMethod = "addBFILSBOperands<32>";
1332  let DiagnosticType = "UImm5";
1333}
1334
1335def bfi32_lsb : Operand<i64>,
1336                ImmLeaf<i64, [{ return Imm >= 0 && Imm <= 31; }]> {
1337  let PrintMethod = "printBFILSBOperand<32>";
1338  let ParserMatchClass = bfi32_lsb_asmoperand;
1339}
1340
1341def bfi64_lsb_asmoperand : AsmOperandClass {
1342  let Name = "BFI64LSB";
1343  let PredicateMethod = "isUImm<6>";
1344  let RenderMethod = "addBFILSBOperands<64>";
1345  let DiagnosticType = "UImm6";
1346}
1347
1348def bfi64_lsb : Operand<i64>,
1349                ImmLeaf<i64, [{ return Imm >= 0 && Imm <= 63; }]> {
1350  let PrintMethod = "printBFILSBOperand<64>";
1351  let ParserMatchClass = bfi64_lsb_asmoperand;
1352}
1353
1354// Width verification is performed during conversion so width operand can be
1355// shared between 32/64-bit cases. Still needed for the print method though
1356// because ImmR encodes "width - 1".
1357def bfi32_width_asmoperand : AsmOperandClass {
1358  let Name = "BFI32Width";
1359  let PredicateMethod = "isBitfieldWidth<32>";
1360  let RenderMethod = "addBFIWidthOperands";
1361  let DiagnosticType = "Width32";
1362}
1363
1364def bfi32_width : Operand<i64>,
1365                  ImmLeaf<i64, [{ return Imm >= 1 && Imm <= 32; }]> {
1366  let PrintMethod = "printBFIWidthOperand";
1367  let ParserMatchClass = bfi32_width_asmoperand;
1368}
1369
1370def bfi64_width_asmoperand : AsmOperandClass {
1371  let Name = "BFI64Width";
1372  let PredicateMethod = "isBitfieldWidth<64>";
1373  let RenderMethod = "addBFIWidthOperands";
1374  let DiagnosticType = "Width64";
1375}
1376
1377def bfi64_width : Operand<i64>,
1378                  ImmLeaf<i64, [{ return Imm >= 1 && Imm <= 64; }]> {
1379  let PrintMethod = "printBFIWidthOperand";
1380  let ParserMatchClass = bfi64_width_asmoperand;
1381}
1382
1383multiclass A64I_bitfield_insert<bits<2> opc, string asmop> {
1384  def wwii : A64I_bitfield<0b0, opc, 0b0, (outs GPR32:$Rd),
1385                           (ins GPR32:$Rn, bfi32_lsb:$ImmR, bfi32_width:$ImmS),
1386                           !strconcat(asmop, "\t$Rd, $Rn, $ImmR, $ImmS"),
1387                           [], NoItinerary>,
1388             Sched<[WriteALU, ReadALU]> {
1389    // As above, no disassembler allowed.
1390    let isAsmParserOnly = 1;
1391  }
1392
1393  def xxii : A64I_bitfield<0b1, opc, 0b1, (outs GPR64:$Rd),
1394                           (ins GPR64:$Rn, bfi64_lsb:$ImmR, bfi64_width:$ImmS),
1395                           !strconcat(asmop, "\t$Rd, $Rn, $ImmR, $ImmS"),
1396                           [], NoItinerary>,
1397             Sched<[WriteALU, ReadALU]> {
1398    // As above, no disassembler allowed.
1399    let isAsmParserOnly = 1;
1400  }
1401}
1402
1403defm SBFIZ :  A64I_bitfield_insert<0b00, "sbfiz">;
1404defm UBFIZ :  A64I_bitfield_insert<0b10, "ubfiz">;
1405
1406
1407def BFIwwii : A64I_bitfield<0b0, 0b01, 0b0, (outs GPR32:$Rd),
1408                (ins GPR32:$src, GPR32:$Rn, bfi32_lsb:$ImmR, bfi32_width:$ImmS),
1409                "bfi\t$Rd, $Rn, $ImmR, $ImmS", [], NoItinerary>,
1410              Sched<[WriteALU, ReadALU, ReadALU]> {
1411  // As above, no disassembler allowed.
1412  let isAsmParserOnly = 1;
1413  let Constraints = "$src = $Rd";
1414}
1415
1416def BFIxxii : A64I_bitfield<0b1, 0b01, 0b1, (outs GPR64:$Rd),
1417                (ins GPR64:$src, GPR64:$Rn, bfi64_lsb:$ImmR, bfi64_width:$ImmS),
1418                "bfi\t$Rd, $Rn, $ImmR, $ImmS", [], NoItinerary>,
1419              Sched<[WriteALU, ReadALU, ReadALU]> {
1420  // As above, no disassembler allowed.
1421  let isAsmParserOnly = 1;
1422  let Constraints = "$src = $Rd";
1423}
1424
1425//===----------------------------------------------------------------------===//
1426// Compare and branch (immediate)
1427//===----------------------------------------------------------------------===//
1428// Contains: CBZ, CBNZ
1429
1430class label_asmoperand<int width, int scale> : AsmOperandClass {
1431  let Name = "Label" # width # "_" # scale;
1432  let PredicateMethod = "isLabel<" # width # "," # scale # ">";
1433  let RenderMethod = "addLabelOperands<" # width # ", " # scale # ">";
1434  let DiagnosticType = "Label";
1435}
1436
1437def label_wid19_scal4_asmoperand : label_asmoperand<19, 4>;
1438
1439// All conditional immediate branches are the same really: 19 signed bits scaled
1440// by the instruction-size (4).
1441def bcc_target : Operand<OtherVT> {
1442  // This label is a 19-bit offset from PC, scaled by the instruction-width: 4.
1443  let ParserMatchClass = label_wid19_scal4_asmoperand;
1444  let PrintMethod = "printLabelOperand<19, 4>";
1445  let EncoderMethod = "getLabelOpValue<AArch64::fixup_a64_condbr>";
1446  let OperandType = "OPERAND_PCREL";
1447}
1448
1449multiclass cmpbr_sizes<bit op, string asmop, ImmLeaf SETOP> {
1450  let isBranch = 1, isTerminator = 1 in {
1451  def x : A64I_cmpbr<0b1, op,
1452                     (outs),
1453                     (ins GPR64:$Rt, bcc_target:$Label),
1454                     !strconcat(asmop,"\t$Rt, $Label"),
1455                     [(A64br_cc (A64cmp i64:$Rt, 0), SETOP, bb:$Label)],
1456                     NoItinerary>,
1457          Sched<[WriteBr, ReadBr]>;
1458
1459  def w : A64I_cmpbr<0b0, op,
1460                     (outs),
1461                     (ins GPR32:$Rt, bcc_target:$Label),
1462                     !strconcat(asmop,"\t$Rt, $Label"),
1463                     [(A64br_cc (A64cmp i32:$Rt, 0), SETOP, bb:$Label)],
1464                     NoItinerary>,
1465          Sched<[WriteBr, ReadBr]>;
1466  }
1467}
1468
1469defm CBZ  : cmpbr_sizes<0b0, "cbz",  ImmLeaf<i32, [{
1470  return Imm == A64CC::EQ;
1471}]> >;
1472defm CBNZ : cmpbr_sizes<0b1, "cbnz", ImmLeaf<i32, [{
1473  return Imm == A64CC::NE;
1474}]> >;
1475
1476//===----------------------------------------------------------------------===//
1477// Conditional branch (immediate) instructions
1478//===----------------------------------------------------------------------===//
1479// Contains: B.cc
1480
1481def cond_code_asmoperand : AsmOperandClass {
1482  let Name = "CondCode";
1483  let DiagnosticType = "CondCode";
1484}
1485
1486def cond_code : Operand<i32>, ImmLeaf<i32, [{
1487  return Imm >= 0 && Imm <= 15;
1488}]> {
1489  let PrintMethod = "printCondCodeOperand";
1490  let ParserMatchClass = cond_code_asmoperand;
1491}
1492
1493def Bcc : A64I_condbr<0b0, 0b0, (outs),
1494                (ins cond_code:$Cond, bcc_target:$Label),
1495                "b.$Cond $Label", [(A64br_cc NZCV, (i32 imm:$Cond), bb:$Label)],
1496                NoItinerary>,
1497          Sched<[WriteBr]> {
1498  let Uses = [NZCV];
1499  let isBranch = 1;
1500  let isTerminator = 1;
1501}
1502
1503//===----------------------------------------------------------------------===//
1504// Conditional compare (immediate) instructions
1505//===----------------------------------------------------------------------===//
1506// Contains: CCMN, CCMP
1507
1508def uimm4_asmoperand : AsmOperandClass {
1509  let Name = "UImm4";
1510  let PredicateMethod = "isUImm<4>";
1511  let RenderMethod = "addImmOperands";
1512  let DiagnosticType = "UImm4";
1513}
1514
1515def uimm4 : Operand<i32> {
1516  let ParserMatchClass = uimm4_asmoperand;
1517}
1518
1519def uimm5 : Operand<i32> {
1520  let ParserMatchClass = uimm5_asmoperand;
1521}
1522
1523// The only difference between this operand and the one for instructions like
1524// B.cc is that it's parsed manually. The other get parsed implicitly as part of
1525// the mnemonic handling.
1526def cond_code_op_asmoperand : AsmOperandClass {
1527  let Name = "CondCodeOp";
1528  let RenderMethod = "addCondCodeOperands";
1529  let PredicateMethod = "isCondCode";
1530  let ParserMethod = "ParseCondCodeOperand";
1531  let DiagnosticType = "CondCode";
1532}
1533
1534def cond_code_op : Operand<i32> {
1535  let PrintMethod = "printCondCodeOperand";
1536  let ParserMatchClass = cond_code_op_asmoperand;
1537}
1538
1539class A64I_condcmpimmImpl<bit sf, bit op, RegisterClass GPR, string asmop>
1540  : A64I_condcmpimm<sf, op, 0b0, 0b0, 0b1, (outs),
1541                (ins GPR:$Rn, uimm5:$UImm5, uimm4:$NZCVImm, cond_code_op:$Cond),
1542                !strconcat(asmop, "\t$Rn, $UImm5, $NZCVImm, $Cond"),
1543                [], NoItinerary>,
1544    Sched<[WriteCMP, ReadCMP]> {
1545  let Defs = [NZCV];
1546}
1547
1548def CCMNwi : A64I_condcmpimmImpl<0b0, 0b0, GPR32, "ccmn">;
1549def CCMNxi : A64I_condcmpimmImpl<0b1, 0b0, GPR64, "ccmn">;
1550def CCMPwi : A64I_condcmpimmImpl<0b0, 0b1, GPR32, "ccmp">;
1551def CCMPxi : A64I_condcmpimmImpl<0b1, 0b1, GPR64, "ccmp">;
1552
1553//===----------------------------------------------------------------------===//
1554// Conditional compare (register) instructions
1555//===----------------------------------------------------------------------===//
1556// Contains: CCMN, CCMP
1557
1558class A64I_condcmpregImpl<bit sf, bit op, RegisterClass GPR, string asmop>
1559  : A64I_condcmpreg<sf, op, 0b0, 0b0, 0b1,
1560                    (outs),
1561                    (ins GPR:$Rn, GPR:$Rm, uimm4:$NZCVImm, cond_code_op:$Cond),
1562                    !strconcat(asmop, "\t$Rn, $Rm, $NZCVImm, $Cond"),
1563                    [], NoItinerary>,
1564    Sched<[WriteCMP, ReadCMP, ReadCMP]> {
1565  let Defs = [NZCV];
1566}
1567
1568def CCMNww : A64I_condcmpregImpl<0b0, 0b0, GPR32, "ccmn">;
1569def CCMNxx : A64I_condcmpregImpl<0b1, 0b0, GPR64, "ccmn">;
1570def CCMPww : A64I_condcmpregImpl<0b0, 0b1, GPR32, "ccmp">;
1571def CCMPxx : A64I_condcmpregImpl<0b1, 0b1, GPR64, "ccmp">;
1572
1573//===----------------------------------------------------------------------===//
1574// Conditional select instructions
1575//===----------------------------------------------------------------------===//
1576// Contains: CSEL, CSINC, CSINV, CSNEG + aliases CSET, CSETM, CINC, CINV, CNEG
1577
1578// Condition code which is encoded as the inversion (semantically rather than
1579// bitwise) in the instruction.
1580def inv_cond_code_op_asmoperand : AsmOperandClass {
1581  let Name = "InvCondCodeOp";
1582  let RenderMethod = "addInvCondCodeOperands";
1583  let PredicateMethod = "isCondCode";
1584  let ParserMethod = "ParseCondCodeOperand";
1585  let DiagnosticType = "CondCode";
1586}
1587
1588def inv_cond_code_op : Operand<i32> {
1589  let ParserMatchClass = inv_cond_code_op_asmoperand;
1590}
1591
1592// Having a separate operand for the selectable use-case is debatable, but gives
1593// consistency with cond_code.
1594def inv_cond_XFORM : SDNodeXForm<imm, [{
1595  A64CC::CondCodes CC = static_cast<A64CC::CondCodes>(N->getZExtValue());
1596  return CurDAG->getTargetConstant(A64InvertCondCode(CC), MVT::i32);
1597}]>;
1598
1599def inv_cond_code
1600  : ImmLeaf<i32, [{ return Imm >= 0 && Imm <= 15; }], inv_cond_XFORM>;
1601
1602
1603multiclass A64I_condselSizes<bit op, bits<2> op2, string asmop,
1604                             SDPatternOperator select> {
1605  let Uses = [NZCV] in {
1606    def wwwc : A64I_condsel<0b0, op, 0b0, op2,
1607                            (outs GPR32:$Rd),
1608                            (ins GPR32:$Rn, GPR32:$Rm, cond_code_op:$Cond),
1609                            !strconcat(asmop, "\t$Rd, $Rn, $Rm, $Cond"),
1610                            [(set i32:$Rd, (select i32:$Rn, i32:$Rm))],
1611                            NoItinerary>,
1612               Sched<[WriteCMP, ReadCMP, ReadCMP]>;
1613
1614
1615    def xxxc : A64I_condsel<0b1, op, 0b0, op2,
1616                            (outs GPR64:$Rd),
1617                            (ins GPR64:$Rn, GPR64:$Rm, cond_code_op:$Cond),
1618                            !strconcat(asmop, "\t$Rd, $Rn, $Rm, $Cond"),
1619                            [(set i64:$Rd, (select i64:$Rn, i64:$Rm))],
1620                            NoItinerary>,
1621               Sched<[WriteCMP, ReadCMP, ReadCMP]>;
1622  }
1623}
1624
1625def simple_select
1626  : PatFrag<(ops node:$lhs, node:$rhs),
1627            (A64select_cc NZCV, node:$lhs, node:$rhs, (i32 imm:$Cond))>;
1628
1629class complex_select<SDPatternOperator opnode>
1630  : PatFrag<(ops node:$lhs, node:$rhs),
1631        (A64select_cc NZCV, node:$lhs, (opnode node:$rhs), (i32 imm:$Cond))>;
1632
1633
1634defm CSEL : A64I_condselSizes<0b0, 0b00, "csel", simple_select>;
1635defm CSINC : A64I_condselSizes<0b0, 0b01, "csinc",
1636                               complex_select<PatFrag<(ops node:$val),
1637                                                      (add node:$val, 1)>>>;
1638defm CSINV : A64I_condselSizes<0b1, 0b00, "csinv", complex_select<not>>;
1639defm CSNEG : A64I_condselSizes<0b1, 0b01, "csneg", complex_select<ineg>>;
1640
1641// Now the instruction aliases, which fit nicely into LLVM's model:
1642
1643def : InstAlias<"cset $Rd, $Cond",
1644                (CSINCwwwc GPR32:$Rd, WZR, WZR, inv_cond_code_op:$Cond)>;
1645def : InstAlias<"cset $Rd, $Cond",
1646                (CSINCxxxc GPR64:$Rd, XZR, XZR, inv_cond_code_op:$Cond)>;
1647def : InstAlias<"csetm $Rd, $Cond",
1648                (CSINVwwwc GPR32:$Rd, WZR, WZR, inv_cond_code_op:$Cond)>;
1649def : InstAlias<"csetm $Rd, $Cond",
1650                (CSINVxxxc GPR64:$Rd, XZR, XZR, inv_cond_code_op:$Cond)>;
1651def : InstAlias<"cinc $Rd, $Rn, $Cond",
1652           (CSINCwwwc GPR32:$Rd, GPR32:$Rn, GPR32:$Rn, inv_cond_code_op:$Cond)>;
1653def : InstAlias<"cinc $Rd, $Rn, $Cond",
1654           (CSINCxxxc GPR64:$Rd, GPR64:$Rn, GPR64:$Rn, inv_cond_code_op:$Cond)>;
1655def : InstAlias<"cinv $Rd, $Rn, $Cond",
1656           (CSINVwwwc GPR32:$Rd, GPR32:$Rn, GPR32:$Rn, inv_cond_code_op:$Cond)>;
1657def : InstAlias<"cinv $Rd, $Rn, $Cond",
1658           (CSINVxxxc GPR64:$Rd, GPR64:$Rn, GPR64:$Rn, inv_cond_code_op:$Cond)>;
1659def : InstAlias<"cneg $Rd, $Rn, $Cond",
1660           (CSNEGwwwc GPR32:$Rd, GPR32:$Rn, GPR32:$Rn, inv_cond_code_op:$Cond)>;
1661def : InstAlias<"cneg $Rd, $Rn, $Cond",
1662           (CSNEGxxxc GPR64:$Rd, GPR64:$Rn, GPR64:$Rn, inv_cond_code_op:$Cond)>;
1663
1664// Finally some helper patterns.
1665
1666// For CSET (a.k.a. zero-extension of icmp)
1667def : Pat<(A64select_cc NZCV, 0, 1, cond_code:$Cond),
1668          (CSINCwwwc WZR, WZR, cond_code:$Cond)>;
1669def : Pat<(A64select_cc NZCV, 1, 0, inv_cond_code:$Cond),
1670          (CSINCwwwc WZR, WZR, inv_cond_code:$Cond)>;
1671
1672def : Pat<(A64select_cc NZCV, 0, 1, cond_code:$Cond),
1673          (CSINCxxxc XZR, XZR, cond_code:$Cond)>;
1674def : Pat<(A64select_cc NZCV, 1, 0, inv_cond_code:$Cond),
1675          (CSINCxxxc XZR, XZR, inv_cond_code:$Cond)>;
1676
1677// For CSETM (a.k.a. sign-extension of icmp)
1678def : Pat<(A64select_cc NZCV, 0, -1, cond_code:$Cond),
1679          (CSINVwwwc WZR, WZR, cond_code:$Cond)>;
1680def : Pat<(A64select_cc NZCV, -1, 0, inv_cond_code:$Cond),
1681          (CSINVwwwc WZR, WZR, inv_cond_code:$Cond)>;
1682
1683def : Pat<(A64select_cc NZCV, 0, -1, cond_code:$Cond),
1684          (CSINVxxxc XZR, XZR, cond_code:$Cond)>;
1685def : Pat<(A64select_cc NZCV, -1, 0, inv_cond_code:$Cond),
1686          (CSINVxxxc XZR, XZR, inv_cond_code:$Cond)>;
1687
1688// CINC, CINV and CNEG get dealt with automatically, which leaves the issue of
1689// commutativity. The instructions are to complex for isCommutable to be used,
1690// so we have to create the patterns manually:
1691
1692// No commutable pattern for CSEL since the commuted version is isomorphic.
1693
1694// CSINC
1695def :Pat<(A64select_cc NZCV, (add i32:$Rm, 1), i32:$Rn, inv_cond_code:$Cond),
1696         (CSINCwwwc $Rn, $Rm, inv_cond_code:$Cond)>;
1697def :Pat<(A64select_cc NZCV, (add i64:$Rm, 1), i64:$Rn, inv_cond_code:$Cond),
1698         (CSINCxxxc $Rn, $Rm, inv_cond_code:$Cond)>;
1699
1700// CSINV
1701def :Pat<(A64select_cc NZCV, (not i32:$Rm), i32:$Rn, inv_cond_code:$Cond),
1702         (CSINVwwwc $Rn, $Rm, inv_cond_code:$Cond)>;
1703def :Pat<(A64select_cc NZCV, (not i64:$Rm), i64:$Rn, inv_cond_code:$Cond),
1704         (CSINVxxxc $Rn, $Rm, inv_cond_code:$Cond)>;
1705
1706// CSNEG
1707def :Pat<(A64select_cc NZCV, (ineg i32:$Rm), i32:$Rn, inv_cond_code:$Cond),
1708         (CSNEGwwwc $Rn, $Rm, inv_cond_code:$Cond)>;
1709def :Pat<(A64select_cc NZCV, (ineg i64:$Rm), i64:$Rn, inv_cond_code:$Cond),
1710         (CSNEGxxxc $Rn, $Rm, inv_cond_code:$Cond)>;
1711
1712//===----------------------------------------------------------------------===//
1713// Data Processing (1 source) instructions
1714//===----------------------------------------------------------------------===//
1715// Contains: RBIT, REV16, REV, REV32, CLZ, CLS.
1716
1717// We define an unary operator which always fails. We will use this to
1718// define unary operators that cannot be matched.
1719
1720class A64I_dp_1src_impl<bit sf, bits<6> opcode, string asmop,
1721                   list<dag> patterns, RegisterClass GPRrc,
1722                   InstrItinClass itin>:
1723      A64I_dp_1src<sf,
1724                   0,
1725                   0b00000,
1726                   opcode,
1727                   !strconcat(asmop, "\t$Rd, $Rn"),
1728                   (outs GPRrc:$Rd),
1729                   (ins GPRrc:$Rn),
1730                   patterns,
1731                   itin>,
1732      Sched<[WriteALU, ReadALU]>;
1733
1734multiclass A64I_dp_1src <bits<6> opcode, string asmop> {
1735  let hasSideEffects = 0 in {
1736    def ww : A64I_dp_1src_impl<0b0, opcode, asmop, [], GPR32, NoItinerary>;
1737    def xx : A64I_dp_1src_impl<0b1, opcode, asmop, [], GPR64, NoItinerary>;
1738  }
1739}
1740
1741defm RBIT  : A64I_dp_1src<0b000000, "rbit">;
1742defm CLS   : A64I_dp_1src<0b000101, "cls">;
1743defm CLZ   : A64I_dp_1src<0b000100, "clz">;
1744
1745def : Pat<(ctlz i32:$Rn), (CLZww $Rn)>;
1746def : Pat<(ctlz i64:$Rn), (CLZxx $Rn)>;
1747def : Pat<(ctlz_zero_undef i32:$Rn), (CLZww $Rn)>;
1748def : Pat<(ctlz_zero_undef i64:$Rn), (CLZxx $Rn)>;
1749
1750def : Pat<(cttz i32:$Rn), (CLZww (RBITww $Rn))>;
1751def : Pat<(cttz i64:$Rn), (CLZxx (RBITxx $Rn))>;
1752def : Pat<(cttz_zero_undef i32:$Rn), (CLZww (RBITww $Rn))>;
1753def : Pat<(cttz_zero_undef i64:$Rn), (CLZxx (RBITxx $Rn))>;
1754
1755
1756def REVww : A64I_dp_1src_impl<0b0, 0b000010, "rev",
1757                              [(set i32:$Rd, (bswap i32:$Rn))],
1758                              GPR32, NoItinerary>;
1759def REVxx : A64I_dp_1src_impl<0b1, 0b000011, "rev",
1760                              [(set i64:$Rd, (bswap i64:$Rn))],
1761                              GPR64, NoItinerary>;
1762def REV32xx : A64I_dp_1src_impl<0b1, 0b000010, "rev32",
1763                          [(set i64:$Rd, (bswap (rotr i64:$Rn, (i64 32))))],
1764                          GPR64, NoItinerary>;
1765def REV16ww : A64I_dp_1src_impl<0b0, 0b000001, "rev16",
1766                          [(set i32:$Rd, (bswap (rotr i32:$Rn, (i64 16))))],
1767                          GPR32,
1768                          NoItinerary>;
1769def REV16xx : A64I_dp_1src_impl<0b1, 0b000001, "rev16", [], GPR64, NoItinerary>;
1770
1771//===----------------------------------------------------------------------===//
1772// Data Processing (2 sources) instructions
1773//===----------------------------------------------------------------------===//
1774// Contains: CRC32C?[BHWX], UDIV, SDIV, LSLV, LSRV, ASRV, RORV + aliases LSL,
1775//           LSR, ASR, ROR
1776
1777
1778class dp_2src_impl<bit sf, bits<6> opcode, string asmop, list<dag> patterns,
1779                   RegisterClass GPRsp,
1780                   InstrItinClass itin>:
1781      A64I_dp_2src<sf,
1782                   opcode,
1783                   0,
1784                   !strconcat(asmop, "\t$Rd, $Rn, $Rm"),
1785                   (outs GPRsp:$Rd),
1786                   (ins GPRsp:$Rn, GPRsp:$Rm),
1787                   patterns,
1788                   itin>,
1789	  Sched<[WriteALU, ReadALU, ReadALU]>;
1790
1791multiclass dp_2src_crc<bit c, string asmop> {
1792  def B_www : dp_2src_impl<0b0, {0, 1, 0, c, 0, 0},
1793                           !strconcat(asmop, "b"), [], GPR32, NoItinerary>;
1794  def H_www : dp_2src_impl<0b0, {0, 1, 0, c, 0, 1},
1795                           !strconcat(asmop, "h"), [], GPR32, NoItinerary>;
1796  def W_www : dp_2src_impl<0b0, {0, 1, 0, c, 1, 0},
1797                           !strconcat(asmop, "w"), [], GPR32, NoItinerary>;
1798  def X_wwx : A64I_dp_2src<0b1, {0, 1, 0, c, 1, 1}, 0b0,
1799                           !strconcat(asmop, "x\t$Rd, $Rn, $Rm"),
1800                           (outs GPR32:$Rd), (ins GPR32:$Rn, GPR64:$Rm), [],
1801                           NoItinerary>,
1802	          Sched<[WriteALU, ReadALU, ReadALU]>;
1803}
1804
1805multiclass dp_2src_zext <bits<6> opcode, string asmop, SDPatternOperator op> {
1806   def www : dp_2src_impl<0b0,
1807                         opcode,
1808                         asmop,
1809                         [(set i32:$Rd,
1810                               (op i32:$Rn, (i64 (zext i32:$Rm))))],
1811                         GPR32,
1812                         NoItinerary>;
1813   def xxx : dp_2src_impl<0b1,
1814                         opcode,
1815                         asmop,
1816                         [(set i64:$Rd, (op i64:$Rn, i64:$Rm))],
1817                         GPR64,
1818                         NoItinerary>;
1819}
1820
1821
1822multiclass dp_2src <bits<6> opcode, string asmop, SDPatternOperator op> {
1823    def www : dp_2src_impl<0b0,
1824                         opcode,
1825                         asmop,
1826                         [(set i32:$Rd, (op i32:$Rn, i32:$Rm))],
1827                         GPR32,
1828                         NoItinerary>;
1829   def xxx : dp_2src_impl<0b1,
1830                         opcode,
1831                         asmop,
1832                         [(set i64:$Rd, (op i64:$Rn, i64:$Rm))],
1833                         GPR64,
1834                         NoItinerary>;
1835}
1836
1837// Here we define the data processing 2 source instructions.
1838defm CRC32  : dp_2src_crc<0b0, "crc32">;
1839defm CRC32C : dp_2src_crc<0b1, "crc32c">;
1840
1841let SchedRW = [WriteDiv, ReadDiv, ReadDiv] in {
1842  defm UDIV : dp_2src<0b000010, "udiv", udiv>;
1843  defm SDIV : dp_2src<0b000011, "sdiv", sdiv>;
1844}
1845
1846let SchedRW = [WriteALUs, ReadALU, ReadALU] in {
1847  defm LSLV : dp_2src_zext<0b001000, "lsl", shl>;
1848  defm LSRV : dp_2src_zext<0b001001, "lsr", srl>;
1849  defm ASRV : dp_2src_zext<0b001010, "asr", sra>;
1850  defm RORV : dp_2src_zext<0b001011, "ror", rotr>;
1851}
1852
1853// Extra patterns for an incoming 64-bit value for a 32-bit
1854// operation. Since the LLVM operations are undefined (as in C) if the
1855// RHS is out of range, it's perfectly permissible to discard the high
1856// bits of the GPR64.
1857def : Pat<(shl i32:$Rn, i64:$Rm),
1858          (LSLVwww $Rn, (EXTRACT_SUBREG $Rm, sub_32))>;
1859def : Pat<(srl i32:$Rn, i64:$Rm),
1860          (LSRVwww $Rn, (EXTRACT_SUBREG $Rm, sub_32))>;
1861def : Pat<(sra i32:$Rn, i64:$Rm),
1862          (ASRVwww $Rn, (EXTRACT_SUBREG $Rm, sub_32))>;
1863def : Pat<(rotr i32:$Rn, i64:$Rm),
1864          (RORVwww $Rn, (EXTRACT_SUBREG $Rm, sub_32))>;
1865
1866// Here we define the aliases for the data processing 2 source instructions.
1867def LSL_mnemonic : MnemonicAlias<"lslv", "lsl">;
1868def LSR_mnemonic : MnemonicAlias<"lsrv", "lsr">;
1869def ASR_menmonic : MnemonicAlias<"asrv", "asr">;
1870def ROR_menmonic : MnemonicAlias<"rorv", "ror">;
1871
1872//===----------------------------------------------------------------------===//
1873// Data Processing (3 sources) instructions
1874//===----------------------------------------------------------------------===//
1875// Contains: MADD, MSUB, SMADDL, SMSUBL, SMULH, UMADDL, UMSUBL, UMULH
1876//    + aliases MUL, MNEG, SMULL, SMNEGL, UMULL, UMNEGL
1877
1878class A64I_dp3_4operand<bit sf, bits<6> opcode, RegisterClass AccReg,
1879                        ValueType AccTy, RegisterClass SrcReg,
1880                        string asmop, dag pattern>
1881  : A64I_dp3<sf, opcode,
1882             (outs AccReg:$Rd), (ins SrcReg:$Rn, SrcReg:$Rm, AccReg:$Ra),
1883             !strconcat(asmop, "\t$Rd, $Rn, $Rm, $Ra"),
1884             [(set AccTy:$Rd, pattern)], NoItinerary>,
1885    Sched<[WriteMAC, ReadMAC, ReadMAC, ReadMAC]> {
1886  bits<5> Ra;
1887  let Inst{14-10} = Ra;
1888
1889  RegisterClass AccGPR = AccReg;
1890  RegisterClass SrcGPR = SrcReg;
1891}
1892
1893def MADDwwww : A64I_dp3_4operand<0b0, 0b000000, GPR32, i32, GPR32, "madd",
1894                                 (add i32:$Ra, (mul i32:$Rn, i32:$Rm))>;
1895def MADDxxxx : A64I_dp3_4operand<0b1, 0b000000, GPR64, i64, GPR64, "madd",
1896                                 (add i64:$Ra, (mul i64:$Rn, i64:$Rm))>;
1897
1898def MSUBwwww : A64I_dp3_4operand<0b0, 0b000001, GPR32, i32, GPR32, "msub",
1899                                 (sub i32:$Ra, (mul i32:$Rn, i32:$Rm))>;
1900def MSUBxxxx : A64I_dp3_4operand<0b1, 0b000001, GPR64, i64, GPR64, "msub",
1901                                 (sub i64:$Ra, (mul i64:$Rn, i64:$Rm))>;
1902
1903def SMADDLxwwx : A64I_dp3_4operand<0b1, 0b000010, GPR64, i64, GPR32, "smaddl",
1904                     (add i64:$Ra, (mul (i64 (sext i32:$Rn)), (sext i32:$Rm)))>;
1905def SMSUBLxwwx : A64I_dp3_4operand<0b1, 0b000011, GPR64, i64, GPR32, "smsubl",
1906                     (sub i64:$Ra, (mul (i64 (sext i32:$Rn)), (sext i32:$Rm)))>;
1907
1908def UMADDLxwwx : A64I_dp3_4operand<0b1, 0b001010, GPR64, i64, GPR32, "umaddl",
1909                     (add i64:$Ra, (mul (i64 (zext i32:$Rn)), (zext i32:$Rm)))>;
1910def UMSUBLxwwx : A64I_dp3_4operand<0b1, 0b001011, GPR64, i64, GPR32, "umsubl",
1911                     (sub i64:$Ra, (mul (i64 (zext i32:$Rn)), (zext i32:$Rm)))>;
1912
1913let isCommutable = 1, PostEncoderMethod = "fixMulHigh" in {
1914  def UMULHxxx : A64I_dp3<0b1, 0b001100, (outs GPR64:$Rd),
1915                          (ins GPR64:$Rn, GPR64:$Rm),
1916                          "umulh\t$Rd, $Rn, $Rm",
1917                          [(set i64:$Rd, (mulhu i64:$Rn, i64:$Rm))],
1918                          NoItinerary>,
1919                 Sched<[WriteMAC, ReadMAC, ReadMAC]>;
1920
1921  def SMULHxxx : A64I_dp3<0b1, 0b000100, (outs GPR64:$Rd),
1922                          (ins GPR64:$Rn, GPR64:$Rm),
1923                          "smulh\t$Rd, $Rn, $Rm",
1924                          [(set i64:$Rd, (mulhs i64:$Rn, i64:$Rm))],
1925                          NoItinerary>,
1926                 Sched<[WriteMAC, ReadMAC, ReadMAC]>;
1927}
1928
1929multiclass A64I_dp3_3operand<string asmop, A64I_dp3_4operand INST,
1930                             Register ZR, dag pattern> {
1931  def : InstAlias<asmop # " $Rd, $Rn, $Rm",
1932                  (INST INST.AccGPR:$Rd, INST.SrcGPR:$Rn, INST.SrcGPR:$Rm, ZR)>;
1933
1934  def : Pat<pattern, (INST $Rn, $Rm, ZR)>;
1935}
1936
1937defm : A64I_dp3_3operand<"mul", MADDwwww, WZR, (mul i32:$Rn, i32:$Rm)>;
1938defm : A64I_dp3_3operand<"mul", MADDxxxx, XZR, (mul i64:$Rn, i64:$Rm)>;
1939
1940defm : A64I_dp3_3operand<"mneg", MSUBwwww, WZR,
1941                         (sub 0, (mul i32:$Rn, i32:$Rm))>;
1942defm : A64I_dp3_3operand<"mneg", MSUBxxxx, XZR,
1943                         (sub 0, (mul i64:$Rn, i64:$Rm))>;
1944
1945defm : A64I_dp3_3operand<"smull", SMADDLxwwx, XZR,
1946                         (mul (i64 (sext i32:$Rn)), (sext i32:$Rm))>;
1947defm : A64I_dp3_3operand<"smnegl", SMSUBLxwwx, XZR,
1948                       (sub 0, (mul (i64 (sext i32:$Rn)), (sext i32:$Rm)))>;
1949
1950defm : A64I_dp3_3operand<"umull", UMADDLxwwx, XZR,
1951                         (mul (i64 (zext i32:$Rn)), (zext i32:$Rm))>;
1952defm : A64I_dp3_3operand<"umnegl", UMSUBLxwwx, XZR,
1953                       (sub 0, (mul (i64 (zext i32:$Rn)), (zext i32:$Rm)))>;
1954
1955
1956//===----------------------------------------------------------------------===//
1957// Exception generation
1958//===----------------------------------------------------------------------===//
1959// Contains: SVC, HVC, SMC, BRK, HLT, DCPS1, DCPS2, DCPS3
1960
1961def uimm16_asmoperand : AsmOperandClass {
1962  let Name = "UImm16";
1963  let PredicateMethod = "isUImm<16>";
1964  let RenderMethod = "addImmOperands";
1965  let DiagnosticType = "UImm16";
1966}
1967
1968def uimm16 : Operand<i32> {
1969  let ParserMatchClass = uimm16_asmoperand;
1970}
1971
1972class A64I_exceptImpl<bits<3> opc, bits<2> ll, string asmop>
1973  : A64I_exception<opc, 0b000, ll, (outs), (ins uimm16:$UImm16),
1974                   !strconcat(asmop, "\t$UImm16"), [], NoItinerary>,
1975    Sched<[WriteBr]> {
1976  let isBranch = 1;
1977  let isTerminator = 1;
1978}
1979
1980def SVCi : A64I_exceptImpl<0b000, 0b01, "svc">;
1981def HVCi : A64I_exceptImpl<0b000, 0b10, "hvc">;
1982def SMCi : A64I_exceptImpl<0b000, 0b11, "smc">;
1983def BRKi : A64I_exceptImpl<0b001, 0b00, "brk">;
1984def HLTi : A64I_exceptImpl<0b010, 0b00, "hlt">;
1985
1986def DCPS1i : A64I_exceptImpl<0b101, 0b01, "dcps1">;
1987def DCPS2i : A64I_exceptImpl<0b101, 0b10, "dcps2">;
1988def DCPS3i : A64I_exceptImpl<0b101, 0b11, "dcps3">;
1989
1990// The immediate is optional for the DCPS instructions, defaulting to 0.
1991def : InstAlias<"dcps1", (DCPS1i 0)>;
1992def : InstAlias<"dcps2", (DCPS2i 0)>;
1993def : InstAlias<"dcps3", (DCPS3i 0)>;
1994
1995//===----------------------------------------------------------------------===//
1996// Extract (immediate)
1997//===----------------------------------------------------------------------===//
1998// Contains: EXTR + alias ROR
1999
2000def EXTRwwwi : A64I_extract<0b0, 0b000, 0b0,
2001                            (outs GPR32:$Rd),
2002                            (ins GPR32:$Rn, GPR32:$Rm, bitfield32_imm:$LSB),
2003                            "extr\t$Rd, $Rn, $Rm, $LSB",
2004                            [(set i32:$Rd,
2005                                  (A64Extr i32:$Rn, i32:$Rm, imm:$LSB))],
2006                            NoItinerary>,
2007               Sched<[WriteALU, ReadALU, ReadALU]>;
2008def EXTRxxxi : A64I_extract<0b1, 0b000, 0b1,
2009                            (outs GPR64:$Rd),
2010                            (ins GPR64:$Rn, GPR64:$Rm, bitfield64_imm:$LSB),
2011                            "extr\t$Rd, $Rn, $Rm, $LSB",
2012                            [(set i64:$Rd,
2013                                  (A64Extr i64:$Rn, i64:$Rm, imm:$LSB))],
2014                            NoItinerary>,
2015               Sched<[WriteALU, ReadALU, ReadALU]>;
2016
2017def : InstAlias<"ror $Rd, $Rs, $LSB",
2018               (EXTRwwwi GPR32:$Rd, GPR32:$Rs, GPR32:$Rs, bitfield32_imm:$LSB)>;
2019def : InstAlias<"ror $Rd, $Rs, $LSB",
2020               (EXTRxxxi GPR64:$Rd, GPR64:$Rs, GPR64:$Rs, bitfield64_imm:$LSB)>;
2021
2022def : Pat<(rotr i32:$Rn, bitfield32_imm:$LSB),
2023          (EXTRwwwi $Rn, $Rn, bitfield32_imm:$LSB)>;
2024def : Pat<(rotr i64:$Rn, bitfield64_imm:$LSB),
2025          (EXTRxxxi $Rn, $Rn, bitfield64_imm:$LSB)>;
2026
2027//===----------------------------------------------------------------------===//
2028// Floating-point compare instructions
2029//===----------------------------------------------------------------------===//
2030// Contains: FCMP, FCMPE
2031
2032def fpzero_asmoperand : AsmOperandClass {
2033  let Name = "FPZero";
2034  let ParserMethod = "ParseFPImmOperand";
2035  let DiagnosticType = "FPZero";
2036}
2037
2038def fpz32 : Operand<f32>,
2039            ComplexPattern<f32, 1, "SelectFPZeroOperand", [fpimm]> {
2040  let ParserMatchClass = fpzero_asmoperand;
2041  let PrintMethod = "printFPZeroOperand";
2042  let DecoderMethod = "DecodeFPZeroOperand";
2043}
2044
2045def fpz64 : Operand<f64>,
2046            ComplexPattern<f64, 1, "SelectFPZeroOperand", [fpimm]> {
2047  let ParserMatchClass = fpzero_asmoperand;
2048  let PrintMethod = "printFPZeroOperand";
2049  let DecoderMethod = "DecodeFPZeroOperand";
2050}
2051
2052def fpz64movi : Operand<i64>,
2053            ComplexPattern<f64, 1, "SelectFPZeroOperand", [fpimm]> {
2054  let ParserMatchClass = fpzero_asmoperand;
2055  let PrintMethod = "printFPZeroOperand";
2056  let DecoderMethod = "DecodeFPZeroOperand";
2057}
2058
2059multiclass A64I_fpcmpSignal<bits<2> type, bit imm, dag ins, dag pattern> {
2060  def _quiet : A64I_fpcmp<0b0, 0b0, type, 0b00, {0b0, imm, 0b0, 0b0, 0b0},
2061                          (outs), ins, "fcmp\t$Rn, $Rm", [pattern],
2062                          NoItinerary>,
2063               Sched<[WriteFPALU, ReadFPALU, ReadFPALU]> {
2064    let Defs = [NZCV];
2065  }
2066
2067  def _sig : A64I_fpcmp<0b0, 0b0, type, 0b00, {0b1, imm, 0b0, 0b0, 0b0},
2068                        (outs), ins, "fcmpe\t$Rn, $Rm", [], NoItinerary>,
2069             Sched<[WriteFPALU, ReadFPALU, ReadFPALU]> {
2070    let Defs = [NZCV];
2071  }
2072}
2073
2074defm FCMPss : A64I_fpcmpSignal<0b00, 0b0, (ins FPR32:$Rn, FPR32:$Rm),
2075                               (set NZCV, (A64cmp f32:$Rn, f32:$Rm))>;
2076defm FCMPdd : A64I_fpcmpSignal<0b01, 0b0, (ins FPR64:$Rn, FPR64:$Rm),
2077                               (set NZCV, (A64cmp f64:$Rn, f64:$Rm))>;
2078
2079// What would be Rm should be written as 0; note that even though it's called
2080// "$Rm" here to fit in with the InstrFormats, it's actually an immediate.
2081defm FCMPsi : A64I_fpcmpSignal<0b00, 0b1, (ins FPR32:$Rn, fpz32:$Rm),
2082                               (set NZCV, (A64cmp f32:$Rn, fpz32:$Rm))>;
2083
2084defm FCMPdi : A64I_fpcmpSignal<0b01, 0b1, (ins FPR64:$Rn, fpz64:$Rm),
2085                               (set NZCV, (A64cmp f64:$Rn, fpz64:$Rm))>;
2086
2087
2088//===----------------------------------------------------------------------===//
2089// Floating-point conditional compare instructions
2090//===----------------------------------------------------------------------===//
2091// Contains: FCCMP, FCCMPE
2092
2093class A64I_fpccmpImpl<bits<2> type, bit op, RegisterClass FPR, string asmop>
2094  : A64I_fpccmp<0b0, 0b0, type, op,
2095                (outs),
2096                (ins FPR:$Rn, FPR:$Rm, uimm4:$NZCVImm, cond_code_op:$Cond),
2097                !strconcat(asmop, "\t$Rn, $Rm, $NZCVImm, $Cond"),
2098                [], NoItinerary>,
2099    Sched<[WriteFPALU, ReadFPALU, ReadFPALU]> {
2100  let Defs = [NZCV];
2101}
2102
2103def FCCMPss : A64I_fpccmpImpl<0b00, 0b0, FPR32, "fccmp">;
2104def FCCMPEss : A64I_fpccmpImpl<0b00, 0b1, FPR32, "fccmpe">;
2105def FCCMPdd : A64I_fpccmpImpl<0b01, 0b0, FPR64, "fccmp">;
2106def FCCMPEdd : A64I_fpccmpImpl<0b01, 0b1, FPR64, "fccmpe">;
2107
2108//===----------------------------------------------------------------------===//
2109// Floating-point conditional select instructions
2110//===----------------------------------------------------------------------===//
2111// Contains: FCSEL
2112
2113let Uses = [NZCV] in {
2114  def FCSELsssc : A64I_fpcondsel<0b0, 0b0, 0b00, (outs FPR32:$Rd),
2115                                 (ins FPR32:$Rn, FPR32:$Rm, cond_code_op:$Cond),
2116                                 "fcsel\t$Rd, $Rn, $Rm, $Cond",
2117                                 [(set f32:$Rd,
2118                                       (simple_select f32:$Rn, f32:$Rm))],
2119                                 NoItinerary>,
2120                  Sched<[WriteFPALU, ReadFPALU, ReadFPALU]>;
2121
2122
2123  def FCSELdddc : A64I_fpcondsel<0b0, 0b0, 0b01, (outs FPR64:$Rd),
2124                                 (ins FPR64:$Rn, FPR64:$Rm, cond_code_op:$Cond),
2125                                 "fcsel\t$Rd, $Rn, $Rm, $Cond",
2126                                 [(set f64:$Rd,
2127                                       (simple_select f64:$Rn, f64:$Rm))],
2128                                 NoItinerary>,
2129                  Sched<[WriteFPALU, ReadFPALU, ReadFPALU]>;
2130}
2131
2132//===----------------------------------------------------------------------===//
2133// Floating-point data-processing (1 source)
2134//===----------------------------------------------------------------------===//
2135// Contains: FMOV, FABS, FNEG, FSQRT, FCVT, FRINT[NPMZAXI].
2136
2137def FPNoUnop : PatFrag<(ops node:$val), (fneg node:$val),
2138                       [{ (void)N; return false; }]>;
2139
2140// First we do the fairly trivial bunch with uniform "OP s, s" and "OP d, d"
2141// syntax. Default to no pattern because most are odd enough not to have one.
2142multiclass A64I_fpdp1sizes<bits<6> opcode, string asmstr,
2143                           SDPatternOperator opnode = FPNoUnop> {
2144  def ss : A64I_fpdp1<0b0, 0b0, 0b00, opcode, (outs FPR32:$Rd), (ins FPR32:$Rn),
2145                     !strconcat(asmstr, "\t$Rd, $Rn"),
2146                     [(set f32:$Rd, (opnode f32:$Rn))],
2147                     NoItinerary>,
2148           Sched<[WriteFPALU, ReadFPALU]>;
2149
2150  def dd : A64I_fpdp1<0b0, 0b0, 0b01, opcode, (outs FPR64:$Rd), (ins FPR64:$Rn),
2151                     !strconcat(asmstr, "\t$Rd, $Rn"),
2152                     [(set f64:$Rd, (opnode f64:$Rn))],
2153                     NoItinerary>,
2154           Sched<[WriteFPALU, ReadFPALU]>;
2155}
2156
2157defm FMOV   : A64I_fpdp1sizes<0b000000, "fmov">;
2158defm FABS   : A64I_fpdp1sizes<0b000001, "fabs", fabs>;
2159defm FNEG   : A64I_fpdp1sizes<0b000010, "fneg", fneg>;
2160let SchedRW = [WriteFPSqrt, ReadFPSqrt] in {
2161  defm FSQRT  : A64I_fpdp1sizes<0b000011, "fsqrt", fsqrt>;
2162}
2163
2164defm FRINTN : A64I_fpdp1sizes<0b001000, "frintn">;
2165defm FRINTP : A64I_fpdp1sizes<0b001001, "frintp", fceil>;
2166defm FRINTM : A64I_fpdp1sizes<0b001010, "frintm", ffloor>;
2167defm FRINTZ : A64I_fpdp1sizes<0b001011, "frintz", ftrunc>;
2168defm FRINTA : A64I_fpdp1sizes<0b001100, "frinta">;
2169defm FRINTX : A64I_fpdp1sizes<0b001110, "frintx", frint>;
2170defm FRINTI : A64I_fpdp1sizes<0b001111, "frinti", fnearbyint>;
2171
2172// The FCVT instrucitons have different source and destination register-types,
2173// but the fields are uniform everywhere a D-register (say) crops up. Package
2174// this information in a Record.
2175class FCVTRegType<RegisterClass rc, bits<2> fld, ValueType vt> {
2176    RegisterClass Class = rc;
2177    ValueType VT = vt;
2178    bit t1 = fld{1};
2179    bit t0 = fld{0};
2180}
2181
2182def FCVT16 : FCVTRegType<FPR16, 0b11, f16>;
2183def FCVT32 : FCVTRegType<FPR32, 0b00, f32>;
2184def FCVT64 : FCVTRegType<FPR64, 0b01, f64>;
2185
2186class A64I_fpdp1_fcvt<FCVTRegType DestReg, FCVTRegType SrcReg, SDNode opnode>
2187  : A64I_fpdp1<0b0, 0b0, {SrcReg.t1, SrcReg.t0},
2188               {0,0,0,1, DestReg.t1, DestReg.t0},
2189               (outs DestReg.Class:$Rd), (ins SrcReg.Class:$Rn),
2190               "fcvt\t$Rd, $Rn",
2191               [(set DestReg.VT:$Rd, (opnode SrcReg.VT:$Rn))], NoItinerary>,
2192    Sched<[WriteFPALU, ReadFPALU]>;
2193
2194def FCVTds : A64I_fpdp1_fcvt<FCVT64, FCVT32, fextend>;
2195def FCVThs : A64I_fpdp1_fcvt<FCVT16, FCVT32, fround>;
2196def FCVTsd : A64I_fpdp1_fcvt<FCVT32, FCVT64, fround>;
2197def FCVThd : A64I_fpdp1_fcvt<FCVT16, FCVT64, fround>;
2198def FCVTsh : A64I_fpdp1_fcvt<FCVT32, FCVT16, fextend>;
2199def FCVTdh : A64I_fpdp1_fcvt<FCVT64, FCVT16, fextend>;
2200
2201
2202//===----------------------------------------------------------------------===//
2203// Floating-point data-processing (2 sources) instructions
2204//===----------------------------------------------------------------------===//
2205// Contains: FMUL, FDIV, FADD, FSUB, FMAX, FMIN, FMAXNM, FMINNM, FNMUL
2206
2207def FPNoBinop : PatFrag<(ops node:$lhs, node:$rhs), (fadd node:$lhs, node:$rhs),
2208                      [{ (void)N; return false; }]>;
2209
2210multiclass A64I_fpdp2sizes<bits<4> opcode, string asmstr,
2211                           SDPatternOperator opnode> {
2212  def sss : A64I_fpdp2<0b0, 0b0, 0b00, opcode,
2213                      (outs FPR32:$Rd),
2214                      (ins FPR32:$Rn, FPR32:$Rm),
2215                      !strconcat(asmstr, "\t$Rd, $Rn, $Rm"),
2216                      [(set f32:$Rd, (opnode f32:$Rn, f32:$Rm))],
2217                      NoItinerary>,
2218            Sched<[WriteFPALU, ReadFPALU, ReadFPALU]>;
2219
2220  def ddd : A64I_fpdp2<0b0, 0b0, 0b01, opcode,
2221                      (outs FPR64:$Rd),
2222                      (ins FPR64:$Rn, FPR64:$Rm),
2223                      !strconcat(asmstr, "\t$Rd, $Rn, $Rm"),
2224                      [(set f64:$Rd, (opnode f64:$Rn, f64:$Rm))],
2225                      NoItinerary>,
2226            Sched<[WriteFPALU, ReadFPALU, ReadFPALU]>;
2227}
2228
2229let isCommutable = 1 in {
2230  let SchedRW = [WriteFPMul, ReadFPMul, ReadFPMul] in {
2231    defm FMUL   : A64I_fpdp2sizes<0b0000, "fmul", fmul>;
2232  }
2233  defm FADD   : A64I_fpdp2sizes<0b0010, "fadd", fadd>;
2234
2235  // No patterns for these.
2236  defm FMAX   : A64I_fpdp2sizes<0b0100, "fmax", FPNoBinop>;
2237  defm FMIN   : A64I_fpdp2sizes<0b0101, "fmin", FPNoBinop>;
2238  defm FMAXNM : A64I_fpdp2sizes<0b0110, "fmaxnm", FPNoBinop>;
2239  defm FMINNM : A64I_fpdp2sizes<0b0111, "fminnm", FPNoBinop>;
2240
2241  let SchedRW = [WriteFPMul, ReadFPMul, ReadFPMul] in {
2242    defm FNMUL  : A64I_fpdp2sizes<0b1000, "fnmul",
2243                                  PatFrag<(ops node:$lhs, node:$rhs),
2244                                          (fneg (fmul node:$lhs, node:$rhs))> >;
2245  }
2246}
2247
2248let SchedRW = [WriteFPDiv, ReadFPDiv, ReadFPDiv] in {
2249  defm FDIV : A64I_fpdp2sizes<0b0001, "fdiv", fdiv>;
2250}
2251defm FSUB : A64I_fpdp2sizes<0b0011, "fsub", fsub>;
2252
2253//===----------------------------------------------------------------------===//
2254// Floating-point data-processing (3 sources) instructions
2255//===----------------------------------------------------------------------===//
2256// Contains: FMADD, FMSUB, FNMADD, FNMSUB
2257
2258def fmsub : PatFrag<(ops node:$Rn, node:$Rm, node:$Ra),
2259                    (fma (fneg node:$Rn),  node:$Rm, node:$Ra)>;
2260def fnmsub : PatFrag<(ops node:$Rn, node:$Rm, node:$Ra),
2261                     (fma node:$Rn,  node:$Rm, (fneg node:$Ra))>;
2262def fnmadd : PatFrag<(ops node:$Rn, node:$Rm, node:$Ra),
2263                     (fma (fneg node:$Rn),  node:$Rm, (fneg node:$Ra))>;
2264
2265class A64I_fpdp3Impl<string asmop, RegisterClass FPR, ValueType VT,
2266                     bits<2> type, bit o1, bit o0, SDPatternOperator fmakind>
2267  : A64I_fpdp3<0b0, 0b0, type, o1, o0, (outs FPR:$Rd),
2268               (ins FPR:$Rn, FPR:$Rm, FPR:$Ra),
2269               !strconcat(asmop,"\t$Rd, $Rn, $Rm, $Ra"),
2270               [(set VT:$Rd, (fmakind VT:$Rn, VT:$Rm, VT:$Ra))],
2271               NoItinerary>,
2272    Sched<[WriteFPMAC, ReadFPMAC, ReadFPMAC, ReadFPMAC]>;
2273
2274def FMADDssss  : A64I_fpdp3Impl<"fmadd",  FPR32, f32, 0b00, 0b0, 0b0, fma>;
2275def FMSUBssss  : A64I_fpdp3Impl<"fmsub",  FPR32, f32, 0b00, 0b0, 0b1, fmsub>;
2276def FNMADDssss : A64I_fpdp3Impl<"fnmadd", FPR32, f32, 0b00, 0b1, 0b0, fnmadd>;
2277def FNMSUBssss : A64I_fpdp3Impl<"fnmsub", FPR32, f32, 0b00, 0b1, 0b1, fnmsub>;
2278
2279def FMADDdddd  : A64I_fpdp3Impl<"fmadd",  FPR64, f64, 0b01, 0b0, 0b0, fma>;
2280def FMSUBdddd  : A64I_fpdp3Impl<"fmsub",  FPR64, f64, 0b01, 0b0, 0b1, fmsub>;
2281def FNMADDdddd : A64I_fpdp3Impl<"fnmadd", FPR64, f64, 0b01, 0b1, 0b0, fnmadd>;
2282def FNMSUBdddd : A64I_fpdp3Impl<"fnmsub", FPR64, f64, 0b01, 0b1, 0b1, fnmsub>;
2283
2284// Extra patterns for when we're allowed to optimise separate multiplication and
2285// addition.
2286let Predicates = [HasFPARMv8, UseFusedMAC] in {
2287def : Pat<(f32 (fadd FPR32:$Ra, (f32 (fmul_su FPR32:$Rn, FPR32:$Rm)))),
2288          (FMADDssss FPR32:$Rn, FPR32:$Rm, FPR32:$Ra)>;
2289def : Pat<(f32 (fsub FPR32:$Ra, (f32 (fmul_su FPR32:$Rn, FPR32:$Rm)))),
2290          (FMSUBssss FPR32:$Rn, FPR32:$Rm, FPR32:$Ra)>;
2291def : Pat<(f32 (fsub (f32 (fneg FPR32:$Ra)), (f32 (fmul_su FPR32:$Rn, FPR32:$Rm)))),
2292          (FNMADDssss FPR32:$Rn, FPR32:$Rm, FPR32:$Ra)>;
2293def : Pat<(f32 (fsub (f32 (fmul_su FPR32:$Rn, FPR32:$Rm)), FPR32:$Ra)),
2294          (FNMSUBssss FPR32:$Rn, FPR32:$Rm, FPR32:$Ra)>;
2295
2296def : Pat<(f64 (fadd FPR64:$Ra, (f64 (fmul_su FPR64:$Rn, FPR64:$Rm)))),
2297          (FMADDdddd FPR64:$Rn, FPR64:$Rm, FPR64:$Ra)>;
2298def : Pat<(f64 (fsub FPR64:$Ra, (f64 (fmul_su FPR64:$Rn, FPR64:$Rm)))),
2299          (FMSUBdddd FPR64:$Rn, FPR64:$Rm, FPR64:$Ra)>;
2300def : Pat<(f64 (fsub (f64 (fneg FPR64:$Ra)), (f64 (fmul_su FPR64:$Rn, FPR64:$Rm)))),
2301          (FNMADDdddd FPR64:$Rn, FPR64:$Rm, FPR64:$Ra)>;
2302def : Pat<(f64 (fsub (f64 (fmul_su FPR64:$Rn, FPR64:$Rm)), FPR64:$Ra)),
2303          (FNMSUBdddd FPR64:$Rn, FPR64:$Rm, FPR64:$Ra)>;
2304}
2305
2306
2307//===----------------------------------------------------------------------===//
2308// Floating-point <-> fixed-point conversion instructions
2309//===----------------------------------------------------------------------===//
2310// Contains: FCVTZS, FCVTZU, SCVTF, UCVTF
2311
2312// #1-#32 allowed, encoded as "64 - <specified imm>
2313def fixedpos_asmoperand_i32 : AsmOperandClass {
2314  let Name = "CVTFixedPos32";
2315  let RenderMethod = "addCVTFixedPosOperands";
2316  let PredicateMethod = "isCVTFixedPos<32>";
2317  let DiagnosticType = "CVTFixedPos32";
2318}
2319
2320// Also encoded as "64 - <specified imm>" but #1-#64 allowed.
2321def fixedpos_asmoperand_i64 : AsmOperandClass {
2322  let Name = "CVTFixedPos64";
2323  let RenderMethod = "addCVTFixedPosOperands";
2324  let PredicateMethod = "isCVTFixedPos<64>";
2325  let DiagnosticType = "CVTFixedPos64";
2326}
2327
2328// We need the cartesian product of f32/f64 i32/i64 operands for
2329// conversions:
2330//   + Selection needs to use operands of correct floating type
2331//   + Assembly parsing and decoding depend on integer width
2332class cvtfix_i32_op<ValueType FloatVT>
2333  : Operand<FloatVT>,
2334    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm]> {
2335  let ParserMatchClass = fixedpos_asmoperand_i32;
2336  let DecoderMethod = "DecodeCVT32FixedPosOperand";
2337  let PrintMethod = "printCVTFixedPosOperand";
2338}
2339
2340class cvtfix_i64_op<ValueType FloatVT>
2341  : Operand<FloatVT>,
2342    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm]> {
2343  let ParserMatchClass = fixedpos_asmoperand_i64;
2344  let PrintMethod = "printCVTFixedPosOperand";
2345}
2346
2347// Because of the proliferation of weird operands, it's not really
2348// worth going for a multiclass here. Oh well.
2349
2350class A64I_fptofix<bit sf, bits<2> type, bits<3> opcode,
2351                   RegisterClass GPR, RegisterClass FPR,
2352                   ValueType DstTy, ValueType SrcTy,
2353                   Operand scale_op, string asmop, SDNode cvtop>
2354  : A64I_fpfixed<sf, 0b0, type, 0b11, opcode,
2355                 (outs GPR:$Rd), (ins FPR:$Rn, scale_op:$Scale),
2356                 !strconcat(asmop, "\t$Rd, $Rn, $Scale"),
2357                 [(set DstTy:$Rd, (cvtop (fmul SrcTy:$Rn, scale_op:$Scale)))],
2358                 NoItinerary>,
2359    Sched<[WriteFPALU, ReadFPALU]>;
2360
2361def FCVTZSwsi : A64I_fptofix<0b0, 0b00, 0b000, GPR32, FPR32, i32, f32,
2362                             cvtfix_i32_op<f32>, "fcvtzs", fp_to_sint>;
2363def FCVTZSxsi : A64I_fptofix<0b1, 0b00, 0b000, GPR64, FPR32, i64, f32,
2364                             cvtfix_i64_op<f32>, "fcvtzs", fp_to_sint>;
2365def FCVTZUwsi : A64I_fptofix<0b0, 0b00, 0b001, GPR32, FPR32, i32, f32,
2366                             cvtfix_i32_op<f32>, "fcvtzu", fp_to_uint>;
2367def FCVTZUxsi : A64I_fptofix<0b1, 0b00, 0b001, GPR64, FPR32, i64, f32,
2368                             cvtfix_i64_op<f32>, "fcvtzu", fp_to_uint>;
2369
2370def FCVTZSwdi : A64I_fptofix<0b0, 0b01, 0b000, GPR32, FPR64, i32, f64,
2371                             cvtfix_i32_op<f64>, "fcvtzs", fp_to_sint>;
2372def FCVTZSxdi : A64I_fptofix<0b1, 0b01, 0b000, GPR64, FPR64, i64, f64,
2373                             cvtfix_i64_op<f64>, "fcvtzs", fp_to_sint>;
2374def FCVTZUwdi : A64I_fptofix<0b0, 0b01, 0b001, GPR32, FPR64, i32, f64,
2375                             cvtfix_i32_op<f64>, "fcvtzu", fp_to_uint>;
2376def FCVTZUxdi : A64I_fptofix<0b1, 0b01, 0b001, GPR64, FPR64, i64, f64,
2377                             cvtfix_i64_op<f64>, "fcvtzu", fp_to_uint>;
2378
2379
2380class A64I_fixtofp<bit sf, bits<2> type, bits<3> opcode,
2381                   RegisterClass FPR, RegisterClass GPR,
2382                   ValueType DstTy, ValueType SrcTy,
2383                   Operand scale_op, string asmop, SDNode cvtop>
2384  : A64I_fpfixed<sf, 0b0, type, 0b00, opcode,
2385                 (outs FPR:$Rd), (ins GPR:$Rn, scale_op:$Scale),
2386                 !strconcat(asmop, "\t$Rd, $Rn, $Scale"),
2387                 [(set DstTy:$Rd, (fdiv (cvtop SrcTy:$Rn), scale_op:$Scale))],
2388                 NoItinerary>,
2389    Sched<[WriteFPALU, ReadFPALU]>;
2390
2391def SCVTFswi : A64I_fixtofp<0b0, 0b00, 0b010, FPR32, GPR32, f32, i32,
2392                            cvtfix_i32_op<f32>, "scvtf", sint_to_fp>;
2393def SCVTFsxi : A64I_fixtofp<0b1, 0b00, 0b010, FPR32, GPR64, f32, i64,
2394                            cvtfix_i64_op<f32>, "scvtf", sint_to_fp>;
2395def UCVTFswi : A64I_fixtofp<0b0, 0b00, 0b011, FPR32, GPR32, f32, i32,
2396                            cvtfix_i32_op<f32>, "ucvtf", uint_to_fp>;
2397def UCVTFsxi : A64I_fixtofp<0b1, 0b00, 0b011, FPR32, GPR64, f32, i64,
2398                            cvtfix_i64_op<f32>, "ucvtf", uint_to_fp>;
2399def SCVTFdwi : A64I_fixtofp<0b0, 0b01, 0b010, FPR64, GPR32, f64, i32,
2400                            cvtfix_i32_op<f64>, "scvtf", sint_to_fp>;
2401def SCVTFdxi : A64I_fixtofp<0b1, 0b01, 0b010, FPR64, GPR64, f64, i64,
2402                            cvtfix_i64_op<f64>, "scvtf", sint_to_fp>;
2403def UCVTFdwi : A64I_fixtofp<0b0, 0b01, 0b011, FPR64, GPR32, f64, i32,
2404                            cvtfix_i32_op<f64>, "ucvtf", uint_to_fp>;
2405def UCVTFdxi : A64I_fixtofp<0b1, 0b01, 0b011, FPR64, GPR64, f64, i64,
2406                            cvtfix_i64_op<f64>, "ucvtf", uint_to_fp>;
2407
2408//===----------------------------------------------------------------------===//
2409// Floating-point <-> integer conversion instructions
2410//===----------------------------------------------------------------------===//
2411// Contains: FCVTZS, FCVTZU, SCVTF, UCVTF
2412
2413class A64I_fpintI<bit sf, bits<2> type, bits<2> rmode, bits<3> opcode,
2414                   RegisterClass DestPR, RegisterClass SrcPR, string asmop>
2415  : A64I_fpint<sf, 0b0, type, rmode, opcode, (outs DestPR:$Rd), (ins SrcPR:$Rn),
2416               !strconcat(asmop, "\t$Rd, $Rn"), [], NoItinerary>,
2417    Sched<[WriteFPALU, ReadFPALU]>;
2418
2419multiclass A64I_fptointRM<bits<2> rmode, bit o2, string asmop> {
2420  def Sws : A64I_fpintI<0b0, 0b00, rmode, {o2, 0, 0},
2421                        GPR32, FPR32, asmop # "s">;
2422  def Sxs : A64I_fpintI<0b1, 0b00, rmode, {o2, 0, 0},
2423                        GPR64, FPR32, asmop # "s">;
2424  def Uws : A64I_fpintI<0b0, 0b00, rmode, {o2, 0, 1},
2425                        GPR32, FPR32, asmop # "u">;
2426  def Uxs : A64I_fpintI<0b1, 0b00, rmode, {o2, 0, 1},
2427                        GPR64, FPR32, asmop # "u">;
2428
2429  def Swd : A64I_fpintI<0b0, 0b01, rmode, {o2, 0, 0},
2430                        GPR32, FPR64, asmop # "s">;
2431  def Sxd : A64I_fpintI<0b1, 0b01, rmode, {o2, 0, 0},
2432                        GPR64, FPR64, asmop # "s">;
2433  def Uwd : A64I_fpintI<0b0, 0b01, rmode, {o2, 0, 1},
2434                        GPR32, FPR64, asmop # "u">;
2435  def Uxd : A64I_fpintI<0b1, 0b01, rmode, {o2, 0, 1},
2436                        GPR64, FPR64, asmop # "u">;
2437}
2438
2439defm FCVTN : A64I_fptointRM<0b00, 0b0, "fcvtn">;
2440defm FCVTP : A64I_fptointRM<0b01, 0b0, "fcvtp">;
2441defm FCVTM : A64I_fptointRM<0b10, 0b0, "fcvtm">;
2442defm FCVTZ : A64I_fptointRM<0b11, 0b0, "fcvtz">;
2443defm FCVTA : A64I_fptointRM<0b00, 0b1, "fcvta">;
2444
2445let Predicates = [HasFPARMv8] in {
2446def : Pat<(i32 (fp_to_sint f32:$Rn)), (FCVTZSws $Rn)>;
2447def : Pat<(i64 (fp_to_sint f32:$Rn)), (FCVTZSxs $Rn)>;
2448def : Pat<(i32 (fp_to_uint f32:$Rn)), (FCVTZUws $Rn)>;
2449def : Pat<(i64 (fp_to_uint f32:$Rn)), (FCVTZUxs $Rn)>;
2450def : Pat<(i32 (fp_to_sint f64:$Rn)), (FCVTZSwd $Rn)>;
2451def : Pat<(i64 (fp_to_sint f64:$Rn)), (FCVTZSxd $Rn)>;
2452def : Pat<(i32 (fp_to_uint f64:$Rn)), (FCVTZUwd $Rn)>;
2453def : Pat<(i64 (fp_to_uint f64:$Rn)), (FCVTZUxd $Rn)>;
2454}
2455
2456multiclass A64I_inttofp<bit o0, string asmop> {
2457  def CVTFsw : A64I_fpintI<0b0, 0b00, 0b00, {0, 1, o0}, FPR32, GPR32, asmop>;
2458  def CVTFsx : A64I_fpintI<0b1, 0b00, 0b00, {0, 1, o0}, FPR32, GPR64, asmop>;
2459  def CVTFdw : A64I_fpintI<0b0, 0b01, 0b00, {0, 1, o0}, FPR64, GPR32, asmop>;
2460  def CVTFdx : A64I_fpintI<0b1, 0b01, 0b00, {0, 1, o0}, FPR64, GPR64, asmop>;
2461}
2462
2463defm S : A64I_inttofp<0b0, "scvtf">;
2464defm U : A64I_inttofp<0b1, "ucvtf">;
2465
2466let Predicates = [HasFPARMv8] in {
2467def : Pat<(f32 (sint_to_fp i32:$Rn)), (SCVTFsw $Rn)>;
2468def : Pat<(f32 (sint_to_fp i64:$Rn)), (SCVTFsx $Rn)>;
2469def : Pat<(f64 (sint_to_fp i32:$Rn)), (SCVTFdw $Rn)>;
2470def : Pat<(f64 (sint_to_fp i64:$Rn)), (SCVTFdx $Rn)>;
2471def : Pat<(f32 (uint_to_fp i32:$Rn)), (UCVTFsw $Rn)>;
2472def : Pat<(f32 (uint_to_fp i64:$Rn)), (UCVTFsx $Rn)>;
2473def : Pat<(f64 (uint_to_fp i32:$Rn)), (UCVTFdw $Rn)>;
2474def : Pat<(f64 (uint_to_fp i64:$Rn)), (UCVTFdx $Rn)>;
2475}
2476
2477def FMOVws : A64I_fpintI<0b0, 0b00, 0b00, 0b110, GPR32, FPR32, "fmov">;
2478def FMOVsw : A64I_fpintI<0b0, 0b00, 0b00, 0b111, FPR32, GPR32, "fmov">;
2479def FMOVxd : A64I_fpintI<0b1, 0b01, 0b00, 0b110, GPR64, FPR64, "fmov">;
2480def FMOVdx : A64I_fpintI<0b1, 0b01, 0b00, 0b111, FPR64, GPR64, "fmov">;
2481
2482let Predicates = [HasFPARMv8] in {
2483def : Pat<(i32 (bitconvert f32:$Rn)), (FMOVws $Rn)>;
2484def : Pat<(f32 (bitconvert i32:$Rn)), (FMOVsw $Rn)>;
2485def : Pat<(i64 (bitconvert f64:$Rn)), (FMOVxd $Rn)>;
2486def : Pat<(f64 (bitconvert i64:$Rn)), (FMOVdx $Rn)>;
2487}
2488
2489def lane1_asmoperand : AsmOperandClass {
2490  let Name = "Lane1";
2491  let RenderMethod = "addImmOperands";
2492  let DiagnosticType = "Lane1";
2493}
2494
2495def lane1 : Operand<i32> {
2496  let ParserMatchClass = lane1_asmoperand;
2497  let PrintMethod = "printBareImmOperand";
2498}
2499
2500let DecoderMethod =  "DecodeFMOVLaneInstruction" in {
2501  def FMOVxv : A64I_fpint<0b1, 0b0, 0b10, 0b01, 0b110,
2502                          (outs GPR64:$Rd), (ins VPR128:$Rn, lane1:$Lane),
2503                          "fmov\t$Rd, $Rn.d[$Lane]", [], NoItinerary>,
2504               Sched<[WriteFPALU, ReadFPALU]>;
2505
2506  def FMOVvx : A64I_fpint<0b1, 0b0, 0b10, 0b01, 0b111,
2507                          (outs VPR128:$Rd), (ins GPR64:$Rn, lane1:$Lane),
2508                          "fmov\t$Rd.d[$Lane], $Rn", [], NoItinerary>,
2509               Sched<[WriteFPALU, ReadFPALU]>;
2510}
2511
2512let Predicates = [HasFPARMv8] in {
2513def : InstAlias<"fmov $Rd, $Rn.2d[$Lane]",
2514                (FMOVxv GPR64:$Rd, VPR128:$Rn, lane1:$Lane), 0b0>;
2515
2516def : InstAlias<"fmov $Rd.2d[$Lane], $Rn",
2517                (FMOVvx VPR128:$Rd, GPR64:$Rn, lane1:$Lane), 0b0>;
2518}
2519
2520//===----------------------------------------------------------------------===//
2521// Floating-point immediate instructions
2522//===----------------------------------------------------------------------===//
2523// Contains: FMOV
2524
2525def fpimm_asmoperand : AsmOperandClass {
2526  let Name = "FMOVImm";
2527  let ParserMethod = "ParseFPImmOperand";
2528  let DiagnosticType = "FPImm";
2529}
2530
2531// The MCOperand for these instructions are the encoded 8-bit values.
2532def SDXF_fpimm : SDNodeXForm<fpimm, [{
2533  uint32_t Imm8;
2534  A64Imms::isFPImm(N->getValueAPF(), Imm8);
2535  return CurDAG->getTargetConstant(Imm8, MVT::i32);
2536}]>;
2537
2538class fmov_operand<ValueType FT>
2539  : Operand<i32>,
2540    PatLeaf<(FT fpimm), [{ return A64Imms::isFPImm(N->getValueAPF()); }],
2541            SDXF_fpimm> {
2542  let PrintMethod = "printFPImmOperand";
2543  let ParserMatchClass = fpimm_asmoperand;
2544}
2545
2546def fmov32_operand : fmov_operand<f32>;
2547def fmov64_operand : fmov_operand<f64>;
2548
2549class A64I_fpimm_impl<bits<2> type, RegisterClass Reg, ValueType VT,
2550                      Operand fmov_operand>
2551  : A64I_fpimm<0b0, 0b0, type, 0b00000,
2552               (outs Reg:$Rd),
2553               (ins fmov_operand:$Imm8),
2554               "fmov\t$Rd, $Imm8",
2555               [(set VT:$Rd, fmov_operand:$Imm8)],
2556               NoItinerary>,
2557    Sched<[WriteFPALU]>;
2558
2559def FMOVsi : A64I_fpimm_impl<0b00, FPR32, f32, fmov32_operand>;
2560def FMOVdi : A64I_fpimm_impl<0b01, FPR64, f64, fmov64_operand>;
2561
2562//===----------------------------------------------------------------------===//
2563// Load-register (literal) instructions
2564//===----------------------------------------------------------------------===//
2565// Contains: LDR, LDRSW, PRFM
2566
2567def ldrlit_label_asmoperand : AsmOperandClass {
2568  let Name = "LoadLitLabel";
2569  let RenderMethod = "addLabelOperands<19, 4>";
2570  let DiagnosticType = "Label";
2571}
2572
2573def ldrlit_label : Operand<i64> {
2574  let EncoderMethod = "getLoadLitLabelOpValue";
2575
2576  // This label is a 19-bit offset from PC, scaled by the instruction-width: 4.
2577  let PrintMethod = "printLabelOperand<19, 4>";
2578  let ParserMatchClass = ldrlit_label_asmoperand;
2579  let OperandType = "OPERAND_PCREL";
2580}
2581
2582// Various instructions take an immediate value (which can always be used),
2583// where some numbers have a symbolic name to make things easier. These operands
2584// and the associated functions abstract away the differences.
2585multiclass namedimm<string prefix, string mapper> {
2586  def _asmoperand : AsmOperandClass {
2587    let Name = "NamedImm" # prefix;
2588    let PredicateMethod = "isUImm";
2589    let RenderMethod = "addImmOperands";
2590    let ParserMethod = "ParseNamedImmOperand<" # mapper # ">";
2591    let DiagnosticType = "NamedImm_" # prefix;
2592  }
2593
2594  def _op : Operand<i32> {
2595    let ParserMatchClass = !cast<AsmOperandClass>(prefix # "_asmoperand");
2596    let PrintMethod = "printNamedImmOperand<" # mapper # ">";
2597    let DecoderMethod = "DecodeNamedImmOperand<" # mapper # ">";
2598  }
2599}
2600
2601defm prefetch : namedimm<"prefetch", "A64PRFM::PRFMMapper">;
2602
2603class A64I_LDRlitSimple<bits<2> opc, bit v, RegisterClass OutReg,
2604                      list<dag> patterns = []>
2605   : A64I_LDRlit<opc, v, (outs OutReg:$Rt), (ins ldrlit_label:$Imm19),
2606                 "ldr\t$Rt, $Imm19", patterns, NoItinerary>,
2607     Sched<[WriteLd]>;
2608
2609let mayLoad = 1 in {
2610  def LDRw_lit : A64I_LDRlitSimple<0b00, 0b0, GPR32>;
2611  def LDRx_lit : A64I_LDRlitSimple<0b01, 0b0, GPR64>;
2612}
2613
2614let Predicates = [HasFPARMv8] in {
2615def LDRs_lit  : A64I_LDRlitSimple<0b00, 0b1, FPR32>;
2616def LDRd_lit  : A64I_LDRlitSimple<0b01, 0b1, FPR64>;
2617}
2618
2619let mayLoad = 1 in {
2620  let Predicates = [HasFPARMv8] in {
2621  def LDRq_lit : A64I_LDRlitSimple<0b10, 0b1, FPR128>;
2622  }
2623
2624  def LDRSWx_lit : A64I_LDRlit<0b10, 0b0,
2625                               (outs GPR64:$Rt),
2626                               (ins ldrlit_label:$Imm19),
2627                               "ldrsw\t$Rt, $Imm19",
2628                               [], NoItinerary>,
2629                   Sched<[WriteLd]>;
2630
2631  def PRFM_lit : A64I_LDRlit<0b11, 0b0,
2632                             (outs), (ins prefetch_op:$Rt, ldrlit_label:$Imm19),
2633                             "prfm\t$Rt, $Imm19",
2634                             [], NoItinerary>,
2635                 Sched<[WriteLd, ReadLd]>;
2636}
2637
2638//===----------------------------------------------------------------------===//
2639// Load-store exclusive instructions
2640//===----------------------------------------------------------------------===//
2641// Contains: STXRB, STXRH, STXR, LDXRB, LDXRH, LDXR. STXP, LDXP, STLXRB,
2642//           STLXRH, STLXR, LDAXRB, LDAXRH, LDAXR, STLXP, LDAXP, STLRB,
2643//           STLRH, STLR, LDARB, LDARH, LDAR
2644
2645// Since these instructions have the undefined register bits set to 1 in
2646// their canonical form, we need a post encoder method to set those bits
2647// to 1 when encoding these instructions. We do this using the
2648// fixLoadStoreExclusive function. This function has template parameters:
2649//
2650// fixLoadStoreExclusive<int hasRs, int hasRt2>
2651//
2652// hasRs indicates that the instruction uses the Rs field, so we won't set
2653// it to 1 (and the same for Rt2). We don't need template parameters for
2654// the other register fiels since Rt and Rn are always used.
2655
2656// This operand parses a GPR64xsp register, followed by an optional immediate
2657// #0.
2658def GPR64xsp0_asmoperand : AsmOperandClass {
2659  let Name = "GPR64xsp0";
2660  let PredicateMethod = "isWrappedReg";
2661  let RenderMethod = "addRegOperands";
2662  let ParserMethod = "ParseLSXAddressOperand";
2663  // Diagnostics are provided by ParserMethod
2664}
2665
2666def GPR64xsp0 : RegisterOperand<GPR64xsp> {
2667  let ParserMatchClass = GPR64xsp0_asmoperand;
2668}
2669
2670//===----------------------------------
2671// Store-exclusive (releasing & normal)
2672//===----------------------------------
2673
2674class A64I_SRexs_impl<bits<2> size, bits<3> opcode, string asm, dag outs,
2675                        dag ins, list<dag> pat,
2676                        InstrItinClass itin> :
2677       A64I_LDSTex_stn <size,
2678                        opcode{2}, 0, opcode{1}, opcode{0},
2679                        outs, ins,
2680                        !strconcat(asm, "\t$Rs, $Rt, [$Rn]"),
2681                        pat, itin> {
2682  let mayStore = 1;
2683  let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
2684  let Constraints = "@earlyclobber $Rs";
2685}
2686
2687multiclass A64I_SRex<string asmstr, bits<3> opcode, string prefix> {
2688  def _byte:  A64I_SRexs_impl<0b00, opcode, !strconcat(asmstr, "b"),
2689                              (outs GPR32:$Rs), (ins GPR32:$Rt, GPR64xsp0:$Rn),
2690                              [], NoItinerary>,
2691              Sched<[WriteSt, ReadSt, ReadSt]>;
2692
2693  def _hword:  A64I_SRexs_impl<0b01, opcode, !strconcat(asmstr, "h"),
2694                               (outs GPR32:$Rs), (ins GPR32:$Rt, GPR64xsp0:$Rn),
2695                               [],NoItinerary>,
2696               Sched<[WriteSt, ReadSt, ReadSt]>;
2697
2698  def _word:  A64I_SRexs_impl<0b10, opcode, asmstr,
2699                              (outs GPR32:$Rs), (ins GPR32:$Rt, GPR64xsp0:$Rn),
2700                              [], NoItinerary>,
2701              Sched<[WriteSt, ReadSt, ReadSt]>;
2702
2703  def _dword: A64I_SRexs_impl<0b11, opcode, asmstr,
2704                              (outs GPR32:$Rs), (ins GPR64:$Rt, GPR64xsp0:$Rn),
2705                              [], NoItinerary>,
2706              Sched<[WriteSt, ReadSt, ReadSt]>;
2707}
2708
2709defm STXR  : A64I_SRex<"stxr",  0b000, "STXR">;
2710defm STLXR : A64I_SRex<"stlxr", 0b001, "STLXR">;
2711
2712//===----------------------------------
2713// Loads
2714//===----------------------------------
2715
2716class A64I_LRexs_impl<bits<2> size, bits<3> opcode, string asm, dag outs,
2717                        dag ins, list<dag> pat,
2718                        InstrItinClass itin> :
2719        A64I_LDSTex_tn <size,
2720                        opcode{2}, 1, opcode{1}, opcode{0},
2721                        outs, ins,
2722                        !strconcat(asm, "\t$Rt, [$Rn]"),
2723                        pat, itin> {
2724  let mayLoad = 1;
2725  let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
2726}
2727
2728multiclass A64I_LRex<string asmstr, bits<3> opcode> {
2729  def _byte:  A64I_LRexs_impl<0b00, opcode, !strconcat(asmstr, "b"),
2730                            (outs GPR32:$Rt), (ins GPR64xsp0:$Rn),
2731                            [], NoItinerary>,
2732              Sched<[WriteLd]>;
2733
2734  def _hword:  A64I_LRexs_impl<0b01, opcode, !strconcat(asmstr, "h"),
2735                            (outs GPR32:$Rt), (ins GPR64xsp0:$Rn),
2736                            [], NoItinerary>,
2737               Sched<[WriteLd]>;
2738
2739  def _word:  A64I_LRexs_impl<0b10, opcode, asmstr,
2740                            (outs GPR32:$Rt), (ins GPR64xsp0:$Rn),
2741                            [], NoItinerary>,
2742              Sched<[WriteLd]>;
2743
2744  def _dword: A64I_LRexs_impl<0b11, opcode, asmstr,
2745                            (outs GPR64:$Rt), (ins GPR64xsp0:$Rn),
2746                            [], NoItinerary>,
2747              Sched<[WriteLd]>;
2748}
2749
2750defm LDXR  : A64I_LRex<"ldxr",  0b000>;
2751defm LDAXR : A64I_LRex<"ldaxr", 0b001>;
2752defm LDAR  : A64I_LRex<"ldar",  0b101>;
2753
2754class acquiring_load<PatFrag base>
2755  : PatFrag<(ops node:$ptr), (base node:$ptr), [{
2756  AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getOrdering();
2757  return Ordering == Acquire || Ordering == SequentiallyConsistent;
2758}]>;
2759
2760def atomic_load_acquire_8  : acquiring_load<atomic_load_8>;
2761def atomic_load_acquire_16 : acquiring_load<atomic_load_16>;
2762def atomic_load_acquire_32 : acquiring_load<atomic_load_32>;
2763def atomic_load_acquire_64 : acquiring_load<atomic_load_64>;
2764
2765def : Pat<(atomic_load_acquire_8  i64:$Rn), (LDAR_byte  $Rn)>;
2766def : Pat<(atomic_load_acquire_16 i64:$Rn), (LDAR_hword $Rn)>;
2767def : Pat<(atomic_load_acquire_32 i64:$Rn), (LDAR_word  $Rn)>;
2768def : Pat<(atomic_load_acquire_64 i64:$Rn), (LDAR_dword $Rn)>;
2769
2770//===----------------------------------
2771// Store-release (no exclusivity)
2772//===----------------------------------
2773
2774class A64I_SLexs_impl<bits<2> size, bits<3> opcode, string asm, dag outs,
2775                        dag ins, list<dag> pat,
2776                        InstrItinClass itin> :
2777        A64I_LDSTex_tn <size,
2778                        opcode{2}, 0, opcode{1}, opcode{0},
2779                        outs, ins,
2780                        !strconcat(asm, "\t$Rt, [$Rn]"),
2781                        pat, itin> {
2782  let mayStore = 1;
2783  let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
2784}
2785
2786class releasing_store<PatFrag base>
2787  : PatFrag<(ops node:$ptr, node:$val), (base node:$ptr, node:$val), [{
2788  AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getOrdering();
2789  return Ordering == Release || Ordering == SequentiallyConsistent;
2790}]>;
2791
2792def atomic_store_release_8  : releasing_store<atomic_store_8>;
2793def atomic_store_release_16 : releasing_store<atomic_store_16>;
2794def atomic_store_release_32 : releasing_store<atomic_store_32>;
2795def atomic_store_release_64 : releasing_store<atomic_store_64>;
2796
2797multiclass A64I_SLex<string asmstr, bits<3> opcode, string prefix> {
2798  def _byte:  A64I_SLexs_impl<0b00, opcode, !strconcat(asmstr, "b"),
2799                            (outs), (ins GPR32:$Rt, GPR64xsp0:$Rn),
2800                            [(atomic_store_release_8 i64:$Rn, i32:$Rt)],
2801                            NoItinerary>,
2802              Sched<[WriteSt, ReadSt, ReadSt]>;
2803
2804  def _hword:  A64I_SLexs_impl<0b01, opcode, !strconcat(asmstr, "h"),
2805                           (outs), (ins GPR32:$Rt, GPR64xsp0:$Rn),
2806                           [(atomic_store_release_16 i64:$Rn, i32:$Rt)],
2807                           NoItinerary>,
2808               Sched<[WriteSt, ReadSt, ReadSt]>;
2809
2810  def _word:  A64I_SLexs_impl<0b10, opcode, asmstr,
2811                           (outs), (ins GPR32:$Rt, GPR64xsp0:$Rn),
2812                           [(atomic_store_release_32 i64:$Rn, i32:$Rt)],
2813                           NoItinerary>,
2814              Sched<[WriteSt, ReadSt, ReadSt]>;
2815
2816  def _dword: A64I_SLexs_impl<0b11, opcode, asmstr,
2817                           (outs), (ins GPR64:$Rt, GPR64xsp0:$Rn),
2818                           [(atomic_store_release_64 i64:$Rn, i64:$Rt)],
2819                           NoItinerary>,
2820              Sched<[WriteSt, ReadSt, ReadSt]>;
2821}
2822
2823defm STLR  : A64I_SLex<"stlr", 0b101, "STLR">;
2824
2825//===----------------------------------
2826// Store-exclusive pair (releasing & normal)
2827//===----------------------------------
2828
2829class A64I_SPexs_impl<bits<2> size, bits<3> opcode, string asm, dag outs,
2830                        dag ins, list<dag> pat,
2831                        InstrItinClass itin> :
2832     A64I_LDSTex_stt2n <size,
2833                        opcode{2}, 0, opcode{1}, opcode{0},
2834                        outs, ins,
2835                        !strconcat(asm, "\t$Rs, $Rt, $Rt2, [$Rn]"),
2836                        pat, itin> {
2837  let mayStore = 1;
2838}
2839
2840
2841multiclass A64I_SPex<string asmstr, bits<3> opcode> {
2842  def _word:  A64I_SPexs_impl<0b10, opcode, asmstr, (outs),
2843                            (ins GPR32:$Rs, GPR32:$Rt, GPR32:$Rt2,
2844                                 GPR64xsp0:$Rn),
2845                            [], NoItinerary>,
2846              Sched<[WriteSt, ReadSt, ReadSt, ReadSt]>;
2847
2848  def _dword: A64I_SPexs_impl<0b11, opcode, asmstr, (outs),
2849                            (ins GPR32:$Rs, GPR64:$Rt, GPR64:$Rt2,
2850                                            GPR64xsp0:$Rn),
2851                            [], NoItinerary>,
2852              Sched<[WriteSt, ReadSt, ReadSt, ReadSt]>;
2853}
2854
2855defm STXP  : A64I_SPex<"stxp", 0b010>;
2856defm STLXP : A64I_SPex<"stlxp", 0b011>;
2857
2858//===----------------------------------
2859// Load-exclusive pair (acquiring & normal)
2860//===----------------------------------
2861
2862class A64I_LPexs_impl<bits<2> size, bits<3> opcode, string asm, dag outs,
2863                        dag ins, list<dag> pat,
2864                        InstrItinClass itin> :
2865      A64I_LDSTex_tt2n <size,
2866                        opcode{2}, 1, opcode{1}, opcode{0},
2867                        outs, ins,
2868                        !strconcat(asm, "\t$Rt, $Rt2, [$Rn]"),
2869                        pat, itin>{
2870  let mayLoad = 1;
2871  let DecoderMethod = "DecodeLoadPairExclusiveInstruction";
2872  let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
2873}
2874
2875multiclass A64I_LPex<string asmstr, bits<3> opcode> {
2876  def _word:  A64I_LPexs_impl<0b10, opcode, asmstr,
2877                            (outs GPR32:$Rt, GPR32:$Rt2),
2878                            (ins GPR64xsp0:$Rn),
2879                            [], NoItinerary>,
2880              Sched<[WriteLd, WriteLd, ReadLd]>;
2881
2882  def _dword: A64I_LPexs_impl<0b11, opcode, asmstr,
2883                            (outs GPR64:$Rt, GPR64:$Rt2),
2884                            (ins GPR64xsp0:$Rn),
2885                            [], NoItinerary>,
2886              Sched<[WriteLd, WriteLd, ReadLd]>;
2887}
2888
2889defm LDXP  : A64I_LPex<"ldxp", 0b010>;
2890defm LDAXP : A64I_LPex<"ldaxp", 0b011>;
2891
2892//===----------------------------------------------------------------------===//
2893// Load-store register (unscaled immediate) instructions
2894//===----------------------------------------------------------------------===//
2895// Contains: LDURB, LDURH, LDRUSB, LDRUSH, LDRUSW, STUR, STURB, STURH and PRFUM
2896//
2897// and
2898//
2899//===----------------------------------------------------------------------===//
2900// Load-store register (register offset) instructions
2901//===----------------------------------------------------------------------===//
2902// Contains: LDRB, LDRH, LDRSB, LDRSH, LDRSW, STR, STRB, STRH and PRFM
2903//
2904// and
2905//
2906//===----------------------------------------------------------------------===//
2907// Load-store register (unsigned immediate) instructions
2908//===----------------------------------------------------------------------===//
2909// Contains: LDRB, LDRH, LDRSB, LDRSH, LDRSW, STR, STRB, STRH and PRFM
2910//
2911// and
2912//
2913//===----------------------------------------------------------------------===//
2914// Load-store register (immediate post-indexed) instructions
2915//===----------------------------------------------------------------------===//
2916// Contains: STRB, STRH, STR, LDRB, LDRH, LDR, LDRSB, LDRSH, LDRSW
2917//
2918// and
2919//
2920//===----------------------------------------------------------------------===//
2921// Load-store register (immediate pre-indexed) instructions
2922//===----------------------------------------------------------------------===//
2923// Contains: STRB, STRH, STR, LDRB, LDRH, LDR, LDRSB, LDRSH, LDRSW
2924
2925// Note that patterns are much later on in a completely separate section (they
2926// need ADRPxi to be defined).
2927
2928//===-------------------------------
2929// 1. Various operands needed
2930//===-------------------------------
2931
2932//===-------------------------------
2933// 1.1 Unsigned 12-bit immediate operands
2934//===-------------------------------
2935// The addressing mode for these instructions consists of an unsigned 12-bit
2936// immediate which is scaled by the size of the memory access.
2937//
2938// We represent this in the MC layer by two operands:
2939//     1. A base register.
2940//     2. A 12-bit immediate: not multiplied by access size, so "LDR x0,[x0,#8]"
2941//        would have '1' in this field.
2942// This means that separate functions are needed for converting representations
2943// which *are* aware of the intended access size.
2944
2945// Anything that creates an MCInst (Decoding, selection and AsmParsing) has to
2946// know the access size via some means. An isolated operand does not have this
2947// information unless told from here, which means we need separate tablegen
2948// Operands for each access size. This multiclass takes care of instantiating
2949// the correct template functions in the rest of the backend.
2950
2951//===-------------------------------
2952// 1.1 Unsigned 12-bit immediate operands
2953//===-------------------------------
2954
2955multiclass offsets_uimm12<int MemSize, string prefix> {
2956  def uimm12_asmoperand : AsmOperandClass {
2957    let Name = "OffsetUImm12_" # MemSize;
2958    let PredicateMethod = "isOffsetUImm12<" # MemSize # ">";
2959    let RenderMethod = "addOffsetUImm12Operands<" # MemSize # ">";
2960    let DiagnosticType = "LoadStoreUImm12_" # MemSize;
2961  }
2962
2963  // Pattern is really no more than an ImmLeaf, but predicated on MemSize which
2964  // complicates things beyond TableGen's ken.
2965  def uimm12 : Operand<i64>,
2966               ComplexPattern<i64, 1, "SelectOffsetUImm12<" # MemSize # ">"> {
2967    let ParserMatchClass
2968      = !cast<AsmOperandClass>(prefix # uimm12_asmoperand);
2969
2970    let PrintMethod = "printOffsetUImm12Operand<" # MemSize # ">";
2971    let EncoderMethod = "getOffsetUImm12OpValue<" # MemSize # ">";
2972  }
2973}
2974
2975defm byte_  : offsets_uimm12<1, "byte_">;
2976defm hword_ : offsets_uimm12<2, "hword_">;
2977defm word_  : offsets_uimm12<4, "word_">;
2978defm dword_ : offsets_uimm12<8, "dword_">;
2979defm qword_ : offsets_uimm12<16, "qword_">;
2980
2981//===-------------------------------
2982// 1.1 Signed 9-bit immediate operands
2983//===-------------------------------
2984
2985// The MCInst is expected to store the bit-wise encoding of the value,
2986// which amounts to lopping off the extended sign bits.
2987def SDXF_simm9 : SDNodeXForm<imm, [{
2988  return CurDAG->getTargetConstant(N->getZExtValue() & 0x1ff, MVT::i32);
2989}]>;
2990
2991def simm9_asmoperand : AsmOperandClass {
2992  let Name = "SImm9";
2993  let PredicateMethod = "isSImm<9>";
2994  let RenderMethod = "addSImmOperands<9>";
2995  let DiagnosticType = "LoadStoreSImm9";
2996}
2997
2998def simm9 : Operand<i64>,
2999            ImmLeaf<i64, [{ return Imm >= -0x100 && Imm <= 0xff; }],
3000            SDXF_simm9> {
3001  let PrintMethod = "printOffsetSImm9Operand";
3002  let ParserMatchClass = simm9_asmoperand;
3003}
3004
3005
3006//===-------------------------------
3007// 1.3 Register offset extensions
3008//===-------------------------------
3009
3010// The assembly-syntax for these addressing-modes is:
3011//    [<Xn|SP>, <R><m> {, <extend> {<amount>}}]
3012//
3013// The essential semantics are:
3014//     + <amount> is a shift: #<log(transfer size)> or #0
3015//     + <R> can be W or X.
3016//     + If <R> is W, <extend> can be UXTW or SXTW
3017//     + If <R> is X, <extend> can be LSL or SXTX
3018//
3019// The trickiest of those constraints is that Rm can be either GPR32 or GPR64,
3020// which will need separate instructions for LLVM type-consistency. We'll also
3021// need separate operands, of course.
3022multiclass regexts<int MemSize, int RmSize, RegisterClass GPR,
3023                   string Rm, string prefix> {
3024  def regext_asmoperand : AsmOperandClass {
3025    let Name = "AddrRegExtend_" # MemSize # "_" #  Rm;
3026    let PredicateMethod = "isAddrRegExtend<" # MemSize # "," # RmSize # ">";
3027    let RenderMethod = "addAddrRegExtendOperands<" # MemSize # ">";
3028    let DiagnosticType = "LoadStoreExtend" # RmSize # "_" # MemSize;
3029  }
3030
3031  def regext : Operand<i64> {
3032    let PrintMethod
3033      = "printAddrRegExtendOperand<" # MemSize # ", " # RmSize # ">";
3034
3035    let DecoderMethod = "DecodeAddrRegExtendOperand";
3036    let ParserMatchClass
3037      = !cast<AsmOperandClass>(prefix # regext_asmoperand);
3038  }
3039}
3040
3041multiclass regexts_wx<int MemSize, string prefix> {
3042  // Rm is an X-register if LSL or SXTX are specified as the shift.
3043  defm Xm_ : regexts<MemSize, 64, GPR64, "Xm", prefix # "Xm_">;
3044
3045  // Rm is a W-register if UXTW or SXTW are specified as the shift.
3046  defm Wm_ : regexts<MemSize, 32, GPR32, "Wm", prefix # "Wm_">;
3047}
3048
3049defm byte_  : regexts_wx<1, "byte_">;
3050defm hword_ : regexts_wx<2, "hword_">;
3051defm word_  : regexts_wx<4, "word_">;
3052defm dword_ : regexts_wx<8, "dword_">;
3053defm qword_ : regexts_wx<16, "qword_">;
3054
3055
3056//===------------------------------
3057// 2. The instructions themselves.
3058//===------------------------------
3059
3060// We have the following instructions to implement:
3061// |                 | B     | H     | W     | X      |
3062// |-----------------+-------+-------+-------+--------|
3063// | unsigned str    | STRB  | STRH  | STR   | STR    |
3064// | unsigned ldr    | LDRB  | LDRH  | LDR   | LDR    |
3065// | signed ldr to W | LDRSB | LDRSH | -     | -      |
3066// | signed ldr to X | LDRSB | LDRSH | LDRSW | (PRFM) |
3067
3068// This will instantiate the LDR/STR instructions you'd expect to use for an
3069// unsigned datatype (first two rows above) or floating-point register, which is
3070// reasonably uniform across all access sizes.
3071
3072
3073//===------------------------------
3074// 2.1 Regular instructions
3075//===------------------------------
3076
3077// This class covers the basic unsigned or irrelevantly-signed loads and stores,
3078// to general-purpose and floating-point registers.
3079
3080class AddrParams<string prefix> {
3081  Operand uimm12 = !cast<Operand>(prefix # "_uimm12");
3082
3083  Operand regextWm = !cast<Operand>(prefix # "_Wm_regext");
3084  Operand regextXm = !cast<Operand>(prefix # "_Xm_regext");
3085}
3086
3087def byte_addrparams : AddrParams<"byte">;
3088def hword_addrparams : AddrParams<"hword">;
3089def word_addrparams : AddrParams<"word">;
3090def dword_addrparams : AddrParams<"dword">;
3091def qword_addrparams : AddrParams<"qword">;
3092
3093multiclass A64I_LDRSTR_unsigned<string prefix, bits<2> size, bit v,
3094                                bit high_opc, string asmsuffix,
3095                                RegisterClass GPR, AddrParams params> {
3096  // Unsigned immediate
3097  def _STR : A64I_LSunsigimm<size, v, {high_opc, 0b0},
3098                     (outs), (ins GPR:$Rt, GPR64xsp:$Rn, params.uimm12:$UImm12),
3099                     "str" # asmsuffix # "\t$Rt, [$Rn, $UImm12]",
3100                     [], NoItinerary>,
3101             Sched<[WriteSt, ReadSt, ReadSt]> {
3102    let mayStore = 1;
3103  }
3104  def : InstAlias<"str" # asmsuffix # " $Rt, [$Rn]",
3105                (!cast<Instruction>(prefix # "_STR") GPR:$Rt, GPR64xsp:$Rn, 0)>;
3106
3107  def _LDR : A64I_LSunsigimm<size, v, {high_opc, 0b1},
3108                      (outs GPR:$Rt), (ins GPR64xsp:$Rn, params.uimm12:$UImm12),
3109                      "ldr" #  asmsuffix # "\t$Rt, [$Rn, $UImm12]",
3110                      [], NoItinerary>,
3111             Sched<[WriteLd, ReadLd]> {
3112    let mayLoad = 1;
3113  }
3114  def : InstAlias<"ldr" # asmsuffix # " $Rt, [$Rn]",
3115                (!cast<Instruction>(prefix # "_LDR") GPR:$Rt, GPR64xsp:$Rn, 0)>;
3116
3117  // Register offset (four of these: load/store and Wm/Xm).
3118  let mayLoad = 1 in {
3119    def _Wm_RegOffset_LDR : A64I_LSregoff<size, v, {high_opc, 0b1}, 0b0,
3120                            (outs GPR:$Rt),
3121                            (ins GPR64xsp:$Rn, GPR32:$Rm, params.regextWm:$Ext),
3122                            "ldr" # asmsuffix # "\t$Rt, [$Rn, $Rm, $Ext]",
3123                            [], NoItinerary>,
3124                            Sched<[WriteLd, ReadLd, ReadLd]>;
3125
3126    def _Xm_RegOffset_LDR : A64I_LSregoff<size, v, {high_opc, 0b1}, 0b1,
3127                            (outs GPR:$Rt),
3128                            (ins GPR64xsp:$Rn, GPR64:$Rm, params.regextXm:$Ext),
3129                            "ldr" # asmsuffix # "\t$Rt, [$Rn, $Rm, $Ext]",
3130                            [], NoItinerary>,
3131                            Sched<[WriteLd, ReadLd, ReadLd]>;
3132  }
3133  def : InstAlias<"ldr" # asmsuffix # " $Rt, [$Rn, $Rm]",
3134        (!cast<Instruction>(prefix # "_Xm_RegOffset_LDR") GPR:$Rt, GPR64xsp:$Rn,
3135                                                          GPR64:$Rm, 2)>;
3136
3137  let mayStore = 1 in {
3138    def _Wm_RegOffset_STR : A64I_LSregoff<size, v, {high_opc, 0b0}, 0b0,
3139                                  (outs), (ins GPR:$Rt, GPR64xsp:$Rn, GPR32:$Rm,
3140                                               params.regextWm:$Ext),
3141                                  "str" # asmsuffix # "\t$Rt, [$Rn, $Rm, $Ext]",
3142                                  [], NoItinerary>,
3143                            Sched<[WriteSt, ReadSt, ReadSt, ReadSt]>;
3144
3145    def _Xm_RegOffset_STR : A64I_LSregoff<size, v, {high_opc, 0b0}, 0b1,
3146                                  (outs), (ins GPR:$Rt, GPR64xsp:$Rn, GPR64:$Rm,
3147                                               params.regextXm:$Ext),
3148                                  "str" # asmsuffix # "\t$Rt, [$Rn, $Rm, $Ext]",
3149                                  [], NoItinerary>,
3150                            Sched<[WriteSt, ReadSt, ReadSt, ReadSt]>;
3151  }
3152  def : InstAlias<"str" # asmsuffix # " $Rt, [$Rn, $Rm]",
3153      (!cast<Instruction>(prefix # "_Xm_RegOffset_STR") GPR:$Rt, GPR64xsp:$Rn,
3154                                                        GPR64:$Rm, 2)>;
3155
3156  // Unaligned immediate
3157  def _STUR : A64I_LSunalimm<size, v, {high_opc, 0b0},
3158                             (outs), (ins GPR:$Rt, GPR64xsp:$Rn, simm9:$SImm9),
3159                             "stur" # asmsuffix # "\t$Rt, [$Rn, $SImm9]",
3160                             [], NoItinerary>,
3161              Sched<[WriteSt, ReadSt, ReadSt]> {
3162    let mayStore = 1;
3163  }
3164  def : InstAlias<"stur" # asmsuffix # " $Rt, [$Rn]",
3165               (!cast<Instruction>(prefix # "_STUR") GPR:$Rt, GPR64xsp:$Rn, 0)>;
3166
3167  def _LDUR : A64I_LSunalimm<size, v, {high_opc, 0b1},
3168                             (outs GPR:$Rt), (ins GPR64xsp:$Rn, simm9:$SImm9),
3169                             "ldur" # asmsuffix # "\t$Rt, [$Rn, $SImm9]",
3170                             [], NoItinerary>,
3171              Sched<[WriteLd, ReadLd]> {
3172    let mayLoad = 1;
3173  }
3174  def : InstAlias<"ldur" # asmsuffix # " $Rt, [$Rn]",
3175               (!cast<Instruction>(prefix # "_LDUR") GPR:$Rt, GPR64xsp:$Rn, 0)>;
3176
3177  // Post-indexed
3178  def _PostInd_STR : A64I_LSpostind<size, v, {high_opc, 0b0},
3179                               (outs GPR64xsp:$Rn_wb),
3180                               (ins GPR:$Rt, GPR64xsp:$Rn, simm9:$SImm9),
3181                               "str" # asmsuffix # "\t$Rt, [$Rn], $SImm9",
3182                               [], NoItinerary>,
3183                     Sched<[WriteSt, ReadSt, ReadSt]> {
3184    let Constraints = "$Rn = $Rn_wb";
3185    let mayStore = 1;
3186
3187    // Decoder only needed for unpredictability checking (FIXME).
3188    let DecoderMethod = "DecodeSingleIndexedInstruction";
3189  }
3190
3191  def _PostInd_LDR : A64I_LSpostind<size, v, {high_opc, 0b1},
3192                                    (outs GPR:$Rt, GPR64xsp:$Rn_wb),
3193                                    (ins GPR64xsp:$Rn, simm9:$SImm9),
3194                                    "ldr" # asmsuffix # "\t$Rt, [$Rn], $SImm9",
3195                                    [], NoItinerary>,
3196                     Sched<[WriteLd, WriteLd, ReadLd]> {
3197    let mayLoad = 1;
3198    let Constraints = "$Rn = $Rn_wb";
3199    let DecoderMethod = "DecodeSingleIndexedInstruction";
3200  }
3201
3202  // Pre-indexed
3203  def _PreInd_STR : A64I_LSpreind<size, v, {high_opc, 0b0},
3204                               (outs GPR64xsp:$Rn_wb),
3205                               (ins GPR:$Rt, GPR64xsp:$Rn, simm9:$SImm9),
3206                               "str" # asmsuffix # "\t$Rt, [$Rn, $SImm9]!",
3207                               [], NoItinerary>,
3208                    Sched<[WriteSt, ReadSt, ReadSt]> {
3209    let Constraints = "$Rn = $Rn_wb";
3210    let mayStore = 1;
3211
3212    // Decoder only needed for unpredictability checking (FIXME).
3213    let DecoderMethod = "DecodeSingleIndexedInstruction";
3214  }
3215
3216  def _PreInd_LDR : A64I_LSpreind<size, v, {high_opc, 0b1},
3217                                    (outs GPR:$Rt, GPR64xsp:$Rn_wb),
3218                                    (ins GPR64xsp:$Rn, simm9:$SImm9),
3219                                    "ldr" # asmsuffix # "\t$Rt, [$Rn, $SImm9]!",
3220                                    [], NoItinerary>,
3221                    Sched<[WriteLd, WriteLd, ReadLd]> {
3222    let mayLoad = 1;
3223    let Constraints = "$Rn = $Rn_wb";
3224    let DecoderMethod = "DecodeSingleIndexedInstruction";
3225  }
3226
3227}
3228
3229// STRB/LDRB: First define the instructions
3230defm LS8
3231  : A64I_LDRSTR_unsigned<"LS8", 0b00, 0b0, 0b0, "b", GPR32, byte_addrparams>;
3232
3233// STRH/LDRH
3234defm LS16
3235  : A64I_LDRSTR_unsigned<"LS16", 0b01, 0b0, 0b0, "h", GPR32, hword_addrparams>;
3236
3237
3238// STR/LDR to/from a W register
3239defm LS32
3240  : A64I_LDRSTR_unsigned<"LS32", 0b10, 0b0, 0b0, "", GPR32, word_addrparams>;
3241
3242// STR/LDR to/from an X register
3243defm LS64
3244  : A64I_LDRSTR_unsigned<"LS64", 0b11, 0b0, 0b0, "", GPR64, dword_addrparams>;
3245
3246let Predicates = [HasFPARMv8] in {
3247// STR/LDR to/from a B register
3248defm LSFP8
3249  : A64I_LDRSTR_unsigned<"LSFP8", 0b00, 0b1, 0b0, "", FPR8, byte_addrparams>;
3250
3251// STR/LDR to/from an H register
3252defm LSFP16
3253  : A64I_LDRSTR_unsigned<"LSFP16", 0b01, 0b1, 0b0, "", FPR16, hword_addrparams>;
3254
3255// STR/LDR to/from an S register
3256defm LSFP32
3257  : A64I_LDRSTR_unsigned<"LSFP32", 0b10, 0b1, 0b0, "", FPR32, word_addrparams>;
3258// STR/LDR to/from a D register
3259defm LSFP64
3260  : A64I_LDRSTR_unsigned<"LSFP64", 0b11, 0b1, 0b0, "", FPR64, dword_addrparams>;
3261// STR/LDR to/from a Q register
3262defm LSFP128
3263  : A64I_LDRSTR_unsigned<"LSFP128", 0b00, 0b1, 0b1, "", FPR128,
3264                         qword_addrparams>;
3265}
3266
3267//===------------------------------
3268// 2.3 Signed loads
3269//===------------------------------
3270
3271// Byte and half-word signed loads can both go into either an X or a W register,
3272// so it's worth factoring out. Signed word loads don't fit because there is no
3273// W version.
3274multiclass A64I_LDR_signed<bits<2> size, string asmopcode, AddrParams params,
3275                           string prefix> {
3276  // Unsigned offset
3277  def w : A64I_LSunsigimm<size, 0b0, 0b11,
3278                          (outs GPR32:$Rt),
3279                          (ins GPR64xsp:$Rn, params.uimm12:$UImm12),
3280                          "ldrs" # asmopcode # "\t$Rt, [$Rn, $UImm12]",
3281                          [], NoItinerary>,
3282          Sched<[WriteLd, ReadLd]> {
3283    let mayLoad = 1;
3284  }
3285  def : InstAlias<"ldrs" # asmopcode # " $Rt, [$Rn]",
3286                  (!cast<Instruction>(prefix # w) GPR32:$Rt, GPR64xsp:$Rn, 0)>;
3287
3288  def x : A64I_LSunsigimm<size, 0b0, 0b10,
3289                          (outs GPR64:$Rt),
3290                          (ins GPR64xsp:$Rn, params.uimm12:$UImm12),
3291                          "ldrs" # asmopcode # "\t$Rt, [$Rn, $UImm12]",
3292                          [], NoItinerary>,
3293          Sched<[WriteLd, ReadLd]> {
3294    let mayLoad = 1;
3295  }
3296  def : InstAlias<"ldrs" # asmopcode # " $Rt, [$Rn]",
3297                  (!cast<Instruction>(prefix # x) GPR64:$Rt, GPR64xsp:$Rn, 0)>;
3298
3299  // Register offset
3300  let mayLoad = 1 in {
3301    def w_Wm_RegOffset : A64I_LSregoff<size, 0b0, 0b11, 0b0,
3302                            (outs GPR32:$Rt),
3303                            (ins GPR64xsp:$Rn, GPR32:$Rm, params.regextWm:$Ext),
3304                            "ldrs" # asmopcode # "\t$Rt, [$Rn, $Rm, $Ext]",
3305                            [], NoItinerary>,
3306                         Sched<[WriteLd, ReadLd, ReadLd]>;
3307
3308    def w_Xm_RegOffset : A64I_LSregoff<size, 0b0, 0b11, 0b1,
3309                            (outs GPR32:$Rt),
3310                            (ins GPR64xsp:$Rn, GPR64:$Rm, params.regextXm:$Ext),
3311                            "ldrs" # asmopcode # "\t$Rt, [$Rn, $Rm, $Ext]",
3312                            [], NoItinerary>,
3313                         Sched<[WriteLd, ReadLd, ReadLd]>;
3314
3315    def x_Wm_RegOffset : A64I_LSregoff<size, 0b0, 0b10, 0b0,
3316                            (outs GPR64:$Rt),
3317                            (ins GPR64xsp:$Rn, GPR32:$Rm, params.regextWm:$Ext),
3318                            "ldrs" # asmopcode # "\t$Rt, [$Rn, $Rm, $Ext]",
3319                            [], NoItinerary>,
3320                         Sched<[WriteLd, ReadLd, ReadLd]>;
3321
3322    def x_Xm_RegOffset : A64I_LSregoff<size, 0b0, 0b10, 0b1,
3323                            (outs GPR64:$Rt),
3324                            (ins GPR64xsp:$Rn, GPR64:$Rm, params.regextXm:$Ext),
3325                            "ldrs" # asmopcode # "\t$Rt, [$Rn, $Rm, $Ext]",
3326                            [], NoItinerary>,
3327                         Sched<[WriteLd, ReadLd, ReadLd]>;
3328  }
3329  def : InstAlias<"ldrs" # asmopcode # " $Rt, [$Rn, $Rm]",
3330        (!cast<Instruction>(prefix # "w_Xm_RegOffset") GPR32:$Rt, GPR64xsp:$Rn,
3331                                                       GPR64:$Rm, 2)>;
3332
3333  def : InstAlias<"ldrs" # asmopcode # " $Rt, [$Rn, $Rm]",
3334        (!cast<Instruction>(prefix # "x_Xm_RegOffset") GPR64:$Rt, GPR64xsp:$Rn,
3335                                                       GPR64:$Rm, 2)>;
3336
3337
3338  let mayLoad = 1 in {
3339    // Unaligned offset
3340    def w_U : A64I_LSunalimm<size, 0b0, 0b11,
3341                             (outs GPR32:$Rt),
3342                             (ins GPR64xsp:$Rn, simm9:$SImm9),
3343                             "ldurs" # asmopcode # "\t$Rt, [$Rn, $SImm9]",
3344                             [], NoItinerary>,
3345              Sched<[WriteLd, ReadLd]>;
3346
3347    def x_U : A64I_LSunalimm<size, 0b0, 0b10,
3348                             (outs GPR64:$Rt),
3349                             (ins GPR64xsp:$Rn, simm9:$SImm9),
3350                             "ldurs" # asmopcode # "\t$Rt, [$Rn, $SImm9]",
3351                             [], NoItinerary>,
3352              Sched<[WriteLd, ReadLd]>;
3353
3354
3355    // Post-indexed
3356    def w_PostInd : A64I_LSpostind<size, 0b0, 0b11,
3357                                 (outs GPR32:$Rt, GPR64xsp:$Rn_wb),
3358                                 (ins GPR64xsp:$Rn, simm9:$SImm9),
3359                                 "ldrs" # asmopcode # "\t$Rt, [$Rn], $SImm9",
3360                                 [], NoItinerary>,
3361                    Sched<[WriteLd, WriteLd, ReadLd]> {
3362      let Constraints = "$Rn = $Rn_wb";
3363      let DecoderMethod = "DecodeSingleIndexedInstruction";
3364    }
3365
3366    def x_PostInd : A64I_LSpostind<size, 0b0, 0b10,
3367                                   (outs GPR64:$Rt, GPR64xsp:$Rn_wb),
3368                                   (ins GPR64xsp:$Rn, simm9:$SImm9),
3369                                   "ldrs" # asmopcode # "\t$Rt, [$Rn], $SImm9",
3370                                   [], NoItinerary>,
3371                    Sched<[WriteLd, WriteLd, ReadLd]> {
3372      let Constraints = "$Rn = $Rn_wb";
3373      let DecoderMethod = "DecodeSingleIndexedInstruction";
3374    }
3375
3376    // Pre-indexed
3377    def w_PreInd : A64I_LSpreind<size, 0b0, 0b11,
3378                                 (outs GPR32:$Rt, GPR64xsp:$Rn_wb),
3379                                 (ins GPR64xsp:$Rn, simm9:$SImm9),
3380                                 "ldrs" # asmopcode # "\t$Rt, [$Rn, $SImm9]!",
3381                                 [], NoItinerary>,
3382                   Sched<[WriteLd, WriteLd, ReadLd]> {
3383      let Constraints = "$Rn = $Rn_wb";
3384      let DecoderMethod = "DecodeSingleIndexedInstruction";
3385    }
3386
3387    def x_PreInd : A64I_LSpreind<size, 0b0, 0b10,
3388                                 (outs GPR64:$Rt, GPR64xsp:$Rn_wb),
3389                                 (ins GPR64xsp:$Rn, simm9:$SImm9),
3390                                 "ldrs" # asmopcode # "\t$Rt, [$Rn, $SImm9]!",
3391                                 [], NoItinerary>,
3392                   Sched<[WriteLd, WriteLd, ReadLd]> {
3393      let Constraints = "$Rn = $Rn_wb";
3394      let DecoderMethod = "DecodeSingleIndexedInstruction";
3395    }
3396  } // let mayLoad = 1
3397}
3398
3399// LDRSB
3400defm LDRSB : A64I_LDR_signed<0b00, "b", byte_addrparams, "LDRSB">;
3401// LDRSH
3402defm LDRSH : A64I_LDR_signed<0b01, "h", hword_addrparams, "LDRSH">;
3403
3404// LDRSW: load a 32-bit register, sign-extending to 64-bits.
3405def LDRSWx
3406    : A64I_LSunsigimm<0b10, 0b0, 0b10,
3407                    (outs GPR64:$Rt),
3408                    (ins GPR64xsp:$Rn, word_uimm12:$UImm12),
3409                    "ldrsw\t$Rt, [$Rn, $UImm12]",
3410                    [], NoItinerary>,
3411      Sched<[WriteLd, ReadLd]> {
3412  let mayLoad = 1;
3413}
3414def : InstAlias<"ldrsw $Rt, [$Rn]", (LDRSWx GPR64:$Rt, GPR64xsp:$Rn, 0)>;
3415
3416let mayLoad = 1 in {
3417  def LDRSWx_Wm_RegOffset : A64I_LSregoff<0b10, 0b0, 0b10, 0b0,
3418                             (outs GPR64:$Rt),
3419                             (ins GPR64xsp:$Rn, GPR32:$Rm, word_Wm_regext:$Ext),
3420                             "ldrsw\t$Rt, [$Rn, $Rm, $Ext]",
3421                             [], NoItinerary>,
3422                            Sched<[WriteLd, ReadLd, ReadLd]>;
3423
3424  def LDRSWx_Xm_RegOffset : A64I_LSregoff<0b10, 0b0, 0b10, 0b1,
3425                             (outs GPR64:$Rt),
3426                             (ins GPR64xsp:$Rn, GPR64:$Rm, word_Xm_regext:$Ext),
3427                             "ldrsw\t$Rt, [$Rn, $Rm, $Ext]",
3428                             [], NoItinerary>,
3429                            Sched<[WriteLd, ReadLd, ReadLd]>;
3430}
3431def : InstAlias<"ldrsw $Rt, [$Rn, $Rm]",
3432                (LDRSWx_Xm_RegOffset GPR64:$Rt, GPR64xsp:$Rn, GPR64:$Rm, 2)>;
3433
3434
3435def LDURSWx
3436    : A64I_LSunalimm<0b10, 0b0, 0b10,
3437                    (outs GPR64:$Rt),
3438                    (ins GPR64xsp:$Rn, simm9:$SImm9),
3439                    "ldursw\t$Rt, [$Rn, $SImm9]",
3440                    [], NoItinerary>,
3441      Sched<[WriteLd, ReadLd]> {
3442  let mayLoad = 1;
3443}
3444def : InstAlias<"ldursw $Rt, [$Rn]", (LDURSWx GPR64:$Rt, GPR64xsp:$Rn, 0)>;
3445
3446def LDRSWx_PostInd
3447    : A64I_LSpostind<0b10, 0b0, 0b10,
3448                    (outs GPR64:$Rt, GPR64xsp:$Rn_wb),
3449                    (ins GPR64xsp:$Rn, simm9:$SImm9),
3450                    "ldrsw\t$Rt, [$Rn], $SImm9",
3451                    [], NoItinerary>,
3452      Sched<[WriteLd, WriteLd, ReadLd]> {
3453  let mayLoad = 1;
3454  let Constraints = "$Rn = $Rn_wb";
3455  let DecoderMethod = "DecodeSingleIndexedInstruction";
3456}
3457
3458def LDRSWx_PreInd : A64I_LSpreind<0b10, 0b0, 0b10,
3459                                 (outs GPR64:$Rt, GPR64xsp:$Rn_wb),
3460                                 (ins GPR64xsp:$Rn, simm9:$SImm9),
3461                                 "ldrsw\t$Rt, [$Rn, $SImm9]!",
3462                                 [], NoItinerary>,
3463                    Sched<[WriteLd, WriteLd, ReadLd]> {
3464  let mayLoad = 1;
3465  let Constraints = "$Rn = $Rn_wb";
3466  let DecoderMethod = "DecodeSingleIndexedInstruction";
3467}
3468
3469//===------------------------------
3470// 2.4 Prefetch operations
3471//===------------------------------
3472
3473def PRFM : A64I_LSunsigimm<0b11, 0b0, 0b10, (outs),
3474                 (ins prefetch_op:$Rt, GPR64xsp:$Rn, dword_uimm12:$UImm12),
3475                 "prfm\t$Rt, [$Rn, $UImm12]",
3476                 [], NoItinerary>,
3477           Sched<[WritePreLd, ReadPreLd]> {
3478  let mayLoad = 1;
3479}
3480def : InstAlias<"prfm $Rt, [$Rn]",
3481                (PRFM prefetch_op:$Rt, GPR64xsp:$Rn, 0)>;
3482
3483let mayLoad = 1 in {
3484  def PRFM_Wm_RegOffset : A64I_LSregoff<0b11, 0b0, 0b10, 0b0, (outs),
3485                                        (ins prefetch_op:$Rt, GPR64xsp:$Rn,
3486                                             GPR32:$Rm, dword_Wm_regext:$Ext),
3487                                        "prfm\t$Rt, [$Rn, $Rm, $Ext]",
3488                                        [], NoItinerary>,
3489                          Sched<[WritePreLd, ReadPreLd]>;
3490  def PRFM_Xm_RegOffset : A64I_LSregoff<0b11, 0b0, 0b10, 0b1, (outs),
3491                                        (ins prefetch_op:$Rt, GPR64xsp:$Rn,
3492                                             GPR64:$Rm, dword_Xm_regext:$Ext),
3493                                        "prfm\t$Rt, [$Rn, $Rm, $Ext]",
3494                                        [], NoItinerary>,
3495                          Sched<[WritePreLd, ReadPreLd]>;
3496}
3497
3498def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
3499                (PRFM_Xm_RegOffset prefetch_op:$Rt, GPR64xsp:$Rn,
3500                                   GPR64:$Rm, 2)>;
3501
3502
3503def PRFUM : A64I_LSunalimm<0b11, 0b0, 0b10, (outs),
3504                         (ins prefetch_op:$Rt, GPR64xsp:$Rn, simm9:$SImm9),
3505                         "prfum\t$Rt, [$Rn, $SImm9]",
3506                         [], NoItinerary>,
3507            Sched<[WritePreLd, ReadPreLd]> {
3508  let mayLoad = 1;
3509}
3510def : InstAlias<"prfum $Rt, [$Rn]",
3511                (PRFUM prefetch_op:$Rt, GPR64xsp:$Rn, 0)>;
3512
3513//===----------------------------------------------------------------------===//
3514// Load-store register (unprivileged) instructions
3515//===----------------------------------------------------------------------===//
3516// Contains: LDTRB, LDTRH, LDTRSB, LDTRSH, LDTRSW, STTR, STTRB and STTRH
3517
3518// These instructions very much mirror the "unscaled immediate" loads, but since
3519// there are no floating-point variants we need to split them out into their own
3520// section to avoid instantiation of "ldtr d0, [sp]" etc.
3521
3522multiclass A64I_LDTRSTTR<bits<2> size, string asmsuffix, RegisterClass GPR,
3523                         string prefix> {
3524  def _UnPriv_STR : A64I_LSunpriv<size, 0b0, 0b00,
3525                              (outs), (ins GPR:$Rt, GPR64xsp:$Rn, simm9:$SImm9),
3526                              "sttr" # asmsuffix # "\t$Rt, [$Rn, $SImm9]",
3527                              [], NoItinerary>,
3528                    Sched<[WriteLd, ReadLd]> {
3529    let mayStore = 1;
3530  }
3531
3532  def : InstAlias<"sttr" # asmsuffix # " $Rt, [$Rn]",
3533         (!cast<Instruction>(prefix # "_UnPriv_STR") GPR:$Rt, GPR64xsp:$Rn, 0)>;
3534
3535  def _UnPriv_LDR : A64I_LSunpriv<size, 0b0, 0b01,
3536                               (outs GPR:$Rt), (ins GPR64xsp:$Rn, simm9:$SImm9),
3537                               "ldtr" # asmsuffix # "\t$Rt, [$Rn, $SImm9]",
3538                               [], NoItinerary>,
3539                    Sched<[WriteLd, ReadLd]> {
3540    let mayLoad = 1;
3541  }
3542
3543  def : InstAlias<"ldtr" # asmsuffix # " $Rt, [$Rn]",
3544         (!cast<Instruction>(prefix # "_UnPriv_LDR") GPR:$Rt, GPR64xsp:$Rn, 0)>;
3545
3546}
3547
3548// STTRB/LDTRB: First define the instructions
3549defm LS8 : A64I_LDTRSTTR<0b00, "b", GPR32, "LS8">;
3550
3551// STTRH/LDTRH
3552defm LS16 : A64I_LDTRSTTR<0b01, "h", GPR32, "LS16">;
3553
3554// STTR/LDTR to/from a W register
3555defm LS32 : A64I_LDTRSTTR<0b10, "", GPR32, "LS32">;
3556
3557// STTR/LDTR to/from an X register
3558defm LS64 : A64I_LDTRSTTR<0b11, "", GPR64, "LS64">;
3559
3560// Now a class for the signed instructions that can go to either 32 or 64
3561// bits...
3562multiclass A64I_LDTR_signed<bits<2> size, string asmopcode, string prefix> {
3563  let mayLoad = 1 in {
3564    def w : A64I_LSunpriv<size, 0b0, 0b11,
3565                          (outs GPR32:$Rt),
3566                          (ins GPR64xsp:$Rn, simm9:$SImm9),
3567                          "ldtrs" # asmopcode # "\t$Rt, [$Rn, $SImm9]",
3568                          [], NoItinerary>,
3569            Sched<[WriteLd, ReadLd]>;
3570
3571    def x : A64I_LSunpriv<size, 0b0, 0b10,
3572                          (outs GPR64:$Rt),
3573                          (ins GPR64xsp:$Rn, simm9:$SImm9),
3574                          "ldtrs" # asmopcode # "\t$Rt, [$Rn, $SImm9]",
3575                          [], NoItinerary>,
3576            Sched<[WriteLd, ReadLd]>;
3577  }
3578
3579  def : InstAlias<"ldtrs" # asmopcode # " $Rt, [$Rn]",
3580                 (!cast<Instruction>(prefix # "w") GPR32:$Rt, GPR64xsp:$Rn, 0)>;
3581
3582  def : InstAlias<"ldtrs" # asmopcode # " $Rt, [$Rn]",
3583                 (!cast<Instruction>(prefix # "x") GPR64:$Rt, GPR64xsp:$Rn, 0)>;
3584
3585}
3586
3587// LDTRSB
3588defm LDTRSB : A64I_LDTR_signed<0b00, "b", "LDTRSB">;
3589// LDTRSH
3590defm LDTRSH : A64I_LDTR_signed<0b01, "h", "LDTRSH">;
3591
3592// And finally LDTRSW which only goes to 64 bits.
3593def LDTRSWx : A64I_LSunpriv<0b10, 0b0, 0b10,
3594                            (outs GPR64:$Rt),
3595                            (ins GPR64xsp:$Rn, simm9:$SImm9),
3596                            "ldtrsw\t$Rt, [$Rn, $SImm9]",
3597                            [], NoItinerary>,
3598              Sched<[WriteLd, ReadLd]> {
3599  let mayLoad = 1;
3600}
3601def : InstAlias<"ldtrsw $Rt, [$Rn]", (LDTRSWx GPR64:$Rt, GPR64xsp:$Rn, 0)>;
3602
3603//===----------------------------------------------------------------------===//
3604// Load-store register pair (offset) instructions
3605//===----------------------------------------------------------------------===//
3606//
3607// and
3608//
3609//===----------------------------------------------------------------------===//
3610// Load-store register pair (post-indexed) instructions
3611//===----------------------------------------------------------------------===//
3612// Contains: STP, LDP, LDPSW
3613//
3614// and
3615//
3616//===----------------------------------------------------------------------===//
3617// Load-store register pair (pre-indexed) instructions
3618//===----------------------------------------------------------------------===//
3619// Contains: STP, LDP, LDPSW
3620//
3621// and
3622//
3623//===----------------------------------------------------------------------===//
3624// Load-store non-temporal register pair (offset) instructions
3625//===----------------------------------------------------------------------===//
3626// Contains: STNP, LDNP
3627
3628
3629// Anything that creates an MCInst (Decoding, selection and AsmParsing) has to
3630// know the access size via some means. An isolated operand does not have this
3631// information unless told from here, which means we need separate tablegen
3632// Operands for each access size. This multiclass takes care of instantiating
3633// the correct template functions in the rest of the backend.
3634
3635multiclass offsets_simm7<string MemSize, string prefix> {
3636  // The bare signed 7-bit immediate is used in post-indexed instructions, but
3637  // because of the scaling performed a generic "simm7" operand isn't
3638  // appropriate here either.
3639  def simm7_asmoperand : AsmOperandClass {
3640    let Name = "SImm7_Scaled" # MemSize;
3641    let PredicateMethod = "isSImm7Scaled<" # MemSize # ">";
3642    let RenderMethod = "addSImm7ScaledOperands<" # MemSize # ">";
3643    let DiagnosticType = "LoadStoreSImm7_" # MemSize;
3644  }
3645
3646  def simm7 : Operand<i64> {
3647    let PrintMethod = "printSImm7ScaledOperand<" # MemSize # ">";
3648    let ParserMatchClass = !cast<AsmOperandClass>(prefix # "simm7_asmoperand");
3649  }
3650}
3651
3652defm word_  : offsets_simm7<"4", "word_">;
3653defm dword_ : offsets_simm7<"8", "dword_">;
3654defm qword_ : offsets_simm7<"16", "qword_">;
3655
3656multiclass A64I_LSPsimple<bits<2> opc, bit v, RegisterClass SomeReg,
3657                          Operand simm7, string prefix> {
3658  def _STR : A64I_LSPoffset<opc, v, 0b0, (outs),
3659                    (ins SomeReg:$Rt, SomeReg:$Rt2, GPR64xsp:$Rn, simm7:$SImm7),
3660                    "stp\t$Rt, $Rt2, [$Rn, $SImm7]", [], NoItinerary>,
3661             Sched<[WriteLd, ReadLd]> {
3662    let mayStore = 1;
3663    let DecoderMethod = "DecodeLDSTPairInstruction";
3664  }
3665  def : InstAlias<"stp $Rt, $Rt2, [$Rn]",
3666                  (!cast<Instruction>(prefix # "_STR") SomeReg:$Rt,
3667                                                SomeReg:$Rt2, GPR64xsp:$Rn, 0)>;
3668
3669  def _LDR : A64I_LSPoffset<opc, v, 0b1,
3670                            (outs SomeReg:$Rt, SomeReg:$Rt2),
3671                            (ins GPR64xsp:$Rn, simm7:$SImm7),
3672                            "ldp\t$Rt, $Rt2, [$Rn, $SImm7]", [], NoItinerary>,
3673             Sched<[WriteLd, WriteLd, ReadLd]> {
3674    let mayLoad = 1;
3675    let DecoderMethod = "DecodeLDSTPairInstruction";
3676  }
3677  def : InstAlias<"ldp $Rt, $Rt2, [$Rn]",
3678                  (!cast<Instruction>(prefix # "_LDR") SomeReg:$Rt,
3679                                                SomeReg:$Rt2, GPR64xsp:$Rn, 0)>;
3680
3681  def _PostInd_STR : A64I_LSPpostind<opc, v, 0b0,
3682                               (outs GPR64xsp:$Rn_wb),
3683                               (ins SomeReg:$Rt, SomeReg:$Rt2,
3684                                    GPR64xsp:$Rn,
3685                                    simm7:$SImm7),
3686                               "stp\t$Rt, $Rt2, [$Rn], $SImm7",
3687                               [], NoItinerary>,
3688                     Sched<[WriteSt, ReadSt, ReadSt, ReadSt]> {
3689    let mayStore = 1;
3690    let Constraints = "$Rn = $Rn_wb";
3691
3692    // Decoder only needed for unpredictability checking (FIXME).
3693    let DecoderMethod = "DecodeLDSTPairInstruction";
3694  }
3695
3696  def _PostInd_LDR : A64I_LSPpostind<opc, v, 0b1,
3697                        (outs SomeReg:$Rt, SomeReg:$Rt2, GPR64xsp:$Rn_wb),
3698                        (ins GPR64xsp:$Rn, simm7:$SImm7),
3699                        "ldp\t$Rt, $Rt2, [$Rn], $SImm7",
3700                        [], NoItinerary>,
3701                     Sched<[WriteLd, WriteLd, WriteLd, ReadLd]> {
3702    let mayLoad = 1;
3703    let Constraints = "$Rn = $Rn_wb";
3704    let DecoderMethod = "DecodeLDSTPairInstruction";
3705  }
3706
3707  def _PreInd_STR : A64I_LSPpreind<opc, v, 0b0, (outs GPR64xsp:$Rn_wb),
3708                       (ins SomeReg:$Rt, SomeReg:$Rt2, GPR64xsp:$Rn, simm7:$SImm7),
3709                       "stp\t$Rt, $Rt2, [$Rn, $SImm7]!",
3710                       [], NoItinerary>,
3711                    Sched<[WriteSt, ReadSt, ReadSt, ReadSt]> {
3712    let mayStore = 1;
3713    let Constraints = "$Rn = $Rn_wb";
3714    let DecoderMethod = "DecodeLDSTPairInstruction";
3715  }
3716
3717  def _PreInd_LDR : A64I_LSPpreind<opc, v, 0b1,
3718                              (outs SomeReg:$Rt, SomeReg:$Rt2, GPR64xsp:$Rn_wb),
3719                              (ins GPR64xsp:$Rn, simm7:$SImm7),
3720                              "ldp\t$Rt, $Rt2, [$Rn, $SImm7]!",
3721                              [], NoItinerary>,
3722                    Sched<[WriteLd, WriteLd, WriteLd, ReadLd]> {
3723    let mayLoad = 1;
3724    let Constraints = "$Rn = $Rn_wb";
3725    let DecoderMethod = "DecodeLDSTPairInstruction";
3726  }
3727
3728  def _NonTemp_STR : A64I_LSPnontemp<opc, v, 0b0, (outs),
3729                       (ins SomeReg:$Rt, SomeReg:$Rt2, GPR64xsp:$Rn, simm7:$SImm7),
3730                       "stnp\t$Rt, $Rt2, [$Rn, $SImm7]", [], NoItinerary>,
3731                     Sched<[WriteSt, ReadSt, ReadSt, ReadSt]> {
3732    let mayStore = 1;
3733    let DecoderMethod = "DecodeLDSTPairInstruction";
3734  }
3735  def : InstAlias<"stnp $Rt, $Rt2, [$Rn]",
3736                  (!cast<Instruction>(prefix # "_NonTemp_STR") SomeReg:$Rt,
3737                                                SomeReg:$Rt2, GPR64xsp:$Rn, 0)>;
3738
3739  def _NonTemp_LDR : A64I_LSPnontemp<opc, v, 0b1,
3740                            (outs SomeReg:$Rt, SomeReg:$Rt2),
3741                            (ins GPR64xsp:$Rn, simm7:$SImm7),
3742                            "ldnp\t$Rt, $Rt2, [$Rn, $SImm7]", [], NoItinerary>,
3743                     Sched<[WriteLd, WriteLd, ReadLd]> {
3744    let mayLoad = 1;
3745    let DecoderMethod = "DecodeLDSTPairInstruction";
3746  }
3747  def : InstAlias<"ldnp $Rt, $Rt2, [$Rn]",
3748                  (!cast<Instruction>(prefix # "_NonTemp_LDR") SomeReg:$Rt,
3749                                                SomeReg:$Rt2, GPR64xsp:$Rn, 0)>;
3750
3751}
3752
3753
3754defm LSPair32 : A64I_LSPsimple<0b00, 0b0, GPR32, word_simm7, "LSPair32">;
3755defm LSPair64 : A64I_LSPsimple<0b10, 0b0, GPR64, dword_simm7, "LSPair64">;
3756
3757let Predicates = [HasFPARMv8] in {
3758defm LSFPPair32 : A64I_LSPsimple<0b00, 0b1, FPR32, word_simm7, "LSFPPair32">;
3759defm LSFPPair64 : A64I_LSPsimple<0b01, 0b1, FPR64,  dword_simm7, "LSFPPair64">;
3760defm LSFPPair128 : A64I_LSPsimple<0b10, 0b1, FPR128, qword_simm7,
3761                                  "LSFPPair128">;
3762}
3763
3764
3765def LDPSWx : A64I_LSPoffset<0b01, 0b0, 0b1,
3766                           (outs GPR64:$Rt, GPR64:$Rt2),
3767                           (ins GPR64xsp:$Rn, word_simm7:$SImm7),
3768                           "ldpsw\t$Rt, $Rt2, [$Rn, $SImm7]", [], NoItinerary>,
3769             Sched<[WriteLd, WriteLd, ReadLd]> {
3770  let mayLoad = 1;
3771  let DecoderMethod = "DecodeLDSTPairInstruction";
3772}
3773def : InstAlias<"ldpsw $Rt, $Rt2, [$Rn]",
3774                (LDPSWx GPR64:$Rt, GPR64:$Rt2, GPR64xsp:$Rn, 0)>;
3775
3776def LDPSWx_PostInd : A64I_LSPpostind<0b01, 0b0, 0b1,
3777                                  (outs GPR64:$Rt, GPR64:$Rt2, GPR64:$Rn_wb),
3778                                  (ins GPR64xsp:$Rn, word_simm7:$SImm7),
3779                                  "ldpsw\t$Rt, $Rt2, [$Rn], $SImm7",
3780                                  [], NoItinerary>,
3781                     Sched<[WriteLd, WriteLd, WriteLd, ReadLd]> {
3782  let mayLoad = 1;
3783  let Constraints = "$Rn = $Rn_wb";
3784  let DecoderMethod = "DecodeLDSTPairInstruction";
3785}
3786
3787def LDPSWx_PreInd : A64I_LSPpreind<0b01, 0b0, 0b1,
3788                                   (outs GPR64:$Rt, GPR64:$Rt2, GPR64:$Rn_wb),
3789                                   (ins GPR64xsp:$Rn, word_simm7:$SImm7),
3790                                   "ldpsw\t$Rt, $Rt2, [$Rn, $SImm7]!",
3791                                   [], NoItinerary>,
3792                    Sched<[WriteLd, WriteLd, WriteLd, ReadLd]> {
3793  let mayLoad = 1;
3794  let Constraints = "$Rn = $Rn_wb";
3795  let DecoderMethod = "DecodeLDSTPairInstruction";
3796}
3797
3798//===----------------------------------------------------------------------===//
3799// Logical (immediate) instructions
3800//===----------------------------------------------------------------------===//
3801// Contains: AND, ORR, EOR, ANDS, + aliases TST, MOV
3802
3803multiclass logical_imm_operands<string prefix, string note,
3804                                int size, ValueType VT> {
3805  def _asmoperand : AsmOperandClass {
3806    let Name = "LogicalImm" # note # size;
3807    let PredicateMethod = "isLogicalImm" # note # "<" # size # ">";
3808    let RenderMethod = "addLogicalImmOperands<" # size # ">";
3809    let DiagnosticType = "LogicalSecondSource";
3810  }
3811
3812  def _operand
3813        : Operand<VT>, ComplexPattern<VT, 1, "SelectLogicalImm", [imm]> {
3814    let ParserMatchClass = !cast<AsmOperandClass>(prefix # "_asmoperand");
3815    let PrintMethod = "printLogicalImmOperand<" # size # ">";
3816    let DecoderMethod = "DecodeLogicalImmOperand<" # size # ">";
3817  }
3818}
3819
3820defm logical_imm32 : logical_imm_operands<"logical_imm32", "", 32, i32>;
3821defm logical_imm64 : logical_imm_operands<"logical_imm64", "", 64, i64>;
3822
3823// The mov versions only differ in assembly parsing, where they
3824// exclude values representable with either MOVZ or MOVN.
3825defm logical_imm32_mov
3826  : logical_imm_operands<"logical_imm32_mov", "MOV", 32, i32>;
3827defm logical_imm64_mov
3828  : logical_imm_operands<"logical_imm64_mov", "MOV", 64, i64>;
3829
3830
3831multiclass A64I_logimmSizes<bits<2> opc, string asmop, SDNode opnode> {
3832  def wwi : A64I_logicalimm<0b0, opc, (outs GPR32wsp:$Rd),
3833                         (ins GPR32:$Rn, logical_imm32_operand:$Imm),
3834                         !strconcat(asmop, "\t$Rd, $Rn, $Imm"),
3835                         [(set i32:$Rd,
3836                               (opnode i32:$Rn, logical_imm32_operand:$Imm))],
3837                         NoItinerary>,
3838            Sched<[WriteALU, ReadALU]>;
3839
3840  def xxi : A64I_logicalimm<0b1, opc, (outs GPR64xsp:$Rd),
3841                         (ins GPR64:$Rn, logical_imm64_operand:$Imm),
3842                         !strconcat(asmop, "\t$Rd, $Rn, $Imm"),
3843                         [(set i64:$Rd,
3844                               (opnode i64:$Rn, logical_imm64_operand:$Imm))],
3845                         NoItinerary>,
3846            Sched<[WriteALU, ReadALU]>;
3847}
3848
3849defm AND : A64I_logimmSizes<0b00, "and", and>;
3850defm ORR : A64I_logimmSizes<0b01, "orr", or>;
3851defm EOR : A64I_logimmSizes<0b10, "eor", xor>;
3852
3853let Defs = [NZCV] in {
3854  def ANDSwwi : A64I_logicalimm<0b0, 0b11, (outs GPR32:$Rd),
3855                                (ins GPR32:$Rn, logical_imm32_operand:$Imm),
3856                                "ands\t$Rd, $Rn, $Imm",
3857                                [], NoItinerary>,
3858                Sched<[WriteALU, ReadALU]>;
3859
3860  def ANDSxxi : A64I_logicalimm<0b1, 0b11, (outs GPR64:$Rd),
3861                                (ins GPR64:$Rn, logical_imm64_operand:$Imm),
3862                                "ands\t$Rd, $Rn, $Imm",
3863                                [], NoItinerary>,
3864                Sched<[WriteALU, ReadALU]>;
3865}
3866
3867
3868def : InstAlias<"tst $Rn, $Imm",
3869                (ANDSwwi WZR, GPR32:$Rn, logical_imm32_operand:$Imm)>;
3870def : InstAlias<"tst $Rn, $Imm",
3871                (ANDSxxi XZR, GPR64:$Rn, logical_imm64_operand:$Imm)>;
3872def : InstAlias<"mov $Rd, $Imm",
3873                (ORRwwi GPR32wsp:$Rd, WZR, logical_imm32_mov_operand:$Imm)>;
3874def : InstAlias<"mov $Rd, $Imm",
3875                (ORRxxi GPR64xsp:$Rd, XZR, logical_imm64_mov_operand:$Imm)>;
3876
3877//===----------------------------------------------------------------------===//
3878// Logical (shifted register) instructions
3879//===----------------------------------------------------------------------===//
3880// Contains: AND, BIC, ORR, ORN, EOR, EON, ANDS, BICS + aliases TST, MVN, MOV
3881
3882// Operand for optimizing (icmp (and LHS, RHS), 0, SomeCode). In theory "ANDS"
3883// behaves differently for unsigned comparisons, so we defensively only allow
3884// signed or n/a as the operand. In practice "unsigned greater than 0" is "not
3885// equal to 0" and LLVM gives us this.
3886def signed_cond : PatLeaf<(cond), [{
3887  return !isUnsignedIntSetCC(N->get());
3888}]>;
3889
3890
3891// These instructions share their "shift" operands with add/sub (shifted
3892// register instructions). They are defined there.
3893
3894// N.b. the commutable parameter is just !N. It will be first against the wall
3895// when the revolution comes.
3896multiclass logical_shifts<string prefix, bit sf, bits<2> opc,
3897                          bit N, bit commutable,
3898                          string asmop, SDPatternOperator opfrag, ValueType ty,
3899                          RegisterClass GPR, list<Register> defs> {
3900  let isCommutable = commutable, Defs = defs in {
3901  def _lsl : A64I_logicalshift<sf, opc, 0b00, N,
3902                       (outs GPR:$Rd),
3903                       (ins GPR:$Rn, GPR:$Rm,
3904                            !cast<Operand>("lsl_operand_" # ty):$Imm6),
3905                       !strconcat(asmop, "\t$Rd, $Rn, $Rm, $Imm6"),
3906                       [(set ty:$Rd, (opfrag ty:$Rn, (shl ty:$Rm,
3907                            !cast<Operand>("lsl_operand_" # ty):$Imm6))
3908                       )],
3909                       NoItinerary>,
3910             Sched<[WriteALU, ReadALU, ReadALU]>;
3911
3912  def _lsr : A64I_logicalshift<sf, opc, 0b01, N,
3913                       (outs GPR:$Rd),
3914                       (ins GPR:$Rn, GPR:$Rm,
3915                            !cast<Operand>("lsr_operand_" # ty):$Imm6),
3916                       !strconcat(asmop, "\t$Rd, $Rn, $Rm, $Imm6"),
3917                       [(set ty:$Rd, (opfrag ty:$Rn, (srl ty:$Rm,
3918                            !cast<Operand>("lsr_operand_" # ty):$Imm6))
3919                       )],
3920                       NoItinerary>,
3921             Sched<[WriteALU, ReadALU, ReadALU]>;
3922
3923  def _asr : A64I_logicalshift<sf, opc, 0b10, N,
3924                       (outs GPR:$Rd),
3925                       (ins GPR:$Rn, GPR:$Rm,
3926                            !cast<Operand>("asr_operand_" # ty):$Imm6),
3927                       !strconcat(asmop, "\t$Rd, $Rn, $Rm, $Imm6"),
3928                       [(set ty:$Rd, (opfrag ty:$Rn, (sra ty:$Rm,
3929                            !cast<Operand>("asr_operand_" # ty):$Imm6))
3930                       )],
3931                       NoItinerary>,
3932             Sched<[WriteALU, ReadALU, ReadALU]>;
3933
3934  def _ror : A64I_logicalshift<sf, opc, 0b11, N,
3935                       (outs GPR:$Rd),
3936                       (ins GPR:$Rn, GPR:$Rm,
3937                            !cast<Operand>("ror_operand_" # ty):$Imm6),
3938                       !strconcat(asmop, "\t$Rd, $Rn, $Rm, $Imm6"),
3939                       [(set ty:$Rd, (opfrag ty:$Rn, (rotr ty:$Rm,
3940                            !cast<Operand>("ror_operand_" # ty):$Imm6))
3941                       )],
3942                       NoItinerary>,
3943             Sched<[WriteALU, ReadALU, ReadALU]>;
3944  }
3945
3946  def _noshift
3947      : InstAlias<!strconcat(asmop, " $Rd, $Rn, $Rm"),
3948                 (!cast<Instruction>(prefix # "_lsl") GPR:$Rd, GPR:$Rn,
3949                                                      GPR:$Rm, 0)>;
3950
3951  def : Pat<(opfrag ty:$Rn, ty:$Rm),
3952            (!cast<Instruction>(prefix # "_lsl") $Rn, $Rm, 0)>;
3953}
3954
3955multiclass logical_sizes<string prefix, bits<2> opc, bit N, bit commutable,
3956                         string asmop, SDPatternOperator opfrag,
3957                         list<Register> defs> {
3958  defm xxx : logical_shifts<prefix # "xxx", 0b1, opc, N,
3959                            commutable, asmop, opfrag, i64, GPR64, defs>;
3960  defm www : logical_shifts<prefix # "www", 0b0, opc, N,
3961                            commutable, asmop, opfrag, i32, GPR32, defs>;
3962}
3963
3964
3965defm AND : logical_sizes<"AND", 0b00, 0b0, 0b1, "and", and, []>;
3966defm ORR : logical_sizes<"ORR", 0b01, 0b0, 0b1, "orr", or, []>;
3967defm EOR : logical_sizes<"EOR", 0b10, 0b0, 0b1, "eor", xor, []>;
3968defm ANDS : logical_sizes<"ANDS", 0b11, 0b0, 0b1, "ands",
3969             PatFrag<(ops node:$lhs, node:$rhs), (and node:$lhs, node:$rhs),
3970                     [{ (void)N; return false; }]>,
3971             [NZCV]>;
3972
3973defm BIC : logical_sizes<"BIC", 0b00, 0b1, 0b0, "bic",
3974                         PatFrag<(ops node:$lhs, node:$rhs),
3975                                 (and node:$lhs, (not node:$rhs))>, []>;
3976defm ORN : logical_sizes<"ORN", 0b01, 0b1, 0b0, "orn",
3977                         PatFrag<(ops node:$lhs, node:$rhs),
3978                                 (or node:$lhs, (not node:$rhs))>, []>;
3979defm EON : logical_sizes<"EON", 0b10, 0b1, 0b0, "eon",
3980                         PatFrag<(ops node:$lhs, node:$rhs),
3981                                 (xor node:$lhs, (not node:$rhs))>, []>;
3982defm BICS : logical_sizes<"BICS", 0b11, 0b1, 0b0, "bics",
3983                          PatFrag<(ops node:$lhs, node:$rhs),
3984                                  (and node:$lhs, (not node:$rhs)),
3985                                  [{ (void)N; return false; }]>,
3986                          [NZCV]>;
3987
3988multiclass tst_shifts<string prefix, bit sf, ValueType ty, RegisterClass GPR> {
3989  let isCommutable = 1, Rd = 0b11111, Defs = [NZCV] in {
3990  def _lsl : A64I_logicalshift<sf, 0b11, 0b00, 0b0,
3991                       (outs),
3992                       (ins GPR:$Rn, GPR:$Rm,
3993                            !cast<Operand>("lsl_operand_" # ty):$Imm6),
3994                       "tst\t$Rn, $Rm, $Imm6",
3995                       [(set NZCV, (A64setcc (and ty:$Rn, (shl ty:$Rm,
3996                           !cast<Operand>("lsl_operand_" # ty):$Imm6)),
3997                                          0, signed_cond))],
3998                       NoItinerary>,
3999             Sched<[WriteALU, ReadALU, ReadALU]>;
4000
4001
4002  def _lsr : A64I_logicalshift<sf, 0b11, 0b01, 0b0,
4003                       (outs),
4004                       (ins GPR:$Rn, GPR:$Rm,
4005                            !cast<Operand>("lsr_operand_" # ty):$Imm6),
4006                       "tst\t$Rn, $Rm, $Imm6",
4007                       [(set NZCV, (A64setcc (and ty:$Rn, (srl ty:$Rm,
4008                           !cast<Operand>("lsr_operand_" # ty):$Imm6)),
4009                                          0, signed_cond))],
4010                       NoItinerary>,
4011             Sched<[WriteALU, ReadALU, ReadALU]>;
4012
4013  def _asr : A64I_logicalshift<sf, 0b11, 0b10, 0b0,
4014                       (outs),
4015                       (ins GPR:$Rn, GPR:$Rm,
4016                            !cast<Operand>("asr_operand_" # ty):$Imm6),
4017                       "tst\t$Rn, $Rm, $Imm6",
4018                       [(set NZCV, (A64setcc (and ty:$Rn, (sra ty:$Rm,
4019                           !cast<Operand>("asr_operand_" # ty):$Imm6)),
4020                                          0, signed_cond))],
4021                       NoItinerary>,
4022             Sched<[WriteALU, ReadALU, ReadALU]>;
4023
4024  def _ror : A64I_logicalshift<sf, 0b11, 0b11, 0b0,
4025                       (outs),
4026                       (ins GPR:$Rn, GPR:$Rm,
4027                            !cast<Operand>("ror_operand_" # ty):$Imm6),
4028                       "tst\t$Rn, $Rm, $Imm6",
4029                       [(set NZCV, (A64setcc (and ty:$Rn, (rotr ty:$Rm,
4030                           !cast<Operand>("ror_operand_" # ty):$Imm6)),
4031                                          0, signed_cond))],
4032                       NoItinerary>,
4033             Sched<[WriteALU, ReadALU, ReadALU]>;
4034  }
4035
4036  def _noshift : InstAlias<"tst $Rn, $Rm",
4037                     (!cast<Instruction>(prefix # "_lsl") GPR:$Rn, GPR:$Rm, 0)>;
4038
4039  def : Pat<(A64setcc (and ty:$Rn, ty:$Rm), 0, signed_cond),
4040            (!cast<Instruction>(prefix # "_lsl") $Rn, $Rm, 0)>;
4041}
4042
4043defm TSTxx : tst_shifts<"TSTxx", 0b1, i64, GPR64>;
4044defm TSTww : tst_shifts<"TSTww", 0b0, i32, GPR32>;
4045
4046
4047multiclass mvn_shifts<string prefix, bit sf, ValueType ty, RegisterClass GPR> {
4048  let isCommutable = 0, Rn = 0b11111 in {
4049  def _lsl : A64I_logicalshift<sf, 0b01, 0b00, 0b1,
4050                       (outs GPR:$Rd),
4051                       (ins GPR:$Rm,
4052                            !cast<Operand>("lsl_operand_" # ty):$Imm6),
4053                       "mvn\t$Rd, $Rm, $Imm6",
4054                       [(set ty:$Rd, (not (shl ty:$Rm,
4055                         !cast<Operand>("lsl_operand_" # ty):$Imm6)))],
4056                       NoItinerary>,
4057             Sched<[WriteALU, ReadALU, ReadALU]>;
4058
4059
4060  def _lsr : A64I_logicalshift<sf, 0b01, 0b01, 0b1,
4061                       (outs GPR:$Rd),
4062                       (ins GPR:$Rm,
4063                            !cast<Operand>("lsr_operand_" # ty):$Imm6),
4064                       "mvn\t$Rd, $Rm, $Imm6",
4065                       [(set ty:$Rd, (not (srl ty:$Rm,
4066                         !cast<Operand>("lsr_operand_" # ty):$Imm6)))],
4067                       NoItinerary>,
4068             Sched<[WriteALU, ReadALU, ReadALU]>;
4069
4070  def _asr : A64I_logicalshift<sf, 0b01, 0b10, 0b1,
4071                       (outs GPR:$Rd),
4072                       (ins GPR:$Rm,
4073                            !cast<Operand>("asr_operand_" # ty):$Imm6),
4074                       "mvn\t$Rd, $Rm, $Imm6",
4075                       [(set ty:$Rd, (not (sra ty:$Rm,
4076                         !cast<Operand>("asr_operand_" # ty):$Imm6)))],
4077                       NoItinerary>,
4078             Sched<[WriteALU, ReadALU, ReadALU]>;
4079
4080  def _ror : A64I_logicalshift<sf, 0b01, 0b11, 0b1,
4081                       (outs GPR:$Rd),
4082                       (ins GPR:$Rm,
4083                            !cast<Operand>("ror_operand_" # ty):$Imm6),
4084                       "mvn\t$Rd, $Rm, $Imm6",
4085                       [(set ty:$Rd, (not (rotr ty:$Rm,
4086                         !cast<Operand>("lsl_operand_" # ty):$Imm6)))],
4087                       NoItinerary>,
4088             Sched<[WriteALU, ReadALU, ReadALU]>;
4089  }
4090
4091  def _noshift : InstAlias<"mvn $Rn, $Rm",
4092                     (!cast<Instruction>(prefix # "_lsl") GPR:$Rn, GPR:$Rm, 0)>;
4093
4094  def : Pat<(not ty:$Rm),
4095            (!cast<Instruction>(prefix # "_lsl") $Rm, 0)>;
4096}
4097
4098defm MVNxx : mvn_shifts<"MVNxx", 0b1, i64, GPR64>;
4099defm MVNww : mvn_shifts<"MVNww", 0b0, i32, GPR32>;
4100
4101def MOVxx :InstAlias<"mov $Rd, $Rm", (ORRxxx_lsl GPR64:$Rd, XZR, GPR64:$Rm, 0)>;
4102def MOVww :InstAlias<"mov $Rd, $Rm", (ORRwww_lsl GPR32:$Rd, WZR, GPR32:$Rm, 0)>;
4103
4104//===----------------------------------------------------------------------===//
4105// Move wide (immediate) instructions
4106//===----------------------------------------------------------------------===//
4107// Contains: MOVN, MOVZ, MOVK + MOV aliases
4108
4109// A wide variety of different relocations are needed for variants of these
4110// instructions, so it turns out that we need a different operand for all of
4111// them.
4112multiclass movw_operands<string prefix, string instname, int width> {
4113  def _imm_asmoperand : AsmOperandClass {
4114    let Name = instname # width # "Shifted" # shift;
4115    let PredicateMethod = "is" # instname # width # "Imm";
4116    let RenderMethod = "addMoveWideImmOperands";
4117    let ParserMethod = "ParseImmWithLSLOperand";
4118    let DiagnosticType = "MOVWUImm16";
4119  }
4120
4121  def _imm : Operand<i64> {
4122    let ParserMatchClass = !cast<AsmOperandClass>(prefix # "_imm_asmoperand");
4123    let PrintMethod = "printMoveWideImmOperand";
4124    let EncoderMethod = "getMoveWideImmOpValue";
4125    let DecoderMethod = "DecodeMoveWideImmOperand<" # width # ">";
4126
4127    let MIOperandInfo = (ops uimm16:$UImm16, imm:$Shift);
4128  }
4129}
4130
4131defm movn32 : movw_operands<"movn32", "MOVN", 32>;
4132defm movn64 : movw_operands<"movn64", "MOVN", 64>;
4133defm movz32 : movw_operands<"movz32", "MOVZ", 32>;
4134defm movz64 : movw_operands<"movz64", "MOVZ", 64>;
4135defm movk32 : movw_operands<"movk32", "MOVK", 32>;
4136defm movk64 : movw_operands<"movk64", "MOVK", 64>;
4137
4138multiclass A64I_movwSizes<bits<2> opc, string asmop, dag ins32bit,
4139                          dag ins64bit> {
4140
4141  def wii : A64I_movw<0b0, opc, (outs GPR32:$Rd), ins32bit,
4142                      !strconcat(asmop, "\t$Rd, $FullImm"),
4143                      [], NoItinerary>,
4144            Sched<[WriteALU]> {
4145    bits<18> FullImm;
4146    let UImm16 = FullImm{15-0};
4147    let Shift = FullImm{17-16};
4148  }
4149
4150  def xii : A64I_movw<0b1, opc, (outs GPR64:$Rd), ins64bit,
4151                      !strconcat(asmop, "\t$Rd, $FullImm"),
4152                      [], NoItinerary>,
4153            Sched<[WriteALU]> {
4154    bits<18> FullImm;
4155    let UImm16 = FullImm{15-0};
4156    let Shift = FullImm{17-16};
4157  }
4158}
4159
4160let isMoveImm = 1, isReMaterializable = 1,
4161    isAsCheapAsAMove = 1, hasSideEffects = 0 in {
4162  defm MOVN : A64I_movwSizes<0b00, "movn",
4163                             (ins movn32_imm:$FullImm),
4164                             (ins movn64_imm:$FullImm)>;
4165
4166  // Some relocations are able to convert between a MOVZ and a MOVN. If these
4167  // are applied the instruction must be emitted with the corresponding bits as
4168  // 0, which means a MOVZ needs to override that bit from the default.
4169  let PostEncoderMethod = "fixMOVZ" in
4170  defm MOVZ : A64I_movwSizes<0b10, "movz",
4171                             (ins movz32_imm:$FullImm),
4172                             (ins movz64_imm:$FullImm)>;
4173}
4174
4175let Constraints = "$src = $Rd",
4176    SchedRW = [WriteALU, ReadALU] in
4177defm MOVK : A64I_movwSizes<0b11, "movk",
4178                           (ins GPR32:$src, movk32_imm:$FullImm),
4179                           (ins GPR64:$src, movk64_imm:$FullImm)>;
4180
4181
4182// And now the "MOV" aliases. These also need their own operands because what
4183// they accept is completely different to what the base instructions accept.
4184multiclass movalias_operand<string prefix, string basename,
4185                            string immpredicate, int width> {
4186  def _asmoperand : AsmOperandClass {
4187    let Name = basename # width # "MovAlias";
4188    let PredicateMethod
4189          = "isMoveWideMovAlias<" # width # ", A64Imms::" # immpredicate # ">";
4190    let RenderMethod
4191      = "addMoveWideMovAliasOperands<" # width # ", "
4192                                       # "A64Imms::" # immpredicate # ">";
4193  }
4194
4195  def _movimm : Operand<i64> {
4196    let ParserMatchClass = !cast<AsmOperandClass>(prefix # "_asmoperand");
4197
4198    let MIOperandInfo = (ops uimm16:$UImm16, imm:$Shift);
4199  }
4200}
4201
4202defm movz32 : movalias_operand<"movz32", "MOVZ", "isMOVZImm", 32>;
4203defm movz64 : movalias_operand<"movz64", "MOVZ", "isMOVZImm", 64>;
4204defm movn32 : movalias_operand<"movn32", "MOVN", "isOnlyMOVNImm", 32>;
4205defm movn64 : movalias_operand<"movn64", "MOVN", "isOnlyMOVNImm", 64>;
4206
4207// FIXME: these are officially canonical aliases, but TableGen is too limited to
4208// print them at the moment. I believe in this case an "AliasPredicate" method
4209// will need to be implemented. to allow it, as well as the more generally
4210// useful handling of non-register, non-constant operands.
4211class movalias<Instruction INST, RegisterClass GPR, Operand operand>
4212  : InstAlias<"mov $Rd, $FullImm", (INST GPR:$Rd, operand:$FullImm)>;
4213
4214def : movalias<MOVZwii, GPR32, movz32_movimm>;
4215def : movalias<MOVZxii, GPR64, movz64_movimm>;
4216def : movalias<MOVNwii, GPR32, movn32_movimm>;
4217def : movalias<MOVNxii, GPR64, movn64_movimm>;
4218
4219def movw_addressref_g0 : ComplexPattern<i64, 2, "SelectMOVWAddressRef<0>">;
4220def movw_addressref_g1 : ComplexPattern<i64, 2, "SelectMOVWAddressRef<1>">;
4221def movw_addressref_g2 : ComplexPattern<i64, 2, "SelectMOVWAddressRef<2>">;
4222def movw_addressref_g3 : ComplexPattern<i64, 2, "SelectMOVWAddressRef<3>">;
4223
4224def : Pat<(A64WrapperLarge movw_addressref_g3:$G3, movw_addressref_g2:$G2,
4225                           movw_addressref_g1:$G1, movw_addressref_g0:$G0),
4226          (MOVKxii (MOVKxii (MOVKxii (MOVZxii movw_addressref_g3:$G3),
4227                                     movw_addressref_g2:$G2),
4228                            movw_addressref_g1:$G1),
4229                   movw_addressref_g0:$G0)>;
4230
4231//===----------------------------------------------------------------------===//
4232// PC-relative addressing instructions
4233//===----------------------------------------------------------------------===//
4234// Contains: ADR, ADRP
4235
4236def adr_label : Operand<i64> {
4237  let EncoderMethod = "getLabelOpValue<AArch64::fixup_a64_adr_prel>";
4238
4239  // This label is a 21-bit offset from PC, unscaled
4240  let PrintMethod = "printLabelOperand<21, 1>";
4241  let ParserMatchClass = label_asmoperand<21, 1>;
4242  let OperandType = "OPERAND_PCREL";
4243}
4244
4245def adrp_label_asmoperand : AsmOperandClass {
4246  let Name = "AdrpLabel";
4247  let RenderMethod = "addLabelOperands<21, 4096>";
4248  let DiagnosticType = "Label";
4249}
4250
4251def adrp_label : Operand<i64> {
4252  let EncoderMethod = "getAdrpLabelOpValue";
4253
4254  // This label is a 21-bit offset from PC, scaled by the page-size: 4096.
4255  let PrintMethod = "printLabelOperand<21, 4096>";
4256  let ParserMatchClass = adrp_label_asmoperand;
4257  let OperandType = "OPERAND_PCREL";
4258}
4259
4260let hasSideEffects = 0 in {
4261  def ADRxi : A64I_PCADR<0b0, (outs GPR64:$Rd), (ins adr_label:$Label),
4262                         "adr\t$Rd, $Label", [], NoItinerary>,
4263              Sched<[WriteALUs]>;
4264
4265  def ADRPxi : A64I_PCADR<0b1, (outs GPR64:$Rd), (ins adrp_label:$Label),
4266                          "adrp\t$Rd, $Label", [], NoItinerary>,
4267               Sched<[WriteALUs]>;
4268}
4269
4270//===----------------------------------------------------------------------===//
4271// System instructions
4272//===----------------------------------------------------------------------===//
4273// Contains: HINT, CLREX, DSB, DMB, ISB, MSR, SYS, SYSL, MRS
4274//    + aliases IC, DC, AT, TLBI, NOP, YIELD, WFE, WFI, SEV, SEVL
4275
4276// Op1 and Op2 fields are sometimes simple 3-bit unsigned immediate values.
4277def uimm3_asmoperand : AsmOperandClass {
4278  let Name = "UImm3";
4279  let PredicateMethod = "isUImm<3>";
4280  let RenderMethod = "addImmOperands";
4281  let DiagnosticType = "UImm3";
4282}
4283
4284def uimm3 : Operand<i32> {
4285  let ParserMatchClass = uimm3_asmoperand;
4286}
4287
4288// The HINT alias can accept a simple unsigned 7-bit immediate.
4289def uimm7_asmoperand : AsmOperandClass {
4290  let Name = "UImm7";
4291  let PredicateMethod = "isUImm<7>";
4292  let RenderMethod = "addImmOperands";
4293  let DiagnosticType = "UImm7";
4294}
4295
4296def uimm7 : Operand<i32> {
4297  let ParserMatchClass = uimm7_asmoperand;
4298}
4299
4300// Multiclass namedimm is defined with the prefetch operands. Most of these fit
4301// into the NamedImmMapper scheme well: they either accept a named operand or
4302// any immediate under a particular value (which may be 0, implying no immediate
4303// is allowed).
4304defm dbarrier : namedimm<"dbarrier", "A64DB::DBarrierMapper">;
4305defm isb : namedimm<"isb", "A64ISB::ISBMapper">;
4306defm ic : namedimm<"ic", "A64IC::ICMapper">;
4307defm dc : namedimm<"dc", "A64DC::DCMapper">;
4308defm at : namedimm<"at", "A64AT::ATMapper">;
4309defm tlbi : namedimm<"tlbi", "A64TLBI::TLBIMapper">;
4310
4311// However, MRS and MSR are more complicated for a few reasons:
4312//   * There are ~1000 generic names S3_<op1>_<CRn>_<CRm>_<Op2> which have an
4313//     implementation-defined effect
4314//   * Most registers are shared, but some are read-only or write-only.
4315//   * There is a variant of MSR which accepts the same register name (SPSel),
4316//     but which would have a different encoding.
4317
4318// In principle these could be resolved in with more complicated subclasses of
4319// NamedImmMapper, however that imposes an overhead on other "named
4320// immediates". Both in concrete terms with virtual tables and in unnecessary
4321// abstraction.
4322
4323// The solution adopted here is to take the MRS/MSR Mappers out of the usual
4324// hierarchy (they're not derived from NamedImmMapper) and to add logic for
4325// their special situation.
4326def mrs_asmoperand : AsmOperandClass {
4327  let Name = "MRS";
4328  let ParserMethod = "ParseSysRegOperand";
4329  let DiagnosticType = "MRS";
4330}
4331
4332def mrs_op : Operand<i32> {
4333  let ParserMatchClass = mrs_asmoperand;
4334  let PrintMethod = "printMRSOperand";
4335  let DecoderMethod = "DecodeMRSOperand";
4336}
4337
4338def msr_asmoperand : AsmOperandClass {
4339  let Name = "MSRWithReg";
4340
4341  // Note that SPSel is valid for both this and the pstate operands, but with
4342  // different immediate encodings. This is why these operands provide a string
4343  // AArch64Operand rather than an immediate. The overlap is small enough that
4344  // it could be resolved with hackery now, but who can say in future?
4345  let ParserMethod = "ParseSysRegOperand";
4346  let DiagnosticType = "MSR";
4347}
4348
4349def msr_op : Operand<i32> {
4350  let ParserMatchClass = msr_asmoperand;
4351  let PrintMethod = "printMSROperand";
4352  let DecoderMethod = "DecodeMSROperand";
4353}
4354
4355def pstate_asmoperand : AsmOperandClass {
4356  let Name = "MSRPState";
4357  // See comment above about parser.
4358  let ParserMethod = "ParseSysRegOperand";
4359  let DiagnosticType = "MSR";
4360}
4361
4362def pstate_op : Operand<i32> {
4363  let ParserMatchClass = pstate_asmoperand;
4364  let PrintMethod = "printNamedImmOperand<A64PState::PStateMapper>";
4365  let DecoderMethod = "DecodeNamedImmOperand<A64PState::PStateMapper>";
4366}
4367
4368// When <CRn> is specified, an assembler should accept something like "C4", not
4369// the usual "#4" immediate.
4370def CRx_asmoperand : AsmOperandClass {
4371  let Name = "CRx";
4372  let PredicateMethod = "isUImm<4>";
4373  let RenderMethod = "addImmOperands";
4374  let ParserMethod = "ParseCRxOperand";
4375  // Diagnostics are handled in all cases by ParseCRxOperand.
4376}
4377
4378def CRx : Operand<i32> {
4379  let ParserMatchClass = CRx_asmoperand;
4380  let PrintMethod = "printCRxOperand";
4381}
4382
4383
4384// Finally, we can start defining the instructions.
4385
4386// HINT is straightforward, with a few aliases.
4387def HINTi : A64I_system<0b0, (outs), (ins uimm7:$UImm7), "hint\t$UImm7",
4388                        [], NoItinerary> {
4389  bits<7> UImm7;
4390  let CRm = UImm7{6-3};
4391  let Op2 = UImm7{2-0};
4392
4393  let Op0 = 0b00;
4394  let Op1 = 0b011;
4395  let CRn = 0b0010;
4396  let Rt = 0b11111;
4397}
4398
4399def : InstAlias<"nop", (HINTi 0)>;
4400def : InstAlias<"yield", (HINTi 1)>;
4401def : InstAlias<"wfe", (HINTi 2)>;
4402def : InstAlias<"wfi", (HINTi 3)>;
4403def : InstAlias<"sev", (HINTi 4)>;
4404def : InstAlias<"sevl", (HINTi 5)>;
4405
4406// Quite a few instructions then follow a similar pattern of fixing common
4407// fields in the bitpattern, we'll define a helper-class for them.
4408class simple_sys<bits<2> op0, bits<3> op1, bits<4> crn, bits<3> op2,
4409                 Operand operand, string asmop>
4410  : A64I_system<0b0, (outs), (ins operand:$CRm), !strconcat(asmop, "\t$CRm"),
4411                [], NoItinerary> {
4412  let Op0 = op0;
4413  let Op1 = op1;
4414  let CRn = crn;
4415  let Op2 = op2;
4416  let Rt = 0b11111;
4417}
4418
4419
4420def CLREXi : simple_sys<0b00, 0b011, 0b0011, 0b010, uimm4, "clrex">;
4421def DSBi : simple_sys<0b00, 0b011, 0b0011, 0b100, dbarrier_op, "dsb">;
4422def DMBi : simple_sys<0b00, 0b011, 0b0011, 0b101, dbarrier_op, "dmb">;
4423def ISBi : simple_sys<0b00, 0b011, 0b0011, 0b110, isb_op, "isb">;
4424
4425def : InstAlias<"clrex", (CLREXi 0b1111)>;
4426def : InstAlias<"isb", (ISBi 0b1111)>;
4427
4428// (DMBi 0xb) is a "DMB ISH" instruciton, appropriate for Linux SMP
4429// configurations at least.
4430def : Pat<(atomic_fence imm, imm), (DMBi 0xb)>;
4431
4432// Any SYS bitpattern can be represented with a complex and opaque "SYS"
4433// instruction.
4434def SYSiccix : A64I_system<0b0, (outs),
4435                           (ins uimm3:$Op1, CRx:$CRn, CRx:$CRm,
4436                                uimm3:$Op2, GPR64:$Rt),
4437                           "sys\t$Op1, $CRn, $CRm, $Op2, $Rt",
4438                           [], NoItinerary> {
4439  let Op0 = 0b01;
4440}
4441
4442// You can skip the Xt argument whether it makes sense or not for the generic
4443// SYS instruction.
4444def : InstAlias<"sys $Op1, $CRn, $CRm, $Op2",
4445                (SYSiccix uimm3:$Op1, CRx:$CRn, CRx:$CRm, uimm3:$Op2, XZR)>;
4446
4447
4448// But many have aliases, which obviously don't fit into
4449class SYSalias<dag ins, string asmstring>
4450  : A64I_system<0b0, (outs), ins, asmstring, [], NoItinerary> {
4451  let isAsmParserOnly = 1;
4452
4453  bits<14> SysOp;
4454  let Op0 = 0b01;
4455  let Op1 = SysOp{13-11};
4456  let CRn = SysOp{10-7};
4457  let CRm = SysOp{6-3};
4458  let Op2 = SysOp{2-0};
4459}
4460
4461def ICix : SYSalias<(ins ic_op:$SysOp, GPR64:$Rt), "ic\t$SysOp, $Rt">;
4462
4463def ICi : SYSalias<(ins ic_op:$SysOp), "ic\t$SysOp"> {
4464  let Rt = 0b11111;
4465}
4466
4467def DCix : SYSalias<(ins dc_op:$SysOp, GPR64:$Rt), "dc\t$SysOp, $Rt">;
4468def ATix : SYSalias<(ins at_op:$SysOp, GPR64:$Rt), "at\t$SysOp, $Rt">;
4469
4470def TLBIix : SYSalias<(ins tlbi_op:$SysOp, GPR64:$Rt), "tlbi\t$SysOp, $Rt">;
4471
4472def TLBIi : SYSalias<(ins tlbi_op:$SysOp), "tlbi\t$SysOp"> {
4473  let Rt = 0b11111;
4474}
4475
4476
4477def SYSLxicci : A64I_system<0b1, (outs GPR64:$Rt),
4478                            (ins uimm3:$Op1, CRx:$CRn, CRx:$CRm, uimm3:$Op2),
4479                            "sysl\t$Rt, $Op1, $CRn, $CRm, $Op2",
4480                            [], NoItinerary> {
4481  let Op0 = 0b01;
4482}
4483
4484// The instructions themselves are rather simple for MSR and MRS.
4485def MSRix : A64I_system<0b0, (outs), (ins msr_op:$SysReg, GPR64:$Rt),
4486                        "msr\t$SysReg, $Rt", [], NoItinerary> {
4487  bits<16> SysReg;
4488  let Op0 = SysReg{15-14};
4489  let Op1 = SysReg{13-11};
4490  let CRn = SysReg{10-7};
4491  let CRm = SysReg{6-3};
4492  let Op2 = SysReg{2-0};
4493}
4494
4495def MRSxi : A64I_system<0b1, (outs GPR64:$Rt), (ins mrs_op:$SysReg),
4496                        "mrs\t$Rt, $SysReg", [], NoItinerary> {
4497  bits<16> SysReg;
4498  let Op0 = SysReg{15-14};
4499  let Op1 = SysReg{13-11};
4500  let CRn = SysReg{10-7};
4501  let CRm = SysReg{6-3};
4502  let Op2 = SysReg{2-0};
4503}
4504
4505def MSRii : A64I_system<0b0, (outs), (ins pstate_op:$PState, uimm4:$CRm),
4506                        "msr\t$PState, $CRm", [], NoItinerary> {
4507  bits<6> PState;
4508
4509  let Op0 = 0b00;
4510  let Op1 = PState{5-3};
4511  let CRn = 0b0100;
4512  let Op2 = PState{2-0};
4513  let Rt = 0b11111;
4514}
4515
4516//===----------------------------------------------------------------------===//
4517// Test & branch (immediate) instructions
4518//===----------------------------------------------------------------------===//
4519// Contains: TBZ, TBNZ
4520
4521// The bit to test is a simple unsigned 6-bit immediate in the X-register
4522// versions.
4523def uimm6 : Operand<i64> {
4524  let ParserMatchClass = uimm6_asmoperand;
4525}
4526
4527def label_wid14_scal4_asmoperand : label_asmoperand<14, 4>;
4528
4529def tbimm_target : Operand<OtherVT> {
4530  let EncoderMethod = "getLabelOpValue<AArch64::fixup_a64_tstbr>";
4531
4532  // This label is a 14-bit offset from PC, scaled by the instruction-width: 4.
4533  let PrintMethod = "printLabelOperand<14, 4>";
4534  let ParserMatchClass = label_wid14_scal4_asmoperand;
4535
4536  let OperandType = "OPERAND_PCREL";
4537}
4538
4539def A64eq : ImmLeaf<i32, [{ return Imm == A64CC::EQ; }]>;
4540def A64ne : ImmLeaf<i32, [{ return Imm == A64CC::NE; }]>;
4541
4542// These instructions correspond to patterns involving "and" with a power of
4543// two, which we need to be able to select.
4544def tstb64_pat : ComplexPattern<i64, 1, "SelectTSTBOperand<64>">;
4545def tstb32_pat : ComplexPattern<i32, 1, "SelectTSTBOperand<32>">;
4546
4547let isBranch = 1, isTerminator = 1 in {
4548  def TBZxii : A64I_TBimm<0b0, (outs),
4549                        (ins GPR64:$Rt, uimm6:$Imm, tbimm_target:$Label),
4550                        "tbz\t$Rt, $Imm, $Label",
4551                        [(A64br_cc (A64cmp (and i64:$Rt, tstb64_pat:$Imm), 0),
4552                                   A64eq, bb:$Label)],
4553                        NoItinerary>,
4554               Sched<[WriteBr]>;
4555
4556  def TBNZxii : A64I_TBimm<0b1, (outs),
4557                        (ins GPR64:$Rt, uimm6:$Imm, tbimm_target:$Label),
4558                        "tbnz\t$Rt, $Imm, $Label",
4559                        [(A64br_cc (A64cmp (and i64:$Rt, tstb64_pat:$Imm), 0),
4560                                   A64ne, bb:$Label)],
4561                        NoItinerary>,
4562                Sched<[WriteBr]>;
4563
4564
4565  // Note, these instructions overlap with the above 64-bit patterns. This is
4566  // intentional, "tbz x3, #1, somewhere" and "tbz w3, #1, somewhere" would both
4567  // do the same thing and are both permitted assembly. They also both have
4568  // sensible DAG patterns.
4569  def TBZwii : A64I_TBimm<0b0, (outs),
4570                        (ins GPR32:$Rt, uimm5:$Imm, tbimm_target:$Label),
4571                        "tbz\t$Rt, $Imm, $Label",
4572                        [(A64br_cc (A64cmp (and i32:$Rt, tstb32_pat:$Imm), 0),
4573                                   A64eq, bb:$Label)],
4574                        NoItinerary>,
4575               Sched<[WriteBr]> {
4576    let Imm{5} = 0b0;
4577  }
4578
4579  def TBNZwii : A64I_TBimm<0b1, (outs),
4580                        (ins GPR32:$Rt, uimm5:$Imm, tbimm_target:$Label),
4581                        "tbnz\t$Rt, $Imm, $Label",
4582                        [(A64br_cc (A64cmp (and i32:$Rt, tstb32_pat:$Imm), 0),
4583                                   A64ne, bb:$Label)],
4584                        NoItinerary>,
4585                Sched<[WriteBr]> {
4586    let Imm{5} = 0b0;
4587  }
4588}
4589
4590//===----------------------------------------------------------------------===//
4591// Unconditional branch (immediate) instructions
4592//===----------------------------------------------------------------------===//
4593// Contains: B, BL
4594
4595def label_wid26_scal4_asmoperand : label_asmoperand<26, 4>;
4596
4597def bimm_target : Operand<OtherVT> {
4598  let EncoderMethod = "getLabelOpValue<AArch64::fixup_a64_uncondbr>";
4599
4600  // This label is a 26-bit offset from PC, scaled by the instruction-width: 4.
4601  let PrintMethod = "printLabelOperand<26, 4>";
4602  let ParserMatchClass = label_wid26_scal4_asmoperand;
4603
4604  let OperandType = "OPERAND_PCREL";
4605}
4606
4607def blimm_target : Operand<i64> {
4608  let EncoderMethod = "getLabelOpValue<AArch64::fixup_a64_call>";
4609
4610  // This label is a 26-bit offset from PC, scaled by the instruction-width: 4.
4611  let PrintMethod = "printLabelOperand<26, 4>";
4612  let ParserMatchClass = label_wid26_scal4_asmoperand;
4613
4614  let OperandType = "OPERAND_PCREL";
4615}
4616
4617class A64I_BimmImpl<bit op, string asmop, list<dag> patterns, Operand lbl_type>
4618  : A64I_Bimm<op, (outs), (ins lbl_type:$Label),
4619              !strconcat(asmop, "\t$Label"), patterns,
4620              NoItinerary>,
4621    Sched<[WriteBr]>;
4622
4623let isBranch = 1 in {
4624  def Bimm : A64I_BimmImpl<0b0, "b", [(br bb:$Label)], bimm_target> {
4625    let isTerminator = 1;
4626    let isBarrier = 1;
4627  }
4628
4629  let SchedRW = [WriteBrL] in {
4630    def BLimm : A64I_BimmImpl<0b1, "bl",
4631                              [(AArch64Call tglobaladdr:$Label)], blimm_target> {
4632      let isCall = 1;
4633      let Defs = [X30];
4634    }
4635  }
4636}
4637
4638def : Pat<(AArch64Call texternalsym:$Label), (BLimm texternalsym:$Label)>;
4639
4640//===----------------------------------------------------------------------===//
4641// Unconditional branch (register) instructions
4642//===----------------------------------------------------------------------===//
4643// Contains: BR, BLR, RET, ERET, DRP.
4644
4645// Most of the notional opcode fields in the A64I_Breg format are fixed in A64
4646// at the moment.
4647class A64I_BregImpl<bits<4> opc,
4648                    dag outs, dag ins, string asmstr, list<dag> patterns,
4649                    InstrItinClass itin = NoItinerary>
4650  : A64I_Breg<opc, 0b11111, 0b000000, 0b00000,
4651              outs, ins, asmstr, patterns, itin>,
4652    Sched<[WriteBr]> {
4653  let isBranch         = 1;
4654  let isIndirectBranch = 1;
4655}
4656
4657// Note that these are not marked isCall or isReturn because as far as LLVM is
4658// concerned they're not. "ret" is just another jump unless it has been selected
4659// by LLVM as the function's return.
4660
4661let isBranch = 1 in {
4662  def BRx : A64I_BregImpl<0b0000,(outs), (ins GPR64:$Rn),
4663                          "br\t$Rn", [(brind i64:$Rn)]> {
4664    let isBarrier = 1;
4665    let isTerminator = 1;
4666  }
4667
4668  let SchedRW = [WriteBrL] in {
4669    def BLRx : A64I_BregImpl<0b0001, (outs), (ins GPR64:$Rn),
4670                             "blr\t$Rn", [(AArch64Call i64:$Rn)]> {
4671      let isBarrier = 0;
4672      let isCall = 1;
4673      let Defs = [X30];
4674    }
4675  }
4676
4677  def RETx : A64I_BregImpl<0b0010, (outs), (ins GPR64:$Rn),
4678                           "ret\t$Rn", []> {
4679    let isBarrier = 1;
4680    let isTerminator = 1;
4681    let isReturn = 1;
4682  }
4683
4684  // Create a separate pseudo-instruction for codegen to use so that we don't
4685  // flag x30 as used in every function. It'll be restored before the RET by the
4686  // epilogue if it's legitimately used.
4687  def RET : A64PseudoExpand<(outs), (ins), [(A64ret)], (RETx (ops X30))> {
4688    let isTerminator = 1;
4689    let isBarrier = 1;
4690    let isReturn = 1;
4691  }
4692
4693  def ERET : A64I_BregImpl<0b0100, (outs), (ins), "eret", []> {
4694    let Rn = 0b11111;
4695    let isBarrier = 1;
4696    let isTerminator = 1;
4697    let isReturn = 1;
4698  }
4699
4700  def DRPS : A64I_BregImpl<0b0101, (outs), (ins), "drps", []> {
4701    let Rn = 0b11111;
4702    let isBarrier = 1;
4703  }
4704}
4705
4706def RETAlias : InstAlias<"ret", (RETx X30)>;
4707
4708
4709//===----------------------------------------------------------------------===//
4710// Address generation patterns
4711//===----------------------------------------------------------------------===//
4712
4713// Primary method of address generation for the small/absolute memory model is
4714// an ADRP/ADR pair:
4715//     ADRP x0, some_variable
4716//     ADD x0, x0, #:lo12:some_variable
4717//
4718// The load/store elision of the ADD is accomplished when selecting
4719// addressing-modes. This just mops up the cases where that doesn't work and we
4720// really need an address in some register.
4721
4722// This wrapper applies a LO12 modifier to the address. Otherwise we could just
4723// use the same address.
4724
4725class ADRP_ADD<SDNode Wrapper, SDNode addrop>
4726 : Pat<(Wrapper addrop:$Hi, addrop:$Lo12, (i32 imm)),
4727       (ADDxxi_lsl0_s (ADRPxi addrop:$Hi), addrop:$Lo12)>;
4728
4729def : ADRP_ADD<A64WrapperSmall, tblockaddress>;
4730def : ADRP_ADD<A64WrapperSmall, texternalsym>;
4731def : ADRP_ADD<A64WrapperSmall, tglobaladdr>;
4732def : ADRP_ADD<A64WrapperSmall, tglobaltlsaddr>;
4733def : ADRP_ADD<A64WrapperSmall, tjumptable>;
4734def : ADRP_ADD<A64WrapperSmall, tconstpool>;
4735
4736//===----------------------------------------------------------------------===//
4737// GOT access patterns
4738//===----------------------------------------------------------------------===//
4739
4740class GOTLoadSmall<SDNode addrfrag>
4741  : Pat<(A64GOTLoad (A64WrapperSmall addrfrag:$Hi, addrfrag:$Lo12, 8)),
4742        (LS64_LDR (ADRPxi addrfrag:$Hi), addrfrag:$Lo12)>;
4743
4744def : GOTLoadSmall<texternalsym>;
4745def : GOTLoadSmall<tglobaladdr>;
4746def : GOTLoadSmall<tglobaltlsaddr>;
4747
4748//===----------------------------------------------------------------------===//
4749// Tail call handling
4750//===----------------------------------------------------------------------===//
4751
4752let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [XSP] in {
4753  def TC_RETURNdi
4754    : PseudoInst<(outs), (ins i64imm:$dst, i32imm:$FPDiff),
4755                 [(AArch64tcret tglobaladdr:$dst, (i32 timm:$FPDiff))]>;
4756
4757  def TC_RETURNxi
4758    : PseudoInst<(outs), (ins tcGPR64:$dst, i32imm:$FPDiff),
4759                 [(AArch64tcret i64:$dst, (i32 timm:$FPDiff))]>;
4760}
4761
4762let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1,
4763    Uses = [XSP] in {
4764  def TAIL_Bimm : A64PseudoExpand<(outs), (ins bimm_target:$Label), [],
4765                                  (Bimm bimm_target:$Label)>;
4766
4767  def TAIL_BRx : A64PseudoExpand<(outs), (ins tcGPR64:$Rd), [],
4768                                 (BRx GPR64:$Rd)>;
4769}
4770
4771
4772def : Pat<(AArch64tcret texternalsym:$dst, (i32 timm:$FPDiff)),
4773          (TC_RETURNdi texternalsym:$dst, imm:$FPDiff)>;
4774
4775//===----------------------------------------------------------------------===//
4776// Thread local storage
4777//===----------------------------------------------------------------------===//
4778
4779// This is a pseudo-instruction representing the ".tlsdesccall" directive in
4780// assembly. Its effect is to insert an R_AARCH64_TLSDESC_CALL relocation at the
4781// current location. It should always be immediately followed by a BLR
4782// instruction, and is intended solely for relaxation by the linker.
4783
4784def : Pat<(A64threadpointer), (MRSxi 0xde82)>;
4785
4786def TLSDESCCALL : PseudoInst<(outs), (ins i64imm:$Lbl), []> {
4787  let hasSideEffects = 1;
4788}
4789
4790def TLSDESC_BLRx : PseudoInst<(outs), (ins GPR64:$Rn, i64imm:$Var),
4791                            [(A64tlsdesc_blr i64:$Rn, tglobaltlsaddr:$Var)]> {
4792  let isCall = 1;
4793  let Defs = [X30];
4794}
4795
4796def : Pat<(A64tlsdesc_blr i64:$Rn, texternalsym:$Var),
4797          (TLSDESC_BLRx $Rn, texternalsym:$Var)>;
4798
4799//===----------------------------------------------------------------------===//
4800// Bitfield patterns
4801//===----------------------------------------------------------------------===//
4802
4803def bfi32_lsb_to_immr : SDNodeXForm<imm, [{
4804  return CurDAG->getTargetConstant((32 - N->getZExtValue()) % 32, MVT::i64);
4805}]>;
4806
4807def bfi64_lsb_to_immr : SDNodeXForm<imm, [{
4808  return CurDAG->getTargetConstant((64 - N->getZExtValue()) % 64, MVT::i64);
4809}]>;
4810
4811def bfi_width_to_imms : SDNodeXForm<imm, [{
4812  return CurDAG->getTargetConstant(N->getZExtValue() - 1, MVT::i64);
4813}]>;
4814
4815
4816// The simpler patterns deal with cases where no AND mask is actually needed
4817// (either all bits are used or the low 32 bits are used).
4818let AddedComplexity = 10 in {
4819
4820def : Pat<(A64Bfi i64:$src, i64:$Rn, imm:$ImmR, imm:$ImmS),
4821           (BFIxxii $src, $Rn,
4822                    (bfi64_lsb_to_immr (i64 imm:$ImmR)),
4823                    (bfi_width_to_imms (i64 imm:$ImmS)))>;
4824
4825def : Pat<(A64Bfi i32:$src, i32:$Rn, imm:$ImmR, imm:$ImmS),
4826          (BFIwwii $src, $Rn,
4827                   (bfi32_lsb_to_immr (i64 imm:$ImmR)),
4828                   (bfi_width_to_imms (i64 imm:$ImmS)))>;
4829
4830
4831def : Pat<(and (A64Bfi i64:$src, i64:$Rn, imm:$ImmR, imm:$ImmS),
4832               (i64 4294967295)),
4833          (SUBREG_TO_REG (i64 0),
4834                         (BFIwwii (EXTRACT_SUBREG $src, sub_32),
4835                                  (EXTRACT_SUBREG $Rn, sub_32),
4836                                  (bfi32_lsb_to_immr (i64 imm:$ImmR)),
4837                                  (bfi_width_to_imms (i64 imm:$ImmS))),
4838                         sub_32)>;
4839
4840}
4841
4842//===----------------------------------------------------------------------===//
4843// Miscellaneous patterns
4844//===----------------------------------------------------------------------===//
4845
4846// Truncation from 64 to 32-bits just involves renaming your register.
4847def : Pat<(i32 (trunc i64:$val)), (EXTRACT_SUBREG $val, sub_32)>;
4848
4849// Similarly, extension where we don't care about the high bits is
4850// just a rename.
4851def : Pat<(i64 (anyext i32:$val)),
4852          (INSERT_SUBREG (IMPLICIT_DEF), $val, sub_32)>;
4853
4854// SELECT instructions providing f128 types need to be handled by a
4855// pseudo-instruction since the eventual code will need to introduce basic
4856// blocks and control flow.
4857def F128CSEL : PseudoInst<(outs FPR128:$Rd),
4858                         (ins FPR128:$Rn, FPR128:$Rm, cond_code_op:$Cond),
4859                         [(set f128:$Rd, (simple_select f128:$Rn, f128:$Rm))]> {
4860  let Uses = [NZCV];
4861  let usesCustomInserter = 1;
4862}
4863
4864//===----------------------------------------------------------------------===//
4865// Load/store patterns
4866//===----------------------------------------------------------------------===//
4867
4868// There are lots of patterns here, because we need to allow at least three
4869// parameters to vary independently.
4870//   1. Instruction: "ldrb w9, [sp]", "ldrh w9, [sp]", ...
4871//   2. LLVM source: zextloadi8, anyextloadi8, ...
4872//   3. Address-generation: A64Wrapper, (add BASE, OFFSET), ...
4873//
4874// The biggest problem turns out to be the address-generation variable. At the
4875// point of instantiation we need to produce two DAGs, one for the pattern and
4876// one for the instruction. Doing this at the lowest level of classes doesn't
4877// work.
4878//
4879// Consider the simple uimm12 addressing mode, and the desire to match both (add
4880// GPR64xsp:$Rn, uimm12:$Offset) and GPR64xsp:$Rn, particularly on the
4881// instruction side. We'd need to insert either "GPR64xsp" and "uimm12" or
4882// "GPR64xsp" and "0" into an unknown dag. !subst is not capable of this
4883// operation, and PatFrags are for selection not output.
4884//
4885// As a result, the address-generation patterns are the final
4886// instantiations. However, we do still need to vary the operand for the address
4887// further down (At the point we're deciding A64WrapperSmall, we don't know
4888// the memory width of the operation).
4889
4890//===------------------------------
4891// 1. Basic infrastructural defs
4892//===------------------------------
4893
4894// First, some simple classes for !foreach and !subst to use:
4895class Decls {
4896  dag pattern;
4897}
4898
4899def decls : Decls;
4900def ALIGN;
4901def INST;
4902def OFFSET;
4903def SHIFT;
4904
4905// You can't use !subst on an actual immediate, but you *can* use it on an
4906// operand record that happens to match a single immediate. So we do.
4907def imm_eq0 : ImmLeaf<i64, [{ return Imm == 0; }]>;
4908def imm_eq1 : ImmLeaf<i64, [{ return Imm == 1; }]>;
4909def imm_eq2 : ImmLeaf<i64, [{ return Imm == 2; }]>;
4910def imm_eq3 : ImmLeaf<i64, [{ return Imm == 3; }]>;
4911def imm_eq4 : ImmLeaf<i64, [{ return Imm == 4; }]>;
4912
4913// If the low bits of a pointer are known to be 0 then an "or" is just as good
4914// as addition for computing an offset. This fragment forwards that check for
4915// TableGen's use.
4916def add_like_or : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),
4917[{
4918  return CurDAG->isBaseWithConstantOffset(SDValue(N, 0));
4919}]>;
4920
4921// Load/store (unsigned immediate) operations with relocations against global
4922// symbols (for lo12) are only valid if those symbols have correct alignment
4923// (since the immediate offset is divided by the access scale, it can't have a
4924// remainder).
4925//
4926// The guaranteed alignment is provided as part of the WrapperSmall
4927// operation, and checked against one of these.
4928def any_align   : ImmLeaf<i32, [{ (void)Imm; return true; }]>;
4929def min_align2  : ImmLeaf<i32, [{ return Imm >= 2; }]>;
4930def min_align4  : ImmLeaf<i32, [{ return Imm >= 4; }]>;
4931def min_align8  : ImmLeaf<i32, [{ return Imm >= 8; }]>;
4932def min_align16 : ImmLeaf<i32, [{ return Imm >= 16; }]>;
4933
4934// "Normal" load/store instructions can be used on atomic operations, provided
4935// the ordering parameter is at most "monotonic". Anything above that needs
4936// special handling with acquire/release instructions.
4937class simple_load<PatFrag base>
4938  : PatFrag<(ops node:$ptr), (base node:$ptr), [{
4939  return cast<AtomicSDNode>(N)->getOrdering() <= Monotonic;
4940}]>;
4941
4942def atomic_load_simple_i8  : simple_load<atomic_load_8>;
4943def atomic_load_simple_i16 : simple_load<atomic_load_16>;
4944def atomic_load_simple_i32 : simple_load<atomic_load_32>;
4945def atomic_load_simple_i64 : simple_load<atomic_load_64>;
4946
4947class simple_store<PatFrag base>
4948  : PatFrag<(ops node:$ptr, node:$val), (base node:$ptr, node:$val), [{
4949  return cast<AtomicSDNode>(N)->getOrdering() <= Monotonic;
4950}]>;
4951
4952def atomic_store_simple_i8  : simple_store<atomic_store_8>;
4953def atomic_store_simple_i16 : simple_store<atomic_store_16>;
4954def atomic_store_simple_i32 : simple_store<atomic_store_32>;
4955def atomic_store_simple_i64 : simple_store<atomic_store_64>;
4956
4957//===------------------------------
4958// 2. UImm12 and SImm9
4959//===------------------------------
4960
4961// These instructions have two operands providing the address so they can be
4962// treated similarly for most purposes.
4963
4964//===------------------------------
4965// 2.1 Base patterns covering extend/truncate semantics
4966//===------------------------------
4967
4968// Atomic patterns can be shared between integer operations of all sizes, a
4969// quick multiclass here allows reuse.
4970multiclass ls_atomic_pats<Instruction LOAD, Instruction STORE, dag Base,
4971                          dag Offset, dag address, ValueType transty,
4972                          ValueType sty> {
4973  def : Pat<(!cast<PatFrag>("atomic_load_simple_" # sty) address),
4974            (LOAD Base, Offset)>;
4975
4976  def : Pat<(!cast<PatFrag>("atomic_store_simple_" # sty) address, transty:$Rt),
4977            (STORE $Rt, Base, Offset)>;
4978}
4979
4980// Instructions accessing a memory chunk smaller than a register (or, in a
4981// pinch, the same size) have a characteristic set of patterns they want to
4982// match: extending loads and truncating stores. This class deals with the
4983// sign-neutral version of those patterns.
4984//
4985// It will be instantiated across multiple addressing-modes.
4986multiclass ls_small_pats<Instruction LOAD, Instruction STORE,
4987                         dag Base, dag Offset,
4988                         dag address, ValueType sty>
4989  : ls_atomic_pats<LOAD, STORE, Base, Offset, address, i32, sty> {
4990  def : Pat<(!cast<SDNode>(zextload # sty) address), (LOAD Base, Offset)>;
4991
4992  def : Pat<(!cast<SDNode>(extload # sty) address), (LOAD Base, Offset)>;
4993
4994  // For zero-extension to 64-bits we have to tell LLVM that the whole 64-bit
4995  // register was actually set.
4996  def : Pat<(i64 (!cast<SDNode>(zextload # sty) address)),
4997            (SUBREG_TO_REG (i64 0), (LOAD Base, Offset), sub_32)>;
4998
4999  def : Pat<(i64 (!cast<SDNode>(extload # sty) address)),
5000            (SUBREG_TO_REG (i64 0), (LOAD Base, Offset), sub_32)>;
5001
5002  def : Pat<(!cast<SDNode>(truncstore # sty) i32:$Rt, address),
5003            (STORE $Rt, Base, Offset)>;
5004
5005  // For truncating store from 64-bits, we have to manually tell LLVM to
5006  // ignore the high bits of the x register.
5007  def : Pat<(!cast<SDNode>(truncstore # sty) i64:$Rt, address),
5008            (STORE (EXTRACT_SUBREG $Rt, sub_32), Base, Offset)>;
5009}
5010
5011// Next come patterns for sign-extending loads.
5012multiclass load_signed_pats<string T, string U, dag Base, dag Offset,
5013                            dag address, ValueType sty> {
5014  def : Pat<(i32 (!cast<SDNode>("sextload" # sty) address)),
5015            (!cast<Instruction>("LDRS" # T # "w" # U) Base, Offset)>;
5016
5017  def : Pat<(i64 (!cast<SDNode>("sextload" # sty) address)),
5018            (!cast<Instruction>("LDRS" # T # "x" # U) Base, Offset)>;
5019
5020}
5021
5022// and finally "natural-width" loads and stores come next.
5023multiclass ls_neutral_pats<Instruction LOAD, Instruction STORE, dag Base,
5024                           dag Offset, dag address, ValueType sty> {
5025  def : Pat<(sty (load address)), (LOAD Base, Offset)>;
5026  def : Pat<(store sty:$Rt, address), (STORE $Rt, Base, Offset)>;
5027}
5028
5029// Integer operations also get atomic instructions to select for.
5030multiclass ls_int_neutral_pats<Instruction LOAD, Instruction STORE, dag Base,
5031                           dag Offset, dag address, ValueType sty>
5032  : ls_neutral_pats<LOAD, STORE, Base, Offset, address, sty>,
5033    ls_atomic_pats<LOAD, STORE, Base, Offset, address, sty, sty>;
5034
5035//===------------------------------
5036// 2.2. Addressing-mode instantiations
5037//===------------------------------
5038
5039multiclass uimm12_pats<dag address, dag Base, dag Offset> {
5040  defm : ls_small_pats<LS8_LDR, LS8_STR, Base,
5041                       !foreach(decls.pattern, Offset,
5042                                !subst(OFFSET, byte_uimm12, decls.pattern)),
5043                       !foreach(decls.pattern, address,
5044                                !subst(OFFSET, byte_uimm12,
5045                                !subst(ALIGN, any_align, decls.pattern))),
5046                       i8>;
5047  defm : ls_small_pats<LS16_LDR, LS16_STR, Base,
5048                       !foreach(decls.pattern, Offset,
5049                                !subst(OFFSET, hword_uimm12, decls.pattern)),
5050                       !foreach(decls.pattern, address,
5051                                !subst(OFFSET, hword_uimm12,
5052                                !subst(ALIGN, min_align2, decls.pattern))),
5053                       i16>;
5054  defm : ls_small_pats<LS32_LDR, LS32_STR, Base,
5055                       !foreach(decls.pattern, Offset,
5056                                !subst(OFFSET, word_uimm12, decls.pattern)),
5057                       !foreach(decls.pattern, address,
5058                                !subst(OFFSET, word_uimm12,
5059                                !subst(ALIGN, min_align4, decls.pattern))),
5060                       i32>;
5061
5062  defm : ls_int_neutral_pats<LS32_LDR, LS32_STR, Base,
5063                          !foreach(decls.pattern, Offset,
5064                                   !subst(OFFSET, word_uimm12, decls.pattern)),
5065                          !foreach(decls.pattern, address,
5066                                   !subst(OFFSET, word_uimm12,
5067                                   !subst(ALIGN, min_align4, decls.pattern))),
5068                          i32>;
5069
5070  defm : ls_int_neutral_pats<LS64_LDR, LS64_STR, Base,
5071                          !foreach(decls.pattern, Offset,
5072                                   !subst(OFFSET, dword_uimm12, decls.pattern)),
5073                          !foreach(decls.pattern, address,
5074                                   !subst(OFFSET, dword_uimm12,
5075                                   !subst(ALIGN, min_align8, decls.pattern))),
5076                          i64>;
5077
5078  defm : ls_neutral_pats<LSFP16_LDR, LSFP16_STR, Base,
5079                          !foreach(decls.pattern, Offset,
5080                                   !subst(OFFSET, hword_uimm12, decls.pattern)),
5081                          !foreach(decls.pattern, address,
5082                                   !subst(OFFSET, hword_uimm12,
5083                                   !subst(ALIGN, min_align2, decls.pattern))),
5084                          f16>;
5085
5086  defm : ls_neutral_pats<LSFP32_LDR, LSFP32_STR, Base,
5087                          !foreach(decls.pattern, Offset,
5088                                   !subst(OFFSET, word_uimm12, decls.pattern)),
5089                          !foreach(decls.pattern, address,
5090                                   !subst(OFFSET, word_uimm12,
5091                                   !subst(ALIGN, min_align4, decls.pattern))),
5092                          f32>;
5093
5094  defm : ls_neutral_pats<LSFP64_LDR, LSFP64_STR, Base,
5095                          !foreach(decls.pattern, Offset,
5096                                   !subst(OFFSET, dword_uimm12, decls.pattern)),
5097                          !foreach(decls.pattern, address,
5098                                   !subst(OFFSET, dword_uimm12,
5099                                   !subst(ALIGN, min_align8, decls.pattern))),
5100                          f64>;
5101
5102  defm : ls_neutral_pats<LSFP128_LDR, LSFP128_STR, Base,
5103                          !foreach(decls.pattern, Offset,
5104                                   !subst(OFFSET, qword_uimm12, decls.pattern)),
5105                          !foreach(decls.pattern, address,
5106                                   !subst(OFFSET, qword_uimm12,
5107                                   !subst(ALIGN, min_align16, decls.pattern))),
5108                          f128>;
5109
5110  defm : load_signed_pats<"B", "", Base,
5111                          !foreach(decls.pattern, Offset,
5112                                   !subst(OFFSET, byte_uimm12, decls.pattern)),
5113                          !foreach(decls.pattern, address,
5114                                   !subst(OFFSET, byte_uimm12,
5115                                   !subst(ALIGN, any_align, decls.pattern))),
5116                          i8>;
5117
5118  defm : load_signed_pats<"H", "", Base,
5119                          !foreach(decls.pattern, Offset,
5120                                   !subst(OFFSET, hword_uimm12, decls.pattern)),
5121                          !foreach(decls.pattern, address,
5122                                   !subst(OFFSET, hword_uimm12,
5123                                   !subst(ALIGN, min_align2, decls.pattern))),
5124                          i16>;
5125
5126  def : Pat<(sextloadi32 !foreach(decls.pattern, address,
5127                                  !subst(OFFSET, word_uimm12,
5128                                  !subst(ALIGN, min_align4, decls.pattern)))),
5129            (LDRSWx Base, !foreach(decls.pattern, Offset,
5130                                  !subst(OFFSET, word_uimm12, decls.pattern)))>;
5131}
5132
5133// Straightforward patterns of last resort: a pointer with or without an
5134// appropriate offset.
5135defm : uimm12_pats<(i64 i64:$Rn), (i64 i64:$Rn), (i64 0)>;
5136defm : uimm12_pats<(add i64:$Rn, OFFSET:$UImm12),
5137                   (i64 i64:$Rn), (i64 OFFSET:$UImm12)>;
5138
5139// The offset could be hidden behind an "or", of course:
5140defm : uimm12_pats<(add_like_or i64:$Rn, OFFSET:$UImm12),
5141                   (i64 i64:$Rn), (i64 OFFSET:$UImm12)>;
5142
5143// Global addresses under the small-absolute model should use these
5144// instructions. There are ELF relocations specifically for it.
5145defm : uimm12_pats<(A64WrapperSmall tglobaladdr:$Hi, tglobaladdr:$Lo12, ALIGN),
5146                   (ADRPxi tglobaladdr:$Hi), (i64 tglobaladdr:$Lo12)>;
5147
5148defm : uimm12_pats<(A64WrapperSmall tglobaltlsaddr:$Hi, tglobaltlsaddr:$Lo12,
5149                                    ALIGN),
5150                   (ADRPxi tglobaltlsaddr:$Hi), (i64 tglobaltlsaddr:$Lo12)>;
5151
5152// External symbols that make it this far should also get standard relocations.
5153defm : uimm12_pats<(A64WrapperSmall texternalsym:$Hi, texternalsym:$Lo12,
5154                                    ALIGN),
5155                   (ADRPxi texternalsym:$Hi), (i64 texternalsym:$Lo12)>;
5156
5157defm : uimm12_pats<(A64WrapperSmall tconstpool:$Hi, tconstpool:$Lo12, ALIGN),
5158                   (ADRPxi tconstpool:$Hi), (i64 tconstpool:$Lo12)>;
5159
5160// We also want to use uimm12 instructions for local variables at the moment.
5161def tframeindex_XFORM : SDNodeXForm<frameindex, [{
5162  int FI = cast<FrameIndexSDNode>(N)->getIndex();
5163  return CurDAG->getTargetFrameIndex(FI, MVT::i64);
5164}]>;
5165
5166defm : uimm12_pats<(i64 frameindex:$Rn),
5167                   (tframeindex_XFORM tframeindex:$Rn), (i64 0)>;
5168
5169// These can be much simpler than uimm12 because we don't to change the operand
5170// type (e.g. LDURB and LDURH take the same operands).
5171multiclass simm9_pats<dag address, dag Base, dag Offset> {
5172  defm : ls_small_pats<LS8_LDUR, LS8_STUR, Base, Offset, address, i8>;
5173  defm : ls_small_pats<LS16_LDUR, LS16_STUR, Base, Offset, address, i16>;
5174
5175  defm : ls_int_neutral_pats<LS32_LDUR, LS32_STUR, Base, Offset, address, i32>;
5176  defm : ls_int_neutral_pats<LS64_LDUR, LS64_STUR, Base, Offset, address, i64>;
5177
5178  defm : ls_neutral_pats<LSFP16_LDUR, LSFP16_STUR, Base, Offset, address, f16>;
5179  defm : ls_neutral_pats<LSFP32_LDUR, LSFP32_STUR, Base, Offset, address, f32>;
5180  defm : ls_neutral_pats<LSFP64_LDUR, LSFP64_STUR, Base, Offset, address, f64>;
5181  defm : ls_neutral_pats<LSFP128_LDUR, LSFP128_STUR, Base, Offset, address,
5182                         f128>;
5183
5184  def : Pat<(i64 (zextloadi32 address)),
5185            (SUBREG_TO_REG (i64 0), (LS32_LDUR Base, Offset), sub_32)>;
5186
5187  def : Pat<(truncstorei32 i64:$Rt, address),
5188            (LS32_STUR (EXTRACT_SUBREG $Rt, sub_32), Base, Offset)>;
5189
5190  defm : load_signed_pats<"B", "_U", Base, Offset, address, i8>;
5191  defm : load_signed_pats<"H", "_U", Base, Offset, address, i16>;
5192  def : Pat<(sextloadi32 address), (LDURSWx Base, Offset)>;
5193}
5194
5195defm : simm9_pats<(add i64:$Rn, simm9:$SImm9),
5196                  (i64 $Rn), (SDXF_simm9 simm9:$SImm9)>;
5197
5198defm : simm9_pats<(add_like_or i64:$Rn, simm9:$SImm9),
5199                  (i64 $Rn), (SDXF_simm9 simm9:$SImm9)>;
5200
5201
5202//===------------------------------
5203// 3. Register offset patterns
5204//===------------------------------
5205
5206// Atomic patterns can be shared between integer operations of all sizes, a
5207// quick multiclass here allows reuse.
5208multiclass ro_atomic_pats<Instruction LOAD, Instruction STORE, dag Base,
5209                          dag Offset, dag Extend, dag address,
5210                          ValueType transty, ValueType sty> {
5211  def : Pat<(!cast<PatFrag>("atomic_load_simple_" # sty) address),
5212            (LOAD Base, Offset, Extend)>;
5213
5214  def : Pat<(!cast<PatFrag>("atomic_store_simple_" # sty) address, transty:$Rt),
5215            (STORE $Rt, Base, Offset, Extend)>;
5216}
5217
5218// The register offset instructions take three operands giving the instruction,
5219// and have an annoying split between instructions where Rm is 32-bit and
5220// 64-bit. So we need a special hierarchy to describe them. Other than that the
5221// same operations should be supported as for simm9 and uimm12 addressing.
5222
5223multiclass ro_small_pats<Instruction LOAD, Instruction STORE,
5224                         dag Base, dag Offset, dag Extend,
5225                         dag address, ValueType sty>
5226  : ro_atomic_pats<LOAD, STORE, Base, Offset, Extend, address, i32, sty> {
5227  def : Pat<(!cast<SDNode>(zextload # sty) address),
5228            (LOAD Base, Offset, Extend)>;
5229
5230  def : Pat<(!cast<SDNode>(extload # sty) address),
5231            (LOAD Base, Offset, Extend)>;
5232
5233  // For zero-extension to 64-bits we have to tell LLVM that the whole 64-bit
5234  // register was actually set.
5235  def : Pat<(i64 (!cast<SDNode>(zextload # sty) address)),
5236            (SUBREG_TO_REG (i64 0), (LOAD Base, Offset, Extend), sub_32)>;
5237
5238  def : Pat<(i64 (!cast<SDNode>(extload # sty) address)),
5239            (SUBREG_TO_REG (i64 0), (LOAD Base, Offset, Extend), sub_32)>;
5240
5241  def : Pat<(!cast<SDNode>(truncstore # sty) i32:$Rt, address),
5242            (STORE $Rt, Base, Offset, Extend)>;
5243
5244  // For truncating store from 64-bits, we have to manually tell LLVM to
5245  // ignore the high bits of the x register.
5246  def : Pat<(!cast<SDNode>(truncstore # sty) i64:$Rt, address),
5247            (STORE (EXTRACT_SUBREG $Rt, sub_32), Base, Offset, Extend)>;
5248
5249}
5250
5251// Next come patterns for sign-extending loads.
5252multiclass ro_signed_pats<string T, string Rm, dag Base, dag Offset, dag Extend,
5253                          dag address, ValueType sty> {
5254  def : Pat<(i32 (!cast<SDNode>("sextload" # sty) address)),
5255            (!cast<Instruction>("LDRS" # T # "w_" # Rm # "_RegOffset")
5256              Base, Offset, Extend)>;
5257
5258  def : Pat<(i64 (!cast<SDNode>("sextload" # sty) address)),
5259            (!cast<Instruction>("LDRS" # T # "x_" # Rm # "_RegOffset")
5260              Base, Offset, Extend)>;
5261}
5262
5263// and finally "natural-width" loads and stores come next.
5264multiclass ro_neutral_pats<Instruction LOAD, Instruction STORE,
5265                           dag Base, dag Offset, dag Extend, dag address,
5266                           ValueType sty> {
5267  def : Pat<(sty (load address)), (LOAD Base, Offset, Extend)>;
5268  def : Pat<(store sty:$Rt, address),
5269            (STORE $Rt, Base, Offset, Extend)>;
5270}
5271
5272multiclass ro_int_neutral_pats<Instruction LOAD, Instruction STORE,
5273                               dag Base, dag Offset, dag Extend, dag address,
5274                               ValueType sty>
5275  : ro_neutral_pats<LOAD, STORE, Base, Offset, Extend, address, sty>,
5276    ro_atomic_pats<LOAD, STORE, Base, Offset, Extend, address, sty, sty>;
5277
5278multiclass regoff_pats<string Rm, dag address, dag Base, dag Offset,
5279                       dag Extend> {
5280  defm : ro_small_pats<!cast<Instruction>("LS8_" # Rm # "_RegOffset_LDR"),
5281                       !cast<Instruction>("LS8_" # Rm # "_RegOffset_STR"),
5282                       Base, Offset, Extend,
5283                       !foreach(decls.pattern, address,
5284                                !subst(SHIFT, imm_eq0, decls.pattern)),
5285                       i8>;
5286  defm : ro_small_pats<!cast<Instruction>("LS16_" # Rm # "_RegOffset_LDR"),
5287                       !cast<Instruction>("LS16_" # Rm # "_RegOffset_STR"),
5288                       Base, Offset, Extend,
5289                       !foreach(decls.pattern, address,
5290                                !subst(SHIFT, imm_eq1, decls.pattern)),
5291                       i16>;
5292  defm : ro_small_pats<!cast<Instruction>("LS32_" # Rm # "_RegOffset_LDR"),
5293                       !cast<Instruction>("LS32_" # Rm # "_RegOffset_STR"),
5294                       Base, Offset, Extend,
5295                       !foreach(decls.pattern, address,
5296                                !subst(SHIFT, imm_eq2, decls.pattern)),
5297                       i32>;
5298
5299  defm : ro_int_neutral_pats<
5300                            !cast<Instruction>("LS32_" # Rm # "_RegOffset_LDR"),
5301                            !cast<Instruction>("LS32_" # Rm # "_RegOffset_STR"),
5302                            Base, Offset, Extend,
5303                            !foreach(decls.pattern, address,
5304                                     !subst(SHIFT, imm_eq2, decls.pattern)),
5305                            i32>;
5306
5307  defm : ro_int_neutral_pats<
5308                            !cast<Instruction>("LS64_" # Rm # "_RegOffset_LDR"),
5309                            !cast<Instruction>("LS64_" # Rm # "_RegOffset_STR"),
5310                            Base, Offset, Extend,
5311                            !foreach(decls.pattern, address,
5312                                     !subst(SHIFT, imm_eq3, decls.pattern)),
5313                            i64>;
5314
5315  defm : ro_neutral_pats<!cast<Instruction>("LSFP16_" # Rm # "_RegOffset_LDR"),
5316                         !cast<Instruction>("LSFP16_" # Rm # "_RegOffset_STR"),
5317                         Base, Offset, Extend,
5318                         !foreach(decls.pattern, address,
5319                                  !subst(SHIFT, imm_eq1, decls.pattern)),
5320                         f16>;
5321
5322  defm : ro_neutral_pats<!cast<Instruction>("LSFP32_" # Rm # "_RegOffset_LDR"),
5323                         !cast<Instruction>("LSFP32_" # Rm # "_RegOffset_STR"),
5324                         Base, Offset, Extend,
5325                         !foreach(decls.pattern, address,
5326                                  !subst(SHIFT, imm_eq2, decls.pattern)),
5327                         f32>;
5328
5329  defm : ro_neutral_pats<!cast<Instruction>("LSFP64_" # Rm # "_RegOffset_LDR"),
5330                         !cast<Instruction>("LSFP64_" # Rm # "_RegOffset_STR"),
5331                         Base, Offset, Extend,
5332                         !foreach(decls.pattern, address,
5333                                  !subst(SHIFT, imm_eq3, decls.pattern)),
5334                         f64>;
5335
5336  defm : ro_neutral_pats<!cast<Instruction>("LSFP128_" # Rm # "_RegOffset_LDR"),
5337                         !cast<Instruction>("LSFP128_" # Rm # "_RegOffset_STR"),
5338                         Base, Offset, Extend,
5339                         !foreach(decls.pattern, address,
5340                                  !subst(SHIFT, imm_eq4, decls.pattern)),
5341                         f128>;
5342
5343  defm : ro_signed_pats<"B", Rm, Base, Offset, Extend,
5344                        !foreach(decls.pattern, address,
5345                                 !subst(SHIFT, imm_eq0, decls.pattern)),
5346                        i8>;
5347
5348  defm : ro_signed_pats<"H", Rm, Base, Offset, Extend,
5349                        !foreach(decls.pattern, address,
5350                                 !subst(SHIFT, imm_eq1, decls.pattern)),
5351                        i16>;
5352
5353  def : Pat<(sextloadi32 !foreach(decls.pattern, address,
5354                                  !subst(SHIFT, imm_eq2, decls.pattern))),
5355            (!cast<Instruction>("LDRSWx_" # Rm # "_RegOffset")
5356              Base, Offset, Extend)>;
5357}
5358
5359
5360// Finally we're in a position to tell LLVM exactly what addresses are reachable
5361// using register-offset instructions. Essentially a base plus a possibly
5362// extended, possibly shifted (by access size) offset.
5363
5364defm : regoff_pats<"Wm", (add i64:$Rn, (sext i32:$Rm)),
5365                   (i64 i64:$Rn), (i32 i32:$Rm), (i64 6)>;
5366
5367defm : regoff_pats<"Wm", (add i64:$Rn, (shl (sext i32:$Rm), SHIFT)),
5368                   (i64 i64:$Rn), (i32 i32:$Rm), (i64 7)>;
5369
5370defm : regoff_pats<"Wm", (add i64:$Rn, (zext i32:$Rm)),
5371                   (i64 i64:$Rn), (i32 i32:$Rm), (i64 2)>;
5372
5373defm : regoff_pats<"Wm", (add i64:$Rn, (shl (zext i32:$Rm), SHIFT)),
5374                   (i64 i64:$Rn), (i32 i32:$Rm), (i64 3)>;
5375
5376defm : regoff_pats<"Xm", (add i64:$Rn, i64:$Rm),
5377                   (i64 i64:$Rn), (i64 i64:$Rm), (i64 2)>;
5378
5379defm : regoff_pats<"Xm", (add i64:$Rn, (shl i64:$Rm, SHIFT)),
5380                   (i64 i64:$Rn), (i64 i64:$Rm), (i64 3)>;
5381
5382//===----------------------------------------------------------------------===//
5383// Advanced SIMD (NEON) Support
5384//
5385
5386include "AArch64InstrNEON.td"
5387