]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/lib/Target/AArch64/AArch64InstrFormats.td
Merge ^/vendor/lld/dist up to its last change, and resolve conflicts.
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / lib / Target / AArch64 / AArch64InstrFormats.td
1 //===- AArch64InstrFormats.td - AArch64 Instruction Formats --*- tblgen -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 //===----------------------------------------------------------------------===//
10 //  Describe AArch64 instructions format here
11 //
12
13 // Format specifies the encoding used by the instruction.  This is part of the
14 // ad-hoc solution used to emit machine instruction encodings by our machine
15 // code emitter.
16 class Format<bits<2> val> {
17   bits<2> Value = val;
18 }
19
20 def PseudoFrm   : Format<0>;
21 def NormalFrm   : Format<1>; // Do we need any others?
22
23 // AArch64 Instruction Format
24 class AArch64Inst<Format f, string cstr> : Instruction {
25   field bits<32> Inst; // Instruction encoding.
26   // Mask of bits that cause an encoding to be UNPREDICTABLE.
27   // If a bit is set, then if the corresponding bit in the
28   // target encoding differs from its value in the "Inst" field,
29   // the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
30   field bits<32> Unpredictable = 0;
31   // SoftFail is the generic name for this field, but we alias it so
32   // as to make it more obvious what it means in ARM-land.
33   field bits<32> SoftFail = Unpredictable;
34   let Namespace   = "AArch64";
35   Format F        = f;
36   bits<2> Form    = F.Value;
37   let Pattern     = [];
38   let Constraints = cstr;
39 }
40
41 class InstSubst<string Asm, dag Result, bit EmitPriority = 0>
42   : InstAlias<Asm, Result, EmitPriority>, Requires<[UseNegativeImmediates]>;
43
44 // Pseudo instructions (don't have encoding information)
45 class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
46     : AArch64Inst<PseudoFrm, cstr> {
47   dag OutOperandList = oops;
48   dag InOperandList  = iops;
49   let Pattern        = pattern;
50   let isCodeGenOnly  = 1;
51 }
52
53 // Real instructions (have encoding information)
54 class EncodedI<string cstr, list<dag> pattern> : AArch64Inst<NormalFrm, cstr> {
55   let Pattern = pattern;
56   let Size = 4;
57 }
58
59 // Enum describing whether an instruction is
60 // destructive in its first source operand.
61 class DestructiveInstTypeEnum<bits<1> val> {
62   bits<1> Value = val;
63 }
64 def NotDestructive  : DestructiveInstTypeEnum<0>;
65 def Destructive     : DestructiveInstTypeEnum<1>;
66
67 // Normal instructions
68 class I<dag oops, dag iops, string asm, string operands, string cstr,
69         list<dag> pattern>
70     : EncodedI<cstr, pattern> {
71   dag OutOperandList = oops;
72   dag InOperandList  = iops;
73   let AsmString      = !strconcat(asm, operands);
74
75   // Destructive operations (SVE)
76   DestructiveInstTypeEnum DestructiveInstType = NotDestructive;
77   ElementSizeEnum ElementSize = ElementSizeB;
78
79   let TSFlags{3} = DestructiveInstType.Value;
80   let TSFlags{2-0} = ElementSize.Value;
81 }
82
83 class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
84 class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
85 class UnOpFrag<dag res>  : PatFrag<(ops node:$LHS), res>;
86
87 // Helper fragment for an extract of the high portion of a 128-bit vector.
88 def extract_high_v16i8 :
89    UnOpFrag<(extract_subvector (v16i8 node:$LHS), (i64 8))>;
90 def extract_high_v8i16 :
91    UnOpFrag<(extract_subvector (v8i16 node:$LHS), (i64 4))>;
92 def extract_high_v4i32 :
93    UnOpFrag<(extract_subvector (v4i32 node:$LHS), (i64 2))>;
94 def extract_high_v2i64 :
95    UnOpFrag<(extract_subvector (v2i64 node:$LHS), (i64 1))>;
96
97 //===----------------------------------------------------------------------===//
98 // Asm Operand Classes.
99 //
100
101 // Shifter operand for arithmetic shifted encodings.
102 def ShifterOperand : AsmOperandClass {
103   let Name = "Shifter";
104 }
105
106 // Shifter operand for mov immediate encodings.
107 def MovImm32ShifterOperand : AsmOperandClass {
108   let SuperClasses = [ShifterOperand];
109   let Name = "MovImm32Shifter";
110   let RenderMethod = "addShifterOperands";
111   let DiagnosticType = "InvalidMovImm32Shift";
112 }
113 def MovImm64ShifterOperand : AsmOperandClass {
114   let SuperClasses = [ShifterOperand];
115   let Name = "MovImm64Shifter";
116   let RenderMethod = "addShifterOperands";
117   let DiagnosticType = "InvalidMovImm64Shift";
118 }
119
120 // Shifter operand for arithmetic register shifted encodings.
121 class ArithmeticShifterOperand<int width> : AsmOperandClass {
122   let SuperClasses = [ShifterOperand];
123   let Name = "ArithmeticShifter" # width;
124   let PredicateMethod = "isArithmeticShifter<" # width # ">";
125   let RenderMethod = "addShifterOperands";
126   let DiagnosticType = "AddSubRegShift" # width;
127 }
128
129 def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
130 def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
131
132 // Shifter operand for logical register shifted encodings.
133 class LogicalShifterOperand<int width> : AsmOperandClass {
134   let SuperClasses = [ShifterOperand];
135   let Name = "LogicalShifter" # width;
136   let PredicateMethod = "isLogicalShifter<" # width # ">";
137   let RenderMethod = "addShifterOperands";
138   let DiagnosticType = "AddSubRegShift" # width;
139 }
140
141 def LogicalShifterOperand32 : LogicalShifterOperand<32>;
142 def LogicalShifterOperand64 : LogicalShifterOperand<64>;
143
144 // Shifter operand for logical vector 128/64-bit shifted encodings.
145 def LogicalVecShifterOperand : AsmOperandClass {
146   let SuperClasses = [ShifterOperand];
147   let Name = "LogicalVecShifter";
148   let RenderMethod = "addShifterOperands";
149 }
150 def LogicalVecHalfWordShifterOperand : AsmOperandClass {
151   let SuperClasses = [LogicalVecShifterOperand];
152   let Name = "LogicalVecHalfWordShifter";
153   let RenderMethod = "addShifterOperands";
154 }
155
156 // The "MSL" shifter on the vector MOVI instruction.
157 def MoveVecShifterOperand : AsmOperandClass {
158   let SuperClasses = [ShifterOperand];
159   let Name = "MoveVecShifter";
160   let RenderMethod = "addShifterOperands";
161 }
162
163 // Extend operand for arithmetic encodings.
164 def ExtendOperand : AsmOperandClass {
165   let Name = "Extend";
166   let DiagnosticType = "AddSubRegExtendLarge";
167 }
168 def ExtendOperand64 : AsmOperandClass {
169   let SuperClasses = [ExtendOperand];
170   let Name = "Extend64";
171   let DiagnosticType = "AddSubRegExtendSmall";
172 }
173 // 'extend' that's a lsl of a 64-bit register.
174 def ExtendOperandLSL64 : AsmOperandClass {
175   let SuperClasses = [ExtendOperand];
176   let Name = "ExtendLSL64";
177   let RenderMethod = "addExtend64Operands";
178   let DiagnosticType = "AddSubRegExtendLarge";
179 }
180
181 // 8-bit floating-point immediate encodings.
182 def FPImmOperand : AsmOperandClass {
183   let Name = "FPImm";
184   let ParserMethod = "tryParseFPImm<true>";
185   let DiagnosticType = "InvalidFPImm";
186 }
187
188 def CondCode : AsmOperandClass {
189   let Name = "CondCode";
190   let DiagnosticType = "InvalidCondCode";
191 }
192
193 // A 32-bit register pasrsed as 64-bit
194 def GPR32as64Operand : AsmOperandClass {
195   let Name = "GPR32as64";
196   let ParserMethod =
197       "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSubReg>";
198 }
199 def GPR32as64 : RegisterOperand<GPR32> {
200   let ParserMatchClass = GPR32as64Operand;
201 }
202
203 // A 64-bit register pasrsed as 32-bit
204 def GPR64as32Operand : AsmOperandClass {
205   let Name = "GPR64as32";
206   let ParserMethod =
207       "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSuperReg>";
208 }
209 def GPR64as32 : RegisterOperand<GPR64, "printGPR64as32"> {
210   let ParserMatchClass = GPR64as32Operand;
211 }
212
213 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
214 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
215 // are encoded as the eight bit value 'abcdefgh'.
216 def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
217
218 class UImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
219   let Name = "UImm" # Width # "s" # Scale;
220   let DiagnosticType = "InvalidMemoryIndexed" # Scale # "UImm" # Width;
221   let RenderMethod = "addImmScaledOperands<" # Scale # ">";
222   let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ">";
223 }
224
225 class SImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
226   let Name = "SImm" # Width # "s" # Scale;
227   let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm" # Width;
228   let RenderMethod = "addImmScaledOperands<" # Scale # ">";
229   let PredicateMethod = "isSImmScaled<" # Width # ", " # Scale # ">";
230 }
231
232 //===----------------------------------------------------------------------===//
233 // Operand Definitions.
234 //
235
236 // ADR[P] instruction labels.
237 def AdrpOperand : AsmOperandClass {
238   let Name = "AdrpLabel";
239   let ParserMethod = "tryParseAdrpLabel";
240   let DiagnosticType = "InvalidLabel";
241 }
242 def adrplabel : Operand<i64> {
243   let EncoderMethod = "getAdrLabelOpValue";
244   let PrintMethod = "printAdrpLabel";
245   let ParserMatchClass = AdrpOperand;
246 }
247
248 def AdrOperand : AsmOperandClass {
249   let Name = "AdrLabel";
250   let ParserMethod = "tryParseAdrLabel";
251   let DiagnosticType = "InvalidLabel";
252 }
253 def adrlabel : Operand<i64> {
254   let EncoderMethod = "getAdrLabelOpValue";
255   let ParserMatchClass = AdrOperand;
256 }
257
258 class SImmOperand<int width> : AsmOperandClass {
259   let Name = "SImm" # width;
260   let DiagnosticType = "InvalidMemoryIndexedSImm" # width;
261   let RenderMethod = "addImmOperands";
262   let PredicateMethod = "isSImm<" # width # ">";
263 }
264
265
266 class AsmImmRange<int Low, int High> : AsmOperandClass {
267   let Name = "Imm" # Low # "_" # High;
268   let DiagnosticType = "InvalidImm" # Low # "_" # High;
269   let RenderMethod = "addImmOperands";
270   let PredicateMethod = "isImmInRange<" # Low # "," # High # ">";
271 }
272
273 // Authenticated loads for v8.3 can have scaled 10-bit immediate offsets.
274 def SImm10s8Operand : SImmScaledMemoryIndexed<10, 8>;
275 def simm10Scaled : Operand<i64> {
276   let ParserMatchClass = SImm10s8Operand;
277   let DecoderMethod = "DecodeSImm<10>";
278   let PrintMethod = "printImmScale<8>";
279 }
280
281 def simm9s16 : Operand<i64> {
282   let ParserMatchClass = SImmScaledMemoryIndexed<9, 16>;
283   let DecoderMethod = "DecodeSImm<9>";
284   let PrintMethod = "printImmScale<16>";
285 }
286
287 // uimm6 predicate - True if the immediate is in the range [0, 63].
288 def UImm6Operand : AsmOperandClass {
289   let Name = "UImm6";
290   let DiagnosticType = "InvalidImm0_63";
291 }
292
293 def uimm6 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
294   let ParserMatchClass = UImm6Operand;
295 }
296
297 def uimm16 : Operand<i16>, ImmLeaf<i16, [{return Imm >= 0 && Imm < 65536;}]>{
298   let ParserMatchClass = AsmImmRange<0, 65535>;
299 }
300
301 def SImm9Operand : SImmOperand<9>;
302 def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
303   let ParserMatchClass = SImm9Operand;
304   let DecoderMethod = "DecodeSImm<9>";
305 }
306
307 def SImm8Operand : SImmOperand<8>;
308 def simm8 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -128 && Imm < 127; }]> {
309   let ParserMatchClass = SImm8Operand;
310   let DecoderMethod = "DecodeSImm<8>";
311 }
312
313 def SImm6Operand : SImmOperand<6>;
314 def simm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -32 && Imm < 32; }]> {
315   let ParserMatchClass = SImm6Operand;
316   let DecoderMethod = "DecodeSImm<6>";
317 }
318
319 def SImm5Operand : SImmOperand<5>;
320 def simm5_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -16 && Imm < 16; }]> {
321   let ParserMatchClass = SImm5Operand;
322   let DecoderMethod = "DecodeSImm<5>";
323 }
324
325 def simm5_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -16 && Imm < 16; }]> {
326   let ParserMatchClass = SImm5Operand;
327   let DecoderMethod = "DecodeSImm<5>";
328 }
329
330 // simm7sN predicate - True if the immediate is a multiple of N in the range
331 // [-64 * N, 63 * N].
332
333 def SImm7s4Operand : SImmScaledMemoryIndexed<7, 4>;
334 def SImm7s8Operand : SImmScaledMemoryIndexed<7, 8>;
335 def SImm7s16Operand : SImmScaledMemoryIndexed<7, 16>;
336
337 def simm7s4 : Operand<i32> {
338   let ParserMatchClass = SImm7s4Operand;
339   let PrintMethod = "printImmScale<4>";
340 }
341
342 def simm7s8 : Operand<i32> {
343   let ParserMatchClass = SImm7s8Operand;
344   let PrintMethod = "printImmScale<8>";
345 }
346
347 def simm7s16 : Operand<i32> {
348   let ParserMatchClass = SImm7s16Operand;
349   let PrintMethod = "printImmScale<16>";
350 }
351
352 def am_indexed7s8   : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S8", []>;
353 def am_indexed7s16  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S16", []>;
354 def am_indexed7s32  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S32", []>;
355 def am_indexed7s64  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S64", []>;
356 def am_indexed7s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S128", []>;
357
358 def am_indexedu6s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexedU6S128", []>;
359 def am_indexeds9s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexedS9S128", []>;
360
361 // uimm5sN predicate - True if the immediate is a multiple of N in the range
362 // [0 * N, 32 * N].
363 def UImm5s2Operand : UImmScaledMemoryIndexed<5, 2>;
364 def UImm5s4Operand : UImmScaledMemoryIndexed<5, 4>;
365 def UImm5s8Operand : UImmScaledMemoryIndexed<5, 8>;
366
367 def uimm5s2 : Operand<i64>, ImmLeaf<i64,
368                 [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }]> {
369   let ParserMatchClass = UImm5s2Operand;
370   let PrintMethod = "printImmScale<2>";
371 }
372 def uimm5s4 : Operand<i64>, ImmLeaf<i64,
373                 [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }]> {
374   let ParserMatchClass = UImm5s4Operand;
375   let PrintMethod = "printImmScale<4>";
376 }
377 def uimm5s8 : Operand<i64>, ImmLeaf<i64,
378                 [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }]> {
379   let ParserMatchClass = UImm5s8Operand;
380   let PrintMethod = "printImmScale<8>";
381 }
382
383 // uimm6sN predicate - True if the immediate is a multiple of N in the range
384 // [0 * N, 64 * N].
385 def UImm6s1Operand : UImmScaledMemoryIndexed<6, 1>;
386 def UImm6s2Operand : UImmScaledMemoryIndexed<6, 2>;
387 def UImm6s4Operand : UImmScaledMemoryIndexed<6, 4>;
388 def UImm6s8Operand : UImmScaledMemoryIndexed<6, 8>;
389 def UImm6s16Operand : UImmScaledMemoryIndexed<6, 16>;
390
391 def uimm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
392   let ParserMatchClass = UImm6s1Operand;
393 }
394 def uimm6s2 : Operand<i64>, ImmLeaf<i64,
395 [{ return Imm >= 0 && Imm < (64*2) && ((Imm % 2) == 0); }]> {
396   let PrintMethod = "printImmScale<2>";
397   let ParserMatchClass = UImm6s2Operand;
398 }
399 def uimm6s4 : Operand<i64>, ImmLeaf<i64,
400 [{ return Imm >= 0 && Imm < (64*4) && ((Imm % 4) == 0); }]> {
401   let PrintMethod = "printImmScale<4>";
402   let ParserMatchClass = UImm6s4Operand;
403 }
404 def uimm6s8 : Operand<i64>, ImmLeaf<i64,
405 [{ return Imm >= 0 && Imm < (64*8) && ((Imm % 8) == 0); }]> {
406   let PrintMethod = "printImmScale<8>";
407   let ParserMatchClass = UImm6s8Operand;
408 }
409 def uimm6s16 : Operand<i64>, ImmLeaf<i64,
410 [{ return Imm >= 0 && Imm < (64*16) && ((Imm % 16) == 0); }]> {
411   let PrintMethod = "printImmScale<16>";
412   let ParserMatchClass = UImm6s16Operand;
413 }
414
415 // simm6sN predicate - True if the immediate is a multiple of N in the range
416 // [-32 * N, 31 * N].
417 def SImm6s1Operand : SImmScaledMemoryIndexed<6, 1>;
418 def simm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -32 && Imm < 32; }]> {
419   let ParserMatchClass = SImm6s1Operand;
420   let DecoderMethod = "DecodeSImm<6>";
421 }
422
423 // simm4sN predicate - True if the immediate is a multiple of N in the range
424 // [ -8* N, 7 * N].
425 def SImm4s1Operand  : SImmScaledMemoryIndexed<4, 1>;
426 def SImm4s2Operand  : SImmScaledMemoryIndexed<4, 2>;
427 def SImm4s3Operand  : SImmScaledMemoryIndexed<4, 3>;
428 def SImm4s4Operand  : SImmScaledMemoryIndexed<4, 4>;
429 def SImm4s16Operand : SImmScaledMemoryIndexed<4, 16>;
430
431 def simm4s1 : Operand<i64>, ImmLeaf<i64,
432 [{ return Imm >=-8  && Imm <= 7; }]> {
433   let ParserMatchClass = SImm4s1Operand;
434   let DecoderMethod = "DecodeSImm<4>";
435 }
436
437 def simm4s2 : Operand<i64>, ImmLeaf<i64,
438 [{ return Imm >=-16  && Imm <= 14 && (Imm % 2) == 0x0; }]> {
439   let PrintMethod = "printImmScale<2>";
440   let ParserMatchClass = SImm4s2Operand;
441   let DecoderMethod = "DecodeSImm<4>";
442 }
443
444 def simm4s3 : Operand<i64>, ImmLeaf<i64,
445 [{ return Imm >=-24  && Imm <= 21 && (Imm % 3) == 0x0; }]> {
446   let PrintMethod = "printImmScale<3>";
447   let ParserMatchClass = SImm4s3Operand;
448   let DecoderMethod = "DecodeSImm<4>";
449 }
450
451 def simm4s4 : Operand<i64>, ImmLeaf<i64,
452 [{ return Imm >=-32  && Imm <= 28 && (Imm % 4) == 0x0; }]> {
453   let PrintMethod = "printImmScale<4>";
454   let ParserMatchClass = SImm4s4Operand;
455   let DecoderMethod = "DecodeSImm<4>";
456 }
457 def simm4s16 : Operand<i64>, ImmLeaf<i64,
458 [{ return Imm >=-128  && Imm <= 112 && (Imm % 16) == 0x0; }]> {
459   let PrintMethod = "printImmScale<16>";
460   let ParserMatchClass = SImm4s16Operand;
461   let DecoderMethod = "DecodeSImm<4>";
462 }
463
464 def Imm1_8Operand : AsmImmRange<1, 8>;
465 def Imm1_16Operand : AsmImmRange<1, 16>;
466 def Imm1_32Operand : AsmImmRange<1, 32>;
467 def Imm1_64Operand : AsmImmRange<1, 64>;
468
469 class BranchTarget<int N> : AsmOperandClass {
470   let Name = "BranchTarget" # N;
471   let DiagnosticType = "InvalidLabel";
472   let PredicateMethod = "isBranchTarget<" # N # ">";
473 }
474
475 class PCRelLabel<int N> : BranchTarget<N> {
476   let Name = "PCRelLabel" # N;
477 }
478
479 def BranchTarget14Operand : BranchTarget<14>;
480 def BranchTarget26Operand : BranchTarget<26>;
481 def PCRelLabel19Operand   : PCRelLabel<19>;
482
483 def MovWSymbolG3AsmOperand : AsmOperandClass {
484   let Name = "MovWSymbolG3";
485   let RenderMethod = "addImmOperands";
486 }
487
488 def movw_symbol_g3 : Operand<i32> {
489   let ParserMatchClass = MovWSymbolG3AsmOperand;
490 }
491
492 def MovWSymbolG2AsmOperand : AsmOperandClass {
493   let Name = "MovWSymbolG2";
494   let RenderMethod = "addImmOperands";
495 }
496
497 def movw_symbol_g2 : Operand<i32> {
498   let ParserMatchClass = MovWSymbolG2AsmOperand;
499 }
500
501 def MovWSymbolG1AsmOperand : AsmOperandClass {
502   let Name = "MovWSymbolG1";
503   let RenderMethod = "addImmOperands";
504 }
505
506 def movw_symbol_g1 : Operand<i32> {
507   let ParserMatchClass = MovWSymbolG1AsmOperand;
508 }
509
510 def MovWSymbolG0AsmOperand : AsmOperandClass {
511   let Name = "MovWSymbolG0";
512   let RenderMethod = "addImmOperands";
513 }
514
515 def movw_symbol_g0 : Operand<i32> {
516   let ParserMatchClass = MovWSymbolG0AsmOperand;
517 }
518
519 class fixedpoint_i32<ValueType FloatVT>
520   : Operand<FloatVT>,
521     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
522   let EncoderMethod = "getFixedPointScaleOpValue";
523   let DecoderMethod = "DecodeFixedPointScaleImm32";
524   let ParserMatchClass = Imm1_32Operand;
525 }
526
527 class fixedpoint_i64<ValueType FloatVT>
528   : Operand<FloatVT>,
529     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
530   let EncoderMethod = "getFixedPointScaleOpValue";
531   let DecoderMethod = "DecodeFixedPointScaleImm64";
532   let ParserMatchClass = Imm1_64Operand;
533 }
534
535 def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
536 def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
537 def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
538
539 def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
540 def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
541 def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
542
543 def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
544   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
545 }]> {
546   let EncoderMethod = "getVecShiftR8OpValue";
547   let DecoderMethod = "DecodeVecShiftR8Imm";
548   let ParserMatchClass = Imm1_8Operand;
549 }
550 def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
551   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
552 }]> {
553   let EncoderMethod = "getVecShiftR16OpValue";
554   let DecoderMethod = "DecodeVecShiftR16Imm";
555   let ParserMatchClass = Imm1_16Operand;
556 }
557 def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
558   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
559 }]> {
560   let EncoderMethod = "getVecShiftR16OpValue";
561   let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
562   let ParserMatchClass = Imm1_8Operand;
563 }
564 def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
565   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
566 }]> {
567   let EncoderMethod = "getVecShiftR32OpValue";
568   let DecoderMethod = "DecodeVecShiftR32Imm";
569   let ParserMatchClass = Imm1_32Operand;
570 }
571 def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
572   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
573 }]> {
574   let EncoderMethod = "getVecShiftR32OpValue";
575   let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
576   let ParserMatchClass = Imm1_16Operand;
577 }
578 def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
579   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
580 }]> {
581   let EncoderMethod = "getVecShiftR64OpValue";
582   let DecoderMethod = "DecodeVecShiftR64Imm";
583   let ParserMatchClass = Imm1_64Operand;
584 }
585 def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
586   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
587 }]> {
588   let EncoderMethod = "getVecShiftR64OpValue";
589   let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
590   let ParserMatchClass = Imm1_32Operand;
591 }
592
593 def Imm0_1Operand : AsmImmRange<0, 1>;
594 def Imm0_7Operand : AsmImmRange<0, 7>;
595 def Imm0_15Operand : AsmImmRange<0, 15>;
596 def Imm0_31Operand : AsmImmRange<0, 31>;
597 def Imm0_63Operand : AsmImmRange<0, 63>;
598
599 def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
600   return (((uint32_t)Imm) < 8);
601 }]> {
602   let EncoderMethod = "getVecShiftL8OpValue";
603   let DecoderMethod = "DecodeVecShiftL8Imm";
604   let ParserMatchClass = Imm0_7Operand;
605 }
606 def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
607   return (((uint32_t)Imm) < 16);
608 }]> {
609   let EncoderMethod = "getVecShiftL16OpValue";
610   let DecoderMethod = "DecodeVecShiftL16Imm";
611   let ParserMatchClass = Imm0_15Operand;
612 }
613 def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
614   return (((uint32_t)Imm) < 32);
615 }]> {
616   let EncoderMethod = "getVecShiftL32OpValue";
617   let DecoderMethod = "DecodeVecShiftL32Imm";
618   let ParserMatchClass = Imm0_31Operand;
619 }
620 def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
621   return (((uint32_t)Imm) < 64);
622 }]> {
623   let EncoderMethod = "getVecShiftL64OpValue";
624   let DecoderMethod = "DecodeVecShiftL64Imm";
625   let ParserMatchClass = Imm0_63Operand;
626 }
627
628
629 // Crazy immediate formats used by 32-bit and 64-bit logical immediate
630 // instructions for splatting repeating bit patterns across the immediate.
631 def logical_imm32_XFORM : SDNodeXForm<imm, [{
632   uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
633   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
634 }]>;
635 def logical_imm64_XFORM : SDNodeXForm<imm, [{
636   uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
637   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
638 }]>;
639
640 def gi_logical_imm32_XFORM : GICustomOperandRenderer<"renderLogicalImm32">,
641   GISDNodeXFormEquiv<logical_imm32_XFORM>;
642 def gi_logical_imm64_XFORM : GICustomOperandRenderer<"renderLogicalImm64">,
643   GISDNodeXFormEquiv<logical_imm64_XFORM>;
644
645 let DiagnosticType = "LogicalSecondSource" in {
646   def LogicalImm32Operand : AsmOperandClass {
647     let Name = "LogicalImm32";
648     let PredicateMethod = "isLogicalImm<int32_t>";
649     let RenderMethod = "addLogicalImmOperands<int32_t>";
650   }
651   def LogicalImm64Operand : AsmOperandClass {
652     let Name = "LogicalImm64";
653     let PredicateMethod = "isLogicalImm<int64_t>";
654     let RenderMethod = "addLogicalImmOperands<int64_t>";
655   }
656   def LogicalImm32NotOperand : AsmOperandClass {
657     let Name = "LogicalImm32Not";
658     let PredicateMethod = "isLogicalImm<int32_t>";
659     let RenderMethod = "addLogicalImmNotOperands<int32_t>";
660   }
661   def LogicalImm64NotOperand : AsmOperandClass {
662     let Name = "LogicalImm64Not";
663     let PredicateMethod = "isLogicalImm<int64_t>";
664     let RenderMethod = "addLogicalImmNotOperands<int64_t>";
665   }
666 }
667 def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{
668   return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32);
669 }], logical_imm32_XFORM> {
670   let PrintMethod = "printLogicalImm<int32_t>";
671   let ParserMatchClass = LogicalImm32Operand;
672 }
673 def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{
674   return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64);
675 }], logical_imm64_XFORM> {
676   let PrintMethod = "printLogicalImm<int64_t>";
677   let ParserMatchClass = LogicalImm64Operand;
678 }
679 def logical_imm32_not : Operand<i32> {
680   let ParserMatchClass = LogicalImm32NotOperand;
681 }
682 def logical_imm64_not : Operand<i64> {
683   let ParserMatchClass = LogicalImm64NotOperand;
684 }
685
686 // iXX_imm0_65535 predicates - True if the immediate is in the range [0,65535].
687 let ParserMatchClass = AsmImmRange<0, 65535>, PrintMethod = "printImmHex" in {
688 def i32_imm0_65535 : Operand<i32>, TImmLeaf<i32, [{
689   return ((uint32_t)Imm) < 65536;
690 }]>;
691
692 def i64_imm0_65535 : Operand<i64>, TImmLeaf<i64, [{
693   return ((uint64_t)Imm) < 65536;
694 }]>;
695 }
696
697 // imm0_255 predicate - True if the immediate is in the range [0,255].
698 def Imm0_255Operand : AsmImmRange<0,255>;
699
700 def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
701   return ((uint32_t)Imm) < 256;
702 }]> {
703   let ParserMatchClass = Imm0_255Operand;
704   let PrintMethod = "printImm";
705 }
706
707 // imm0_127 predicate - True if the immediate is in the range [0,127]
708 def Imm0_127Operand : AsmImmRange<0, 127>;
709 def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
710   return ((uint32_t)Imm) < 128;
711 }]> {
712   let ParserMatchClass = Imm0_127Operand;
713   let PrintMethod = "printImm";
714 }
715
716 // NOTE: These imm0_N operands have to be of type i64 because i64 is the size
717 // for all shift-amounts.
718
719 // imm0_63 predicate - True if the immediate is in the range [0,63]
720 def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
721   return ((uint64_t)Imm) < 64;
722 }]> {
723   let ParserMatchClass = Imm0_63Operand;
724 }
725
726 // imm0_31 predicate - True if the immediate is in the range [0,31]
727 def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
728   return ((uint64_t)Imm) < 32;
729 }]> {
730   let ParserMatchClass = Imm0_31Operand;
731 }
732
733 // True if the 32-bit immediate is in the range [0,31]
734 def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
735   return ((uint64_t)Imm) < 32;
736 }]> {
737   let ParserMatchClass = Imm0_31Operand;
738 }
739
740 // imm0_1 predicate - True if the immediate is in the range [0,1]
741 def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
742   return ((uint64_t)Imm) < 2;
743 }]> {
744   let ParserMatchClass = Imm0_1Operand;
745 }
746
747 // imm0_15 predicate - True if the immediate is in the range [0,15]
748 def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
749   return ((uint64_t)Imm) < 16;
750 }]> {
751   let ParserMatchClass = Imm0_15Operand;
752 }
753
754 // imm0_7 predicate - True if the immediate is in the range [0,7]
755 def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
756   return ((uint64_t)Imm) < 8;
757 }]> {
758   let ParserMatchClass = Imm0_7Operand;
759 }
760
761 // imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
762 def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
763   return ((uint32_t)Imm) < 16;
764 }]> {
765   let ParserMatchClass = Imm0_15Operand;
766 }
767
768 // An arithmetic shifter operand:
769 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
770 //  {5-0} - imm6
771 class arith_shift<ValueType Ty, int width> : Operand<Ty> {
772   let PrintMethod = "printShifter";
773   let ParserMatchClass = !cast<AsmOperandClass>(
774                          "ArithmeticShifterOperand" # width);
775 }
776
777 def arith_shift32 : arith_shift<i32, 32>;
778 def arith_shift64 : arith_shift<i64, 64>;
779
780 class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
781     : Operand<Ty>,
782       ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
783   let PrintMethod = "printShiftedRegister";
784   let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
785 }
786
787 def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
788 def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
789
790 def gi_arith_shifted_reg32 :
791   GIComplexOperandMatcher<s32, "selectArithShiftedRegister">,
792   GIComplexPatternEquiv<arith_shifted_reg32>;
793
794 def gi_arith_shifted_reg64 :
795   GIComplexOperandMatcher<s64, "selectArithShiftedRegister">,
796   GIComplexPatternEquiv<arith_shifted_reg64>;
797
798 // An arithmetic shifter operand:
799 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
800 //  {5-0} - imm6
801 class logical_shift<int width> : Operand<i32> {
802   let PrintMethod = "printShifter";
803   let ParserMatchClass = !cast<AsmOperandClass>(
804                          "LogicalShifterOperand" # width);
805 }
806
807 def logical_shift32 : logical_shift<32>;
808 def logical_shift64 : logical_shift<64>;
809
810 class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
811     : Operand<Ty>,
812       ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
813   let PrintMethod = "printShiftedRegister";
814   let MIOperandInfo = (ops regclass, shiftop);
815 }
816
817 def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
818 def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
819
820 def gi_logical_shifted_reg32 :
821   GIComplexOperandMatcher<s32, "selectLogicalShiftedRegister">,
822   GIComplexPatternEquiv<logical_shifted_reg32>;
823
824 def gi_logical_shifted_reg64 :
825   GIComplexOperandMatcher<s64, "selectLogicalShiftedRegister">,
826   GIComplexPatternEquiv<logical_shifted_reg64>;
827
828 // A logical vector shifter operand:
829 //  {7-6} - shift type: 00 = lsl
830 //  {5-0} - imm6: #0, #8, #16, or #24
831 def logical_vec_shift : Operand<i32> {
832   let PrintMethod = "printShifter";
833   let EncoderMethod = "getVecShifterOpValue";
834   let ParserMatchClass = LogicalVecShifterOperand;
835 }
836
837 // A logical vector half-word shifter operand:
838 //  {7-6} - shift type: 00 = lsl
839 //  {5-0} - imm6: #0 or #8
840 def logical_vec_hw_shift : Operand<i32> {
841   let PrintMethod = "printShifter";
842   let EncoderMethod = "getVecShifterOpValue";
843   let ParserMatchClass = LogicalVecHalfWordShifterOperand;
844 }
845
846 // A vector move shifter operand:
847 //  {0} - imm1: #8 or #16
848 def move_vec_shift : Operand<i32> {
849   let PrintMethod = "printShifter";
850   let EncoderMethod = "getMoveVecShifterOpValue";
851   let ParserMatchClass = MoveVecShifterOperand;
852 }
853
854 let DiagnosticType = "AddSubSecondSource" in {
855   def AddSubImmOperand : AsmOperandClass {
856     let Name = "AddSubImm";
857     let ParserMethod = "tryParseImmWithOptionalShift";
858     let RenderMethod = "addImmWithOptionalShiftOperands<12>";
859   }
860   def AddSubImmNegOperand : AsmOperandClass {
861     let Name = "AddSubImmNeg";
862     let ParserMethod = "tryParseImmWithOptionalShift";
863     let RenderMethod = "addImmNegWithOptionalShiftOperands<12>";
864   }
865 }
866 // An ADD/SUB immediate shifter operand:
867 //  second operand:
868 //  {7-6} - shift type: 00 = lsl
869 //  {5-0} - imm6: #0 or #12
870 class addsub_shifted_imm<ValueType Ty>
871     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
872   let PrintMethod = "printAddSubImm";
873   let EncoderMethod = "getAddSubImmOpValue";
874   let ParserMatchClass = AddSubImmOperand;
875   let MIOperandInfo = (ops i32imm, i32imm);
876 }
877
878 class addsub_shifted_imm_neg<ValueType Ty>
879     : Operand<Ty> {
880   let EncoderMethod = "getAddSubImmOpValue";
881   let ParserMatchClass = AddSubImmNegOperand;
882   let MIOperandInfo = (ops i32imm, i32imm);
883 }
884
885 def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
886 def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
887 def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
888 def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
889
890 def gi_addsub_shifted_imm32 :
891     GIComplexOperandMatcher<s32, "selectArithImmed">,
892     GIComplexPatternEquiv<addsub_shifted_imm32>;
893
894 def gi_addsub_shifted_imm64 :
895     GIComplexOperandMatcher<s64, "selectArithImmed">,
896     GIComplexPatternEquiv<addsub_shifted_imm64>;
897
898 class neg_addsub_shifted_imm<ValueType Ty>
899     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
900   let PrintMethod = "printAddSubImm";
901   let EncoderMethod = "getAddSubImmOpValue";
902   let ParserMatchClass = AddSubImmOperand;
903   let MIOperandInfo = (ops i32imm, i32imm);
904 }
905
906 def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
907 def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
908
909 def gi_neg_addsub_shifted_imm32 :
910     GIComplexOperandMatcher<s32, "selectNegArithImmed">,
911     GIComplexPatternEquiv<neg_addsub_shifted_imm32>;
912
913 def gi_neg_addsub_shifted_imm64 :
914     GIComplexOperandMatcher<s64, "selectNegArithImmed">,
915     GIComplexPatternEquiv<neg_addsub_shifted_imm64>;
916
917 // An extend operand:
918 //  {5-3} - extend type
919 //  {2-0} - imm3
920 def arith_extend : Operand<i32> {
921   let PrintMethod = "printArithExtend";
922   let ParserMatchClass = ExtendOperand;
923 }
924 def arith_extend64 : Operand<i32> {
925   let PrintMethod = "printArithExtend";
926   let ParserMatchClass = ExtendOperand64;
927 }
928
929 // 'extend' that's a lsl of a 64-bit register.
930 def arith_extendlsl64 : Operand<i32> {
931   let PrintMethod = "printArithExtend";
932   let ParserMatchClass = ExtendOperandLSL64;
933 }
934
935 class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
936                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
937   let PrintMethod = "printExtendedRegister";
938   let MIOperandInfo = (ops GPR32, arith_extend);
939 }
940
941 class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
942                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
943   let PrintMethod = "printExtendedRegister";
944   let MIOperandInfo = (ops GPR32, arith_extend64);
945 }
946
947 def arith_extended_reg32_i32 : arith_extended_reg32<i32>;
948 def gi_arith_extended_reg32_i32 :
949     GIComplexOperandMatcher<s32, "selectArithExtendedRegister">,
950     GIComplexPatternEquiv<arith_extended_reg32_i32>;
951
952 def arith_extended_reg32_i64 : arith_extended_reg32<i64>;
953 def gi_arith_extended_reg32_i64 :
954     GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
955     GIComplexPatternEquiv<arith_extended_reg32_i64>;
956
957 def arith_extended_reg32to64_i64 : arith_extended_reg32to64<i64>;
958 def gi_arith_extended_reg32to64_i64 :
959     GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
960     GIComplexPatternEquiv<arith_extended_reg32to64_i64>;
961
962 // Floating-point immediate.
963 def fpimm16 : Operand<f16>,
964               FPImmLeaf<f16, [{
965       return AArch64_AM::getFP16Imm(Imm) != -1;
966     }], SDNodeXForm<fpimm, [{
967       APFloat InVal = N->getValueAPF();
968       uint32_t enc = AArch64_AM::getFP16Imm(InVal);
969       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
970     }]>> {
971   let ParserMatchClass = FPImmOperand;
972   let PrintMethod = "printFPImmOperand";
973 }
974 def fpimm32 : Operand<f32>,
975               FPImmLeaf<f32, [{
976       return AArch64_AM::getFP32Imm(Imm) != -1;
977     }], SDNodeXForm<fpimm, [{
978       APFloat InVal = N->getValueAPF();
979       uint32_t enc = AArch64_AM::getFP32Imm(InVal);
980       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
981     }]>> {
982   let ParserMatchClass = FPImmOperand;
983   let PrintMethod = "printFPImmOperand";
984 }
985 def fpimm64 : Operand<f64>,
986               FPImmLeaf<f64, [{
987       return AArch64_AM::getFP64Imm(Imm) != -1;
988     }], SDNodeXForm<fpimm, [{
989       APFloat InVal = N->getValueAPF();
990       uint32_t enc = AArch64_AM::getFP64Imm(InVal);
991       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
992     }]>> {
993   let ParserMatchClass = FPImmOperand;
994   let PrintMethod = "printFPImmOperand";
995 }
996
997 def fpimm8 : Operand<i32> {
998   let ParserMatchClass = FPImmOperand;
999   let PrintMethod = "printFPImmOperand";
1000 }
1001
1002 def fpimm0 : FPImmLeaf<fAny, [{
1003   return Imm.isExactlyValue(+0.0);
1004 }]>;
1005
1006 // Vector lane operands
1007 class AsmVectorIndex<int Min, int Max, string NamePrefix=""> : AsmOperandClass {
1008   let Name = NamePrefix # "IndexRange" # Min # "_" # Max;
1009   let DiagnosticType = "Invalid" # Name;
1010   let PredicateMethod = "isVectorIndex<" # Min # ", " # Max #  ">";
1011   let RenderMethod = "addVectorIndexOperands";
1012 }
1013
1014 class AsmVectorIndexOpnd<ValueType ty, AsmOperandClass mc, code pred>
1015     : Operand<ty>, ImmLeaf<ty, pred> {
1016   let ParserMatchClass = mc;
1017   let PrintMethod = "printVectorIndex";
1018 }
1019
1020 def VectorIndex1Operand : AsmVectorIndex<1, 1>;
1021 def VectorIndexBOperand : AsmVectorIndex<0, 15>;
1022 def VectorIndexHOperand : AsmVectorIndex<0, 7>;
1023 def VectorIndexSOperand : AsmVectorIndex<0, 3>;
1024 def VectorIndexDOperand : AsmVectorIndex<0, 1>;
1025
1026 def VectorIndex1 : AsmVectorIndexOpnd<i64, VectorIndex1Operand, [{ return ((uint64_t)Imm) == 1; }]>;
1027 def VectorIndexB : AsmVectorIndexOpnd<i64, VectorIndexBOperand, [{ return ((uint64_t)Imm) < 16; }]>;
1028 def VectorIndexH : AsmVectorIndexOpnd<i64, VectorIndexHOperand, [{ return ((uint64_t)Imm) < 8; }]>;
1029 def VectorIndexS : AsmVectorIndexOpnd<i64, VectorIndexSOperand, [{ return ((uint64_t)Imm) < 4; }]>;
1030 def VectorIndexD : AsmVectorIndexOpnd<i64, VectorIndexDOperand, [{ return ((uint64_t)Imm) < 2; }]>;
1031
1032 def VectorIndex132b : AsmVectorIndexOpnd<i32, VectorIndex1Operand, [{ return ((uint64_t)Imm) == 1; }]>;
1033 def VectorIndexB32b : AsmVectorIndexOpnd<i32, VectorIndexBOperand, [{ return ((uint64_t)Imm) < 16; }]>;
1034 def VectorIndexH32b : AsmVectorIndexOpnd<i32, VectorIndexHOperand, [{ return ((uint64_t)Imm) < 8; }]>;
1035 def VectorIndexS32b : AsmVectorIndexOpnd<i32, VectorIndexSOperand, [{ return ((uint64_t)Imm) < 4; }]>;
1036 def VectorIndexD32b : AsmVectorIndexOpnd<i32, VectorIndexDOperand, [{ return ((uint64_t)Imm) < 2; }]>;
1037
1038 def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">;
1039 def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">;
1040 def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">;
1041 def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">;
1042 def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">;
1043
1044 def sve_elm_idx_extdup_b
1045   : AsmVectorIndexOpnd<i64, SVEVectorIndexExtDupBOperand, [{ return ((uint64_t)Imm) < 64; }]>;
1046 def sve_elm_idx_extdup_h
1047   : AsmVectorIndexOpnd<i64, SVEVectorIndexExtDupHOperand, [{ return ((uint64_t)Imm) < 32; }]>;
1048 def sve_elm_idx_extdup_s
1049   : AsmVectorIndexOpnd<i64, SVEVectorIndexExtDupSOperand, [{ return ((uint64_t)Imm) < 16; }]>;
1050 def sve_elm_idx_extdup_d
1051   : AsmVectorIndexOpnd<i64, SVEVectorIndexExtDupDOperand, [{ return ((uint64_t)Imm) < 8; }]>;
1052 def sve_elm_idx_extdup_q
1053   : AsmVectorIndexOpnd<i64, SVEVectorIndexExtDupQOperand, [{ return ((uint64_t)Imm) < 4; }]>;
1054
1055 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
1056 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
1057 // are encoded as the eight bit value 'abcdefgh'.
1058 def simdimmtype10 : Operand<i32>,
1059                     FPImmLeaf<f64, [{
1060       return AArch64_AM::isAdvSIMDModImmType10(
1061                  Imm.bitcastToAPInt().getZExtValue());
1062     }], SDNodeXForm<fpimm, [{
1063       APFloat InVal = N->getValueAPF();
1064       uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
1065                                                            .bitcastToAPInt()
1066                                                            .getZExtValue());
1067       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1068     }]>> {
1069   let ParserMatchClass = SIMDImmType10Operand;
1070   let PrintMethod = "printSIMDType10Operand";
1071 }
1072
1073
1074 //---
1075 // System management
1076 //---
1077
1078 // Base encoding for system instruction operands.
1079 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
1080 class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
1081                   list<dag> pattern = []>
1082     : I<oops, iops, asm, operands, "", pattern> {
1083   let Inst{31-22} = 0b1101010100;
1084   let Inst{21}    = L;
1085 }
1086
1087 // System instructions which do not have an Rt register.
1088 class SimpleSystemI<bit L, dag iops, string asm, string operands,
1089                     list<dag> pattern = []>
1090     : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
1091   let Inst{4-0} = 0b11111;
1092 }
1093
1094 // System instructions which have an Rt register.
1095 class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
1096     : BaseSystemI<L, oops, iops, asm, operands>,
1097       Sched<[WriteSys]> {
1098   bits<5> Rt;
1099   let Inst{4-0} = Rt;
1100 }
1101
1102 // System instructions for transactional memory extension
1103 class TMBaseSystemI<bit L, bits<4> CRm, bits<3> op2, dag oops, dag iops,
1104                     string asm, string operands, list<dag> pattern>
1105     : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1106       Sched<[WriteSys]> {
1107   let Inst{20-12} = 0b000110011;
1108   let Inst{11-8} = CRm;
1109   let Inst{7-5} = op2;
1110   let DecoderMethod = "";
1111
1112   let mayLoad = 1;
1113   let mayStore = 1;
1114 }
1115
1116 // System instructions for transactional memory - single input operand
1117 class TMSystemI<bits<4> CRm, string asm, list<dag> pattern>
1118     : TMBaseSystemI<0b1, CRm, 0b011,
1119                     (outs GPR64:$Rt), (ins), asm, "\t$Rt", pattern> {
1120   bits<5> Rt;
1121   let Inst{4-0} = Rt;
1122 }
1123
1124 // System instructions for transactional memory - no operand
1125 class TMSystemINoOperand<bits<4> CRm, string asm, list<dag> pattern>
1126     : TMBaseSystemI<0b0, CRm, 0b011, (outs), (ins), asm, "", pattern> {
1127   let Inst{4-0} = 0b11111;
1128 }
1129
1130 // System instructions for exit from transactions
1131 class TMSystemException<bits<3> op1, string asm, list<dag> pattern>
1132     : I<(outs), (ins i64_imm0_65535:$imm), asm, "\t$imm", "", pattern>,
1133       Sched<[WriteSys]> {
1134   bits<16> imm;
1135   let Inst{31-24} = 0b11010100;
1136   let Inst{23-21} = op1;
1137   let Inst{20-5}  = imm;
1138   let Inst{4-0}   = 0b00000;
1139 }
1140
1141 // Hint instructions that take both a CRm and a 3-bit immediate.
1142 // NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
1143 // model patterns with sufficiently fine granularity
1144 let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
1145   class HintI<string mnemonic>
1146       : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
1147                       [(int_aarch64_hint imm0_127:$imm)]>,
1148         Sched<[WriteHint]> {
1149     bits <7> imm;
1150     let Inst{20-12} = 0b000110010;
1151     let Inst{11-5} = imm;
1152   }
1153
1154 // System instructions taking a single literal operand which encodes into
1155 // CRm. op2 differentiates the opcodes.
1156 def BarrierAsmOperand : AsmOperandClass {
1157   let Name = "Barrier";
1158   let ParserMethod = "tryParseBarrierOperand";
1159 }
1160 def barrier_op : Operand<i32> {
1161   let PrintMethod = "printBarrierOption";
1162   let ParserMatchClass = BarrierAsmOperand;
1163 }
1164 class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
1165                  list<dag> pattern = []>
1166     : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
1167       Sched<[WriteBarrier]> {
1168   bits<4> CRm;
1169   let Inst{20-12} = 0b000110011;
1170   let Inst{11-8} = CRm;
1171   let Inst{7-5} = opc;
1172 }
1173
1174 class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
1175     : SimpleSystemI<0, (ins), asm, "", pattern>,
1176       Sched<[]> {
1177   bits<4> CRm;
1178   let CRm = 0b0011;
1179   let Inst{31-12} = 0b11010101000000110010;
1180   let Inst{11-8} = CRm;
1181   let Inst{7-5} = op2;
1182   let Inst{4-0} = 0b11111;
1183 }
1184
1185 // MRS/MSR system instructions. These have different operand classes because
1186 // a different subset of registers can be accessed through each instruction.
1187 def MRSSystemRegisterOperand : AsmOperandClass {
1188   let Name = "MRSSystemRegister";
1189   let ParserMethod = "tryParseSysReg";
1190   let DiagnosticType = "MRS";
1191 }
1192 // concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
1193 def mrs_sysreg_op : Operand<i32> {
1194   let ParserMatchClass = MRSSystemRegisterOperand;
1195   let DecoderMethod = "DecodeMRSSystemRegister";
1196   let PrintMethod = "printMRSSystemRegister";
1197 }
1198
1199 def MSRSystemRegisterOperand : AsmOperandClass {
1200   let Name = "MSRSystemRegister";
1201   let ParserMethod = "tryParseSysReg";
1202   let DiagnosticType = "MSR";
1203 }
1204 def msr_sysreg_op : Operand<i32> {
1205   let ParserMatchClass = MSRSystemRegisterOperand;
1206   let DecoderMethod = "DecodeMSRSystemRegister";
1207   let PrintMethod = "printMSRSystemRegister";
1208 }
1209
1210 def PSBHintOperand : AsmOperandClass {
1211   let Name = "PSBHint";
1212   let ParserMethod = "tryParsePSBHint";
1213 }
1214 def psbhint_op : Operand<i32> {
1215   let ParserMatchClass = PSBHintOperand;
1216   let PrintMethod = "printPSBHintOp";
1217   let MCOperandPredicate = [{
1218     // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
1219     // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
1220     if (!MCOp.isImm())
1221       return false;
1222     return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
1223   }];
1224 }
1225
1226 def BTIHintOperand : AsmOperandClass {
1227   let Name = "BTIHint";
1228   let ParserMethod = "tryParseBTIHint";
1229 }
1230 def btihint_op : Operand<i32> {
1231   let ParserMatchClass = BTIHintOperand;
1232   let PrintMethod = "printBTIHintOp";
1233   let MCOperandPredicate = [{
1234     // "bti" is an alias to "hint" only for certain values of CRm:Op2 fields.
1235     if (!MCOp.isImm())
1236       return false;
1237     return AArch64BTIHint::lookupBTIByEncoding((MCOp.getImm() ^ 32) >> 1) != nullptr;
1238   }];
1239 }
1240
1241 class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
1242                        "mrs", "\t$Rt, $systemreg"> {
1243   bits<16> systemreg;
1244   let Inst{20-5} = systemreg;
1245 }
1246
1247 // FIXME: Some of these def NZCV, others don't. Best way to model that?
1248 // Explicitly modeling each of the system register as a register class
1249 // would do it, but feels like overkill at this point.
1250 class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
1251                        "msr", "\t$systemreg, $Rt"> {
1252   bits<16> systemreg;
1253   let Inst{20-5} = systemreg;
1254 }
1255
1256 def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
1257   let Name = "SystemPStateFieldWithImm0_15";
1258   let ParserMethod = "tryParseSysReg";
1259 }
1260 def pstatefield4_op : Operand<i32> {
1261   let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
1262   let PrintMethod = "printSystemPStateField";
1263 }
1264
1265 // Instructions to modify PSTATE, no input reg
1266 let Defs = [NZCV] in
1267 class PstateWriteSimple<dag iops, string asm, string operands>
1268   : SimpleSystemI<0, iops, asm, operands> {
1269
1270   let Inst{20-19} = 0b00;
1271   let Inst{15-12} = 0b0100;
1272 }
1273
1274 class MSRpstateImm0_15
1275   : PstateWriteSimple<(ins pstatefield4_op:$pstatefield, imm0_15:$imm), "msr",
1276                   "\t$pstatefield, $imm">,
1277     Sched<[WriteSys]> {
1278
1279   bits<6> pstatefield;
1280   bits<4> imm;
1281   let Inst{18-16} = pstatefield{5-3};
1282   let Inst{11-8} = imm;
1283   let Inst{7-5} = pstatefield{2-0};
1284
1285   let DecoderMethod = "DecodeSystemPStateInstruction";
1286   // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1287   // Fail the decoder should attempt to decode the instruction as MSRI.
1288   let hasCompleteDecoder = 0;
1289 }
1290
1291 def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
1292   let Name = "SystemPStateFieldWithImm0_1";
1293   let ParserMethod = "tryParseSysReg";
1294 }
1295 def pstatefield1_op : Operand<i32> {
1296   let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
1297   let PrintMethod = "printSystemPStateField";
1298 }
1299
1300 class MSRpstateImm0_1
1301   : PstateWriteSimple<(ins pstatefield1_op:$pstatefield, imm0_1:$imm), "msr",
1302                  "\t$pstatefield, $imm">,
1303     Sched<[WriteSys]> {
1304
1305   bits<6> pstatefield;
1306   bit imm;
1307   let Inst{18-16} = pstatefield{5-3};
1308   let Inst{11-9} = 0b000;
1309   let Inst{8} = imm;
1310   let Inst{7-5} = pstatefield{2-0};
1311
1312   let DecoderMethod = "DecodeSystemPStateInstruction";
1313   // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1314   // Fail the decoder should attempt to decode the instruction as MSRI.
1315   let hasCompleteDecoder = 0;
1316 }
1317
1318 // SYS and SYSL generic system instructions.
1319 def SysCRAsmOperand : AsmOperandClass {
1320   let Name = "SysCR";
1321   let ParserMethod = "tryParseSysCROperand";
1322 }
1323
1324 def sys_cr_op : Operand<i32> {
1325   let PrintMethod = "printSysCROperand";
1326   let ParserMatchClass = SysCRAsmOperand;
1327 }
1328
1329 class SystemXtI<bit L, string asm>
1330   : RtSystemI<L, (outs),
1331        (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1332        asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1333   bits<3> op1;
1334   bits<4> Cn;
1335   bits<4> Cm;
1336   bits<3> op2;
1337   let Inst{20-19} = 0b01;
1338   let Inst{18-16} = op1;
1339   let Inst{15-12} = Cn;
1340   let Inst{11-8}  = Cm;
1341   let Inst{7-5}   = op2;
1342 }
1343
1344 class SystemLXtI<bit L, string asm>
1345   : RtSystemI<L, (outs),
1346        (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1347        asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1348   bits<3> op1;
1349   bits<4> Cn;
1350   bits<4> Cm;
1351   bits<3> op2;
1352   let Inst{20-19} = 0b01;
1353   let Inst{18-16} = op1;
1354   let Inst{15-12} = Cn;
1355   let Inst{11-8}  = Cm;
1356   let Inst{7-5}   = op2;
1357 }
1358
1359
1360 // Branch (register) instructions:
1361 //
1362 //  case opc of
1363 //    0001 blr
1364 //    0000 br
1365 //    0101 dret
1366 //    0100 eret
1367 //    0010 ret
1368 //    otherwise UNDEFINED
1369 class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1370                     string operands, list<dag> pattern>
1371     : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1372   let Inst{31-25} = 0b1101011;
1373   let Inst{24-21} = opc;
1374   let Inst{20-16} = 0b11111;
1375   let Inst{15-10} = 0b000000;
1376   let Inst{4-0}   = 0b00000;
1377 }
1378
1379 class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1380     : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1381   bits<5> Rn;
1382   let Inst{9-5} = Rn;
1383 }
1384
1385 let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1386 class SpecialReturn<bits<4> opc, string asm>
1387     : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1388   let Inst{9-5} = 0b11111;
1389 }
1390
1391 let mayLoad = 1 in
1392 class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
1393   : I<(outs RC:$Rt), (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]", "", []>,
1394   Sched<[]> {
1395   bits<5> Rn;
1396   bits<5> Rt;
1397   let Inst{31-30} = sz;
1398   let Inst{29-10} = 0b11100010111111110000;
1399   let Inst{9-5} = Rn;
1400   let Inst{4-0} = Rt;
1401 }
1402
1403 class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
1404                list<dag> pattern>
1405   : I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
1406   let Inst{31-25} = 0b1101011;
1407   let Inst{20-11} = 0b1111100001;
1408   let Inst{10} = M;
1409   let Inst{4-0} = 0b11111;
1410 }
1411
1412 class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
1413   : AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
1414   bits<5> Rn;
1415   bits<5> Rm;
1416   let Inst{24-22} = 0b100;
1417   let Inst{21} = op;
1418   let Inst{9-5} = Rn;
1419   let Inst{4-0} = Rm;
1420 }
1421
1422 class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
1423   : AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
1424   bits<5> Rn;
1425   let Inst{24} = 0;
1426   let Inst{23-21} = opc;
1427   let Inst{9-5} = Rn;
1428 }
1429
1430 class AuthReturn<bits<3> op, bits<1> M, string asm>
1431   : AuthBase<M, (outs), (ins), asm, "", []> {
1432   let Inst{24} = 0;
1433   let Inst{23-21} = op;
1434   let Inst{9-0} = 0b1111111111;
1435 }
1436
1437 let mayLoad = 1 in
1438 class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
1439                    string operands, string cstr, Operand opr>
1440   : I<oops, iops, asm, operands, cstr, []>, Sched<[]> {
1441   bits<10> offset;
1442   bits<5> Rn;
1443   bits<5> Rt;
1444   let Inst{31-24} = 0b11111000;
1445   let Inst{23} = M;
1446   let Inst{22} = offset{9};
1447   let Inst{21} = 1;
1448   let Inst{20-12} = offset{8-0};
1449   let Inst{11} = W;
1450   let Inst{10} = 1;
1451   let Inst{9-5} = Rn;
1452   let Inst{4-0} = Rt;
1453 }
1454
1455 multiclass AuthLoad<bit M, string asm, Operand opr> {
1456   def indexed   : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
1457                                (ins GPR64sp:$Rn, opr:$offset),
1458                                asm, "\t$Rt, [$Rn, $offset]", "", opr>;
1459   def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
1460                                (ins GPR64sp:$Rn, opr:$offset),
1461                                asm, "\t$Rt, [$Rn, $offset]!",
1462                                "$Rn = $wback,@earlyclobber $wback", opr>;
1463
1464   def : InstAlias<asm # "\t$Rt, [$Rn]",
1465                   (!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
1466 }
1467
1468 //---
1469 // Conditional branch instruction.
1470 //---
1471
1472 // Condition code.
1473 // 4-bit immediate. Pretty-printed as <cc>
1474 def ccode : Operand<i32> {
1475   let PrintMethod = "printCondCode";
1476   let ParserMatchClass = CondCode;
1477 }
1478 def inv_ccode : Operand<i32> {
1479   // AL and NV are invalid in the aliases which use inv_ccode
1480   let PrintMethod = "printInverseCondCode";
1481   let ParserMatchClass = CondCode;
1482   let MCOperandPredicate = [{
1483     return MCOp.isImm() &&
1484            MCOp.getImm() != AArch64CC::AL &&
1485            MCOp.getImm() != AArch64CC::NV;
1486   }];
1487 }
1488
1489 // Conditional branch target. 19-bit immediate. The low two bits of the target
1490 // offset are implied zero and so are not part of the immediate.
1491 def am_brcond : Operand<OtherVT> {
1492   let EncoderMethod = "getCondBranchTargetOpValue";
1493   let DecoderMethod = "DecodePCRelLabel19";
1494   let PrintMethod = "printAlignedLabel";
1495   let ParserMatchClass = PCRelLabel19Operand;
1496   let OperandType = "OPERAND_PCREL";
1497 }
1498
1499 class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target),
1500                      "b", ".$cond\t$target", "",
1501                      [(AArch64brcond bb:$target, imm:$cond, NZCV)]>,
1502                    Sched<[WriteBr]> {
1503   let isBranch = 1;
1504   let isTerminator = 1;
1505   let Uses = [NZCV];
1506
1507   bits<4> cond;
1508   bits<19> target;
1509   let Inst{31-24} = 0b01010100;
1510   let Inst{23-5} = target;
1511   let Inst{4} = 0;
1512   let Inst{3-0} = cond;
1513 }
1514
1515 //---
1516 // Compare-and-branch instructions.
1517 //---
1518 class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1519     : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1520          asm, "\t$Rt, $target", "",
1521          [(node regtype:$Rt, bb:$target)]>,
1522       Sched<[WriteBr]> {
1523   let isBranch = 1;
1524   let isTerminator = 1;
1525
1526   bits<5> Rt;
1527   bits<19> target;
1528   let Inst{30-25} = 0b011010;
1529   let Inst{24}    = op;
1530   let Inst{23-5}  = target;
1531   let Inst{4-0}   = Rt;
1532 }
1533
1534 multiclass CmpBranch<bit op, string asm, SDNode node> {
1535   def W : BaseCmpBranch<GPR32, op, asm, node> {
1536     let Inst{31} = 0;
1537   }
1538   def X : BaseCmpBranch<GPR64, op, asm, node> {
1539     let Inst{31} = 1;
1540   }
1541 }
1542
1543 //---
1544 // Test-bit-and-branch instructions.
1545 //---
1546 // Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1547 // the target offset are implied zero and so are not part of the immediate.
1548 def am_tbrcond : Operand<OtherVT> {
1549   let EncoderMethod = "getTestBranchTargetOpValue";
1550   let PrintMethod = "printAlignedLabel";
1551   let ParserMatchClass = BranchTarget14Operand;
1552   let OperandType = "OPERAND_PCREL";
1553 }
1554
1555 // AsmOperand classes to emit (or not) special diagnostics
1556 def TBZImm0_31Operand : AsmOperandClass {
1557   let Name = "TBZImm0_31";
1558   let PredicateMethod = "isImmInRange<0,31>";
1559   let RenderMethod = "addImmOperands";
1560 }
1561 def TBZImm32_63Operand : AsmOperandClass {
1562   let Name = "Imm32_63";
1563   let PredicateMethod = "isImmInRange<32,63>";
1564   let DiagnosticType = "InvalidImm0_63";
1565   let RenderMethod = "addImmOperands";
1566 }
1567
1568 class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1569   return (((uint32_t)Imm) < 32);
1570 }]> {
1571   let ParserMatchClass = matcher;
1572 }
1573
1574 def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1575 def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1576
1577 def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1578   return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1579 }]> {
1580   let ParserMatchClass = TBZImm32_63Operand;
1581 }
1582
1583 class BaseTestBranch<RegisterClass regtype, Operand immtype,
1584                      bit op, string asm, SDNode node>
1585     : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1586        asm, "\t$Rt, $bit_off, $target", "",
1587        [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1588       Sched<[WriteBr]> {
1589   let isBranch = 1;
1590   let isTerminator = 1;
1591
1592   bits<5> Rt;
1593   bits<6> bit_off;
1594   bits<14> target;
1595
1596   let Inst{30-25} = 0b011011;
1597   let Inst{24}    = op;
1598   let Inst{23-19} = bit_off{4-0};
1599   let Inst{18-5}  = target;
1600   let Inst{4-0}   = Rt;
1601
1602   let DecoderMethod = "DecodeTestAndBranch";
1603 }
1604
1605 multiclass TestBranch<bit op, string asm, SDNode node> {
1606   def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1607     let Inst{31} = 0;
1608   }
1609
1610   def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1611     let Inst{31} = 1;
1612   }
1613
1614   // Alias X-reg with 0-31 imm to W-Reg.
1615   def : InstAlias<asm # "\t$Rd, $imm, $target",
1616                   (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1617                   tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1618   def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1619             (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1620             tbz_imm0_31_diag:$imm, bb:$target)>;
1621 }
1622
1623 //---
1624 // Unconditional branch (immediate) instructions.
1625 //---
1626 def am_b_target : Operand<OtherVT> {
1627   let EncoderMethod = "getBranchTargetOpValue";
1628   let PrintMethod = "printAlignedLabel";
1629   let ParserMatchClass = BranchTarget26Operand;
1630   let OperandType = "OPERAND_PCREL";
1631 }
1632 def am_bl_target : Operand<i64> {
1633   let EncoderMethod = "getBranchTargetOpValue";
1634   let PrintMethod = "printAlignedLabel";
1635   let ParserMatchClass = BranchTarget26Operand;
1636   let OperandType = "OPERAND_PCREL";
1637 }
1638
1639 class BImm<bit op, dag iops, string asm, list<dag> pattern>
1640     : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1641   bits<26> addr;
1642   let Inst{31}    = op;
1643   let Inst{30-26} = 0b00101;
1644   let Inst{25-0}  = addr;
1645
1646   let DecoderMethod = "DecodeUnconditionalBranch";
1647 }
1648
1649 class BranchImm<bit op, string asm, list<dag> pattern>
1650     : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1651 class CallImm<bit op, string asm, list<dag> pattern>
1652     : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1653
1654 //---
1655 // Basic one-operand data processing instructions.
1656 //---
1657
1658 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1659 class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1660                          SDPatternOperator node>
1661   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1662       [(set regtype:$Rd, (node regtype:$Rn))]>,
1663     Sched<[WriteI, ReadI]> {
1664   bits<5> Rd;
1665   bits<5> Rn;
1666
1667   let Inst{30-13} = 0b101101011000000000;
1668   let Inst{12-10} = opc;
1669   let Inst{9-5}   = Rn;
1670   let Inst{4-0}   = Rd;
1671 }
1672
1673 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1674 multiclass OneOperandData<bits<3> opc, string asm,
1675                           SDPatternOperator node = null_frag> {
1676   def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1677     let Inst{31} = 0;
1678   }
1679
1680   def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1681     let Inst{31} = 1;
1682   }
1683 }
1684
1685 class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1686     : BaseOneOperandData<opc, GPR32, asm, node> {
1687   let Inst{31} = 0;
1688 }
1689
1690 class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1691     : BaseOneOperandData<opc, GPR64, asm, node> {
1692   let Inst{31} = 1;
1693 }
1694
1695 class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm>
1696   : I<(outs GPR64:$Rd), (ins GPR64sp:$Rn), asm, "\t$Rd, $Rn", "",
1697       []>,
1698     Sched<[WriteI, ReadI]> {
1699   bits<5> Rd;
1700   bits<5> Rn;
1701   let Inst{31-15} = 0b11011010110000010;
1702   let Inst{14-12} = opcode_prefix;
1703   let Inst{11-10} = opcode;
1704   let Inst{9-5} = Rn;
1705   let Inst{4-0} = Rd;
1706 }
1707
1708 class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm>
1709   : I<(outs GPR64:$Rd), (ins), asm, "\t$Rd", "", []>, Sched<[]> {
1710   bits<5> Rd;
1711   let Inst{31-15} = 0b11011010110000010;
1712   let Inst{14-12} = opcode_prefix;
1713   let Inst{11-10} = opcode;
1714   let Inst{9-5} = 0b11111;
1715   let Inst{4-0} = Rd;
1716 }
1717
1718 class SignAuthTwoOperand<bits<4> opc, string asm,
1719                          SDPatternOperator OpNode>
1720   : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
1721       asm, "\t$Rd, $Rn, $Rm", "",
1722       [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
1723     Sched<[WriteI, ReadI, ReadI]> {
1724   bits<5> Rd;
1725   bits<5> Rn;
1726   bits<5> Rm;
1727   let Inst{31-21} = 0b10011010110;
1728   let Inst{20-16} = Rm;
1729   let Inst{15-14} = 0b00;
1730   let Inst{13-10} = opc;
1731   let Inst{9-5}   = Rn;
1732   let Inst{4-0}   = Rd;
1733 }
1734
1735 // Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions
1736 class BaseFlagManipulation<bit sf, bit sz, dag iops, string asm, string ops>
1737     : I<(outs), iops, asm, ops, "", []>,
1738       Sched<[WriteI, ReadI, ReadI]> {
1739   let Uses = [NZCV];
1740   bits<5> Rn;
1741   let Inst{31}    = sf;
1742   let Inst{30-15} = 0b0111010000000000;
1743   let Inst{14}    = sz;
1744   let Inst{13-10} = 0b0010;
1745   let Inst{9-5}   = Rn;
1746   let Inst{4-0}   = 0b01101;
1747 }
1748
1749 class FlagRotate<dag iops, string asm, string ops>
1750     : BaseFlagManipulation<0b1, 0b0, iops, asm, ops> {
1751   bits<6> imm;
1752   bits<4> mask;
1753   let Inst{20-15} = imm;
1754   let Inst{13-10} = 0b0001;
1755   let Inst{4}     = 0b0;
1756   let Inst{3-0}   = mask;
1757 }
1758
1759 //---
1760 // Basic two-operand data processing instructions.
1761 //---
1762 class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1763                           list<dag> pattern>
1764     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1765         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1766       Sched<[WriteI, ReadI, ReadI]> {
1767   let Uses = [NZCV];
1768   bits<5> Rd;
1769   bits<5> Rn;
1770   bits<5> Rm;
1771   let Inst{30}    = isSub;
1772   let Inst{28-21} = 0b11010000;
1773   let Inst{20-16} = Rm;
1774   let Inst{15-10} = 0;
1775   let Inst{9-5}   = Rn;
1776   let Inst{4-0}   = Rd;
1777 }
1778
1779 class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1780                       SDNode OpNode>
1781     : BaseBaseAddSubCarry<isSub, regtype, asm,
1782         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
1783
1784 class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1785                               SDNode OpNode>
1786     : BaseBaseAddSubCarry<isSub, regtype, asm,
1787         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
1788          (implicit NZCV)]> {
1789   let Defs = [NZCV];
1790 }
1791
1792 multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1793                        SDNode OpNode, SDNode OpNode_setflags> {
1794   def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1795     let Inst{31} = 0;
1796     let Inst{29} = 0;
1797   }
1798   def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1799     let Inst{31} = 1;
1800     let Inst{29} = 0;
1801   }
1802
1803   // Sets flags.
1804   def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1805                                     OpNode_setflags> {
1806     let Inst{31} = 0;
1807     let Inst{29} = 1;
1808   }
1809   def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1810                                     OpNode_setflags> {
1811     let Inst{31} = 1;
1812     let Inst{29} = 1;
1813   }
1814 }
1815
1816 class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1817                      SDPatternOperator OpNode,
1818                      RegisterClass in1regtype = regtype,
1819                      RegisterClass in2regtype = regtype>
1820   : I<(outs regtype:$Rd), (ins in1regtype:$Rn, in2regtype:$Rm),
1821       asm, "\t$Rd, $Rn, $Rm", "",
1822       [(set regtype:$Rd, (OpNode in1regtype:$Rn, in2regtype:$Rm))]> {
1823   bits<5> Rd;
1824   bits<5> Rn;
1825   bits<5> Rm;
1826   let Inst{30-21} = 0b0011010110;
1827   let Inst{20-16} = Rm;
1828   let Inst{15-14} = 0b00;
1829   let Inst{13-10} = opc;
1830   let Inst{9-5}   = Rn;
1831   let Inst{4-0}   = Rd;
1832 }
1833
1834 class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1835               SDPatternOperator OpNode>
1836     : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1837   let Inst{10}    = isSigned;
1838 }
1839
1840 multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1841   def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1842            Sched<[WriteID32, ReadID, ReadID]> {
1843     let Inst{31} = 0;
1844   }
1845   def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1846            Sched<[WriteID64, ReadID, ReadID]> {
1847     let Inst{31} = 1;
1848   }
1849 }
1850
1851 class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1852                 SDPatternOperator OpNode = null_frag>
1853   : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1854     Sched<[WriteIS, ReadI]> {
1855   let Inst{11-10} = shift_type;
1856 }
1857
1858 multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
1859   def Wr : BaseShift<shift_type, GPR32, asm> {
1860     let Inst{31} = 0;
1861   }
1862
1863   def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1864     let Inst{31} = 1;
1865   }
1866
1867   def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1868             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1869                                              (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1870
1871   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1872             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1873
1874   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1875             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1876
1877   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1878             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1879
1880   def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (sext GPR32:$Rm)))),
1881             (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
1882                 (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
1883
1884   def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (zext GPR32:$Rm)))),
1885             (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
1886                 (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
1887 }
1888
1889 class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1890     : InstAlias<asm#"\t$dst, $src1, $src2",
1891                 (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
1892
1893 class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1894                        RegisterClass addtype, string asm,
1895                        list<dag> pattern>
1896   : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1897       asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1898   bits<5> Rd;
1899   bits<5> Rn;
1900   bits<5> Rm;
1901   bits<5> Ra;
1902   let Inst{30-24} = 0b0011011;
1903   let Inst{23-21} = opc;
1904   let Inst{20-16} = Rm;
1905   let Inst{15}    = isSub;
1906   let Inst{14-10} = Ra;
1907   let Inst{9-5}   = Rn;
1908   let Inst{4-0}   = Rd;
1909 }
1910
1911 multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1912   // MADD/MSUB generation is decided by MachineCombiner.cpp
1913   def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1914       [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>,
1915       Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1916     let Inst{31} = 0;
1917   }
1918
1919   def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1920       [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>,
1921       Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
1922     let Inst{31} = 1;
1923   }
1924 }
1925
1926 class WideMulAccum<bit isSub, bits<3> opc, string asm,
1927                    SDNode AccNode, SDNode ExtNode>
1928   : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1929     [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1930                             (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1931     Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1932   let Inst{31} = 1;
1933 }
1934
1935 class MulHi<bits<3> opc, string asm, SDNode OpNode>
1936   : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1937       asm, "\t$Rd, $Rn, $Rm", "",
1938       [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1939     Sched<[WriteIM64, ReadIM, ReadIM]> {
1940   bits<5> Rd;
1941   bits<5> Rn;
1942   bits<5> Rm;
1943   let Inst{31-24} = 0b10011011;
1944   let Inst{23-21} = opc;
1945   let Inst{20-16} = Rm;
1946   let Inst{15}    = 0;
1947   let Inst{9-5}   = Rn;
1948   let Inst{4-0}   = Rd;
1949
1950   // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
1951   // (i.e. all bits 1) but is ignored by the processor.
1952   let PostEncoderMethod = "fixMulHigh";
1953 }
1954
1955 class MulAccumWAlias<string asm, Instruction inst>
1956     : InstAlias<asm#"\t$dst, $src1, $src2",
1957                 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1958 class MulAccumXAlias<string asm, Instruction inst>
1959     : InstAlias<asm#"\t$dst, $src1, $src2",
1960                 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1961 class WideMulAccumAlias<string asm, Instruction inst>
1962     : InstAlias<asm#"\t$dst, $src1, $src2",
1963                 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1964
1965 class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1966               SDPatternOperator OpNode, string asm>
1967   : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1968       asm, "\t$Rd, $Rn, $Rm", "",
1969       [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1970     Sched<[WriteISReg, ReadI, ReadISReg]> {
1971   bits<5> Rd;
1972   bits<5> Rn;
1973   bits<5> Rm;
1974
1975   let Inst{31} = sf;
1976   let Inst{30-21} = 0b0011010110;
1977   let Inst{20-16} = Rm;
1978   let Inst{15-13} = 0b010;
1979   let Inst{12} = C;
1980   let Inst{11-10} = sz;
1981   let Inst{9-5} = Rn;
1982   let Inst{4-0} = Rd;
1983   let Predicates = [HasCRC];
1984 }
1985
1986 //---
1987 // Address generation.
1988 //---
1989
1990 class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1991     : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1992         pattern>,
1993       Sched<[WriteI]> {
1994   bits<5>  Xd;
1995   bits<21> label;
1996   let Inst{31}    = page;
1997   let Inst{30-29} = label{1-0};
1998   let Inst{28-24} = 0b10000;
1999   let Inst{23-5}  = label{20-2};
2000   let Inst{4-0}   = Xd;
2001
2002   let DecoderMethod = "DecodeAdrInstruction";
2003 }
2004
2005 //---
2006 // Move immediate.
2007 //---
2008
2009 def movimm32_imm : Operand<i32> {
2010   let ParserMatchClass = AsmImmRange<0, 65535>;
2011   let EncoderMethod = "getMoveWideImmOpValue";
2012   let PrintMethod = "printImm";
2013 }
2014 def movimm32_shift : Operand<i32> {
2015   let PrintMethod = "printShifter";
2016   let ParserMatchClass = MovImm32ShifterOperand;
2017 }
2018 def movimm64_shift : Operand<i32> {
2019   let PrintMethod = "printShifter";
2020   let ParserMatchClass = MovImm64ShifterOperand;
2021 }
2022
2023 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2024 class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2025                         string asm>
2026   : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
2027        asm, "\t$Rd, $imm$shift", "", []>,
2028     Sched<[WriteImm]> {
2029   bits<5> Rd;
2030   bits<16> imm;
2031   bits<6> shift;
2032   let Inst{30-29} = opc;
2033   let Inst{28-23} = 0b100101;
2034   let Inst{22-21} = shift{5-4};
2035   let Inst{20-5}  = imm;
2036   let Inst{4-0}   = Rd;
2037
2038   let DecoderMethod = "DecodeMoveImmInstruction";
2039 }
2040
2041 multiclass MoveImmediate<bits<2> opc, string asm> {
2042   def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
2043     let Inst{31} = 0;
2044   }
2045
2046   def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
2047     let Inst{31} = 1;
2048   }
2049 }
2050
2051 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2052 class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2053                           string asm>
2054   : I<(outs regtype:$Rd),
2055       (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
2056        asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
2057     Sched<[WriteI, ReadI]> {
2058   bits<5> Rd;
2059   bits<16> imm;
2060   bits<6> shift;
2061   let Inst{30-29} = opc;
2062   let Inst{28-23} = 0b100101;
2063   let Inst{22-21} = shift{5-4};
2064   let Inst{20-5}  = imm;
2065   let Inst{4-0}   = Rd;
2066
2067   let DecoderMethod = "DecodeMoveImmInstruction";
2068 }
2069
2070 multiclass InsertImmediate<bits<2> opc, string asm> {
2071   def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
2072     let Inst{31} = 0;
2073   }
2074
2075   def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
2076     let Inst{31} = 1;
2077   }
2078 }
2079
2080 //---
2081 // Add/Subtract
2082 //---
2083
2084 class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
2085                     string asm_inst, string asm_ops,
2086                     dag inputs, dag pattern>
2087     : I<(outs dstRegtype:$Rd), inputs, asm_inst, asm_ops, "", [pattern]>,
2088       Sched<[WriteI, ReadI]> {
2089   bits<5>  Rd;
2090   bits<5>  Rn;
2091   let Inst{30}    = isSub;
2092   let Inst{29}    = setFlags;
2093   let Inst{28-24} = 0b10001;
2094   let Inst{9-5}   = Rn;
2095   let Inst{4-0}   = Rd;
2096 }
2097
2098 class AddSubImmShift<bit isSub, bit setFlags, RegisterClass dstRegtype,
2099                      RegisterClass srcRegtype, addsub_shifted_imm immtype,
2100                      string asm_inst, SDPatternOperator OpNode>
2101     : BaseAddSubImm<isSub, setFlags, dstRegtype, asm_inst, "\t$Rd, $Rn, $imm",
2102                     (ins srcRegtype:$Rn, immtype:$imm),
2103                     (set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))> {
2104   bits<14> imm;
2105   let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
2106   let Inst{21-10} = imm{11-0};
2107   let DecoderMethod = "DecodeAddSubImmShift";
2108 }
2109
2110 class BaseAddSubRegPseudo<RegisterClass regtype,
2111                           SDPatternOperator OpNode>
2112     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2113              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2114       Sched<[WriteI, ReadI, ReadI]>;
2115
2116 class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
2117                      arith_shifted_reg shifted_regtype, string asm,
2118                      SDPatternOperator OpNode>
2119     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2120         asm, "\t$Rd, $Rn, $Rm", "",
2121         [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
2122       Sched<[WriteISReg, ReadI, ReadISReg]> {
2123   // The operands are in order to match the 'addr' MI operands, so we
2124   // don't need an encoder method and by-name matching. Just use the default
2125   // in-order handling. Since we're using by-order, make sure the names
2126   // do not match.
2127   bits<5> dst;
2128   bits<5> src1;
2129   bits<5> src2;
2130   bits<8> shift;
2131   let Inst{30}    = isSub;
2132   let Inst{29}    = setFlags;
2133   let Inst{28-24} = 0b01011;
2134   let Inst{23-22} = shift{7-6};
2135   let Inst{21}    = 0;
2136   let Inst{20-16} = src2;
2137   let Inst{15-10} = shift{5-0};
2138   let Inst{9-5}   = src1;
2139   let Inst{4-0}   = dst;
2140
2141   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2142 }
2143
2144 class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
2145                      RegisterClass src1Regtype, Operand src2Regtype,
2146                      string asm, SDPatternOperator OpNode>
2147     : I<(outs dstRegtype:$R1),
2148         (ins src1Regtype:$R2, src2Regtype:$R3),
2149         asm, "\t$R1, $R2, $R3", "",
2150         [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
2151       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2152   bits<5> Rd;
2153   bits<5> Rn;
2154   bits<5> Rm;
2155   bits<6> ext;
2156   let Inst{30}    = isSub;
2157   let Inst{29}    = setFlags;
2158   let Inst{28-24} = 0b01011;
2159   let Inst{23-21} = 0b001;
2160   let Inst{20-16} = Rm;
2161   let Inst{15-13} = ext{5-3};
2162   let Inst{12-10} = ext{2-0};
2163   let Inst{9-5}   = Rn;
2164   let Inst{4-0}   = Rd;
2165
2166   let DecoderMethod = "DecodeAddSubERegInstruction";
2167 }
2168
2169 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2170 class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
2171                        RegisterClass src1Regtype, RegisterClass src2Regtype,
2172                        Operand ext_op, string asm>
2173     : I<(outs dstRegtype:$Rd),
2174         (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
2175         asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
2176       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2177   bits<5> Rd;
2178   bits<5> Rn;
2179   bits<5> Rm;
2180   bits<6> ext;
2181   let Inst{30}    = isSub;
2182   let Inst{29}    = setFlags;
2183   let Inst{28-24} = 0b01011;
2184   let Inst{23-21} = 0b001;
2185   let Inst{20-16} = Rm;
2186   let Inst{15}    = ext{5};
2187   let Inst{12-10} = ext{2-0};
2188   let Inst{9-5}   = Rn;
2189   let Inst{4-0}   = Rd;
2190
2191   let DecoderMethod = "DecodeAddSubERegInstruction";
2192 }
2193
2194 // Aliases for register+register add/subtract.
2195 class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
2196                      RegisterClass src1Regtype, RegisterClass src2Regtype,
2197                      int shiftExt>
2198     : InstAlias<asm#"\t$dst, $src1, $src2",
2199                 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
2200                       shiftExt)>;
2201
2202 multiclass AddSub<bit isSub, string mnemonic, string alias,
2203                   SDPatternOperator OpNode = null_frag> {
2204   let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2205   // Add/Subtract immediate
2206   // Increase the weight of the immediate variant to try to match it before
2207   // the extended register variant.
2208   // We used to match the register variant before the immediate when the
2209   // register argument could be implicitly zero-extended.
2210   let AddedComplexity = 6 in
2211   def Wri  : AddSubImmShift<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
2212                            mnemonic, OpNode> {
2213     let Inst{31} = 0;
2214   }
2215   let AddedComplexity = 6 in
2216   def Xri  : AddSubImmShift<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
2217                            mnemonic, OpNode> {
2218     let Inst{31} = 1;
2219   }
2220
2221   // Add/Subtract register - Only used for CodeGen
2222   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2223   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2224
2225   // Add/Subtract shifted register
2226   def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
2227                            OpNode> {
2228     let Inst{31} = 0;
2229   }
2230   def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
2231                            OpNode> {
2232     let Inst{31} = 1;
2233   }
2234   }
2235
2236   // Add/Subtract extended register
2237   let AddedComplexity = 1, hasSideEffects = 0 in {
2238   def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
2239                            arith_extended_reg32_i32, mnemonic, OpNode> {
2240     let Inst{31} = 0;
2241   }
2242   def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
2243                            arith_extended_reg32to64_i64, mnemonic, OpNode> {
2244     let Inst{31} = 1;
2245   }
2246   }
2247
2248   def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
2249                                arith_extendlsl64, mnemonic> {
2250     // UXTX and SXTX only.
2251     let Inst{14-13} = 0b11;
2252     let Inst{31} = 1;
2253   }
2254
2255   // add Rd, Rb, -imm -> sub Rd, Rn, imm
2256   def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2257                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
2258                       addsub_shifted_imm32_neg:$imm), 0>;
2259   def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2260                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
2261                        addsub_shifted_imm64_neg:$imm), 0>;
2262
2263   // Register/register aliases with no shift when SP is not used.
2264   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2265                        GPR32, GPR32, GPR32, 0>;
2266   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2267                        GPR64, GPR64, GPR64, 0>;
2268
2269   // Register/register aliases with no shift when either the destination or
2270   // first source register is SP.
2271   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2272                        GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
2273   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2274                        GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
2275   def : AddSubRegAlias<mnemonic,
2276                        !cast<Instruction>(NAME#"Xrx64"),
2277                        GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
2278   def : AddSubRegAlias<mnemonic,
2279                        !cast<Instruction>(NAME#"Xrx64"),
2280                        GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
2281 }
2282
2283 multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
2284                    string alias, string cmpAlias> {
2285   let isCompare = 1, Defs = [NZCV] in {
2286   // Add/Subtract immediate
2287   def Wri  : AddSubImmShift<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
2288                            mnemonic, OpNode> {
2289     let Inst{31} = 0;
2290   }
2291   def Xri  : AddSubImmShift<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
2292                            mnemonic, OpNode> {
2293     let Inst{31} = 1;
2294   }
2295
2296   // Add/Subtract register
2297   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2298   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2299
2300   // Add/Subtract shifted register
2301   def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
2302                            OpNode> {
2303     let Inst{31} = 0;
2304   }
2305   def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
2306                            OpNode> {
2307     let Inst{31} = 1;
2308   }
2309
2310   // Add/Subtract extended register
2311   let AddedComplexity = 1 in {
2312   def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
2313                            arith_extended_reg32_i32, mnemonic, OpNode> {
2314     let Inst{31} = 0;
2315   }
2316   def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
2317                            arith_extended_reg32_i64, mnemonic, OpNode> {
2318     let Inst{31} = 1;
2319   }
2320   }
2321
2322   def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
2323                                arith_extendlsl64, mnemonic> {
2324     // UXTX and SXTX only.
2325     let Inst{14-13} = 0b11;
2326     let Inst{31} = 1;
2327   }
2328   } // Defs = [NZCV]
2329
2330   // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
2331   def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2332                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
2333                       addsub_shifted_imm32_neg:$imm), 0>;
2334   def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2335                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
2336                        addsub_shifted_imm64_neg:$imm), 0>;
2337
2338   // Compare aliases
2339   def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2340                   WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
2341   def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2342                   XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
2343   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
2344                   WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2345   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
2346                   XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2347   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
2348                   XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
2349   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
2350                   WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
2351   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
2352                   XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
2353
2354   // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
2355   def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2356                   WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
2357   def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2358                   XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
2359
2360   // Compare shorthands
2361   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
2362                   WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
2363   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
2364                   XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
2365   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
2366                   WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
2367   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
2368                   XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
2369
2370   // Register/register aliases with no shift when SP is not used.
2371   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2372                        GPR32, GPR32, GPR32, 0>;
2373   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2374                        GPR64, GPR64, GPR64, 0>;
2375
2376   // Register/register aliases with no shift when the first source register
2377   // is SP.
2378   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2379                        GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
2380   def : AddSubRegAlias<mnemonic,
2381                        !cast<Instruction>(NAME#"Xrx64"),
2382                        GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
2383 }
2384
2385 class AddSubG<bit isSub, string asm_inst, SDPatternOperator OpNode>
2386       : BaseAddSubImm<
2387           isSub, 0, GPR64sp, asm_inst, "\t$Rd, $Rn, $imm6, $imm4",
2388           (ins GPR64sp:$Rn, uimm6s16:$imm6, imm0_15:$imm4),
2389           (set GPR64sp:$Rd, (OpNode GPR64sp:$Rn, imm0_63:$imm6, imm0_15:$imm4))> {
2390   bits<6> imm6;
2391   bits<4> imm4;
2392   let Inst{31} = 1;
2393   let Inst{23-22} = 0b10;
2394   let Inst{21-16} = imm6;
2395   let Inst{15-14} = 0b00;
2396   let Inst{13-10} = imm4;
2397   let Unpredictable{15-14} = 0b11;
2398 }
2399
2400 class SUBP<bit setsFlags, string asm_instr, SDPatternOperator OpNode>
2401       : BaseTwoOperand<0b0000, GPR64, asm_instr, OpNode, GPR64sp, GPR64sp> {
2402   let Inst{31} = 1;
2403   let Inst{29} = setsFlags;
2404 }
2405
2406 //---
2407 // Extract
2408 //---
2409 def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
2410                                       SDTCisPtrTy<3>]>;
2411 def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
2412
2413 class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
2414                      list<dag> patterns>
2415     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
2416          asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
2417       Sched<[WriteExtr, ReadExtrHi]> {
2418   bits<5> Rd;
2419   bits<5> Rn;
2420   bits<5> Rm;
2421   bits<6> imm;
2422
2423   let Inst{30-23} = 0b00100111;
2424   let Inst{21}    = 0;
2425   let Inst{20-16} = Rm;
2426   let Inst{15-10} = imm;
2427   let Inst{9-5}   = Rn;
2428   let Inst{4-0}   = Rd;
2429 }
2430
2431 multiclass ExtractImm<string asm> {
2432   def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
2433                       [(set GPR32:$Rd,
2434                         (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
2435     let Inst{31} = 0;
2436     let Inst{22} = 0;
2437     // imm<5> must be zero.
2438     let imm{5}   = 0;
2439   }
2440   def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
2441                       [(set GPR64:$Rd,
2442                         (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
2443
2444     let Inst{31} = 1;
2445     let Inst{22} = 1;
2446   }
2447 }
2448
2449 //---
2450 // Bitfield
2451 //---
2452
2453 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2454 class BaseBitfieldImm<bits<2> opc,
2455                       RegisterClass regtype, Operand imm_type, string asm>
2456     : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
2457          asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
2458       Sched<[WriteIS, ReadI]> {
2459   bits<5> Rd;
2460   bits<5> Rn;
2461   bits<6> immr;
2462   bits<6> imms;
2463
2464   let Inst{30-29} = opc;
2465   let Inst{28-23} = 0b100110;
2466   let Inst{21-16} = immr;
2467   let Inst{15-10} = imms;
2468   let Inst{9-5}   = Rn;
2469   let Inst{4-0}   = Rd;
2470 }
2471
2472 multiclass BitfieldImm<bits<2> opc, string asm> {
2473   def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
2474     let Inst{31} = 0;
2475     let Inst{22} = 0;
2476     // imms<5> and immr<5> must be zero, else ReservedValue().
2477     let Inst{21} = 0;
2478     let Inst{15} = 0;
2479   }
2480   def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
2481     let Inst{31} = 1;
2482     let Inst{22} = 1;
2483   }
2484 }
2485
2486 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2487 class BaseBitfieldImmWith2RegArgs<bits<2> opc,
2488                       RegisterClass regtype, Operand imm_type, string asm>
2489     : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
2490                              imm_type:$imms),
2491          asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
2492       Sched<[WriteIS, ReadI]> {
2493   bits<5> Rd;
2494   bits<5> Rn;
2495   bits<6> immr;
2496   bits<6> imms;
2497
2498   let Inst{30-29} = opc;
2499   let Inst{28-23} = 0b100110;
2500   let Inst{21-16} = immr;
2501   let Inst{15-10} = imms;
2502   let Inst{9-5}   = Rn;
2503   let Inst{4-0}   = Rd;
2504 }
2505
2506 multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
2507   def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
2508     let Inst{31} = 0;
2509     let Inst{22} = 0;
2510     // imms<5> and immr<5> must be zero, else ReservedValue().
2511     let Inst{21} = 0;
2512     let Inst{15} = 0;
2513   }
2514   def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
2515     let Inst{31} = 1;
2516     let Inst{22} = 1;
2517   }
2518 }
2519
2520 //---
2521 // Logical
2522 //---
2523
2524 // Logical (immediate)
2525 class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
2526                      RegisterClass sregtype, Operand imm_type, string asm,
2527                      list<dag> pattern>
2528     : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
2529          asm, "\t$Rd, $Rn, $imm", "", pattern>,
2530       Sched<[WriteI, ReadI]> {
2531   bits<5>  Rd;
2532   bits<5>  Rn;
2533   bits<13> imm;
2534   let Inst{30-29} = opc;
2535   let Inst{28-23} = 0b100100;
2536   let Inst{22}    = imm{12};
2537   let Inst{21-16} = imm{11-6};
2538   let Inst{15-10} = imm{5-0};
2539   let Inst{9-5}   = Rn;
2540   let Inst{4-0}   = Rd;
2541
2542   let DecoderMethod = "DecodeLogicalImmInstruction";
2543 }
2544
2545 // Logical (shifted register)
2546 class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
2547                       logical_shifted_reg shifted_regtype, string asm,
2548                       list<dag> pattern>
2549     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2550         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2551       Sched<[WriteISReg, ReadI, ReadISReg]> {
2552   // The operands are in order to match the 'addr' MI operands, so we
2553   // don't need an encoder method and by-name matching. Just use the default
2554   // in-order handling. Since we're using by-order, make sure the names
2555   // do not match.
2556   bits<5> dst;
2557   bits<5> src1;
2558   bits<5> src2;
2559   bits<8> shift;
2560   let Inst{30-29} = opc;
2561   let Inst{28-24} = 0b01010;
2562   let Inst{23-22} = shift{7-6};
2563   let Inst{21}    = N;
2564   let Inst{20-16} = src2;
2565   let Inst{15-10} = shift{5-0};
2566   let Inst{9-5}   = src1;
2567   let Inst{4-0}   = dst;
2568
2569   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2570 }
2571
2572 // Aliases for register+register logical instructions.
2573 class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2574     : InstAlias<asm#"\t$dst, $src1, $src2",
2575                 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2576
2577 multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2578                       string Alias> {
2579   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2580   def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2581                            [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2582                                                logical_imm32:$imm))]> {
2583     let Inst{31} = 0;
2584     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2585   }
2586   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2587   def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2588                            [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2589                                                logical_imm64:$imm))]> {
2590     let Inst{31} = 1;
2591   }
2592
2593   def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2594                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2595                       logical_imm32_not:$imm), 0>;
2596   def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2597                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2598                        logical_imm64_not:$imm), 0>;
2599 }
2600
2601 multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2602                        string Alias> {
2603   let isCompare = 1, Defs = [NZCV] in {
2604   def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2605       [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2606     let Inst{31} = 0;
2607     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2608   }
2609   def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2610       [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2611     let Inst{31} = 1;
2612   }
2613   } // end Defs = [NZCV]
2614
2615   def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2616                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2617                       logical_imm32_not:$imm), 0>;
2618   def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2619                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2620                        logical_imm64_not:$imm), 0>;
2621 }
2622
2623 class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2624     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2625              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2626       Sched<[WriteI, ReadI, ReadI]>;
2627
2628 // Split from LogicalImm as not all instructions have both.
2629 multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2630                       SDPatternOperator OpNode> {
2631   let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2632   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2633   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2634   }
2635
2636   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2637                             [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2638                                                  logical_shifted_reg32:$Rm))]> {
2639     let Inst{31} = 0;
2640   }
2641   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2642                             [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2643                                                  logical_shifted_reg64:$Rm))]> {
2644     let Inst{31} = 1;
2645   }
2646
2647   def : LogicalRegAlias<mnemonic,
2648                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2649   def : LogicalRegAlias<mnemonic,
2650                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2651 }
2652
2653 // Split from LogicalReg to allow setting NZCV Defs
2654 multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2655                        SDPatternOperator OpNode = null_frag> {
2656   let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2657   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2658   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2659
2660   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2661             [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2662     let Inst{31} = 0;
2663   }
2664   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2665             [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2666     let Inst{31} = 1;
2667   }
2668   } // Defs = [NZCV]
2669
2670   def : LogicalRegAlias<mnemonic,
2671                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2672   def : LogicalRegAlias<mnemonic,
2673                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2674 }
2675
2676 //---
2677 // Conditionally set flags
2678 //---
2679
2680 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2681 class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
2682                             string mnemonic, SDNode OpNode>
2683     : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
2684          mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
2685          [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
2686                              (i32 imm:$cond), NZCV))]>,
2687       Sched<[WriteI, ReadI]> {
2688   let Uses = [NZCV];
2689   let Defs = [NZCV];
2690
2691   bits<5> Rn;
2692   bits<5> imm;
2693   bits<4> nzcv;
2694   bits<4> cond;
2695
2696   let Inst{30}    = op;
2697   let Inst{29-21} = 0b111010010;
2698   let Inst{20-16} = imm;
2699   let Inst{15-12} = cond;
2700   let Inst{11-10} = 0b10;
2701   let Inst{9-5}   = Rn;
2702   let Inst{4}     = 0b0;
2703   let Inst{3-0}   = nzcv;
2704 }
2705
2706 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2707 class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
2708                             SDNode OpNode>
2709     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
2710          mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
2711          [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
2712                              (i32 imm:$cond), NZCV))]>,
2713       Sched<[WriteI, ReadI, ReadI]> {
2714   let Uses = [NZCV];
2715   let Defs = [NZCV];
2716
2717   bits<5> Rn;
2718   bits<5> Rm;
2719   bits<4> nzcv;
2720   bits<4> cond;
2721
2722   let Inst{30}    = op;
2723   let Inst{29-21} = 0b111010010;
2724   let Inst{20-16} = Rm;
2725   let Inst{15-12} = cond;
2726   let Inst{11-10} = 0b00;
2727   let Inst{9-5}   = Rn;
2728   let Inst{4}     = 0b0;
2729   let Inst{3-0}   = nzcv;
2730 }
2731
2732 multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
2733   // immediate operand variants
2734   def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
2735     let Inst{31} = 0;
2736   }
2737   def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
2738     let Inst{31} = 1;
2739   }
2740   // register operand variants
2741   def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
2742     let Inst{31} = 0;
2743   }
2744   def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
2745     let Inst{31} = 1;
2746   }
2747 }
2748
2749 //---
2750 // Conditional select
2751 //---
2752
2753 class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
2754     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2755          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2756          [(set regtype:$Rd,
2757                (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
2758       Sched<[WriteI, ReadI, ReadI]> {
2759   let Uses = [NZCV];
2760
2761   bits<5> Rd;
2762   bits<5> Rn;
2763   bits<5> Rm;
2764   bits<4> cond;
2765
2766   let Inst{30}    = op;
2767   let Inst{29-21} = 0b011010100;
2768   let Inst{20-16} = Rm;
2769   let Inst{15-12} = cond;
2770   let Inst{11-10} = op2;
2771   let Inst{9-5}   = Rn;
2772   let Inst{4-0}   = Rd;
2773 }
2774
2775 multiclass CondSelect<bit op, bits<2> op2, string asm> {
2776   def Wr : BaseCondSelect<op, op2, GPR32, asm> {
2777     let Inst{31} = 0;
2778   }
2779   def Xr : BaseCondSelect<op, op2, GPR64, asm> {
2780     let Inst{31} = 1;
2781   }
2782 }
2783
2784 class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
2785                        PatFrag frag>
2786     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2787          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2788          [(set regtype:$Rd,
2789                (AArch64csel regtype:$Rn, (frag regtype:$Rm),
2790                (i32 imm:$cond), NZCV))]>,
2791       Sched<[WriteI, ReadI, ReadI]> {
2792   let Uses = [NZCV];
2793
2794   bits<5> Rd;
2795   bits<5> Rn;
2796   bits<5> Rm;
2797   bits<4> cond;
2798
2799   let Inst{30}    = op;
2800   let Inst{29-21} = 0b011010100;
2801   let Inst{20-16} = Rm;
2802   let Inst{15-12} = cond;
2803   let Inst{11-10} = op2;
2804   let Inst{9-5}   = Rn;
2805   let Inst{4-0}   = Rd;
2806 }
2807
2808 def inv_cond_XFORM : SDNodeXForm<imm, [{
2809   AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
2810   return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
2811                                    MVT::i32);
2812 }]>;
2813
2814 multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
2815   def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
2816     let Inst{31} = 0;
2817   }
2818   def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
2819     let Inst{31} = 1;
2820   }
2821
2822   def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
2823             (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
2824                                            (inv_cond_XFORM imm:$cond))>;
2825
2826   def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
2827             (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
2828                                            (inv_cond_XFORM imm:$cond))>;
2829 }
2830
2831 //---
2832 // Special Mask Value
2833 //---
2834 def maski8_or_more : Operand<i32>,
2835   ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
2836 }
2837 def maski16_or_more : Operand<i32>,
2838   ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
2839 }
2840
2841
2842 //---
2843 // Load/store
2844 //---
2845
2846 // (unsigned immediate)
2847 // Indexed for 8-bit registers. offset is in range [0,4095].
2848 def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>;
2849 def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>;
2850 def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
2851 def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
2852 def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
2853
2854 def gi_am_indexed8 :
2855     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
2856     GIComplexPatternEquiv<am_indexed8>;
2857 def gi_am_indexed16 :
2858     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
2859     GIComplexPatternEquiv<am_indexed16>;
2860 def gi_am_indexed32 :
2861     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
2862     GIComplexPatternEquiv<am_indexed32>;
2863 def gi_am_indexed64 :
2864     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
2865     GIComplexPatternEquiv<am_indexed64>;
2866 def gi_am_indexed128 :
2867     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
2868     GIComplexPatternEquiv<am_indexed128>;
2869
2870 class UImm12OffsetOperand<int Scale> : AsmOperandClass {
2871   let Name = "UImm12Offset" # Scale;
2872   let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
2873   let PredicateMethod = "isUImm12Offset<" # Scale # ">";
2874   let DiagnosticType = "InvalidMemoryIndexed" # Scale;
2875 }
2876
2877 def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
2878 def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
2879 def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
2880 def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
2881 def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
2882
2883 class uimm12_scaled<int Scale> : Operand<i64> {
2884   let ParserMatchClass
2885    = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
2886   let EncoderMethod
2887    = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
2888   let PrintMethod = "printUImm12Offset<" # Scale # ">";
2889 }
2890
2891 def uimm12s1 : uimm12_scaled<1>;
2892 def uimm12s2 : uimm12_scaled<2>;
2893 def uimm12s4 : uimm12_scaled<4>;
2894 def uimm12s8 : uimm12_scaled<8>;
2895 def uimm12s16 : uimm12_scaled<16>;
2896
2897 class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2898                       string asm, list<dag> pattern>
2899     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2900   bits<5> Rt;
2901
2902   bits<5> Rn;
2903   bits<12> offset;
2904
2905   let Inst{31-30} = sz;
2906   let Inst{29-27} = 0b111;
2907   let Inst{26}    = V;
2908   let Inst{25-24} = 0b01;
2909   let Inst{23-22} = opc;
2910   let Inst{21-10} = offset;
2911   let Inst{9-5}   = Rn;
2912   let Inst{4-0}   = Rt;
2913
2914   let DecoderMethod = "DecodeUnsignedLdStInstruction";
2915 }
2916
2917 multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
2918                   Operand indextype, string asm, list<dag> pattern> {
2919   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2920   def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
2921                            (ins GPR64sp:$Rn, indextype:$offset),
2922                            asm, pattern>,
2923            Sched<[WriteLD]>;
2924
2925   def : InstAlias<asm # "\t$Rt, [$Rn]",
2926                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2927 }
2928
2929 multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
2930              Operand indextype, string asm, list<dag> pattern> {
2931   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2932   def ui : BaseLoadStoreUI<sz, V, opc, (outs),
2933                            (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
2934                            asm, pattern>,
2935            Sched<[WriteST]>;
2936
2937   def : InstAlias<asm # "\t$Rt, [$Rn]",
2938                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2939 }
2940
2941 // Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
2942 // substitute zero-registers automatically.
2943 //
2944 // TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
2945 //       into StoreUI.
2946 multiclass StoreUIz<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
2947              Operand indextype, string asm, list<dag> pattern> {
2948   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2949   def ui : BaseLoadStoreUI<sz, V, opc, (outs),
2950                            (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
2951                            asm, pattern>,
2952            Sched<[WriteST]>;
2953
2954   def : InstAlias<asm # "\t$Rt, [$Rn]",
2955                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2956 }
2957
2958 def PrefetchOperand : AsmOperandClass {
2959   let Name = "Prefetch";
2960   let ParserMethod = "tryParsePrefetch";
2961 }
2962 def prfop : Operand<i32> {
2963   let PrintMethod = "printPrefetchOp";
2964   let ParserMatchClass = PrefetchOperand;
2965 }
2966
2967 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2968 class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2969     : BaseLoadStoreUI<sz, V, opc,
2970                       (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
2971                       asm, pat>,
2972       Sched<[WriteLD]>;
2973
2974 //---
2975 // Load literal
2976 //---
2977
2978 // Load literal address: 19-bit immediate. The low two bits of the target
2979 // offset are implied zero and so are not part of the immediate.
2980 def am_ldrlit : Operand<iPTR> {
2981   let EncoderMethod = "getLoadLiteralOpValue";
2982   let DecoderMethod = "DecodePCRelLabel19";
2983   let PrintMethod = "printAlignedLabel";
2984   let ParserMatchClass = PCRelLabel19Operand;
2985   let OperandType = "OPERAND_PCREL";
2986 }
2987
2988 let mayLoad = 1, mayStore = 0, hasSideEffects = 0, AddedComplexity = 20 in
2989 class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm, list<dag> pat>
2990     : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
2991         asm, "\t$Rt, $label", "", pat>,
2992       Sched<[WriteLD]> {
2993   bits<5> Rt;
2994   bits<19> label;
2995   let Inst{31-30} = opc;
2996   let Inst{29-27} = 0b011;
2997   let Inst{26}    = V;
2998   let Inst{25-24} = 0b00;
2999   let Inst{23-5}  = label;
3000   let Inst{4-0}   = Rt;
3001 }
3002
3003 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3004 class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
3005     : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
3006         asm, "\t$Rt, $label", "", pat>,
3007       Sched<[WriteLD]> {
3008   bits<5> Rt;
3009   bits<19> label;
3010   let Inst{31-30} = opc;
3011   let Inst{29-27} = 0b011;
3012   let Inst{26}    = V;
3013   let Inst{25-24} = 0b00;
3014   let Inst{23-5}  = label;
3015   let Inst{4-0}   = Rt;
3016 }
3017
3018 //---
3019 // Load/store register offset
3020 //---
3021
3022 def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>;
3023 def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>;
3024 def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>;
3025 def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>;
3026 def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>;
3027
3028 def gi_ro_Xindexed8 :
3029     GIComplexOperandMatcher<s64, "selectAddrModeXRO<8>">,
3030     GIComplexPatternEquiv<ro_Xindexed8>;
3031 def gi_ro_Xindexed16 :
3032     GIComplexOperandMatcher<s64, "selectAddrModeXRO<16>">,
3033     GIComplexPatternEquiv<ro_Xindexed16>;
3034 def gi_ro_Xindexed32 :
3035     GIComplexOperandMatcher<s64, "selectAddrModeXRO<32>">,
3036     GIComplexPatternEquiv<ro_Xindexed32>;
3037 def gi_ro_Xindexed64 :
3038     GIComplexOperandMatcher<s64, "selectAddrModeXRO<64>">,
3039     GIComplexPatternEquiv<ro_Xindexed64>;
3040 def gi_ro_Xindexed128 :
3041     GIComplexOperandMatcher<s64, "selectAddrModeXRO<128>">,
3042     GIComplexPatternEquiv<ro_Xindexed128>;
3043
3044 def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>;
3045 def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>;
3046 def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>;
3047 def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>;
3048 def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>;
3049
3050 class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
3051   let Name = "Mem" # Reg # "Extend" # Width;
3052   let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
3053   let RenderMethod = "addMemExtendOperands";
3054   let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
3055 }
3056
3057 def MemWExtend8Operand : MemExtendOperand<"W", 8> {
3058   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3059   // the trivial shift.
3060   let RenderMethod = "addMemExtend8Operands";
3061 }
3062 def MemWExtend16Operand : MemExtendOperand<"W", 16>;
3063 def MemWExtend32Operand : MemExtendOperand<"W", 32>;
3064 def MemWExtend64Operand : MemExtendOperand<"W", 64>;
3065 def MemWExtend128Operand : MemExtendOperand<"W", 128>;
3066
3067 def MemXExtend8Operand : MemExtendOperand<"X", 8> {
3068   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3069   // the trivial shift.
3070   let RenderMethod = "addMemExtend8Operands";
3071 }
3072 def MemXExtend16Operand : MemExtendOperand<"X", 16>;
3073 def MemXExtend32Operand : MemExtendOperand<"X", 32>;
3074 def MemXExtend64Operand : MemExtendOperand<"X", 64>;
3075 def MemXExtend128Operand : MemExtendOperand<"X", 128>;
3076
3077 class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
3078         : Operand<i32> {
3079   let ParserMatchClass = ParserClass;
3080   let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
3081   let DecoderMethod = "DecodeMemExtend";
3082   let EncoderMethod = "getMemExtendOpValue";
3083   let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
3084 }
3085
3086 def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
3087 def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
3088 def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
3089 def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
3090 def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
3091
3092 def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
3093 def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
3094 def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
3095 def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
3096 def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
3097
3098 class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
3099                   Operand wextend, Operand xextend>  {
3100   // CodeGen-level pattern covering the entire addressing mode.
3101   ComplexPattern Wpat = windex;
3102   ComplexPattern Xpat = xindex;
3103
3104   // Asm-level Operand covering the valid "uxtw #3" style syntax.
3105   Operand Wext = wextend;
3106   Operand Xext = xextend;
3107 }
3108
3109 def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
3110 def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
3111 def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
3112 def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
3113 def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
3114                        ro_Xextend128>;
3115
3116 class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3117                       string asm, dag ins, dag outs, list<dag> pat>
3118     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3119   bits<5> Rt;
3120   bits<5> Rn;
3121   bits<5> Rm;
3122   bits<2> extend;
3123   let Inst{31-30} = sz;
3124   let Inst{29-27} = 0b111;
3125   let Inst{26}    = V;
3126   let Inst{25-24} = 0b00;
3127   let Inst{23-22} = opc;
3128   let Inst{21}    = 1;
3129   let Inst{20-16} = Rm;
3130   let Inst{15}    = extend{1}; // sign extend Rm?
3131   let Inst{14}    = 1;
3132   let Inst{12}    = extend{0}; // do shift?
3133   let Inst{11-10} = 0b10;
3134   let Inst{9-5}   = Rn;
3135   let Inst{4-0}   = Rt;
3136 }
3137
3138 class ROInstAlias<string asm, RegisterOperand regtype, Instruction INST>
3139   : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
3140               (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3141
3142 multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3143                    string asm, ValueType Ty, SDPatternOperator loadop> {
3144   let AddedComplexity = 10 in
3145   def roW : LoadStore8RO<sz, V, opc, regtype, asm,
3146                  (outs regtype:$Rt),
3147                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3148                  [(set (Ty regtype:$Rt),
3149                        (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3150                                              ro_Wextend8:$extend)))]>,
3151            Sched<[WriteLDIdx, ReadAdrBase]> {
3152     let Inst{13} = 0b0;
3153   }
3154
3155   let AddedComplexity = 10 in
3156   def roX : LoadStore8RO<sz, V, opc, regtype, asm,
3157                  (outs regtype:$Rt),
3158                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3159                  [(set (Ty regtype:$Rt),
3160                        (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3161                                              ro_Xextend8:$extend)))]>,
3162            Sched<[WriteLDIdx, ReadAdrBase]> {
3163     let Inst{13} = 0b1;
3164   }
3165
3166   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3167 }
3168
3169 multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3170                     string asm, ValueType Ty, SDPatternOperator storeop> {
3171   let AddedComplexity = 10 in
3172   def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3173                  (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3174                  [(storeop (Ty regtype:$Rt),
3175                            (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3176                                          ro_Wextend8:$extend))]>,
3177             Sched<[WriteSTIdx, ReadAdrBase]> {
3178     let Inst{13} = 0b0;
3179   }
3180
3181   let AddedComplexity = 10 in
3182   def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3183                  (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3184                  [(storeop (Ty regtype:$Rt),
3185                            (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3186                                          ro_Xextend8:$extend))]>,
3187             Sched<[WriteSTIdx, ReadAdrBase]> {
3188     let Inst{13} = 0b1;
3189   }
3190
3191   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3192 }
3193
3194 class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3195                       string asm, dag ins, dag outs, list<dag> pat>
3196     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3197   bits<5> Rt;
3198   bits<5> Rn;
3199   bits<5> Rm;
3200   bits<2> extend;
3201   let Inst{31-30} = sz;
3202   let Inst{29-27} = 0b111;
3203   let Inst{26}    = V;
3204   let Inst{25-24} = 0b00;
3205   let Inst{23-22} = opc;
3206   let Inst{21}    = 1;
3207   let Inst{20-16} = Rm;
3208   let Inst{15}    = extend{1}; // sign extend Rm?
3209   let Inst{14}    = 1;
3210   let Inst{12}    = extend{0}; // do shift?
3211   let Inst{11-10} = 0b10;
3212   let Inst{9-5}   = Rn;
3213   let Inst{4-0}   = Rt;
3214 }
3215
3216 multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3217                     string asm, ValueType Ty, SDPatternOperator loadop> {
3218   let AddedComplexity = 10 in
3219   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3220                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3221                  [(set (Ty regtype:$Rt),
3222                        (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3223                                               ro_Wextend16:$extend)))]>,
3224             Sched<[WriteLDIdx, ReadAdrBase]> {
3225     let Inst{13} = 0b0;
3226   }
3227
3228   let AddedComplexity = 10 in
3229   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3230                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3231                  [(set (Ty regtype:$Rt),
3232                        (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3233                                              ro_Xextend16:$extend)))]>,
3234             Sched<[WriteLDIdx, ReadAdrBase]> {
3235     let Inst{13} = 0b1;
3236   }
3237
3238   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3239 }
3240
3241 multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3242                      string asm, ValueType Ty, SDPatternOperator storeop> {
3243   let AddedComplexity = 10 in
3244   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3245                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3246                 [(storeop (Ty regtype:$Rt),
3247                           (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3248                                          ro_Wextend16:$extend))]>,
3249            Sched<[WriteSTIdx, ReadAdrBase]> {
3250     let Inst{13} = 0b0;
3251   }
3252
3253   let AddedComplexity = 10 in
3254   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3255                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3256                 [(storeop (Ty regtype:$Rt),
3257                           (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3258                                          ro_Xextend16:$extend))]>,
3259            Sched<[WriteSTIdx, ReadAdrBase]> {
3260     let Inst{13} = 0b1;
3261   }
3262
3263   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3264 }
3265
3266 class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3267                       string asm, dag ins, dag outs, list<dag> pat>
3268     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3269   bits<5> Rt;
3270   bits<5> Rn;
3271   bits<5> Rm;
3272   bits<2> extend;
3273   let Inst{31-30} = sz;
3274   let Inst{29-27} = 0b111;
3275   let Inst{26}    = V;
3276   let Inst{25-24} = 0b00;
3277   let Inst{23-22} = opc;
3278   let Inst{21}    = 1;
3279   let Inst{20-16} = Rm;
3280   let Inst{15}    = extend{1}; // sign extend Rm?
3281   let Inst{14}    = 1;
3282   let Inst{12}    = extend{0}; // do shift?
3283   let Inst{11-10} = 0b10;
3284   let Inst{9-5}   = Rn;
3285   let Inst{4-0}   = Rt;
3286 }
3287
3288 multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3289                     string asm, ValueType Ty, SDPatternOperator loadop> {
3290   let AddedComplexity = 10 in
3291   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3292                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3293                  [(set (Ty regtype:$Rt),
3294                        (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3295                                               ro_Wextend32:$extend)))]>,
3296            Sched<[WriteLDIdx, ReadAdrBase]> {
3297     let Inst{13} = 0b0;
3298   }
3299
3300   let AddedComplexity = 10 in
3301   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3302                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3303                  [(set (Ty regtype:$Rt),
3304                        (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3305                                               ro_Xextend32:$extend)))]>,
3306            Sched<[WriteLDIdx, ReadAdrBase]> {
3307     let Inst{13} = 0b1;
3308   }
3309
3310   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3311 }
3312
3313 multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3314                      string asm, ValueType Ty, SDPatternOperator storeop> {
3315   let AddedComplexity = 10 in
3316   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3317                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3318                 [(storeop (Ty regtype:$Rt),
3319                           (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3320                                          ro_Wextend32:$extend))]>,
3321             Sched<[WriteSTIdx, ReadAdrBase]> {
3322     let Inst{13} = 0b0;
3323   }
3324
3325   let AddedComplexity = 10 in
3326   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3327                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3328                 [(storeop (Ty regtype:$Rt),
3329                           (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3330                                         ro_Xextend32:$extend))]>,
3331             Sched<[WriteSTIdx, ReadAdrBase]> {
3332     let Inst{13} = 0b1;
3333   }
3334
3335   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3336 }
3337
3338 class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3339                       string asm, dag ins, dag outs, list<dag> pat>
3340     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3341   bits<5> Rt;
3342   bits<5> Rn;
3343   bits<5> Rm;
3344   bits<2> extend;
3345   let Inst{31-30} = sz;
3346   let Inst{29-27} = 0b111;
3347   let Inst{26}    = V;
3348   let Inst{25-24} = 0b00;
3349   let Inst{23-22} = opc;
3350   let Inst{21}    = 1;
3351   let Inst{20-16} = Rm;
3352   let Inst{15}    = extend{1}; // sign extend Rm?
3353   let Inst{14}    = 1;
3354   let Inst{12}    = extend{0}; // do shift?
3355   let Inst{11-10} = 0b10;
3356   let Inst{9-5}   = Rn;
3357   let Inst{4-0}   = Rt;
3358 }
3359
3360 multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3361                     string asm, ValueType Ty, SDPatternOperator loadop> {
3362   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3363   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3364                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3365                 [(set (Ty regtype:$Rt),
3366                       (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3367                                              ro_Wextend64:$extend)))]>,
3368            Sched<[WriteLDIdx, ReadAdrBase]> {
3369     let Inst{13} = 0b0;
3370   }
3371
3372   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3373   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3374                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3375                  [(set (Ty regtype:$Rt),
3376                        (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3377                                               ro_Xextend64:$extend)))]>,
3378            Sched<[WriteLDIdx, ReadAdrBase]> {
3379     let Inst{13} = 0b1;
3380   }
3381
3382   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3383 }
3384
3385 multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3386                      string asm, ValueType Ty, SDPatternOperator storeop> {
3387   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3388   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3389                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3390                 [(storeop (Ty regtype:$Rt),
3391                           (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3392                                          ro_Wextend64:$extend))]>,
3393             Sched<[WriteSTIdx, ReadAdrBase]> {
3394     let Inst{13} = 0b0;
3395   }
3396
3397   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3398   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3399                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3400                 [(storeop (Ty regtype:$Rt),
3401                           (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3402                                          ro_Xextend64:$extend))]>,
3403             Sched<[WriteSTIdx, ReadAdrBase]> {
3404     let Inst{13} = 0b1;
3405   }
3406
3407   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3408 }
3409
3410 class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3411                       string asm, dag ins, dag outs, list<dag> pat>
3412     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3413   bits<5> Rt;
3414   bits<5> Rn;
3415   bits<5> Rm;
3416   bits<2> extend;
3417   let Inst{31-30} = sz;
3418   let Inst{29-27} = 0b111;
3419   let Inst{26}    = V;
3420   let Inst{25-24} = 0b00;
3421   let Inst{23-22} = opc;
3422   let Inst{21}    = 1;
3423   let Inst{20-16} = Rm;
3424   let Inst{15}    = extend{1}; // sign extend Rm?
3425   let Inst{14}    = 1;
3426   let Inst{12}    = extend{0}; // do shift?
3427   let Inst{11-10} = 0b10;
3428   let Inst{9-5}   = Rn;
3429   let Inst{4-0}   = Rt;
3430 }
3431
3432 multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3433                      string asm, ValueType Ty, SDPatternOperator loadop> {
3434   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3435   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3436                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3437                  [(set (Ty regtype:$Rt),
3438                        (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
3439                                                ro_Wextend128:$extend)))]>,
3440             Sched<[WriteLDIdx, ReadAdrBase]> {
3441     let Inst{13} = 0b0;
3442   }
3443
3444   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3445   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3446                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3447                  [(set (Ty regtype:$Rt),
3448                        (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
3449                                                ro_Xextend128:$extend)))]>,
3450             Sched<[WriteLDIdx, ReadAdrBase]> {
3451     let Inst{13} = 0b1;
3452   }
3453
3454   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3455 }
3456
3457 multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3458                       string asm, ValueType Ty, SDPatternOperator storeop> {
3459   let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3460   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3461                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3462                 []>,
3463             Sched<[WriteSTIdx, ReadAdrBase]> {
3464     let Inst{13} = 0b0;
3465   }
3466
3467   let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3468   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3469                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3470                 []>,
3471             Sched<[WriteSTIdx, ReadAdrBase]> {
3472     let Inst{13} = 0b1;
3473   }
3474
3475   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3476 }
3477
3478 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3479 class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
3480                      string asm, list<dag> pat>
3481     : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
3482       Sched<[WriteLD]> {
3483   bits<5> Rt;
3484   bits<5> Rn;
3485   bits<5> Rm;
3486   bits<2> extend;
3487   let Inst{31-30} = sz;
3488   let Inst{29-27} = 0b111;
3489   let Inst{26}    = V;
3490   let Inst{25-24} = 0b00;
3491   let Inst{23-22} = opc;
3492   let Inst{21}    = 1;
3493   let Inst{20-16} = Rm;
3494   let Inst{15}    = extend{1}; // sign extend Rm?
3495   let Inst{14}    = 1;
3496   let Inst{12}    = extend{0}; // do shift?
3497   let Inst{11-10} = 0b10;
3498   let Inst{9-5}   = Rn;
3499   let Inst{4-0}   = Rt;
3500 }
3501
3502 multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
3503   def roW : BasePrefetchRO<sz, V, opc, (outs),
3504                 (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3505                 asm, [(AArch64Prefetch imm:$Rt,
3506                                      (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3507                                                     ro_Wextend64:$extend))]> {
3508     let Inst{13} = 0b0;
3509   }
3510
3511   def roX : BasePrefetchRO<sz, V, opc, (outs),
3512                 (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3513                 asm,  [(AArch64Prefetch imm:$Rt,
3514                                       (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3515                                                      ro_Xextend64:$extend))]> {
3516     let Inst{13} = 0b1;
3517   }
3518
3519   def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
3520                (!cast<Instruction>(NAME # "roX") prfop:$Rt,
3521                                                  GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3522 }
3523
3524 //---
3525 // Load/store unscaled immediate
3526 //---
3527
3528 def am_unscaled8 :  ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
3529 def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
3530 def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
3531 def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
3532 def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
3533
3534 def gi_am_unscaled8 :
3535     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
3536     GIComplexPatternEquiv<am_unscaled8>;
3537 def gi_am_unscaled16 :
3538     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
3539     GIComplexPatternEquiv<am_unscaled16>;
3540 def gi_am_unscaled32 :
3541     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
3542     GIComplexPatternEquiv<am_unscaled32>;
3543 def gi_am_unscaled64 :
3544     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
3545     GIComplexPatternEquiv<am_unscaled64>;
3546 def gi_am_unscaled128 :
3547     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
3548     GIComplexPatternEquiv<am_unscaled128>;
3549
3550
3551 class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3552                            string asm, list<dag> pattern>
3553     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3554   bits<5> Rt;
3555   bits<5> Rn;
3556   bits<9> offset;
3557   let Inst{31-30} = sz;
3558   let Inst{29-27} = 0b111;
3559   let Inst{26}    = V;
3560   let Inst{25-24} = 0b00;
3561   let Inst{23-22} = opc;
3562   let Inst{21}    = 0;
3563   let Inst{20-12} = offset;
3564   let Inst{11-10} = 0b00;
3565   let Inst{9-5}   = Rn;
3566   let Inst{4-0}   = Rt;
3567
3568   let DecoderMethod = "DecodeSignedLdStInstruction";
3569 }
3570
3571 // Armv8.4 LDAPR & STLR with Immediate Offset instruction
3572 multiclass BaseLoadUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3573                               RegisterOperand regtype > {
3574   def i : BaseLoadStoreUnscale<sz, 0, opc, (outs regtype:$Rt),
3575                                (ins GPR64sp:$Rn, simm9:$offset), asm, []>,
3576           Sched<[WriteST]> {
3577     let Inst{29} = 0;
3578     let Inst{24} = 1;
3579   }
3580   def : InstAlias<asm # "\t$Rt, [$Rn]",
3581                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3582 }
3583
3584 multiclass BaseStoreUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3585                                RegisterOperand regtype > {
3586   def i : BaseLoadStoreUnscale<sz, 0, opc, (outs),
3587                                (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3588                                asm, []>,
3589           Sched<[WriteST]> {
3590     let Inst{29} = 0;
3591     let Inst{24} = 1;
3592   }
3593   def : InstAlias<asm # "\t$Rt, [$Rn]",
3594                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3595 }
3596
3597 multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3598                    string asm, list<dag> pattern> {
3599   let AddedComplexity = 1 in // try this before LoadUI
3600   def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
3601                                (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
3602           Sched<[WriteLD]>;
3603
3604   def : InstAlias<asm # "\t$Rt, [$Rn]",
3605                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3606 }
3607
3608 multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3609                          string asm, list<dag> pattern> {
3610   let AddedComplexity = 1 in // try this before StoreUI
3611   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3612                                (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3613                                asm, pattern>,
3614           Sched<[WriteST]>;
3615
3616   def : InstAlias<asm # "\t$Rt, [$Rn]",
3617                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3618 }
3619
3620 multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
3621                             list<dag> pat> {
3622   let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3623   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3624                                (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
3625                                asm, pat>,
3626           Sched<[WriteLD]>;
3627
3628   def : InstAlias<asm # "\t$Rt, [$Rn]",
3629                   (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
3630 }
3631
3632 //---
3633 // Load/store unscaled immediate, unprivileged
3634 //---
3635
3636 class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3637                                 dag oops, dag iops, string asm>
3638     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
3639   bits<5> Rt;
3640   bits<5> Rn;
3641   bits<9> offset;
3642   let Inst{31-30} = sz;
3643   let Inst{29-27} = 0b111;
3644   let Inst{26}    = V;
3645   let Inst{25-24} = 0b00;
3646   let Inst{23-22} = opc;
3647   let Inst{21}    = 0;
3648   let Inst{20-12} = offset;
3649   let Inst{11-10} = 0b10;
3650   let Inst{9-5}   = Rn;
3651   let Inst{4-0}   = Rt;
3652
3653   let DecoderMethod = "DecodeSignedLdStInstruction";
3654 }
3655
3656 multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
3657                             RegisterClass regtype, string asm> {
3658   let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
3659   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
3660                                     (ins GPR64sp:$Rn, simm9:$offset), asm>,
3661           Sched<[WriteLD]>;
3662
3663   def : InstAlias<asm # "\t$Rt, [$Rn]",
3664                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3665 }
3666
3667 multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3668                              RegisterClass regtype, string asm> {
3669   let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
3670   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
3671                                  (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3672                                  asm>,
3673           Sched<[WriteST]>;
3674
3675   def : InstAlias<asm # "\t$Rt, [$Rn]",
3676                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3677 }
3678
3679 //---
3680 // Load/store pre-indexed
3681 //---
3682
3683 class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3684                           string asm, string cstr, list<dag> pat>
3685     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
3686   bits<5> Rt;
3687   bits<5> Rn;
3688   bits<9> offset;
3689   let Inst{31-30} = sz;
3690   let Inst{29-27} = 0b111;
3691   let Inst{26}    = V;
3692   let Inst{25-24} = 0;
3693   let Inst{23-22} = opc;
3694   let Inst{21}    = 0;
3695   let Inst{20-12} = offset;
3696   let Inst{11-10} = 0b11;
3697   let Inst{9-5}   = Rn;
3698   let Inst{4-0}   = Rt;
3699
3700   let DecoderMethod = "DecodeSignedLdStInstruction";
3701 }
3702
3703 let hasSideEffects = 0 in {
3704 let mayStore = 0, mayLoad = 1 in
3705 class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3706              string asm>
3707     : BaseLoadStorePreIdx<sz, V, opc,
3708                      (outs GPR64sp:$wback, regtype:$Rt),
3709                      (ins GPR64sp:$Rn, simm9:$offset), asm,
3710                      "$Rn = $wback,@earlyclobber $wback", []>,
3711       Sched<[WriteLD, WriteAdr]>;
3712
3713 let mayStore = 1, mayLoad = 0 in
3714 class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3715                   string asm, SDPatternOperator storeop, ValueType Ty>
3716     : BaseLoadStorePreIdx<sz, V, opc,
3717                       (outs GPR64sp:$wback),
3718                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3719                       asm, "$Rn = $wback,@earlyclobber $wback",
3720       [(set GPR64sp:$wback,
3721             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3722       Sched<[WriteAdr, WriteST]>;
3723 } // hasSideEffects = 0
3724
3725 //---
3726 // Load/store post-indexed
3727 //---
3728
3729 class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3730                           string asm, string cstr, list<dag> pat>
3731     : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
3732   bits<5> Rt;
3733   bits<5> Rn;
3734   bits<9> offset;
3735   let Inst{31-30} = sz;
3736   let Inst{29-27} = 0b111;
3737   let Inst{26}    = V;
3738   let Inst{25-24} = 0b00;
3739   let Inst{23-22} = opc;
3740   let Inst{21}    = 0b0;
3741   let Inst{20-12} = offset;
3742   let Inst{11-10} = 0b01;
3743   let Inst{9-5}   = Rn;
3744   let Inst{4-0}   = Rt;
3745
3746   let DecoderMethod = "DecodeSignedLdStInstruction";
3747 }
3748
3749 let hasSideEffects = 0 in {
3750 let mayStore = 0, mayLoad = 1 in
3751 class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3752              string asm>
3753     : BaseLoadStorePostIdx<sz, V, opc,
3754                       (outs GPR64sp:$wback, regtype:$Rt),
3755                       (ins GPR64sp:$Rn, simm9:$offset),
3756                       asm, "$Rn = $wback,@earlyclobber $wback", []>,
3757       Sched<[WriteLD, WriteAdr]>;
3758
3759 let mayStore = 1, mayLoad = 0 in
3760 class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3761                    string asm, SDPatternOperator storeop, ValueType Ty>
3762     : BaseLoadStorePostIdx<sz, V, opc,
3763                       (outs GPR64sp:$wback),
3764                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3765                        asm, "$Rn = $wback,@earlyclobber $wback",
3766       [(set GPR64sp:$wback,
3767             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3768     Sched<[WriteAdr, WriteST]>;
3769 } // hasSideEffects = 0
3770
3771
3772 //---
3773 // Load/store pair
3774 //---
3775
3776 // (indexed, offset)
3777
3778 class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
3779                               string asm>
3780     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3781   bits<5> Rt;
3782   bits<5> Rt2;
3783   bits<5> Rn;
3784   bits<7> offset;
3785   let Inst{31-30} = opc;
3786   let Inst{29-27} = 0b101;
3787   let Inst{26}    = V;
3788   let Inst{25-23} = 0b010;
3789   let Inst{22}    = L;
3790   let Inst{21-15} = offset;
3791   let Inst{14-10} = Rt2;
3792   let Inst{9-5}   = Rn;
3793   let Inst{4-0}   = Rt;
3794
3795   let DecoderMethod = "DecodePairLdStInstruction";
3796 }
3797
3798 multiclass LoadPairOffset<bits<2> opc, bit V, RegisterOperand regtype,
3799                           Operand indextype, string asm> {
3800   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3801   def i : BaseLoadStorePairOffset<opc, V, 1,
3802                                   (outs regtype:$Rt, regtype:$Rt2),
3803                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
3804           Sched<[WriteLD, WriteLDHi]>;
3805
3806   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3807                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3808                                                   GPR64sp:$Rn, 0)>;
3809 }
3810
3811
3812 multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
3813                            Operand indextype, string asm> {
3814   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
3815   def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
3816                                   (ins regtype:$Rt, regtype:$Rt2,
3817                                        GPR64sp:$Rn, indextype:$offset),
3818                                   asm>,
3819           Sched<[WriteSTP]>;
3820
3821   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3822                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3823                                                   GPR64sp:$Rn, 0)>;
3824 }
3825
3826 // (pre-indexed)
3827 class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3828                               string asm>
3829     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
3830   bits<5> Rt;
3831   bits<5> Rt2;
3832   bits<5> Rn;
3833   bits<7> offset;
3834   let Inst{31-30} = opc;
3835   let Inst{29-27} = 0b101;
3836   let Inst{26}    = V;
3837   let Inst{25-23} = 0b011;
3838   let Inst{22}    = L;
3839   let Inst{21-15} = offset;
3840   let Inst{14-10} = Rt2;
3841   let Inst{9-5}   = Rn;
3842   let Inst{4-0}   = Rt;
3843
3844   let DecoderMethod = "DecodePairLdStInstruction";
3845 }
3846
3847 let hasSideEffects = 0 in {
3848 let mayStore = 0, mayLoad = 1 in
3849 class LoadPairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
3850                      Operand indextype, string asm>
3851     : BaseLoadStorePairPreIdx<opc, V, 1,
3852                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3853                               (ins GPR64sp:$Rn, indextype:$offset), asm>,
3854       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3855
3856 let mayStore = 1, mayLoad = 0 in
3857 class StorePairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
3858                       Operand indextype, string asm>
3859     : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
3860                              (ins regtype:$Rt, regtype:$Rt2,
3861                                   GPR64sp:$Rn, indextype:$offset),
3862                              asm>,
3863       Sched<[WriteAdr, WriteSTP]>;
3864 } // hasSideEffects = 0
3865
3866 // (post-indexed)
3867
3868 class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3869                               string asm>
3870     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
3871   bits<5> Rt;
3872   bits<5> Rt2;
3873   bits<5> Rn;
3874   bits<7> offset;
3875   let Inst{31-30} = opc;
3876   let Inst{29-27} = 0b101;
3877   let Inst{26}    = V;
3878   let Inst{25-23} = 0b001;
3879   let Inst{22}    = L;
3880   let Inst{21-15} = offset;
3881   let Inst{14-10} = Rt2;
3882   let Inst{9-5}   = Rn;
3883   let Inst{4-0}   = Rt;
3884
3885   let DecoderMethod = "DecodePairLdStInstruction";
3886 }
3887
3888 let hasSideEffects = 0 in {
3889 let mayStore = 0, mayLoad = 1 in
3890 class LoadPairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
3891                       Operand idxtype, string asm>
3892     : BaseLoadStorePairPostIdx<opc, V, 1,
3893                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3894                               (ins GPR64sp:$Rn, idxtype:$offset), asm>,
3895       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3896
3897 let mayStore = 1, mayLoad = 0 in
3898 class StorePairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
3899                        Operand idxtype, string asm>
3900     : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
3901                              (ins regtype:$Rt, regtype:$Rt2,
3902                                   GPR64sp:$Rn, idxtype:$offset),
3903                              asm>,
3904       Sched<[WriteAdr, WriteSTP]>;
3905 } // hasSideEffects = 0
3906
3907 //  (no-allocate)
3908
3909 class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
3910                               string asm>
3911     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3912   bits<5> Rt;
3913   bits<5> Rt2;
3914   bits<5> Rn;
3915   bits<7> offset;
3916   let Inst{31-30} = opc;
3917   let Inst{29-27} = 0b101;
3918   let Inst{26}    = V;
3919   let Inst{25-23} = 0b000;
3920   let Inst{22}    = L;
3921   let Inst{21-15} = offset;
3922   let Inst{14-10} = Rt2;
3923   let Inst{9-5}   = Rn;
3924   let Inst{4-0}   = Rt;
3925
3926   let DecoderMethod = "DecodePairLdStInstruction";
3927 }
3928
3929 multiclass LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3930                            Operand indextype, string asm> {
3931   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3932   def i : BaseLoadStorePairNoAlloc<opc, V, 1,
3933                                    (outs regtype:$Rt, regtype:$Rt2),
3934                                    (ins GPR64sp:$Rn, indextype:$offset), asm>,
3935           Sched<[WriteLD, WriteLDHi]>;
3936
3937
3938   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3939                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3940                                                   GPR64sp:$Rn, 0)>;
3941 }
3942
3943 multiclass StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3944                       Operand indextype, string asm> {
3945   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
3946   def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
3947                                    (ins regtype:$Rt, regtype:$Rt2,
3948                                         GPR64sp:$Rn, indextype:$offset),
3949                                    asm>,
3950           Sched<[WriteSTP]>;
3951
3952   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3953                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3954                                                   GPR64sp:$Rn, 0)>;
3955 }
3956
3957 //---
3958 // Load/store exclusive
3959 //---
3960
3961 // True exclusive operations write to and/or read from the system's exclusive
3962 // monitors, which as far as a compiler is concerned can be modelled as a
3963 // random shared memory address. Hence LoadExclusive mayStore.
3964 //
3965 // Since these instructions have the undefined register bits set to 1 in
3966 // their canonical form, we need a post encoder method to set those bits
3967 // to 1 when encoding these instructions. We do this using the
3968 // fixLoadStoreExclusive function. This function has template parameters:
3969 //
3970 // fixLoadStoreExclusive<int hasRs, int hasRt2>
3971 //
3972 // hasRs indicates that the instruction uses the Rs field, so we won't set
3973 // it to 1 (and the same for Rt2). We don't need template parameters for
3974 // the other register fields since Rt and Rn are always used.
3975 //
3976 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
3977 class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3978                              dag oops, dag iops, string asm, string operands>
3979     : I<oops, iops, asm, operands, "", []> {
3980   let Inst{31-30} = sz;
3981   let Inst{29-24} = 0b001000;
3982   let Inst{23}    = o2;
3983   let Inst{22}    = L;
3984   let Inst{21}    = o1;
3985   let Inst{15}    = o0;
3986
3987   let DecoderMethod = "DecodeExclusiveLdStInstruction";
3988 }
3989
3990 // Neither Rs nor Rt2 operands.
3991 class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3992                                dag oops, dag iops, string asm, string operands>
3993     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
3994   bits<5> Rt;
3995   bits<5> Rn;
3996   let Inst{20-16} = 0b11111;
3997   let Unpredictable{20-16} = 0b11111;
3998   let Inst{14-10} = 0b11111;
3999   let Unpredictable{14-10} = 0b11111;
4000   let Inst{9-5} = Rn;
4001   let Inst{4-0} = Rt;
4002
4003   let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
4004 }
4005
4006 // Simple load acquires don't set the exclusive monitor
4007 let mayLoad = 1, mayStore = 0 in
4008 class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4009                   RegisterClass regtype, string asm>
4010     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4011                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4012       Sched<[WriteLD]>;
4013
4014 class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4015                     RegisterClass regtype, string asm>
4016     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4017                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4018       Sched<[WriteLD]>;
4019
4020 class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4021                        RegisterClass regtype, string asm>
4022     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4023                              (outs regtype:$Rt, regtype:$Rt2),
4024                              (ins GPR64sp0:$Rn), asm,
4025                              "\t$Rt, $Rt2, [$Rn]">,
4026       Sched<[WriteLD, WriteLDHi]> {
4027   bits<5> Rt;
4028   bits<5> Rt2;
4029   bits<5> Rn;
4030   let Inst{14-10} = Rt2;
4031   let Inst{9-5} = Rn;
4032   let Inst{4-0} = Rt;
4033
4034   let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
4035 }
4036
4037 // Simple store release operations do not check the exclusive monitor.
4038 let mayLoad = 0, mayStore = 1 in
4039 class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4040                    RegisterClass regtype, string asm>
4041     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
4042                                (ins regtype:$Rt, GPR64sp0:$Rn),
4043                                asm, "\t$Rt, [$Rn]">,
4044       Sched<[WriteST]>;
4045
4046 let mayLoad = 1, mayStore = 1 in
4047 class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4048                      RegisterClass regtype, string asm>
4049     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
4050                              (ins regtype:$Rt, GPR64sp0:$Rn),
4051                              asm, "\t$Ws, $Rt, [$Rn]">,
4052       Sched<[WriteSTX]> {
4053   bits<5> Ws;
4054   bits<5> Rt;
4055   bits<5> Rn;
4056   let Inst{20-16} = Ws;
4057   let Inst{9-5} = Rn;
4058   let Inst{4-0} = Rt;
4059
4060   let Constraints = "@earlyclobber $Ws";
4061   let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
4062 }
4063
4064 class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4065                          RegisterClass regtype, string asm>
4066     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4067                              (outs GPR32:$Ws),
4068                              (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
4069                               asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
4070       Sched<[WriteSTX]> {
4071   bits<5> Ws;
4072   bits<5> Rt;
4073   bits<5> Rt2;
4074   bits<5> Rn;
4075   let Inst{20-16} = Ws;
4076   let Inst{14-10} = Rt2;
4077   let Inst{9-5} = Rn;
4078   let Inst{4-0} = Rt;
4079
4080   let Constraints = "@earlyclobber $Ws";
4081 }
4082
4083 // Armv8.5-A Memory Tagging Extension
4084 class BaseMemTag<bits<2> opc1, bits<2> opc2, string asm_insn,
4085                  string asm_opnds, string cstr, dag oops, dag iops>
4086     : I<oops, iops, asm_insn, asm_opnds, cstr, []>,
4087       Sched<[]> {
4088   bits<5> Rn;
4089
4090   let Inst{31-24} = 0b11011001;
4091   let Inst{23-22} = opc1;
4092   let Inst{21}    = 1;
4093   // Inst{20-12} defined by subclass
4094   let Inst{11-10} = opc2;
4095   let Inst{9-5}   = Rn;
4096   // Inst{4-0} defined by subclass
4097 }
4098
4099 class MemTagVector<bit Load, string asm_insn, string asm_opnds,
4100                    dag oops, dag iops>
4101     : BaseMemTag<{0b1, Load}, 0b00, asm_insn, asm_opnds,
4102                   "", oops, iops> {
4103   bits<5> Rt;
4104
4105   let Inst{20-12} = 0b000000000;
4106   let Inst{4-0}   = Rt;
4107
4108   let mayLoad = Load;
4109 }
4110
4111 class MemTagLoad<string asm_insn, string asm_opnds>
4112     : BaseMemTag<0b01, 0b00, asm_insn, asm_opnds, "$Rt = $wback",
4113                  (outs GPR64:$wback),
4114                  (ins GPR64:$Rt, GPR64sp:$Rn, simm9s16:$offset)> {
4115   bits<5> Rt;
4116   bits<9> offset;
4117
4118   let Inst{20-12} = offset;
4119   let Inst{4-0}   = Rt;
4120
4121   let mayLoad = 1;
4122 }
4123
4124 class BaseMemTagStore<bits<2> opc1, bits<2> opc2, string asm_insn,
4125                      string asm_opnds, string cstr, dag oops, dag iops>
4126     : BaseMemTag<opc1, opc2, asm_insn, asm_opnds, cstr, oops, iops> {
4127   bits<5> Rt;
4128   bits<9> offset;
4129
4130   let Inst{20-12} = offset;
4131   let Inst{4-0}   = Rt;
4132
4133   let mayStore = 1;
4134 }
4135
4136 multiclass MemTagStore<bits<2> opc1, string insn> {
4137   def Offset :
4138     BaseMemTagStore<opc1, 0b10, insn, "\t$Rt, [$Rn, $offset]", "",
4139                     (outs), (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4140   def PreIndex :
4141     BaseMemTagStore<opc1, 0b11, insn, "\t$Rt, [$Rn, $offset]!",
4142                     "$Rn = $wback",
4143                     (outs GPR64sp:$wback),
4144                     (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4145   def PostIndex :
4146     BaseMemTagStore<opc1, 0b01, insn, "\t$Rt, [$Rn], $offset",
4147                     "$Rn = $wback",
4148                     (outs GPR64sp:$wback),
4149                     (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4150
4151   def : InstAlias<insn # "\t$Rt, [$Rn]",
4152                   (!cast<Instruction>(NAME # "Offset") GPR64sp:$Rt, GPR64sp:$Rn, 0)>;
4153 }
4154
4155 //---
4156 // Exception generation
4157 //---
4158
4159 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4160 class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
4161     : I<(outs), (ins i32_imm0_65535:$imm), asm, "\t$imm", "", []>,
4162       Sched<[WriteSys]> {
4163   bits<16> imm;
4164   let Inst{31-24} = 0b11010100;
4165   let Inst{23-21} = op1;
4166   let Inst{20-5}  = imm;
4167   let Inst{4-2}   = 0b000;
4168   let Inst{1-0}   = ll;
4169 }
4170
4171 //---
4172 // UDF : Permanently UNDEFINED instructions.  Format: Opc = 0x0000, 16 bit imm.
4173 //--
4174 let hasSideEffects = 1, isTrap = 1, mayLoad = 0, mayStore = 0 in {
4175 class UDFType<bits<16> opc, string asm>
4176   : I<(outs), (ins uimm16:$imm),
4177        asm, "\t$imm", "", []>,
4178     Sched<[]> {
4179   bits<16> imm;
4180   let Inst{31-16} = opc;
4181   let Inst{15-0} = imm;
4182 }
4183 }
4184 let Predicates = [HasFPARMv8] in {
4185
4186 //---
4187 // Floating point to integer conversion
4188 //---
4189
4190 class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
4191                       RegisterClass srcType, RegisterClass dstType,
4192                       string asm, list<dag> pattern>
4193     : I<(outs dstType:$Rd), (ins srcType:$Rn),
4194          asm, "\t$Rd, $Rn", "", pattern>,
4195       Sched<[WriteFCvt]> {
4196   bits<5> Rd;
4197   bits<5> Rn;
4198   let Inst{30-29} = 0b00;
4199   let Inst{28-24} = 0b11110;
4200   let Inst{23-22} = type;
4201   let Inst{21}    = 1;
4202   let Inst{20-19} = rmode;
4203   let Inst{18-16} = opcode;
4204   let Inst{15-10} = 0;
4205   let Inst{9-5}   = Rn;
4206   let Inst{4-0}   = Rd;
4207 }
4208
4209 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4210 class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
4211                       RegisterClass srcType, RegisterClass dstType,
4212                       Operand immType, string asm, list<dag> pattern>
4213     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4214          asm, "\t$Rd, $Rn, $scale", "", pattern>,
4215       Sched<[WriteFCvt]> {
4216   bits<5> Rd;
4217   bits<5> Rn;
4218   bits<6> scale;
4219   let Inst{30-29} = 0b00;
4220   let Inst{28-24} = 0b11110;
4221   let Inst{23-22} = type;
4222   let Inst{21}    = 0;
4223   let Inst{20-19} = rmode;
4224   let Inst{18-16} = opcode;
4225   let Inst{15-10} = scale;
4226   let Inst{9-5}   = Rn;
4227   let Inst{4-0}   = Rd;
4228 }
4229
4230 multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
4231            SDPatternOperator OpN> {
4232   // Unscaled half-precision to 32-bit
4233   def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
4234                                      [(set GPR32:$Rd, (OpN FPR16:$Rn))]> {
4235     let Inst{31} = 0; // 32-bit GPR flag
4236     let Predicates = [HasFullFP16];
4237   }
4238
4239   // Unscaled half-precision to 64-bit
4240   def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
4241                                      [(set GPR64:$Rd, (OpN FPR16:$Rn))]> {
4242     let Inst{31} = 1; // 64-bit GPR flag
4243     let Predicates = [HasFullFP16];
4244   }
4245
4246   // Unscaled single-precision to 32-bit
4247   def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
4248                                      [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
4249     let Inst{31} = 0; // 32-bit GPR flag
4250   }
4251
4252   // Unscaled single-precision to 64-bit
4253   def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
4254                                      [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
4255     let Inst{31} = 1; // 64-bit GPR flag
4256   }
4257
4258   // Unscaled double-precision to 32-bit
4259   def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
4260                                      [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4261     let Inst{31} = 0; // 32-bit GPR flag
4262   }
4263
4264   // Unscaled double-precision to 64-bit
4265   def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
4266                                      [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4267     let Inst{31} = 1; // 64-bit GPR flag
4268   }
4269 }
4270
4271 multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
4272                              SDPatternOperator OpN> {
4273   // Scaled half-precision to 32-bit
4274   def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
4275                               fixedpoint_f16_i32, asm,
4276               [(set GPR32:$Rd, (OpN (fmul FPR16:$Rn,
4277                                           fixedpoint_f16_i32:$scale)))]> {
4278     let Inst{31} = 0; // 32-bit GPR flag
4279     let scale{5} = 1;
4280     let Predicates = [HasFullFP16];
4281   }
4282
4283   // Scaled half-precision to 64-bit
4284   def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
4285                               fixedpoint_f16_i64, asm,
4286               [(set GPR64:$Rd, (OpN (fmul FPR16:$Rn,
4287                                           fixedpoint_f16_i64:$scale)))]> {
4288     let Inst{31} = 1; // 64-bit GPR flag
4289     let Predicates = [HasFullFP16];
4290   }
4291
4292   // Scaled single-precision to 32-bit
4293   def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
4294                               fixedpoint_f32_i32, asm,
4295               [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
4296                                           fixedpoint_f32_i32:$scale)))]> {
4297     let Inst{31} = 0; // 32-bit GPR flag
4298     let scale{5} = 1;
4299   }
4300
4301   // Scaled single-precision to 64-bit
4302   def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
4303                               fixedpoint_f32_i64, asm,
4304               [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
4305                                           fixedpoint_f32_i64:$scale)))]> {
4306     let Inst{31} = 1; // 64-bit GPR flag
4307   }
4308
4309   // Scaled double-precision to 32-bit
4310   def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
4311                               fixedpoint_f64_i32, asm,
4312               [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
4313                                           fixedpoint_f64_i32:$scale)))]> {
4314     let Inst{31} = 0; // 32-bit GPR flag
4315     let scale{5} = 1;
4316   }
4317
4318   // Scaled double-precision to 64-bit
4319   def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
4320                               fixedpoint_f64_i64, asm,
4321               [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
4322                                           fixedpoint_f64_i64:$scale)))]> {
4323     let Inst{31} = 1; // 64-bit GPR flag
4324   }
4325 }
4326
4327 //---
4328 // Integer to floating point conversion
4329 //---
4330
4331 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
4332 class BaseIntegerToFP<bit isUnsigned,
4333                       RegisterClass srcType, RegisterClass dstType,
4334                       Operand immType, string asm, list<dag> pattern>
4335     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4336          asm, "\t$Rd, $Rn, $scale", "", pattern>,
4337       Sched<[WriteFCvt]> {
4338   bits<5> Rd;
4339   bits<5> Rn;
4340   bits<6> scale;
4341   let Inst{30-24} = 0b0011110;
4342   let Inst{21-17} = 0b00001;
4343   let Inst{16}    = isUnsigned;
4344   let Inst{15-10} = scale;
4345   let Inst{9-5}   = Rn;
4346   let Inst{4-0}   = Rd;
4347 }
4348
4349 class BaseIntegerToFPUnscaled<bit isUnsigned,
4350                       RegisterClass srcType, RegisterClass dstType,
4351                       ValueType dvt, string asm, SDNode node>
4352     : I<(outs dstType:$Rd), (ins srcType:$Rn),
4353          asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
4354       Sched<[WriteFCvt]> {
4355   bits<5> Rd;
4356   bits<5> Rn;
4357   bits<6> scale;
4358   let Inst{30-24} = 0b0011110;
4359   let Inst{21-17} = 0b10001;
4360   let Inst{16}    = isUnsigned;
4361   let Inst{15-10} = 0b000000;
4362   let Inst{9-5}   = Rn;
4363   let Inst{4-0}   = Rd;
4364 }
4365
4366 multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
4367   // Unscaled
4368   def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
4369     let Inst{31} = 0; // 32-bit GPR flag
4370     let Inst{23-22} = 0b11; // 16-bit FPR flag
4371     let Predicates = [HasFullFP16];
4372   }
4373
4374   def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
4375     let Inst{31} = 0; // 32-bit GPR flag
4376     let Inst{23-22} = 0b00; // 32-bit FPR flag
4377   }
4378
4379   def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
4380     let Inst{31} = 0; // 32-bit GPR flag
4381     let Inst{23-22} = 0b01; // 64-bit FPR flag
4382   }
4383
4384   def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
4385     let Inst{31} = 1; // 64-bit GPR flag
4386     let Inst{23-22} = 0b11; // 16-bit FPR flag
4387     let Predicates = [HasFullFP16];
4388   }
4389
4390   def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
4391     let Inst{31} = 1; // 64-bit GPR flag
4392     let Inst{23-22} = 0b00; // 32-bit FPR flag
4393   }
4394
4395   def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
4396     let Inst{31} = 1; // 64-bit GPR flag
4397     let Inst{23-22} = 0b01; // 64-bit FPR flag
4398   }
4399
4400   // Scaled
4401   def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
4402                              [(set FPR16:$Rd,
4403                                    (fdiv (node GPR32:$Rn),
4404                                          fixedpoint_f16_i32:$scale))]> {
4405     let Inst{31} = 0; // 32-bit GPR flag
4406     let Inst{23-22} = 0b11; // 16-bit FPR flag
4407     let scale{5} = 1;
4408     let Predicates = [HasFullFP16];
4409   }
4410
4411   def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
4412                              [(set FPR32:$Rd,
4413                                    (fdiv (node GPR32:$Rn),
4414                                          fixedpoint_f32_i32:$scale))]> {
4415     let Inst{31} = 0; // 32-bit GPR flag
4416     let Inst{23-22} = 0b00; // 32-bit FPR flag
4417     let scale{5} = 1;
4418   }
4419
4420   def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
4421                              [(set FPR64:$Rd,
4422                                    (fdiv (node GPR32:$Rn),
4423                                          fixedpoint_f64_i32:$scale))]> {
4424     let Inst{31} = 0; // 32-bit GPR flag
4425     let Inst{23-22} = 0b01; // 64-bit FPR flag
4426     let scale{5} = 1;
4427   }
4428
4429   def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
4430                              [(set FPR16:$Rd,
4431                                    (fdiv (node GPR64:$Rn),
4432                                          fixedpoint_f16_i64:$scale))]> {
4433     let Inst{31} = 1; // 64-bit GPR flag
4434     let Inst{23-22} = 0b11; // 16-bit FPR flag
4435     let Predicates = [HasFullFP16];
4436   }
4437
4438   def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
4439                              [(set FPR32:$Rd,
4440                                    (fdiv (node GPR64:$Rn),
4441                                          fixedpoint_f32_i64:$scale))]> {
4442     let Inst{31} = 1; // 64-bit GPR flag
4443     let Inst{23-22} = 0b00; // 32-bit FPR flag
4444   }
4445
4446   def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
4447                              [(set FPR64:$Rd,
4448                                    (fdiv (node GPR64:$Rn),
4449                                          fixedpoint_f64_i64:$scale))]> {
4450     let Inst{31} = 1; // 64-bit GPR flag
4451     let Inst{23-22} = 0b01; // 64-bit FPR flag
4452   }
4453 }
4454
4455 //---
4456 // Unscaled integer <-> floating point conversion (i.e. FMOV)
4457 //---
4458
4459 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4460 class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
4461                       RegisterClass srcType, RegisterClass dstType,
4462                       string asm>
4463     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
4464         // We use COPY_TO_REGCLASS for these bitconvert operations.
4465         // copyPhysReg() expands the resultant COPY instructions after
4466         // regalloc is done. This gives greater freedom for the allocator
4467         // and related passes (coalescing, copy propagation, et. al.) to
4468         // be more effective.
4469         [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
4470       Sched<[WriteFCopy]> {
4471   bits<5> Rd;
4472   bits<5> Rn;
4473   let Inst{30-24} = 0b0011110;
4474   let Inst{21}    = 1;
4475   let Inst{20-19} = rmode;
4476   let Inst{18-16} = opcode;
4477   let Inst{15-10} = 0b000000;
4478   let Inst{9-5}   = Rn;
4479   let Inst{4-0}   = Rd;
4480 }
4481
4482 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4483 class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
4484                      RegisterClass srcType, RegisterOperand dstType, string asm,
4485                      string kind>
4486     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4487         "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
4488       Sched<[WriteFCopy]> {
4489   bits<5> Rd;
4490   bits<5> Rn;
4491   let Inst{30-23} = 0b00111101;
4492   let Inst{21}    = 1;
4493   let Inst{20-19} = rmode;
4494   let Inst{18-16} = opcode;
4495   let Inst{15-10} = 0b000000;
4496   let Inst{9-5}   = Rn;
4497   let Inst{4-0}   = Rd;
4498
4499   let DecoderMethod =  "DecodeFMOVLaneInstruction";
4500 }
4501
4502 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4503 class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
4504                      RegisterOperand srcType, RegisterClass dstType, string asm,
4505                      string kind>
4506     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4507         "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
4508       Sched<[WriteFCopy]> {
4509   bits<5> Rd;
4510   bits<5> Rn;
4511   let Inst{30-23} = 0b00111101;
4512   let Inst{21}    = 1;
4513   let Inst{20-19} = rmode;
4514   let Inst{18-16} = opcode;
4515   let Inst{15-10} = 0b000000;
4516   let Inst{9-5}   = Rn;
4517   let Inst{4-0}   = Rd;
4518
4519   let DecoderMethod =  "DecodeFMOVLaneInstruction";
4520 }
4521
4522
4523 multiclass UnscaledConversion<string asm> {
4524   def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
4525     let Inst{31} = 0; // 32-bit GPR flag
4526     let Inst{23-22} = 0b11; // 16-bit FPR flag
4527     let Predicates = [HasFullFP16];
4528   }
4529
4530   def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
4531     let Inst{31} = 1; // 64-bit GPR flag
4532     let Inst{23-22} = 0b11; // 16-bit FPR flag
4533     let Predicates = [HasFullFP16];
4534   }
4535
4536   def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
4537     let Inst{31} = 0; // 32-bit GPR flag
4538     let Inst{23-22} = 0b00; // 32-bit FPR flag
4539   }
4540
4541   def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
4542     let Inst{31} = 1; // 64-bit GPR flag
4543     let Inst{23-22} = 0b01; // 64-bit FPR flag
4544   }
4545
4546   def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
4547     let Inst{31} = 0; // 32-bit GPR flag
4548     let Inst{23-22} = 0b11; // 16-bit FPR flag
4549     let Predicates = [HasFullFP16];
4550   }
4551
4552   def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
4553     let Inst{31} = 1; // 64-bit GPR flag
4554     let Inst{23-22} = 0b11; // 16-bit FPR flag
4555     let Predicates = [HasFullFP16];
4556   }
4557
4558   def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
4559     let Inst{31} = 0; // 32-bit GPR flag
4560     let Inst{23-22} = 0b00; // 32-bit FPR flag
4561   }
4562
4563   def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
4564     let Inst{31} = 1; // 64-bit GPR flag
4565     let Inst{23-22} = 0b01; // 64-bit FPR flag
4566   }
4567
4568   def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
4569                                              asm, ".d"> {
4570     let Inst{31} = 1;
4571     let Inst{22} = 0;
4572   }
4573
4574   def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
4575                                                asm, ".d"> {
4576     let Inst{31} = 1;
4577     let Inst{22} = 0;
4578   }
4579 }
4580
4581 //---
4582 // Floating point conversion
4583 //---
4584
4585 class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
4586                        RegisterClass srcType, string asm, list<dag> pattern>
4587     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
4588       Sched<[WriteFCvt]> {
4589   bits<5> Rd;
4590   bits<5> Rn;
4591   let Inst{31-24} = 0b00011110;
4592   let Inst{23-22} = type;
4593   let Inst{21-17} = 0b10001;
4594   let Inst{16-15} = opcode;
4595   let Inst{14-10} = 0b10000;
4596   let Inst{9-5}   = Rn;
4597   let Inst{4-0}   = Rd;
4598 }
4599
4600 multiclass FPConversion<string asm> {
4601   // Double-precision to Half-precision
4602   def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
4603                              [(set FPR16:$Rd, (fpround FPR64:$Rn))]>;
4604
4605   // Double-precision to Single-precision
4606   def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
4607                              [(set FPR32:$Rd, (fpround FPR64:$Rn))]>;
4608
4609   // Half-precision to Double-precision
4610   def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
4611                              [(set FPR64:$Rd, (fpextend FPR16:$Rn))]>;
4612
4613   // Half-precision to Single-precision
4614   def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
4615                              [(set FPR32:$Rd, (fpextend FPR16:$Rn))]>;
4616
4617   // Single-precision to Double-precision
4618   def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
4619                              [(set FPR64:$Rd, (fpextend FPR32:$Rn))]>;
4620
4621   // Single-precision to Half-precision
4622   def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
4623                              [(set FPR16:$Rd, (fpround FPR32:$Rn))]>;
4624 }
4625
4626 //---
4627 // Single operand floating point data processing
4628 //---
4629
4630 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4631 class BaseSingleOperandFPData<bits<6> opcode, RegisterClass regtype,
4632                               ValueType vt, string asm, SDPatternOperator node>
4633     : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
4634          [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
4635       Sched<[WriteF]> {
4636   bits<5> Rd;
4637   bits<5> Rn;
4638   let Inst{31-24} = 0b00011110;
4639   let Inst{21}    = 0b1;
4640   let Inst{20-15} = opcode;
4641   let Inst{14-10} = 0b10000;
4642   let Inst{9-5}   = Rn;
4643   let Inst{4-0}   = Rd;
4644 }
4645
4646 multiclass SingleOperandFPData<bits<4> opcode, string asm,
4647                                SDPatternOperator node = null_frag> {
4648
4649   def Hr : BaseSingleOperandFPData<{0b00,opcode}, FPR16, f16, asm, node> {
4650     let Inst{23-22} = 0b11; // 16-bit size flag
4651     let Predicates = [HasFullFP16];
4652   }
4653
4654   def Sr : BaseSingleOperandFPData<{0b00,opcode}, FPR32, f32, asm, node> {
4655     let Inst{23-22} = 0b00; // 32-bit size flag
4656   }
4657
4658   def Dr : BaseSingleOperandFPData<{0b00,opcode}, FPR64, f64, asm, node> {
4659     let Inst{23-22} = 0b01; // 64-bit size flag
4660   }
4661 }
4662
4663 multiclass SingleOperandFPNo16<bits<6> opcode, string asm,
4664                   SDPatternOperator node = null_frag>{
4665
4666   def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
4667     let Inst{23-22} = 0b00; // 32-bit registers
4668   }
4669
4670   def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
4671     let Inst{23-22} = 0b01; // 64-bit registers
4672   }
4673 }
4674
4675 // FRInt[32|64][Z|N] instructions
4676 multiclass FRIntNNT<bits<2> opcode, string asm, SDPatternOperator node = null_frag> :
4677       SingleOperandFPNo16<{0b0100,opcode}, asm, node>;
4678
4679 //---
4680 // Two operand floating point data processing
4681 //---
4682
4683 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4684 class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
4685                            string asm, list<dag> pat>
4686     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
4687          asm, "\t$Rd, $Rn, $Rm", "", pat>,
4688       Sched<[WriteF]> {
4689   bits<5> Rd;
4690   bits<5> Rn;
4691   bits<5> Rm;
4692   let Inst{31-24} = 0b00011110;
4693   let Inst{21}    = 1;
4694   let Inst{20-16} = Rm;
4695   let Inst{15-12} = opcode;
4696   let Inst{11-10} = 0b10;
4697   let Inst{9-5}   = Rn;
4698   let Inst{4-0}   = Rd;
4699 }
4700
4701 multiclass TwoOperandFPData<bits<4> opcode, string asm,
4702                             SDPatternOperator node = null_frag> {
4703   def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4704                          [(set (f16 FPR16:$Rd),
4705                                (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
4706     let Inst{23-22} = 0b11; // 16-bit size flag
4707     let Predicates = [HasFullFP16];
4708   }
4709
4710   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4711                          [(set (f32 FPR32:$Rd),
4712                                (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
4713     let Inst{23-22} = 0b00; // 32-bit size flag
4714   }
4715
4716   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4717                          [(set (f64 FPR64:$Rd),
4718                                (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
4719     let Inst{23-22} = 0b01; // 64-bit size flag
4720   }
4721 }
4722
4723 multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
4724   def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4725                   [(set FPR16:$Rd, (fneg (node FPR16:$Rn, (f16 FPR16:$Rm))))]> {
4726     let Inst{23-22} = 0b11; // 16-bit size flag
4727     let Predicates = [HasFullFP16];
4728   }
4729
4730   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4731                   [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
4732     let Inst{23-22} = 0b00; // 32-bit size flag
4733   }
4734
4735   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4736                   [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
4737     let Inst{23-22} = 0b01; // 64-bit size flag
4738   }
4739 }
4740
4741
4742 //---
4743 // Three operand floating point data processing
4744 //---
4745
4746 class BaseThreeOperandFPData<bit isNegated, bit isSub,
4747                              RegisterClass regtype, string asm, list<dag> pat>
4748     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
4749          asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
4750       Sched<[WriteFMul]> {
4751   bits<5> Rd;
4752   bits<5> Rn;
4753   bits<5> Rm;
4754   bits<5> Ra;
4755   let Inst{31-24} = 0b00011111;
4756   let Inst{21}    = isNegated;
4757   let Inst{20-16} = Rm;
4758   let Inst{15}    = isSub;
4759   let Inst{14-10} = Ra;
4760   let Inst{9-5}   = Rn;
4761   let Inst{4-0}   = Rd;
4762 }
4763
4764 multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
4765                               SDPatternOperator node> {
4766   def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
4767             [(set FPR16:$Rd,
4768                   (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
4769     let Inst{23-22} = 0b11; // 16-bit size flag
4770     let Predicates = [HasFullFP16];
4771   }
4772
4773   def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
4774             [(set FPR32:$Rd,
4775                   (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
4776     let Inst{23-22} = 0b00; // 32-bit size flag
4777   }
4778
4779   def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
4780             [(set FPR64:$Rd,
4781                   (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
4782     let Inst{23-22} = 0b01; // 64-bit size flag
4783   }
4784 }
4785
4786 //---
4787 // Floating point data comparisons
4788 //---
4789
4790 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4791 class BaseOneOperandFPComparison<bit signalAllNans,
4792                                  RegisterClass regtype, string asm,
4793                                  list<dag> pat>
4794     : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
4795       Sched<[WriteFCmp]> {
4796   bits<5> Rn;
4797   let Inst{31-24} = 0b00011110;
4798   let Inst{21}    = 1;
4799
4800   let Inst{15-10} = 0b001000;
4801   let Inst{9-5}   = Rn;
4802   let Inst{4}     = signalAllNans;
4803   let Inst{3-0}   = 0b1000;
4804
4805   // Rm should be 0b00000 canonically, but we need to accept any value.
4806   let PostEncoderMethod = "fixOneOperandFPComparison";
4807 }
4808
4809 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4810 class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
4811                                 string asm, list<dag> pat>
4812     : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
4813       Sched<[WriteFCmp]> {
4814   bits<5> Rm;
4815   bits<5> Rn;
4816   let Inst{31-24} = 0b00011110;
4817   let Inst{21}    = 1;
4818   let Inst{20-16} = Rm;
4819   let Inst{15-10} = 0b001000;
4820   let Inst{9-5}   = Rn;
4821   let Inst{4}     = signalAllNans;
4822   let Inst{3-0}   = 0b0000;
4823 }
4824
4825 multiclass FPComparison<bit signalAllNans, string asm,
4826                         SDPatternOperator OpNode = null_frag> {
4827   let Defs = [NZCV] in {
4828   def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
4829       [(OpNode FPR16:$Rn, (f16 FPR16:$Rm)), (implicit NZCV)]> {
4830     let Inst{23-22} = 0b11;
4831     let Predicates = [HasFullFP16];
4832   }
4833
4834   def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
4835       [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
4836     let Inst{23-22} = 0b11;
4837     let Predicates = [HasFullFP16];
4838   }
4839
4840   def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
4841       [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
4842     let Inst{23-22} = 0b00;
4843   }
4844
4845   def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
4846       [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
4847     let Inst{23-22} = 0b00;
4848   }
4849
4850   def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
4851       [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
4852     let Inst{23-22} = 0b01;
4853   }
4854
4855   def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
4856       [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
4857     let Inst{23-22} = 0b01;
4858   }
4859   } // Defs = [NZCV]
4860 }
4861
4862 //---
4863 // Floating point conditional comparisons
4864 //---
4865
4866 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4867 class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
4868                            string mnemonic, list<dag> pat>
4869     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
4870          mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
4871       Sched<[WriteFCmp]> {
4872   let Uses = [NZCV];
4873   let Defs = [NZCV];
4874
4875   bits<5> Rn;
4876   bits<5> Rm;
4877   bits<4> nzcv;
4878   bits<4> cond;
4879
4880   let Inst{31-24} = 0b00011110;
4881   let Inst{21}    = 1;
4882   let Inst{20-16} = Rm;
4883   let Inst{15-12} = cond;
4884   let Inst{11-10} = 0b01;
4885   let Inst{9-5}   = Rn;
4886   let Inst{4}     = signalAllNans;
4887   let Inst{3-0}   = nzcv;
4888 }
4889
4890 multiclass FPCondComparison<bit signalAllNans, string mnemonic,
4891                             SDPatternOperator OpNode = null_frag> {
4892   def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic,
4893       [(set NZCV, (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm), (i32 imm:$nzcv),
4894                           (i32 imm:$cond), NZCV))]> {
4895     let Inst{23-22} = 0b11;
4896     let Predicates = [HasFullFP16];
4897   }
4898
4899   def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
4900       [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
4901                           (i32 imm:$cond), NZCV))]> {
4902     let Inst{23-22} = 0b00;
4903   }
4904
4905   def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
4906       [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
4907                           (i32 imm:$cond), NZCV))]> {
4908     let Inst{23-22} = 0b01;
4909   }
4910 }
4911
4912 //---
4913 // Floating point conditional select
4914 //---
4915
4916 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
4917     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
4918          asm, "\t$Rd, $Rn, $Rm, $cond", "",
4919          [(set regtype:$Rd,
4920                (AArch64csel (vt regtype:$Rn), regtype:$Rm,
4921                           (i32 imm:$cond), NZCV))]>,
4922       Sched<[WriteF]> {
4923   bits<5> Rd;
4924   bits<5> Rn;
4925   bits<5> Rm;
4926   bits<4> cond;
4927
4928   let Inst{31-24} = 0b00011110;
4929   let Inst{21}    = 1;
4930   let Inst{20-16} = Rm;
4931   let Inst{15-12} = cond;
4932   let Inst{11-10} = 0b11;
4933   let Inst{9-5}   = Rn;
4934   let Inst{4-0}   = Rd;
4935 }
4936
4937 multiclass FPCondSelect<string asm> {
4938   let Uses = [NZCV] in {
4939   def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
4940     let Inst{23-22} = 0b11;
4941     let Predicates = [HasFullFP16];
4942   }
4943
4944   def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
4945     let Inst{23-22} = 0b00;
4946   }
4947
4948   def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
4949     let Inst{23-22} = 0b01;
4950   }
4951   } // Uses = [NZCV]
4952 }
4953
4954 //---
4955 // Floating move immediate
4956 //---
4957
4958 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
4959   : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
4960       [(set regtype:$Rd, fpimmtype:$imm)]>,
4961     Sched<[WriteFImm]> {
4962   bits<5> Rd;
4963   bits<8> imm;
4964   let Inst{31-24} = 0b00011110;
4965   let Inst{21}    = 1;
4966   let Inst{20-13} = imm;
4967   let Inst{12-5}  = 0b10000000;
4968   let Inst{4-0}   = Rd;
4969 }
4970
4971 multiclass FPMoveImmediate<string asm> {
4972   def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
4973     let Inst{23-22} = 0b11;
4974     let Predicates = [HasFullFP16];
4975   }
4976
4977   def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
4978     let Inst{23-22} = 0b00;
4979   }
4980
4981   def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
4982     let Inst{23-22} = 0b01;
4983   }
4984 }
4985 } // end of 'let Predicates = [HasFPARMv8]'
4986
4987 //----------------------------------------------------------------------------
4988 // AdvSIMD
4989 //----------------------------------------------------------------------------
4990
4991 let Predicates = [HasNEON] in {
4992
4993 //----------------------------------------------------------------------------
4994 // AdvSIMD three register vector instructions
4995 //----------------------------------------------------------------------------
4996
4997 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4998 class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
4999                         RegisterOperand regtype, string asm, string kind,
5000                         list<dag> pattern>
5001   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5002       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5003       "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
5004     Sched<[WriteV]> {
5005   bits<5> Rd;
5006   bits<5> Rn;
5007   bits<5> Rm;
5008   let Inst{31}    = 0;
5009   let Inst{30}    = Q;
5010   let Inst{29}    = U;
5011   let Inst{28-24} = 0b01110;
5012   let Inst{23-21} = size;
5013   let Inst{20-16} = Rm;
5014   let Inst{15-11} = opcode;
5015   let Inst{10}    = 1;
5016   let Inst{9-5}   = Rn;
5017   let Inst{4-0}   = Rd;
5018 }
5019
5020 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5021 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
5022                         RegisterOperand regtype, string asm, string kind,
5023                         list<dag> pattern>
5024   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
5025       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5026       "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5027     Sched<[WriteV]> {
5028   bits<5> Rd;
5029   bits<5> Rn;
5030   bits<5> Rm;
5031   let Inst{31}    = 0;
5032   let Inst{30}    = Q;
5033   let Inst{29}    = U;
5034   let Inst{28-24} = 0b01110;
5035   let Inst{23-21} = size;
5036   let Inst{20-16} = Rm;
5037   let Inst{15-11} = opcode;
5038   let Inst{10}    = 1;
5039   let Inst{9-5}   = Rn;
5040   let Inst{4-0}   = Rd;
5041 }
5042
5043 // All operand sizes distinguished in the encoding.
5044 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
5045                                SDPatternOperator OpNode> {
5046   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5047                                       asm, ".8b",
5048          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5049   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5050                                       asm, ".16b",
5051          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5052   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5053                                       asm, ".4h",
5054          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5055   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5056                                       asm, ".8h",
5057          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5058   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5059                                       asm, ".2s",
5060          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5061   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5062                                       asm, ".4s",
5063          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5064   def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
5065                                       asm, ".2d",
5066          [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5067 }
5068
5069 // As above, but D sized elements unsupported.
5070 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
5071                                   SDPatternOperator OpNode> {
5072   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5073                                       asm, ".8b",
5074         [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
5075   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5076                                       asm, ".16b",
5077         [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
5078   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5079                                       asm, ".4h",
5080         [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
5081   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5082                                       asm, ".8h",
5083         [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
5084   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5085                                       asm, ".2s",
5086         [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
5087   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5088                                       asm, ".4s",
5089         [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
5090 }
5091
5092 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
5093                                   SDPatternOperator OpNode> {
5094   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
5095                                       asm, ".8b",
5096       [(set (v8i8 V64:$dst),
5097             (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5098   def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
5099                                       asm, ".16b",
5100       [(set (v16i8 V128:$dst),
5101             (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5102   def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
5103                                       asm, ".4h",
5104       [(set (v4i16 V64:$dst),
5105             (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5106   def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
5107                                       asm, ".8h",
5108       [(set (v8i16 V128:$dst),
5109             (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5110   def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
5111                                       asm, ".2s",
5112       [(set (v2i32 V64:$dst),
5113             (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5114   def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
5115                                       asm, ".4s",
5116       [(set (v4i32 V128:$dst),
5117             (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5118 }
5119
5120 // As above, but only B sized elements supported.
5121 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
5122                                 SDPatternOperator OpNode> {
5123   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5124                                       asm, ".8b",
5125     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5126   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5127                                       asm, ".16b",
5128     [(set (v16i8 V128:$Rd),
5129           (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5130 }
5131
5132 // As above, but only floating point elements supported.
5133 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
5134                                  string asm, SDPatternOperator OpNode> {
5135   let Predicates = [HasNEON, HasFullFP16] in {
5136   def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5137                                       asm, ".4h",
5138         [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5139   def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5140                                       asm, ".8h",
5141         [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5142   } // Predicates = [HasNEON, HasFullFP16]
5143   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5144                                       asm, ".2s",
5145         [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5146   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5147                                       asm, ".4s",
5148         [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5149   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5150                                       asm, ".2d",
5151         [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5152 }
5153
5154 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
5155                                     string asm,
5156                                     SDPatternOperator OpNode> {
5157   let Predicates = [HasNEON, HasFullFP16] in {
5158   def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5159                                       asm, ".4h",
5160         [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5161   def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5162                                       asm, ".8h",
5163         [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5164   } // Predicates = [HasNEON, HasFullFP16]
5165   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5166                                       asm, ".2s",
5167         [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5168   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5169                                       asm, ".4s",
5170         [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5171   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5172                                       asm, ".2d",
5173         [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5174 }
5175
5176 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
5177                                  string asm, SDPatternOperator OpNode> {
5178   let Predicates = [HasNEON, HasFullFP16] in {
5179   def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
5180                                       asm, ".4h",
5181      [(set (v4f16 V64:$dst),
5182            (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5183   def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
5184                                       asm, ".8h",
5185      [(set (v8f16 V128:$dst),
5186            (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5187   } // Predicates = [HasNEON, HasFullFP16]
5188   def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
5189                                       asm, ".2s",
5190      [(set (v2f32 V64:$dst),
5191            (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5192   def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
5193                                       asm, ".4s",
5194      [(set (v4f32 V128:$dst),
5195            (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5196   def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
5197                                       asm, ".2d",
5198      [(set (v2f64 V128:$dst),
5199            (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5200 }
5201
5202 // As above, but D and B sized elements unsupported.
5203 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
5204                                 SDPatternOperator OpNode> {
5205   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5206                                       asm, ".4h",
5207         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5208   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5209                                       asm, ".8h",
5210         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5211   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5212                                       asm, ".2s",
5213         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5214   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5215                                       asm, ".4s",
5216         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5217 }
5218
5219 // Logical three vector ops share opcode bits, and only use B sized elements.
5220 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
5221                                   SDPatternOperator OpNode = null_frag> {
5222   def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
5223                                      asm, ".8b",
5224                          [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
5225   def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
5226                                      asm, ".16b",
5227                          [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
5228
5229   def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5230           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5231   def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5232           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5233   def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
5234           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5235
5236   def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5237       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5238   def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5239       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5240   def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5241       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5242 }
5243
5244 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
5245                                   string asm, SDPatternOperator OpNode> {
5246   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
5247                                      asm, ".8b",
5248              [(set (v8i8 V64:$dst),
5249                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5250   def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
5251                                      asm, ".16b",
5252              [(set (v16i8 V128:$dst),
5253                    (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5254                            (v16i8 V128:$Rm)))]>;
5255
5256   def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5257                            (v4i16 V64:$RHS))),
5258           (!cast<Instruction>(NAME#"v8i8")
5259             V64:$LHS, V64:$MHS, V64:$RHS)>;
5260   def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5261                            (v2i32 V64:$RHS))),
5262           (!cast<Instruction>(NAME#"v8i8")
5263             V64:$LHS, V64:$MHS, V64:$RHS)>;
5264   def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5265                            (v1i64 V64:$RHS))),
5266           (!cast<Instruction>(NAME#"v8i8")
5267             V64:$LHS, V64:$MHS, V64:$RHS)>;
5268
5269   def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5270                            (v8i16 V128:$RHS))),
5271       (!cast<Instruction>(NAME#"v16i8")
5272         V128:$LHS, V128:$MHS, V128:$RHS)>;
5273   def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5274                            (v4i32 V128:$RHS))),
5275       (!cast<Instruction>(NAME#"v16i8")
5276         V128:$LHS, V128:$MHS, V128:$RHS)>;
5277   def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5278                            (v2i64 V128:$RHS))),
5279       (!cast<Instruction>(NAME#"v16i8")
5280         V128:$LHS, V128:$MHS, V128:$RHS)>;
5281 }
5282
5283 // ARMv8.2-A Dot Product Instructions (Vector): These instructions extract
5284 // bytes from S-sized elements.
5285 class BaseSIMDThreeSameVectorDot<bit Q, bit U, string asm, string kind1,
5286                                  string kind2, RegisterOperand RegType,
5287                                  ValueType AccumType, ValueType InputType,
5288                                  SDPatternOperator OpNode> :
5289         BaseSIMDThreeSameVectorTied<Q, U, 0b100, 0b10010, RegType, asm, kind1,
5290         [(set (AccumType RegType:$dst),
5291               (OpNode (AccumType RegType:$Rd),
5292                       (InputType RegType:$Rn),
5293                       (InputType RegType:$Rm)))]> {
5294   let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5295 }
5296
5297 multiclass SIMDThreeSameVectorDot<bit U, string asm, SDPatternOperator OpNode> {
5298   def v8i8  : BaseSIMDThreeSameVectorDot<0, U, asm, ".2s", ".8b", V64,
5299                                          v2i32, v8i8, OpNode>;
5300   def v16i8 : BaseSIMDThreeSameVectorDot<1, U, asm, ".4s", ".16b", V128,
5301                                          v4i32, v16i8, OpNode>;
5302 }
5303
5304 // ARMv8.2-A Fused Multiply Add-Long Instructions (Vector): These instructions
5305 // select inputs from 4H vectors and accumulate outputs to a 2S vector (or from
5306 // 8H to 4S, when Q=1).
5307 class BaseSIMDThreeSameVectorFML<bit Q, bit U, bit b13, bits<3> size, string asm, string kind1,
5308                                  string kind2, RegisterOperand RegType,
5309                                  ValueType AccumType, ValueType InputType,
5310                                  SDPatternOperator OpNode> :
5311         BaseSIMDThreeSameVectorTied<Q, U, size, 0b11101, RegType, asm, kind1,
5312                 [(set (AccumType RegType:$dst),
5313               (OpNode (AccumType RegType:$Rd),
5314                       (InputType RegType:$Rn),
5315                       (InputType RegType:$Rm)))]> {
5316   let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5317   let Inst{13} = b13;
5318 }
5319
5320 multiclass SIMDThreeSameVectorFML<bit U, bit b13, bits<3> size, string asm,
5321                                   SDPatternOperator OpNode> {
5322   def v4f16 : BaseSIMDThreeSameVectorFML<0, U, b13, size, asm, ".2s", ".2h", V64,
5323                                          v2f32, v4f16, OpNode>;
5324   def v8f16 : BaseSIMDThreeSameVectorFML<1, U, b13, size, asm, ".4s", ".4h", V128,
5325                                          v4f32, v8f16, OpNode>;
5326 }
5327
5328
5329 //----------------------------------------------------------------------------
5330 // AdvSIMD two register vector instructions.
5331 //----------------------------------------------------------------------------
5332
5333 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5334 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5335                             bits<2> size2, RegisterOperand regtype, string asm,
5336                             string dstkind, string srckind, list<dag> pattern>
5337   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5338       "{\t$Rd" # dstkind # ", $Rn" # srckind #
5339       "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
5340     Sched<[WriteV]> {
5341   bits<5> Rd;
5342   bits<5> Rn;
5343   let Inst{31}    = 0;
5344   let Inst{30}    = Q;
5345   let Inst{29}    = U;
5346   let Inst{28-24} = 0b01110;
5347   let Inst{23-22} = size;
5348   let Inst{21} = 0b1;
5349   let Inst{20-19} = size2;
5350   let Inst{18-17} = 0b00;
5351   let Inst{16-12} = opcode;
5352   let Inst{11-10} = 0b10;
5353   let Inst{9-5}   = Rn;
5354   let Inst{4-0}   = Rd;
5355 }
5356
5357 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5358 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5359                                 bits<2> size2, RegisterOperand regtype,
5360                                 string asm, string dstkind, string srckind,
5361                                 list<dag> pattern>
5362   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
5363       "{\t$Rd" # dstkind # ", $Rn" # srckind #
5364       "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5365     Sched<[WriteV]> {
5366   bits<5> Rd;
5367   bits<5> Rn;
5368   let Inst{31}    = 0;
5369   let Inst{30}    = Q;
5370   let Inst{29}    = U;
5371   let Inst{28-24} = 0b01110;
5372   let Inst{23-22} = size;
5373   let Inst{21} = 0b1;
5374   let Inst{20-19} = size2;
5375   let Inst{18-17} = 0b00;
5376   let Inst{16-12} = opcode;
5377   let Inst{11-10} = 0b10;
5378   let Inst{9-5}   = Rn;
5379   let Inst{4-0}   = Rd;
5380 }
5381
5382 // Supports B, H, and S element sizes.
5383 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
5384                             SDPatternOperator OpNode> {
5385   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5386                                       asm, ".8b", ".8b",
5387                           [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5388   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5389                                       asm, ".16b", ".16b",
5390                           [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5391   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5392                                       asm, ".4h", ".4h",
5393                           [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5394   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5395                                       asm, ".8h", ".8h",
5396                           [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5397   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5398                                       asm, ".2s", ".2s",
5399                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5400   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5401                                       asm, ".4s", ".4s",
5402                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5403 }
5404
5405 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
5406                             RegisterOperand regtype, string asm, string dstkind,
5407                             string srckind, string amount>
5408   : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
5409       "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
5410       "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
5411     Sched<[WriteV]> {
5412   bits<5> Rd;
5413   bits<5> Rn;
5414   let Inst{31}    = 0;
5415   let Inst{30}    = Q;
5416   let Inst{29-24} = 0b101110;
5417   let Inst{23-22} = size;
5418   let Inst{21-10} = 0b100001001110;
5419   let Inst{9-5}   = Rn;
5420   let Inst{4-0}   = Rd;
5421 }
5422
5423 multiclass SIMDVectorLShiftLongBySizeBHS {
5424   let hasSideEffects = 0 in {
5425   def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
5426                                              "shll", ".8h",  ".8b", "8">;
5427   def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
5428                                              "shll2", ".8h", ".16b", "8">;
5429   def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
5430                                              "shll", ".4s",  ".4h", "16">;
5431   def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
5432                                              "shll2", ".4s", ".8h", "16">;
5433   def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
5434                                              "shll", ".2d",  ".2s", "32">;
5435   def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
5436                                              "shll2", ".2d", ".4s", "32">;
5437   }
5438 }
5439
5440 // Supports all element sizes.
5441 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
5442                              SDPatternOperator OpNode> {
5443   def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5444                                       asm, ".4h", ".8b",
5445                [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5446   def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5447                                       asm, ".8h", ".16b",
5448                [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5449   def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5450                                       asm, ".2s", ".4h",
5451                [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5452   def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5453                                       asm, ".4s", ".8h",
5454                [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5455   def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5456                                       asm, ".1d", ".2s",
5457                [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5458   def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5459                                       asm, ".2d", ".4s",
5460                [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5461 }
5462
5463 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
5464                                  SDPatternOperator OpNode> {
5465   def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5466                                           asm, ".4h", ".8b",
5467       [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
5468                                       (v8i8 V64:$Rn)))]>;
5469   def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5470                                           asm, ".8h", ".16b",
5471       [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
5472                                       (v16i8 V128:$Rn)))]>;
5473   def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5474                                           asm, ".2s", ".4h",
5475       [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
5476                                       (v4i16 V64:$Rn)))]>;
5477   def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5478                                           asm, ".4s", ".8h",
5479       [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
5480                                       (v8i16 V128:$Rn)))]>;
5481   def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5482                                           asm, ".1d", ".2s",
5483       [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
5484                                       (v2i32 V64:$Rn)))]>;
5485   def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5486                                           asm, ".2d", ".4s",
5487       [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
5488                                       (v4i32 V128:$Rn)))]>;
5489 }
5490
5491 // Supports all element sizes, except 1xD.
5492 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
5493                                   SDPatternOperator OpNode> {
5494   def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5495                                     asm, ".8b", ".8b",
5496     [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
5497   def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5498                                     asm, ".16b", ".16b",
5499     [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
5500   def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5501                                     asm, ".4h", ".4h",
5502     [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
5503   def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5504                                     asm, ".8h", ".8h",
5505     [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
5506   def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5507                                     asm, ".2s", ".2s",
5508     [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
5509   def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5510                                     asm, ".4s", ".4s",
5511     [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
5512   def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
5513                                     asm, ".2d", ".2d",
5514     [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
5515 }
5516
5517 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
5518                              SDPatternOperator OpNode = null_frag> {
5519   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5520                                 asm, ".8b", ".8b",
5521     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5522   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5523                                 asm, ".16b", ".16b",
5524     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5525   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5526                                 asm, ".4h", ".4h",
5527     [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5528   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5529                                 asm, ".8h", ".8h",
5530     [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5531   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5532                                 asm, ".2s", ".2s",
5533     [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5534   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5535                                 asm, ".4s", ".4s",
5536     [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5537   def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
5538                                 asm, ".2d", ".2d",
5539     [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5540 }
5541
5542
5543 // Supports only B element sizes.
5544 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
5545                           SDPatternOperator OpNode> {
5546   def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
5547                                 asm, ".8b", ".8b",
5548                     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5549   def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
5550                                 asm, ".16b", ".16b",
5551                     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5552
5553 }
5554
5555 // Supports only B and H element sizes.
5556 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
5557                                 SDPatternOperator OpNode> {
5558   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5559                                 asm, ".8b", ".8b",
5560                     [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
5561   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5562                                 asm, ".16b", ".16b",
5563                     [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
5564   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5565                                 asm, ".4h", ".4h",
5566                     [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
5567   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5568                                 asm, ".8h", ".8h",
5569                     [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
5570 }
5571
5572 // Supports H, S and D element sizes, uses high bit of the size field
5573 // as an extra opcode bit.
5574 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
5575                            SDPatternOperator OpNode> {
5576   let Predicates = [HasNEON, HasFullFP16] in {
5577   def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5578                                 asm, ".4h", ".4h",
5579                           [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5580   def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5581                                 asm, ".8h", ".8h",
5582                           [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5583   } // Predicates = [HasNEON, HasFullFP16]
5584   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5585                                 asm, ".2s", ".2s",
5586                           [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5587   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5588                                 asm, ".4s", ".4s",
5589                           [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5590   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5591                                 asm, ".2d", ".2d",
5592                           [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5593 }
5594
5595 // Supports only S and D element sizes
5596 multiclass SIMDTwoVectorSD<bit U, bits<5> opc, string asm,
5597                            SDPatternOperator OpNode = null_frag> {
5598
5599   def v2f32 : BaseSIMDTwoSameVector<0, U, 00, opc, 0b00, V64,
5600                                 asm, ".2s", ".2s",
5601                           [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5602   def v4f32 : BaseSIMDTwoSameVector<1, U, 00, opc, 0b00, V128,
5603                                 asm, ".4s", ".4s",
5604                           [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5605   def v2f64 : BaseSIMDTwoSameVector<1, U, 01, opc, 0b00, V128,
5606                                 asm, ".2d", ".2d",
5607                           [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5608 }
5609
5610 multiclass FRIntNNTVector<bit U, bit op, string asm,
5611                           SDPatternOperator OpNode = null_frag> :
5612            SIMDTwoVectorSD<U, {0b1111,op}, asm, OpNode>;
5613
5614 // Supports only S element size.
5615 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
5616                            SDPatternOperator OpNode> {
5617   def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5618                                 asm, ".2s", ".2s",
5619                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5620   def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5621                                 asm, ".4s", ".4s",
5622                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5623 }
5624
5625
5626 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
5627                            SDPatternOperator OpNode> {
5628   let Predicates = [HasNEON, HasFullFP16] in {
5629   def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5630                                 asm, ".4h", ".4h",
5631                           [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5632   def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5633                                 asm, ".8h", ".8h",
5634                           [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5635   } // Predicates = [HasNEON, HasFullFP16]
5636   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5637                                 asm, ".2s", ".2s",
5638                           [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5639   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5640                                 asm, ".4s", ".4s",
5641                           [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5642   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5643                                 asm, ".2d", ".2d",
5644                           [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5645 }
5646
5647 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
5648                            SDPatternOperator OpNode> {
5649   let Predicates = [HasNEON, HasFullFP16] in {
5650   def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5651                                 asm, ".4h", ".4h",
5652                           [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5653   def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5654                                 asm, ".8h", ".8h",
5655                           [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5656   } // Predicates = [HasNEON, HasFullFP16]
5657   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5658                                 asm, ".2s", ".2s",
5659                           [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5660   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5661                                 asm, ".4s", ".4s",
5662                           [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5663   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5664                                 asm, ".2d", ".2d",
5665                           [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5666 }
5667
5668
5669 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5670                            RegisterOperand inreg, RegisterOperand outreg,
5671                            string asm, string outkind, string inkind,
5672                            list<dag> pattern>
5673   : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
5674       "{\t$Rd" # outkind # ", $Rn" # inkind #
5675       "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
5676     Sched<[WriteV]> {
5677   bits<5> Rd;
5678   bits<5> Rn;
5679   let Inst{31}    = 0;
5680   let Inst{30}    = Q;
5681   let Inst{29}    = U;
5682   let Inst{28-24} = 0b01110;
5683   let Inst{23-22} = size;
5684   let Inst{21-17} = 0b10000;
5685   let Inst{16-12} = opcode;
5686   let Inst{11-10} = 0b10;
5687   let Inst{9-5}   = Rn;
5688   let Inst{4-0}   = Rd;
5689 }
5690
5691 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5692                            RegisterOperand inreg, RegisterOperand outreg,
5693                            string asm, string outkind, string inkind,
5694                            list<dag> pattern>
5695   : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
5696       "{\t$Rd" # outkind # ", $Rn" # inkind #
5697       "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5698     Sched<[WriteV]> {
5699   bits<5> Rd;
5700   bits<5> Rn;
5701   let Inst{31}    = 0;
5702   let Inst{30}    = Q;
5703   let Inst{29}    = U;
5704   let Inst{28-24} = 0b01110;
5705   let Inst{23-22} = size;
5706   let Inst{21-17} = 0b10000;
5707   let Inst{16-12} = opcode;
5708   let Inst{11-10} = 0b10;
5709   let Inst{9-5}   = Rn;
5710   let Inst{4-0}   = Rd;
5711 }
5712
5713 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
5714                               SDPatternOperator OpNode> {
5715   def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
5716                                       asm, ".8b", ".8h",
5717         [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5718   def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
5719                                       asm#"2", ".16b", ".8h", []>;
5720   def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
5721                                       asm, ".4h", ".4s",
5722         [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5723   def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
5724                                       asm#"2", ".8h", ".4s", []>;
5725   def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
5726                                       asm, ".2s", ".2d",
5727         [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5728   def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
5729                                       asm#"2", ".4s", ".2d", []>;
5730
5731   def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
5732             (!cast<Instruction>(NAME # "v16i8")
5733                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5734   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
5735             (!cast<Instruction>(NAME # "v8i16")
5736                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5737   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
5738             (!cast<Instruction>(NAME # "v4i32")
5739                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5740 }
5741
5742 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
5743                            bits<5> opcode, RegisterOperand regtype, string asm,
5744                            string kind, string zero, ValueType dty,
5745                            ValueType sty, SDNode OpNode>
5746   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5747       "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
5748       "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
5749       [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
5750     Sched<[WriteV]> {
5751   bits<5> Rd;
5752   bits<5> Rn;
5753   let Inst{31}    = 0;
5754   let Inst{30}    = Q;
5755   let Inst{29}    = U;
5756   let Inst{28-24} = 0b01110;
5757   let Inst{23-22} = size;
5758   let Inst{21} = 0b1;
5759   let Inst{20-19} = size2;
5760   let Inst{18-17} = 0b00;
5761   let Inst{16-12} = opcode;
5762   let Inst{11-10} = 0b10;
5763   let Inst{9-5}   = Rn;
5764   let Inst{4-0}   = Rd;
5765 }
5766
5767 // Comparisons support all element sizes, except 1xD.
5768 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
5769                             SDNode OpNode> {
5770   def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
5771                                      asm, ".8b", "0",
5772                                      v8i8, v8i8, OpNode>;
5773   def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
5774                                      asm, ".16b", "0",
5775                                      v16i8, v16i8, OpNode>;
5776   def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
5777                                      asm, ".4h", "0",
5778                                      v4i16, v4i16, OpNode>;
5779   def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
5780                                      asm, ".8h", "0",
5781                                      v8i16, v8i16, OpNode>;
5782   def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
5783                                      asm, ".2s", "0",
5784                                      v2i32, v2i32, OpNode>;
5785   def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
5786                                      asm, ".4s", "0",
5787                                      v4i32, v4i32, OpNode>;
5788   def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
5789                                      asm, ".2d", "0",
5790                                      v2i64, v2i64, OpNode>;
5791 }
5792
5793 // FP Comparisons support only S and D element sizes (and H for v8.2a).
5794 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
5795                               string asm, SDNode OpNode> {
5796
5797   let Predicates = [HasNEON, HasFullFP16] in {
5798   def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
5799                                      asm, ".4h", "0.0",
5800                                      v4i16, v4f16, OpNode>;
5801   def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
5802                                      asm, ".8h", "0.0",
5803                                      v8i16, v8f16, OpNode>;
5804   } // Predicates = [HasNEON, HasFullFP16]
5805   def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
5806                                      asm, ".2s", "0.0",
5807                                      v2i32, v2f32, OpNode>;
5808   def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
5809                                      asm, ".4s", "0.0",
5810                                      v4i32, v4f32, OpNode>;
5811   def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
5812                                      asm, ".2d", "0.0",
5813                                      v2i64, v2f64, OpNode>;
5814
5815   let Predicates = [HasNEON, HasFullFP16] in {
5816   def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
5817                   (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
5818   def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
5819                   (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
5820   }
5821   def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
5822                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
5823   def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
5824                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
5825   def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
5826                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5827   let Predicates = [HasNEON, HasFullFP16] in {
5828   def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
5829                   (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
5830   def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
5831                   (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
5832   }
5833   def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
5834                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
5835   def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
5836                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
5837   def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
5838                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5839 }
5840
5841 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5842 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5843                              RegisterOperand outtype, RegisterOperand intype,
5844                              string asm, string VdTy, string VnTy,
5845                              list<dag> pattern>
5846   : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
5847       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
5848     Sched<[WriteV]> {
5849   bits<5> Rd;
5850   bits<5> Rn;
5851   let Inst{31}    = 0;
5852   let Inst{30}    = Q;
5853   let Inst{29}    = U;
5854   let Inst{28-24} = 0b01110;
5855   let Inst{23-22} = size;
5856   let Inst{21-17} = 0b10000;
5857   let Inst{16-12} = opcode;
5858   let Inst{11-10} = 0b10;
5859   let Inst{9-5}   = Rn;
5860   let Inst{4-0}   = Rd;
5861 }
5862
5863 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5864                              RegisterOperand outtype, RegisterOperand intype,
5865                              string asm, string VdTy, string VnTy,
5866                              list<dag> pattern>
5867   : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
5868       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
5869     Sched<[WriteV]> {
5870   bits<5> Rd;
5871   bits<5> Rn;
5872   let Inst{31}    = 0;
5873   let Inst{30}    = Q;
5874   let Inst{29}    = U;
5875   let Inst{28-24} = 0b01110;
5876   let Inst{23-22} = size;
5877   let Inst{21-17} = 0b10000;
5878   let Inst{16-12} = opcode;
5879   let Inst{11-10} = 0b10;
5880   let Inst{9-5}   = Rn;
5881   let Inst{4-0}   = Rd;
5882 }
5883
5884 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
5885   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
5886                                     asm, ".4s", ".4h", []>;
5887   def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
5888                                     asm#"2", ".4s", ".8h", []>;
5889   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
5890                                     asm, ".2d", ".2s", []>;
5891   def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
5892                                     asm#"2", ".2d", ".4s", []>;
5893 }
5894
5895 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
5896   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
5897                                     asm, ".4h", ".4s", []>;
5898   def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
5899                                     asm#"2", ".8h", ".4s", []>;
5900   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5901                                     asm, ".2s", ".2d", []>;
5902   def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5903                                     asm#"2", ".4s", ".2d", []>;
5904 }
5905
5906 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
5907                                      Intrinsic OpNode> {
5908   def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5909                                      asm, ".2s", ".2d",
5910                           [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5911   def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5912                                     asm#"2", ".4s", ".2d", []>;
5913
5914   def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
5915             (!cast<Instruction>(NAME # "v4f32")
5916                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5917 }
5918
5919 //----------------------------------------------------------------------------
5920 // AdvSIMD three register different-size vector instructions.
5921 //----------------------------------------------------------------------------
5922
5923 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5924 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
5925                       RegisterOperand outtype, RegisterOperand intype1,
5926                       RegisterOperand intype2, string asm,
5927                       string outkind, string inkind1, string inkind2,
5928                       list<dag> pattern>
5929   : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
5930       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5931       "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
5932     Sched<[WriteV]> {
5933   bits<5> Rd;
5934   bits<5> Rn;
5935   bits<5> Rm;
5936   let Inst{31}    = 0;
5937   let Inst{30}    = size{0};
5938   let Inst{29}    = U;
5939   let Inst{28-24} = 0b01110;
5940   let Inst{23-22} = size{2-1};
5941   let Inst{21}    = 1;
5942   let Inst{20-16} = Rm;
5943   let Inst{15-12} = opcode;
5944   let Inst{11-10} = 0b00;
5945   let Inst{9-5}   = Rn;
5946   let Inst{4-0}   = Rd;
5947 }
5948
5949 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5950 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
5951                       RegisterOperand outtype, RegisterOperand intype1,
5952                       RegisterOperand intype2, string asm,
5953                       string outkind, string inkind1, string inkind2,
5954                       list<dag> pattern>
5955   : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
5956       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5957       "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5958     Sched<[WriteV]> {
5959   bits<5> Rd;
5960   bits<5> Rn;
5961   bits<5> Rm;
5962   let Inst{31}    = 0;
5963   let Inst{30}    = size{0};
5964   let Inst{29}    = U;
5965   let Inst{28-24} = 0b01110;
5966   let Inst{23-22} = size{2-1};
5967   let Inst{21}    = 1;
5968   let Inst{20-16} = Rm;
5969   let Inst{15-12} = opcode;
5970   let Inst{11-10} = 0b00;
5971   let Inst{9-5}   = Rn;
5972   let Inst{4-0}   = Rd;
5973 }
5974
5975 // FIXME: TableGen doesn't know how to deal with expanded types that also
5976 //        change the element count (in this case, placing the results in
5977 //        the high elements of the result register rather than the low
5978 //        elements). Until that's fixed, we can't code-gen those.
5979 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
5980                                     Intrinsic IntOp> {
5981   def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5982                                                   V64, V128, V128,
5983                                                   asm, ".8b", ".8h", ".8h",
5984      [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5985   def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5986                                                   V128, V128, V128,
5987                                                   asm#"2", ".16b", ".8h", ".8h",
5988      []>;
5989   def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5990                                                   V64, V128, V128,
5991                                                   asm, ".4h", ".4s", ".4s",
5992      [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5993   def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5994                                                   V128, V128, V128,
5995                                                   asm#"2", ".8h", ".4s", ".4s",
5996      []>;
5997   def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5998                                                   V64, V128, V128,
5999                                                   asm, ".2s", ".2d", ".2d",
6000      [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
6001   def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6002                                                   V128, V128, V128,
6003                                                   asm#"2", ".4s", ".2d", ".2d",
6004      []>;
6005
6006
6007   // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
6008   // a version attached to an instruction.
6009   def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
6010                                                    (v8i16 V128:$Rm))),
6011             (!cast<Instruction>(NAME # "v8i16_v16i8")
6012                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6013                 V128:$Rn, V128:$Rm)>;
6014   def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
6015                                                     (v4i32 V128:$Rm))),
6016             (!cast<Instruction>(NAME # "v4i32_v8i16")
6017                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6018                 V128:$Rn, V128:$Rm)>;
6019   def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
6020                                                     (v2i64 V128:$Rm))),
6021             (!cast<Instruction>(NAME # "v2i64_v4i32")
6022                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6023                 V128:$Rn, V128:$Rm)>;
6024 }
6025
6026 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
6027                                       Intrinsic IntOp> {
6028   def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6029                                             V128, V64, V64,
6030                                             asm, ".8h", ".8b", ".8b",
6031       [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6032   def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6033                                             V128, V128, V128,
6034                                             asm#"2", ".8h", ".16b", ".16b", []>;
6035   let Predicates = [HasAES] in {
6036     def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
6037                                               V128, V64, V64,
6038                                               asm, ".1q", ".1d", ".1d", []>;
6039     def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
6040                                               V128, V128, V128,
6041                                               asm#"2", ".1q", ".2d", ".2d", []>;
6042   }
6043
6044   def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
6045                           (v8i8 (extract_high_v16i8 V128:$Rm)))),
6046       (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
6047 }
6048
6049 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
6050                                  SDPatternOperator OpNode> {
6051   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6052                                                   V128, V64, V64,
6053                                                   asm, ".4s", ".4h", ".4h",
6054       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6055   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6056                                                   V128, V128, V128,
6057                                                   asm#"2", ".4s", ".8h", ".8h",
6058       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
6059                                       (extract_high_v8i16 V128:$Rm)))]>;
6060   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6061                                                   V128, V64, V64,
6062                                                   asm, ".2d", ".2s", ".2s",
6063       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6064   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6065                                                   V128, V128, V128,
6066                                                   asm#"2", ".2d", ".4s", ".4s",
6067       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
6068                                       (extract_high_v4i32 V128:$Rm)))]>;
6069 }
6070
6071 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
6072                                   SDPatternOperator OpNode = null_frag> {
6073   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6074                                                   V128, V64, V64,
6075                                                   asm, ".8h", ".8b", ".8b",
6076       [(set (v8i16 V128:$Rd),
6077             (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
6078   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6079                                                  V128, V128, V128,
6080                                                  asm#"2", ".8h", ".16b", ".16b",
6081       [(set (v8i16 V128:$Rd),
6082             (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
6083                                 (extract_high_v16i8 V128:$Rm)))))]>;
6084   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6085                                                   V128, V64, V64,
6086                                                   asm, ".4s", ".4h", ".4h",
6087       [(set (v4i32 V128:$Rd),
6088             (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
6089   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6090                                                   V128, V128, V128,
6091                                                   asm#"2", ".4s", ".8h", ".8h",
6092       [(set (v4i32 V128:$Rd),
6093             (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
6094                                   (extract_high_v8i16 V128:$Rm)))))]>;
6095   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6096                                                   V128, V64, V64,
6097                                                   asm, ".2d", ".2s", ".2s",
6098       [(set (v2i64 V128:$Rd),
6099             (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
6100   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6101                                                   V128, V128, V128,
6102                                                   asm#"2", ".2d", ".4s", ".4s",
6103       [(set (v2i64 V128:$Rd),
6104             (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
6105                                  (extract_high_v4i32 V128:$Rm)))))]>;
6106 }
6107
6108 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
6109                                           string asm,
6110                                           SDPatternOperator OpNode> {
6111   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6112                                                   V128, V64, V64,
6113                                                   asm, ".8h", ".8b", ".8b",
6114     [(set (v8i16 V128:$dst),
6115           (add (v8i16 V128:$Rd),
6116                (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
6117   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6118                                                  V128, V128, V128,
6119                                                  asm#"2", ".8h", ".16b", ".16b",
6120     [(set (v8i16 V128:$dst),
6121           (add (v8i16 V128:$Rd),
6122                (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
6123                                    (extract_high_v16i8 V128:$Rm))))))]>;
6124   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6125                                                   V128, V64, V64,
6126                                                   asm, ".4s", ".4h", ".4h",
6127     [(set (v4i32 V128:$dst),
6128           (add (v4i32 V128:$Rd),
6129                (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
6130   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6131                                                   V128, V128, V128,
6132                                                   asm#"2", ".4s", ".8h", ".8h",
6133     [(set (v4i32 V128:$dst),
6134           (add (v4i32 V128:$Rd),
6135                (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
6136                                     (extract_high_v8i16 V128:$Rm))))))]>;
6137   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6138                                                   V128, V64, V64,
6139                                                   asm, ".2d", ".2s", ".2s",
6140     [(set (v2i64 V128:$dst),
6141           (add (v2i64 V128:$Rd),
6142                (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
6143   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6144                                                   V128, V128, V128,
6145                                                   asm#"2", ".2d", ".4s", ".4s",
6146     [(set (v2i64 V128:$dst),
6147           (add (v2i64 V128:$Rd),
6148                (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
6149                                     (extract_high_v4i32 V128:$Rm))))))]>;
6150 }
6151
6152 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
6153                                   SDPatternOperator OpNode = null_frag> {
6154   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6155                                                   V128, V64, V64,
6156                                                   asm, ".8h", ".8b", ".8b",
6157       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6158   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6159                                                  V128, V128, V128,
6160                                                  asm#"2", ".8h", ".16b", ".16b",
6161       [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
6162                                       (extract_high_v16i8 V128:$Rm)))]>;
6163   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6164                                                   V128, V64, V64,
6165                                                   asm, ".4s", ".4h", ".4h",
6166       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6167   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6168                                                   V128, V128, V128,
6169                                                   asm#"2", ".4s", ".8h", ".8h",
6170       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
6171                                       (extract_high_v8i16 V128:$Rm)))]>;
6172   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6173                                                   V128, V64, V64,
6174                                                   asm, ".2d", ".2s", ".2s",
6175       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6176   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6177                                                   V128, V128, V128,
6178                                                   asm#"2", ".2d", ".4s", ".4s",
6179       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
6180                                       (extract_high_v4i32 V128:$Rm)))]>;
6181 }
6182
6183 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
6184                                       string asm,
6185                                       SDPatternOperator OpNode> {
6186   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6187                                                   V128, V64, V64,
6188                                                   asm, ".8h", ".8b", ".8b",
6189     [(set (v8i16 V128:$dst),
6190           (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6191   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6192                                                  V128, V128, V128,
6193                                                  asm#"2", ".8h", ".16b", ".16b",
6194     [(set (v8i16 V128:$dst),
6195           (OpNode (v8i16 V128:$Rd),
6196                   (extract_high_v16i8 V128:$Rn),
6197                   (extract_high_v16i8 V128:$Rm)))]>;
6198   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6199                                                   V128, V64, V64,
6200                                                   asm, ".4s", ".4h", ".4h",
6201     [(set (v4i32 V128:$dst),
6202           (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6203   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6204                                                   V128, V128, V128,
6205                                                   asm#"2", ".4s", ".8h", ".8h",
6206     [(set (v4i32 V128:$dst),
6207           (OpNode (v4i32 V128:$Rd),
6208                   (extract_high_v8i16 V128:$Rn),
6209                   (extract_high_v8i16 V128:$Rm)))]>;
6210   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6211                                                   V128, V64, V64,
6212                                                   asm, ".2d", ".2s", ".2s",
6213     [(set (v2i64 V128:$dst),
6214           (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6215   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6216                                                   V128, V128, V128,
6217                                                   asm#"2", ".2d", ".4s", ".4s",
6218     [(set (v2i64 V128:$dst),
6219           (OpNode (v2i64 V128:$Rd),
6220                   (extract_high_v4i32 V128:$Rn),
6221                   (extract_high_v4i32 V128:$Rm)))]>;
6222 }
6223
6224 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
6225                                            SDPatternOperator Accum> {
6226   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6227                                                   V128, V64, V64,
6228                                                   asm, ".4s", ".4h", ".4h",
6229     [(set (v4i32 V128:$dst),
6230           (Accum (v4i32 V128:$Rd),
6231                  (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
6232                                                 (v4i16 V64:$Rm)))))]>;
6233   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6234                                                   V128, V128, V128,
6235                                                   asm#"2", ".4s", ".8h", ".8h",
6236     [(set (v4i32 V128:$dst),
6237           (Accum (v4i32 V128:$Rd),
6238                  (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
6239                                             (extract_high_v8i16 V128:$Rm)))))]>;
6240   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6241                                                   V128, V64, V64,
6242                                                   asm, ".2d", ".2s", ".2s",
6243     [(set (v2i64 V128:$dst),
6244           (Accum (v2i64 V128:$Rd),
6245                  (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
6246                                                 (v2i32 V64:$Rm)))))]>;
6247   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6248                                                   V128, V128, V128,
6249                                                   asm#"2", ".2d", ".4s", ".4s",
6250     [(set (v2i64 V128:$dst),
6251           (Accum (v2i64 V128:$Rd),
6252                  (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
6253                                             (extract_high_v4i32 V128:$Rm)))))]>;
6254 }
6255
6256 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
6257                                   SDPatternOperator OpNode> {
6258   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6259                                                   V128, V128, V64,
6260                                                   asm, ".8h", ".8h", ".8b",
6261        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
6262   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6263                                                   V128, V128, V128,
6264                                                   asm#"2", ".8h", ".8h", ".16b",
6265        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
6266                                        (extract_high_v16i8 V128:$Rm)))]>;
6267   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6268                                                   V128, V128, V64,
6269                                                   asm, ".4s", ".4s", ".4h",
6270        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
6271   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6272                                                   V128, V128, V128,
6273                                                   asm#"2", ".4s", ".4s", ".8h",
6274        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
6275                                        (extract_high_v8i16 V128:$Rm)))]>;
6276   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6277                                                   V128, V128, V64,
6278                                                   asm, ".2d", ".2d", ".2s",
6279        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
6280   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6281                                                   V128, V128, V128,
6282                                                   asm#"2", ".2d", ".2d", ".4s",
6283        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
6284                                        (extract_high_v4i32 V128:$Rm)))]>;
6285 }
6286
6287 //----------------------------------------------------------------------------
6288 // AdvSIMD bitwise extract from vector
6289 //----------------------------------------------------------------------------
6290
6291 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
6292                              string asm, string kind>
6293   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
6294       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
6295       "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
6296       [(set (vty regtype:$Rd),
6297             (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
6298     Sched<[WriteV]> {
6299   bits<5> Rd;
6300   bits<5> Rn;
6301   bits<5> Rm;
6302   bits<4> imm;
6303   let Inst{31}    = 0;
6304   let Inst{30}    = size;
6305   let Inst{29-21} = 0b101110000;
6306   let Inst{20-16} = Rm;
6307   let Inst{15}    = 0;
6308   let Inst{14-11} = imm;
6309   let Inst{10}    = 0;
6310   let Inst{9-5}   = Rn;
6311   let Inst{4-0}   = Rd;
6312 }
6313
6314
6315 multiclass SIMDBitwiseExtract<string asm> {
6316   def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
6317     let imm{3} = 0;
6318   }
6319   def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
6320 }
6321
6322 //----------------------------------------------------------------------------
6323 // AdvSIMD zip vector
6324 //----------------------------------------------------------------------------
6325
6326 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
6327                         string asm, string kind, SDNode OpNode, ValueType valty>
6328   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6329       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
6330       "|" # kind # "\t$Rd, $Rn, $Rm}", "",
6331       [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
6332     Sched<[WriteV]> {
6333   bits<5> Rd;
6334   bits<5> Rn;
6335   bits<5> Rm;
6336   let Inst{31}    = 0;
6337   let Inst{30}    = size{0};
6338   let Inst{29-24} = 0b001110;
6339   let Inst{23-22} = size{2-1};
6340   let Inst{21}    = 0;
6341   let Inst{20-16} = Rm;
6342   let Inst{15}    = 0;
6343   let Inst{14-12} = opc;
6344   let Inst{11-10} = 0b10;
6345   let Inst{9-5}   = Rn;
6346   let Inst{4-0}   = Rd;
6347 }
6348
6349 multiclass SIMDZipVector<bits<3>opc, string asm,
6350                          SDNode OpNode> {
6351   def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
6352       asm, ".8b", OpNode, v8i8>;
6353   def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
6354       asm, ".16b", OpNode, v16i8>;
6355   def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
6356       asm, ".4h", OpNode, v4i16>;
6357   def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
6358       asm, ".8h", OpNode, v8i16>;
6359   def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
6360       asm, ".2s", OpNode, v2i32>;
6361   def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
6362       asm, ".4s", OpNode, v4i32>;
6363   def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
6364       asm, ".2d", OpNode, v2i64>;
6365
6366   def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
6367         (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
6368   def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
6369         (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
6370   def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
6371         (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
6372   def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
6373         (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
6374   def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
6375         (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
6376 }
6377
6378 //----------------------------------------------------------------------------
6379 // AdvSIMD three register scalar instructions
6380 //----------------------------------------------------------------------------
6381
6382 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6383 class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
6384                         RegisterClass regtype, string asm,
6385                         list<dag> pattern>
6386   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6387       "\t$Rd, $Rn, $Rm", "", pattern>,
6388     Sched<[WriteV]> {
6389   bits<5> Rd;
6390   bits<5> Rn;
6391   bits<5> Rm;
6392   let Inst{31-30} = 0b01;
6393   let Inst{29}    = U;
6394   let Inst{28-24} = 0b11110;
6395   let Inst{23-21} = size;
6396   let Inst{20-16} = Rm;
6397   let Inst{15-11} = opcode;
6398   let Inst{10}    = 1;
6399   let Inst{9-5}   = Rn;
6400   let Inst{4-0}   = Rd;
6401 }
6402
6403 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6404 class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
6405                         dag oops, dag iops, string asm,
6406             list<dag> pattern>
6407   : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
6408     Sched<[WriteV]> {
6409   bits<5> Rd;
6410   bits<5> Rn;
6411   bits<5> Rm;
6412   let Inst{31-30} = 0b01;
6413   let Inst{29}    = U;
6414   let Inst{28-24} = 0b11110;
6415   let Inst{23-22} = size;
6416   let Inst{21}    = R;
6417   let Inst{20-16} = Rm;
6418   let Inst{15-11} = opcode;
6419   let Inst{10}    = 1;
6420   let Inst{9-5}   = Rn;
6421   let Inst{4-0}   = Rd;
6422 }
6423
6424 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
6425                             SDPatternOperator OpNode> {
6426   def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6427     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6428 }
6429
6430 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
6431                                SDPatternOperator OpNode> {
6432   def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6433     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6434   def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
6435   def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6436   def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
6437
6438   def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
6439             (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
6440   def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
6441             (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
6442 }
6443
6444 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
6445                              SDPatternOperator OpNode> {
6446   def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
6447                              [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6448   def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6449 }
6450
6451 multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
6452                                  SDPatternOperator OpNode = null_frag> {
6453   def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
6454                                      (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
6455                                      asm, []>;
6456   def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
6457                                      (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
6458                                      asm, []>;
6459 }
6460
6461 multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
6462                              SDPatternOperator OpNode = null_frag> {
6463   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6464     def #NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6465       [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6466     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6467       [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6468     let Predicates = [HasNEON, HasFullFP16] in {
6469     def #NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6470       [(set FPR16:$Rd, (OpNode FPR16:$Rn, FPR16:$Rm))]>;
6471     } // Predicates = [HasNEON, HasFullFP16]
6472   }
6473
6474   def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6475             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6476 }
6477
6478 multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
6479                                 SDPatternOperator OpNode = null_frag> {
6480   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6481     def #NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6482       [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6483     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6484       [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
6485     let Predicates = [HasNEON, HasFullFP16] in {
6486     def #NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6487       []>;
6488     } // Predicates = [HasNEON, HasFullFP16]
6489   }
6490
6491   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6492             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6493 }
6494
6495 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
6496               dag oops, dag iops, string asm, string cstr, list<dag> pat>
6497   : I<oops, iops, asm,
6498       "\t$Rd, $Rn, $Rm", cstr, pat>,
6499     Sched<[WriteV]> {
6500   bits<5> Rd;
6501   bits<5> Rn;
6502   bits<5> Rm;
6503   let Inst{31-30} = 0b01;
6504   let Inst{29}    = U;
6505   let Inst{28-24} = 0b11110;
6506   let Inst{23-22} = size;
6507   let Inst{21}    = 1;
6508   let Inst{20-16} = Rm;
6509   let Inst{15-11} = opcode;
6510   let Inst{10}    = 0;
6511   let Inst{9-5}   = Rn;
6512   let Inst{4-0}   = Rd;
6513 }
6514
6515 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6516 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
6517                                   SDPatternOperator OpNode = null_frag> {
6518   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6519                                       (outs FPR32:$Rd),
6520                                       (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
6521   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6522                                       (outs FPR64:$Rd),
6523                                       (ins FPR32:$Rn, FPR32:$Rm), asm, "",
6524             [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6525 }
6526
6527 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6528 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
6529                                   SDPatternOperator OpNode = null_frag> {
6530   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6531                                       (outs FPR32:$dst),
6532                                       (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
6533                                       asm, "$Rd = $dst", []>;
6534   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6535                                       (outs FPR64:$dst),
6536                                       (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
6537                                       asm, "$Rd = $dst",
6538             [(set (i64 FPR64:$dst),
6539                   (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6540 }
6541
6542 //----------------------------------------------------------------------------
6543 // AdvSIMD two register scalar instructions
6544 //----------------------------------------------------------------------------
6545
6546 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6547 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6548                         RegisterClass regtype, RegisterClass regtype2,
6549                         string asm, list<dag> pat>
6550   : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
6551       "\t$Rd, $Rn", "", pat>,
6552     Sched<[WriteV]> {
6553   bits<5> Rd;
6554   bits<5> Rn;
6555   let Inst{31-30} = 0b01;
6556   let Inst{29}    = U;
6557   let Inst{28-24} = 0b11110;
6558   let Inst{23-22} = size;
6559   let Inst{21} = 0b1;
6560   let Inst{20-19} = size2;
6561   let Inst{18-17} = 0b00;
6562   let Inst{16-12} = opcode;
6563   let Inst{11-10} = 0b10;
6564   let Inst{9-5}   = Rn;
6565   let Inst{4-0}   = Rd;
6566 }
6567
6568 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6569 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
6570                         RegisterClass regtype, RegisterClass regtype2,
6571                         string asm, list<dag> pat>
6572   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
6573       "\t$Rd, $Rn", "$Rd = $dst", pat>,
6574     Sched<[WriteV]> {
6575   bits<5> Rd;
6576   bits<5> Rn;
6577   let Inst{31-30} = 0b01;
6578   let Inst{29}    = U;
6579   let Inst{28-24} = 0b11110;
6580   let Inst{23-22} = size;
6581   let Inst{21-17} = 0b10000;
6582   let Inst{16-12} = opcode;
6583   let Inst{11-10} = 0b10;
6584   let Inst{9-5}   = Rn;
6585   let Inst{4-0}   = Rd;
6586 }
6587
6588
6589 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6590 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6591                         RegisterClass regtype, string asm, string zero>
6592   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6593       "\t$Rd, $Rn, #" # zero, "", []>,
6594     Sched<[WriteV]> {
6595   bits<5> Rd;
6596   bits<5> Rn;
6597   let Inst{31-30} = 0b01;
6598   let Inst{29}    = U;
6599   let Inst{28-24} = 0b11110;
6600   let Inst{23-22} = size;
6601   let Inst{21} = 0b1;
6602   let Inst{20-19} = size2;
6603   let Inst{18-17} = 0b00;
6604   let Inst{16-12} = opcode;
6605   let Inst{11-10} = 0b10;
6606   let Inst{9-5}   = Rn;
6607   let Inst{4-0}   = Rd;
6608 }
6609
6610 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
6611   : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
6612      [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
6613     Sched<[WriteV]> {
6614   bits<5> Rd;
6615   bits<5> Rn;
6616   let Inst{31-17} = 0b011111100110000;
6617   let Inst{16-12} = opcode;
6618   let Inst{11-10} = 0b10;
6619   let Inst{9-5}   = Rn;
6620   let Inst{4-0}   = Rd;
6621 }
6622
6623 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
6624                              SDPatternOperator OpNode> {
6625   def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
6626
6627   def : Pat<(v1i64 (OpNode FPR64:$Rn)),
6628             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6629 }
6630
6631 multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
6632                               SDPatternOperator OpNode> {
6633   def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
6634   def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
6635   let Predicates = [HasNEON, HasFullFP16] in {
6636   def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
6637   }
6638
6639   def : InstAlias<asm # "\t$Rd, $Rn, #0",
6640                   (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
6641   def : InstAlias<asm # "\t$Rd, $Rn, #0",
6642                   (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
6643   let Predicates = [HasNEON, HasFullFP16] in {
6644   def : InstAlias<asm # "\t$Rd, $Rn, #0",
6645                   (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
6646   }
6647
6648   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
6649             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6650 }
6651
6652 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
6653                           SDPatternOperator OpNode = null_frag> {
6654   def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
6655     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
6656
6657   def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
6658             (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
6659 }
6660
6661 multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm> {
6662   def v1i64       : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
6663   def v1i32       : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
6664   let Predicates = [HasNEON, HasFullFP16] in {
6665   def v1f16       : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
6666   }
6667 }
6668
6669 multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
6670                               SDPatternOperator OpNode> {
6671   def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
6672                                 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
6673   def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
6674                                 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
6675   let Predicates = [HasNEON, HasFullFP16] in {
6676   def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
6677                                 [(set FPR16:$Rd, (OpNode (f16 FPR16:$Rn)))]>;
6678   }
6679 }
6680
6681 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
6682                              SDPatternOperator OpNode = null_frag> {
6683   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6684     def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
6685            [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
6686     def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
6687            [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
6688     def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
6689     def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
6690   }
6691
6692   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
6693             (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
6694 }
6695
6696 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
6697                                  Intrinsic OpNode> {
6698   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6699     def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
6700         [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
6701     def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
6702         [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
6703     def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
6704     def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
6705   }
6706
6707   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
6708             (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
6709 }
6710
6711
6712
6713 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6714 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
6715                                  SDPatternOperator OpNode = null_frag> {
6716   def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
6717         [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
6718   def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
6719   def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
6720 }
6721
6722 //----------------------------------------------------------------------------
6723 // AdvSIMD scalar pairwise instructions
6724 //----------------------------------------------------------------------------
6725
6726 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6727 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
6728                         RegisterOperand regtype, RegisterOperand vectype,
6729                         string asm, string kind>
6730   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
6731       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
6732     Sched<[WriteV]> {
6733   bits<5> Rd;
6734   bits<5> Rn;
6735   let Inst{31-30} = 0b01;
6736   let Inst{29}    = U;
6737   let Inst{28-24} = 0b11110;
6738   let Inst{23-22} = size;
6739   let Inst{21-17} = 0b11000;
6740   let Inst{16-12} = opcode;
6741   let Inst{11-10} = 0b10;
6742   let Inst{9-5}   = Rn;
6743   let Inst{4-0}   = Rd;
6744 }
6745
6746 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
6747   def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
6748                                       asm, ".2d">;
6749 }
6750
6751 multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
6752   let Predicates = [HasNEON, HasFullFP16] in {
6753   def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
6754                                       asm, ".2h">;
6755   }
6756   def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
6757                                       asm, ".2s">;
6758   def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
6759                                       asm, ".2d">;
6760 }
6761
6762 //----------------------------------------------------------------------------
6763 // AdvSIMD across lanes instructions
6764 //----------------------------------------------------------------------------
6765
6766 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6767 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
6768                           RegisterClass regtype, RegisterOperand vectype,
6769                           string asm, string kind, list<dag> pattern>
6770   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
6771       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
6772     Sched<[WriteV]> {
6773   bits<5> Rd;
6774   bits<5> Rn;
6775   let Inst{31}    = 0;
6776   let Inst{30}    = Q;
6777   let Inst{29}    = U;
6778   let Inst{28-24} = 0b01110;
6779   let Inst{23-22} = size;
6780   let Inst{21-17} = 0b11000;
6781   let Inst{16-12} = opcode;
6782   let Inst{11-10} = 0b10;
6783   let Inst{9-5}   = Rn;
6784   let Inst{4-0}   = Rd;
6785 }
6786
6787 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
6788                               string asm> {
6789   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
6790                                    asm, ".8b", []>;
6791   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
6792                                    asm, ".16b", []>;
6793   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
6794                                    asm, ".4h", []>;
6795   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
6796                                    asm, ".8h", []>;
6797   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
6798                                    asm, ".4s", []>;
6799 }
6800
6801 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
6802   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
6803                                    asm, ".8b", []>;
6804   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
6805                                    asm, ".16b", []>;
6806   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
6807                                    asm, ".4h", []>;
6808   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
6809                                    asm, ".8h", []>;
6810   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
6811                                    asm, ".4s", []>;
6812 }
6813
6814 multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
6815                             Intrinsic intOp> {
6816   let Predicates = [HasNEON, HasFullFP16] in {
6817   def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
6818                                    asm, ".4h",
6819         [(set FPR16:$Rd, (intOp (v4f16 V64:$Rn)))]>;
6820   def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
6821                                    asm, ".8h",
6822         [(set FPR16:$Rd, (intOp (v8f16 V128:$Rn)))]>;
6823   } // Predicates = [HasNEON, HasFullFP16]
6824   def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
6825                                    asm, ".4s",
6826         [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
6827 }
6828
6829 //----------------------------------------------------------------------------
6830 // AdvSIMD INS/DUP instructions
6831 //----------------------------------------------------------------------------
6832
6833 // FIXME: There has got to be a better way to factor these. ugh.
6834
6835 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
6836                      string operands, string constraints, list<dag> pattern>
6837   : I<outs, ins, asm, operands, constraints, pattern>,
6838     Sched<[WriteV]> {
6839   bits<5> Rd;
6840   bits<5> Rn;
6841   let Inst{31} = 0;
6842   let Inst{30} = Q;
6843   let Inst{29} = op;
6844   let Inst{28-21} = 0b01110000;
6845   let Inst{15} = 0;
6846   let Inst{10} = 1;
6847   let Inst{9-5} = Rn;
6848   let Inst{4-0} = Rd;
6849 }
6850
6851 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
6852                       RegisterOperand vecreg, RegisterClass regtype>
6853   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
6854                    "{\t$Rd" # size # ", $Rn" #
6855                    "|" # size # "\t$Rd, $Rn}", "",
6856                    [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
6857   let Inst{20-16} = imm5;
6858   let Inst{14-11} = 0b0001;
6859 }
6860
6861 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
6862                          ValueType vectype, ValueType insreg,
6863                          RegisterOperand vecreg, Operand idxtype,
6864                          ValueType elttype, SDNode OpNode>
6865   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
6866                    "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
6867                    "|" # dstkind # "\t$Rd, $Rn$idx}", "",
6868                  [(set (vectype vecreg:$Rd),
6869                        (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
6870   let Inst{14-11} = 0b0000;
6871 }
6872
6873 class SIMDDup64FromElement
6874   : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
6875                        VectorIndexD, i64, AArch64duplane64> {
6876   bits<1> idx;
6877   let Inst{20} = idx;
6878   let Inst{19-16} = 0b1000;
6879 }
6880
6881 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
6882                            RegisterOperand vecreg>
6883   : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
6884                        VectorIndexS, i64, AArch64duplane32> {
6885   bits<2> idx;
6886   let Inst{20-19} = idx;
6887   let Inst{18-16} = 0b100;
6888 }
6889
6890 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
6891                            RegisterOperand vecreg>
6892   : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
6893                        VectorIndexH, i64, AArch64duplane16> {
6894   bits<3> idx;
6895   let Inst{20-18} = idx;
6896   let Inst{17-16} = 0b10;
6897 }
6898
6899 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
6900                           RegisterOperand vecreg>
6901   : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
6902                        VectorIndexB, i64, AArch64duplane8> {
6903   bits<4> idx;
6904   let Inst{20-17} = idx;
6905   let Inst{16} = 1;
6906 }
6907
6908 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
6909                   Operand idxtype, string asm, list<dag> pattern>
6910   : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
6911                    "{\t$Rd, $Rn" # size # "$idx" #
6912                    "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
6913   let Inst{14-11} = imm4;
6914 }
6915
6916 class SIMDSMov<bit Q, string size, RegisterClass regtype,
6917                Operand idxtype>
6918   : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
6919 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
6920                Operand idxtype>
6921   : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
6922       [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
6923
6924 class SIMDMovAlias<string asm, string size, Instruction inst,
6925                    RegisterClass regtype, Operand idxtype>
6926     : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
6927                     "|" # size # "\t$dst, $src$idx}",
6928                 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
6929
6930 multiclass SMov {
6931   def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
6932     bits<4> idx;
6933     let Inst{20-17} = idx;
6934     let Inst{16} = 1;
6935   }
6936   def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
6937     bits<4> idx;
6938     let Inst{20-17} = idx;
6939     let Inst{16} = 1;
6940   }
6941   def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
6942     bits<3> idx;
6943     let Inst{20-18} = idx;
6944     let Inst{17-16} = 0b10;
6945   }
6946   def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
6947     bits<3> idx;
6948     let Inst{20-18} = idx;
6949     let Inst{17-16} = 0b10;
6950   }
6951   def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
6952     bits<2> idx;
6953     let Inst{20-19} = idx;
6954     let Inst{18-16} = 0b100;
6955   }
6956 }
6957
6958 multiclass UMov {
6959   def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
6960     bits<4> idx;
6961     let Inst{20-17} = idx;
6962     let Inst{16} = 1;
6963   }
6964   def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
6965     bits<3> idx;
6966     let Inst{20-18} = idx;
6967     let Inst{17-16} = 0b10;
6968   }
6969   def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
6970     bits<2> idx;
6971     let Inst{20-19} = idx;
6972     let Inst{18-16} = 0b100;
6973   }
6974   def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
6975     bits<1> idx;
6976     let Inst{20} = idx;
6977     let Inst{19-16} = 0b1000;
6978   }
6979   def : SIMDMovAlias<"mov", ".s",
6980                      !cast<Instruction>(NAME#"vi32"),
6981                      GPR32, VectorIndexS>;
6982   def : SIMDMovAlias<"mov", ".d",
6983                      !cast<Instruction>(NAME#"vi64"),
6984                      GPR64, VectorIndexD>;
6985 }
6986
6987 class SIMDInsFromMain<string size, ValueType vectype,
6988                       RegisterClass regtype, Operand idxtype>
6989   : BaseSIMDInsDup<1, 0, (outs V128:$dst),
6990                    (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
6991                    "{\t$Rd" # size # "$idx, $Rn" #
6992                    "|" # size # "\t$Rd$idx, $Rn}",
6993                    "$Rd = $dst",
6994             [(set V128:$dst,
6995               (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
6996   let Inst{14-11} = 0b0011;
6997 }
6998
6999 class SIMDInsFromElement<string size, ValueType vectype,
7000                          ValueType elttype, Operand idxtype>
7001   : BaseSIMDInsDup<1, 1, (outs V128:$dst),
7002                    (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
7003                    "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
7004                    "|" # size # "\t$Rd$idx, $Rn$idx2}",
7005                    "$Rd = $dst",
7006          [(set V128:$dst,
7007                (vector_insert
7008                  (vectype V128:$Rd),
7009                  (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
7010                  idxtype:$idx))]>;
7011
7012 class SIMDInsMainMovAlias<string size, Instruction inst,
7013                           RegisterClass regtype, Operand idxtype>
7014     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
7015                         "|" # size #"\t$dst$idx, $src}",
7016                 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
7017 class SIMDInsElementMovAlias<string size, Instruction inst,
7018                              Operand idxtype>
7019     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
7020                       # "|" # size #"\t$dst$idx, $src$idx2}",
7021                 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
7022
7023
7024 multiclass SIMDIns {
7025   def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
7026     bits<4> idx;
7027     let Inst{20-17} = idx;
7028     let Inst{16} = 1;
7029   }
7030   def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
7031     bits<3> idx;
7032     let Inst{20-18} = idx;
7033     let Inst{17-16} = 0b10;
7034   }
7035   def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
7036     bits<2> idx;
7037     let Inst{20-19} = idx;
7038     let Inst{18-16} = 0b100;
7039   }
7040   def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
7041     bits<1> idx;
7042     let Inst{20} = idx;
7043     let Inst{19-16} = 0b1000;
7044   }
7045
7046   def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
7047     bits<4> idx;
7048     bits<4> idx2;
7049     let Inst{20-17} = idx;
7050     let Inst{16} = 1;
7051     let Inst{14-11} = idx2;
7052   }
7053   def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
7054     bits<3> idx;
7055     bits<3> idx2;
7056     let Inst{20-18} = idx;
7057     let Inst{17-16} = 0b10;
7058     let Inst{14-12} = idx2;
7059     let Inst{11} = {?};
7060   }
7061   def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
7062     bits<2> idx;
7063     bits<2> idx2;
7064     let Inst{20-19} = idx;
7065     let Inst{18-16} = 0b100;
7066     let Inst{14-13} = idx2;
7067     let Inst{12-11} = {?,?};
7068   }
7069   def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
7070     bits<1> idx;
7071     bits<1> idx2;
7072     let Inst{20} = idx;
7073     let Inst{19-16} = 0b1000;
7074     let Inst{14} = idx2;
7075     let Inst{13-11} = {?,?,?};
7076   }
7077
7078   // For all forms of the INS instruction, the "mov" mnemonic is the
7079   // preferred alias. Why they didn't just call the instruction "mov" in
7080   // the first place is a very good question indeed...
7081   def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
7082                          GPR32, VectorIndexB>;
7083   def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
7084                          GPR32, VectorIndexH>;
7085   def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
7086                          GPR32, VectorIndexS>;
7087   def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
7088                          GPR64, VectorIndexD>;
7089
7090   def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
7091                          VectorIndexB>;
7092   def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
7093                          VectorIndexH>;
7094   def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
7095                          VectorIndexS>;
7096   def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
7097                          VectorIndexD>;
7098 }
7099
7100 //----------------------------------------------------------------------------
7101 // AdvSIMD TBL/TBX
7102 //----------------------------------------------------------------------------
7103
7104 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7105 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7106                           RegisterOperand listtype, string asm, string kind>
7107   : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
7108        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
7109     Sched<[WriteV]> {
7110   bits<5> Vd;
7111   bits<5> Vn;
7112   bits<5> Vm;
7113   let Inst{31}    = 0;
7114   let Inst{30}    = Q;
7115   let Inst{29-21} = 0b001110000;
7116   let Inst{20-16} = Vm;
7117   let Inst{15}    = 0;
7118   let Inst{14-13} = len;
7119   let Inst{12}    = op;
7120   let Inst{11-10} = 0b00;
7121   let Inst{9-5}   = Vn;
7122   let Inst{4-0}   = Vd;
7123 }
7124
7125 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7126 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7127                           RegisterOperand listtype, string asm, string kind>
7128   : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
7129        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
7130     Sched<[WriteV]> {
7131   bits<5> Vd;
7132   bits<5> Vn;
7133   bits<5> Vm;
7134   let Inst{31}    = 0;
7135   let Inst{30}    = Q;
7136   let Inst{29-21} = 0b001110000;
7137   let Inst{20-16} = Vm;
7138   let Inst{15}    = 0;
7139   let Inst{14-13} = len;
7140   let Inst{12}    = op;
7141   let Inst{11-10} = 0b00;
7142   let Inst{9-5}   = Vn;
7143   let Inst{4-0}   = Vd;
7144 }
7145
7146 class SIMDTableLookupAlias<string asm, Instruction inst,
7147                           RegisterOperand vectype, RegisterOperand listtype>
7148     : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
7149                 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
7150
7151 multiclass SIMDTableLookup<bit op, string asm> {
7152   def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
7153                                       asm, ".8b">;
7154   def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
7155                                       asm, ".8b">;
7156   def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
7157                                       asm, ".8b">;
7158   def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
7159                                       asm, ".8b">;
7160   def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
7161                                       asm, ".16b">;
7162   def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
7163                                       asm, ".16b">;
7164   def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
7165                                       asm, ".16b">;
7166   def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
7167                                       asm, ".16b">;
7168
7169   def : SIMDTableLookupAlias<asm # ".8b",
7170                          !cast<Instruction>(NAME#"v8i8One"),
7171                          V64, VecListOne128>;
7172   def : SIMDTableLookupAlias<asm # ".8b",
7173                          !cast<Instruction>(NAME#"v8i8Two"),
7174                          V64, VecListTwo128>;
7175   def : SIMDTableLookupAlias<asm # ".8b",
7176                          !cast<Instruction>(NAME#"v8i8Three"),
7177                          V64, VecListThree128>;
7178   def : SIMDTableLookupAlias<asm # ".8b",
7179                          !cast<Instruction>(NAME#"v8i8Four"),
7180                          V64, VecListFour128>;
7181   def : SIMDTableLookupAlias<asm # ".16b",
7182                          !cast<Instruction>(NAME#"v16i8One"),
7183                          V128, VecListOne128>;
7184   def : SIMDTableLookupAlias<asm # ".16b",
7185                          !cast<Instruction>(NAME#"v16i8Two"),
7186                          V128, VecListTwo128>;
7187   def : SIMDTableLookupAlias<asm # ".16b",
7188                          !cast<Instruction>(NAME#"v16i8Three"),
7189                          V128, VecListThree128>;
7190   def : SIMDTableLookupAlias<asm # ".16b",
7191                          !cast<Instruction>(NAME#"v16i8Four"),
7192                          V128, VecListFour128>;
7193 }
7194
7195 multiclass SIMDTableLookupTied<bit op, string asm> {
7196   def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
7197                                       asm, ".8b">;
7198   def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
7199                                       asm, ".8b">;
7200   def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
7201                                       asm, ".8b">;
7202   def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
7203                                       asm, ".8b">;
7204   def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
7205                                       asm, ".16b">;
7206   def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
7207                                       asm, ".16b">;
7208   def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
7209                                       asm, ".16b">;
7210   def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
7211                                       asm, ".16b">;
7212
7213   def : SIMDTableLookupAlias<asm # ".8b",
7214                          !cast<Instruction>(NAME#"v8i8One"),
7215                          V64, VecListOne128>;
7216   def : SIMDTableLookupAlias<asm # ".8b",
7217                          !cast<Instruction>(NAME#"v8i8Two"),
7218                          V64, VecListTwo128>;
7219   def : SIMDTableLookupAlias<asm # ".8b",
7220                          !cast<Instruction>(NAME#"v8i8Three"),
7221                          V64, VecListThree128>;
7222   def : SIMDTableLookupAlias<asm # ".8b",
7223                          !cast<Instruction>(NAME#"v8i8Four"),
7224                          V64, VecListFour128>;
7225   def : SIMDTableLookupAlias<asm # ".16b",
7226                          !cast<Instruction>(NAME#"v16i8One"),
7227                          V128, VecListOne128>;
7228   def : SIMDTableLookupAlias<asm # ".16b",
7229                          !cast<Instruction>(NAME#"v16i8Two"),
7230                          V128, VecListTwo128>;
7231   def : SIMDTableLookupAlias<asm # ".16b",
7232                          !cast<Instruction>(NAME#"v16i8Three"),
7233                          V128, VecListThree128>;
7234   def : SIMDTableLookupAlias<asm # ".16b",
7235                          !cast<Instruction>(NAME#"v16i8Four"),
7236                          V128, VecListFour128>;
7237 }
7238
7239
7240 //----------------------------------------------------------------------------
7241 // AdvSIMD scalar CPY
7242 //----------------------------------------------------------------------------
7243 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7244 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
7245                         string kind, Operand idxtype>
7246   : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
7247        "{\t$dst, $src" # kind # "$idx" #
7248        "|\t$dst, $src$idx}", "", []>,
7249     Sched<[WriteV]> {
7250   bits<5> dst;
7251   bits<5> src;
7252   let Inst{31-21} = 0b01011110000;
7253   let Inst{15-10} = 0b000001;
7254   let Inst{9-5}   = src;
7255   let Inst{4-0}   = dst;
7256 }
7257
7258 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
7259       RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
7260     : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
7261                     # "|\t$dst, $src$index}",
7262                 (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
7263
7264
7265 multiclass SIMDScalarCPY<string asm> {
7266   def i8  : BaseSIMDScalarCPY<FPR8,  V128, ".b", VectorIndexB> {
7267     bits<4> idx;
7268     let Inst{20-17} = idx;
7269     let Inst{16} = 1;
7270   }
7271   def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
7272     bits<3> idx;
7273     let Inst{20-18} = idx;
7274     let Inst{17-16} = 0b10;
7275   }
7276   def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
7277     bits<2> idx;
7278     let Inst{20-19} = idx;
7279     let Inst{18-16} = 0b100;
7280   }
7281   def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
7282     bits<1> idx;
7283     let Inst{20} = idx;
7284     let Inst{19-16} = 0b1000;
7285   }
7286
7287   def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
7288                                                           VectorIndexD:$idx)))),
7289             (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
7290
7291   // 'DUP' mnemonic aliases.
7292   def : SIMDScalarCPYAlias<"dup", ".b",
7293                            !cast<Instruction>(NAME#"i8"),
7294                            FPR8, V128, VectorIndexB>;
7295   def : SIMDScalarCPYAlias<"dup", ".h",
7296                            !cast<Instruction>(NAME#"i16"),
7297                            FPR16, V128, VectorIndexH>;
7298   def : SIMDScalarCPYAlias<"dup", ".s",
7299                            !cast<Instruction>(NAME#"i32"),
7300                            FPR32, V128, VectorIndexS>;
7301   def : SIMDScalarCPYAlias<"dup", ".d",
7302                            !cast<Instruction>(NAME#"i64"),
7303                            FPR64, V128, VectorIndexD>;
7304 }
7305
7306 //----------------------------------------------------------------------------
7307 // AdvSIMD modified immediate instructions
7308 //----------------------------------------------------------------------------
7309
7310 class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
7311                           string asm, string op_string,
7312                           string cstr, list<dag> pattern>
7313   : I<oops, iops, asm, op_string, cstr, pattern>,
7314     Sched<[WriteV]> {
7315   bits<5> Rd;
7316   bits<8> imm8;
7317   let Inst{31}    = 0;
7318   let Inst{30}    = Q;
7319   let Inst{29}    = op;
7320   let Inst{28-19} = 0b0111100000;
7321   let Inst{18-16} = imm8{7-5};
7322   let Inst{11} = op2;
7323   let Inst{10} = 1;
7324   let Inst{9-5}   = imm8{4-0};
7325   let Inst{4-0}   = Rd;
7326 }
7327
7328 class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
7329                                 Operand immtype, dag opt_shift_iop,
7330                                 string opt_shift, string asm, string kind,
7331                                 list<dag> pattern>
7332   : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
7333                         !con((ins immtype:$imm8), opt_shift_iop), asm,
7334                         "{\t$Rd" # kind # ", $imm8" # opt_shift #
7335                         "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7336                         "", pattern> {
7337   let DecoderMethod = "DecodeModImmInstruction";
7338 }
7339
7340 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
7341                                 Operand immtype, dag opt_shift_iop,
7342                                 string opt_shift, string asm, string kind,
7343                                 list<dag> pattern>
7344   : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
7345                         !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
7346                         asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
7347                              "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7348                         "$Rd = $dst", pattern> {
7349   let DecoderMethod = "DecodeModImmTiedInstruction";
7350 }
7351
7352 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
7353                                      RegisterOperand vectype, string asm,
7354                                      string kind, list<dag> pattern>
7355   : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7356                               (ins logical_vec_shift:$shift),
7357                               "$shift", asm, kind, pattern> {
7358   bits<2> shift;
7359   let Inst{15}    = b15_b12{1};
7360   let Inst{14-13} = shift;
7361   let Inst{12}    = b15_b12{0};
7362 }
7363
7364 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
7365                                      RegisterOperand vectype, string asm,
7366                                      string kind, list<dag> pattern>
7367   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7368                               (ins logical_vec_shift:$shift),
7369                               "$shift", asm, kind, pattern> {
7370   bits<2> shift;
7371   let Inst{15}    = b15_b12{1};
7372   let Inst{14-13} = shift;
7373   let Inst{12}    = b15_b12{0};
7374 }
7375
7376
7377 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
7378                                          RegisterOperand vectype, string asm,
7379                                          string kind, list<dag> pattern>
7380   : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7381                               (ins logical_vec_hw_shift:$shift),
7382                               "$shift", asm, kind, pattern> {
7383   bits<2> shift;
7384   let Inst{15} = b15_b12{1};
7385   let Inst{14} = 0;
7386   let Inst{13} = shift{0};
7387   let Inst{12} = b15_b12{0};
7388 }
7389
7390 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
7391                                          RegisterOperand vectype, string asm,
7392                                          string kind, list<dag> pattern>
7393   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7394                               (ins logical_vec_hw_shift:$shift),
7395                               "$shift", asm, kind, pattern> {
7396   bits<2> shift;
7397   let Inst{15} = b15_b12{1};
7398   let Inst{14} = 0;
7399   let Inst{13} = shift{0};
7400   let Inst{12} = b15_b12{0};
7401 }
7402
7403 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
7404                                       string asm> {
7405   def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
7406                                                  asm, ".4h", []>;
7407   def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
7408                                                  asm, ".8h", []>;
7409
7410   def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
7411                                              asm, ".2s", []>;
7412   def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
7413                                              asm, ".4s", []>;
7414 }
7415
7416 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
7417                                       bits<2> w_cmode, string asm,
7418                                       SDNode OpNode> {
7419   def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
7420                                                  asm, ".4h",
7421              [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
7422                                              imm0_255:$imm8,
7423                                              (i32 imm:$shift)))]>;
7424   def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
7425                                                  asm, ".8h",
7426              [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
7427                                               imm0_255:$imm8,
7428                                               (i32 imm:$shift)))]>;
7429
7430   def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
7431                                              asm, ".2s",
7432              [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
7433                                              imm0_255:$imm8,
7434                                              (i32 imm:$shift)))]>;
7435   def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
7436                                              asm, ".4s",
7437              [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
7438                                               imm0_255:$imm8,
7439                                               (i32 imm:$shift)))]>;
7440 }
7441
7442 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
7443                              RegisterOperand vectype, string asm,
7444                              string kind, list<dag> pattern>
7445   : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7446                               (ins move_vec_shift:$shift),
7447                               "$shift", asm, kind, pattern> {
7448   bits<1> shift;
7449   let Inst{15-13} = cmode{3-1};
7450   let Inst{12}    = shift;
7451 }
7452
7453 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
7454                                    RegisterOperand vectype,
7455                                    Operand imm_type, string asm,
7456                                    string kind, list<dag> pattern>
7457   : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
7458                               asm, kind, pattern> {
7459   let Inst{15-12} = cmode;
7460 }
7461
7462 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
7463                                    list<dag> pattern>
7464   : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
7465                         "\t$Rd, $imm8", "", pattern> {
7466   let Inst{15-12} = cmode;
7467   let DecoderMethod = "DecodeModImmInstruction";
7468 }
7469
7470 //----------------------------------------------------------------------------
7471 // AdvSIMD indexed element
7472 //----------------------------------------------------------------------------
7473
7474 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7475 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7476                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
7477                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
7478                       string apple_kind, string dst_kind, string lhs_kind,
7479                       string rhs_kind, list<dag> pattern>
7480   : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
7481       asm,
7482       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7483       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
7484     Sched<[WriteV]> {
7485   bits<5> Rd;
7486   bits<5> Rn;
7487   bits<5> Rm;
7488
7489   let Inst{31}    = 0;
7490   let Inst{30}    = Q;
7491   let Inst{29}    = U;
7492   let Inst{28}    = Scalar;
7493   let Inst{27-24} = 0b1111;
7494   let Inst{23-22} = size;
7495   // Bit 21 must be set by the derived class.
7496   let Inst{20-16} = Rm;
7497   let Inst{15-12} = opc;
7498   // Bit 11 must be set by the derived class.
7499   let Inst{10}    = 0;
7500   let Inst{9-5}   = Rn;
7501   let Inst{4-0}   = Rd;
7502 }
7503
7504 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7505 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7506                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
7507                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
7508                       string apple_kind, string dst_kind, string lhs_kind,
7509                       string rhs_kind, list<dag> pattern>
7510   : I<(outs dst_reg:$dst),
7511       (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
7512       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7513       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
7514     Sched<[WriteV]> {
7515   bits<5> Rd;
7516   bits<5> Rn;
7517   bits<5> Rm;
7518
7519   let Inst{31}    = 0;
7520   let Inst{30}    = Q;
7521   let Inst{29}    = U;
7522   let Inst{28}    = Scalar;
7523   let Inst{27-24} = 0b1111;
7524   let Inst{23-22} = size;
7525   // Bit 21 must be set by the derived class.
7526   let Inst{20-16} = Rm;
7527   let Inst{15-12} = opc;
7528   // Bit 11 must be set by the derived class.
7529   let Inst{10}    = 0;
7530   let Inst{9-5}   = Rn;
7531   let Inst{4-0}   = Rd;
7532 }
7533
7534 // ARMv8.2-A Dot Product Instructions (Indexed)
7535 class BaseSIMDThreeSameVectorDotIndex<bit Q, bit U, string asm, string dst_kind,
7536                                       string lhs_kind, string rhs_kind,
7537                                       RegisterOperand RegType,
7538                                       ValueType AccumType, ValueType InputType,
7539                                       SDPatternOperator OpNode> :
7540         BaseSIMDIndexedTied<Q, U, 0b0, 0b10, 0b1110, RegType, RegType, V128,
7541                             VectorIndexS, asm, "", dst_kind, lhs_kind, rhs_kind,
7542         [(set (AccumType RegType:$dst),
7543               (AccumType (OpNode (AccumType RegType:$Rd),
7544                                  (InputType RegType:$Rn),
7545                                  (InputType (bitconvert (AccumType
7546                                     (AArch64duplane32 (v4i32 V128:$Rm),
7547                                         VectorIndexS:$idx)))))))]> {
7548   bits<2> idx;
7549   let Inst{21}    = idx{0};  // L
7550   let Inst{11}    = idx{1};  // H
7551 }
7552
7553 multiclass SIMDThreeSameVectorDotIndex<bit U, string asm,
7554                                        SDPatternOperator OpNode> {
7555   def v8i8  : BaseSIMDThreeSameVectorDotIndex<0, U, asm, ".2s", ".8b", ".4b",
7556                                               V64, v2i32, v8i8, OpNode>;
7557   def v16i8 : BaseSIMDThreeSameVectorDotIndex<1, U, asm, ".4s", ".16b", ".4b",
7558                                               V128, v4i32, v16i8, OpNode>;
7559 }
7560
7561 // ARMv8.2-A Fused Multiply Add-Long Instructions (Indexed)
7562 class BaseSIMDThreeSameVectorFMLIndex<bit Q, bit U, bits<4> opc, string asm,
7563                                       string dst_kind, string lhs_kind,
7564                                       string rhs_kind, RegisterOperand RegType,
7565                                       ValueType AccumType, ValueType InputType,
7566                                       SDPatternOperator OpNode> :
7567         BaseSIMDIndexedTied<Q, U, 0, 0b10, opc, RegType, RegType, V128,
7568                             VectorIndexH, asm, "", dst_kind, lhs_kind, rhs_kind,
7569           [(set (AccumType RegType:$dst),
7570                 (AccumType (OpNode (AccumType RegType:$Rd),
7571                                    (InputType RegType:$Rn),
7572                                    (InputType (AArch64duplane16 (v8f16 V128:$Rm),
7573                                                 VectorIndexH:$idx)))))]> {
7574   // idx = H:L:M
7575   bits<3> idx;
7576   let Inst{11} = idx{2}; // H
7577   let Inst{21} = idx{1}; // L
7578   let Inst{20} = idx{0}; // M
7579 }
7580
7581 multiclass SIMDThreeSameVectorFMLIndex<bit U, bits<4> opc, string asm,
7582                                        SDPatternOperator OpNode> {
7583   def v4f16 : BaseSIMDThreeSameVectorFMLIndex<0, U, opc, asm, ".2s", ".2h", ".h",
7584                                               V64, v2f32, v4f16, OpNode>;
7585   def v8f16 : BaseSIMDThreeSameVectorFMLIndex<1, U, opc, asm, ".4s", ".4h", ".h",
7586                                               V128, v4f32, v8f16, OpNode>;
7587 }
7588
7589 multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
7590                          SDPatternOperator OpNode> {
7591   let Predicates = [HasNEON, HasFullFP16] in {
7592   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
7593                                       V64, V64,
7594                                       V128_lo, VectorIndexH,
7595                                       asm, ".4h", ".4h", ".4h", ".h",
7596     [(set (v4f16 V64:$Rd),
7597         (OpNode (v4f16 V64:$Rn),
7598          (v4f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7599     bits<3> idx;
7600     let Inst{11} = idx{2};
7601     let Inst{21} = idx{1};
7602     let Inst{20} = idx{0};
7603   }
7604
7605   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
7606                                       V128, V128,
7607                                       V128_lo, VectorIndexH,
7608                                       asm, ".8h", ".8h", ".8h", ".h",
7609     [(set (v8f16 V128:$Rd),
7610         (OpNode (v8f16 V128:$Rn),
7611          (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7612     bits<3> idx;
7613     let Inst{11} = idx{2};
7614     let Inst{21} = idx{1};
7615     let Inst{20} = idx{0};
7616   }
7617   } // Predicates = [HasNEON, HasFullFP16]
7618
7619   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7620                                       V64, V64,
7621                                       V128, VectorIndexS,
7622                                       asm, ".2s", ".2s", ".2s", ".s",
7623     [(set (v2f32 V64:$Rd),
7624         (OpNode (v2f32 V64:$Rn),
7625          (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
7626     bits<2> idx;
7627     let Inst{11} = idx{1};
7628     let Inst{21} = idx{0};
7629   }
7630
7631   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7632                                       V128, V128,
7633                                       V128, VectorIndexS,
7634                                       asm, ".4s", ".4s", ".4s", ".s",
7635     [(set (v4f32 V128:$Rd),
7636         (OpNode (v4f32 V128:$Rn),
7637          (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
7638     bits<2> idx;
7639     let Inst{11} = idx{1};
7640     let Inst{21} = idx{0};
7641   }
7642
7643   def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
7644                                       V128, V128,
7645                                       V128, VectorIndexD,
7646                                       asm, ".2d", ".2d", ".2d", ".d",
7647     [(set (v2f64 V128:$Rd),
7648         (OpNode (v2f64 V128:$Rn),
7649          (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
7650     bits<1> idx;
7651     let Inst{11} = idx{0};
7652     let Inst{21} = 0;
7653   }
7654
7655   let Predicates = [HasNEON, HasFullFP16] in {
7656   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
7657                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7658                                       asm, ".h", "", "", ".h",
7659     [(set (f16 FPR16Op:$Rd),
7660           (OpNode (f16 FPR16Op:$Rn),
7661                   (f16 (vector_extract (v8f16 V128_lo:$Rm),
7662                                        VectorIndexH:$idx))))]> {
7663     bits<3> idx;
7664     let Inst{11} = idx{2};
7665     let Inst{21} = idx{1};
7666     let Inst{20} = idx{0};
7667   }
7668   } // Predicates = [HasNEON, HasFullFP16]
7669
7670   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7671                                       FPR32Op, FPR32Op, V128, VectorIndexS,
7672                                       asm, ".s", "", "", ".s",
7673     [(set (f32 FPR32Op:$Rd),
7674           (OpNode (f32 FPR32Op:$Rn),
7675                   (f32 (vector_extract (v4f32 V128:$Rm),
7676                                        VectorIndexS:$idx))))]> {
7677     bits<2> idx;
7678     let Inst{11} = idx{1};
7679     let Inst{21} = idx{0};
7680   }
7681
7682   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
7683                                       FPR64Op, FPR64Op, V128, VectorIndexD,
7684                                       asm, ".d", "", "", ".d",
7685     [(set (f64 FPR64Op:$Rd),
7686           (OpNode (f64 FPR64Op:$Rn),
7687                   (f64 (vector_extract (v2f64 V128:$Rm),
7688                                        VectorIndexD:$idx))))]> {
7689     bits<1> idx;
7690     let Inst{11} = idx{0};
7691     let Inst{21} = 0;
7692   }
7693 }
7694
7695 multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
7696   // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
7697   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
7698                            (AArch64duplane32 (v4f32 V128:$Rm),
7699                                            VectorIndexS:$idx))),
7700             (!cast<Instruction>(INST # v2i32_indexed)
7701                 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7702   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
7703                            (AArch64dup (f32 FPR32Op:$Rm)))),
7704             (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
7705                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
7706
7707
7708   // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
7709   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
7710                            (AArch64duplane32 (v4f32 V128:$Rm),
7711                                            VectorIndexS:$idx))),
7712             (!cast<Instruction>(INST # "v4i32_indexed")
7713                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7714   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
7715                            (AArch64dup (f32 FPR32Op:$Rm)))),
7716             (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
7717                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
7718
7719   // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
7720   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
7721                            (AArch64duplane64 (v2f64 V128:$Rm),
7722                                            VectorIndexD:$idx))),
7723             (!cast<Instruction>(INST # "v2i64_indexed")
7724                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7725   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
7726                            (AArch64dup (f64 FPR64Op:$Rm)))),
7727             (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
7728                 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
7729
7730   // 2 variants for 32-bit scalar version: extract from .2s or from .4s
7731   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
7732                          (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
7733             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
7734                 V128:$Rm, VectorIndexS:$idx)>;
7735   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
7736                          (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
7737             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
7738                 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
7739
7740   // 1 variant for 64-bit scalar version: extract from .1d or from .2d
7741   def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
7742                          (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
7743             (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
7744                 V128:$Rm, VectorIndexD:$idx)>;
7745 }
7746
7747 multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
7748   let Predicates = [HasNEON, HasFullFP16] in {
7749   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
7750                                           V128_lo, VectorIndexH,
7751                                           asm, ".4h", ".4h", ".4h", ".h", []> {
7752     bits<3> idx;
7753     let Inst{11} = idx{2};
7754     let Inst{21} = idx{1};
7755     let Inst{20} = idx{0};
7756   }
7757
7758   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
7759                                           V128, V128,
7760                                           V128_lo, VectorIndexH,
7761                                           asm, ".8h", ".8h", ".8h", ".h", []> {
7762     bits<3> idx;
7763     let Inst{11} = idx{2};
7764     let Inst{21} = idx{1};
7765     let Inst{20} = idx{0};
7766   }
7767   } // Predicates = [HasNEON, HasFullFP16]
7768
7769   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
7770                                           V128, VectorIndexS,
7771                                           asm, ".2s", ".2s", ".2s", ".s", []> {
7772     bits<2> idx;
7773     let Inst{11} = idx{1};
7774     let Inst{21} = idx{0};
7775   }
7776
7777   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7778                                       V128, V128,
7779                                       V128, VectorIndexS,
7780                                       asm, ".4s", ".4s", ".4s", ".s", []> {
7781     bits<2> idx;
7782     let Inst{11} = idx{1};
7783     let Inst{21} = idx{0};
7784   }
7785
7786   def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
7787                                       V128, V128,
7788                                       V128, VectorIndexD,
7789                                       asm, ".2d", ".2d", ".2d", ".d", []> {
7790     bits<1> idx;
7791     let Inst{11} = idx{0};
7792     let Inst{21} = 0;
7793   }
7794
7795   let Predicates = [HasNEON, HasFullFP16] in {
7796   def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
7797                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7798                                       asm, ".h", "", "", ".h", []> {
7799     bits<3> idx;
7800     let Inst{11} = idx{2};
7801     let Inst{21} = idx{1};
7802     let Inst{20} = idx{0};
7803   }
7804   } // Predicates = [HasNEON, HasFullFP16]
7805
7806   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
7807                                       FPR32Op, FPR32Op, V128, VectorIndexS,
7808                                       asm, ".s", "", "", ".s", []> {
7809     bits<2> idx;
7810     let Inst{11} = idx{1};
7811     let Inst{21} = idx{0};
7812   }
7813
7814   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
7815                                       FPR64Op, FPR64Op, V128, VectorIndexD,
7816                                       asm, ".d", "", "", ".d", []> {
7817     bits<1> idx;
7818     let Inst{11} = idx{0};
7819     let Inst{21} = 0;
7820   }
7821 }
7822
7823 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
7824                          SDPatternOperator OpNode> {
7825   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
7826                                       V128_lo, VectorIndexH,
7827                                       asm, ".4h", ".4h", ".4h", ".h",
7828     [(set (v4i16 V64:$Rd),
7829         (OpNode (v4i16 V64:$Rn),
7830          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7831     bits<3> idx;
7832     let Inst{11} = idx{2};
7833     let Inst{21} = idx{1};
7834     let Inst{20} = idx{0};
7835   }
7836
7837   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7838                                       V128, V128,
7839                                       V128_lo, VectorIndexH,
7840                                       asm, ".8h", ".8h", ".8h", ".h",
7841     [(set (v8i16 V128:$Rd),
7842        (OpNode (v8i16 V128:$Rn),
7843          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7844     bits<3> idx;
7845     let Inst{11} = idx{2};
7846     let Inst{21} = idx{1};
7847     let Inst{20} = idx{0};
7848   }
7849
7850   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7851                                       V64, V64,
7852                                       V128, VectorIndexS,
7853                                       asm, ".2s", ".2s", ".2s",  ".s",
7854     [(set (v2i32 V64:$Rd),
7855        (OpNode (v2i32 V64:$Rn),
7856           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7857     bits<2> idx;
7858     let Inst{11} = idx{1};
7859     let Inst{21} = idx{0};
7860   }
7861
7862   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7863                                       V128, V128,
7864                                       V128, VectorIndexS,
7865                                       asm, ".4s", ".4s", ".4s", ".s",
7866     [(set (v4i32 V128:$Rd),
7867        (OpNode (v4i32 V128:$Rn),
7868           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7869     bits<2> idx;
7870     let Inst{11} = idx{1};
7871     let Inst{21} = idx{0};
7872   }
7873
7874   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
7875                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7876                                       asm, ".h", "", "", ".h", []> {
7877     bits<3> idx;
7878     let Inst{11} = idx{2};
7879     let Inst{21} = idx{1};
7880     let Inst{20} = idx{0};
7881   }
7882
7883   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7884                                       FPR32Op, FPR32Op, V128, VectorIndexS,
7885                                       asm, ".s", "", "", ".s",
7886       [(set (i32 FPR32Op:$Rd),
7887             (OpNode FPR32Op:$Rn,
7888                     (i32 (vector_extract (v4i32 V128:$Rm),
7889                                          VectorIndexS:$idx))))]> {
7890     bits<2> idx;
7891     let Inst{11} = idx{1};
7892     let Inst{21} = idx{0};
7893   }
7894 }
7895
7896 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
7897                                SDPatternOperator OpNode> {
7898   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7899                                       V64, V64,
7900                                       V128_lo, VectorIndexH,
7901                                       asm, ".4h", ".4h", ".4h", ".h",
7902     [(set (v4i16 V64:$Rd),
7903         (OpNode (v4i16 V64:$Rn),
7904          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7905     bits<3> idx;
7906     let Inst{11} = idx{2};
7907     let Inst{21} = idx{1};
7908     let Inst{20} = idx{0};
7909   }
7910
7911   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7912                                       V128, V128,
7913                                       V128_lo, VectorIndexH,
7914                                       asm, ".8h", ".8h", ".8h", ".h",
7915     [(set (v8i16 V128:$Rd),
7916        (OpNode (v8i16 V128:$Rn),
7917          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7918     bits<3> idx;
7919     let Inst{11} = idx{2};
7920     let Inst{21} = idx{1};
7921     let Inst{20} = idx{0};
7922   }
7923
7924   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7925                                       V64, V64,
7926                                       V128, VectorIndexS,
7927                                       asm, ".2s", ".2s", ".2s", ".s",
7928     [(set (v2i32 V64:$Rd),
7929        (OpNode (v2i32 V64:$Rn),
7930           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7931     bits<2> idx;
7932     let Inst{11} = idx{1};
7933     let Inst{21} = idx{0};
7934   }
7935
7936   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7937                                       V128, V128,
7938                                       V128, VectorIndexS,
7939                                       asm, ".4s", ".4s", ".4s", ".s",
7940     [(set (v4i32 V128:$Rd),
7941        (OpNode (v4i32 V128:$Rn),
7942           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7943     bits<2> idx;
7944     let Inst{11} = idx{1};
7945     let Inst{21} = idx{0};
7946   }
7947 }
7948
7949 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
7950                                    SDPatternOperator OpNode> {
7951   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
7952                                           V128_lo, VectorIndexH,
7953                                           asm, ".4h", ".4h", ".4h", ".h",
7954     [(set (v4i16 V64:$dst),
7955         (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
7956          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7957     bits<3> idx;
7958     let Inst{11} = idx{2};
7959     let Inst{21} = idx{1};
7960     let Inst{20} = idx{0};
7961   }
7962
7963   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7964                                       V128, V128,
7965                                       V128_lo, VectorIndexH,
7966                                       asm, ".8h", ".8h", ".8h", ".h",
7967     [(set (v8i16 V128:$dst),
7968        (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7969          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7970     bits<3> idx;
7971     let Inst{11} = idx{2};
7972     let Inst{21} = idx{1};
7973     let Inst{20} = idx{0};
7974   }
7975
7976   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7977                                       V64, V64,
7978                                       V128, VectorIndexS,
7979                                       asm, ".2s", ".2s", ".2s", ".s",
7980     [(set (v2i32 V64:$dst),
7981        (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7982           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7983     bits<2> idx;
7984     let Inst{11} = idx{1};
7985     let Inst{21} = idx{0};
7986   }
7987
7988   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7989                                       V128, V128,
7990                                       V128, VectorIndexS,
7991                                       asm, ".4s", ".4s", ".4s", ".s",
7992     [(set (v4i32 V128:$dst),
7993        (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7994           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7995     bits<2> idx;
7996     let Inst{11} = idx{1};
7997     let Inst{21} = idx{0};
7998   }
7999 }
8000
8001 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
8002                              SDPatternOperator OpNode> {
8003   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8004                                       V128, V64,
8005                                       V128_lo, VectorIndexH,
8006                                       asm, ".4s", ".4s", ".4h", ".h",
8007     [(set (v4i32 V128:$Rd),
8008         (OpNode (v4i16 V64:$Rn),
8009          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8010     bits<3> idx;
8011     let Inst{11} = idx{2};
8012     let Inst{21} = idx{1};
8013     let Inst{20} = idx{0};
8014   }
8015
8016   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8017                                       V128, V128,
8018                                       V128_lo, VectorIndexH,
8019                                       asm#"2", ".4s", ".4s", ".8h", ".h",
8020     [(set (v4i32 V128:$Rd),
8021           (OpNode (extract_high_v8i16 V128:$Rn),
8022                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8023                                                       VectorIndexH:$idx))))]> {
8024
8025     bits<3> idx;
8026     let Inst{11} = idx{2};
8027     let Inst{21} = idx{1};
8028     let Inst{20} = idx{0};
8029   }
8030
8031   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8032                                       V128, V64,
8033                                       V128, VectorIndexS,
8034                                       asm, ".2d", ".2d", ".2s", ".s",
8035     [(set (v2i64 V128:$Rd),
8036         (OpNode (v2i32 V64:$Rn),
8037          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8038     bits<2> idx;
8039     let Inst{11} = idx{1};
8040     let Inst{21} = idx{0};
8041   }
8042
8043   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8044                                       V128, V128,
8045                                       V128, VectorIndexS,
8046                                       asm#"2", ".2d", ".2d", ".4s", ".s",
8047     [(set (v2i64 V128:$Rd),
8048           (OpNode (extract_high_v4i32 V128:$Rn),
8049                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8050                                                       VectorIndexS:$idx))))]> {
8051     bits<2> idx;
8052     let Inst{11} = idx{1};
8053     let Inst{21} = idx{0};
8054   }
8055
8056   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8057                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8058                                       asm, ".h", "", "", ".h", []> {
8059     bits<3> idx;
8060     let Inst{11} = idx{2};
8061     let Inst{21} = idx{1};
8062     let Inst{20} = idx{0};
8063   }
8064
8065   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8066                                       FPR64Op, FPR32Op, V128, VectorIndexS,
8067                                       asm, ".s", "", "", ".s", []> {
8068     bits<2> idx;
8069     let Inst{11} = idx{1};
8070     let Inst{21} = idx{0};
8071   }
8072 }
8073
8074 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
8075                                        SDPatternOperator Accum> {
8076   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8077                                       V128, V64,
8078                                       V128_lo, VectorIndexH,
8079                                       asm, ".4s", ".4s", ".4h", ".h",
8080     [(set (v4i32 V128:$dst),
8081           (Accum (v4i32 V128:$Rd),
8082                  (v4i32 (int_aarch64_neon_sqdmull
8083                              (v4i16 V64:$Rn),
8084                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8085                                                     VectorIndexH:$idx))))))]> {
8086     bits<3> idx;
8087     let Inst{11} = idx{2};
8088     let Inst{21} = idx{1};
8089     let Inst{20} = idx{0};
8090   }
8091
8092   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
8093   // intermediate EXTRACT_SUBREG would be untyped.
8094   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8095                 (i32 (vector_extract (v4i32
8096                          (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
8097                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8098                                                     VectorIndexH:$idx)))),
8099                          (i64 0))))),
8100             (EXTRACT_SUBREG
8101                 (!cast<Instruction>(NAME # v4i16_indexed)
8102                     (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
8103                     V128_lo:$Rm, VectorIndexH:$idx),
8104                 ssub)>;
8105
8106   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8107                                       V128, V128,
8108                                       V128_lo, VectorIndexH,
8109                                       asm#"2", ".4s", ".4s", ".8h", ".h",
8110     [(set (v4i32 V128:$dst),
8111           (Accum (v4i32 V128:$Rd),
8112                  (v4i32 (int_aarch64_neon_sqdmull
8113                             (extract_high_v8i16 V128:$Rn),
8114                             (extract_high_v8i16
8115                                 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8116                                                 VectorIndexH:$idx))))))]> {
8117     bits<3> idx;
8118     let Inst{11} = idx{2};
8119     let Inst{21} = idx{1};
8120     let Inst{20} = idx{0};
8121   }
8122
8123   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8124                                       V128, V64,
8125                                       V128, VectorIndexS,
8126                                       asm, ".2d", ".2d", ".2s", ".s",
8127     [(set (v2i64 V128:$dst),
8128         (Accum (v2i64 V128:$Rd),
8129                (v2i64 (int_aarch64_neon_sqdmull
8130                           (v2i32 V64:$Rn),
8131                           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
8132                                                  VectorIndexS:$idx))))))]> {
8133     bits<2> idx;
8134     let Inst{11} = idx{1};
8135     let Inst{21} = idx{0};
8136   }
8137
8138   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8139                                       V128, V128,
8140                                       V128, VectorIndexS,
8141                                       asm#"2", ".2d", ".2d", ".4s", ".s",
8142     [(set (v2i64 V128:$dst),
8143           (Accum (v2i64 V128:$Rd),
8144                  (v2i64 (int_aarch64_neon_sqdmull
8145                             (extract_high_v4i32 V128:$Rn),
8146                             (extract_high_v4i32
8147                                 (AArch64duplane32 (v4i32 V128:$Rm),
8148                                                 VectorIndexS:$idx))))))]> {
8149     bits<2> idx;
8150     let Inst{11} = idx{1};
8151     let Inst{21} = idx{0};
8152   }
8153
8154   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
8155                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8156                                       asm, ".h", "", "", ".h", []> {
8157     bits<3> idx;
8158     let Inst{11} = idx{2};
8159     let Inst{21} = idx{1};
8160     let Inst{20} = idx{0};
8161   }
8162
8163
8164   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8165                                       FPR64Op, FPR32Op, V128, VectorIndexS,
8166                                       asm, ".s", "", "", ".s",
8167     [(set (i64 FPR64Op:$dst),
8168           (Accum (i64 FPR64Op:$Rd),
8169                  (i64 (int_aarch64_neon_sqdmulls_scalar
8170                             (i32 FPR32Op:$Rn),
8171                             (i32 (vector_extract (v4i32 V128:$Rm),
8172                                                  VectorIndexS:$idx))))))]> {
8173
8174     bits<2> idx;
8175     let Inst{11} = idx{1};
8176     let Inst{21} = idx{0};
8177   }
8178 }
8179
8180 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
8181                                    SDPatternOperator OpNode> {
8182   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8183   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8184                                       V128, V64,
8185                                       V128_lo, VectorIndexH,
8186                                       asm, ".4s", ".4s", ".4h", ".h",
8187     [(set (v4i32 V128:$Rd),
8188         (OpNode (v4i16 V64:$Rn),
8189          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8190     bits<3> idx;
8191     let Inst{11} = idx{2};
8192     let Inst{21} = idx{1};
8193     let Inst{20} = idx{0};
8194   }
8195
8196   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8197                                       V128, V128,
8198                                       V128_lo, VectorIndexH,
8199                                       asm#"2", ".4s", ".4s", ".8h", ".h",
8200     [(set (v4i32 V128:$Rd),
8201           (OpNode (extract_high_v8i16 V128:$Rn),
8202                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8203                                                       VectorIndexH:$idx))))]> {
8204
8205     bits<3> idx;
8206     let Inst{11} = idx{2};
8207     let Inst{21} = idx{1};
8208     let Inst{20} = idx{0};
8209   }
8210
8211   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8212                                       V128, V64,
8213                                       V128, VectorIndexS,
8214                                       asm, ".2d", ".2d", ".2s", ".s",
8215     [(set (v2i64 V128:$Rd),
8216         (OpNode (v2i32 V64:$Rn),
8217          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8218     bits<2> idx;
8219     let Inst{11} = idx{1};
8220     let Inst{21} = idx{0};
8221   }
8222
8223   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8224                                       V128, V128,
8225                                       V128, VectorIndexS,
8226                                       asm#"2", ".2d", ".2d", ".4s", ".s",
8227     [(set (v2i64 V128:$Rd),
8228           (OpNode (extract_high_v4i32 V128:$Rn),
8229                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8230                                                       VectorIndexS:$idx))))]> {
8231     bits<2> idx;
8232     let Inst{11} = idx{1};
8233     let Inst{21} = idx{0};
8234   }
8235   }
8236 }
8237
8238 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
8239                                        SDPatternOperator OpNode> {
8240   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8241   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8242                                       V128, V64,
8243                                       V128_lo, VectorIndexH,
8244                                       asm, ".4s", ".4s", ".4h", ".h",
8245     [(set (v4i32 V128:$dst),
8246         (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
8247          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8248     bits<3> idx;
8249     let Inst{11} = idx{2};
8250     let Inst{21} = idx{1};
8251     let Inst{20} = idx{0};
8252   }
8253
8254   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8255                                       V128, V128,
8256                                       V128_lo, VectorIndexH,
8257                                       asm#"2", ".4s", ".4s", ".8h", ".h",
8258     [(set (v4i32 V128:$dst),
8259           (OpNode (v4i32 V128:$Rd),
8260                   (extract_high_v8i16 V128:$Rn),
8261                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8262                                                       VectorIndexH:$idx))))]> {
8263     bits<3> idx;
8264     let Inst{11} = idx{2};
8265     let Inst{21} = idx{1};
8266     let Inst{20} = idx{0};
8267   }
8268
8269   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8270                                       V128, V64,
8271                                       V128, VectorIndexS,
8272                                       asm, ".2d", ".2d", ".2s", ".s",
8273     [(set (v2i64 V128:$dst),
8274         (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
8275          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8276     bits<2> idx;
8277     let Inst{11} = idx{1};
8278     let Inst{21} = idx{0};
8279   }
8280
8281   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8282                                       V128, V128,
8283                                       V128, VectorIndexS,
8284                                       asm#"2", ".2d", ".2d", ".4s", ".s",
8285     [(set (v2i64 V128:$dst),
8286           (OpNode (v2i64 V128:$Rd),
8287                   (extract_high_v4i32 V128:$Rn),
8288                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8289                                                       VectorIndexS:$idx))))]> {
8290     bits<2> idx;
8291     let Inst{11} = idx{1};
8292     let Inst{21} = idx{0};
8293   }
8294   }
8295 }
8296
8297 //----------------------------------------------------------------------------
8298 // AdvSIMD scalar shift by immediate
8299 //----------------------------------------------------------------------------
8300
8301 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8302 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
8303                      RegisterClass regtype1, RegisterClass regtype2,
8304                      Operand immtype, string asm, list<dag> pattern>
8305   : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
8306       asm, "\t$Rd, $Rn, $imm", "", pattern>,
8307     Sched<[WriteV]> {
8308   bits<5> Rd;
8309   bits<5> Rn;
8310   bits<7> imm;
8311   let Inst{31-30} = 0b01;
8312   let Inst{29}    = U;
8313   let Inst{28-23} = 0b111110;
8314   let Inst{22-16} = fixed_imm;
8315   let Inst{15-11} = opc;
8316   let Inst{10}    = 1;
8317   let Inst{9-5} = Rn;
8318   let Inst{4-0} = Rd;
8319 }
8320
8321 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8322 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
8323                      RegisterClass regtype1, RegisterClass regtype2,
8324                      Operand immtype, string asm, list<dag> pattern>
8325   : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
8326       asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
8327     Sched<[WriteV]> {
8328   bits<5> Rd;
8329   bits<5> Rn;
8330   bits<7> imm;
8331   let Inst{31-30} = 0b01;
8332   let Inst{29}    = U;
8333   let Inst{28-23} = 0b111110;
8334   let Inst{22-16} = fixed_imm;
8335   let Inst{15-11} = opc;
8336   let Inst{10}    = 1;
8337   let Inst{9-5} = Rn;
8338   let Inst{4-0} = Rd;
8339 }
8340
8341
8342 multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
8343   let Predicates = [HasNEON, HasFullFP16] in {
8344   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8345                               FPR16, FPR16, vecshiftR16, asm, []> {
8346     let Inst{19-16} = imm{3-0};
8347   }
8348   } // Predicates = [HasNEON, HasFullFP16]
8349   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8350                               FPR32, FPR32, vecshiftR32, asm, []> {
8351     let Inst{20-16} = imm{4-0};
8352   }
8353   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8354                               FPR64, FPR64, vecshiftR64, asm, []> {
8355     let Inst{21-16} = imm{5-0};
8356   }
8357 }
8358
8359 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
8360                              SDPatternOperator OpNode> {
8361   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8362                               FPR64, FPR64, vecshiftR64, asm,
8363   [(set (i64 FPR64:$Rd),
8364      (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
8365     let Inst{21-16} = imm{5-0};
8366   }
8367
8368   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
8369             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
8370 }
8371
8372 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
8373                                  SDPatternOperator OpNode = null_frag> {
8374   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8375                               FPR64, FPR64, vecshiftR64, asm,
8376   [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
8377                                                    (i32 vecshiftR64:$imm)))]> {
8378     let Inst{21-16} = imm{5-0};
8379   }
8380
8381   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
8382                            (i32 vecshiftR64:$imm))),
8383             (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
8384                                             vecshiftR64:$imm)>;
8385 }
8386
8387 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
8388                              SDPatternOperator OpNode> {
8389   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8390                               FPR64, FPR64, vecshiftL64, asm,
8391     [(set (v1i64 FPR64:$Rd),
8392        (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8393     let Inst{21-16} = imm{5-0};
8394   }
8395 }
8396
8397 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8398 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
8399   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8400                               FPR64, FPR64, vecshiftL64, asm, []> {
8401     let Inst{21-16} = imm{5-0};
8402   }
8403 }
8404
8405 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8406 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
8407                                SDPatternOperator OpNode = null_frag> {
8408   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8409                               FPR8, FPR16, vecshiftR8, asm, []> {
8410     let Inst{18-16} = imm{2-0};
8411   }
8412
8413   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8414                               FPR16, FPR32, vecshiftR16, asm, []> {
8415     let Inst{19-16} = imm{3-0};
8416   }
8417
8418   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8419                               FPR32, FPR64, vecshiftR32, asm,
8420     [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
8421     let Inst{20-16} = imm{4-0};
8422   }
8423 }
8424
8425 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
8426                                 SDPatternOperator OpNode> {
8427   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8428                               FPR8, FPR8, vecshiftL8, asm, []> {
8429     let Inst{18-16} = imm{2-0};
8430   }
8431
8432   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8433                               FPR16, FPR16, vecshiftL16, asm, []> {
8434     let Inst{19-16} = imm{3-0};
8435   }
8436
8437   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8438                               FPR32, FPR32, vecshiftL32, asm,
8439     [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
8440     let Inst{20-16} = imm{4-0};
8441   }
8442
8443   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8444                               FPR64, FPR64, vecshiftL64, asm,
8445     [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8446     let Inst{21-16} = imm{5-0};
8447   }
8448
8449   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
8450             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
8451 }
8452
8453 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
8454   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8455                               FPR8, FPR8, vecshiftR8, asm, []> {
8456     let Inst{18-16} = imm{2-0};
8457   }
8458
8459   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8460                               FPR16, FPR16, vecshiftR16, asm, []> {
8461     let Inst{19-16} = imm{3-0};
8462   }
8463
8464   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8465                               FPR32, FPR32, vecshiftR32, asm, []> {
8466     let Inst{20-16} = imm{4-0};
8467   }
8468
8469   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8470                               FPR64, FPR64, vecshiftR64, asm, []> {
8471     let Inst{21-16} = imm{5-0};
8472   }
8473 }
8474
8475 //----------------------------------------------------------------------------
8476 // AdvSIMD vector x indexed element
8477 //----------------------------------------------------------------------------
8478
8479 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8480 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
8481                      RegisterOperand dst_reg, RegisterOperand src_reg,
8482                      Operand immtype,
8483                      string asm, string dst_kind, string src_kind,
8484                      list<dag> pattern>
8485   : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
8486       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
8487            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
8488     Sched<[WriteV]> {
8489   bits<5> Rd;
8490   bits<5> Rn;
8491   let Inst{31}    = 0;
8492   let Inst{30}    = Q;
8493   let Inst{29}    = U;
8494   let Inst{28-23} = 0b011110;
8495   let Inst{22-16} = fixed_imm;
8496   let Inst{15-11} = opc;
8497   let Inst{10}    = 1;
8498   let Inst{9-5}   = Rn;
8499   let Inst{4-0}   = Rd;
8500 }
8501
8502 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8503 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
8504                      RegisterOperand vectype1, RegisterOperand vectype2,
8505                      Operand immtype,
8506                      string asm, string dst_kind, string src_kind,
8507                      list<dag> pattern>
8508   : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
8509       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
8510            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
8511     Sched<[WriteV]> {
8512   bits<5> Rd;
8513   bits<5> Rn;
8514   let Inst{31}    = 0;
8515   let Inst{30}    = Q;
8516   let Inst{29}    = U;
8517   let Inst{28-23} = 0b011110;
8518   let Inst{22-16} = fixed_imm;
8519   let Inst{15-11} = opc;
8520   let Inst{10}    = 1;
8521   let Inst{9-5}   = Rn;
8522   let Inst{4-0}   = Rd;
8523 }
8524
8525 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
8526                               Intrinsic OpNode> {
8527   let Predicates = [HasNEON, HasFullFP16] in {
8528   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8529                                   V64, V64, vecshiftR16,
8530                                   asm, ".4h", ".4h",
8531       [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
8532     bits<4> imm;
8533     let Inst{19-16} = imm;
8534   }
8535
8536   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8537                                   V128, V128, vecshiftR16,
8538                                   asm, ".8h", ".8h",
8539       [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
8540     bits<4> imm;
8541     let Inst{19-16} = imm;
8542   }
8543   } // Predicates = [HasNEON, HasFullFP16]
8544   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8545                                   V64, V64, vecshiftR32,
8546                                   asm, ".2s", ".2s",
8547       [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
8548     bits<5> imm;
8549     let Inst{20-16} = imm;
8550   }
8551
8552   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8553                                   V128, V128, vecshiftR32,
8554                                   asm, ".4s", ".4s",
8555       [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
8556     bits<5> imm;
8557     let Inst{20-16} = imm;
8558   }
8559
8560   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8561                                   V128, V128, vecshiftR64,
8562                                   asm, ".2d", ".2d",
8563       [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
8564     bits<6> imm;
8565     let Inst{21-16} = imm;
8566   }
8567 }
8568
8569 multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
8570                                   Intrinsic OpNode> {
8571   let Predicates = [HasNEON, HasFullFP16] in {
8572   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8573                                   V64, V64, vecshiftR16,
8574                                   asm, ".4h", ".4h",
8575       [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
8576     bits<4> imm;
8577     let Inst{19-16} = imm;
8578   }
8579
8580   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8581                                   V128, V128, vecshiftR16,
8582                                   asm, ".8h", ".8h",
8583       [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
8584     bits<4> imm;
8585     let Inst{19-16} = imm;
8586   }
8587   } // Predicates = [HasNEON, HasFullFP16]
8588
8589   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8590                                   V64, V64, vecshiftR32,
8591                                   asm, ".2s", ".2s",
8592       [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
8593     bits<5> imm;
8594     let Inst{20-16} = imm;
8595   }
8596
8597   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8598                                   V128, V128, vecshiftR32,
8599                                   asm, ".4s", ".4s",
8600       [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
8601     bits<5> imm;
8602     let Inst{20-16} = imm;
8603   }
8604
8605   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8606                                   V128, V128, vecshiftR64,
8607                                   asm, ".2d", ".2d",
8608       [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
8609     bits<6> imm;
8610     let Inst{21-16} = imm;
8611   }
8612 }
8613
8614 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
8615                                      SDPatternOperator OpNode> {
8616   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8617                                   V64, V128, vecshiftR16Narrow,
8618                                   asm, ".8b", ".8h",
8619       [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
8620     bits<3> imm;
8621     let Inst{18-16} = imm;
8622   }
8623
8624   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8625                                   V128, V128, vecshiftR16Narrow,
8626                                   asm#"2", ".16b", ".8h", []> {
8627     bits<3> imm;
8628     let Inst{18-16} = imm;
8629     let hasSideEffects = 0;
8630   }
8631
8632   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8633                                   V64, V128, vecshiftR32Narrow,
8634                                   asm, ".4h", ".4s",
8635       [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
8636     bits<4> imm;
8637     let Inst{19-16} = imm;
8638   }
8639
8640   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8641                                   V128, V128, vecshiftR32Narrow,
8642                                   asm#"2", ".8h", ".4s", []> {
8643     bits<4> imm;
8644     let Inst{19-16} = imm;
8645     let hasSideEffects = 0;
8646   }
8647
8648   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8649                                   V64, V128, vecshiftR64Narrow,
8650                                   asm, ".2s", ".2d",
8651       [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
8652     bits<5> imm;
8653     let Inst{20-16} = imm;
8654   }
8655
8656   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8657                                   V128, V128, vecshiftR64Narrow,
8658                                   asm#"2", ".4s", ".2d", []> {
8659     bits<5> imm;
8660     let Inst{20-16} = imm;
8661     let hasSideEffects = 0;
8662   }
8663
8664   // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
8665   // themselves, so put them here instead.
8666
8667   // Patterns involving what's effectively an insert high and a normal
8668   // intrinsic, represented by CONCAT_VECTORS.
8669   def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
8670                                                    vecshiftR16Narrow:$imm)),
8671             (!cast<Instruction>(NAME # "v16i8_shift")
8672                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8673                 V128:$Rn, vecshiftR16Narrow:$imm)>;
8674   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
8675                                                      vecshiftR32Narrow:$imm)),
8676             (!cast<Instruction>(NAME # "v8i16_shift")
8677                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8678                 V128:$Rn, vecshiftR32Narrow:$imm)>;
8679   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
8680                                                      vecshiftR64Narrow:$imm)),
8681             (!cast<Instruction>(NAME # "v4i32_shift")
8682                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8683                 V128:$Rn, vecshiftR64Narrow:$imm)>;
8684 }
8685
8686 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
8687                                 SDPatternOperator OpNode> {
8688   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8689                                   V64, V64, vecshiftL8,
8690                                   asm, ".8b", ".8b",
8691                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
8692                        (i32 vecshiftL8:$imm)))]> {
8693     bits<3> imm;
8694     let Inst{18-16} = imm;
8695   }
8696
8697   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8698                                   V128, V128, vecshiftL8,
8699                                   asm, ".16b", ".16b",
8700              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
8701                    (i32 vecshiftL8:$imm)))]> {
8702     bits<3> imm;
8703     let Inst{18-16} = imm;
8704   }
8705
8706   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8707                                   V64, V64, vecshiftL16,
8708                                   asm, ".4h", ".4h",
8709               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
8710                     (i32 vecshiftL16:$imm)))]> {
8711     bits<4> imm;
8712     let Inst{19-16} = imm;
8713   }
8714
8715   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8716                                   V128, V128, vecshiftL16,
8717                                   asm, ".8h", ".8h",
8718             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
8719                   (i32 vecshiftL16:$imm)))]> {
8720     bits<4> imm;
8721     let Inst{19-16} = imm;
8722   }
8723
8724   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8725                                   V64, V64, vecshiftL32,
8726                                   asm, ".2s", ".2s",
8727               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
8728                     (i32 vecshiftL32:$imm)))]> {
8729     bits<5> imm;
8730     let Inst{20-16} = imm;
8731   }
8732
8733   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8734                                   V128, V128, vecshiftL32,
8735                                   asm, ".4s", ".4s",
8736             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
8737                   (i32 vecshiftL32:$imm)))]> {
8738     bits<5> imm;
8739     let Inst{20-16} = imm;
8740   }
8741
8742   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8743                                   V128, V128, vecshiftL64,
8744                                   asm, ".2d", ".2d",
8745             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
8746                   (i32 vecshiftL64:$imm)))]> {
8747     bits<6> imm;
8748     let Inst{21-16} = imm;
8749   }
8750 }
8751
8752 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
8753                                 SDPatternOperator OpNode> {
8754   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8755                                   V64, V64, vecshiftR8,
8756                                   asm, ".8b", ".8b",
8757                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
8758                        (i32 vecshiftR8:$imm)))]> {
8759     bits<3> imm;
8760     let Inst{18-16} = imm;
8761   }
8762
8763   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8764                                   V128, V128, vecshiftR8,
8765                                   asm, ".16b", ".16b",
8766              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
8767                    (i32 vecshiftR8:$imm)))]> {
8768     bits<3> imm;
8769     let Inst{18-16} = imm;
8770   }
8771
8772   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8773                                   V64, V64, vecshiftR16,
8774                                   asm, ".4h", ".4h",
8775               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
8776                     (i32 vecshiftR16:$imm)))]> {
8777     bits<4> imm;
8778     let Inst{19-16} = imm;
8779   }
8780
8781   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8782                                   V128, V128, vecshiftR16,
8783                                   asm, ".8h", ".8h",
8784             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
8785                   (i32 vecshiftR16:$imm)))]> {
8786     bits<4> imm;
8787     let Inst{19-16} = imm;
8788   }
8789
8790   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8791                                   V64, V64, vecshiftR32,
8792                                   asm, ".2s", ".2s",
8793               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
8794                     (i32 vecshiftR32:$imm)))]> {
8795     bits<5> imm;
8796     let Inst{20-16} = imm;
8797   }
8798
8799   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8800                                   V128, V128, vecshiftR32,
8801                                   asm, ".4s", ".4s",
8802             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
8803                   (i32 vecshiftR32:$imm)))]> {
8804     bits<5> imm;
8805     let Inst{20-16} = imm;
8806   }
8807
8808   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8809                                   V128, V128, vecshiftR64,
8810                                   asm, ".2d", ".2d",
8811             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
8812                   (i32 vecshiftR64:$imm)))]> {
8813     bits<6> imm;
8814     let Inst{21-16} = imm;
8815   }
8816 }
8817
8818 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8819 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
8820                                     SDPatternOperator OpNode = null_frag> {
8821   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
8822                                   V64, V64, vecshiftR8, asm, ".8b", ".8b",
8823                  [(set (v8i8 V64:$dst),
8824                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
8825                            (i32 vecshiftR8:$imm)))]> {
8826     bits<3> imm;
8827     let Inst{18-16} = imm;
8828   }
8829
8830   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8831                                   V128, V128, vecshiftR8, asm, ".16b", ".16b",
8832              [(set (v16i8 V128:$dst),
8833                (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
8834                        (i32 vecshiftR8:$imm)))]> {
8835     bits<3> imm;
8836     let Inst{18-16} = imm;
8837   }
8838
8839   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
8840                                   V64, V64, vecshiftR16, asm, ".4h", ".4h",
8841               [(set (v4i16 V64:$dst),
8842                 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
8843                         (i32 vecshiftR16:$imm)))]> {
8844     bits<4> imm;
8845     let Inst{19-16} = imm;
8846   }
8847
8848   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8849                                   V128, V128, vecshiftR16, asm, ".8h", ".8h",
8850             [(set (v8i16 V128:$dst),
8851               (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8852                       (i32 vecshiftR16:$imm)))]> {
8853     bits<4> imm;
8854     let Inst{19-16} = imm;
8855   }
8856
8857   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
8858                                   V64, V64, vecshiftR32, asm, ".2s", ".2s",
8859               [(set (v2i32 V64:$dst),
8860                 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8861                         (i32 vecshiftR32:$imm)))]> {
8862     bits<5> imm;
8863     let Inst{20-16} = imm;
8864   }
8865
8866   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8867                                   V128, V128, vecshiftR32, asm, ".4s", ".4s",
8868             [(set (v4i32 V128:$dst),
8869               (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8870                       (i32 vecshiftR32:$imm)))]> {
8871     bits<5> imm;
8872     let Inst{20-16} = imm;
8873   }
8874
8875   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
8876                                   V128, V128, vecshiftR64,
8877                                   asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
8878               (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
8879                       (i32 vecshiftR64:$imm)))]> {
8880     bits<6> imm;
8881     let Inst{21-16} = imm;
8882   }
8883 }
8884
8885 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
8886                                     SDPatternOperator OpNode = null_frag> {
8887   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
8888                                   V64, V64, vecshiftL8,
8889                                   asm, ".8b", ".8b",
8890                     [(set (v8i8 V64:$dst),
8891                           (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
8892                                   (i32 vecshiftL8:$imm)))]> {
8893     bits<3> imm;
8894     let Inst{18-16} = imm;
8895   }
8896
8897   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8898                                   V128, V128, vecshiftL8,
8899                                   asm, ".16b", ".16b",
8900                     [(set (v16i8 V128:$dst),
8901                           (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
8902                                   (i32 vecshiftL8:$imm)))]> {
8903     bits<3> imm;
8904     let Inst{18-16} = imm;
8905   }
8906
8907   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
8908                                   V64, V64, vecshiftL16,
8909                                   asm, ".4h", ".4h",
8910                     [(set (v4i16 V64:$dst),
8911                            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
8912                                    (i32 vecshiftL16:$imm)))]> {
8913     bits<4> imm;
8914     let Inst{19-16} = imm;
8915   }
8916
8917   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8918                                   V128, V128, vecshiftL16,
8919                                   asm, ".8h", ".8h",
8920                     [(set (v8i16 V128:$dst),
8921                           (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8922                                   (i32 vecshiftL16:$imm)))]> {
8923     bits<4> imm;
8924     let Inst{19-16} = imm;
8925   }
8926
8927   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
8928                                   V64, V64, vecshiftL32,
8929                                   asm, ".2s", ".2s",
8930                     [(set (v2i32 V64:$dst),
8931                           (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8932                                   (i32 vecshiftL32:$imm)))]> {
8933     bits<5> imm;
8934     let Inst{20-16} = imm;
8935   }
8936
8937   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8938                                   V128, V128, vecshiftL32,
8939                                   asm, ".4s", ".4s",
8940                     [(set (v4i32 V128:$dst),
8941                           (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8942                                   (i32 vecshiftL32:$imm)))]> {
8943     bits<5> imm;
8944     let Inst{20-16} = imm;
8945   }
8946
8947   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
8948                                   V128, V128, vecshiftL64,
8949                                   asm, ".2d", ".2d",
8950                     [(set (v2i64 V128:$dst),
8951                           (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
8952                                   (i32 vecshiftL64:$imm)))]> {
8953     bits<6> imm;
8954     let Inst{21-16} = imm;
8955   }
8956 }
8957
8958 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
8959                                    SDPatternOperator OpNode> {
8960   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8961                                   V128, V64, vecshiftL8, asm, ".8h", ".8b",
8962       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
8963     bits<3> imm;
8964     let Inst{18-16} = imm;
8965   }
8966
8967   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8968                                   V128, V128, vecshiftL8,
8969                                   asm#"2", ".8h", ".16b",
8970       [(set (v8i16 V128:$Rd),
8971             (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
8972     bits<3> imm;
8973     let Inst{18-16} = imm;
8974   }
8975
8976   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8977                                   V128, V64, vecshiftL16, asm, ".4s", ".4h",
8978       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
8979     bits<4> imm;
8980     let Inst{19-16} = imm;
8981   }
8982
8983   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8984                                   V128, V128, vecshiftL16,
8985                                   asm#"2", ".4s", ".8h",
8986       [(set (v4i32 V128:$Rd),
8987             (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
8988
8989     bits<4> imm;
8990     let Inst{19-16} = imm;
8991   }
8992
8993   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8994                                   V128, V64, vecshiftL32, asm, ".2d", ".2s",
8995       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
8996     bits<5> imm;
8997     let Inst{20-16} = imm;
8998   }
8999
9000   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9001                                   V128, V128, vecshiftL32,
9002                                   asm#"2", ".2d", ".4s",
9003       [(set (v2i64 V128:$Rd),
9004             (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
9005     bits<5> imm;
9006     let Inst{20-16} = imm;
9007   }
9008 }
9009
9010
9011 //---
9012 // Vector load/store
9013 //---
9014 // SIMD ldX/stX no-index memory references don't allow the optional
9015 // ", #0" constant and handle post-indexing explicitly, so we use
9016 // a more specialized parse method for them. Otherwise, it's the same as
9017 // the general GPR64sp handling.
9018
9019 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
9020                    string asm, dag oops, dag iops, list<dag> pattern>
9021   : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
9022   bits<5> Vt;
9023   bits<5> Rn;
9024   let Inst{31} = 0;
9025   let Inst{30} = Q;
9026   let Inst{29-23} = 0b0011000;
9027   let Inst{22} = L;
9028   let Inst{21-16} = 0b000000;
9029   let Inst{15-12} = opcode;
9030   let Inst{11-10} = size;
9031   let Inst{9-5} = Rn;
9032   let Inst{4-0} = Vt;
9033 }
9034
9035 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
9036                        string asm, dag oops, dag iops>
9037   : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
9038   bits<5> Vt;
9039   bits<5> Rn;
9040   bits<5> Xm;
9041   let Inst{31} = 0;
9042   let Inst{30} = Q;
9043   let Inst{29-23} = 0b0011001;
9044   let Inst{22} = L;
9045   let Inst{21} = 0;
9046   let Inst{20-16} = Xm;
9047   let Inst{15-12} = opcode;
9048   let Inst{11-10} = size;
9049   let Inst{9-5} = Rn;
9050   let Inst{4-0} = Vt;
9051 }
9052
9053 // The immediate form of AdvSIMD post-indexed addressing is encoded with
9054 // register post-index addressing from the zero register.
9055 multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
9056                            int Offset, int Size> {
9057   // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
9058   //      "ld1\t$Vt, [$Rn], #16"
9059   // may get mapped to
9060   //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
9061   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9062                   (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9063                       GPR64sp:$Rn,
9064                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9065                       XZR), 1>;
9066
9067   // E.g. "ld1.8b { v0, v1 }, [x1], #16"
9068   //      "ld1.8b\t$Vt, [$Rn], #16"
9069   // may get mapped to
9070   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
9071   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9072                   (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9073                       GPR64sp:$Rn,
9074                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9075                       XZR), 0>;
9076
9077   // E.g. "ld1.8b { v0, v1 }, [x1]"
9078   //      "ld1\t$Vt, [$Rn]"
9079   // may get mapped to
9080   //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
9081   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9082                   (!cast<Instruction>(BaseName # Count # "v" # layout)
9083                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9084                       GPR64sp:$Rn), 0>;
9085
9086   // E.g. "ld1.8b { v0, v1 }, [x1], x2"
9087   //      "ld1\t$Vt, [$Rn], $Xm"
9088   // may get mapped to
9089   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
9090   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9091                   (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9092                       GPR64sp:$Rn,
9093                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9094                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9095 }
9096
9097 multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
9098                        int Offset128, int Offset64, bits<4> opcode> {
9099   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9100     def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
9101                            (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
9102                            (ins GPR64sp:$Rn), []>;
9103     def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
9104                            (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
9105                            (ins GPR64sp:$Rn), []>;
9106     def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
9107                            (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
9108                            (ins GPR64sp:$Rn), []>;
9109     def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
9110                            (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
9111                            (ins GPR64sp:$Rn), []>;
9112     def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
9113                            (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
9114                            (ins GPR64sp:$Rn), []>;
9115     def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
9116                            (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
9117                            (ins GPR64sp:$Rn), []>;
9118     def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
9119                            (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
9120                            (ins GPR64sp:$Rn), []>;
9121
9122
9123     def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
9124                        (outs GPR64sp:$wback,
9125                              !cast<RegisterOperand>(veclist # "16b"):$Vt),
9126                        (ins GPR64sp:$Rn,
9127                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9128     def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
9129                        (outs GPR64sp:$wback,
9130                              !cast<RegisterOperand>(veclist # "8h"):$Vt),
9131                        (ins GPR64sp:$Rn,
9132                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9133     def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
9134                        (outs GPR64sp:$wback,
9135                              !cast<RegisterOperand>(veclist # "4s"):$Vt),
9136                        (ins GPR64sp:$Rn,
9137                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9138     def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
9139                        (outs GPR64sp:$wback,
9140                              !cast<RegisterOperand>(veclist # "2d"):$Vt),
9141                        (ins GPR64sp:$Rn,
9142                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9143     def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
9144                        (outs GPR64sp:$wback,
9145                              !cast<RegisterOperand>(veclist # "8b"):$Vt),
9146                        (ins GPR64sp:$Rn,
9147                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9148     def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
9149                        (outs GPR64sp:$wback,
9150                              !cast<RegisterOperand>(veclist # "4h"):$Vt),
9151                        (ins GPR64sp:$Rn,
9152                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9153     def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
9154                        (outs GPR64sp:$wback,
9155                              !cast<RegisterOperand>(veclist # "2s"):$Vt),
9156                        (ins GPR64sp:$Rn,
9157                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9158   }
9159
9160   defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9161   defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9162   defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9163   defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9164   defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9165   defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9166   defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9167 }
9168
9169 // Only ld1/st1 has a v1d version.
9170 multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
9171                        int Offset128, int Offset64, bits<4> opcode> {
9172   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
9173     def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
9174                             (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9175                                  GPR64sp:$Rn), []>;
9176     def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
9177                            (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9178                                 GPR64sp:$Rn), []>;
9179     def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
9180                            (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9181                                 GPR64sp:$Rn), []>;
9182     def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
9183                            (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9184                                 GPR64sp:$Rn), []>;
9185     def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
9186                            (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9187                                 GPR64sp:$Rn), []>;
9188     def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
9189                            (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9190                                 GPR64sp:$Rn), []>;
9191     def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
9192                            (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9193                                 GPR64sp:$Rn), []>;
9194
9195     def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
9196                        (outs GPR64sp:$wback),
9197                        (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9198                             GPR64sp:$Rn,
9199                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9200     def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
9201                        (outs GPR64sp:$wback),
9202                        (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9203                             GPR64sp:$Rn,
9204                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9205     def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
9206                        (outs GPR64sp:$wback),
9207                        (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9208                             GPR64sp:$Rn,
9209                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9210     def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
9211                        (outs GPR64sp:$wback),
9212                        (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9213                             GPR64sp:$Rn,
9214                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9215     def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
9216                        (outs GPR64sp:$wback),
9217                        (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9218                             GPR64sp:$Rn,
9219                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9220     def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
9221                        (outs GPR64sp:$wback),
9222                        (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9223                             GPR64sp:$Rn,
9224                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9225     def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
9226                        (outs GPR64sp:$wback),
9227                        (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9228                             GPR64sp:$Rn,
9229                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9230   }
9231
9232   defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9233   defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9234   defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9235   defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9236   defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9237   defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9238   defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9239 }
9240
9241 multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
9242                        int Offset128, int Offset64, bits<4> opcode>
9243   : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9244
9245   // LD1 instructions have extra "1d" variants.
9246   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9247     def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
9248                            (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
9249                            (ins GPR64sp:$Rn), []>;
9250
9251     def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
9252                        (outs GPR64sp:$wback,
9253                              !cast<RegisterOperand>(veclist # "1d"):$Vt),
9254                        (ins GPR64sp:$Rn,
9255                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9256   }
9257
9258   defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
9259 }
9260
9261 multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
9262                        int Offset128, int Offset64, bits<4> opcode>
9263   : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9264
9265   // ST1 instructions have extra "1d" variants.
9266   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
9267     def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
9268                            (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
9269                                 GPR64sp:$Rn), []>;
9270
9271     def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
9272                        (outs GPR64sp:$wback),
9273                        (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
9274                             GPR64sp:$Rn,
9275                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9276   }
9277
9278   defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
9279 }
9280
9281 multiclass SIMDLd1Multiple<string asm> {
9282   defm One   : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
9283   defm Two   : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
9284   defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
9285   defm Four  : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
9286 }
9287
9288 multiclass SIMDSt1Multiple<string asm> {
9289   defm One   : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
9290   defm Two   : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
9291   defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
9292   defm Four  : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
9293 }
9294
9295 multiclass SIMDLd2Multiple<string asm> {
9296   defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
9297 }
9298
9299 multiclass SIMDSt2Multiple<string asm> {
9300   defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
9301 }
9302
9303 multiclass SIMDLd3Multiple<string asm> {
9304   defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
9305 }
9306
9307 multiclass SIMDSt3Multiple<string asm> {
9308   defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
9309 }
9310
9311 multiclass SIMDLd4Multiple<string asm> {
9312   defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
9313 }
9314
9315 multiclass SIMDSt4Multiple<string asm> {
9316   defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
9317 }
9318
9319 //---
9320 // AdvSIMD Load/store single-element
9321 //---
9322
9323 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
9324                          string asm, string operands, string cst,
9325                          dag oops, dag iops, list<dag> pattern>
9326   : I<oops, iops, asm, operands, cst, pattern> {
9327   bits<5> Vt;
9328   bits<5> Rn;
9329   let Inst{31} = 0;
9330   let Inst{29-24} = 0b001101;
9331   let Inst{22} = L;
9332   let Inst{21} = R;
9333   let Inst{15-13} = opcode;
9334   let Inst{9-5} = Rn;
9335   let Inst{4-0} = Vt;
9336 }
9337
9338 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
9339                          string asm, string operands, string cst,
9340                          dag oops, dag iops, list<dag> pattern>
9341   : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
9342   bits<5> Vt;
9343   bits<5> Rn;
9344   let Inst{31} = 0;
9345   let Inst{29-24} = 0b001101;
9346   let Inst{22} = L;
9347   let Inst{21} = R;
9348   let Inst{15-13} = opcode;
9349   let Inst{9-5} = Rn;
9350   let Inst{4-0} = Vt;
9351 }
9352
9353
9354 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9355 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
9356                   DAGOperand listtype>
9357   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
9358                        (outs listtype:$Vt), (ins GPR64sp:$Rn),
9359                        []> {
9360   let Inst{30} = Q;
9361   let Inst{23} = 0;
9362   let Inst{20-16} = 0b00000;
9363   let Inst{12} = S;
9364   let Inst{11-10} = size;
9365 }
9366 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9367 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
9368                       string asm, DAGOperand listtype, DAGOperand GPR64pi>
9369   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
9370                        "$Rn = $wback",
9371                        (outs GPR64sp:$wback, listtype:$Vt),
9372                        (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
9373   bits<5> Xm;
9374   let Inst{30} = Q;
9375   let Inst{23} = 1;
9376   let Inst{20-16} = Xm;
9377   let Inst{12} = S;
9378   let Inst{11-10} = size;
9379 }
9380
9381 multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
9382                           int Offset, int Size> {
9383   // E.g. "ld1r { v0.8b }, [x1], #1"
9384   //      "ld1r.8b\t$Vt, [$Rn], #1"
9385   // may get mapped to
9386   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
9387   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9388                   (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9389                       GPR64sp:$Rn,
9390                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9391                       XZR), 1>;
9392
9393   // E.g. "ld1r.8b { v0 }, [x1], #1"
9394   //      "ld1r.8b\t$Vt, [$Rn], #1"
9395   // may get mapped to
9396   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9397   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9398                   (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9399                       GPR64sp:$Rn,
9400                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9401                       XZR), 0>;
9402
9403   // E.g. "ld1r.8b { v0 }, [x1]"
9404   //      "ld1r.8b\t$Vt, [$Rn]"
9405   // may get mapped to
9406   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9407   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9408                   (!cast<Instruction>(BaseName # "v" # layout)
9409                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9410                       GPR64sp:$Rn), 0>;
9411
9412   // E.g. "ld1r.8b { v0 }, [x1], x2"
9413   //      "ld1r.8b\t$Vt, [$Rn], $Xm"
9414   // may get mapped to
9415   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9416   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9417                   (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9418                       GPR64sp:$Rn,
9419                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9420                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9421 }
9422
9423 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
9424   int Offset1, int Offset2, int Offset4, int Offset8> {
9425   def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
9426                         !cast<DAGOperand>("VecList" # Count # "8b")>;
9427   def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
9428                         !cast<DAGOperand>("VecList" # Count #"16b")>;
9429   def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
9430                         !cast<DAGOperand>("VecList" # Count #"4h")>;
9431   def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
9432                         !cast<DAGOperand>("VecList" # Count #"8h")>;
9433   def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
9434                         !cast<DAGOperand>("VecList" # Count #"2s")>;
9435   def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
9436                         !cast<DAGOperand>("VecList" # Count #"4s")>;
9437   def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
9438                         !cast<DAGOperand>("VecList" # Count #"1d")>;
9439   def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
9440                         !cast<DAGOperand>("VecList" # Count #"2d")>;
9441
9442   def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
9443                                  !cast<DAGOperand>("VecList" # Count # "8b"),
9444                                  !cast<DAGOperand>("GPR64pi" # Offset1)>;
9445   def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
9446                                  !cast<DAGOperand>("VecList" # Count # "16b"),
9447                                  !cast<DAGOperand>("GPR64pi" # Offset1)>;
9448   def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
9449                                  !cast<DAGOperand>("VecList" # Count # "4h"),
9450                                  !cast<DAGOperand>("GPR64pi" # Offset2)>;
9451   def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
9452                                  !cast<DAGOperand>("VecList" # Count # "8h"),
9453                                  !cast<DAGOperand>("GPR64pi" # Offset2)>;
9454   def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
9455                                  !cast<DAGOperand>("VecList" # Count # "2s"),
9456                                  !cast<DAGOperand>("GPR64pi" # Offset4)>;
9457   def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
9458                                  !cast<DAGOperand>("VecList" # Count # "4s"),
9459                                  !cast<DAGOperand>("GPR64pi" # Offset4)>;
9460   def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
9461                                  !cast<DAGOperand>("VecList" # Count # "1d"),
9462                                  !cast<DAGOperand>("GPR64pi" # Offset8)>;
9463   def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
9464                                  !cast<DAGOperand>("VecList" # Count # "2d"),
9465                                  !cast<DAGOperand>("GPR64pi" # Offset8)>;
9466
9467   defm : SIMDLdrAliases<NAME, asm, "8b",  Count, Offset1,  64>;
9468   defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
9469   defm : SIMDLdrAliases<NAME, asm, "4h",  Count, Offset2,  64>;
9470   defm : SIMDLdrAliases<NAME, asm, "8h",  Count, Offset2, 128>;
9471   defm : SIMDLdrAliases<NAME, asm, "2s",  Count, Offset4,  64>;
9472   defm : SIMDLdrAliases<NAME, asm, "4s",  Count, Offset4, 128>;
9473   defm : SIMDLdrAliases<NAME, asm, "1d",  Count, Offset8,  64>;
9474   defm : SIMDLdrAliases<NAME, asm, "2d",  Count, Offset8, 128>;
9475 }
9476
9477 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
9478                       dag oops, dag iops, list<dag> pattern>
9479   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9480                        pattern> {
9481   // idx encoded in Q:S:size fields.
9482   bits<4> idx;
9483   let Inst{30} = idx{3};
9484   let Inst{23} = 0;
9485   let Inst{20-16} = 0b00000;
9486   let Inst{12} = idx{2};
9487   let Inst{11-10} = idx{1-0};
9488 }
9489 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
9490                       dag oops, dag iops, list<dag> pattern>
9491   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9492                            oops, iops, pattern> {
9493   // idx encoded in Q:S:size fields.
9494   bits<4> idx;
9495   let Inst{30} = idx{3};
9496   let Inst{23} = 0;
9497   let Inst{20-16} = 0b00000;
9498   let Inst{12} = idx{2};
9499   let Inst{11-10} = idx{1-0};
9500 }
9501 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
9502                           dag oops, dag iops>
9503   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9504                        "$Rn = $wback", oops, iops, []> {
9505   // idx encoded in Q:S:size fields.
9506   bits<4> idx;
9507   bits<5> Xm;
9508   let Inst{30} = idx{3};
9509   let Inst{23} = 1;
9510   let Inst{20-16} = Xm;
9511   let Inst{12} = idx{2};
9512   let Inst{11-10} = idx{1-0};
9513 }
9514 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
9515                           dag oops, dag iops>
9516   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9517                            "$Rn = $wback", oops, iops, []> {
9518   // idx encoded in Q:S:size fields.
9519   bits<4> idx;
9520   bits<5> Xm;
9521   let Inst{30} = idx{3};
9522   let Inst{23} = 1;
9523   let Inst{20-16} = Xm;
9524   let Inst{12} = idx{2};
9525   let Inst{11-10} = idx{1-0};
9526 }
9527
9528 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
9529                       dag oops, dag iops, list<dag> pattern>
9530   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9531                        pattern> {
9532   // idx encoded in Q:S:size<1> fields.
9533   bits<3> idx;
9534   let Inst{30} = idx{2};
9535   let Inst{23} = 0;
9536   let Inst{20-16} = 0b00000;
9537   let Inst{12} = idx{1};
9538   let Inst{11} = idx{0};
9539   let Inst{10} = size;
9540 }
9541 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
9542                       dag oops, dag iops, list<dag> pattern>
9543   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9544                            oops, iops, pattern> {
9545   // idx encoded in Q:S:size<1> fields.
9546   bits<3> idx;
9547   let Inst{30} = idx{2};
9548   let Inst{23} = 0;
9549   let Inst{20-16} = 0b00000;
9550   let Inst{12} = idx{1};
9551   let Inst{11} = idx{0};
9552   let Inst{10} = size;
9553 }
9554
9555 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
9556                           dag oops, dag iops>
9557   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9558                        "$Rn = $wback", oops, iops, []> {
9559   // idx encoded in Q:S:size<1> fields.
9560   bits<3> idx;
9561   bits<5> Xm;
9562   let Inst{30} = idx{2};
9563   let Inst{23} = 1;
9564   let Inst{20-16} = Xm;
9565   let Inst{12} = idx{1};
9566   let Inst{11} = idx{0};
9567   let Inst{10} = size;
9568 }
9569 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
9570                           dag oops, dag iops>
9571   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9572                            "$Rn = $wback", oops, iops, []> {
9573   // idx encoded in Q:S:size<1> fields.
9574   bits<3> idx;
9575   bits<5> Xm;
9576   let Inst{30} = idx{2};
9577   let Inst{23} = 1;
9578   let Inst{20-16} = Xm;
9579   let Inst{12} = idx{1};
9580   let Inst{11} = idx{0};
9581   let Inst{10} = size;
9582 }
9583 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9584                       dag oops, dag iops, list<dag> pattern>
9585   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9586                        pattern> {
9587   // idx encoded in Q:S fields.
9588   bits<2> idx;
9589   let Inst{30} = idx{1};
9590   let Inst{23} = 0;
9591   let Inst{20-16} = 0b00000;
9592   let Inst{12} = idx{0};
9593   let Inst{11-10} = size;
9594 }
9595 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9596                       dag oops, dag iops, list<dag> pattern>
9597   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9598                            oops, iops, pattern> {
9599   // idx encoded in Q:S fields.
9600   bits<2> idx;
9601   let Inst{30} = idx{1};
9602   let Inst{23} = 0;
9603   let Inst{20-16} = 0b00000;
9604   let Inst{12} = idx{0};
9605   let Inst{11-10} = size;
9606 }
9607 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
9608                           string asm, dag oops, dag iops>
9609   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9610                        "$Rn = $wback", oops, iops, []> {
9611   // idx encoded in Q:S fields.
9612   bits<2> idx;
9613   bits<5> Xm;
9614   let Inst{30} = idx{1};
9615   let Inst{23} = 1;
9616   let Inst{20-16} = Xm;
9617   let Inst{12} = idx{0};
9618   let Inst{11-10} = size;
9619 }
9620 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
9621                           string asm, dag oops, dag iops>
9622   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9623                            "$Rn = $wback", oops, iops, []> {
9624   // idx encoded in Q:S fields.
9625   bits<2> idx;
9626   bits<5> Xm;
9627   let Inst{30} = idx{1};
9628   let Inst{23} = 1;
9629   let Inst{20-16} = Xm;
9630   let Inst{12} = idx{0};
9631   let Inst{11-10} = size;
9632 }
9633 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9634                       dag oops, dag iops, list<dag> pattern>
9635   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9636                        pattern> {
9637   // idx encoded in Q field.
9638   bits<1> idx;
9639   let Inst{30} = idx;
9640   let Inst{23} = 0;
9641   let Inst{20-16} = 0b00000;
9642   let Inst{12} = 0;
9643   let Inst{11-10} = size;
9644 }
9645 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9646                       dag oops, dag iops, list<dag> pattern>
9647   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9648                            oops, iops, pattern> {
9649   // idx encoded in Q field.
9650   bits<1> idx;
9651   let Inst{30} = idx;
9652   let Inst{23} = 0;
9653   let Inst{20-16} = 0b00000;
9654   let Inst{12} = 0;
9655   let Inst{11-10} = size;
9656 }
9657 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
9658                           string asm, dag oops, dag iops>
9659   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9660                        "$Rn = $wback", oops, iops, []> {
9661   // idx encoded in Q field.
9662   bits<1> idx;
9663   bits<5> Xm;
9664   let Inst{30} = idx;
9665   let Inst{23} = 1;
9666   let Inst{20-16} = Xm;
9667   let Inst{12} = 0;
9668   let Inst{11-10} = size;
9669 }
9670 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
9671                           string asm, dag oops, dag iops>
9672   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9673                            "$Rn = $wback", oops, iops, []> {
9674   // idx encoded in Q field.
9675   bits<1> idx;
9676   bits<5> Xm;
9677   let Inst{30} = idx;
9678   let Inst{23} = 1;
9679   let Inst{20-16} = Xm;
9680   let Inst{12} = 0;
9681   let Inst{11-10} = size;
9682 }
9683
9684 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9685 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
9686                          RegisterOperand listtype,
9687                          RegisterOperand GPR64pi> {
9688   def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
9689                            (outs listtype:$dst),
9690                            (ins listtype:$Vt, VectorIndexB:$idx,
9691                                 GPR64sp:$Rn), []>;
9692
9693   def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
9694                             (outs GPR64sp:$wback, listtype:$dst),
9695                             (ins listtype:$Vt, VectorIndexB:$idx,
9696                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9697 }
9698 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9699 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
9700                          RegisterOperand listtype,
9701                          RegisterOperand GPR64pi> {
9702   def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
9703                             (outs listtype:$dst),
9704                             (ins listtype:$Vt, VectorIndexH:$idx,
9705                                  GPR64sp:$Rn), []>;
9706
9707   def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
9708                             (outs GPR64sp:$wback, listtype:$dst),
9709                             (ins listtype:$Vt, VectorIndexH:$idx,
9710                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9711 }
9712 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9713 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
9714                          RegisterOperand listtype,
9715                          RegisterOperand GPR64pi> {
9716   def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
9717                             (outs listtype:$dst),
9718                             (ins listtype:$Vt, VectorIndexS:$idx,
9719                                  GPR64sp:$Rn), []>;
9720
9721   def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
9722                             (outs GPR64sp:$wback, listtype:$dst),
9723                             (ins listtype:$Vt, VectorIndexS:$idx,
9724                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9725 }
9726 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9727 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
9728                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9729   def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
9730                             (outs listtype:$dst),
9731                             (ins listtype:$Vt, VectorIndexD:$idx,
9732                                  GPR64sp:$Rn), []>;
9733
9734   def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
9735                             (outs GPR64sp:$wback, listtype:$dst),
9736                             (ins listtype:$Vt, VectorIndexD:$idx,
9737                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9738 }
9739 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9740 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
9741                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9742   def i8 : SIMDLdStSingleB<0, R, opcode, asm,
9743                            (outs), (ins listtype:$Vt, VectorIndexB:$idx,
9744                                         GPR64sp:$Rn), []>;
9745
9746   def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
9747                                     (outs GPR64sp:$wback),
9748                                     (ins listtype:$Vt, VectorIndexB:$idx,
9749                                          GPR64sp:$Rn, GPR64pi:$Xm)>;
9750 }
9751 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9752 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
9753                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9754   def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
9755                             (outs), (ins listtype:$Vt, VectorIndexH:$idx,
9756                                          GPR64sp:$Rn), []>;
9757
9758   def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
9759                             (outs GPR64sp:$wback),
9760                             (ins listtype:$Vt, VectorIndexH:$idx,
9761                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9762 }
9763 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9764 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
9765                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9766   def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
9767                             (outs), (ins listtype:$Vt, VectorIndexS:$idx,
9768                                          GPR64sp:$Rn), []>;
9769
9770   def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
9771                             (outs GPR64sp:$wback),
9772                             (ins listtype:$Vt, VectorIndexS:$idx,
9773                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9774 }
9775 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9776 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
9777                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9778   def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
9779                             (outs), (ins listtype:$Vt, VectorIndexD:$idx,
9780                                          GPR64sp:$Rn), []>;
9781
9782   def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
9783                             (outs GPR64sp:$wback),
9784                             (ins listtype:$Vt, VectorIndexD:$idx,
9785                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9786 }
9787
9788 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
9789                                  string Count, int Offset, Operand idxtype> {
9790   // E.g. "ld1 { v0.8b }[0], [x1], #1"
9791   //      "ld1\t$Vt, [$Rn], #1"
9792   // may get mapped to
9793   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
9794   def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
9795                   (!cast<Instruction>(NAME # Type  # "_POST")
9796                       GPR64sp:$Rn,
9797                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9798                       idxtype:$idx, XZR), 1>;
9799
9800   // E.g. "ld1.8b { v0 }[0], [x1], #1"
9801   //      "ld1.8b\t$Vt, [$Rn], #1"
9802   // may get mapped to
9803   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9804   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
9805                   (!cast<Instruction>(NAME # Type # "_POST")
9806                       GPR64sp:$Rn,
9807                       !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9808                       idxtype:$idx, XZR), 0>;
9809
9810   // E.g. "ld1.8b { v0 }[0], [x1]"
9811   //      "ld1.8b\t$Vt, [$Rn]"
9812   // may get mapped to
9813   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9814   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
9815                       (!cast<Instruction>(NAME # Type)
9816                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9817                          idxtype:$idx, GPR64sp:$Rn), 0>;
9818
9819   // E.g. "ld1.8b { v0 }[0], [x1], x2"
9820   //      "ld1.8b\t$Vt, [$Rn], $Xm"
9821   // may get mapped to
9822   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9823   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
9824                       (!cast<Instruction>(NAME # Type # "_POST")
9825                          GPR64sp:$Rn,
9826                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9827                          idxtype:$idx,
9828                          !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9829 }
9830
9831 multiclass SIMDLdSt1SingleAliases<string asm> {
9832   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
9833   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
9834   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
9835   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
9836 }
9837
9838 multiclass SIMDLdSt2SingleAliases<string asm> {
9839   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
9840   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
9841   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
9842   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
9843 }
9844
9845 multiclass SIMDLdSt3SingleAliases<string asm> {
9846   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
9847   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
9848   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
9849   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
9850 }
9851
9852 multiclass SIMDLdSt4SingleAliases<string asm> {
9853   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
9854   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
9855   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
9856   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
9857 }
9858 } // end of 'let Predicates = [HasNEON]'
9859
9860 //----------------------------------------------------------------------------
9861 // AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
9862 //----------------------------------------------------------------------------
9863
9864 let Predicates = [HasNEON, HasRDM] in {
9865
9866 class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
9867                                     RegisterOperand regtype, string asm,
9868                                     string kind, list<dag> pattern>
9869   : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
9870                                 pattern> {
9871 }
9872 multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
9873                                              SDPatternOperator Accum> {
9874   def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
9875     [(set (v4i16 V64:$dst),
9876           (Accum (v4i16 V64:$Rd),
9877                  (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
9878                                                    (v4i16 V64:$Rm)))))]>;
9879   def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
9880     [(set (v8i16 V128:$dst),
9881           (Accum (v8i16 V128:$Rd),
9882                  (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
9883                                                    (v8i16 V128:$Rm)))))]>;
9884   def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
9885     [(set (v2i32 V64:$dst),
9886           (Accum (v2i32 V64:$Rd),
9887                  (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
9888                                                    (v2i32 V64:$Rm)))))]>;
9889   def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
9890     [(set (v4i32 V128:$dst),
9891           (Accum (v4i32 V128:$Rd),
9892                  (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
9893                                                    (v4i32 V128:$Rm)))))]>;
9894 }
9895
9896 multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
9897                                      SDPatternOperator Accum> {
9898   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
9899                                           V64, V64, V128_lo, VectorIndexH,
9900                                           asm, ".4h", ".4h", ".4h", ".h",
9901     [(set (v4i16 V64:$dst),
9902           (Accum (v4i16 V64:$Rd),
9903                  (v4i16 (int_aarch64_neon_sqrdmulh
9904                           (v4i16 V64:$Rn),
9905                           (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
9906                                                     VectorIndexH:$idx))))))]> {
9907     bits<3> idx;
9908     let Inst{11} = idx{2};
9909     let Inst{21} = idx{1};
9910     let Inst{20} = idx{0};
9911   }
9912
9913   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9914                                           V128, V128, V128_lo, VectorIndexH,
9915                                           asm, ".8h", ".8h", ".8h", ".h",
9916     [(set (v8i16 V128:$dst),
9917           (Accum (v8i16 V128:$Rd),
9918                  (v8i16 (int_aarch64_neon_sqrdmulh
9919                           (v8i16 V128:$Rn),
9920                           (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
9921                                                    VectorIndexH:$idx))))))]> {
9922     bits<3> idx;
9923     let Inst{11} = idx{2};
9924     let Inst{21} = idx{1};
9925     let Inst{20} = idx{0};
9926   }
9927
9928   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9929                                           V64, V64, V128, VectorIndexS,
9930                                           asm, ".2s", ".2s", ".2s", ".s",
9931     [(set (v2i32 V64:$dst),
9932         (Accum (v2i32 V64:$Rd),
9933                (v2i32 (int_aarch64_neon_sqrdmulh
9934                         (v2i32 V64:$Rn),
9935                         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
9936                                                  VectorIndexS:$idx))))))]> {
9937     bits<2> idx;
9938     let Inst{11} = idx{1};
9939     let Inst{21} = idx{0};
9940   }
9941
9942   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
9943   // an intermediate EXTRACT_SUBREG would be untyped.
9944   // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we
9945   // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
9946   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9947                        (i32 (vector_extract
9948                                (v4i32 (insert_subvector
9949                                        (undef),
9950                                         (v2i32 (int_aarch64_neon_sqrdmulh
9951                                                  (v2i32 V64:$Rn),
9952                                                  (v2i32 (AArch64duplane32
9953                                                           (v4i32 V128:$Rm),
9954                                                           VectorIndexS:$idx)))),
9955                                       (i32 0))),
9956                                (i64 0))))),
9957             (EXTRACT_SUBREG
9958                 (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
9959                           (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
9960                                                 FPR32Op:$Rd,
9961                                                 ssub)),
9962                           V64:$Rn,
9963                           V128:$Rm,
9964                           VectorIndexS:$idx)),
9965                 ssub)>;
9966
9967   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9968                                           V128, V128, V128, VectorIndexS,
9969                                           asm, ".4s", ".4s", ".4s", ".s",
9970     [(set (v4i32 V128:$dst),
9971           (Accum (v4i32 V128:$Rd),
9972                  (v4i32 (int_aarch64_neon_sqrdmulh
9973                           (v4i32 V128:$Rn),
9974                           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
9975                                                    VectorIndexS:$idx))))))]> {
9976     bits<2> idx;
9977     let Inst{11} = idx{1};
9978     let Inst{21} = idx{0};
9979   }
9980
9981   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
9982   // an intermediate EXTRACT_SUBREG would be untyped.
9983   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9984                         (i32 (vector_extract
9985                                (v4i32 (int_aarch64_neon_sqrdmulh
9986                                         (v4i32 V128:$Rn),
9987                                         (v4i32 (AArch64duplane32
9988                                                  (v4i32 V128:$Rm),
9989                                                  VectorIndexS:$idx)))),
9990                                (i64 0))))),
9991             (EXTRACT_SUBREG
9992                 (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
9993                          (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
9994                                                FPR32Op:$Rd,
9995                                                ssub)),
9996                          V128:$Rn,
9997                          V128:$Rm,
9998                          VectorIndexS:$idx)),
9999                 ssub)>;
10000
10001   def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
10002                                         FPR16Op, FPR16Op, V128_lo,
10003                                         VectorIndexH, asm, ".h", "", "", ".h",
10004                                         []> {
10005     bits<3> idx;
10006     let Inst{11} = idx{2};
10007     let Inst{21} = idx{1};
10008     let Inst{20} = idx{0};
10009   }
10010
10011   def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
10012                                         FPR32Op, FPR32Op, V128, VectorIndexS,
10013                                         asm, ".s", "", "", ".s",
10014     [(set (i32 FPR32Op:$dst),
10015           (Accum (i32 FPR32Op:$Rd),
10016                  (i32 (int_aarch64_neon_sqrdmulh
10017                         (i32 FPR32Op:$Rn),
10018                         (i32 (vector_extract (v4i32 V128:$Rm),
10019                                              VectorIndexS:$idx))))))]> {
10020     bits<2> idx;
10021     let Inst{11} = idx{1};
10022     let Inst{21} = idx{0};
10023   }
10024 }
10025 } // let Predicates = [HasNeon, HasRDM]
10026
10027 //----------------------------------------------------------------------------
10028 // ARMv8.3 Complex ADD/MLA instructions
10029 //----------------------------------------------------------------------------
10030
10031 class ComplexRotationOperand<int Angle, int Remainder, string Type>
10032   : AsmOperandClass {
10033   let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
10034   let DiagnosticType = "InvalidComplexRotation" # Type;
10035   let Name = "ComplexRotation" # Type;
10036 }
10037 def complexrotateop : Operand<i32> {
10038   let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
10039   let PrintMethod = "printComplexRotationOp<90, 0>";
10040 }
10041 def complexrotateopodd : Operand<i32> {
10042   let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
10043   let PrintMethod = "printComplexRotationOp<180, 90>";
10044 }
10045
10046 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10047 class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
10048                                      RegisterOperand regtype, Operand rottype,
10049                                      string asm, string kind, list<dag> pattern>
10050   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10051       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10052       "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
10053     Sched<[WriteV]> {
10054   bits<5> Rd;
10055   bits<5> Rn;
10056   bits<5> Rm;
10057   bits<1> rot;
10058   let Inst{31}    = 0;
10059   let Inst{30}    = Q;
10060   let Inst{29}    = U;
10061   let Inst{28-24} = 0b01110;
10062   let Inst{23-22} = size;
10063   let Inst{21}    = 0;
10064   let Inst{20-16} = Rm;
10065   let Inst{15-13} = opcode;
10066   // Non-tied version (FCADD) only has one rotation bit
10067   let Inst{12}    = rot;
10068   let Inst{11}    = 0;
10069   let Inst{10}    = 1;
10070   let Inst{9-5}   = Rn;
10071   let Inst{4-0}   = Rd;
10072 }
10073
10074 //8.3 CompNum - Floating-point complex number support
10075 multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
10076                                           string asm, SDPatternOperator OpNode>{
10077   let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10078   def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
10079               asm, ".4h",
10080               [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10081                                               (v4f16 V64:$Rn),
10082                                               (v4f16 V64:$Rm),
10083                                               (rottype i32:$rot)))]>;
10084
10085   def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
10086               asm, ".8h",
10087               [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10088                                                (v8f16 V128:$Rn),
10089                                                (v8f16 V128:$Rm),
10090                                                (rottype i32:$rot)))]>;
10091   }
10092
10093   let Predicates = [HasComplxNum, HasNEON] in {
10094   def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
10095               asm, ".2s",
10096               [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10097                                               (v2f32 V64:$Rn),
10098                                               (v2f32 V64:$Rm),
10099                                               (rottype i32:$rot)))]>;
10100
10101   def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
10102               asm, ".4s",
10103               [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10104                                                (v4f32 V128:$Rn),
10105                                                (v4f32 V128:$Rm),
10106                                                (rottype i32:$rot)))]>;
10107
10108   def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
10109               asm, ".2d",
10110               [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10111                                                (v2f64 V128:$Rn),
10112                                                (v2f64 V128:$Rm),
10113                                                (rottype i32:$rot)))]>;
10114   }
10115 }
10116
10117 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10118 class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
10119                                          bits<3> opcode,
10120                                          RegisterOperand regtype,
10121                                          Operand rottype, string asm,
10122                                          string kind, list<dag> pattern>
10123   : I<(outs regtype:$dst),
10124       (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10125       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10126       "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
10127     Sched<[WriteV]> {
10128   bits<5> Rd;
10129   bits<5> Rn;
10130   bits<5> Rm;
10131   bits<2> rot;
10132   let Inst{31}    = 0;
10133   let Inst{30}    = Q;
10134   let Inst{29}    = U;
10135   let Inst{28-24} = 0b01110;
10136   let Inst{23-22} = size;
10137   let Inst{21}    = 0;
10138   let Inst{20-16} = Rm;
10139   let Inst{15-13} = opcode;
10140   let Inst{12-11} = rot;
10141   let Inst{10}    = 1;
10142   let Inst{9-5}   = Rn;
10143   let Inst{4-0}   = Rd;
10144 }
10145
10146 multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
10147                                              Operand rottype, string asm,
10148                                              SDPatternOperator OpNode> {
10149   let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10150   def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
10151               rottype, asm, ".4h",
10152               [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10153                                               (v4f16 V64:$Rn),
10154                                               (v4f16 V64:$Rm),
10155                                               (rottype i32:$rot)))]>;
10156
10157   def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
10158               rottype, asm, ".8h",
10159               [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10160                                                (v8f16 V128:$Rn),
10161                                                (v8f16 V128:$Rm),
10162                                                (rottype i32:$rot)))]>;
10163   }
10164
10165   let Predicates = [HasComplxNum, HasNEON] in {
10166   def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
10167               rottype, asm, ".2s",
10168               [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10169                                               (v2f32 V64:$Rn),
10170                                               (v2f32 V64:$Rm),
10171                                               (rottype i32:$rot)))]>;
10172
10173   def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
10174               rottype, asm, ".4s",
10175               [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10176                                                (v4f32 V128:$Rn),
10177                                                (v4f32 V128:$Rm),
10178                                                (rottype i32:$rot)))]>;
10179
10180   def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
10181               rottype, asm, ".2d",
10182               [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10183                                                (v2f64 V128:$Rn),
10184                                                (v2f64 V128:$Rm),
10185                                                (rottype i32:$rot)))]>;
10186   }
10187 }
10188
10189 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10190 class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
10191                                  bit opc1, bit opc2, RegisterOperand dst_reg,
10192                                  RegisterOperand lhs_reg,
10193                                  RegisterOperand rhs_reg, Operand vec_idx,
10194                                  Operand rottype, string asm, string apple_kind,
10195                                  string dst_kind, string lhs_kind,
10196                                  string rhs_kind, list<dag> pattern>
10197   : I<(outs dst_reg:$dst),
10198       (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
10199       asm,
10200       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
10201       "$idx, $rot" # "|" # apple_kind #
10202       "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
10203     Sched<[WriteV]> {
10204   bits<5> Rd;
10205   bits<5> Rn;
10206   bits<5> Rm;
10207   bits<2> rot;
10208
10209   let Inst{31}    = 0;
10210   let Inst{30}    = Q;
10211   let Inst{29}    = U;
10212   let Inst{28}    = Scalar;
10213   let Inst{27-24} = 0b1111;
10214   let Inst{23-22} = size;
10215   // Bit 21 must be set by the derived class.
10216   let Inst{20-16} = Rm;
10217   let Inst{15}    = opc1;
10218   let Inst{14-13} = rot;
10219   let Inst{12}    = opc2;
10220   // Bit 11 must be set by the derived class.
10221   let Inst{10}    = 0;
10222   let Inst{9-5}   = Rn;
10223   let Inst{4-0}   = Rd;
10224 }
10225
10226 // The complex instructions index by pairs of elements, so the VectorIndexes
10227 // don't match the lane types, and the index bits are different to the other
10228 // classes.
10229 multiclass SIMDIndexedTiedComplexHSD<bit U, bit opc1, bit opc2, Operand rottype,
10230                                      string asm, SDPatternOperator OpNode> {
10231   let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10232   def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
10233                       V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
10234                       ".4h", ".h", []> {
10235     bits<1> idx;
10236     let Inst{11} = 0;
10237     let Inst{21} = idx{0};
10238   }
10239
10240   def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
10241                       V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
10242                       ".8h", ".8h", ".h", []> {
10243     bits<2> idx;
10244     let Inst{11} = idx{1};
10245     let Inst{21} = idx{0};
10246   }
10247   } // Predicates = HasComplxNum, HasNEON, HasFullFP16]
10248
10249   let Predicates = [HasComplxNum, HasNEON] in {
10250   def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
10251                       V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
10252                       ".4s", ".4s", ".s", []> {
10253     bits<1> idx;
10254     let Inst{11} = idx{0};
10255     let Inst{21} = 0;
10256   }
10257   } // Predicates = [HasComplxNum, HasNEON]
10258 }
10259
10260 //----------------------------------------------------------------------------
10261 // Crypto extensions
10262 //----------------------------------------------------------------------------
10263
10264 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10265 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
10266               list<dag> pat>
10267   : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
10268     Sched<[WriteV]>{
10269   bits<5> Rd;
10270   bits<5> Rn;
10271   let Inst{31-16} = 0b0100111000101000;
10272   let Inst{15-12} = opc;
10273   let Inst{11-10} = 0b10;
10274   let Inst{9-5}   = Rn;
10275   let Inst{4-0}   = Rd;
10276 }
10277
10278 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
10279   : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
10280             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
10281
10282 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
10283   : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
10284             "$Rd = $dst",
10285             [(set (v16i8 V128:$dst),
10286                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
10287
10288 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10289 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
10290                      dag oops, dag iops, list<dag> pat>
10291   : I<oops, iops, asm,
10292       "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
10293       "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
10294     Sched<[WriteV]>{
10295   bits<5> Rd;
10296   bits<5> Rn;
10297   bits<5> Rm;
10298   let Inst{31-21} = 0b01011110000;
10299   let Inst{20-16} = Rm;
10300   let Inst{15}    = 0;
10301   let Inst{14-12} = opc;
10302   let Inst{11-10} = 0b00;
10303   let Inst{9-5}   = Rn;
10304   let Inst{4-0}   = Rd;
10305 }
10306
10307 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
10308   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10309                    (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
10310                    [(set (v4i32 FPR128:$dst),
10311                          (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
10312                                  (v4i32 V128:$Rm)))]>;
10313
10314 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
10315   : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
10316                    (ins V128:$Rd, V128:$Rn, V128:$Rm),
10317                    [(set (v4i32 V128:$dst),
10318                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10319                                  (v4i32 V128:$Rm)))]>;
10320
10321 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
10322   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10323                    (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
10324                    [(set (v4i32 FPR128:$dst),
10325                          (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
10326                                  (v4i32 V128:$Rm)))]>;
10327
10328 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10329 class SHA2OpInst<bits<4> opc, string asm, string kind,
10330                  string cstr, dag oops, dag iops,
10331                  list<dag> pat>
10332   : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
10333                        "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
10334     Sched<[WriteV]>{
10335   bits<5> Rd;
10336   bits<5> Rn;
10337   let Inst{31-16} = 0b0101111000101000;
10338   let Inst{15-12} = opc;
10339   let Inst{11-10} = 0b10;
10340   let Inst{9-5}   = Rn;
10341   let Inst{4-0}   = Rd;
10342 }
10343
10344 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
10345   : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
10346                (ins V128:$Rd, V128:$Rn),
10347                [(set (v4i32 V128:$dst),
10348                      (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
10349
10350 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
10351   : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
10352                [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
10353
10354 // Armv8.2-A Crypto extensions
10355 class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
10356                     list<dag> pattern>
10357   : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteV]> {
10358   bits<5> Vd;
10359   bits<5> Vn;
10360   let Inst{31-25} = 0b1100111;
10361   let Inst{9-5}   = Vn;
10362   let Inst{4-0}   = Vd;
10363 }
10364
10365 class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
10366   : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm, asmops,
10367                   "$Vm = $Vd", []> {
10368   let Inst{31-25} = 0b1100111;
10369   let Inst{24-21} = 0b0110;
10370   let Inst{20-15} = 0b000001;
10371   let Inst{14}    = op0;
10372   let Inst{13-12} = 0b00;
10373   let Inst{11-10} = op1;
10374 }
10375 class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
10376   : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d}">;
10377 class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
10378   : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s}">;
10379
10380 class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
10381                 string asmops, string cst>
10382   : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
10383   bits<5> Vm;
10384   let Inst{24-21} = 0b0011;
10385   let Inst{20-16} = Vm;
10386   let Inst{15}    = 0b1;
10387   let Inst{14}    = op0;
10388   let Inst{13-12} = 0b00;
10389   let Inst{11-10} = op1;
10390 }
10391 class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
10392   : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10393               "{\t$Vd.2d, $Vn.2d, $Vm.2d}", "">;
10394 class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
10395   : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10396               "{\t$Vd.2d, $Vn.2d, $Vm.2d}", "$Vd = $Vdst">;
10397 class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
10398   : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10399               "{\t$Vd.4s, $Vn.4s, $Vm.4s}", "">;
10400 class CryptoRRRTied_4S<bits<1> op0, bits<2>op1, string asm>
10401   : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10402               "{\t$Vd.4s, $Vn.4s, $Vm.4s}", "$Vd = $Vdst">;
10403 class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
10404   : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
10405               asm, "{\t$Vd, $Vn, $Vm.2d}", "$Vd = $Vdst">;
10406
10407 class CryptoRRRR<bits<2>op0, string asm, string asmops>
10408   : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
10409                   asmops, "", []> {
10410   bits<5> Vm;
10411   bits<5> Va;
10412   let Inst{24-23} = 0b00;
10413   let Inst{22-21} = op0;
10414   let Inst{20-16} = Vm;
10415   let Inst{15}    = 0b0;
10416   let Inst{14-10} = Va;
10417 }
10418 class CryptoRRRR_16B<bits<2>op0, string asm>
10419  : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b}"> {
10420 }
10421 class CryptoRRRR_4S<bits<2>op0, string asm>
10422  : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s}"> {
10423 }
10424
10425 class CryptoRRRi6<string asm>
10426   : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
10427                   "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm}", "", []> {
10428   bits<6> imm;
10429   bits<5> Vm;
10430   let Inst{24-21} = 0b0100;
10431   let Inst{20-16} = Vm;
10432   let Inst{15-10} = imm;
10433   let Inst{9-5}   = Vn;
10434   let Inst{4-0}   = Vd;
10435 }
10436
10437 class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
10438   : BaseCryptoV82<(outs V128:$Vdst),
10439                   (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
10440                   asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm}", "$Vd = $Vdst", []> {
10441   bits<2> imm;
10442   bits<5> Vm;
10443   let Inst{24-21} = 0b0010;
10444   let Inst{20-16} = Vm;
10445   let Inst{15}    = 0b1;
10446   let Inst{14}    = op0;
10447   let Inst{13-12} = imm;
10448   let Inst{11-10} = op1;
10449 }
10450
10451 //----------------------------------------------------------------------------
10452 // v8.1 atomic instructions extension:
10453 // * CAS
10454 // * CASP
10455 // * SWP
10456 // * LDOPregister<OP>, and aliases STOPregister<OP>
10457
10458 // Instruction encodings:
10459 //
10460 //      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
10461 // CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
10462 // CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
10463 // SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
10464 // LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
10465 // ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
10466
10467 // Instruction syntax:
10468 //
10469 // CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10470 // CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
10471 // CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
10472 // CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
10473 // SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10474 // SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
10475 // LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10476 // LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
10477 // ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
10478 // ST<OP>{<order>} <Xs>, [<Xn|SP>]
10479
10480 let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
10481 class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
10482                       string cstr, list<dag> pattern>
10483       : I<oops, iops, asm, operands, cstr, pattern> {
10484   bits<2> Sz;
10485   bit NP;
10486   bit Acq;
10487   bit Rel;
10488   bits<5> Rs;
10489   bits<5> Rn;
10490   bits<5> Rt;
10491   let Inst{31-30} = Sz;
10492   let Inst{29-24} = 0b001000;
10493   let Inst{23} = NP;
10494   let Inst{22} = Acq;
10495   let Inst{21} = 0b1;
10496   let Inst{20-16} = Rs;
10497   let Inst{15} = Rel;
10498   let Inst{14-10} = 0b11111;
10499   let Inst{9-5} = Rn;
10500   let Inst{4-0} = Rt;
10501   let Predicates = [HasLSE];
10502 }
10503
10504 class BaseCAS<string order, string size, RegisterClass RC>
10505       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
10506                         "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
10507                         "$out = $Rs",[]>,
10508         Sched<[WriteAtomic]> {
10509   let NP = 1;
10510 }
10511
10512 multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
10513   let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
10514   let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
10515   let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
10516   let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
10517 }
10518
10519 class BaseCASP<string order, string size, RegisterOperand RC>
10520       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
10521                         "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
10522                         "$out = $Rs",[]>,
10523         Sched<[WriteAtomic]> {
10524   let NP = 0;
10525 }
10526
10527 multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
10528   let Sz = 0b00, Acq = Acq, Rel = Rel in
10529     def W : BaseCASP<order, "", WSeqPairClassOperand>;
10530   let Sz = 0b01, Acq = Acq, Rel = Rel in
10531     def X : BaseCASP<order, "", XSeqPairClassOperand>;
10532 }
10533
10534 let Predicates = [HasLSE] in
10535 class BaseSWP<string order, string size, RegisterClass RC>
10536       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
10537           "\t$Rs, $Rt, [$Rn]","",[]>,
10538         Sched<[WriteAtomic]> {
10539   bits<2> Sz;
10540   bit Acq;
10541   bit Rel;
10542   bits<5> Rs;
10543   bits<3> opc = 0b000;
10544   bits<5> Rn;
10545   bits<5> Rt;
10546   let Inst{31-30} = Sz;
10547   let Inst{29-24} = 0b111000;
10548   let Inst{23} = Acq;
10549   let Inst{22} = Rel;
10550   let Inst{21} = 0b1;
10551   let Inst{20-16} = Rs;
10552   let Inst{15} = 0b1;
10553   let Inst{14-12} = opc;
10554   let Inst{11-10} = 0b00;
10555   let Inst{9-5} = Rn;
10556   let Inst{4-0} = Rt;
10557   let Predicates = [HasLSE];
10558 }
10559
10560 multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
10561   let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
10562   let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
10563   let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
10564   let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
10565 }
10566
10567 let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
10568 class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
10569       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
10570           "\t$Rs, $Rt, [$Rn]","",[]>,
10571         Sched<[WriteAtomic]> {
10572   bits<2> Sz;
10573   bit Acq;
10574   bit Rel;
10575   bits<5> Rs;
10576   bits<3> opc;
10577   bits<5> Rn;
10578   bits<5> Rt;
10579   let Inst{31-30} = Sz;
10580   let Inst{29-24} = 0b111000;
10581   let Inst{23} = Acq;
10582   let Inst{22} = Rel;
10583   let Inst{21} = 0b1;
10584   let Inst{20-16} = Rs;
10585   let Inst{15} = 0b0;
10586   let Inst{14-12} = opc;
10587   let Inst{11-10} = 0b00;
10588   let Inst{9-5} = Rn;
10589   let Inst{4-0} = Rt;
10590   let Predicates = [HasLSE];
10591 }
10592
10593 multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
10594                         string order> {
10595   let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
10596     def B : BaseLDOPregister<op, order, "b", GPR32>;
10597   let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
10598     def H : BaseLDOPregister<op, order, "h", GPR32>;
10599   let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
10600     def W : BaseLDOPregister<op, order, "", GPR32>;
10601   let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
10602     def X : BaseLDOPregister<op, order, "", GPR64>;
10603 }
10604
10605 // Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
10606 // complex DAG for DstRHS.
10607 let Predicates = [HasLSE] in
10608 multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
10609                                          string size, dag SrcRHS, dag DstRHS> {
10610   def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
10611             (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
10612   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
10613             (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
10614   def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
10615             (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
10616   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
10617             (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
10618   def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
10619             (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
10620 }
10621
10622 multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
10623                                      string size, dag RHS> {
10624   defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, RHS, RHS>;
10625 }
10626
10627 multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
10628                                          string size, dag LHS, dag RHS> {
10629   defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, LHS, RHS>;
10630 }
10631
10632 multiclass LDOPregister_patterns<string inst, string op> {
10633   defm : LDOPregister_patterns_ord<inst, "X", op, "64", (i64 GPR64:$Rm)>;
10634   defm : LDOPregister_patterns_ord<inst, "W", op, "32", (i32 GPR32:$Rm)>;
10635   defm : LDOPregister_patterns_ord<inst, "H", op, "16", (i32 GPR32:$Rm)>;
10636   defm : LDOPregister_patterns_ord<inst, "B", op, "8",  (i32 GPR32:$Rm)>;
10637 }
10638
10639 multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
10640   defm : LDOPregister_patterns_ord_mod<inst, "X", op, "64",
10641                         (i64 GPR64:$Rm),
10642                         (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
10643   defm : LDOPregister_patterns_ord_mod<inst, "W", op, "32",
10644                         (i32 GPR32:$Rm),
10645                         (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10646   defm : LDOPregister_patterns_ord_mod<inst, "H", op, "16",
10647                         (i32 GPR32:$Rm),
10648                         (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10649   defm : LDOPregister_patterns_ord_mod<inst, "B", op, "8",
10650                         (i32 GPR32:$Rm),
10651                         (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10652 }
10653
10654 let Predicates = [HasLSE] in
10655 multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
10656                                         string size, dag OLD, dag NEW> {
10657   def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
10658             (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
10659   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
10660             (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10661   def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
10662             (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10663   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
10664             (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10665   def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
10666             (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10667 }
10668
10669 multiclass CASregister_patterns_ord<string inst, string suffix, string op,
10670                                     string size, dag OLD, dag NEW> {
10671   defm : CASregister_patterns_ord_dag<inst, suffix, op, size, OLD, NEW>;
10672 }
10673
10674 multiclass CASregister_patterns<string inst, string op> {
10675   defm : CASregister_patterns_ord<inst, "X", op, "64",
10676                         (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
10677   defm : CASregister_patterns_ord<inst, "W", op, "32",
10678                         (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10679   defm : CASregister_patterns_ord<inst, "H", op, "16",
10680                         (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10681   defm : CASregister_patterns_ord<inst, "B", op, "8",
10682                         (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10683 }
10684
10685 let Predicates = [HasLSE] in
10686 class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
10687                         Instruction inst> :
10688       InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
10689
10690 multiclass STOPregister<string asm, string instr> {
10691   def : BaseSTOPregister<asm # "lb", GPR32, WZR,
10692                     !cast<Instruction>(instr # "LB")>;
10693   def : BaseSTOPregister<asm # "lh", GPR32, WZR,
10694                     !cast<Instruction>(instr # "LH")>;
10695   def : BaseSTOPregister<asm # "l",  GPR32, WZR,
10696                     !cast<Instruction>(instr # "LW")>;
10697   def : BaseSTOPregister<asm # "l",  GPR64, XZR,
10698                     !cast<Instruction>(instr # "LX")>;
10699   def : BaseSTOPregister<asm # "b",  GPR32, WZR,
10700                     !cast<Instruction>(instr # "B")>;
10701   def : BaseSTOPregister<asm # "h",  GPR32, WZR,
10702                     !cast<Instruction>(instr # "H")>;
10703   def : BaseSTOPregister<asm,        GPR32, WZR,
10704                     !cast<Instruction>(instr # "W")>;
10705   def : BaseSTOPregister<asm,        GPR64, XZR,
10706                     !cast<Instruction>(instr # "X")>;
10707 }
10708
10709 //----------------------------------------------------------------------------
10710 // Allow the size specifier tokens to be upper case, not just lower.
10711 def : TokenAlias<".4B", ".4b">;  // Add dot product
10712 def : TokenAlias<".8B", ".8b">;
10713 def : TokenAlias<".4H", ".4h">;
10714 def : TokenAlias<".2S", ".2s">;
10715 def : TokenAlias<".1D", ".1d">;
10716 def : TokenAlias<".16B", ".16b">;
10717 def : TokenAlias<".8H", ".8h">;
10718 def : TokenAlias<".4S", ".4s">;
10719 def : TokenAlias<".2D", ".2d">;
10720 def : TokenAlias<".1Q", ".1q">;
10721 def : TokenAlias<".2H", ".2h">;
10722 def : TokenAlias<".B", ".b">;
10723 def : TokenAlias<".H", ".h">;
10724 def : TokenAlias<".S", ".s">;
10725 def : TokenAlias<".D", ".d">;
10726 def : TokenAlias<".Q", ".q">;