]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/AArch64/AArch64InstrFormats.td
Merge llvm trunk r338150 (just before the 7.0.0 branch point), and
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / AArch64 / AArch64InstrFormats.td
1 //===- AArch64InstrFormats.td - AArch64 Instruction Formats --*- tblgen -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 //===----------------------------------------------------------------------===//
11 //  Describe AArch64 instructions format here
12 //
13
14 // Format specifies the encoding used by the instruction.  This is part of the
15 // ad-hoc solution used to emit machine instruction encodings by our machine
16 // code emitter.
17 class Format<bits<2> val> {
18   bits<2> Value = val;
19 }
20
21 def PseudoFrm   : Format<0>;
22 def NormalFrm   : Format<1>; // Do we need any others?
23
24 // AArch64 Instruction Format
25 class AArch64Inst<Format f, string cstr> : Instruction {
26   field bits<32> Inst; // Instruction encoding.
27   // Mask of bits that cause an encoding to be UNPREDICTABLE.
28   // If a bit is set, then if the corresponding bit in the
29   // target encoding differs from its value in the "Inst" field,
30   // the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
31   field bits<32> Unpredictable = 0;
32   // SoftFail is the generic name for this field, but we alias it so
33   // as to make it more obvious what it means in ARM-land.
34   field bits<32> SoftFail = Unpredictable;
35   let Namespace   = "AArch64";
36   Format F        = f;
37   bits<2> Form    = F.Value;
38   let Pattern     = [];
39   let Constraints = cstr;
40 }
41
42 class InstSubst<string Asm, dag Result, bit EmitPriority = 0>
43   : InstAlias<Asm, Result, EmitPriority>, Requires<[UseNegativeImmediates]>;
44
45 // Pseudo instructions (don't have encoding information)
46 class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
47     : AArch64Inst<PseudoFrm, cstr> {
48   dag OutOperandList = oops;
49   dag InOperandList  = iops;
50   let Pattern        = pattern;
51   let isCodeGenOnly  = 1;
52 }
53
54 // Real instructions (have encoding information)
55 class EncodedI<string cstr, list<dag> pattern> : AArch64Inst<NormalFrm, cstr> {
56   let Pattern = pattern;
57   let Size = 4;
58 }
59
60 // Enum describing whether an instruction is
61 // destructive in its first source operand.
62 class DestructiveInstTypeEnum<bits<1> val> {
63   bits<1> Value = val;
64 }
65 def NotDestructive  : DestructiveInstTypeEnum<0>;
66 def Destructive     : DestructiveInstTypeEnum<1>;
67
68 // Normal instructions
69 class I<dag oops, dag iops, string asm, string operands, string cstr,
70         list<dag> pattern>
71     : EncodedI<cstr, pattern> {
72   dag OutOperandList = oops;
73   dag InOperandList  = iops;
74   let AsmString      = !strconcat(asm, operands);
75
76   // Destructive operations (SVE)
77   DestructiveInstTypeEnum DestructiveInstType = NotDestructive;
78   ElementSizeEnum ElementSize = ElementSizeB;
79
80   let TSFlags{3} = DestructiveInstType.Value;
81   let TSFlags{2-0} = ElementSize.Value;
82 }
83
84 class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
85 class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
86 class UnOpFrag<dag res>  : PatFrag<(ops node:$LHS), res>;
87
88 // Helper fragment for an extract of the high portion of a 128-bit vector.
89 def extract_high_v16i8 :
90    UnOpFrag<(extract_subvector (v16i8 node:$LHS), (i64 8))>;
91 def extract_high_v8i16 :
92    UnOpFrag<(extract_subvector (v8i16 node:$LHS), (i64 4))>;
93 def extract_high_v4i32 :
94    UnOpFrag<(extract_subvector (v4i32 node:$LHS), (i64 2))>;
95 def extract_high_v2i64 :
96    UnOpFrag<(extract_subvector (v2i64 node:$LHS), (i64 1))>;
97
98 //===----------------------------------------------------------------------===//
99 // Asm Operand Classes.
100 //
101
102 // Shifter operand for arithmetic shifted encodings.
103 def ShifterOperand : AsmOperandClass {
104   let Name = "Shifter";
105 }
106
107 // Shifter operand for mov immediate encodings.
108 def MovImm32ShifterOperand : AsmOperandClass {
109   let SuperClasses = [ShifterOperand];
110   let Name = "MovImm32Shifter";
111   let RenderMethod = "addShifterOperands";
112   let DiagnosticType = "InvalidMovImm32Shift";
113 }
114 def MovImm64ShifterOperand : AsmOperandClass {
115   let SuperClasses = [ShifterOperand];
116   let Name = "MovImm64Shifter";
117   let RenderMethod = "addShifterOperands";
118   let DiagnosticType = "InvalidMovImm64Shift";
119 }
120
121 // Shifter operand for arithmetic register shifted encodings.
122 class ArithmeticShifterOperand<int width> : AsmOperandClass {
123   let SuperClasses = [ShifterOperand];
124   let Name = "ArithmeticShifter" # width;
125   let PredicateMethod = "isArithmeticShifter<" # width # ">";
126   let RenderMethod = "addShifterOperands";
127   let DiagnosticType = "AddSubRegShift" # width;
128 }
129
130 def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
131 def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
132
133 // Shifter operand for logical register shifted encodings.
134 class LogicalShifterOperand<int width> : AsmOperandClass {
135   let SuperClasses = [ShifterOperand];
136   let Name = "LogicalShifter" # width;
137   let PredicateMethod = "isLogicalShifter<" # width # ">";
138   let RenderMethod = "addShifterOperands";
139   let DiagnosticType = "AddSubRegShift" # width;
140 }
141
142 def LogicalShifterOperand32 : LogicalShifterOperand<32>;
143 def LogicalShifterOperand64 : LogicalShifterOperand<64>;
144
145 // Shifter operand for logical vector 128/64-bit shifted encodings.
146 def LogicalVecShifterOperand : AsmOperandClass {
147   let SuperClasses = [ShifterOperand];
148   let Name = "LogicalVecShifter";
149   let RenderMethod = "addShifterOperands";
150 }
151 def LogicalVecHalfWordShifterOperand : AsmOperandClass {
152   let SuperClasses = [LogicalVecShifterOperand];
153   let Name = "LogicalVecHalfWordShifter";
154   let RenderMethod = "addShifterOperands";
155 }
156
157 // The "MSL" shifter on the vector MOVI instruction.
158 def MoveVecShifterOperand : AsmOperandClass {
159   let SuperClasses = [ShifterOperand];
160   let Name = "MoveVecShifter";
161   let RenderMethod = "addShifterOperands";
162 }
163
164 // Extend operand for arithmetic encodings.
165 def ExtendOperand : AsmOperandClass {
166   let Name = "Extend";
167   let DiagnosticType = "AddSubRegExtendLarge";
168 }
169 def ExtendOperand64 : AsmOperandClass {
170   let SuperClasses = [ExtendOperand];
171   let Name = "Extend64";
172   let DiagnosticType = "AddSubRegExtendSmall";
173 }
174 // 'extend' that's a lsl of a 64-bit register.
175 def ExtendOperandLSL64 : AsmOperandClass {
176   let SuperClasses = [ExtendOperand];
177   let Name = "ExtendLSL64";
178   let RenderMethod = "addExtend64Operands";
179   let DiagnosticType = "AddSubRegExtendLarge";
180 }
181
182 // 8-bit floating-point immediate encodings.
183 def FPImmOperand : AsmOperandClass {
184   let Name = "FPImm";
185   let ParserMethod = "tryParseFPImm<true>";
186   let DiagnosticType = "InvalidFPImm";
187 }
188
189 def CondCode : AsmOperandClass {
190   let Name = "CondCode";
191   let DiagnosticType = "InvalidCondCode";
192 }
193
194 // A 32-bit register pasrsed as 64-bit
195 def GPR32as64Operand : AsmOperandClass {
196   let Name = "GPR32as64";
197   let ParserMethod =
198       "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSubReg>";
199 }
200 def GPR32as64 : RegisterOperand<GPR32> {
201   let ParserMatchClass = GPR32as64Operand;
202 }
203
204 // A 64-bit register pasrsed as 32-bit
205 def GPR64as32Operand : AsmOperandClass {
206   let Name = "GPR64as32";
207   let ParserMethod =
208       "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSuperReg>";
209 }
210 def GPR64as32 : RegisterOperand<GPR64, "printGPR64as32"> {
211   let ParserMatchClass = GPR64as32Operand;
212 }
213
214 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
215 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
216 // are encoded as the eight bit value 'abcdefgh'.
217 def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
218
219 class UImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
220   let Name = "UImm" # Width # "s" # Scale;
221   let DiagnosticType = "InvalidMemoryIndexed" # Scale # "UImm" # Width;
222   let RenderMethod = "addImmScaledOperands<" # Scale # ">";
223   let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ">";
224 }
225
226 class SImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
227   let Name = "SImm" # Width # "s" # Scale;
228   let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm" # Width;
229   let RenderMethod = "addImmScaledOperands<" # Scale # ">";
230   let PredicateMethod = "isSImmScaled<" # Width # ", " # Scale # ">";
231 }
232
233 //===----------------------------------------------------------------------===//
234 // Operand Definitions.
235 //
236
237 // ADR[P] instruction labels.
238 def AdrpOperand : AsmOperandClass {
239   let Name = "AdrpLabel";
240   let ParserMethod = "tryParseAdrpLabel";
241   let DiagnosticType = "InvalidLabel";
242 }
243 def adrplabel : Operand<i64> {
244   let EncoderMethod = "getAdrLabelOpValue";
245   let PrintMethod = "printAdrpLabel";
246   let ParserMatchClass = AdrpOperand;
247 }
248
249 def AdrOperand : AsmOperandClass {
250   let Name = "AdrLabel";
251   let ParserMethod = "tryParseAdrLabel";
252   let DiagnosticType = "InvalidLabel";
253 }
254 def adrlabel : Operand<i64> {
255   let EncoderMethod = "getAdrLabelOpValue";
256   let ParserMatchClass = AdrOperand;
257 }
258
259 class SImmOperand<int width> : AsmOperandClass {
260   let Name = "SImm" # width;
261   let DiagnosticType = "InvalidMemoryIndexedSImm" # width;
262   let RenderMethod = "addImmOperands";
263   let PredicateMethod = "isSImm<" # width # ">";
264 }
265
266 // Authenticated loads for v8.3 can have scaled 10-bit immediate offsets.
267 def SImm10s8Operand : SImmScaledMemoryIndexed<10, 8>;
268 def simm10Scaled : Operand<i64> {
269   let ParserMatchClass = SImm10s8Operand;
270   let DecoderMethod = "DecodeSImm<10>";
271   let PrintMethod = "printImmScale<8>";
272 }
273
274 // uimm6 predicate - True if the immediate is in the range [0, 63].
275 def UImm6Operand : AsmOperandClass {
276   let Name = "UImm6";
277   let DiagnosticType = "InvalidImm0_63";
278 }
279
280 def uimm6 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
281   let ParserMatchClass = UImm6Operand;
282 }
283
284 def SImm9Operand : SImmOperand<9>;
285 def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
286   let ParserMatchClass = SImm9Operand;
287   let DecoderMethod = "DecodeSImm<9>";
288 }
289
290 def SImm8Operand : SImmOperand<8>;
291 def simm8 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -128 && Imm < 127; }]> {
292   let ParserMatchClass = SImm8Operand;
293   let DecoderMethod = "DecodeSImm<8>";
294 }
295
296 def SImm6Operand : SImmOperand<6>;
297 def simm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -32 && Imm < 32; }]> {
298   let ParserMatchClass = SImm6Operand;
299   let DecoderMethod = "DecodeSImm<6>";
300 }
301
302 def SImm5Operand : SImmOperand<5>;
303 def simm5_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -16 && Imm < 16; }]> {
304   let ParserMatchClass = SImm5Operand;
305   let DecoderMethod = "DecodeSImm<5>";
306 }
307
308 def simm5_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -16 && Imm < 16; }]> {
309   let ParserMatchClass = SImm5Operand;
310   let DecoderMethod = "DecodeSImm<5>";
311 }
312
313 // simm7sN predicate - True if the immediate is a multiple of N in the range
314 // [-64 * N, 63 * N].
315
316 def SImm7s4Operand : SImmScaledMemoryIndexed<7, 4>;
317 def SImm7s8Operand : SImmScaledMemoryIndexed<7, 8>;
318 def SImm7s16Operand : SImmScaledMemoryIndexed<7, 16>;
319
320 def simm7s4 : Operand<i32> {
321   let ParserMatchClass = SImm7s4Operand;
322   let PrintMethod = "printImmScale<4>";
323 }
324
325 def simm7s8 : Operand<i32> {
326   let ParserMatchClass = SImm7s8Operand;
327   let PrintMethod = "printImmScale<8>";
328 }
329
330 def simm7s16 : Operand<i32> {
331   let ParserMatchClass = SImm7s16Operand;
332   let PrintMethod = "printImmScale<16>";
333 }
334
335 def am_indexed7s8   : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S8", []>;
336 def am_indexed7s16  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S16", []>;
337 def am_indexed7s32  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S32", []>;
338 def am_indexed7s64  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S64", []>;
339 def am_indexed7s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S128", []>;
340
341 // uimm5sN predicate - True if the immediate is a multiple of N in the range
342 // [0 * N, 32 * N].
343 def UImm5s2Operand : UImmScaledMemoryIndexed<5, 2>;
344 def UImm5s4Operand : UImmScaledMemoryIndexed<5, 4>;
345 def UImm5s8Operand : UImmScaledMemoryIndexed<5, 8>;
346
347 def uimm5s2 : Operand<i64>, ImmLeaf<i64,
348                 [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }]> {
349   let ParserMatchClass = UImm5s2Operand;
350   let PrintMethod = "printImmScale<2>";
351 }
352 def uimm5s4 : Operand<i64>, ImmLeaf<i64,
353                 [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }]> {
354   let ParserMatchClass = UImm5s4Operand;
355   let PrintMethod = "printImmScale<4>";
356 }
357 def uimm5s8 : Operand<i64>, ImmLeaf<i64,
358                 [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }]> {
359   let ParserMatchClass = UImm5s8Operand;
360   let PrintMethod = "printImmScale<8>";
361 }
362
363 // uimm6sN predicate - True if the immediate is a multiple of N in the range
364 // [0 * N, 64 * N].
365 def UImm6s1Operand : UImmScaledMemoryIndexed<6, 1>;
366 def UImm6s2Operand : UImmScaledMemoryIndexed<6, 2>;
367 def UImm6s4Operand : UImmScaledMemoryIndexed<6, 4>;
368 def UImm6s8Operand : UImmScaledMemoryIndexed<6, 8>;
369
370 def uimm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
371   let ParserMatchClass = UImm6s1Operand;
372 }
373 def uimm6s2 : Operand<i64>, ImmLeaf<i64,
374 [{ return Imm >= 0 && Imm < (64*2) && ((Imm % 2) == 0); }]> {
375   let PrintMethod = "printImmScale<2>";
376   let ParserMatchClass = UImm6s2Operand;
377 }
378 def uimm6s4 : Operand<i64>, ImmLeaf<i64,
379 [{ return Imm >= 0 && Imm < (64*4) && ((Imm % 4) == 0); }]> {
380   let PrintMethod = "printImmScale<4>";
381   let ParserMatchClass = UImm6s4Operand;
382 }
383 def uimm6s8 : Operand<i64>, ImmLeaf<i64,
384 [{ return Imm >= 0 && Imm < (64*8) && ((Imm % 8) == 0); }]> {
385   let PrintMethod = "printImmScale<8>";
386   let ParserMatchClass = UImm6s8Operand;
387 }
388
389 // simm6sN predicate - True if the immediate is a multiple of N in the range
390 // [-32 * N, 31 * N].
391 def SImm6s1Operand : SImmScaledMemoryIndexed<6, 1>;
392 def simm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -32 && Imm < 32; }]> {
393   let ParserMatchClass = SImm6s1Operand;
394   let DecoderMethod = "DecodeSImm<6>";
395 }
396
397 // simm4sN predicate - True if the immediate is a multiple of N in the range
398 // [ -8* N, 7 * N].
399 def SImm4s1Operand  : SImmScaledMemoryIndexed<4, 1>;
400 def SImm4s2Operand  : SImmScaledMemoryIndexed<4, 2>;
401 def SImm4s3Operand  : SImmScaledMemoryIndexed<4, 3>;
402 def SImm4s4Operand  : SImmScaledMemoryIndexed<4, 4>;
403 def SImm4s16Operand : SImmScaledMemoryIndexed<4, 16>;
404
405 def simm4s1 : Operand<i64>, ImmLeaf<i64,
406 [{ return Imm >=-8  && Imm <= 7; }]> {
407   let ParserMatchClass = SImm4s1Operand;
408   let DecoderMethod = "DecodeSImm<4>";
409 }
410
411 def simm4s2 : Operand<i64>, ImmLeaf<i64,
412 [{ return Imm >=-16  && Imm <= 14 && (Imm % 2) == 0x0; }]> {
413   let PrintMethod = "printImmScale<2>";
414   let ParserMatchClass = SImm4s2Operand;
415   let DecoderMethod = "DecodeSImm<4>";
416 }
417
418 def simm4s3 : Operand<i64>, ImmLeaf<i64,
419 [{ return Imm >=-24  && Imm <= 21 && (Imm % 3) == 0x0; }]> {
420   let PrintMethod = "printImmScale<3>";
421   let ParserMatchClass = SImm4s3Operand;
422   let DecoderMethod = "DecodeSImm<4>";
423 }
424
425 def simm4s4 : Operand<i64>, ImmLeaf<i64,
426 [{ return Imm >=-32  && Imm <= 28 && (Imm % 4) == 0x0; }]> {
427   let PrintMethod = "printImmScale<4>";
428   let ParserMatchClass = SImm4s4Operand;
429   let DecoderMethod = "DecodeSImm<4>";
430 }
431 def simm4s16 : Operand<i64>, ImmLeaf<i64,
432 [{ return Imm >=-128  && Imm <= 112 && (Imm % 16) == 0x0; }]> {
433   let PrintMethod = "printImmScale<16>";
434   let ParserMatchClass = SImm4s16Operand;
435   let DecoderMethod = "DecodeSImm<4>";
436 }
437
438 class AsmImmRange<int Low, int High> : AsmOperandClass {
439   let Name = "Imm" # Low # "_" # High;
440   let DiagnosticType = "InvalidImm" # Low # "_" # High;
441   let RenderMethod = "addImmOperands";
442   let PredicateMethod = "isImmInRange<" # Low # "," # High # ">";
443 }
444
445 def Imm1_8Operand : AsmImmRange<1, 8>;
446 def Imm1_16Operand : AsmImmRange<1, 16>;
447 def Imm1_32Operand : AsmImmRange<1, 32>;
448 def Imm1_64Operand : AsmImmRange<1, 64>;
449
450 class BranchTarget<int N> : AsmOperandClass {
451   let Name = "BranchTarget" # N;
452   let DiagnosticType = "InvalidLabel";
453   let PredicateMethod = "isBranchTarget<" # N # ">";
454 }
455
456 class PCRelLabel<int N> : BranchTarget<N> {
457   let Name = "PCRelLabel" # N;
458 }
459
460 def BranchTarget14Operand : BranchTarget<14>;
461 def BranchTarget26Operand : BranchTarget<26>;
462 def PCRelLabel19Operand   : PCRelLabel<19>;
463
464 def MovZSymbolG3AsmOperand : AsmOperandClass {
465   let Name = "MovZSymbolG3";
466   let RenderMethod = "addImmOperands";
467 }
468
469 def movz_symbol_g3 : Operand<i32> {
470   let ParserMatchClass = MovZSymbolG3AsmOperand;
471 }
472
473 def MovZSymbolG2AsmOperand : AsmOperandClass {
474   let Name = "MovZSymbolG2";
475   let RenderMethod = "addImmOperands";
476 }
477
478 def movz_symbol_g2 : Operand<i32> {
479   let ParserMatchClass = MovZSymbolG2AsmOperand;
480 }
481
482 def MovZSymbolG1AsmOperand : AsmOperandClass {
483   let Name = "MovZSymbolG1";
484   let RenderMethod = "addImmOperands";
485 }
486
487 def movz_symbol_g1 : Operand<i32> {
488   let ParserMatchClass = MovZSymbolG1AsmOperand;
489 }
490
491 def MovZSymbolG0AsmOperand : AsmOperandClass {
492   let Name = "MovZSymbolG0";
493   let RenderMethod = "addImmOperands";
494 }
495
496 def movz_symbol_g0 : Operand<i32> {
497   let ParserMatchClass = MovZSymbolG0AsmOperand;
498 }
499
500 def MovKSymbolG3AsmOperand : AsmOperandClass {
501   let Name = "MovKSymbolG3";
502   let RenderMethod = "addImmOperands";
503 }
504
505 def movk_symbol_g3 : Operand<i32> {
506   let ParserMatchClass = MovKSymbolG3AsmOperand;
507 }
508
509 def MovKSymbolG2AsmOperand : AsmOperandClass {
510   let Name = "MovKSymbolG2";
511   let RenderMethod = "addImmOperands";
512 }
513
514 def movk_symbol_g2 : Operand<i32> {
515   let ParserMatchClass = MovKSymbolG2AsmOperand;
516 }
517
518 def MovKSymbolG1AsmOperand : AsmOperandClass {
519   let Name = "MovKSymbolG1";
520   let RenderMethod = "addImmOperands";
521 }
522
523 def movk_symbol_g1 : Operand<i32> {
524   let ParserMatchClass = MovKSymbolG1AsmOperand;
525 }
526
527 def MovKSymbolG0AsmOperand : AsmOperandClass {
528   let Name = "MovKSymbolG0";
529   let RenderMethod = "addImmOperands";
530 }
531
532 def movk_symbol_g0 : Operand<i32> {
533   let ParserMatchClass = MovKSymbolG0AsmOperand;
534 }
535
536 class fixedpoint_i32<ValueType FloatVT>
537   : Operand<FloatVT>,
538     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
539   let EncoderMethod = "getFixedPointScaleOpValue";
540   let DecoderMethod = "DecodeFixedPointScaleImm32";
541   let ParserMatchClass = Imm1_32Operand;
542 }
543
544 class fixedpoint_i64<ValueType FloatVT>
545   : Operand<FloatVT>,
546     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
547   let EncoderMethod = "getFixedPointScaleOpValue";
548   let DecoderMethod = "DecodeFixedPointScaleImm64";
549   let ParserMatchClass = Imm1_64Operand;
550 }
551
552 def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
553 def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
554 def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
555
556 def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
557 def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
558 def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
559
560 def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
561   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
562 }]> {
563   let EncoderMethod = "getVecShiftR8OpValue";
564   let DecoderMethod = "DecodeVecShiftR8Imm";
565   let ParserMatchClass = Imm1_8Operand;
566 }
567 def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
568   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
569 }]> {
570   let EncoderMethod = "getVecShiftR16OpValue";
571   let DecoderMethod = "DecodeVecShiftR16Imm";
572   let ParserMatchClass = Imm1_16Operand;
573 }
574 def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
575   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
576 }]> {
577   let EncoderMethod = "getVecShiftR16OpValue";
578   let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
579   let ParserMatchClass = Imm1_8Operand;
580 }
581 def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
582   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
583 }]> {
584   let EncoderMethod = "getVecShiftR32OpValue";
585   let DecoderMethod = "DecodeVecShiftR32Imm";
586   let ParserMatchClass = Imm1_32Operand;
587 }
588 def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
589   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
590 }]> {
591   let EncoderMethod = "getVecShiftR32OpValue";
592   let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
593   let ParserMatchClass = Imm1_16Operand;
594 }
595 def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
596   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
597 }]> {
598   let EncoderMethod = "getVecShiftR64OpValue";
599   let DecoderMethod = "DecodeVecShiftR64Imm";
600   let ParserMatchClass = Imm1_64Operand;
601 }
602 def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
603   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
604 }]> {
605   let EncoderMethod = "getVecShiftR64OpValue";
606   let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
607   let ParserMatchClass = Imm1_32Operand;
608 }
609
610 def Imm0_1Operand : AsmImmRange<0, 1>;
611 def Imm0_7Operand : AsmImmRange<0, 7>;
612 def Imm0_15Operand : AsmImmRange<0, 15>;
613 def Imm0_31Operand : AsmImmRange<0, 31>;
614 def Imm0_63Operand : AsmImmRange<0, 63>;
615
616 def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
617   return (((uint32_t)Imm) < 8);
618 }]> {
619   let EncoderMethod = "getVecShiftL8OpValue";
620   let DecoderMethod = "DecodeVecShiftL8Imm";
621   let ParserMatchClass = Imm0_7Operand;
622 }
623 def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
624   return (((uint32_t)Imm) < 16);
625 }]> {
626   let EncoderMethod = "getVecShiftL16OpValue";
627   let DecoderMethod = "DecodeVecShiftL16Imm";
628   let ParserMatchClass = Imm0_15Operand;
629 }
630 def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
631   return (((uint32_t)Imm) < 32);
632 }]> {
633   let EncoderMethod = "getVecShiftL32OpValue";
634   let DecoderMethod = "DecodeVecShiftL32Imm";
635   let ParserMatchClass = Imm0_31Operand;
636 }
637 def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
638   return (((uint32_t)Imm) < 64);
639 }]> {
640   let EncoderMethod = "getVecShiftL64OpValue";
641   let DecoderMethod = "DecodeVecShiftL64Imm";
642   let ParserMatchClass = Imm0_63Operand;
643 }
644
645
646 // Crazy immediate formats used by 32-bit and 64-bit logical immediate
647 // instructions for splatting repeating bit patterns across the immediate.
648 def logical_imm32_XFORM : SDNodeXForm<imm, [{
649   uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
650   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
651 }]>;
652 def logical_imm64_XFORM : SDNodeXForm<imm, [{
653   uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
654   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
655 }]>;
656
657 let DiagnosticType = "LogicalSecondSource" in {
658   def LogicalImm32Operand : AsmOperandClass {
659     let Name = "LogicalImm32";
660     let PredicateMethod = "isLogicalImm<int32_t>";
661     let RenderMethod = "addLogicalImmOperands<int32_t>";
662   }
663   def LogicalImm64Operand : AsmOperandClass {
664     let Name = "LogicalImm64";
665     let PredicateMethod = "isLogicalImm<int64_t>";
666     let RenderMethod = "addLogicalImmOperands<int64_t>";
667   }
668   def LogicalImm32NotOperand : AsmOperandClass {
669     let Name = "LogicalImm32Not";
670     let PredicateMethod = "isLogicalImm<int32_t>";
671     let RenderMethod = "addLogicalImmNotOperands<int32_t>";
672   }
673   def LogicalImm64NotOperand : AsmOperandClass {
674     let Name = "LogicalImm64Not";
675     let PredicateMethod = "isLogicalImm<int64_t>";
676     let RenderMethod = "addLogicalImmNotOperands<int64_t>";
677   }
678 }
679 def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{
680   return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32);
681 }], logical_imm32_XFORM> {
682   let PrintMethod = "printLogicalImm<int32_t>";
683   let ParserMatchClass = LogicalImm32Operand;
684 }
685 def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{
686   return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64);
687 }], logical_imm64_XFORM> {
688   let PrintMethod = "printLogicalImm<int64_t>";
689   let ParserMatchClass = LogicalImm64Operand;
690 }
691 def logical_imm32_not : Operand<i32> {
692   let ParserMatchClass = LogicalImm32NotOperand;
693 }
694 def logical_imm64_not : Operand<i64> {
695   let ParserMatchClass = LogicalImm64NotOperand;
696 }
697
698 // imm0_65535 predicate - True if the immediate is in the range [0,65535].
699 def Imm0_65535Operand : AsmImmRange<0, 65535>;
700 def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
701   return ((uint32_t)Imm) < 65536;
702 }]> {
703   let ParserMatchClass = Imm0_65535Operand;
704   let PrintMethod = "printImmHex";
705 }
706
707 // imm0_255 predicate - True if the immediate is in the range [0,255].
708 def Imm0_255Operand : AsmImmRange<0,255>;
709
710 def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
711   return ((uint32_t)Imm) < 256;
712 }]> {
713   let ParserMatchClass = Imm0_255Operand;
714   let PrintMethod = "printImm";
715 }
716
717 // imm0_127 predicate - True if the immediate is in the range [0,127]
718 def Imm0_127Operand : AsmImmRange<0, 127>;
719 def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
720   return ((uint32_t)Imm) < 128;
721 }]> {
722   let ParserMatchClass = Imm0_127Operand;
723   let PrintMethod = "printImm";
724 }
725
726 // NOTE: These imm0_N operands have to be of type i64 because i64 is the size
727 // for all shift-amounts.
728
729 // imm0_63 predicate - True if the immediate is in the range [0,63]
730 def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
731   return ((uint64_t)Imm) < 64;
732 }]> {
733   let ParserMatchClass = Imm0_63Operand;
734 }
735
736 // imm0_31 predicate - True if the immediate is in the range [0,31]
737 def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
738   return ((uint64_t)Imm) < 32;
739 }]> {
740   let ParserMatchClass = Imm0_31Operand;
741 }
742
743 // True if the 32-bit immediate is in the range [0,31]
744 def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
745   return ((uint64_t)Imm) < 32;
746 }]> {
747   let ParserMatchClass = Imm0_31Operand;
748 }
749
750 // imm0_1 predicate - True if the immediate is in the range [0,1]
751 def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
752   return ((uint64_t)Imm) < 2;
753 }]> {
754   let ParserMatchClass = Imm0_1Operand;
755 }
756
757 // imm0_15 predicate - True if the immediate is in the range [0,15]
758 def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
759   return ((uint64_t)Imm) < 16;
760 }]> {
761   let ParserMatchClass = Imm0_15Operand;
762 }
763
764 // imm0_7 predicate - True if the immediate is in the range [0,7]
765 def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
766   return ((uint64_t)Imm) < 8;
767 }]> {
768   let ParserMatchClass = Imm0_7Operand;
769 }
770
771 // imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
772 def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
773   return ((uint32_t)Imm) < 16;
774 }]> {
775   let ParserMatchClass = Imm0_15Operand;
776 }
777
778 // An arithmetic shifter operand:
779 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
780 //  {5-0} - imm6
781 class arith_shift<ValueType Ty, int width> : Operand<Ty> {
782   let PrintMethod = "printShifter";
783   let ParserMatchClass = !cast<AsmOperandClass>(
784                          "ArithmeticShifterOperand" # width);
785 }
786
787 def arith_shift32 : arith_shift<i32, 32>;
788 def arith_shift64 : arith_shift<i64, 64>;
789
790 class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
791     : Operand<Ty>,
792       ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
793   let PrintMethod = "printShiftedRegister";
794   let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
795 }
796
797 def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
798 def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
799
800 // An arithmetic shifter operand:
801 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
802 //  {5-0} - imm6
803 class logical_shift<int width> : Operand<i32> {
804   let PrintMethod = "printShifter";
805   let ParserMatchClass = !cast<AsmOperandClass>(
806                          "LogicalShifterOperand" # width);
807 }
808
809 def logical_shift32 : logical_shift<32>;
810 def logical_shift64 : logical_shift<64>;
811
812 class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
813     : Operand<Ty>,
814       ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
815   let PrintMethod = "printShiftedRegister";
816   let MIOperandInfo = (ops regclass, shiftop);
817 }
818
819 def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
820 def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
821
822 // A logical vector shifter operand:
823 //  {7-6} - shift type: 00 = lsl
824 //  {5-0} - imm6: #0, #8, #16, or #24
825 def logical_vec_shift : Operand<i32> {
826   let PrintMethod = "printShifter";
827   let EncoderMethod = "getVecShifterOpValue";
828   let ParserMatchClass = LogicalVecShifterOperand;
829 }
830
831 // A logical vector half-word shifter operand:
832 //  {7-6} - shift type: 00 = lsl
833 //  {5-0} - imm6: #0 or #8
834 def logical_vec_hw_shift : Operand<i32> {
835   let PrintMethod = "printShifter";
836   let EncoderMethod = "getVecShifterOpValue";
837   let ParserMatchClass = LogicalVecHalfWordShifterOperand;
838 }
839
840 // A vector move shifter operand:
841 //  {0} - imm1: #8 or #16
842 def move_vec_shift : Operand<i32> {
843   let PrintMethod = "printShifter";
844   let EncoderMethod = "getMoveVecShifterOpValue";
845   let ParserMatchClass = MoveVecShifterOperand;
846 }
847
848 let DiagnosticType = "AddSubSecondSource" in {
849   def AddSubImmOperand : AsmOperandClass {
850     let Name = "AddSubImm";
851     let ParserMethod = "tryParseImmWithOptionalShift";
852     let RenderMethod = "addImmWithOptionalShiftOperands<12>";
853   }
854   def AddSubImmNegOperand : AsmOperandClass {
855     let Name = "AddSubImmNeg";
856     let ParserMethod = "tryParseImmWithOptionalShift";
857     let RenderMethod = "addImmNegWithOptionalShiftOperands<12>";
858   }
859 }
860 // An ADD/SUB immediate shifter operand:
861 //  second operand:
862 //  {7-6} - shift type: 00 = lsl
863 //  {5-0} - imm6: #0 or #12
864 class addsub_shifted_imm<ValueType Ty>
865     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
866   let PrintMethod = "printAddSubImm";
867   let EncoderMethod = "getAddSubImmOpValue";
868   let ParserMatchClass = AddSubImmOperand;
869   let MIOperandInfo = (ops i32imm, i32imm);
870 }
871
872 class addsub_shifted_imm_neg<ValueType Ty>
873     : Operand<Ty> {
874   let EncoderMethod = "getAddSubImmOpValue";
875   let ParserMatchClass = AddSubImmNegOperand;
876   let MIOperandInfo = (ops i32imm, i32imm);
877 }
878
879 def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
880 def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
881 def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
882 def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
883
884 def gi_addsub_shifted_imm32 :
885     GIComplexOperandMatcher<s32, "selectArithImmed">,
886     GIComplexPatternEquiv<addsub_shifted_imm32>;
887
888 def gi_addsub_shifted_imm64 :
889     GIComplexOperandMatcher<s64, "selectArithImmed">,
890     GIComplexPatternEquiv<addsub_shifted_imm64>;
891
892 class neg_addsub_shifted_imm<ValueType Ty>
893     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
894   let PrintMethod = "printAddSubImm";
895   let EncoderMethod = "getAddSubImmOpValue";
896   let ParserMatchClass = AddSubImmOperand;
897   let MIOperandInfo = (ops i32imm, i32imm);
898 }
899
900 def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
901 def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
902
903 // An extend operand:
904 //  {5-3} - extend type
905 //  {2-0} - imm3
906 def arith_extend : Operand<i32> {
907   let PrintMethod = "printArithExtend";
908   let ParserMatchClass = ExtendOperand;
909 }
910 def arith_extend64 : Operand<i32> {
911   let PrintMethod = "printArithExtend";
912   let ParserMatchClass = ExtendOperand64;
913 }
914
915 // 'extend' that's a lsl of a 64-bit register.
916 def arith_extendlsl64 : Operand<i32> {
917   let PrintMethod = "printArithExtend";
918   let ParserMatchClass = ExtendOperandLSL64;
919 }
920
921 class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
922                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
923   let PrintMethod = "printExtendedRegister";
924   let MIOperandInfo = (ops GPR32, arith_extend);
925 }
926
927 class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
928                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
929   let PrintMethod = "printExtendedRegister";
930   let MIOperandInfo = (ops GPR32, arith_extend64);
931 }
932
933 // Floating-point immediate.
934 def fpimm16 : Operand<f16>,
935               FPImmLeaf<f16, [{
936       return AArch64_AM::getFP16Imm(Imm) != -1;
937     }], SDNodeXForm<fpimm, [{
938       APFloat InVal = N->getValueAPF();
939       uint32_t enc = AArch64_AM::getFP16Imm(InVal);
940       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
941     }]>> {
942   let ParserMatchClass = FPImmOperand;
943   let PrintMethod = "printFPImmOperand";
944 }
945 def fpimm32 : Operand<f32>,
946               FPImmLeaf<f32, [{
947       return AArch64_AM::getFP32Imm(Imm) != -1;
948     }], SDNodeXForm<fpimm, [{
949       APFloat InVal = N->getValueAPF();
950       uint32_t enc = AArch64_AM::getFP32Imm(InVal);
951       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
952     }]>> {
953   let ParserMatchClass = FPImmOperand;
954   let PrintMethod = "printFPImmOperand";
955 }
956 def fpimm64 : Operand<f64>,
957               FPImmLeaf<f64, [{
958       return AArch64_AM::getFP64Imm(Imm) != -1;
959     }], SDNodeXForm<fpimm, [{
960       APFloat InVal = N->getValueAPF();
961       uint32_t enc = AArch64_AM::getFP64Imm(InVal);
962       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
963     }]>> {
964   let ParserMatchClass = FPImmOperand;
965   let PrintMethod = "printFPImmOperand";
966 }
967
968 def fpimm8 : Operand<i32> {
969   let ParserMatchClass = FPImmOperand;
970   let PrintMethod = "printFPImmOperand";
971 }
972
973 def fpimm0 : FPImmLeaf<fAny, [{
974   return Imm.isExactlyValue(+0.0);
975 }]>;
976
977 // Vector lane operands
978 class AsmVectorIndex<int Min, int Max, string NamePrefix=""> : AsmOperandClass {
979   let Name = NamePrefix # "IndexRange" # Min # "_" # Max;
980   let DiagnosticType = "Invalid" # Name;
981   let PredicateMethod = "isVectorIndex<" # Min # ", " # Max #  ">";
982   let RenderMethod = "addVectorIndexOperands";
983 }
984
985 class AsmVectorIndexOpnd<AsmOperandClass mc, code pred>
986     : Operand<i64>, ImmLeaf<i64, pred> {
987   let ParserMatchClass = mc;
988   let PrintMethod = "printVectorIndex";
989 }
990
991 def VectorIndex1Operand : AsmVectorIndex<1, 1>;
992 def VectorIndexBOperand : AsmVectorIndex<0, 15>;
993 def VectorIndexHOperand : AsmVectorIndex<0, 7>;
994 def VectorIndexSOperand : AsmVectorIndex<0, 3>;
995 def VectorIndexDOperand : AsmVectorIndex<0, 1>;
996
997 def VectorIndex1 : AsmVectorIndexOpnd<VectorIndex1Operand, [{ return ((uint64_t)Imm) == 1; }]>;
998 def VectorIndexB : AsmVectorIndexOpnd<VectorIndexBOperand, [{ return ((uint64_t)Imm) < 16; }]>;
999 def VectorIndexH : AsmVectorIndexOpnd<VectorIndexHOperand, [{ return ((uint64_t)Imm) < 8; }]>;
1000 def VectorIndexS : AsmVectorIndexOpnd<VectorIndexSOperand, [{ return ((uint64_t)Imm) < 4; }]>;
1001 def VectorIndexD : AsmVectorIndexOpnd<VectorIndexDOperand, [{ return ((uint64_t)Imm) < 2; }]>;
1002
1003 def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">;
1004 def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">;
1005 def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">;
1006 def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">;
1007 def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">;
1008
1009 def sve_elm_idx_extdup_b
1010   : AsmVectorIndexOpnd<SVEVectorIndexExtDupBOperand, [{ return ((uint64_t)Imm) < 64; }]>;
1011 def sve_elm_idx_extdup_h
1012   : AsmVectorIndexOpnd<SVEVectorIndexExtDupHOperand, [{ return ((uint64_t)Imm) < 32; }]>;
1013 def sve_elm_idx_extdup_s
1014   : AsmVectorIndexOpnd<SVEVectorIndexExtDupSOperand, [{ return ((uint64_t)Imm) < 16; }]>;
1015 def sve_elm_idx_extdup_d
1016   : AsmVectorIndexOpnd<SVEVectorIndexExtDupDOperand, [{ return ((uint64_t)Imm) < 8; }]>;
1017 def sve_elm_idx_extdup_q
1018   : AsmVectorIndexOpnd<SVEVectorIndexExtDupQOperand, [{ return ((uint64_t)Imm) < 4; }]>;
1019
1020 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
1021 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
1022 // are encoded as the eight bit value 'abcdefgh'.
1023 def simdimmtype10 : Operand<i32>,
1024                     FPImmLeaf<f64, [{
1025       return AArch64_AM::isAdvSIMDModImmType10(
1026                  Imm.bitcastToAPInt().getZExtValue());
1027     }], SDNodeXForm<fpimm, [{
1028       APFloat InVal = N->getValueAPF();
1029       uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
1030                                                            .bitcastToAPInt()
1031                                                            .getZExtValue());
1032       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1033     }]>> {
1034   let ParserMatchClass = SIMDImmType10Operand;
1035   let PrintMethod = "printSIMDType10Operand";
1036 }
1037
1038
1039 //---
1040 // System management
1041 //---
1042
1043 // Base encoding for system instruction operands.
1044 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
1045 class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
1046                   list<dag> pattern = []>
1047     : I<oops, iops, asm, operands, "", pattern> {
1048   let Inst{31-22} = 0b1101010100;
1049   let Inst{21}    = L;
1050 }
1051
1052 // System instructions which do not have an Rt register.
1053 class SimpleSystemI<bit L, dag iops, string asm, string operands,
1054                     list<dag> pattern = []>
1055     : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
1056   let Inst{4-0} = 0b11111;
1057 }
1058
1059 // System instructions which have an Rt register.
1060 class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
1061     : BaseSystemI<L, oops, iops, asm, operands>,
1062       Sched<[WriteSys]> {
1063   bits<5> Rt;
1064   let Inst{4-0} = Rt;
1065 }
1066
1067 // Hint instructions that take both a CRm and a 3-bit immediate.
1068 // NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
1069 // model patterns with sufficiently fine granularity
1070 let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
1071   class HintI<string mnemonic>
1072       : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
1073                       [(int_aarch64_hint imm0_127:$imm)]>,
1074         Sched<[WriteHint]> {
1075     bits <7> imm;
1076     let Inst{20-12} = 0b000110010;
1077     let Inst{11-5} = imm;
1078   }
1079
1080 // System instructions taking a single literal operand which encodes into
1081 // CRm. op2 differentiates the opcodes.
1082 def BarrierAsmOperand : AsmOperandClass {
1083   let Name = "Barrier";
1084   let ParserMethod = "tryParseBarrierOperand";
1085 }
1086 def barrier_op : Operand<i32> {
1087   let PrintMethod = "printBarrierOption";
1088   let ParserMatchClass = BarrierAsmOperand;
1089 }
1090 class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
1091                  list<dag> pattern = []>
1092     : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
1093       Sched<[WriteBarrier]> {
1094   bits<4> CRm;
1095   let Inst{20-12} = 0b000110011;
1096   let Inst{11-8} = CRm;
1097   let Inst{7-5} = opc;
1098 }
1099
1100 class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
1101     : SimpleSystemI<0, (ins), asm, "", pattern>,
1102       Sched<[]> {
1103   bits<4> CRm;
1104   let CRm = 0b0011;
1105   let Inst{31-12} = 0b11010101000000110010;
1106   let Inst{11-8} = CRm;
1107   let Inst{7-5} = op2;
1108   let Inst{4-0} = 0b11111;
1109 }
1110
1111 // MRS/MSR system instructions. These have different operand classes because
1112 // a different subset of registers can be accessed through each instruction.
1113 def MRSSystemRegisterOperand : AsmOperandClass {
1114   let Name = "MRSSystemRegister";
1115   let ParserMethod = "tryParseSysReg";
1116   let DiagnosticType = "MRS";
1117 }
1118 // concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
1119 def mrs_sysreg_op : Operand<i32> {
1120   let ParserMatchClass = MRSSystemRegisterOperand;
1121   let DecoderMethod = "DecodeMRSSystemRegister";
1122   let PrintMethod = "printMRSSystemRegister";
1123 }
1124
1125 def MSRSystemRegisterOperand : AsmOperandClass {
1126   let Name = "MSRSystemRegister";
1127   let ParserMethod = "tryParseSysReg";
1128   let DiagnosticType = "MSR";
1129 }
1130 def msr_sysreg_op : Operand<i32> {
1131   let ParserMatchClass = MSRSystemRegisterOperand;
1132   let DecoderMethod = "DecodeMSRSystemRegister";
1133   let PrintMethod = "printMSRSystemRegister";
1134 }
1135
1136 def PSBHintOperand : AsmOperandClass {
1137   let Name = "PSBHint";
1138   let ParserMethod = "tryParsePSBHint";
1139 }
1140 def psbhint_op : Operand<i32> {
1141   let ParserMatchClass = PSBHintOperand;
1142   let PrintMethod = "printPSBHintOp";
1143   let MCOperandPredicate = [{
1144     // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
1145     // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
1146     if (!MCOp.isImm())
1147       return false;
1148     return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
1149   }];
1150 }
1151
1152 class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
1153                        "mrs", "\t$Rt, $systemreg"> {
1154   bits<16> systemreg;
1155   let Inst{20-5} = systemreg;
1156 }
1157
1158 // FIXME: Some of these def NZCV, others don't. Best way to model that?
1159 // Explicitly modeling each of the system register as a register class
1160 // would do it, but feels like overkill at this point.
1161 class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
1162                        "msr", "\t$systemreg, $Rt"> {
1163   bits<16> systemreg;
1164   let Inst{20-5} = systemreg;
1165 }
1166
1167 def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
1168   let Name = "SystemPStateFieldWithImm0_15";
1169   let ParserMethod = "tryParseSysReg";
1170 }
1171 def pstatefield4_op : Operand<i32> {
1172   let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
1173   let PrintMethod = "printSystemPStateField";
1174 }
1175
1176 let Defs = [NZCV] in
1177 class MSRpstateImm0_15
1178   : SimpleSystemI<0, (ins pstatefield4_op:$pstatefield, imm0_15:$imm),
1179                   "msr", "\t$pstatefield, $imm">,
1180     Sched<[WriteSys]> {
1181   bits<6> pstatefield;
1182   bits<4> imm;
1183   let Inst{20-19} = 0b00;
1184   let Inst{18-16} = pstatefield{5-3};
1185   let Inst{15-12} = 0b0100;
1186   let Inst{11-8} = imm;
1187   let Inst{7-5} = pstatefield{2-0};
1188
1189   let DecoderMethod = "DecodeSystemPStateInstruction";
1190   // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1191   // Fail the decoder should attempt to decode the instruction as MSRI.
1192   let hasCompleteDecoder = 0;
1193 }
1194
1195 def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
1196   let Name = "SystemPStateFieldWithImm0_1";
1197   let ParserMethod = "tryParseSysReg";
1198 }
1199 def pstatefield1_op : Operand<i32> {
1200   let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
1201   let PrintMethod = "printSystemPStateField";
1202 }
1203
1204 let Defs = [NZCV] in
1205 class MSRpstateImm0_1
1206   : SimpleSystemI<0, (ins pstatefield1_op:$pstatefield, imm0_1:$imm),
1207                   "msr", "\t$pstatefield, $imm">,
1208     Sched<[WriteSys]> {
1209   bits<6> pstatefield;
1210   bit imm;
1211   let Inst{20-19} = 0b00;
1212   let Inst{18-16} = pstatefield{5-3};
1213   let Inst{15-9} = 0b0100000;
1214   let Inst{8} = imm;
1215   let Inst{7-5} = pstatefield{2-0};
1216
1217   let DecoderMethod = "DecodeSystemPStateInstruction";
1218   // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1219   // Fail the decoder should attempt to decode the instruction as MSRI.
1220   let hasCompleteDecoder = 0;
1221 }
1222
1223 // SYS and SYSL generic system instructions.
1224 def SysCRAsmOperand : AsmOperandClass {
1225   let Name = "SysCR";
1226   let ParserMethod = "tryParseSysCROperand";
1227 }
1228
1229 def sys_cr_op : Operand<i32> {
1230   let PrintMethod = "printSysCROperand";
1231   let ParserMatchClass = SysCRAsmOperand;
1232 }
1233
1234 class SystemXtI<bit L, string asm>
1235   : RtSystemI<L, (outs),
1236        (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1237        asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1238   bits<3> op1;
1239   bits<4> Cn;
1240   bits<4> Cm;
1241   bits<3> op2;
1242   let Inst{20-19} = 0b01;
1243   let Inst{18-16} = op1;
1244   let Inst{15-12} = Cn;
1245   let Inst{11-8}  = Cm;
1246   let Inst{7-5}   = op2;
1247 }
1248
1249 class SystemLXtI<bit L, string asm>
1250   : RtSystemI<L, (outs),
1251        (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1252        asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1253   bits<3> op1;
1254   bits<4> Cn;
1255   bits<4> Cm;
1256   bits<3> op2;
1257   let Inst{20-19} = 0b01;
1258   let Inst{18-16} = op1;
1259   let Inst{15-12} = Cn;
1260   let Inst{11-8}  = Cm;
1261   let Inst{7-5}   = op2;
1262 }
1263
1264
1265 // Branch (register) instructions:
1266 //
1267 //  case opc of
1268 //    0001 blr
1269 //    0000 br
1270 //    0101 dret
1271 //    0100 eret
1272 //    0010 ret
1273 //    otherwise UNDEFINED
1274 class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1275                     string operands, list<dag> pattern>
1276     : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1277   let Inst{31-25} = 0b1101011;
1278   let Inst{24-21} = opc;
1279   let Inst{20-16} = 0b11111;
1280   let Inst{15-10} = 0b000000;
1281   let Inst{4-0}   = 0b00000;
1282 }
1283
1284 class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1285     : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1286   bits<5> Rn;
1287   let Inst{9-5} = Rn;
1288 }
1289
1290 let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1291 class SpecialReturn<bits<4> opc, string asm>
1292     : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1293   let Inst{9-5} = 0b11111;
1294 }
1295
1296 let mayLoad = 1 in
1297 class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
1298   : I<(outs RC:$Rt), (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]", "", []>,
1299   Sched<[]> {
1300   bits<5> Rn;
1301   bits<5> Rt;
1302   let Inst{31-30} = sz;
1303   let Inst{29-10} = 0b11100010111111110000;
1304   let Inst{9-5} = Rn;
1305   let Inst{4-0} = Rt;
1306 }
1307
1308 class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
1309                list<dag> pattern>
1310   : I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
1311   let Inst{31-25} = 0b1101011;
1312   let Inst{20-11} = 0b1111100001;
1313   let Inst{10} = M;
1314   let Inst{4-0} = 0b11111;
1315 }
1316
1317 class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
1318   : AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
1319   bits<5> Rn;
1320   bits<5> Rm;
1321   let Inst{24-22} = 0b100;
1322   let Inst{21} = op;
1323   let Inst{9-5} = Rn;
1324   let Inst{4-0} = Rm;
1325 }
1326
1327 class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
1328   : AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
1329   bits<5> Rn;
1330   let Inst{24} = 0;
1331   let Inst{23-21} = opc;
1332   let Inst{9-5} = Rn;
1333 }
1334
1335 class AuthReturn<bits<3> op, bits<1> M, string asm>
1336   : AuthBase<M, (outs), (ins), asm, "", []> {
1337   let Inst{24} = 0;
1338   let Inst{23-21} = op;
1339   let Inst{9-0} = 0b1111111111;
1340 }
1341
1342 let mayLoad = 1 in
1343 class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
1344                    string operands, string cstr, Operand opr>
1345   : I<oops, iops, asm, operands, cstr, []>, Sched<[]> {
1346   bits<10> offset;
1347   bits<5> Rn;
1348   bits<5> Rt;
1349   let Inst{31-24} = 0b11111000;
1350   let Inst{23} = M;
1351   let Inst{22} = offset{9};
1352   let Inst{21} = 1;
1353   let Inst{20-12} = offset{8-0};
1354   let Inst{11} = W;
1355   let Inst{10} = 1;
1356   let Inst{9-5} = Rn;
1357   let Inst{4-0} = Rt;
1358 }
1359
1360 multiclass AuthLoad<bit M, string asm, Operand opr> {
1361   def indexed   : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
1362                                (ins GPR64sp:$Rn, opr:$offset),
1363                                asm, "\t$Rt, [$Rn, $offset]", "", opr>;
1364   def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
1365                                (ins GPR64sp:$Rn, opr:$offset),
1366                                asm, "\t$Rt, [$Rn, $offset]!",
1367                                "$Rn = $wback,@earlyclobber $wback", opr>;
1368
1369   def : InstAlias<asm # "\t$Rt, [$Rn]",
1370                   (!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
1371 }
1372
1373 //---
1374 // Conditional branch instruction.
1375 //---
1376
1377 // Condition code.
1378 // 4-bit immediate. Pretty-printed as <cc>
1379 def ccode : Operand<i32> {
1380   let PrintMethod = "printCondCode";
1381   let ParserMatchClass = CondCode;
1382 }
1383 def inv_ccode : Operand<i32> {
1384   // AL and NV are invalid in the aliases which use inv_ccode
1385   let PrintMethod = "printInverseCondCode";
1386   let ParserMatchClass = CondCode;
1387   let MCOperandPredicate = [{
1388     return MCOp.isImm() &&
1389            MCOp.getImm() != AArch64CC::AL &&
1390            MCOp.getImm() != AArch64CC::NV;
1391   }];
1392 }
1393
1394 // Conditional branch target. 19-bit immediate. The low two bits of the target
1395 // offset are implied zero and so are not part of the immediate.
1396 def am_brcond : Operand<OtherVT> {
1397   let EncoderMethod = "getCondBranchTargetOpValue";
1398   let DecoderMethod = "DecodePCRelLabel19";
1399   let PrintMethod = "printAlignedLabel";
1400   let ParserMatchClass = PCRelLabel19Operand;
1401   let OperandType = "OPERAND_PCREL";
1402 }
1403
1404 class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target),
1405                      "b", ".$cond\t$target", "",
1406                      [(AArch64brcond bb:$target, imm:$cond, NZCV)]>,
1407                    Sched<[WriteBr]> {
1408   let isBranch = 1;
1409   let isTerminator = 1;
1410   let Uses = [NZCV];
1411
1412   bits<4> cond;
1413   bits<19> target;
1414   let Inst{31-24} = 0b01010100;
1415   let Inst{23-5} = target;
1416   let Inst{4} = 0;
1417   let Inst{3-0} = cond;
1418 }
1419
1420 //---
1421 // Compare-and-branch instructions.
1422 //---
1423 class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1424     : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1425          asm, "\t$Rt, $target", "",
1426          [(node regtype:$Rt, bb:$target)]>,
1427       Sched<[WriteBr]> {
1428   let isBranch = 1;
1429   let isTerminator = 1;
1430
1431   bits<5> Rt;
1432   bits<19> target;
1433   let Inst{30-25} = 0b011010;
1434   let Inst{24}    = op;
1435   let Inst{23-5}  = target;
1436   let Inst{4-0}   = Rt;
1437 }
1438
1439 multiclass CmpBranch<bit op, string asm, SDNode node> {
1440   def W : BaseCmpBranch<GPR32, op, asm, node> {
1441     let Inst{31} = 0;
1442   }
1443   def X : BaseCmpBranch<GPR64, op, asm, node> {
1444     let Inst{31} = 1;
1445   }
1446 }
1447
1448 //---
1449 // Test-bit-and-branch instructions.
1450 //---
1451 // Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1452 // the target offset are implied zero and so are not part of the immediate.
1453 def am_tbrcond : Operand<OtherVT> {
1454   let EncoderMethod = "getTestBranchTargetOpValue";
1455   let PrintMethod = "printAlignedLabel";
1456   let ParserMatchClass = BranchTarget14Operand;
1457   let OperandType = "OPERAND_PCREL";
1458 }
1459
1460 // AsmOperand classes to emit (or not) special diagnostics
1461 def TBZImm0_31Operand : AsmOperandClass {
1462   let Name = "TBZImm0_31";
1463   let PredicateMethod = "isImmInRange<0,31>";
1464   let RenderMethod = "addImmOperands";
1465 }
1466 def TBZImm32_63Operand : AsmOperandClass {
1467   let Name = "Imm32_63";
1468   let PredicateMethod = "isImmInRange<32,63>";
1469   let DiagnosticType = "InvalidImm0_63";
1470   let RenderMethod = "addImmOperands";
1471 }
1472
1473 class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1474   return (((uint32_t)Imm) < 32);
1475 }]> {
1476   let ParserMatchClass = matcher;
1477 }
1478
1479 def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1480 def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1481
1482 def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1483   return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1484 }]> {
1485   let ParserMatchClass = TBZImm32_63Operand;
1486 }
1487
1488 class BaseTestBranch<RegisterClass regtype, Operand immtype,
1489                      bit op, string asm, SDNode node>
1490     : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1491        asm, "\t$Rt, $bit_off, $target", "",
1492        [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1493       Sched<[WriteBr]> {
1494   let isBranch = 1;
1495   let isTerminator = 1;
1496
1497   bits<5> Rt;
1498   bits<6> bit_off;
1499   bits<14> target;
1500
1501   let Inst{30-25} = 0b011011;
1502   let Inst{24}    = op;
1503   let Inst{23-19} = bit_off{4-0};
1504   let Inst{18-5}  = target;
1505   let Inst{4-0}   = Rt;
1506
1507   let DecoderMethod = "DecodeTestAndBranch";
1508 }
1509
1510 multiclass TestBranch<bit op, string asm, SDNode node> {
1511   def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1512     let Inst{31} = 0;
1513   }
1514
1515   def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1516     let Inst{31} = 1;
1517   }
1518
1519   // Alias X-reg with 0-31 imm to W-Reg.
1520   def : InstAlias<asm # "\t$Rd, $imm, $target",
1521                   (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1522                   tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1523   def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1524             (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1525             tbz_imm0_31_diag:$imm, bb:$target)>;
1526 }
1527
1528 //---
1529 // Unconditional branch (immediate) instructions.
1530 //---
1531 def am_b_target : Operand<OtherVT> {
1532   let EncoderMethod = "getBranchTargetOpValue";
1533   let PrintMethod = "printAlignedLabel";
1534   let ParserMatchClass = BranchTarget26Operand;
1535   let OperandType = "OPERAND_PCREL";
1536 }
1537 def am_bl_target : Operand<i64> {
1538   let EncoderMethod = "getBranchTargetOpValue";
1539   let PrintMethod = "printAlignedLabel";
1540   let ParserMatchClass = BranchTarget26Operand;
1541   let OperandType = "OPERAND_PCREL";
1542 }
1543
1544 class BImm<bit op, dag iops, string asm, list<dag> pattern>
1545     : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1546   bits<26> addr;
1547   let Inst{31}    = op;
1548   let Inst{30-26} = 0b00101;
1549   let Inst{25-0}  = addr;
1550
1551   let DecoderMethod = "DecodeUnconditionalBranch";
1552 }
1553
1554 class BranchImm<bit op, string asm, list<dag> pattern>
1555     : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1556 class CallImm<bit op, string asm, list<dag> pattern>
1557     : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1558
1559 //---
1560 // Basic one-operand data processing instructions.
1561 //---
1562
1563 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1564 class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1565                          SDPatternOperator node>
1566   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1567       [(set regtype:$Rd, (node regtype:$Rn))]>,
1568     Sched<[WriteI, ReadI]> {
1569   bits<5> Rd;
1570   bits<5> Rn;
1571
1572   let Inst{30-13} = 0b101101011000000000;
1573   let Inst{12-10} = opc;
1574   let Inst{9-5}   = Rn;
1575   let Inst{4-0}   = Rd;
1576 }
1577
1578 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1579 multiclass OneOperandData<bits<3> opc, string asm,
1580                           SDPatternOperator node = null_frag> {
1581   def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1582     let Inst{31} = 0;
1583   }
1584
1585   def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1586     let Inst{31} = 1;
1587   }
1588 }
1589
1590 class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1591     : BaseOneOperandData<opc, GPR32, asm, node> {
1592   let Inst{31} = 0;
1593 }
1594
1595 class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1596     : BaseOneOperandData<opc, GPR64, asm, node> {
1597   let Inst{31} = 1;
1598 }
1599
1600 class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm>
1601   : I<(outs GPR64:$Rd), (ins GPR64sp:$Rn), asm, "\t$Rd, $Rn", "",
1602       []>,
1603     Sched<[WriteI, ReadI]> {
1604   bits<5> Rd;
1605   bits<5> Rn;
1606   let Inst{31-15} = 0b11011010110000010;
1607   let Inst{14-12} = opcode_prefix;
1608   let Inst{11-10} = opcode;
1609   let Inst{9-5} = Rn;
1610   let Inst{4-0} = Rd;
1611 }
1612
1613 class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm>
1614   : I<(outs GPR64:$Rd), (ins), asm, "\t$Rd", "", []>, Sched<[]> {
1615   bits<5> Rd;
1616   let Inst{31-15} = 0b11011010110000010;
1617   let Inst{14-12} = opcode_prefix;
1618   let Inst{11-10} = opcode;
1619   let Inst{9-5} = 0b11111;
1620   let Inst{4-0} = Rd;
1621 }
1622
1623 class SignAuthTwoOperand<bits<4> opc, string asm,
1624                          SDPatternOperator OpNode>
1625   : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
1626       asm, "\t$Rd, $Rn, $Rm", "",
1627       [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
1628     Sched<[WriteI, ReadI, ReadI]> {
1629   bits<5> Rd;
1630   bits<5> Rn;
1631   bits<5> Rm;
1632   let Inst{31-21} = 0b10011010110;
1633   let Inst{20-16} = Rm;
1634   let Inst{15-14} = 0b00;
1635   let Inst{13-10} = opc;
1636   let Inst{9-5}   = Rn;
1637   let Inst{4-0}   = Rd;
1638 }
1639
1640 // Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions
1641 class BaseFlagManipulation<bit sf, bit sz, dag iops, string asm, string ops>
1642     : I<(outs), iops, asm, ops, "", []>,
1643       Sched<[WriteI, ReadI, ReadI]> {
1644   let Uses = [NZCV];
1645   bits<5> Rn;
1646   let Inst{31}    = sf;
1647   let Inst{30-15} = 0b0111010000000000;
1648   let Inst{14}    = sz;
1649   let Inst{13-10} = 0b0010;
1650   let Inst{9-5}   = Rn;
1651   let Inst{4-0}   = 0b01101;
1652 }
1653
1654 class FlagRotate<dag iops, string asm, string ops>
1655     : BaseFlagManipulation<0b1, 0b0, iops, asm, ops> {
1656   bits<6> imm;
1657   bits<4> mask;
1658   let Inst{20-15} = imm;
1659   let Inst{13-10} = 0b0001;
1660   let Inst{4}     = 0b0;
1661   let Inst{3-0}   = mask;
1662 }
1663
1664 //---
1665 // Basic two-operand data processing instructions.
1666 //---
1667 class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1668                           list<dag> pattern>
1669     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1670         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1671       Sched<[WriteI, ReadI, ReadI]> {
1672   let Uses = [NZCV];
1673   bits<5> Rd;
1674   bits<5> Rn;
1675   bits<5> Rm;
1676   let Inst{30}    = isSub;
1677   let Inst{28-21} = 0b11010000;
1678   let Inst{20-16} = Rm;
1679   let Inst{15-10} = 0;
1680   let Inst{9-5}   = Rn;
1681   let Inst{4-0}   = Rd;
1682 }
1683
1684 class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1685                       SDNode OpNode>
1686     : BaseBaseAddSubCarry<isSub, regtype, asm,
1687         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
1688
1689 class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1690                               SDNode OpNode>
1691     : BaseBaseAddSubCarry<isSub, regtype, asm,
1692         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
1693          (implicit NZCV)]> {
1694   let Defs = [NZCV];
1695 }
1696
1697 multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1698                        SDNode OpNode, SDNode OpNode_setflags> {
1699   def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1700     let Inst{31} = 0;
1701     let Inst{29} = 0;
1702   }
1703   def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1704     let Inst{31} = 1;
1705     let Inst{29} = 0;
1706   }
1707
1708   // Sets flags.
1709   def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1710                                     OpNode_setflags> {
1711     let Inst{31} = 0;
1712     let Inst{29} = 1;
1713   }
1714   def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1715                                     OpNode_setflags> {
1716     let Inst{31} = 1;
1717     let Inst{29} = 1;
1718   }
1719 }
1720
1721 class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1722                      SDPatternOperator OpNode>
1723   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1724       asm, "\t$Rd, $Rn, $Rm", "",
1725       [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]> {
1726   bits<5> Rd;
1727   bits<5> Rn;
1728   bits<5> Rm;
1729   let Inst{30-21} = 0b0011010110;
1730   let Inst{20-16} = Rm;
1731   let Inst{15-14} = 0b00;
1732   let Inst{13-10} = opc;
1733   let Inst{9-5}   = Rn;
1734   let Inst{4-0}   = Rd;
1735 }
1736
1737 class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1738               SDPatternOperator OpNode>
1739     : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1740   let Inst{10}    = isSigned;
1741 }
1742
1743 multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1744   def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1745            Sched<[WriteID32, ReadID, ReadID]> {
1746     let Inst{31} = 0;
1747   }
1748   def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1749            Sched<[WriteID64, ReadID, ReadID]> {
1750     let Inst{31} = 1;
1751   }
1752 }
1753
1754 class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1755                 SDPatternOperator OpNode = null_frag>
1756   : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1757     Sched<[WriteIS, ReadI]> {
1758   let Inst{11-10} = shift_type;
1759 }
1760
1761 multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
1762   def Wr : BaseShift<shift_type, GPR32, asm> {
1763     let Inst{31} = 0;
1764   }
1765
1766   def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1767     let Inst{31} = 1;
1768   }
1769
1770   def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1771             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1772                                              (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1773
1774   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1775             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1776
1777   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1778             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1779
1780   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1781             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1782 }
1783
1784 class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1785     : InstAlias<asm#"\t$dst, $src1, $src2",
1786                 (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
1787
1788 class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1789                        RegisterClass addtype, string asm,
1790                        list<dag> pattern>
1791   : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1792       asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1793   bits<5> Rd;
1794   bits<5> Rn;
1795   bits<5> Rm;
1796   bits<5> Ra;
1797   let Inst{30-24} = 0b0011011;
1798   let Inst{23-21} = opc;
1799   let Inst{20-16} = Rm;
1800   let Inst{15}    = isSub;
1801   let Inst{14-10} = Ra;
1802   let Inst{9-5}   = Rn;
1803   let Inst{4-0}   = Rd;
1804 }
1805
1806 multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1807   // MADD/MSUB generation is decided by MachineCombiner.cpp
1808   def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1809       [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>,
1810       Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1811     let Inst{31} = 0;
1812   }
1813
1814   def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1815       [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>,
1816       Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
1817     let Inst{31} = 1;
1818   }
1819 }
1820
1821 class WideMulAccum<bit isSub, bits<3> opc, string asm,
1822                    SDNode AccNode, SDNode ExtNode>
1823   : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1824     [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1825                             (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1826     Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1827   let Inst{31} = 1;
1828 }
1829
1830 class MulHi<bits<3> opc, string asm, SDNode OpNode>
1831   : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1832       asm, "\t$Rd, $Rn, $Rm", "",
1833       [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1834     Sched<[WriteIM64, ReadIM, ReadIM]> {
1835   bits<5> Rd;
1836   bits<5> Rn;
1837   bits<5> Rm;
1838   let Inst{31-24} = 0b10011011;
1839   let Inst{23-21} = opc;
1840   let Inst{20-16} = Rm;
1841   let Inst{15}    = 0;
1842   let Inst{9-5}   = Rn;
1843   let Inst{4-0}   = Rd;
1844
1845   // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
1846   // (i.e. all bits 1) but is ignored by the processor.
1847   let PostEncoderMethod = "fixMulHigh";
1848 }
1849
1850 class MulAccumWAlias<string asm, Instruction inst>
1851     : InstAlias<asm#"\t$dst, $src1, $src2",
1852                 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1853 class MulAccumXAlias<string asm, Instruction inst>
1854     : InstAlias<asm#"\t$dst, $src1, $src2",
1855                 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1856 class WideMulAccumAlias<string asm, Instruction inst>
1857     : InstAlias<asm#"\t$dst, $src1, $src2",
1858                 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1859
1860 class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1861               SDPatternOperator OpNode, string asm>
1862   : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1863       asm, "\t$Rd, $Rn, $Rm", "",
1864       [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1865     Sched<[WriteISReg, ReadI, ReadISReg]> {
1866   bits<5> Rd;
1867   bits<5> Rn;
1868   bits<5> Rm;
1869
1870   let Inst{31} = sf;
1871   let Inst{30-21} = 0b0011010110;
1872   let Inst{20-16} = Rm;
1873   let Inst{15-13} = 0b010;
1874   let Inst{12} = C;
1875   let Inst{11-10} = sz;
1876   let Inst{9-5} = Rn;
1877   let Inst{4-0} = Rd;
1878   let Predicates = [HasCRC];
1879 }
1880
1881 //---
1882 // Address generation.
1883 //---
1884
1885 class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1886     : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1887         pattern>,
1888       Sched<[WriteI]> {
1889   bits<5>  Xd;
1890   bits<21> label;
1891   let Inst{31}    = page;
1892   let Inst{30-29} = label{1-0};
1893   let Inst{28-24} = 0b10000;
1894   let Inst{23-5}  = label{20-2};
1895   let Inst{4-0}   = Xd;
1896
1897   let DecoderMethod = "DecodeAdrInstruction";
1898 }
1899
1900 //---
1901 // Move immediate.
1902 //---
1903
1904 def movimm32_imm : Operand<i32> {
1905   let ParserMatchClass = Imm0_65535Operand;
1906   let EncoderMethod = "getMoveWideImmOpValue";
1907   let PrintMethod = "printImm";
1908 }
1909 def movimm32_shift : Operand<i32> {
1910   let PrintMethod = "printShifter";
1911   let ParserMatchClass = MovImm32ShifterOperand;
1912 }
1913 def movimm64_shift : Operand<i32> {
1914   let PrintMethod = "printShifter";
1915   let ParserMatchClass = MovImm64ShifterOperand;
1916 }
1917
1918 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1919 class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1920                         string asm>
1921   : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
1922        asm, "\t$Rd, $imm$shift", "", []>,
1923     Sched<[WriteImm]> {
1924   bits<5> Rd;
1925   bits<16> imm;
1926   bits<6> shift;
1927   let Inst{30-29} = opc;
1928   let Inst{28-23} = 0b100101;
1929   let Inst{22-21} = shift{5-4};
1930   let Inst{20-5}  = imm;
1931   let Inst{4-0}   = Rd;
1932
1933   let DecoderMethod = "DecodeMoveImmInstruction";
1934 }
1935
1936 multiclass MoveImmediate<bits<2> opc, string asm> {
1937   def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
1938     let Inst{31} = 0;
1939   }
1940
1941   def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
1942     let Inst{31} = 1;
1943   }
1944 }
1945
1946 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1947 class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1948                           string asm>
1949   : I<(outs regtype:$Rd),
1950       (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
1951        asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
1952     Sched<[WriteI, ReadI]> {
1953   bits<5> Rd;
1954   bits<16> imm;
1955   bits<6> shift;
1956   let Inst{30-29} = opc;
1957   let Inst{28-23} = 0b100101;
1958   let Inst{22-21} = shift{5-4};
1959   let Inst{20-5}  = imm;
1960   let Inst{4-0}   = Rd;
1961
1962   let DecoderMethod = "DecodeMoveImmInstruction";
1963 }
1964
1965 multiclass InsertImmediate<bits<2> opc, string asm> {
1966   def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
1967     let Inst{31} = 0;
1968   }
1969
1970   def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
1971     let Inst{31} = 1;
1972   }
1973 }
1974
1975 //---
1976 // Add/Subtract
1977 //---
1978
1979 class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
1980                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
1981                     string asm, SDPatternOperator OpNode>
1982     : I<(outs dstRegtype:$Rd), (ins srcRegtype:$Rn, immtype:$imm),
1983         asm, "\t$Rd, $Rn, $imm", "",
1984         [(set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))]>,
1985       Sched<[WriteI, ReadI]>  {
1986   bits<5>  Rd;
1987   bits<5>  Rn;
1988   bits<14> imm;
1989   let Inst{30}    = isSub;
1990   let Inst{29}    = setFlags;
1991   let Inst{28-24} = 0b10001;
1992   let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
1993   let Inst{21-10} = imm{11-0};
1994   let Inst{9-5}   = Rn;
1995   let Inst{4-0}   = Rd;
1996   let DecoderMethod = "DecodeBaseAddSubImm";
1997 }
1998
1999 class BaseAddSubRegPseudo<RegisterClass regtype,
2000                           SDPatternOperator OpNode>
2001     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2002              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2003       Sched<[WriteI, ReadI, ReadI]>;
2004
2005 class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
2006                      arith_shifted_reg shifted_regtype, string asm,
2007                      SDPatternOperator OpNode>
2008     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2009         asm, "\t$Rd, $Rn, $Rm", "",
2010         [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
2011       Sched<[WriteISReg, ReadI, ReadISReg]> {
2012   // The operands are in order to match the 'addr' MI operands, so we
2013   // don't need an encoder method and by-name matching. Just use the default
2014   // in-order handling. Since we're using by-order, make sure the names
2015   // do not match.
2016   bits<5> dst;
2017   bits<5> src1;
2018   bits<5> src2;
2019   bits<8> shift;
2020   let Inst{30}    = isSub;
2021   let Inst{29}    = setFlags;
2022   let Inst{28-24} = 0b01011;
2023   let Inst{23-22} = shift{7-6};
2024   let Inst{21}    = 0;
2025   let Inst{20-16} = src2;
2026   let Inst{15-10} = shift{5-0};
2027   let Inst{9-5}   = src1;
2028   let Inst{4-0}   = dst;
2029
2030   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2031 }
2032
2033 class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
2034                      RegisterClass src1Regtype, Operand src2Regtype,
2035                      string asm, SDPatternOperator OpNode>
2036     : I<(outs dstRegtype:$R1),
2037         (ins src1Regtype:$R2, src2Regtype:$R3),
2038         asm, "\t$R1, $R2, $R3", "",
2039         [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
2040       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2041   bits<5> Rd;
2042   bits<5> Rn;
2043   bits<5> Rm;
2044   bits<6> ext;
2045   let Inst{30}    = isSub;
2046   let Inst{29}    = setFlags;
2047   let Inst{28-24} = 0b01011;
2048   let Inst{23-21} = 0b001;
2049   let Inst{20-16} = Rm;
2050   let Inst{15-13} = ext{5-3};
2051   let Inst{12-10} = ext{2-0};
2052   let Inst{9-5}   = Rn;
2053   let Inst{4-0}   = Rd;
2054
2055   let DecoderMethod = "DecodeAddSubERegInstruction";
2056 }
2057
2058 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2059 class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
2060                        RegisterClass src1Regtype, RegisterClass src2Regtype,
2061                        Operand ext_op, string asm>
2062     : I<(outs dstRegtype:$Rd),
2063         (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
2064         asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
2065       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2066   bits<5> Rd;
2067   bits<5> Rn;
2068   bits<5> Rm;
2069   bits<6> ext;
2070   let Inst{30}    = isSub;
2071   let Inst{29}    = setFlags;
2072   let Inst{28-24} = 0b01011;
2073   let Inst{23-21} = 0b001;
2074   let Inst{20-16} = Rm;
2075   let Inst{15}    = ext{5};
2076   let Inst{12-10} = ext{2-0};
2077   let Inst{9-5}   = Rn;
2078   let Inst{4-0}   = Rd;
2079
2080   let DecoderMethod = "DecodeAddSubERegInstruction";
2081 }
2082
2083 // Aliases for register+register add/subtract.
2084 class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
2085                      RegisterClass src1Regtype, RegisterClass src2Regtype,
2086                      int shiftExt>
2087     : InstAlias<asm#"\t$dst, $src1, $src2",
2088                 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
2089                       shiftExt)>;
2090
2091 multiclass AddSub<bit isSub, string mnemonic, string alias,
2092                   SDPatternOperator OpNode = null_frag> {
2093   let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2094   // Add/Subtract immediate
2095   // Increase the weight of the immediate variant to try to match it before
2096   // the extended register variant.
2097   // We used to match the register variant before the immediate when the
2098   // register argument could be implicitly zero-extended.
2099   let AddedComplexity = 6 in
2100   def Wri  : BaseAddSubImm<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
2101                            mnemonic, OpNode> {
2102     let Inst{31} = 0;
2103   }
2104   let AddedComplexity = 6 in
2105   def Xri  : BaseAddSubImm<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
2106                            mnemonic, OpNode> {
2107     let Inst{31} = 1;
2108   }
2109
2110   // Add/Subtract register - Only used for CodeGen
2111   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2112   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2113
2114   // Add/Subtract shifted register
2115   def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
2116                            OpNode> {
2117     let Inst{31} = 0;
2118   }
2119   def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
2120                            OpNode> {
2121     let Inst{31} = 1;
2122   }
2123   }
2124
2125   // Add/Subtract extended register
2126   let AddedComplexity = 1, hasSideEffects = 0 in {
2127   def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
2128                            arith_extended_reg32<i32>, mnemonic, OpNode> {
2129     let Inst{31} = 0;
2130   }
2131   def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
2132                            arith_extended_reg32to64<i64>, mnemonic, OpNode> {
2133     let Inst{31} = 1;
2134   }
2135   }
2136
2137   def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
2138                                arith_extendlsl64, mnemonic> {
2139     // UXTX and SXTX only.
2140     let Inst{14-13} = 0b11;
2141     let Inst{31} = 1;
2142   }
2143
2144   // add Rd, Rb, -imm -> sub Rd, Rn, imm
2145   def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2146                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
2147                       addsub_shifted_imm32_neg:$imm), 0>;
2148   def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2149                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
2150                        addsub_shifted_imm64_neg:$imm), 0>;
2151
2152   // Register/register aliases with no shift when SP is not used.
2153   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2154                        GPR32, GPR32, GPR32, 0>;
2155   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2156                        GPR64, GPR64, GPR64, 0>;
2157
2158   // Register/register aliases with no shift when either the destination or
2159   // first source register is SP.
2160   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2161                        GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
2162   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2163                        GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
2164   def : AddSubRegAlias<mnemonic,
2165                        !cast<Instruction>(NAME#"Xrx64"),
2166                        GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
2167   def : AddSubRegAlias<mnemonic,
2168                        !cast<Instruction>(NAME#"Xrx64"),
2169                        GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
2170 }
2171
2172 multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
2173                    string alias, string cmpAlias> {
2174   let isCompare = 1, Defs = [NZCV] in {
2175   // Add/Subtract immediate
2176   def Wri  : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
2177                            mnemonic, OpNode> {
2178     let Inst{31} = 0;
2179   }
2180   def Xri  : BaseAddSubImm<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
2181                            mnemonic, OpNode> {
2182     let Inst{31} = 1;
2183   }
2184
2185   // Add/Subtract register
2186   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2187   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2188
2189   // Add/Subtract shifted register
2190   def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
2191                            OpNode> {
2192     let Inst{31} = 0;
2193   }
2194   def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
2195                            OpNode> {
2196     let Inst{31} = 1;
2197   }
2198
2199   // Add/Subtract extended register
2200   let AddedComplexity = 1 in {
2201   def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
2202                            arith_extended_reg32<i32>, mnemonic, OpNode> {
2203     let Inst{31} = 0;
2204   }
2205   def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
2206                            arith_extended_reg32<i64>, mnemonic, OpNode> {
2207     let Inst{31} = 1;
2208   }
2209   }
2210
2211   def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
2212                                arith_extendlsl64, mnemonic> {
2213     // UXTX and SXTX only.
2214     let Inst{14-13} = 0b11;
2215     let Inst{31} = 1;
2216   }
2217   } // Defs = [NZCV]
2218
2219   // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
2220   def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2221                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
2222                       addsub_shifted_imm32_neg:$imm), 0>;
2223   def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2224                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
2225                        addsub_shifted_imm64_neg:$imm), 0>;
2226
2227   // Compare aliases
2228   def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2229                   WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
2230   def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2231                   XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
2232   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
2233                   WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2234   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
2235                   XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2236   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
2237                   XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
2238   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
2239                   WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
2240   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
2241                   XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
2242
2243   // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
2244   def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2245                   WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
2246   def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2247                   XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
2248
2249   // Compare shorthands
2250   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
2251                   WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
2252   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
2253                   XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
2254   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
2255                   WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
2256   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
2257                   XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
2258
2259   // Register/register aliases with no shift when SP is not used.
2260   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2261                        GPR32, GPR32, GPR32, 0>;
2262   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2263                        GPR64, GPR64, GPR64, 0>;
2264
2265   // Register/register aliases with no shift when the first source register
2266   // is SP.
2267   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2268                        GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
2269   def : AddSubRegAlias<mnemonic,
2270                        !cast<Instruction>(NAME#"Xrx64"),
2271                        GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
2272 }
2273
2274 //---
2275 // Extract
2276 //---
2277 def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
2278                                       SDTCisPtrTy<3>]>;
2279 def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
2280
2281 class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
2282                      list<dag> patterns>
2283     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
2284          asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
2285       Sched<[WriteExtr, ReadExtrHi]> {
2286   bits<5> Rd;
2287   bits<5> Rn;
2288   bits<5> Rm;
2289   bits<6> imm;
2290
2291   let Inst{30-23} = 0b00100111;
2292   let Inst{21}    = 0;
2293   let Inst{20-16} = Rm;
2294   let Inst{15-10} = imm;
2295   let Inst{9-5}   = Rn;
2296   let Inst{4-0}   = Rd;
2297 }
2298
2299 multiclass ExtractImm<string asm> {
2300   def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
2301                       [(set GPR32:$Rd,
2302                         (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
2303     let Inst{31} = 0;
2304     let Inst{22} = 0;
2305     // imm<5> must be zero.
2306     let imm{5}   = 0;
2307   }
2308   def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
2309                       [(set GPR64:$Rd,
2310                         (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
2311
2312     let Inst{31} = 1;
2313     let Inst{22} = 1;
2314   }
2315 }
2316
2317 //---
2318 // Bitfield
2319 //---
2320
2321 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2322 class BaseBitfieldImm<bits<2> opc,
2323                       RegisterClass regtype, Operand imm_type, string asm>
2324     : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
2325          asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
2326       Sched<[WriteIS, ReadI]> {
2327   bits<5> Rd;
2328   bits<5> Rn;
2329   bits<6> immr;
2330   bits<6> imms;
2331
2332   let Inst{30-29} = opc;
2333   let Inst{28-23} = 0b100110;
2334   let Inst{21-16} = immr;
2335   let Inst{15-10} = imms;
2336   let Inst{9-5}   = Rn;
2337   let Inst{4-0}   = Rd;
2338 }
2339
2340 multiclass BitfieldImm<bits<2> opc, string asm> {
2341   def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
2342     let Inst{31} = 0;
2343     let Inst{22} = 0;
2344     // imms<5> and immr<5> must be zero, else ReservedValue().
2345     let Inst{21} = 0;
2346     let Inst{15} = 0;
2347   }
2348   def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
2349     let Inst{31} = 1;
2350     let Inst{22} = 1;
2351   }
2352 }
2353
2354 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2355 class BaseBitfieldImmWith2RegArgs<bits<2> opc,
2356                       RegisterClass regtype, Operand imm_type, string asm>
2357     : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
2358                              imm_type:$imms),
2359          asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
2360       Sched<[WriteIS, ReadI]> {
2361   bits<5> Rd;
2362   bits<5> Rn;
2363   bits<6> immr;
2364   bits<6> imms;
2365
2366   let Inst{30-29} = opc;
2367   let Inst{28-23} = 0b100110;
2368   let Inst{21-16} = immr;
2369   let Inst{15-10} = imms;
2370   let Inst{9-5}   = Rn;
2371   let Inst{4-0}   = Rd;
2372 }
2373
2374 multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
2375   def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
2376     let Inst{31} = 0;
2377     let Inst{22} = 0;
2378     // imms<5> and immr<5> must be zero, else ReservedValue().
2379     let Inst{21} = 0;
2380     let Inst{15} = 0;
2381   }
2382   def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
2383     let Inst{31} = 1;
2384     let Inst{22} = 1;
2385   }
2386 }
2387
2388 //---
2389 // Logical
2390 //---
2391
2392 // Logical (immediate)
2393 class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
2394                      RegisterClass sregtype, Operand imm_type, string asm,
2395                      list<dag> pattern>
2396     : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
2397          asm, "\t$Rd, $Rn, $imm", "", pattern>,
2398       Sched<[WriteI, ReadI]> {
2399   bits<5>  Rd;
2400   bits<5>  Rn;
2401   bits<13> imm;
2402   let Inst{30-29} = opc;
2403   let Inst{28-23} = 0b100100;
2404   let Inst{22}    = imm{12};
2405   let Inst{21-16} = imm{11-6};
2406   let Inst{15-10} = imm{5-0};
2407   let Inst{9-5}   = Rn;
2408   let Inst{4-0}   = Rd;
2409
2410   let DecoderMethod = "DecodeLogicalImmInstruction";
2411 }
2412
2413 // Logical (shifted register)
2414 class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
2415                       logical_shifted_reg shifted_regtype, string asm,
2416                       list<dag> pattern>
2417     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2418         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2419       Sched<[WriteISReg, ReadI, ReadISReg]> {
2420   // The operands are in order to match the 'addr' MI operands, so we
2421   // don't need an encoder method and by-name matching. Just use the default
2422   // in-order handling. Since we're using by-order, make sure the names
2423   // do not match.
2424   bits<5> dst;
2425   bits<5> src1;
2426   bits<5> src2;
2427   bits<8> shift;
2428   let Inst{30-29} = opc;
2429   let Inst{28-24} = 0b01010;
2430   let Inst{23-22} = shift{7-6};
2431   let Inst{21}    = N;
2432   let Inst{20-16} = src2;
2433   let Inst{15-10} = shift{5-0};
2434   let Inst{9-5}   = src1;
2435   let Inst{4-0}   = dst;
2436
2437   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2438 }
2439
2440 // Aliases for register+register logical instructions.
2441 class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2442     : InstAlias<asm#"\t$dst, $src1, $src2",
2443                 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2444
2445 multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2446                       string Alias> {
2447   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2448   def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2449                            [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2450                                                logical_imm32:$imm))]> {
2451     let Inst{31} = 0;
2452     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2453   }
2454   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2455   def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2456                            [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2457                                                logical_imm64:$imm))]> {
2458     let Inst{31} = 1;
2459   }
2460
2461   def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2462                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2463                       logical_imm32_not:$imm), 0>;
2464   def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2465                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2466                        logical_imm64_not:$imm), 0>;
2467 }
2468
2469 multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2470                        string Alias> {
2471   let isCompare = 1, Defs = [NZCV] in {
2472   def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2473       [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2474     let Inst{31} = 0;
2475     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2476   }
2477   def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2478       [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2479     let Inst{31} = 1;
2480   }
2481   } // end Defs = [NZCV]
2482
2483   def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2484                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2485                       logical_imm32_not:$imm), 0>;
2486   def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2487                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2488                        logical_imm64_not:$imm), 0>;
2489 }
2490
2491 class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2492     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2493              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2494       Sched<[WriteI, ReadI, ReadI]>;
2495
2496 // Split from LogicalImm as not all instructions have both.
2497 multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2498                       SDPatternOperator OpNode> {
2499   let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2500   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2501   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2502   }
2503
2504   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2505                             [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2506                                                  logical_shifted_reg32:$Rm))]> {
2507     let Inst{31} = 0;
2508   }
2509   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2510                             [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2511                                                  logical_shifted_reg64:$Rm))]> {
2512     let Inst{31} = 1;
2513   }
2514
2515   def : LogicalRegAlias<mnemonic,
2516                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2517   def : LogicalRegAlias<mnemonic,
2518                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2519 }
2520
2521 // Split from LogicalReg to allow setting NZCV Defs
2522 multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2523                        SDPatternOperator OpNode = null_frag> {
2524   let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2525   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2526   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2527
2528   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2529             [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2530     let Inst{31} = 0;
2531   }
2532   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2533             [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2534     let Inst{31} = 1;
2535   }
2536   } // Defs = [NZCV]
2537
2538   def : LogicalRegAlias<mnemonic,
2539                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2540   def : LogicalRegAlias<mnemonic,
2541                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2542 }
2543
2544 //---
2545 // Conditionally set flags
2546 //---
2547
2548 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2549 class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
2550                             string mnemonic, SDNode OpNode>
2551     : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
2552          mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
2553          [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
2554                              (i32 imm:$cond), NZCV))]>,
2555       Sched<[WriteI, ReadI]> {
2556   let Uses = [NZCV];
2557   let Defs = [NZCV];
2558
2559   bits<5> Rn;
2560   bits<5> imm;
2561   bits<4> nzcv;
2562   bits<4> cond;
2563
2564   let Inst{30}    = op;
2565   let Inst{29-21} = 0b111010010;
2566   let Inst{20-16} = imm;
2567   let Inst{15-12} = cond;
2568   let Inst{11-10} = 0b10;
2569   let Inst{9-5}   = Rn;
2570   let Inst{4}     = 0b0;
2571   let Inst{3-0}   = nzcv;
2572 }
2573
2574 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2575 class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
2576                             SDNode OpNode>
2577     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
2578          mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
2579          [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
2580                              (i32 imm:$cond), NZCV))]>,
2581       Sched<[WriteI, ReadI, ReadI]> {
2582   let Uses = [NZCV];
2583   let Defs = [NZCV];
2584
2585   bits<5> Rn;
2586   bits<5> Rm;
2587   bits<4> nzcv;
2588   bits<4> cond;
2589
2590   let Inst{30}    = op;
2591   let Inst{29-21} = 0b111010010;
2592   let Inst{20-16} = Rm;
2593   let Inst{15-12} = cond;
2594   let Inst{11-10} = 0b00;
2595   let Inst{9-5}   = Rn;
2596   let Inst{4}     = 0b0;
2597   let Inst{3-0}   = nzcv;
2598 }
2599
2600 multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
2601   // immediate operand variants
2602   def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
2603     let Inst{31} = 0;
2604   }
2605   def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
2606     let Inst{31} = 1;
2607   }
2608   // register operand variants
2609   def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
2610     let Inst{31} = 0;
2611   }
2612   def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
2613     let Inst{31} = 1;
2614   }
2615 }
2616
2617 //---
2618 // Conditional select
2619 //---
2620
2621 class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
2622     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2623          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2624          [(set regtype:$Rd,
2625                (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
2626       Sched<[WriteI, ReadI, ReadI]> {
2627   let Uses = [NZCV];
2628
2629   bits<5> Rd;
2630   bits<5> Rn;
2631   bits<5> Rm;
2632   bits<4> cond;
2633
2634   let Inst{30}    = op;
2635   let Inst{29-21} = 0b011010100;
2636   let Inst{20-16} = Rm;
2637   let Inst{15-12} = cond;
2638   let Inst{11-10} = op2;
2639   let Inst{9-5}   = Rn;
2640   let Inst{4-0}   = Rd;
2641 }
2642
2643 multiclass CondSelect<bit op, bits<2> op2, string asm> {
2644   def Wr : BaseCondSelect<op, op2, GPR32, asm> {
2645     let Inst{31} = 0;
2646   }
2647   def Xr : BaseCondSelect<op, op2, GPR64, asm> {
2648     let Inst{31} = 1;
2649   }
2650 }
2651
2652 class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
2653                        PatFrag frag>
2654     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2655          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2656          [(set regtype:$Rd,
2657                (AArch64csel regtype:$Rn, (frag regtype:$Rm),
2658                (i32 imm:$cond), NZCV))]>,
2659       Sched<[WriteI, ReadI, ReadI]> {
2660   let Uses = [NZCV];
2661
2662   bits<5> Rd;
2663   bits<5> Rn;
2664   bits<5> Rm;
2665   bits<4> cond;
2666
2667   let Inst{30}    = op;
2668   let Inst{29-21} = 0b011010100;
2669   let Inst{20-16} = Rm;
2670   let Inst{15-12} = cond;
2671   let Inst{11-10} = op2;
2672   let Inst{9-5}   = Rn;
2673   let Inst{4-0}   = Rd;
2674 }
2675
2676 def inv_cond_XFORM : SDNodeXForm<imm, [{
2677   AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
2678   return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
2679                                    MVT::i32);
2680 }]>;
2681
2682 multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
2683   def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
2684     let Inst{31} = 0;
2685   }
2686   def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
2687     let Inst{31} = 1;
2688   }
2689
2690   def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
2691             (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
2692                                            (inv_cond_XFORM imm:$cond))>;
2693
2694   def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
2695             (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
2696                                            (inv_cond_XFORM imm:$cond))>;
2697 }
2698
2699 //---
2700 // Special Mask Value
2701 //---
2702 def maski8_or_more : Operand<i32>,
2703   ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
2704 }
2705 def maski16_or_more : Operand<i32>,
2706   ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
2707 }
2708
2709
2710 //---
2711 // Load/store
2712 //---
2713
2714 // (unsigned immediate)
2715 // Indexed for 8-bit registers. offset is in range [0,4095].
2716 def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>;
2717 def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>;
2718 def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
2719 def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
2720 def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
2721
2722 def gi_am_indexed8 :
2723     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
2724     GIComplexPatternEquiv<am_indexed8>;
2725 def gi_am_indexed16 :
2726     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
2727     GIComplexPatternEquiv<am_indexed16>;
2728 def gi_am_indexed32 :
2729     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
2730     GIComplexPatternEquiv<am_indexed32>;
2731 def gi_am_indexed64 :
2732     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
2733     GIComplexPatternEquiv<am_indexed64>;
2734 def gi_am_indexed128 :
2735     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
2736     GIComplexPatternEquiv<am_indexed128>;
2737
2738 class UImm12OffsetOperand<int Scale> : AsmOperandClass {
2739   let Name = "UImm12Offset" # Scale;
2740   let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
2741   let PredicateMethod = "isUImm12Offset<" # Scale # ">";
2742   let DiagnosticType = "InvalidMemoryIndexed" # Scale;
2743 }
2744
2745 def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
2746 def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
2747 def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
2748 def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
2749 def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
2750
2751 class uimm12_scaled<int Scale> : Operand<i64> {
2752   let ParserMatchClass
2753    = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
2754   let EncoderMethod
2755    = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
2756   let PrintMethod = "printUImm12Offset<" # Scale # ">";
2757 }
2758
2759 def uimm12s1 : uimm12_scaled<1>;
2760 def uimm12s2 : uimm12_scaled<2>;
2761 def uimm12s4 : uimm12_scaled<4>;
2762 def uimm12s8 : uimm12_scaled<8>;
2763 def uimm12s16 : uimm12_scaled<16>;
2764
2765 class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2766                       string asm, list<dag> pattern>
2767     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2768   bits<5> Rt;
2769
2770   bits<5> Rn;
2771   bits<12> offset;
2772
2773   let Inst{31-30} = sz;
2774   let Inst{29-27} = 0b111;
2775   let Inst{26}    = V;
2776   let Inst{25-24} = 0b01;
2777   let Inst{23-22} = opc;
2778   let Inst{21-10} = offset;
2779   let Inst{9-5}   = Rn;
2780   let Inst{4-0}   = Rt;
2781
2782   let DecoderMethod = "DecodeUnsignedLdStInstruction";
2783 }
2784
2785 multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
2786                   Operand indextype, string asm, list<dag> pattern> {
2787   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2788   def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
2789                            (ins GPR64sp:$Rn, indextype:$offset),
2790                            asm, pattern>,
2791            Sched<[WriteLD]>;
2792
2793   def : InstAlias<asm # "\t$Rt, [$Rn]",
2794                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2795 }
2796
2797 multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
2798              Operand indextype, string asm, list<dag> pattern> {
2799   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2800   def ui : BaseLoadStoreUI<sz, V, opc, (outs),
2801                            (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
2802                            asm, pattern>,
2803            Sched<[WriteST]>;
2804
2805   def : InstAlias<asm # "\t$Rt, [$Rn]",
2806                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2807 }
2808
2809 // Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
2810 // substitute zero-registers automatically.
2811 //
2812 // TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
2813 //       into StoreUI.
2814 multiclass StoreUIz<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
2815              Operand indextype, string asm, list<dag> pattern> {
2816   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2817   def ui : BaseLoadStoreUI<sz, V, opc, (outs),
2818                            (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
2819                            asm, pattern>,
2820            Sched<[WriteST]>;
2821
2822   def : InstAlias<asm # "\t$Rt, [$Rn]",
2823                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2824 }
2825
2826 def PrefetchOperand : AsmOperandClass {
2827   let Name = "Prefetch";
2828   let ParserMethod = "tryParsePrefetch";
2829 }
2830 def prfop : Operand<i32> {
2831   let PrintMethod = "printPrefetchOp";
2832   let ParserMatchClass = PrefetchOperand;
2833 }
2834
2835 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2836 class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2837     : BaseLoadStoreUI<sz, V, opc,
2838                       (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
2839                       asm, pat>,
2840       Sched<[WriteLD]>;
2841
2842 //---
2843 // Load literal
2844 //---
2845
2846 // Load literal address: 19-bit immediate. The low two bits of the target
2847 // offset are implied zero and so are not part of the immediate.
2848 def am_ldrlit : Operand<iPTR> {
2849   let EncoderMethod = "getLoadLiteralOpValue";
2850   let DecoderMethod = "DecodePCRelLabel19";
2851   let PrintMethod = "printAlignedLabel";
2852   let ParserMatchClass = PCRelLabel19Operand;
2853   let OperandType = "OPERAND_PCREL";
2854 }
2855
2856 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2857 class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm>
2858     : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
2859         asm, "\t$Rt, $label", "", []>,
2860       Sched<[WriteLD]> {
2861   bits<5> Rt;
2862   bits<19> label;
2863   let Inst{31-30} = opc;
2864   let Inst{29-27} = 0b011;
2865   let Inst{26}    = V;
2866   let Inst{25-24} = 0b00;
2867   let Inst{23-5}  = label;
2868   let Inst{4-0}   = Rt;
2869 }
2870
2871 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2872 class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2873     : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
2874         asm, "\t$Rt, $label", "", pat>,
2875       Sched<[WriteLD]> {
2876   bits<5> Rt;
2877   bits<19> label;
2878   let Inst{31-30} = opc;
2879   let Inst{29-27} = 0b011;
2880   let Inst{26}    = V;
2881   let Inst{25-24} = 0b00;
2882   let Inst{23-5}  = label;
2883   let Inst{4-0}   = Rt;
2884 }
2885
2886 //---
2887 // Load/store register offset
2888 //---
2889
2890 def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>;
2891 def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>;
2892 def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>;
2893 def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>;
2894 def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>;
2895
2896 def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>;
2897 def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>;
2898 def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>;
2899 def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>;
2900 def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>;
2901
2902 class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
2903   let Name = "Mem" # Reg # "Extend" # Width;
2904   let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
2905   let RenderMethod = "addMemExtendOperands";
2906   let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
2907 }
2908
2909 def MemWExtend8Operand : MemExtendOperand<"W", 8> {
2910   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2911   // the trivial shift.
2912   let RenderMethod = "addMemExtend8Operands";
2913 }
2914 def MemWExtend16Operand : MemExtendOperand<"W", 16>;
2915 def MemWExtend32Operand : MemExtendOperand<"W", 32>;
2916 def MemWExtend64Operand : MemExtendOperand<"W", 64>;
2917 def MemWExtend128Operand : MemExtendOperand<"W", 128>;
2918
2919 def MemXExtend8Operand : MemExtendOperand<"X", 8> {
2920   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2921   // the trivial shift.
2922   let RenderMethod = "addMemExtend8Operands";
2923 }
2924 def MemXExtend16Operand : MemExtendOperand<"X", 16>;
2925 def MemXExtend32Operand : MemExtendOperand<"X", 32>;
2926 def MemXExtend64Operand : MemExtendOperand<"X", 64>;
2927 def MemXExtend128Operand : MemExtendOperand<"X", 128>;
2928
2929 class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
2930         : Operand<i32> {
2931   let ParserMatchClass = ParserClass;
2932   let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
2933   let DecoderMethod = "DecodeMemExtend";
2934   let EncoderMethod = "getMemExtendOpValue";
2935   let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
2936 }
2937
2938 def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
2939 def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
2940 def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
2941 def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
2942 def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
2943
2944 def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
2945 def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
2946 def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
2947 def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
2948 def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
2949
2950 class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
2951                   Operand wextend, Operand xextend>  {
2952   // CodeGen-level pattern covering the entire addressing mode.
2953   ComplexPattern Wpat = windex;
2954   ComplexPattern Xpat = xindex;
2955
2956   // Asm-level Operand covering the valid "uxtw #3" style syntax.
2957   Operand Wext = wextend;
2958   Operand Xext = xextend;
2959 }
2960
2961 def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
2962 def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
2963 def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
2964 def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
2965 def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
2966                        ro_Xextend128>;
2967
2968 class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
2969                       string asm, dag ins, dag outs, list<dag> pat>
2970     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2971   bits<5> Rt;
2972   bits<5> Rn;
2973   bits<5> Rm;
2974   bits<2> extend;
2975   let Inst{31-30} = sz;
2976   let Inst{29-27} = 0b111;
2977   let Inst{26}    = V;
2978   let Inst{25-24} = 0b00;
2979   let Inst{23-22} = opc;
2980   let Inst{21}    = 1;
2981   let Inst{20-16} = Rm;
2982   let Inst{15}    = extend{1}; // sign extend Rm?
2983   let Inst{14}    = 1;
2984   let Inst{12}    = extend{0}; // do shift?
2985   let Inst{11-10} = 0b10;
2986   let Inst{9-5}   = Rn;
2987   let Inst{4-0}   = Rt;
2988 }
2989
2990 class ROInstAlias<string asm, RegisterOperand regtype, Instruction INST>
2991   : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
2992               (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
2993
2994 multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
2995                    string asm, ValueType Ty, SDPatternOperator loadop> {
2996   let AddedComplexity = 10 in
2997   def roW : LoadStore8RO<sz, V, opc, regtype, asm,
2998                  (outs regtype:$Rt),
2999                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3000                  [(set (Ty regtype:$Rt),
3001                        (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3002                                              ro_Wextend8:$extend)))]>,
3003            Sched<[WriteLDIdx, ReadAdrBase]> {
3004     let Inst{13} = 0b0;
3005   }
3006
3007   let AddedComplexity = 10 in
3008   def roX : LoadStore8RO<sz, V, opc, regtype, asm,
3009                  (outs regtype:$Rt),
3010                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3011                  [(set (Ty regtype:$Rt),
3012                        (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3013                                              ro_Xextend8:$extend)))]>,
3014            Sched<[WriteLDIdx, ReadAdrBase]> {
3015     let Inst{13} = 0b1;
3016   }
3017
3018   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3019 }
3020
3021 multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3022                     string asm, ValueType Ty, SDPatternOperator storeop> {
3023   let AddedComplexity = 10 in
3024   def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3025                  (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3026                  [(storeop (Ty regtype:$Rt),
3027                            (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3028                                          ro_Wextend8:$extend))]>,
3029             Sched<[WriteSTIdx, ReadAdrBase]> {
3030     let Inst{13} = 0b0;
3031   }
3032
3033   let AddedComplexity = 10 in
3034   def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3035                  (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3036                  [(storeop (Ty regtype:$Rt),
3037                            (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3038                                          ro_Xextend8:$extend))]>,
3039             Sched<[WriteSTIdx, ReadAdrBase]> {
3040     let Inst{13} = 0b1;
3041   }
3042
3043   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3044 }
3045
3046 class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3047                       string asm, dag ins, dag outs, list<dag> pat>
3048     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3049   bits<5> Rt;
3050   bits<5> Rn;
3051   bits<5> Rm;
3052   bits<2> extend;
3053   let Inst{31-30} = sz;
3054   let Inst{29-27} = 0b111;
3055   let Inst{26}    = V;
3056   let Inst{25-24} = 0b00;
3057   let Inst{23-22} = opc;
3058   let Inst{21}    = 1;
3059   let Inst{20-16} = Rm;
3060   let Inst{15}    = extend{1}; // sign extend Rm?
3061   let Inst{14}    = 1;
3062   let Inst{12}    = extend{0}; // do shift?
3063   let Inst{11-10} = 0b10;
3064   let Inst{9-5}   = Rn;
3065   let Inst{4-0}   = Rt;
3066 }
3067
3068 multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3069                     string asm, ValueType Ty, SDPatternOperator loadop> {
3070   let AddedComplexity = 10 in
3071   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3072                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3073                  [(set (Ty regtype:$Rt),
3074                        (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3075                                               ro_Wextend16:$extend)))]>,
3076             Sched<[WriteLDIdx, ReadAdrBase]> {
3077     let Inst{13} = 0b0;
3078   }
3079
3080   let AddedComplexity = 10 in
3081   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3082                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3083                  [(set (Ty regtype:$Rt),
3084                        (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3085                                              ro_Xextend16:$extend)))]>,
3086             Sched<[WriteLDIdx, ReadAdrBase]> {
3087     let Inst{13} = 0b1;
3088   }
3089
3090   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3091 }
3092
3093 multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3094                      string asm, ValueType Ty, SDPatternOperator storeop> {
3095   let AddedComplexity = 10 in
3096   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3097                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3098                 [(storeop (Ty regtype:$Rt),
3099                           (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3100                                          ro_Wextend16:$extend))]>,
3101            Sched<[WriteSTIdx, ReadAdrBase]> {
3102     let Inst{13} = 0b0;
3103   }
3104
3105   let AddedComplexity = 10 in
3106   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3107                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3108                 [(storeop (Ty regtype:$Rt),
3109                           (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3110                                          ro_Xextend16:$extend))]>,
3111            Sched<[WriteSTIdx, ReadAdrBase]> {
3112     let Inst{13} = 0b1;
3113   }
3114
3115   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3116 }
3117
3118 class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3119                       string asm, dag ins, dag outs, list<dag> pat>
3120     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3121   bits<5> Rt;
3122   bits<5> Rn;
3123   bits<5> Rm;
3124   bits<2> extend;
3125   let Inst{31-30} = sz;
3126   let Inst{29-27} = 0b111;
3127   let Inst{26}    = V;
3128   let Inst{25-24} = 0b00;
3129   let Inst{23-22} = opc;
3130   let Inst{21}    = 1;
3131   let Inst{20-16} = Rm;
3132   let Inst{15}    = extend{1}; // sign extend Rm?
3133   let Inst{14}    = 1;
3134   let Inst{12}    = extend{0}; // do shift?
3135   let Inst{11-10} = 0b10;
3136   let Inst{9-5}   = Rn;
3137   let Inst{4-0}   = Rt;
3138 }
3139
3140 multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3141                     string asm, ValueType Ty, SDPatternOperator loadop> {
3142   let AddedComplexity = 10 in
3143   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3144                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3145                  [(set (Ty regtype:$Rt),
3146                        (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3147                                               ro_Wextend32:$extend)))]>,
3148            Sched<[WriteLDIdx, ReadAdrBase]> {
3149     let Inst{13} = 0b0;
3150   }
3151
3152   let AddedComplexity = 10 in
3153   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3154                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3155                  [(set (Ty regtype:$Rt),
3156                        (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3157                                               ro_Xextend32:$extend)))]>,
3158            Sched<[WriteLDIdx, ReadAdrBase]> {
3159     let Inst{13} = 0b1;
3160   }
3161
3162   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3163 }
3164
3165 multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3166                      string asm, ValueType Ty, SDPatternOperator storeop> {
3167   let AddedComplexity = 10 in
3168   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3169                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3170                 [(storeop (Ty regtype:$Rt),
3171                           (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3172                                          ro_Wextend32:$extend))]>,
3173             Sched<[WriteSTIdx, ReadAdrBase]> {
3174     let Inst{13} = 0b0;
3175   }
3176
3177   let AddedComplexity = 10 in
3178   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3179                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3180                 [(storeop (Ty regtype:$Rt),
3181                           (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3182                                         ro_Xextend32:$extend))]>,
3183             Sched<[WriteSTIdx, ReadAdrBase]> {
3184     let Inst{13} = 0b1;
3185   }
3186
3187   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3188 }
3189
3190 class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3191                       string asm, dag ins, dag outs, list<dag> pat>
3192     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3193   bits<5> Rt;
3194   bits<5> Rn;
3195   bits<5> Rm;
3196   bits<2> extend;
3197   let Inst{31-30} = sz;
3198   let Inst{29-27} = 0b111;
3199   let Inst{26}    = V;
3200   let Inst{25-24} = 0b00;
3201   let Inst{23-22} = opc;
3202   let Inst{21}    = 1;
3203   let Inst{20-16} = Rm;
3204   let Inst{15}    = extend{1}; // sign extend Rm?
3205   let Inst{14}    = 1;
3206   let Inst{12}    = extend{0}; // do shift?
3207   let Inst{11-10} = 0b10;
3208   let Inst{9-5}   = Rn;
3209   let Inst{4-0}   = Rt;
3210 }
3211
3212 multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3213                     string asm, ValueType Ty, SDPatternOperator loadop> {
3214   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3215   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3216                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3217                 [(set (Ty regtype:$Rt),
3218                       (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3219                                              ro_Wextend64:$extend)))]>,
3220            Sched<[WriteLDIdx, ReadAdrBase]> {
3221     let Inst{13} = 0b0;
3222   }
3223
3224   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3225   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3226                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3227                  [(set (Ty regtype:$Rt),
3228                        (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3229                                               ro_Xextend64:$extend)))]>,
3230            Sched<[WriteLDIdx, ReadAdrBase]> {
3231     let Inst{13} = 0b1;
3232   }
3233
3234   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3235 }
3236
3237 multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3238                      string asm, ValueType Ty, SDPatternOperator storeop> {
3239   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3240   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3241                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3242                 [(storeop (Ty regtype:$Rt),
3243                           (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3244                                          ro_Wextend64:$extend))]>,
3245             Sched<[WriteSTIdx, ReadAdrBase]> {
3246     let Inst{13} = 0b0;
3247   }
3248
3249   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3250   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3251                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3252                 [(storeop (Ty regtype:$Rt),
3253                           (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3254                                          ro_Xextend64:$extend))]>,
3255             Sched<[WriteSTIdx, ReadAdrBase]> {
3256     let Inst{13} = 0b1;
3257   }
3258
3259   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3260 }
3261
3262 class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3263                       string asm, dag ins, dag outs, list<dag> pat>
3264     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3265   bits<5> Rt;
3266   bits<5> Rn;
3267   bits<5> Rm;
3268   bits<2> extend;
3269   let Inst{31-30} = sz;
3270   let Inst{29-27} = 0b111;
3271   let Inst{26}    = V;
3272   let Inst{25-24} = 0b00;
3273   let Inst{23-22} = opc;
3274   let Inst{21}    = 1;
3275   let Inst{20-16} = Rm;
3276   let Inst{15}    = extend{1}; // sign extend Rm?
3277   let Inst{14}    = 1;
3278   let Inst{12}    = extend{0}; // do shift?
3279   let Inst{11-10} = 0b10;
3280   let Inst{9-5}   = Rn;
3281   let Inst{4-0}   = Rt;
3282 }
3283
3284 multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3285                      string asm, ValueType Ty, SDPatternOperator loadop> {
3286   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3287   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3288                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3289                  [(set (Ty regtype:$Rt),
3290                        (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
3291                                                ro_Wextend128:$extend)))]>,
3292             Sched<[WriteLDIdx, ReadAdrBase]> {
3293     let Inst{13} = 0b0;
3294   }
3295
3296   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3297   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3298                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3299                  [(set (Ty regtype:$Rt),
3300                        (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
3301                                                ro_Xextend128:$extend)))]>,
3302             Sched<[WriteLDIdx, ReadAdrBase]> {
3303     let Inst{13} = 0b1;
3304   }
3305
3306   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3307 }
3308
3309 multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3310                       string asm, ValueType Ty, SDPatternOperator storeop> {
3311   let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3312   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3313                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3314                 []>,
3315             Sched<[WriteSTIdx, ReadAdrBase]> {
3316     let Inst{13} = 0b0;
3317   }
3318
3319   let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3320   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3321                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3322                 []>,
3323             Sched<[WriteSTIdx, ReadAdrBase]> {
3324     let Inst{13} = 0b1;
3325   }
3326
3327   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3328 }
3329
3330 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3331 class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
3332                      string asm, list<dag> pat>
3333     : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
3334       Sched<[WriteLD]> {
3335   bits<5> Rt;
3336   bits<5> Rn;
3337   bits<5> Rm;
3338   bits<2> extend;
3339   let Inst{31-30} = sz;
3340   let Inst{29-27} = 0b111;
3341   let Inst{26}    = V;
3342   let Inst{25-24} = 0b00;
3343   let Inst{23-22} = opc;
3344   let Inst{21}    = 1;
3345   let Inst{20-16} = Rm;
3346   let Inst{15}    = extend{1}; // sign extend Rm?
3347   let Inst{14}    = 1;
3348   let Inst{12}    = extend{0}; // do shift?
3349   let Inst{11-10} = 0b10;
3350   let Inst{9-5}   = Rn;
3351   let Inst{4-0}   = Rt;
3352 }
3353
3354 multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
3355   def roW : BasePrefetchRO<sz, V, opc, (outs),
3356                 (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3357                 asm, [(AArch64Prefetch imm:$Rt,
3358                                      (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3359                                                     ro_Wextend64:$extend))]> {
3360     let Inst{13} = 0b0;
3361   }
3362
3363   def roX : BasePrefetchRO<sz, V, opc, (outs),
3364                 (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3365                 asm,  [(AArch64Prefetch imm:$Rt,
3366                                       (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3367                                                      ro_Xextend64:$extend))]> {
3368     let Inst{13} = 0b1;
3369   }
3370
3371   def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
3372                (!cast<Instruction>(NAME # "roX") prfop:$Rt,
3373                                                  GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3374 }
3375
3376 //---
3377 // Load/store unscaled immediate
3378 //---
3379
3380 def am_unscaled8 :  ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
3381 def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
3382 def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
3383 def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
3384 def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
3385
3386 def gi_am_unscaled8 :
3387     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
3388     GIComplexPatternEquiv<am_unscaled8>;
3389 def gi_am_unscaled16 :
3390     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
3391     GIComplexPatternEquiv<am_unscaled16>;
3392 def gi_am_unscaled32 :
3393     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
3394     GIComplexPatternEquiv<am_unscaled32>;
3395 def gi_am_unscaled64 :
3396     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
3397     GIComplexPatternEquiv<am_unscaled64>;
3398 def gi_am_unscaled128 :
3399     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
3400     GIComplexPatternEquiv<am_unscaled128>;
3401
3402
3403 class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3404                            string asm, list<dag> pattern>
3405     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3406   bits<5> Rt;
3407   bits<5> Rn;
3408   bits<9> offset;
3409   let Inst{31-30} = sz;
3410   let Inst{29-27} = 0b111;
3411   let Inst{26}    = V;
3412   let Inst{25-24} = 0b00;
3413   let Inst{23-22} = opc;
3414   let Inst{21}    = 0;
3415   let Inst{20-12} = offset;
3416   let Inst{11-10} = 0b00;
3417   let Inst{9-5}   = Rn;
3418   let Inst{4-0}   = Rt;
3419
3420   let DecoderMethod = "DecodeSignedLdStInstruction";
3421 }
3422
3423 // Armv8.4 LDAPR & STLR with Immediate Offset instruction
3424 multiclass BaseLoadUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3425                               RegisterOperand regtype > {
3426   def i : BaseLoadStoreUnscale<sz, 0, opc, (outs regtype:$Rt),
3427                                (ins GPR64sp:$Rn, simm9:$offset), asm, []>,
3428           Sched<[WriteST]> {
3429     let Inst{29} = 0;
3430     let Inst{24} = 1;
3431   }
3432   def : InstAlias<asm # "\t$Rt, [$Rn]",
3433                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3434 }
3435
3436 multiclass BaseStoreUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3437                                RegisterOperand regtype > {
3438   def i : BaseLoadStoreUnscale<sz, 0, opc, (outs),
3439                                (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3440                                asm, []>,
3441           Sched<[WriteST]> {
3442     let Inst{29} = 0;
3443     let Inst{24} = 1;
3444   }
3445   def : InstAlias<asm # "\t$Rt, [$Rn]",
3446                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3447 }
3448
3449 multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3450                    string asm, list<dag> pattern> {
3451   let AddedComplexity = 1 in // try this before LoadUI
3452   def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
3453                                (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
3454           Sched<[WriteLD]>;
3455
3456   def : InstAlias<asm # "\t$Rt, [$Rn]",
3457                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3458 }
3459
3460 multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3461                          string asm, list<dag> pattern> {
3462   let AddedComplexity = 1 in // try this before StoreUI
3463   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3464                                (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3465                                asm, pattern>,
3466           Sched<[WriteST]>;
3467
3468   def : InstAlias<asm # "\t$Rt, [$Rn]",
3469                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3470 }
3471
3472 multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
3473                             list<dag> pat> {
3474   let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3475   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3476                                (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
3477                                asm, pat>,
3478           Sched<[WriteLD]>;
3479
3480   def : InstAlias<asm # "\t$Rt, [$Rn]",
3481                   (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
3482 }
3483
3484 //---
3485 // Load/store unscaled immediate, unprivileged
3486 //---
3487
3488 class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3489                                 dag oops, dag iops, string asm>
3490     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
3491   bits<5> Rt;
3492   bits<5> Rn;
3493   bits<9> offset;
3494   let Inst{31-30} = sz;
3495   let Inst{29-27} = 0b111;
3496   let Inst{26}    = V;
3497   let Inst{25-24} = 0b00;
3498   let Inst{23-22} = opc;
3499   let Inst{21}    = 0;
3500   let Inst{20-12} = offset;
3501   let Inst{11-10} = 0b10;
3502   let Inst{9-5}   = Rn;
3503   let Inst{4-0}   = Rt;
3504
3505   let DecoderMethod = "DecodeSignedLdStInstruction";
3506 }
3507
3508 multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
3509                             RegisterClass regtype, string asm> {
3510   let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
3511   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
3512                                     (ins GPR64sp:$Rn, simm9:$offset), asm>,
3513           Sched<[WriteLD]>;
3514
3515   def : InstAlias<asm # "\t$Rt, [$Rn]",
3516                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3517 }
3518
3519 multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3520                              RegisterClass regtype, string asm> {
3521   let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
3522   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
3523                                  (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3524                                  asm>,
3525           Sched<[WriteST]>;
3526
3527   def : InstAlias<asm # "\t$Rt, [$Rn]",
3528                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3529 }
3530
3531 //---
3532 // Load/store pre-indexed
3533 //---
3534
3535 class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3536                           string asm, string cstr, list<dag> pat>
3537     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
3538   bits<5> Rt;
3539   bits<5> Rn;
3540   bits<9> offset;
3541   let Inst{31-30} = sz;
3542   let Inst{29-27} = 0b111;
3543   let Inst{26}    = V;
3544   let Inst{25-24} = 0;
3545   let Inst{23-22} = opc;
3546   let Inst{21}    = 0;
3547   let Inst{20-12} = offset;
3548   let Inst{11-10} = 0b11;
3549   let Inst{9-5}   = Rn;
3550   let Inst{4-0}   = Rt;
3551
3552   let DecoderMethod = "DecodeSignedLdStInstruction";
3553 }
3554
3555 let hasSideEffects = 0 in {
3556 let mayStore = 0, mayLoad = 1 in
3557 class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3558              string asm>
3559     : BaseLoadStorePreIdx<sz, V, opc,
3560                      (outs GPR64sp:$wback, regtype:$Rt),
3561                      (ins GPR64sp:$Rn, simm9:$offset), asm,
3562                      "$Rn = $wback,@earlyclobber $wback", []>,
3563       Sched<[WriteLD, WriteAdr]>;
3564
3565 let mayStore = 1, mayLoad = 0 in
3566 class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3567                   string asm, SDPatternOperator storeop, ValueType Ty>
3568     : BaseLoadStorePreIdx<sz, V, opc,
3569                       (outs GPR64sp:$wback),
3570                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3571                       asm, "$Rn = $wback,@earlyclobber $wback",
3572       [(set GPR64sp:$wback,
3573             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3574       Sched<[WriteAdr, WriteST]>;
3575 } // hasSideEffects = 0
3576
3577 //---
3578 // Load/store post-indexed
3579 //---
3580
3581 class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3582                           string asm, string cstr, list<dag> pat>
3583     : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
3584   bits<5> Rt;
3585   bits<5> Rn;
3586   bits<9> offset;
3587   let Inst{31-30} = sz;
3588   let Inst{29-27} = 0b111;
3589   let Inst{26}    = V;
3590   let Inst{25-24} = 0b00;
3591   let Inst{23-22} = opc;
3592   let Inst{21}    = 0b0;
3593   let Inst{20-12} = offset;
3594   let Inst{11-10} = 0b01;
3595   let Inst{9-5}   = Rn;
3596   let Inst{4-0}   = Rt;
3597
3598   let DecoderMethod = "DecodeSignedLdStInstruction";
3599 }
3600
3601 let hasSideEffects = 0 in {
3602 let mayStore = 0, mayLoad = 1 in
3603 class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3604              string asm>
3605     : BaseLoadStorePostIdx<sz, V, opc,
3606                       (outs GPR64sp:$wback, regtype:$Rt),
3607                       (ins GPR64sp:$Rn, simm9:$offset),
3608                       asm, "$Rn = $wback,@earlyclobber $wback", []>,
3609       Sched<[WriteLD, WriteAdr]>;
3610
3611 let mayStore = 1, mayLoad = 0 in
3612 class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3613                    string asm, SDPatternOperator storeop, ValueType Ty>
3614     : BaseLoadStorePostIdx<sz, V, opc,
3615                       (outs GPR64sp:$wback),
3616                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3617                        asm, "$Rn = $wback,@earlyclobber $wback",
3618       [(set GPR64sp:$wback,
3619             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3620     Sched<[WriteAdr, WriteST]>;
3621 } // hasSideEffects = 0
3622
3623
3624 //---
3625 // Load/store pair
3626 //---
3627
3628 // (indexed, offset)
3629
3630 class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
3631                               string asm>
3632     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3633   bits<5> Rt;
3634   bits<5> Rt2;
3635   bits<5> Rn;
3636   bits<7> offset;
3637   let Inst{31-30} = opc;
3638   let Inst{29-27} = 0b101;
3639   let Inst{26}    = V;
3640   let Inst{25-23} = 0b010;
3641   let Inst{22}    = L;
3642   let Inst{21-15} = offset;
3643   let Inst{14-10} = Rt2;
3644   let Inst{9-5}   = Rn;
3645   let Inst{4-0}   = Rt;
3646
3647   let DecoderMethod = "DecodePairLdStInstruction";
3648 }
3649
3650 multiclass LoadPairOffset<bits<2> opc, bit V, RegisterOperand regtype,
3651                           Operand indextype, string asm> {
3652   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3653   def i : BaseLoadStorePairOffset<opc, V, 1,
3654                                   (outs regtype:$Rt, regtype:$Rt2),
3655                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
3656           Sched<[WriteLD, WriteLDHi]>;
3657
3658   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3659                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3660                                                   GPR64sp:$Rn, 0)>;
3661 }
3662
3663
3664 multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
3665                            Operand indextype, string asm> {
3666   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
3667   def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
3668                                   (ins regtype:$Rt, regtype:$Rt2,
3669                                        GPR64sp:$Rn, indextype:$offset),
3670                                   asm>,
3671           Sched<[WriteSTP]>;
3672
3673   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3674                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3675                                                   GPR64sp:$Rn, 0)>;
3676 }
3677
3678 // (pre-indexed)
3679 class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3680                               string asm>
3681     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
3682   bits<5> Rt;
3683   bits<5> Rt2;
3684   bits<5> Rn;
3685   bits<7> offset;
3686   let Inst{31-30} = opc;
3687   let Inst{29-27} = 0b101;
3688   let Inst{26}    = V;
3689   let Inst{25-23} = 0b011;
3690   let Inst{22}    = L;
3691   let Inst{21-15} = offset;
3692   let Inst{14-10} = Rt2;
3693   let Inst{9-5}   = Rn;
3694   let Inst{4-0}   = Rt;
3695
3696   let DecoderMethod = "DecodePairLdStInstruction";
3697 }
3698
3699 let hasSideEffects = 0 in {
3700 let mayStore = 0, mayLoad = 1 in
3701 class LoadPairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
3702                      Operand indextype, string asm>
3703     : BaseLoadStorePairPreIdx<opc, V, 1,
3704                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3705                               (ins GPR64sp:$Rn, indextype:$offset), asm>,
3706       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3707
3708 let mayStore = 1, mayLoad = 0 in
3709 class StorePairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
3710                       Operand indextype, string asm>
3711     : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
3712                              (ins regtype:$Rt, regtype:$Rt2,
3713                                   GPR64sp:$Rn, indextype:$offset),
3714                              asm>,
3715       Sched<[WriteAdr, WriteSTP]>;
3716 } // hasSideEffects = 0
3717
3718 // (post-indexed)
3719
3720 class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3721                               string asm>
3722     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
3723   bits<5> Rt;
3724   bits<5> Rt2;
3725   bits<5> Rn;
3726   bits<7> offset;
3727   let Inst{31-30} = opc;
3728   let Inst{29-27} = 0b101;
3729   let Inst{26}    = V;
3730   let Inst{25-23} = 0b001;
3731   let Inst{22}    = L;
3732   let Inst{21-15} = offset;
3733   let Inst{14-10} = Rt2;
3734   let Inst{9-5}   = Rn;
3735   let Inst{4-0}   = Rt;
3736
3737   let DecoderMethod = "DecodePairLdStInstruction";
3738 }
3739
3740 let hasSideEffects = 0 in {
3741 let mayStore = 0, mayLoad = 1 in
3742 class LoadPairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
3743                       Operand idxtype, string asm>
3744     : BaseLoadStorePairPostIdx<opc, V, 1,
3745                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3746                               (ins GPR64sp:$Rn, idxtype:$offset), asm>,
3747       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3748
3749 let mayStore = 1, mayLoad = 0 in
3750 class StorePairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
3751                        Operand idxtype, string asm>
3752     : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
3753                              (ins regtype:$Rt, regtype:$Rt2,
3754                                   GPR64sp:$Rn, idxtype:$offset),
3755                              asm>,
3756       Sched<[WriteAdr, WriteSTP]>;
3757 } // hasSideEffects = 0
3758
3759 //  (no-allocate)
3760
3761 class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
3762                               string asm>
3763     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3764   bits<5> Rt;
3765   bits<5> Rt2;
3766   bits<5> Rn;
3767   bits<7> offset;
3768   let Inst{31-30} = opc;
3769   let Inst{29-27} = 0b101;
3770   let Inst{26}    = V;
3771   let Inst{25-23} = 0b000;
3772   let Inst{22}    = L;
3773   let Inst{21-15} = offset;
3774   let Inst{14-10} = Rt2;
3775   let Inst{9-5}   = Rn;
3776   let Inst{4-0}   = Rt;
3777
3778   let DecoderMethod = "DecodePairLdStInstruction";
3779 }
3780
3781 multiclass LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3782                            Operand indextype, string asm> {
3783   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3784   def i : BaseLoadStorePairNoAlloc<opc, V, 1,
3785                                    (outs regtype:$Rt, regtype:$Rt2),
3786                                    (ins GPR64sp:$Rn, indextype:$offset), asm>,
3787           Sched<[WriteLD, WriteLDHi]>;
3788
3789
3790   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3791                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3792                                                   GPR64sp:$Rn, 0)>;
3793 }
3794
3795 multiclass StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3796                       Operand indextype, string asm> {
3797   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
3798   def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
3799                                    (ins regtype:$Rt, regtype:$Rt2,
3800                                         GPR64sp:$Rn, indextype:$offset),
3801                                    asm>,
3802           Sched<[WriteSTP]>;
3803
3804   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3805                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3806                                                   GPR64sp:$Rn, 0)>;
3807 }
3808
3809 //---
3810 // Load/store exclusive
3811 //---
3812
3813 // True exclusive operations write to and/or read from the system's exclusive
3814 // monitors, which as far as a compiler is concerned can be modelled as a
3815 // random shared memory address. Hence LoadExclusive mayStore.
3816 //
3817 // Since these instructions have the undefined register bits set to 1 in
3818 // their canonical form, we need a post encoder method to set those bits
3819 // to 1 when encoding these instructions. We do this using the
3820 // fixLoadStoreExclusive function. This function has template parameters:
3821 //
3822 // fixLoadStoreExclusive<int hasRs, int hasRt2>
3823 //
3824 // hasRs indicates that the instruction uses the Rs field, so we won't set
3825 // it to 1 (and the same for Rt2). We don't need template parameters for
3826 // the other register fields since Rt and Rn are always used.
3827 //
3828 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
3829 class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3830                              dag oops, dag iops, string asm, string operands>
3831     : I<oops, iops, asm, operands, "", []> {
3832   let Inst{31-30} = sz;
3833   let Inst{29-24} = 0b001000;
3834   let Inst{23}    = o2;
3835   let Inst{22}    = L;
3836   let Inst{21}    = o1;
3837   let Inst{15}    = o0;
3838
3839   let DecoderMethod = "DecodeExclusiveLdStInstruction";
3840 }
3841
3842 // Neither Rs nor Rt2 operands.
3843 class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3844                                dag oops, dag iops, string asm, string operands>
3845     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
3846   bits<5> Rt;
3847   bits<5> Rn;
3848   let Inst{20-16} = 0b11111;
3849   let Unpredictable{20-16} = 0b11111;
3850   let Inst{14-10} = 0b11111;
3851   let Unpredictable{14-10} = 0b11111;
3852   let Inst{9-5} = Rn;
3853   let Inst{4-0} = Rt;
3854
3855   let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
3856 }
3857
3858 // Simple load acquires don't set the exclusive monitor
3859 let mayLoad = 1, mayStore = 0 in
3860 class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3861                   RegisterClass regtype, string asm>
3862     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3863                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3864       Sched<[WriteLD]>;
3865
3866 class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3867                     RegisterClass regtype, string asm>
3868     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3869                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3870       Sched<[WriteLD]>;
3871
3872 class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3873                        RegisterClass regtype, string asm>
3874     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3875                              (outs regtype:$Rt, regtype:$Rt2),
3876                              (ins GPR64sp0:$Rn), asm,
3877                              "\t$Rt, $Rt2, [$Rn]">,
3878       Sched<[WriteLD, WriteLDHi]> {
3879   bits<5> Rt;
3880   bits<5> Rt2;
3881   bits<5> Rn;
3882   let Inst{14-10} = Rt2;
3883   let Inst{9-5} = Rn;
3884   let Inst{4-0} = Rt;
3885
3886   let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
3887 }
3888
3889 // Simple store release operations do not check the exclusive monitor.
3890 let mayLoad = 0, mayStore = 1 in
3891 class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3892                    RegisterClass regtype, string asm>
3893     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
3894                                (ins regtype:$Rt, GPR64sp0:$Rn),
3895                                asm, "\t$Rt, [$Rn]">,
3896       Sched<[WriteST]>;
3897
3898 let mayLoad = 1, mayStore = 1 in
3899 class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3900                      RegisterClass regtype, string asm>
3901     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
3902                              (ins regtype:$Rt, GPR64sp0:$Rn),
3903                              asm, "\t$Ws, $Rt, [$Rn]">,
3904       Sched<[WriteSTX]> {
3905   bits<5> Ws;
3906   bits<5> Rt;
3907   bits<5> Rn;
3908   let Inst{20-16} = Ws;
3909   let Inst{9-5} = Rn;
3910   let Inst{4-0} = Rt;
3911
3912   let Constraints = "@earlyclobber $Ws";
3913   let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
3914 }
3915
3916 class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3917                          RegisterClass regtype, string asm>
3918     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3919                              (outs GPR32:$Ws),
3920                              (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
3921                               asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
3922       Sched<[WriteSTX]> {
3923   bits<5> Ws;
3924   bits<5> Rt;
3925   bits<5> Rt2;
3926   bits<5> Rn;
3927   let Inst{20-16} = Ws;
3928   let Inst{14-10} = Rt2;
3929   let Inst{9-5} = Rn;
3930   let Inst{4-0} = Rt;
3931
3932   let Constraints = "@earlyclobber $Ws";
3933 }
3934
3935 //---
3936 // Exception generation
3937 //---
3938
3939 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3940 class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
3941     : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
3942       Sched<[WriteSys]> {
3943   bits<16> imm;
3944   let Inst{31-24} = 0b11010100;
3945   let Inst{23-21} = op1;
3946   let Inst{20-5}  = imm;
3947   let Inst{4-2}   = 0b000;
3948   let Inst{1-0}   = ll;
3949 }
3950
3951 let Predicates = [HasFPARMv8] in {
3952
3953 //---
3954 // Floating point to integer conversion
3955 //---
3956
3957 class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
3958                       RegisterClass srcType, RegisterClass dstType,
3959                       string asm, list<dag> pattern>
3960     : I<(outs dstType:$Rd), (ins srcType:$Rn),
3961          asm, "\t$Rd, $Rn", "", pattern>,
3962       Sched<[WriteFCvt]> {
3963   bits<5> Rd;
3964   bits<5> Rn;
3965   let Inst{30-29} = 0b00;
3966   let Inst{28-24} = 0b11110;
3967   let Inst{23-22} = type;
3968   let Inst{21}    = 1;
3969   let Inst{20-19} = rmode;
3970   let Inst{18-16} = opcode;
3971   let Inst{15-10} = 0;
3972   let Inst{9-5}   = Rn;
3973   let Inst{4-0}   = Rd;
3974 }
3975
3976 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3977 class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
3978                       RegisterClass srcType, RegisterClass dstType,
3979                       Operand immType, string asm, list<dag> pattern>
3980     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3981          asm, "\t$Rd, $Rn, $scale", "", pattern>,
3982       Sched<[WriteFCvt]> {
3983   bits<5> Rd;
3984   bits<5> Rn;
3985   bits<6> scale;
3986   let Inst{30-29} = 0b00;
3987   let Inst{28-24} = 0b11110;
3988   let Inst{23-22} = type;
3989   let Inst{21}    = 0;
3990   let Inst{20-19} = rmode;
3991   let Inst{18-16} = opcode;
3992   let Inst{15-10} = scale;
3993   let Inst{9-5}   = Rn;
3994   let Inst{4-0}   = Rd;
3995 }
3996
3997 multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
3998            SDPatternOperator OpN> {
3999   // Unscaled half-precision to 32-bit
4000   def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
4001                                      [(set GPR32:$Rd, (OpN FPR16:$Rn))]> {
4002     let Inst{31} = 0; // 32-bit GPR flag
4003     let Predicates = [HasFullFP16];
4004   }
4005
4006   // Unscaled half-precision to 64-bit
4007   def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
4008                                      [(set GPR64:$Rd, (OpN FPR16:$Rn))]> {
4009     let Inst{31} = 1; // 64-bit GPR flag
4010     let Predicates = [HasFullFP16];
4011   }
4012
4013   // Unscaled single-precision to 32-bit
4014   def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
4015                                      [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
4016     let Inst{31} = 0; // 32-bit GPR flag
4017   }
4018
4019   // Unscaled single-precision to 64-bit
4020   def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
4021                                      [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
4022     let Inst{31} = 1; // 64-bit GPR flag
4023   }
4024
4025   // Unscaled double-precision to 32-bit
4026   def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
4027                                      [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4028     let Inst{31} = 0; // 32-bit GPR flag
4029   }
4030
4031   // Unscaled double-precision to 64-bit
4032   def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
4033                                      [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4034     let Inst{31} = 1; // 64-bit GPR flag
4035   }
4036 }
4037
4038 multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
4039                              SDPatternOperator OpN> {
4040   // Scaled half-precision to 32-bit
4041   def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
4042                               fixedpoint_f16_i32, asm,
4043               [(set GPR32:$Rd, (OpN (fmul FPR16:$Rn,
4044                                           fixedpoint_f16_i32:$scale)))]> {
4045     let Inst{31} = 0; // 32-bit GPR flag
4046     let scale{5} = 1;
4047     let Predicates = [HasFullFP16];
4048   }
4049
4050   // Scaled half-precision to 64-bit
4051   def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
4052                               fixedpoint_f16_i64, asm,
4053               [(set GPR64:$Rd, (OpN (fmul FPR16:$Rn,
4054                                           fixedpoint_f16_i64:$scale)))]> {
4055     let Inst{31} = 1; // 64-bit GPR flag
4056     let Predicates = [HasFullFP16];
4057   }
4058
4059   // Scaled single-precision to 32-bit
4060   def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
4061                               fixedpoint_f32_i32, asm,
4062               [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
4063                                           fixedpoint_f32_i32:$scale)))]> {
4064     let Inst{31} = 0; // 32-bit GPR flag
4065     let scale{5} = 1;
4066   }
4067
4068   // Scaled single-precision to 64-bit
4069   def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
4070                               fixedpoint_f32_i64, asm,
4071               [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
4072                                           fixedpoint_f32_i64:$scale)))]> {
4073     let Inst{31} = 1; // 64-bit GPR flag
4074   }
4075
4076   // Scaled double-precision to 32-bit
4077   def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
4078                               fixedpoint_f64_i32, asm,
4079               [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
4080                                           fixedpoint_f64_i32:$scale)))]> {
4081     let Inst{31} = 0; // 32-bit GPR flag
4082     let scale{5} = 1;
4083   }
4084
4085   // Scaled double-precision to 64-bit
4086   def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
4087                               fixedpoint_f64_i64, asm,
4088               [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
4089                                           fixedpoint_f64_i64:$scale)))]> {
4090     let Inst{31} = 1; // 64-bit GPR flag
4091   }
4092 }
4093
4094 //---
4095 // Integer to floating point conversion
4096 //---
4097
4098 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
4099 class BaseIntegerToFP<bit isUnsigned,
4100                       RegisterClass srcType, RegisterClass dstType,
4101                       Operand immType, string asm, list<dag> pattern>
4102     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4103          asm, "\t$Rd, $Rn, $scale", "", pattern>,
4104       Sched<[WriteFCvt]> {
4105   bits<5> Rd;
4106   bits<5> Rn;
4107   bits<6> scale;
4108   let Inst{30-24} = 0b0011110;
4109   let Inst{21-17} = 0b00001;
4110   let Inst{16}    = isUnsigned;
4111   let Inst{15-10} = scale;
4112   let Inst{9-5}   = Rn;
4113   let Inst{4-0}   = Rd;
4114 }
4115
4116 class BaseIntegerToFPUnscaled<bit isUnsigned,
4117                       RegisterClass srcType, RegisterClass dstType,
4118                       ValueType dvt, string asm, SDNode node>
4119     : I<(outs dstType:$Rd), (ins srcType:$Rn),
4120          asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
4121       Sched<[WriteFCvt]> {
4122   bits<5> Rd;
4123   bits<5> Rn;
4124   bits<6> scale;
4125   let Inst{30-24} = 0b0011110;
4126   let Inst{21-17} = 0b10001;
4127   let Inst{16}    = isUnsigned;
4128   let Inst{15-10} = 0b000000;
4129   let Inst{9-5}   = Rn;
4130   let Inst{4-0}   = Rd;
4131 }
4132
4133 multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
4134   // Unscaled
4135   def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
4136     let Inst{31} = 0; // 32-bit GPR flag
4137     let Inst{23-22} = 0b11; // 16-bit FPR flag
4138     let Predicates = [HasFullFP16];
4139   }
4140
4141   def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
4142     let Inst{31} = 0; // 32-bit GPR flag
4143     let Inst{23-22} = 0b00; // 32-bit FPR flag
4144   }
4145
4146   def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
4147     let Inst{31} = 0; // 32-bit GPR flag
4148     let Inst{23-22} = 0b01; // 64-bit FPR flag
4149   }
4150
4151   def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
4152     let Inst{31} = 1; // 64-bit GPR flag
4153     let Inst{23-22} = 0b11; // 16-bit FPR flag
4154     let Predicates = [HasFullFP16];
4155   }
4156
4157   def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
4158     let Inst{31} = 1; // 64-bit GPR flag
4159     let Inst{23-22} = 0b00; // 32-bit FPR flag
4160   }
4161
4162   def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
4163     let Inst{31} = 1; // 64-bit GPR flag
4164     let Inst{23-22} = 0b01; // 64-bit FPR flag
4165   }
4166
4167   // Scaled
4168   def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
4169                              [(set FPR16:$Rd,
4170                                    (fdiv (node GPR32:$Rn),
4171                                          fixedpoint_f16_i32:$scale))]> {
4172     let Inst{31} = 0; // 32-bit GPR flag
4173     let Inst{23-22} = 0b11; // 16-bit FPR flag
4174     let scale{5} = 1;
4175     let Predicates = [HasFullFP16];
4176   }
4177
4178   def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
4179                              [(set FPR32:$Rd,
4180                                    (fdiv (node GPR32:$Rn),
4181                                          fixedpoint_f32_i32:$scale))]> {
4182     let Inst{31} = 0; // 32-bit GPR flag
4183     let Inst{23-22} = 0b00; // 32-bit FPR flag
4184     let scale{5} = 1;
4185   }
4186
4187   def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
4188                              [(set FPR64:$Rd,
4189                                    (fdiv (node GPR32:$Rn),
4190                                          fixedpoint_f64_i32:$scale))]> {
4191     let Inst{31} = 0; // 32-bit GPR flag
4192     let Inst{23-22} = 0b01; // 64-bit FPR flag
4193     let scale{5} = 1;
4194   }
4195
4196   def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
4197                              [(set FPR16:$Rd,
4198                                    (fdiv (node GPR64:$Rn),
4199                                          fixedpoint_f16_i64:$scale))]> {
4200     let Inst{31} = 1; // 64-bit GPR flag
4201     let Inst{23-22} = 0b11; // 16-bit FPR flag
4202     let Predicates = [HasFullFP16];
4203   }
4204
4205   def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
4206                              [(set FPR32:$Rd,
4207                                    (fdiv (node GPR64:$Rn),
4208                                          fixedpoint_f32_i64:$scale))]> {
4209     let Inst{31} = 1; // 64-bit GPR flag
4210     let Inst{23-22} = 0b00; // 32-bit FPR flag
4211   }
4212
4213   def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
4214                              [(set FPR64:$Rd,
4215                                    (fdiv (node GPR64:$Rn),
4216                                          fixedpoint_f64_i64:$scale))]> {
4217     let Inst{31} = 1; // 64-bit GPR flag
4218     let Inst{23-22} = 0b01; // 64-bit FPR flag
4219   }
4220 }
4221
4222 //---
4223 // Unscaled integer <-> floating point conversion (i.e. FMOV)
4224 //---
4225
4226 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4227 class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
4228                       RegisterClass srcType, RegisterClass dstType,
4229                       string asm>
4230     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
4231         // We use COPY_TO_REGCLASS for these bitconvert operations.
4232         // copyPhysReg() expands the resultant COPY instructions after
4233         // regalloc is done. This gives greater freedom for the allocator
4234         // and related passes (coalescing, copy propagation, et. al.) to
4235         // be more effective.
4236         [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
4237       Sched<[WriteFCopy]> {
4238   bits<5> Rd;
4239   bits<5> Rn;
4240   let Inst{30-24} = 0b0011110;
4241   let Inst{21}    = 1;
4242   let Inst{20-19} = rmode;
4243   let Inst{18-16} = opcode;
4244   let Inst{15-10} = 0b000000;
4245   let Inst{9-5}   = Rn;
4246   let Inst{4-0}   = Rd;
4247 }
4248
4249 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4250 class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
4251                      RegisterClass srcType, RegisterOperand dstType, string asm,
4252                      string kind>
4253     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4254         "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
4255       Sched<[WriteFCopy]> {
4256   bits<5> Rd;
4257   bits<5> Rn;
4258   let Inst{30-23} = 0b00111101;
4259   let Inst{21}    = 1;
4260   let Inst{20-19} = rmode;
4261   let Inst{18-16} = opcode;
4262   let Inst{15-10} = 0b000000;
4263   let Inst{9-5}   = Rn;
4264   let Inst{4-0}   = Rd;
4265
4266   let DecoderMethod =  "DecodeFMOVLaneInstruction";
4267 }
4268
4269 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4270 class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
4271                      RegisterOperand srcType, RegisterClass dstType, string asm,
4272                      string kind>
4273     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4274         "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
4275       Sched<[WriteFCopy]> {
4276   bits<5> Rd;
4277   bits<5> Rn;
4278   let Inst{30-23} = 0b00111101;
4279   let Inst{21}    = 1;
4280   let Inst{20-19} = rmode;
4281   let Inst{18-16} = opcode;
4282   let Inst{15-10} = 0b000000;
4283   let Inst{9-5}   = Rn;
4284   let Inst{4-0}   = Rd;
4285
4286   let DecoderMethod =  "DecodeFMOVLaneInstruction";
4287 }
4288
4289
4290 multiclass UnscaledConversion<string asm> {
4291   def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
4292     let Inst{31} = 0; // 32-bit GPR flag
4293     let Inst{23-22} = 0b11; // 16-bit FPR flag
4294     let Predicates = [HasFullFP16];
4295   }
4296
4297   def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
4298     let Inst{31} = 1; // 64-bit GPR flag
4299     let Inst{23-22} = 0b11; // 16-bit FPR flag
4300     let Predicates = [HasFullFP16];
4301   }
4302
4303   def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
4304     let Inst{31} = 0; // 32-bit GPR flag
4305     let Inst{23-22} = 0b00; // 32-bit FPR flag
4306   }
4307
4308   def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
4309     let Inst{31} = 1; // 64-bit GPR flag
4310     let Inst{23-22} = 0b01; // 64-bit FPR flag
4311   }
4312
4313   def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
4314     let Inst{31} = 0; // 32-bit GPR flag
4315     let Inst{23-22} = 0b11; // 16-bit FPR flag
4316     let Predicates = [HasFullFP16];
4317   }
4318
4319   def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
4320     let Inst{31} = 1; // 64-bit GPR flag
4321     let Inst{23-22} = 0b11; // 16-bit FPR flag
4322     let Predicates = [HasFullFP16];
4323   }
4324
4325   def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
4326     let Inst{31} = 0; // 32-bit GPR flag
4327     let Inst{23-22} = 0b00; // 32-bit FPR flag
4328   }
4329
4330   def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
4331     let Inst{31} = 1; // 64-bit GPR flag
4332     let Inst{23-22} = 0b01; // 64-bit FPR flag
4333   }
4334
4335   def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
4336                                              asm, ".d"> {
4337     let Inst{31} = 1;
4338     let Inst{22} = 0;
4339   }
4340
4341   def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
4342                                                asm, ".d"> {
4343     let Inst{31} = 1;
4344     let Inst{22} = 0;
4345   }
4346 }
4347
4348 //---
4349 // Floating point conversion
4350 //---
4351
4352 class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
4353                        RegisterClass srcType, string asm, list<dag> pattern>
4354     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
4355       Sched<[WriteFCvt]> {
4356   bits<5> Rd;
4357   bits<5> Rn;
4358   let Inst{31-24} = 0b00011110;
4359   let Inst{23-22} = type;
4360   let Inst{21-17} = 0b10001;
4361   let Inst{16-15} = opcode;
4362   let Inst{14-10} = 0b10000;
4363   let Inst{9-5}   = Rn;
4364   let Inst{4-0}   = Rd;
4365 }
4366
4367 multiclass FPConversion<string asm> {
4368   // Double-precision to Half-precision
4369   def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
4370                              [(set FPR16:$Rd, (fpround FPR64:$Rn))]>;
4371
4372   // Double-precision to Single-precision
4373   def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
4374                              [(set FPR32:$Rd, (fpround FPR64:$Rn))]>;
4375
4376   // Half-precision to Double-precision
4377   def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
4378                              [(set FPR64:$Rd, (fpextend FPR16:$Rn))]>;
4379
4380   // Half-precision to Single-precision
4381   def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
4382                              [(set FPR32:$Rd, (fpextend FPR16:$Rn))]>;
4383
4384   // Single-precision to Double-precision
4385   def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
4386                              [(set FPR64:$Rd, (fpextend FPR32:$Rn))]>;
4387
4388   // Single-precision to Half-precision
4389   def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
4390                              [(set FPR16:$Rd, (fpround FPR32:$Rn))]>;
4391 }
4392
4393 //---
4394 // Single operand floating point data processing
4395 //---
4396
4397 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4398 class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype,
4399                               ValueType vt, string asm, SDPatternOperator node>
4400     : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
4401          [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
4402       Sched<[WriteF]> {
4403   bits<5> Rd;
4404   bits<5> Rn;
4405   let Inst{31-24} = 0b00011110;
4406   let Inst{21-19} = 0b100;
4407   let Inst{18-15} = opcode;
4408   let Inst{14-10} = 0b10000;
4409   let Inst{9-5}   = Rn;
4410   let Inst{4-0}   = Rd;
4411 }
4412
4413 multiclass SingleOperandFPData<bits<4> opcode, string asm,
4414                                SDPatternOperator node = null_frag> {
4415   def Hr : BaseSingleOperandFPData<opcode, FPR16, f16, asm, node> {
4416     let Inst{23-22} = 0b11; // 16-bit size flag
4417     let Predicates = [HasFullFP16];
4418   }
4419
4420   def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
4421     let Inst{23-22} = 0b00; // 32-bit size flag
4422   }
4423
4424   def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
4425     let Inst{23-22} = 0b01; // 64-bit size flag
4426   }
4427 }
4428
4429 //---
4430 // Two operand floating point data processing
4431 //---
4432
4433 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4434 class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
4435                            string asm, list<dag> pat>
4436     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
4437          asm, "\t$Rd, $Rn, $Rm", "", pat>,
4438       Sched<[WriteF]> {
4439   bits<5> Rd;
4440   bits<5> Rn;
4441   bits<5> Rm;
4442   let Inst{31-24} = 0b00011110;
4443   let Inst{21}    = 1;
4444   let Inst{20-16} = Rm;
4445   let Inst{15-12} = opcode;
4446   let Inst{11-10} = 0b10;
4447   let Inst{9-5}   = Rn;
4448   let Inst{4-0}   = Rd;
4449 }
4450
4451 multiclass TwoOperandFPData<bits<4> opcode, string asm,
4452                             SDPatternOperator node = null_frag> {
4453   def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4454                          [(set (f16 FPR16:$Rd),
4455                                (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
4456     let Inst{23-22} = 0b11; // 16-bit size flag
4457     let Predicates = [HasFullFP16];
4458   }
4459
4460   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4461                          [(set (f32 FPR32:$Rd),
4462                                (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
4463     let Inst{23-22} = 0b00; // 32-bit size flag
4464   }
4465
4466   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4467                          [(set (f64 FPR64:$Rd),
4468                                (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
4469     let Inst{23-22} = 0b01; // 64-bit size flag
4470   }
4471 }
4472
4473 multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
4474   def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4475                   [(set FPR16:$Rd, (fneg (node FPR16:$Rn, (f16 FPR16:$Rm))))]> {
4476     let Inst{23-22} = 0b11; // 16-bit size flag
4477     let Predicates = [HasFullFP16];
4478   }
4479
4480   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4481                   [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
4482     let Inst{23-22} = 0b00; // 32-bit size flag
4483   }
4484
4485   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4486                   [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
4487     let Inst{23-22} = 0b01; // 64-bit size flag
4488   }
4489 }
4490
4491
4492 //---
4493 // Three operand floating point data processing
4494 //---
4495
4496 class BaseThreeOperandFPData<bit isNegated, bit isSub,
4497                              RegisterClass regtype, string asm, list<dag> pat>
4498     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
4499          asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
4500       Sched<[WriteFMul]> {
4501   bits<5> Rd;
4502   bits<5> Rn;
4503   bits<5> Rm;
4504   bits<5> Ra;
4505   let Inst{31-24} = 0b00011111;
4506   let Inst{21}    = isNegated;
4507   let Inst{20-16} = Rm;
4508   let Inst{15}    = isSub;
4509   let Inst{14-10} = Ra;
4510   let Inst{9-5}   = Rn;
4511   let Inst{4-0}   = Rd;
4512 }
4513
4514 multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
4515                               SDPatternOperator node> {
4516   def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
4517             [(set FPR16:$Rd,
4518                   (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
4519     let Inst{23-22} = 0b11; // 16-bit size flag
4520     let Predicates = [HasFullFP16];
4521   }
4522
4523   def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
4524             [(set FPR32:$Rd,
4525                   (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
4526     let Inst{23-22} = 0b00; // 32-bit size flag
4527   }
4528
4529   def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
4530             [(set FPR64:$Rd,
4531                   (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
4532     let Inst{23-22} = 0b01; // 64-bit size flag
4533   }
4534 }
4535
4536 //---
4537 // Floating point data comparisons
4538 //---
4539
4540 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4541 class BaseOneOperandFPComparison<bit signalAllNans,
4542                                  RegisterClass regtype, string asm,
4543                                  list<dag> pat>
4544     : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
4545       Sched<[WriteFCmp]> {
4546   bits<5> Rn;
4547   let Inst{31-24} = 0b00011110;
4548   let Inst{21}    = 1;
4549
4550   let Inst{15-10} = 0b001000;
4551   let Inst{9-5}   = Rn;
4552   let Inst{4}     = signalAllNans;
4553   let Inst{3-0}   = 0b1000;
4554
4555   // Rm should be 0b00000 canonically, but we need to accept any value.
4556   let PostEncoderMethod = "fixOneOperandFPComparison";
4557 }
4558
4559 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4560 class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
4561                                 string asm, list<dag> pat>
4562     : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
4563       Sched<[WriteFCmp]> {
4564   bits<5> Rm;
4565   bits<5> Rn;
4566   let Inst{31-24} = 0b00011110;
4567   let Inst{21}    = 1;
4568   let Inst{20-16} = Rm;
4569   let Inst{15-10} = 0b001000;
4570   let Inst{9-5}   = Rn;
4571   let Inst{4}     = signalAllNans;
4572   let Inst{3-0}   = 0b0000;
4573 }
4574
4575 multiclass FPComparison<bit signalAllNans, string asm,
4576                         SDPatternOperator OpNode = null_frag> {
4577   let Defs = [NZCV] in {
4578   def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
4579       [(OpNode FPR16:$Rn, (f16 FPR16:$Rm)), (implicit NZCV)]> {
4580     let Inst{23-22} = 0b11;
4581     let Predicates = [HasFullFP16];
4582   }
4583
4584   def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
4585       [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
4586     let Inst{23-22} = 0b11;
4587     let Predicates = [HasFullFP16];
4588   }
4589
4590   def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
4591       [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
4592     let Inst{23-22} = 0b00;
4593   }
4594
4595   def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
4596       [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
4597     let Inst{23-22} = 0b00;
4598   }
4599
4600   def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
4601       [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
4602     let Inst{23-22} = 0b01;
4603   }
4604
4605   def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
4606       [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
4607     let Inst{23-22} = 0b01;
4608   }
4609   } // Defs = [NZCV]
4610 }
4611
4612 //---
4613 // Floating point conditional comparisons
4614 //---
4615
4616 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4617 class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
4618                            string mnemonic, list<dag> pat>
4619     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
4620          mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
4621       Sched<[WriteFCmp]> {
4622   let Uses = [NZCV];
4623   let Defs = [NZCV];
4624
4625   bits<5> Rn;
4626   bits<5> Rm;
4627   bits<4> nzcv;
4628   bits<4> cond;
4629
4630   let Inst{31-24} = 0b00011110;
4631   let Inst{21}    = 1;
4632   let Inst{20-16} = Rm;
4633   let Inst{15-12} = cond;
4634   let Inst{11-10} = 0b01;
4635   let Inst{9-5}   = Rn;
4636   let Inst{4}     = signalAllNans;
4637   let Inst{3-0}   = nzcv;
4638 }
4639
4640 multiclass FPCondComparison<bit signalAllNans, string mnemonic,
4641                             SDPatternOperator OpNode = null_frag> {
4642   def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic, []> {
4643     let Inst{23-22} = 0b11;
4644     let Predicates = [HasFullFP16];
4645   }
4646
4647   def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
4648       [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
4649                           (i32 imm:$cond), NZCV))]> {
4650     let Inst{23-22} = 0b00;
4651   }
4652
4653   def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
4654       [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
4655                           (i32 imm:$cond), NZCV))]> {
4656     let Inst{23-22} = 0b01;
4657   }
4658 }
4659
4660 //---
4661 // Floating point conditional select
4662 //---
4663
4664 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
4665     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
4666          asm, "\t$Rd, $Rn, $Rm, $cond", "",
4667          [(set regtype:$Rd,
4668                (AArch64csel (vt regtype:$Rn), regtype:$Rm,
4669                           (i32 imm:$cond), NZCV))]>,
4670       Sched<[WriteF]> {
4671   bits<5> Rd;
4672   bits<5> Rn;
4673   bits<5> Rm;
4674   bits<4> cond;
4675
4676   let Inst{31-24} = 0b00011110;
4677   let Inst{21}    = 1;
4678   let Inst{20-16} = Rm;
4679   let Inst{15-12} = cond;
4680   let Inst{11-10} = 0b11;
4681   let Inst{9-5}   = Rn;
4682   let Inst{4-0}   = Rd;
4683 }
4684
4685 multiclass FPCondSelect<string asm> {
4686   let Uses = [NZCV] in {
4687   def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
4688     let Inst{23-22} = 0b11;
4689     let Predicates = [HasFullFP16];
4690   }
4691
4692   def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
4693     let Inst{23-22} = 0b00;
4694   }
4695
4696   def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
4697     let Inst{23-22} = 0b01;
4698   }
4699   } // Uses = [NZCV]
4700 }
4701
4702 //---
4703 // Floating move immediate
4704 //---
4705
4706 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
4707   : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
4708       [(set regtype:$Rd, fpimmtype:$imm)]>,
4709     Sched<[WriteFImm]> {
4710   bits<5> Rd;
4711   bits<8> imm;
4712   let Inst{31-24} = 0b00011110;
4713   let Inst{21}    = 1;
4714   let Inst{20-13} = imm;
4715   let Inst{12-5}  = 0b10000000;
4716   let Inst{4-0}   = Rd;
4717 }
4718
4719 multiclass FPMoveImmediate<string asm> {
4720   def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
4721     let Inst{23-22} = 0b11;
4722     let Predicates = [HasFullFP16];
4723   }
4724
4725   def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
4726     let Inst{23-22} = 0b00;
4727   }
4728
4729   def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
4730     let Inst{23-22} = 0b01;
4731   }
4732 }
4733 } // end of 'let Predicates = [HasFPARMv8]'
4734
4735 //----------------------------------------------------------------------------
4736 // AdvSIMD
4737 //----------------------------------------------------------------------------
4738
4739 let Predicates = [HasNEON] in {
4740
4741 //----------------------------------------------------------------------------
4742 // AdvSIMD three register vector instructions
4743 //----------------------------------------------------------------------------
4744
4745 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4746 class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
4747                         RegisterOperand regtype, string asm, string kind,
4748                         list<dag> pattern>
4749   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4750       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4751       "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
4752     Sched<[WriteV]> {
4753   bits<5> Rd;
4754   bits<5> Rn;
4755   bits<5> Rm;
4756   let Inst{31}    = 0;
4757   let Inst{30}    = Q;
4758   let Inst{29}    = U;
4759   let Inst{28-24} = 0b01110;
4760   let Inst{23-21} = size;
4761   let Inst{20-16} = Rm;
4762   let Inst{15-11} = opcode;
4763   let Inst{10}    = 1;
4764   let Inst{9-5}   = Rn;
4765   let Inst{4-0}   = Rd;
4766 }
4767
4768 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4769 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
4770                         RegisterOperand regtype, string asm, string kind,
4771                         list<dag> pattern>
4772   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
4773       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4774       "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4775     Sched<[WriteV]> {
4776   bits<5> Rd;
4777   bits<5> Rn;
4778   bits<5> Rm;
4779   let Inst{31}    = 0;
4780   let Inst{30}    = Q;
4781   let Inst{29}    = U;
4782   let Inst{28-24} = 0b01110;
4783   let Inst{23-21} = size;
4784   let Inst{20-16} = Rm;
4785   let Inst{15-11} = opcode;
4786   let Inst{10}    = 1;
4787   let Inst{9-5}   = Rn;
4788   let Inst{4-0}   = Rd;
4789 }
4790
4791 class BaseSIMDThreeSameVectorDot<bit Q, bit U, string asm, string kind1,
4792                                  string kind2, RegisterOperand RegType,
4793                                  ValueType AccumType, ValueType InputType,
4794                                  SDPatternOperator OpNode> :
4795         BaseSIMDThreeSameVectorTied<Q, U, 0b100, 0b10010, RegType, asm, kind1,
4796         [(set (AccumType RegType:$dst),
4797               (OpNode (AccumType RegType:$Rd),
4798                       (InputType RegType:$Rn),
4799                       (InputType RegType:$Rm)))]> {
4800   let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
4801 }
4802
4803 multiclass SIMDThreeSameVectorDot<bit U, string asm, SDPatternOperator OpNode> {
4804   def v8i8  : BaseSIMDThreeSameVectorDot<0, U, asm, ".2s", ".8b", V64,
4805                                          v2i32, v8i8, OpNode>;
4806   def v16i8 : BaseSIMDThreeSameVectorDot<1, U, asm, ".4s", ".16b", V128,
4807                                          v4i32, v16i8, OpNode>;
4808 }
4809
4810 // All operand sizes distinguished in the encoding.
4811 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
4812                                SDPatternOperator OpNode> {
4813   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
4814                                       asm, ".8b",
4815          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4816   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
4817                                       asm, ".16b",
4818          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4819   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
4820                                       asm, ".4h",
4821          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4822   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
4823                                       asm, ".8h",
4824          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4825   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
4826                                       asm, ".2s",
4827          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4828   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
4829                                       asm, ".4s",
4830          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4831   def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
4832                                       asm, ".2d",
4833          [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4834 }
4835
4836 // As above, but D sized elements unsupported.
4837 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
4838                                   SDPatternOperator OpNode> {
4839   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
4840                                       asm, ".8b",
4841         [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
4842   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
4843                                       asm, ".16b",
4844         [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
4845   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
4846                                       asm, ".4h",
4847         [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
4848   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
4849                                       asm, ".8h",
4850         [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
4851   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
4852                                       asm, ".2s",
4853         [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
4854   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
4855                                       asm, ".4s",
4856         [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
4857 }
4858
4859 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
4860                                   SDPatternOperator OpNode> {
4861   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
4862                                       asm, ".8b",
4863       [(set (v8i8 V64:$dst),
4864             (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4865   def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
4866                                       asm, ".16b",
4867       [(set (v16i8 V128:$dst),
4868             (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4869   def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
4870                                       asm, ".4h",
4871       [(set (v4i16 V64:$dst),
4872             (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4873   def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
4874                                       asm, ".8h",
4875       [(set (v8i16 V128:$dst),
4876             (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4877   def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
4878                                       asm, ".2s",
4879       [(set (v2i32 V64:$dst),
4880             (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4881   def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
4882                                       asm, ".4s",
4883       [(set (v4i32 V128:$dst),
4884             (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4885 }
4886
4887 // As above, but only B sized elements supported.
4888 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
4889                                 SDPatternOperator OpNode> {
4890   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
4891                                       asm, ".8b",
4892     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4893   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
4894                                       asm, ".16b",
4895     [(set (v16i8 V128:$Rd),
4896           (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4897 }
4898
4899 // As above, but only floating point elements supported.
4900 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
4901                                  string asm, SDPatternOperator OpNode> {
4902   let Predicates = [HasNEON, HasFullFP16] in {
4903   def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
4904                                       asm, ".4h",
4905         [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
4906   def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
4907                                       asm, ".8h",
4908         [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
4909   } // Predicates = [HasNEON, HasFullFP16]
4910   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
4911                                       asm, ".2s",
4912         [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4913   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
4914                                       asm, ".4s",
4915         [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4916   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
4917                                       asm, ".2d",
4918         [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4919 }
4920
4921 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
4922                                     string asm,
4923                                     SDPatternOperator OpNode> {
4924   let Predicates = [HasNEON, HasFullFP16] in {
4925   def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
4926                                       asm, ".4h",
4927         [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
4928   def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
4929                                       asm, ".8h",
4930         [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
4931   } // Predicates = [HasNEON, HasFullFP16]
4932   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
4933                                       asm, ".2s",
4934         [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4935   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
4936                                       asm, ".4s",
4937         [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4938   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
4939                                       asm, ".2d",
4940         [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4941 }
4942
4943 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
4944                                  string asm, SDPatternOperator OpNode> {
4945   let Predicates = [HasNEON, HasFullFP16] in {
4946   def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
4947                                       asm, ".4h",
4948      [(set (v4f16 V64:$dst),
4949            (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
4950   def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
4951                                       asm, ".8h",
4952      [(set (v8f16 V128:$dst),
4953            (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
4954   } // Predicates = [HasNEON, HasFullFP16]
4955   def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
4956                                       asm, ".2s",
4957      [(set (v2f32 V64:$dst),
4958            (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4959   def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
4960                                       asm, ".4s",
4961      [(set (v4f32 V128:$dst),
4962            (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4963   def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
4964                                       asm, ".2d",
4965      [(set (v2f64 V128:$dst),
4966            (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4967 }
4968
4969 // As above, but D and B sized elements unsupported.
4970 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
4971                                 SDPatternOperator OpNode> {
4972   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
4973                                       asm, ".4h",
4974         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4975   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
4976                                       asm, ".8h",
4977         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4978   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
4979                                       asm, ".2s",
4980         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4981   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
4982                                       asm, ".4s",
4983         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4984 }
4985
4986 // Logical three vector ops share opcode bits, and only use B sized elements.
4987 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
4988                                   SDPatternOperator OpNode = null_frag> {
4989   def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
4990                                      asm, ".8b",
4991                          [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
4992   def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
4993                                      asm, ".16b",
4994                          [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
4995
4996   def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
4997           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4998   def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
4999           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5000   def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
5001           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5002
5003   def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5004       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5005   def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5006       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5007   def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5008       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5009 }
5010
5011 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
5012                                   string asm, SDPatternOperator OpNode> {
5013   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
5014                                      asm, ".8b",
5015              [(set (v8i8 V64:$dst),
5016                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5017   def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
5018                                      asm, ".16b",
5019              [(set (v16i8 V128:$dst),
5020                    (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5021                            (v16i8 V128:$Rm)))]>;
5022
5023   def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5024                            (v4i16 V64:$RHS))),
5025           (!cast<Instruction>(NAME#"v8i8")
5026             V64:$LHS, V64:$MHS, V64:$RHS)>;
5027   def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5028                            (v2i32 V64:$RHS))),
5029           (!cast<Instruction>(NAME#"v8i8")
5030             V64:$LHS, V64:$MHS, V64:$RHS)>;
5031   def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5032                            (v1i64 V64:$RHS))),
5033           (!cast<Instruction>(NAME#"v8i8")
5034             V64:$LHS, V64:$MHS, V64:$RHS)>;
5035
5036   def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5037                            (v8i16 V128:$RHS))),
5038       (!cast<Instruction>(NAME#"v16i8")
5039         V128:$LHS, V128:$MHS, V128:$RHS)>;
5040   def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5041                            (v4i32 V128:$RHS))),
5042       (!cast<Instruction>(NAME#"v16i8")
5043         V128:$LHS, V128:$MHS, V128:$RHS)>;
5044   def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5045                            (v2i64 V128:$RHS))),
5046       (!cast<Instruction>(NAME#"v16i8")
5047         V128:$LHS, V128:$MHS, V128:$RHS)>;
5048 }
5049
5050
5051 //----------------------------------------------------------------------------
5052 // AdvSIMD two register vector instructions.
5053 //----------------------------------------------------------------------------
5054
5055 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5056 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5057                             bits<2> size2, RegisterOperand regtype, string asm,
5058                             string dstkind, string srckind, list<dag> pattern>
5059   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5060       "{\t$Rd" # dstkind # ", $Rn" # srckind #
5061       "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
5062     Sched<[WriteV]> {
5063   bits<5> Rd;
5064   bits<5> Rn;
5065   let Inst{31}    = 0;
5066   let Inst{30}    = Q;
5067   let Inst{29}    = U;
5068   let Inst{28-24} = 0b01110;
5069   let Inst{23-22} = size;
5070   let Inst{21} = 0b1;
5071   let Inst{20-19} = size2;
5072   let Inst{18-17} = 0b00;
5073   let Inst{16-12} = opcode;
5074   let Inst{11-10} = 0b10;
5075   let Inst{9-5}   = Rn;
5076   let Inst{4-0}   = Rd;
5077 }
5078
5079 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5080 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5081                                 bits<2> size2, RegisterOperand regtype,
5082                                 string asm, string dstkind, string srckind,
5083                                 list<dag> pattern>
5084   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
5085       "{\t$Rd" # dstkind # ", $Rn" # srckind #
5086       "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5087     Sched<[WriteV]> {
5088   bits<5> Rd;
5089   bits<5> Rn;
5090   let Inst{31}    = 0;
5091   let Inst{30}    = Q;
5092   let Inst{29}    = U;
5093   let Inst{28-24} = 0b01110;
5094   let Inst{23-22} = size;
5095   let Inst{21} = 0b1;
5096   let Inst{20-19} = size2;
5097   let Inst{18-17} = 0b00;
5098   let Inst{16-12} = opcode;
5099   let Inst{11-10} = 0b10;
5100   let Inst{9-5}   = Rn;
5101   let Inst{4-0}   = Rd;
5102 }
5103
5104 // Supports B, H, and S element sizes.
5105 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
5106                             SDPatternOperator OpNode> {
5107   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5108                                       asm, ".8b", ".8b",
5109                           [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5110   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5111                                       asm, ".16b", ".16b",
5112                           [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5113   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5114                                       asm, ".4h", ".4h",
5115                           [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5116   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5117                                       asm, ".8h", ".8h",
5118                           [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5119   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5120                                       asm, ".2s", ".2s",
5121                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5122   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5123                                       asm, ".4s", ".4s",
5124                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5125 }
5126
5127 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
5128                             RegisterOperand regtype, string asm, string dstkind,
5129                             string srckind, string amount>
5130   : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
5131       "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
5132       "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
5133     Sched<[WriteV]> {
5134   bits<5> Rd;
5135   bits<5> Rn;
5136   let Inst{31}    = 0;
5137   let Inst{30}    = Q;
5138   let Inst{29-24} = 0b101110;
5139   let Inst{23-22} = size;
5140   let Inst{21-10} = 0b100001001110;
5141   let Inst{9-5}   = Rn;
5142   let Inst{4-0}   = Rd;
5143 }
5144
5145 multiclass SIMDVectorLShiftLongBySizeBHS {
5146   let hasSideEffects = 0 in {
5147   def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
5148                                              "shll", ".8h",  ".8b", "8">;
5149   def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
5150                                              "shll2", ".8h", ".16b", "8">;
5151   def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
5152                                              "shll", ".4s",  ".4h", "16">;
5153   def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
5154                                              "shll2", ".4s", ".8h", "16">;
5155   def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
5156                                              "shll", ".2d",  ".2s", "32">;
5157   def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
5158                                              "shll2", ".2d", ".4s", "32">;
5159   }
5160 }
5161
5162 // Supports all element sizes.
5163 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
5164                              SDPatternOperator OpNode> {
5165   def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5166                                       asm, ".4h", ".8b",
5167                [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5168   def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5169                                       asm, ".8h", ".16b",
5170                [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5171   def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5172                                       asm, ".2s", ".4h",
5173                [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5174   def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5175                                       asm, ".4s", ".8h",
5176                [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5177   def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5178                                       asm, ".1d", ".2s",
5179                [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5180   def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5181                                       asm, ".2d", ".4s",
5182                [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5183 }
5184
5185 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
5186                                  SDPatternOperator OpNode> {
5187   def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5188                                           asm, ".4h", ".8b",
5189       [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
5190                                       (v8i8 V64:$Rn)))]>;
5191   def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5192                                           asm, ".8h", ".16b",
5193       [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
5194                                       (v16i8 V128:$Rn)))]>;
5195   def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5196                                           asm, ".2s", ".4h",
5197       [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
5198                                       (v4i16 V64:$Rn)))]>;
5199   def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5200                                           asm, ".4s", ".8h",
5201       [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
5202                                       (v8i16 V128:$Rn)))]>;
5203   def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5204                                           asm, ".1d", ".2s",
5205       [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
5206                                       (v2i32 V64:$Rn)))]>;
5207   def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5208                                           asm, ".2d", ".4s",
5209       [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
5210                                       (v4i32 V128:$Rn)))]>;
5211 }
5212
5213 // Supports all element sizes, except 1xD.
5214 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
5215                                   SDPatternOperator OpNode> {
5216   def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5217                                     asm, ".8b", ".8b",
5218     [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
5219   def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5220                                     asm, ".16b", ".16b",
5221     [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
5222   def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5223                                     asm, ".4h", ".4h",
5224     [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
5225   def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5226                                     asm, ".8h", ".8h",
5227     [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
5228   def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5229                                     asm, ".2s", ".2s",
5230     [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
5231   def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5232                                     asm, ".4s", ".4s",
5233     [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
5234   def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
5235                                     asm, ".2d", ".2d",
5236     [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
5237 }
5238
5239 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
5240                              SDPatternOperator OpNode = null_frag> {
5241   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5242                                 asm, ".8b", ".8b",
5243     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5244   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5245                                 asm, ".16b", ".16b",
5246     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5247   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5248                                 asm, ".4h", ".4h",
5249     [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5250   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5251                                 asm, ".8h", ".8h",
5252     [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5253   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5254                                 asm, ".2s", ".2s",
5255     [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5256   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5257                                 asm, ".4s", ".4s",
5258     [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5259   def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
5260                                 asm, ".2d", ".2d",
5261     [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5262 }
5263
5264
5265 // Supports only B element sizes.
5266 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
5267                           SDPatternOperator OpNode> {
5268   def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
5269                                 asm, ".8b", ".8b",
5270                     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5271   def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
5272                                 asm, ".16b", ".16b",
5273                     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5274
5275 }
5276
5277 // Supports only B and H element sizes.
5278 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
5279                                 SDPatternOperator OpNode> {
5280   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5281                                 asm, ".8b", ".8b",
5282                     [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
5283   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5284                                 asm, ".16b", ".16b",
5285                     [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
5286   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5287                                 asm, ".4h", ".4h",
5288                     [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
5289   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5290                                 asm, ".8h", ".8h",
5291                     [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
5292 }
5293
5294 // Supports only S and D element sizes, uses high bit of the size field
5295 // as an extra opcode bit.
5296 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
5297                            SDPatternOperator OpNode> {
5298   let Predicates = [HasNEON, HasFullFP16] in {
5299   def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5300                                 asm, ".4h", ".4h",
5301                           [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5302   def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5303                                 asm, ".8h", ".8h",
5304                           [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5305   } // Predicates = [HasNEON, HasFullFP16]
5306   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5307                                 asm, ".2s", ".2s",
5308                           [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5309   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5310                                 asm, ".4s", ".4s",
5311                           [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5312   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5313                                 asm, ".2d", ".2d",
5314                           [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5315 }
5316
5317 // Supports only S element size.
5318 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
5319                            SDPatternOperator OpNode> {
5320   def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5321                                 asm, ".2s", ".2s",
5322                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5323   def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5324                                 asm, ".4s", ".4s",
5325                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5326 }
5327
5328
5329 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
5330                            SDPatternOperator OpNode> {
5331   let Predicates = [HasNEON, HasFullFP16] in {
5332   def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5333                                 asm, ".4h", ".4h",
5334                           [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5335   def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5336                                 asm, ".8h", ".8h",
5337                           [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5338   } // Predicates = [HasNEON, HasFullFP16]
5339   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5340                                 asm, ".2s", ".2s",
5341                           [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5342   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5343                                 asm, ".4s", ".4s",
5344                           [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5345   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5346                                 asm, ".2d", ".2d",
5347                           [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5348 }
5349
5350 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
5351                            SDPatternOperator OpNode> {
5352   let Predicates = [HasNEON, HasFullFP16] in {
5353   def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5354                                 asm, ".4h", ".4h",
5355                           [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5356   def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5357                                 asm, ".8h", ".8h",
5358                           [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5359   } // Predicates = [HasNEON, HasFullFP16]
5360   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5361                                 asm, ".2s", ".2s",
5362                           [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5363   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5364                                 asm, ".4s", ".4s",
5365                           [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5366   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5367                                 asm, ".2d", ".2d",
5368                           [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5369 }
5370
5371
5372 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5373                            RegisterOperand inreg, RegisterOperand outreg,
5374                            string asm, string outkind, string inkind,
5375                            list<dag> pattern>
5376   : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
5377       "{\t$Rd" # outkind # ", $Rn" # inkind #
5378       "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
5379     Sched<[WriteV]> {
5380   bits<5> Rd;
5381   bits<5> Rn;
5382   let Inst{31}    = 0;
5383   let Inst{30}    = Q;
5384   let Inst{29}    = U;
5385   let Inst{28-24} = 0b01110;
5386   let Inst{23-22} = size;
5387   let Inst{21-17} = 0b10000;
5388   let Inst{16-12} = opcode;
5389   let Inst{11-10} = 0b10;
5390   let Inst{9-5}   = Rn;
5391   let Inst{4-0}   = Rd;
5392 }
5393
5394 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5395                            RegisterOperand inreg, RegisterOperand outreg,
5396                            string asm, string outkind, string inkind,
5397                            list<dag> pattern>
5398   : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
5399       "{\t$Rd" # outkind # ", $Rn" # inkind #
5400       "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5401     Sched<[WriteV]> {
5402   bits<5> Rd;
5403   bits<5> Rn;
5404   let Inst{31}    = 0;
5405   let Inst{30}    = Q;
5406   let Inst{29}    = U;
5407   let Inst{28-24} = 0b01110;
5408   let Inst{23-22} = size;
5409   let Inst{21-17} = 0b10000;
5410   let Inst{16-12} = opcode;
5411   let Inst{11-10} = 0b10;
5412   let Inst{9-5}   = Rn;
5413   let Inst{4-0}   = Rd;
5414 }
5415
5416 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
5417                               SDPatternOperator OpNode> {
5418   def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
5419                                       asm, ".8b", ".8h",
5420         [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5421   def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
5422                                       asm#"2", ".16b", ".8h", []>;
5423   def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
5424                                       asm, ".4h", ".4s",
5425         [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5426   def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
5427                                       asm#"2", ".8h", ".4s", []>;
5428   def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
5429                                       asm, ".2s", ".2d",
5430         [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5431   def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
5432                                       asm#"2", ".4s", ".2d", []>;
5433
5434   def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
5435             (!cast<Instruction>(NAME # "v16i8")
5436                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5437   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
5438             (!cast<Instruction>(NAME # "v8i16")
5439                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5440   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
5441             (!cast<Instruction>(NAME # "v4i32")
5442                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5443 }
5444
5445 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
5446                            bits<5> opcode, RegisterOperand regtype, string asm,
5447                            string kind, string zero, ValueType dty,
5448                            ValueType sty, SDNode OpNode>
5449   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5450       "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
5451       "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
5452       [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
5453     Sched<[WriteV]> {
5454   bits<5> Rd;
5455   bits<5> Rn;
5456   let Inst{31}    = 0;
5457   let Inst{30}    = Q;
5458   let Inst{29}    = U;
5459   let Inst{28-24} = 0b01110;
5460   let Inst{23-22} = size;
5461   let Inst{21} = 0b1;
5462   let Inst{20-19} = size2;
5463   let Inst{18-17} = 0b00;
5464   let Inst{16-12} = opcode;
5465   let Inst{11-10} = 0b10;
5466   let Inst{9-5}   = Rn;
5467   let Inst{4-0}   = Rd;
5468 }
5469
5470 // Comparisons support all element sizes, except 1xD.
5471 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
5472                             SDNode OpNode> {
5473   def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
5474                                      asm, ".8b", "0",
5475                                      v8i8, v8i8, OpNode>;
5476   def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
5477                                      asm, ".16b", "0",
5478                                      v16i8, v16i8, OpNode>;
5479   def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
5480                                      asm, ".4h", "0",
5481                                      v4i16, v4i16, OpNode>;
5482   def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
5483                                      asm, ".8h", "0",
5484                                      v8i16, v8i16, OpNode>;
5485   def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
5486                                      asm, ".2s", "0",
5487                                      v2i32, v2i32, OpNode>;
5488   def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
5489                                      asm, ".4s", "0",
5490                                      v4i32, v4i32, OpNode>;
5491   def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
5492                                      asm, ".2d", "0",
5493                                      v2i64, v2i64, OpNode>;
5494 }
5495
5496 // FP Comparisons support only S and D element sizes (and H for v8.2a).
5497 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
5498                               string asm, SDNode OpNode> {
5499
5500   let Predicates = [HasNEON, HasFullFP16] in {
5501   def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
5502                                      asm, ".4h", "0.0",
5503                                      v4i16, v4f16, OpNode>;
5504   def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
5505                                      asm, ".8h", "0.0",
5506                                      v8i16, v8f16, OpNode>;
5507   } // Predicates = [HasNEON, HasFullFP16]
5508   def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
5509                                      asm, ".2s", "0.0",
5510                                      v2i32, v2f32, OpNode>;
5511   def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
5512                                      asm, ".4s", "0.0",
5513                                      v4i32, v4f32, OpNode>;
5514   def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
5515                                      asm, ".2d", "0.0",
5516                                      v2i64, v2f64, OpNode>;
5517
5518   let Predicates = [HasNEON, HasFullFP16] in {
5519   def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
5520                   (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
5521   def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
5522                   (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
5523   }
5524   def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
5525                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
5526   def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
5527                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
5528   def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
5529                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5530   let Predicates = [HasNEON, HasFullFP16] in {
5531   def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
5532                   (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
5533   def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
5534                   (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
5535   }
5536   def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
5537                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
5538   def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
5539                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
5540   def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
5541                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5542 }
5543
5544 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5545 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5546                              RegisterOperand outtype, RegisterOperand intype,
5547                              string asm, string VdTy, string VnTy,
5548                              list<dag> pattern>
5549   : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
5550       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
5551     Sched<[WriteV]> {
5552   bits<5> Rd;
5553   bits<5> Rn;
5554   let Inst{31}    = 0;
5555   let Inst{30}    = Q;
5556   let Inst{29}    = U;
5557   let Inst{28-24} = 0b01110;
5558   let Inst{23-22} = size;
5559   let Inst{21-17} = 0b10000;
5560   let Inst{16-12} = opcode;
5561   let Inst{11-10} = 0b10;
5562   let Inst{9-5}   = Rn;
5563   let Inst{4-0}   = Rd;
5564 }
5565
5566 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5567                              RegisterOperand outtype, RegisterOperand intype,
5568                              string asm, string VdTy, string VnTy,
5569                              list<dag> pattern>
5570   : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
5571       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
5572     Sched<[WriteV]> {
5573   bits<5> Rd;
5574   bits<5> Rn;
5575   let Inst{31}    = 0;
5576   let Inst{30}    = Q;
5577   let Inst{29}    = U;
5578   let Inst{28-24} = 0b01110;
5579   let Inst{23-22} = size;
5580   let Inst{21-17} = 0b10000;
5581   let Inst{16-12} = opcode;
5582   let Inst{11-10} = 0b10;
5583   let Inst{9-5}   = Rn;
5584   let Inst{4-0}   = Rd;
5585 }
5586
5587 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
5588   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
5589                                     asm, ".4s", ".4h", []>;
5590   def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
5591                                     asm#"2", ".4s", ".8h", []>;
5592   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
5593                                     asm, ".2d", ".2s", []>;
5594   def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
5595                                     asm#"2", ".2d", ".4s", []>;
5596 }
5597
5598 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
5599   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
5600                                     asm, ".4h", ".4s", []>;
5601   def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
5602                                     asm#"2", ".8h", ".4s", []>;
5603   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5604                                     asm, ".2s", ".2d", []>;
5605   def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5606                                     asm#"2", ".4s", ".2d", []>;
5607 }
5608
5609 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
5610                                      Intrinsic OpNode> {
5611   def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5612                                      asm, ".2s", ".2d",
5613                           [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5614   def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5615                                     asm#"2", ".4s", ".2d", []>;
5616
5617   def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
5618             (!cast<Instruction>(NAME # "v4f32")
5619                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5620 }
5621
5622 //----------------------------------------------------------------------------
5623 // AdvSIMD three register different-size vector instructions.
5624 //----------------------------------------------------------------------------
5625
5626 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5627 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
5628                       RegisterOperand outtype, RegisterOperand intype1,
5629                       RegisterOperand intype2, string asm,
5630                       string outkind, string inkind1, string inkind2,
5631                       list<dag> pattern>
5632   : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
5633       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5634       "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
5635     Sched<[WriteV]> {
5636   bits<5> Rd;
5637   bits<5> Rn;
5638   bits<5> Rm;
5639   let Inst{31}    = 0;
5640   let Inst{30}    = size{0};
5641   let Inst{29}    = U;
5642   let Inst{28-24} = 0b01110;
5643   let Inst{23-22} = size{2-1};
5644   let Inst{21}    = 1;
5645   let Inst{20-16} = Rm;
5646   let Inst{15-12} = opcode;
5647   let Inst{11-10} = 0b00;
5648   let Inst{9-5}   = Rn;
5649   let Inst{4-0}   = Rd;
5650 }
5651
5652 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5653 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
5654                       RegisterOperand outtype, RegisterOperand intype1,
5655                       RegisterOperand intype2, string asm,
5656                       string outkind, string inkind1, string inkind2,
5657                       list<dag> pattern>
5658   : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
5659       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5660       "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5661     Sched<[WriteV]> {
5662   bits<5> Rd;
5663   bits<5> Rn;
5664   bits<5> Rm;
5665   let Inst{31}    = 0;
5666   let Inst{30}    = size{0};
5667   let Inst{29}    = U;
5668   let Inst{28-24} = 0b01110;
5669   let Inst{23-22} = size{2-1};
5670   let Inst{21}    = 1;
5671   let Inst{20-16} = Rm;
5672   let Inst{15-12} = opcode;
5673   let Inst{11-10} = 0b00;
5674   let Inst{9-5}   = Rn;
5675   let Inst{4-0}   = Rd;
5676 }
5677
5678 // FIXME: TableGen doesn't know how to deal with expanded types that also
5679 //        change the element count (in this case, placing the results in
5680 //        the high elements of the result register rather than the low
5681 //        elements). Until that's fixed, we can't code-gen those.
5682 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
5683                                     Intrinsic IntOp> {
5684   def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5685                                                   V64, V128, V128,
5686                                                   asm, ".8b", ".8h", ".8h",
5687      [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5688   def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5689                                                   V128, V128, V128,
5690                                                   asm#"2", ".16b", ".8h", ".8h",
5691      []>;
5692   def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5693                                                   V64, V128, V128,
5694                                                   asm, ".4h", ".4s", ".4s",
5695      [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5696   def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5697                                                   V128, V128, V128,
5698                                                   asm#"2", ".8h", ".4s", ".4s",
5699      []>;
5700   def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5701                                                   V64, V128, V128,
5702                                                   asm, ".2s", ".2d", ".2d",
5703      [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5704   def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5705                                                   V128, V128, V128,
5706                                                   asm#"2", ".4s", ".2d", ".2d",
5707      []>;
5708
5709
5710   // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
5711   // a version attached to an instruction.
5712   def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
5713                                                    (v8i16 V128:$Rm))),
5714             (!cast<Instruction>(NAME # "v8i16_v16i8")
5715                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5716                 V128:$Rn, V128:$Rm)>;
5717   def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
5718                                                     (v4i32 V128:$Rm))),
5719             (!cast<Instruction>(NAME # "v4i32_v8i16")
5720                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5721                 V128:$Rn, V128:$Rm)>;
5722   def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
5723                                                     (v2i64 V128:$Rm))),
5724             (!cast<Instruction>(NAME # "v2i64_v4i32")
5725                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5726                 V128:$Rn, V128:$Rm)>;
5727 }
5728
5729 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
5730                                       Intrinsic IntOp> {
5731   def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5732                                             V128, V64, V64,
5733                                             asm, ".8h", ".8b", ".8b",
5734       [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5735   def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5736                                             V128, V128, V128,
5737                                             asm#"2", ".8h", ".16b", ".16b", []>;
5738   let Predicates = [HasAES] in {
5739     def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
5740                                               V128, V64, V64,
5741                                               asm, ".1q", ".1d", ".1d", []>;
5742     def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
5743                                               V128, V128, V128,
5744                                               asm#"2", ".1q", ".2d", ".2d", []>;
5745   }
5746
5747   def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
5748                           (v8i8 (extract_high_v16i8 V128:$Rm)))),
5749       (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
5750 }
5751
5752 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
5753                                  SDPatternOperator OpNode> {
5754   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5755                                                   V128, V64, V64,
5756                                                   asm, ".4s", ".4h", ".4h",
5757       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5758   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5759                                                   V128, V128, V128,
5760                                                   asm#"2", ".4s", ".8h", ".8h",
5761       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5762                                       (extract_high_v8i16 V128:$Rm)))]>;
5763   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5764                                                   V128, V64, V64,
5765                                                   asm, ".2d", ".2s", ".2s",
5766       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5767   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5768                                                   V128, V128, V128,
5769                                                   asm#"2", ".2d", ".4s", ".4s",
5770       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5771                                       (extract_high_v4i32 V128:$Rm)))]>;
5772 }
5773
5774 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
5775                                   SDPatternOperator OpNode = null_frag> {
5776   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5777                                                   V128, V64, V64,
5778                                                   asm, ".8h", ".8b", ".8b",
5779       [(set (v8i16 V128:$Rd),
5780             (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
5781   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5782                                                  V128, V128, V128,
5783                                                  asm#"2", ".8h", ".16b", ".16b",
5784       [(set (v8i16 V128:$Rd),
5785             (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5786                                 (extract_high_v16i8 V128:$Rm)))))]>;
5787   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5788                                                   V128, V64, V64,
5789                                                   asm, ".4s", ".4h", ".4h",
5790       [(set (v4i32 V128:$Rd),
5791             (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
5792   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5793                                                   V128, V128, V128,
5794                                                   asm#"2", ".4s", ".8h", ".8h",
5795       [(set (v4i32 V128:$Rd),
5796             (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5797                                   (extract_high_v8i16 V128:$Rm)))))]>;
5798   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5799                                                   V128, V64, V64,
5800                                                   asm, ".2d", ".2s", ".2s",
5801       [(set (v2i64 V128:$Rd),
5802             (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
5803   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5804                                                   V128, V128, V128,
5805                                                   asm#"2", ".2d", ".4s", ".4s",
5806       [(set (v2i64 V128:$Rd),
5807             (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5808                                  (extract_high_v4i32 V128:$Rm)))))]>;
5809 }
5810
5811 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
5812                                           string asm,
5813                                           SDPatternOperator OpNode> {
5814   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5815                                                   V128, V64, V64,
5816                                                   asm, ".8h", ".8b", ".8b",
5817     [(set (v8i16 V128:$dst),
5818           (add (v8i16 V128:$Rd),
5819                (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
5820   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5821                                                  V128, V128, V128,
5822                                                  asm#"2", ".8h", ".16b", ".16b",
5823     [(set (v8i16 V128:$dst),
5824           (add (v8i16 V128:$Rd),
5825                (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5826                                    (extract_high_v16i8 V128:$Rm))))))]>;
5827   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5828                                                   V128, V64, V64,
5829                                                   asm, ".4s", ".4h", ".4h",
5830     [(set (v4i32 V128:$dst),
5831           (add (v4i32 V128:$Rd),
5832                (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
5833   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5834                                                   V128, V128, V128,
5835                                                   asm#"2", ".4s", ".8h", ".8h",
5836     [(set (v4i32 V128:$dst),
5837           (add (v4i32 V128:$Rd),
5838                (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5839                                     (extract_high_v8i16 V128:$Rm))))))]>;
5840   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5841                                                   V128, V64, V64,
5842                                                   asm, ".2d", ".2s", ".2s",
5843     [(set (v2i64 V128:$dst),
5844           (add (v2i64 V128:$Rd),
5845                (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
5846   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5847                                                   V128, V128, V128,
5848                                                   asm#"2", ".2d", ".4s", ".4s",
5849     [(set (v2i64 V128:$dst),
5850           (add (v2i64 V128:$Rd),
5851                (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5852                                     (extract_high_v4i32 V128:$Rm))))))]>;
5853 }
5854
5855 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
5856                                   SDPatternOperator OpNode = null_frag> {
5857   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5858                                                   V128, V64, V64,
5859                                                   asm, ".8h", ".8b", ".8b",
5860       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5861   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5862                                                  V128, V128, V128,
5863                                                  asm#"2", ".8h", ".16b", ".16b",
5864       [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
5865                                       (extract_high_v16i8 V128:$Rm)))]>;
5866   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5867                                                   V128, V64, V64,
5868                                                   asm, ".4s", ".4h", ".4h",
5869       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5870   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5871                                                   V128, V128, V128,
5872                                                   asm#"2", ".4s", ".8h", ".8h",
5873       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5874                                       (extract_high_v8i16 V128:$Rm)))]>;
5875   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5876                                                   V128, V64, V64,
5877                                                   asm, ".2d", ".2s", ".2s",
5878       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5879   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5880                                                   V128, V128, V128,
5881                                                   asm#"2", ".2d", ".4s", ".4s",
5882       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5883                                       (extract_high_v4i32 V128:$Rm)))]>;
5884 }
5885
5886 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
5887                                       string asm,
5888                                       SDPatternOperator OpNode> {
5889   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5890                                                   V128, V64, V64,
5891                                                   asm, ".8h", ".8b", ".8b",
5892     [(set (v8i16 V128:$dst),
5893           (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5894   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5895                                                  V128, V128, V128,
5896                                                  asm#"2", ".8h", ".16b", ".16b",
5897     [(set (v8i16 V128:$dst),
5898           (OpNode (v8i16 V128:$Rd),
5899                   (extract_high_v16i8 V128:$Rn),
5900                   (extract_high_v16i8 V128:$Rm)))]>;
5901   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5902                                                   V128, V64, V64,
5903                                                   asm, ".4s", ".4h", ".4h",
5904     [(set (v4i32 V128:$dst),
5905           (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5906   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5907                                                   V128, V128, V128,
5908                                                   asm#"2", ".4s", ".8h", ".8h",
5909     [(set (v4i32 V128:$dst),
5910           (OpNode (v4i32 V128:$Rd),
5911                   (extract_high_v8i16 V128:$Rn),
5912                   (extract_high_v8i16 V128:$Rm)))]>;
5913   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5914                                                   V128, V64, V64,
5915                                                   asm, ".2d", ".2s", ".2s",
5916     [(set (v2i64 V128:$dst),
5917           (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5918   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5919                                                   V128, V128, V128,
5920                                                   asm#"2", ".2d", ".4s", ".4s",
5921     [(set (v2i64 V128:$dst),
5922           (OpNode (v2i64 V128:$Rd),
5923                   (extract_high_v4i32 V128:$Rn),
5924                   (extract_high_v4i32 V128:$Rm)))]>;
5925 }
5926
5927 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
5928                                            SDPatternOperator Accum> {
5929   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5930                                                   V128, V64, V64,
5931                                                   asm, ".4s", ".4h", ".4h",
5932     [(set (v4i32 V128:$dst),
5933           (Accum (v4i32 V128:$Rd),
5934                  (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
5935                                                 (v4i16 V64:$Rm)))))]>;
5936   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5937                                                   V128, V128, V128,
5938                                                   asm#"2", ".4s", ".8h", ".8h",
5939     [(set (v4i32 V128:$dst),
5940           (Accum (v4i32 V128:$Rd),
5941                  (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
5942                                             (extract_high_v8i16 V128:$Rm)))))]>;
5943   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5944                                                   V128, V64, V64,
5945                                                   asm, ".2d", ".2s", ".2s",
5946     [(set (v2i64 V128:$dst),
5947           (Accum (v2i64 V128:$Rd),
5948                  (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
5949                                                 (v2i32 V64:$Rm)))))]>;
5950   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5951                                                   V128, V128, V128,
5952                                                   asm#"2", ".2d", ".4s", ".4s",
5953     [(set (v2i64 V128:$dst),
5954           (Accum (v2i64 V128:$Rd),
5955                  (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
5956                                             (extract_high_v4i32 V128:$Rm)))))]>;
5957 }
5958
5959 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
5960                                   SDPatternOperator OpNode> {
5961   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5962                                                   V128, V128, V64,
5963                                                   asm, ".8h", ".8h", ".8b",
5964        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
5965   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5966                                                   V128, V128, V128,
5967                                                   asm#"2", ".8h", ".8h", ".16b",
5968        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
5969                                        (extract_high_v16i8 V128:$Rm)))]>;
5970   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5971                                                   V128, V128, V64,
5972                                                   asm, ".4s", ".4s", ".4h",
5973        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
5974   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5975                                                   V128, V128, V128,
5976                                                   asm#"2", ".4s", ".4s", ".8h",
5977        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
5978                                        (extract_high_v8i16 V128:$Rm)))]>;
5979   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5980                                                   V128, V128, V64,
5981                                                   asm, ".2d", ".2d", ".2s",
5982        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
5983   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5984                                                   V128, V128, V128,
5985                                                   asm#"2", ".2d", ".2d", ".4s",
5986        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
5987                                        (extract_high_v4i32 V128:$Rm)))]>;
5988 }
5989
5990 //----------------------------------------------------------------------------
5991 // AdvSIMD bitwise extract from vector
5992 //----------------------------------------------------------------------------
5993
5994 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
5995                              string asm, string kind>
5996   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
5997       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
5998       "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
5999       [(set (vty regtype:$Rd),
6000             (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
6001     Sched<[WriteV]> {
6002   bits<5> Rd;
6003   bits<5> Rn;
6004   bits<5> Rm;
6005   bits<4> imm;
6006   let Inst{31}    = 0;
6007   let Inst{30}    = size;
6008   let Inst{29-21} = 0b101110000;
6009   let Inst{20-16} = Rm;
6010   let Inst{15}    = 0;
6011   let Inst{14-11} = imm;
6012   let Inst{10}    = 0;
6013   let Inst{9-5}   = Rn;
6014   let Inst{4-0}   = Rd;
6015 }
6016
6017
6018 multiclass SIMDBitwiseExtract<string asm> {
6019   def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
6020     let imm{3} = 0;
6021   }
6022   def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
6023 }
6024
6025 //----------------------------------------------------------------------------
6026 // AdvSIMD zip vector
6027 //----------------------------------------------------------------------------
6028
6029 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
6030                         string asm, string kind, SDNode OpNode, ValueType valty>
6031   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6032       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
6033       "|" # kind # "\t$Rd, $Rn, $Rm}", "",
6034       [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
6035     Sched<[WriteV]> {
6036   bits<5> Rd;
6037   bits<5> Rn;
6038   bits<5> Rm;
6039   let Inst{31}    = 0;
6040   let Inst{30}    = size{0};
6041   let Inst{29-24} = 0b001110;
6042   let Inst{23-22} = size{2-1};
6043   let Inst{21}    = 0;
6044   let Inst{20-16} = Rm;
6045   let Inst{15}    = 0;
6046   let Inst{14-12} = opc;
6047   let Inst{11-10} = 0b10;
6048   let Inst{9-5}   = Rn;
6049   let Inst{4-0}   = Rd;
6050 }
6051
6052 multiclass SIMDZipVector<bits<3>opc, string asm,
6053                          SDNode OpNode> {
6054   def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
6055       asm, ".8b", OpNode, v8i8>;
6056   def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
6057       asm, ".16b", OpNode, v16i8>;
6058   def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
6059       asm, ".4h", OpNode, v4i16>;
6060   def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
6061       asm, ".8h", OpNode, v8i16>;
6062   def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
6063       asm, ".2s", OpNode, v2i32>;
6064   def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
6065       asm, ".4s", OpNode, v4i32>;
6066   def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
6067       asm, ".2d", OpNode, v2i64>;
6068
6069   def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
6070         (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
6071   def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
6072         (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
6073   def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
6074         (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
6075   def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
6076         (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
6077   def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
6078         (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
6079 }
6080
6081 //----------------------------------------------------------------------------
6082 // AdvSIMD three register scalar instructions
6083 //----------------------------------------------------------------------------
6084
6085 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6086 class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
6087                         RegisterClass regtype, string asm,
6088                         list<dag> pattern>
6089   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6090       "\t$Rd, $Rn, $Rm", "", pattern>,
6091     Sched<[WriteV]> {
6092   bits<5> Rd;
6093   bits<5> Rn;
6094   bits<5> Rm;
6095   let Inst{31-30} = 0b01;
6096   let Inst{29}    = U;
6097   let Inst{28-24} = 0b11110;
6098   let Inst{23-21} = size;
6099   let Inst{20-16} = Rm;
6100   let Inst{15-11} = opcode;
6101   let Inst{10}    = 1;
6102   let Inst{9-5}   = Rn;
6103   let Inst{4-0}   = Rd;
6104 }
6105
6106 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6107 class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
6108                         dag oops, dag iops, string asm,
6109             list<dag> pattern>
6110   : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
6111     Sched<[WriteV]> {
6112   bits<5> Rd;
6113   bits<5> Rn;
6114   bits<5> Rm;
6115   let Inst{31-30} = 0b01;
6116   let Inst{29}    = U;
6117   let Inst{28-24} = 0b11110;
6118   let Inst{23-22} = size;
6119   let Inst{21}    = R;
6120   let Inst{20-16} = Rm;
6121   let Inst{15-11} = opcode;
6122   let Inst{10}    = 1;
6123   let Inst{9-5}   = Rn;
6124   let Inst{4-0}   = Rd;
6125 }
6126
6127 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
6128                             SDPatternOperator OpNode> {
6129   def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6130     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6131 }
6132
6133 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
6134                                SDPatternOperator OpNode> {
6135   def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6136     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6137   def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
6138   def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6139   def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
6140
6141   def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
6142             (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
6143   def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
6144             (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
6145 }
6146
6147 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
6148                              SDPatternOperator OpNode> {
6149   def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
6150                              [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6151   def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6152 }
6153
6154 multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
6155                                  SDPatternOperator OpNode = null_frag> {
6156   def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
6157                                      (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
6158                                      asm, []>;
6159   def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
6160                                      (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
6161                                      asm, []>;
6162 }
6163
6164 multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
6165                              SDPatternOperator OpNode = null_frag> {
6166   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6167     def #NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6168       [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6169     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6170       [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6171     let Predicates = [HasNEON, HasFullFP16] in {
6172     def #NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6173       [(set FPR16:$Rd, (OpNode FPR16:$Rn, FPR16:$Rm))]>;
6174     } // Predicates = [HasNEON, HasFullFP16]
6175   }
6176
6177   def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6178             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6179 }
6180
6181 multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
6182                                 SDPatternOperator OpNode = null_frag> {
6183   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6184     def #NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6185       [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6186     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6187       [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
6188     let Predicates = [HasNEON, HasFullFP16] in {
6189     def #NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6190       []>;
6191     } // Predicates = [HasNEON, HasFullFP16]
6192   }
6193
6194   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6195             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6196 }
6197
6198 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
6199               dag oops, dag iops, string asm, string cstr, list<dag> pat>
6200   : I<oops, iops, asm,
6201       "\t$Rd, $Rn, $Rm", cstr, pat>,
6202     Sched<[WriteV]> {
6203   bits<5> Rd;
6204   bits<5> Rn;
6205   bits<5> Rm;
6206   let Inst{31-30} = 0b01;
6207   let Inst{29}    = U;
6208   let Inst{28-24} = 0b11110;
6209   let Inst{23-22} = size;
6210   let Inst{21}    = 1;
6211   let Inst{20-16} = Rm;
6212   let Inst{15-11} = opcode;
6213   let Inst{10}    = 0;
6214   let Inst{9-5}   = Rn;
6215   let Inst{4-0}   = Rd;
6216 }
6217
6218 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6219 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
6220                                   SDPatternOperator OpNode = null_frag> {
6221   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6222                                       (outs FPR32:$Rd),
6223                                       (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
6224   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6225                                       (outs FPR64:$Rd),
6226                                       (ins FPR32:$Rn, FPR32:$Rm), asm, "",
6227             [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6228 }
6229
6230 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6231 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
6232                                   SDPatternOperator OpNode = null_frag> {
6233   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6234                                       (outs FPR32:$dst),
6235                                       (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
6236                                       asm, "$Rd = $dst", []>;
6237   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6238                                       (outs FPR64:$dst),
6239                                       (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
6240                                       asm, "$Rd = $dst",
6241             [(set (i64 FPR64:$dst),
6242                   (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6243 }
6244
6245 //----------------------------------------------------------------------------
6246 // AdvSIMD two register scalar instructions
6247 //----------------------------------------------------------------------------
6248
6249 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6250 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6251                         RegisterClass regtype, RegisterClass regtype2,
6252                         string asm, list<dag> pat>
6253   : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
6254       "\t$Rd, $Rn", "", pat>,
6255     Sched<[WriteV]> {
6256   bits<5> Rd;
6257   bits<5> Rn;
6258   let Inst{31-30} = 0b01;
6259   let Inst{29}    = U;
6260   let Inst{28-24} = 0b11110;
6261   let Inst{23-22} = size;
6262   let Inst{21} = 0b1;
6263   let Inst{20-19} = size2;
6264   let Inst{18-17} = 0b00;
6265   let Inst{16-12} = opcode;
6266   let Inst{11-10} = 0b10;
6267   let Inst{9-5}   = Rn;
6268   let Inst{4-0}   = Rd;
6269 }
6270
6271 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6272 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
6273                         RegisterClass regtype, RegisterClass regtype2,
6274                         string asm, list<dag> pat>
6275   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
6276       "\t$Rd, $Rn", "$Rd = $dst", pat>,
6277     Sched<[WriteV]> {
6278   bits<5> Rd;
6279   bits<5> Rn;
6280   let Inst{31-30} = 0b01;
6281   let Inst{29}    = U;
6282   let Inst{28-24} = 0b11110;
6283   let Inst{23-22} = size;
6284   let Inst{21-17} = 0b10000;
6285   let Inst{16-12} = opcode;
6286   let Inst{11-10} = 0b10;
6287   let Inst{9-5}   = Rn;
6288   let Inst{4-0}   = Rd;
6289 }
6290
6291
6292 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6293 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6294                         RegisterClass regtype, string asm, string zero>
6295   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6296       "\t$Rd, $Rn, #" # zero, "", []>,
6297     Sched<[WriteV]> {
6298   bits<5> Rd;
6299   bits<5> Rn;
6300   let Inst{31-30} = 0b01;
6301   let Inst{29}    = U;
6302   let Inst{28-24} = 0b11110;
6303   let Inst{23-22} = size;
6304   let Inst{21} = 0b1;
6305   let Inst{20-19} = size2;
6306   let Inst{18-17} = 0b00;
6307   let Inst{16-12} = opcode;
6308   let Inst{11-10} = 0b10;
6309   let Inst{9-5}   = Rn;
6310   let Inst{4-0}   = Rd;
6311 }
6312
6313 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
6314   : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
6315      [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
6316     Sched<[WriteV]> {
6317   bits<5> Rd;
6318   bits<5> Rn;
6319   let Inst{31-17} = 0b011111100110000;
6320   let Inst{16-12} = opcode;
6321   let Inst{11-10} = 0b10;
6322   let Inst{9-5}   = Rn;
6323   let Inst{4-0}   = Rd;
6324 }
6325
6326 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
6327                              SDPatternOperator OpNode> {
6328   def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
6329
6330   def : Pat<(v1i64 (OpNode FPR64:$Rn)),
6331             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6332 }
6333
6334 multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
6335                               SDPatternOperator OpNode> {
6336   def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
6337   def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
6338   let Predicates = [HasNEON, HasFullFP16] in {
6339   def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
6340   }
6341
6342   def : InstAlias<asm # "\t$Rd, $Rn, #0",
6343                   (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
6344   def : InstAlias<asm # "\t$Rd, $Rn, #0",
6345                   (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
6346   let Predicates = [HasNEON, HasFullFP16] in {
6347   def : InstAlias<asm # "\t$Rd, $Rn, #0",
6348                   (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
6349   }
6350
6351   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
6352             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6353 }
6354
6355 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
6356                           SDPatternOperator OpNode = null_frag> {
6357   def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
6358     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
6359
6360   def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
6361             (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
6362 }
6363
6364 multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm> {
6365   def v1i64       : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
6366   def v1i32       : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
6367   let Predicates = [HasNEON, HasFullFP16] in {
6368   def v1f16       : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
6369   }
6370 }
6371
6372 multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
6373                               SDPatternOperator OpNode> {
6374   def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
6375                                 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
6376   def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
6377                                 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
6378   let Predicates = [HasNEON, HasFullFP16] in {
6379   def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
6380                                 [(set FPR16:$Rd, (OpNode (f16 FPR16:$Rn)))]>;
6381   }
6382 }
6383
6384 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
6385                              SDPatternOperator OpNode = null_frag> {
6386   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6387     def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
6388            [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
6389     def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
6390            [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
6391     def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
6392     def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
6393   }
6394
6395   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
6396             (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
6397 }
6398
6399 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
6400                                  Intrinsic OpNode> {
6401   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6402     def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
6403         [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
6404     def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
6405         [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
6406     def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
6407     def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
6408   }
6409
6410   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
6411             (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
6412 }
6413
6414
6415
6416 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6417 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
6418                                  SDPatternOperator OpNode = null_frag> {
6419   def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
6420         [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
6421   def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
6422   def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
6423 }
6424
6425 //----------------------------------------------------------------------------
6426 // AdvSIMD scalar pairwise instructions
6427 //----------------------------------------------------------------------------
6428
6429 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6430 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
6431                         RegisterOperand regtype, RegisterOperand vectype,
6432                         string asm, string kind>
6433   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
6434       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
6435     Sched<[WriteV]> {
6436   bits<5> Rd;
6437   bits<5> Rn;
6438   let Inst{31-30} = 0b01;
6439   let Inst{29}    = U;
6440   let Inst{28-24} = 0b11110;
6441   let Inst{23-22} = size;
6442   let Inst{21-17} = 0b11000;
6443   let Inst{16-12} = opcode;
6444   let Inst{11-10} = 0b10;
6445   let Inst{9-5}   = Rn;
6446   let Inst{4-0}   = Rd;
6447 }
6448
6449 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
6450   def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
6451                                       asm, ".2d">;
6452 }
6453
6454 multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
6455   let Predicates = [HasNEON, HasFullFP16] in {
6456   def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
6457                                       asm, ".2h">;
6458   }
6459   def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
6460                                       asm, ".2s">;
6461   def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
6462                                       asm, ".2d">;
6463 }
6464
6465 //----------------------------------------------------------------------------
6466 // AdvSIMD across lanes instructions
6467 //----------------------------------------------------------------------------
6468
6469 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6470 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
6471                           RegisterClass regtype, RegisterOperand vectype,
6472                           string asm, string kind, list<dag> pattern>
6473   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
6474       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
6475     Sched<[WriteV]> {
6476   bits<5> Rd;
6477   bits<5> Rn;
6478   let Inst{31}    = 0;
6479   let Inst{30}    = Q;
6480   let Inst{29}    = U;
6481   let Inst{28-24} = 0b01110;
6482   let Inst{23-22} = size;
6483   let Inst{21-17} = 0b11000;
6484   let Inst{16-12} = opcode;
6485   let Inst{11-10} = 0b10;
6486   let Inst{9-5}   = Rn;
6487   let Inst{4-0}   = Rd;
6488 }
6489
6490 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
6491                               string asm> {
6492   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
6493                                    asm, ".8b", []>;
6494   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
6495                                    asm, ".16b", []>;
6496   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
6497                                    asm, ".4h", []>;
6498   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
6499                                    asm, ".8h", []>;
6500   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
6501                                    asm, ".4s", []>;
6502 }
6503
6504 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
6505   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
6506                                    asm, ".8b", []>;
6507   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
6508                                    asm, ".16b", []>;
6509   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
6510                                    asm, ".4h", []>;
6511   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
6512                                    asm, ".8h", []>;
6513   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
6514                                    asm, ".4s", []>;
6515 }
6516
6517 multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
6518                             Intrinsic intOp> {
6519   let Predicates = [HasNEON, HasFullFP16] in {
6520   def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
6521                                    asm, ".4h",
6522         [(set FPR16:$Rd, (intOp (v4f16 V64:$Rn)))]>;
6523   def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
6524                                    asm, ".8h",
6525         [(set FPR16:$Rd, (intOp (v8f16 V128:$Rn)))]>;
6526   } // Predicates = [HasNEON, HasFullFP16]
6527   def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
6528                                    asm, ".4s",
6529         [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
6530 }
6531
6532 //----------------------------------------------------------------------------
6533 // AdvSIMD INS/DUP instructions
6534 //----------------------------------------------------------------------------
6535
6536 // FIXME: There has got to be a better way to factor these. ugh.
6537
6538 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
6539                      string operands, string constraints, list<dag> pattern>
6540   : I<outs, ins, asm, operands, constraints, pattern>,
6541     Sched<[WriteV]> {
6542   bits<5> Rd;
6543   bits<5> Rn;
6544   let Inst{31} = 0;
6545   let Inst{30} = Q;
6546   let Inst{29} = op;
6547   let Inst{28-21} = 0b01110000;
6548   let Inst{15} = 0;
6549   let Inst{10} = 1;
6550   let Inst{9-5} = Rn;
6551   let Inst{4-0} = Rd;
6552 }
6553
6554 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
6555                       RegisterOperand vecreg, RegisterClass regtype>
6556   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
6557                    "{\t$Rd" # size # ", $Rn" #
6558                    "|" # size # "\t$Rd, $Rn}", "",
6559                    [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
6560   let Inst{20-16} = imm5;
6561   let Inst{14-11} = 0b0001;
6562 }
6563
6564 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
6565                          ValueType vectype, ValueType insreg,
6566                          RegisterOperand vecreg, Operand idxtype,
6567                          ValueType elttype, SDNode OpNode>
6568   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
6569                    "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
6570                    "|" # dstkind # "\t$Rd, $Rn$idx}", "",
6571                  [(set (vectype vecreg:$Rd),
6572                        (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
6573   let Inst{14-11} = 0b0000;
6574 }
6575
6576 class SIMDDup64FromElement
6577   : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
6578                        VectorIndexD, i64, AArch64duplane64> {
6579   bits<1> idx;
6580   let Inst{20} = idx;
6581   let Inst{19-16} = 0b1000;
6582 }
6583
6584 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
6585                            RegisterOperand vecreg>
6586   : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
6587                        VectorIndexS, i64, AArch64duplane32> {
6588   bits<2> idx;
6589   let Inst{20-19} = idx;
6590   let Inst{18-16} = 0b100;
6591 }
6592
6593 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
6594                            RegisterOperand vecreg>
6595   : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
6596                        VectorIndexH, i64, AArch64duplane16> {
6597   bits<3> idx;
6598   let Inst{20-18} = idx;
6599   let Inst{17-16} = 0b10;
6600 }
6601
6602 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
6603                           RegisterOperand vecreg>
6604   : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
6605                        VectorIndexB, i64, AArch64duplane8> {
6606   bits<4> idx;
6607   let Inst{20-17} = idx;
6608   let Inst{16} = 1;
6609 }
6610
6611 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
6612                   Operand idxtype, string asm, list<dag> pattern>
6613   : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
6614                    "{\t$Rd, $Rn" # size # "$idx" #
6615                    "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
6616   let Inst{14-11} = imm4;
6617 }
6618
6619 class SIMDSMov<bit Q, string size, RegisterClass regtype,
6620                Operand idxtype>
6621   : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
6622 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
6623                Operand idxtype>
6624   : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
6625       [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
6626
6627 class SIMDMovAlias<string asm, string size, Instruction inst,
6628                    RegisterClass regtype, Operand idxtype>
6629     : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
6630                     "|" # size # "\t$dst, $src$idx}",
6631                 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
6632
6633 multiclass SMov {
6634   def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
6635     bits<4> idx;
6636     let Inst{20-17} = idx;
6637     let Inst{16} = 1;
6638   }
6639   def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
6640     bits<4> idx;
6641     let Inst{20-17} = idx;
6642     let Inst{16} = 1;
6643   }
6644   def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
6645     bits<3> idx;
6646     let Inst{20-18} = idx;
6647     let Inst{17-16} = 0b10;
6648   }
6649   def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
6650     bits<3> idx;
6651     let Inst{20-18} = idx;
6652     let Inst{17-16} = 0b10;
6653   }
6654   def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
6655     bits<2> idx;
6656     let Inst{20-19} = idx;
6657     let Inst{18-16} = 0b100;
6658   }
6659 }
6660
6661 multiclass UMov {
6662   def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
6663     bits<4> idx;
6664     let Inst{20-17} = idx;
6665     let Inst{16} = 1;
6666   }
6667   def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
6668     bits<3> idx;
6669     let Inst{20-18} = idx;
6670     let Inst{17-16} = 0b10;
6671   }
6672   def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
6673     bits<2> idx;
6674     let Inst{20-19} = idx;
6675     let Inst{18-16} = 0b100;
6676   }
6677   def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
6678     bits<1> idx;
6679     let Inst{20} = idx;
6680     let Inst{19-16} = 0b1000;
6681   }
6682   def : SIMDMovAlias<"mov", ".s",
6683                      !cast<Instruction>(NAME#"vi32"),
6684                      GPR32, VectorIndexS>;
6685   def : SIMDMovAlias<"mov", ".d",
6686                      !cast<Instruction>(NAME#"vi64"),
6687                      GPR64, VectorIndexD>;
6688 }
6689
6690 class SIMDInsFromMain<string size, ValueType vectype,
6691                       RegisterClass regtype, Operand idxtype>
6692   : BaseSIMDInsDup<1, 0, (outs V128:$dst),
6693                    (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
6694                    "{\t$Rd" # size # "$idx, $Rn" #
6695                    "|" # size # "\t$Rd$idx, $Rn}",
6696                    "$Rd = $dst",
6697             [(set V128:$dst,
6698               (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
6699   let Inst{14-11} = 0b0011;
6700 }
6701
6702 class SIMDInsFromElement<string size, ValueType vectype,
6703                          ValueType elttype, Operand idxtype>
6704   : BaseSIMDInsDup<1, 1, (outs V128:$dst),
6705                    (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
6706                    "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
6707                    "|" # size # "\t$Rd$idx, $Rn$idx2}",
6708                    "$Rd = $dst",
6709          [(set V128:$dst,
6710                (vector_insert
6711                  (vectype V128:$Rd),
6712                  (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
6713                  idxtype:$idx))]>;
6714
6715 class SIMDInsMainMovAlias<string size, Instruction inst,
6716                           RegisterClass regtype, Operand idxtype>
6717     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
6718                         "|" # size #"\t$dst$idx, $src}",
6719                 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
6720 class SIMDInsElementMovAlias<string size, Instruction inst,
6721                              Operand idxtype>
6722     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
6723                       # "|" # size #"\t$dst$idx, $src$idx2}",
6724                 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
6725
6726
6727 multiclass SIMDIns {
6728   def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
6729     bits<4> idx;
6730     let Inst{20-17} = idx;
6731     let Inst{16} = 1;
6732   }
6733   def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
6734     bits<3> idx;
6735     let Inst{20-18} = idx;
6736     let Inst{17-16} = 0b10;
6737   }
6738   def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
6739     bits<2> idx;
6740     let Inst{20-19} = idx;
6741     let Inst{18-16} = 0b100;
6742   }
6743   def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
6744     bits<1> idx;
6745     let Inst{20} = idx;
6746     let Inst{19-16} = 0b1000;
6747   }
6748
6749   def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
6750     bits<4> idx;
6751     bits<4> idx2;
6752     let Inst{20-17} = idx;
6753     let Inst{16} = 1;
6754     let Inst{14-11} = idx2;
6755   }
6756   def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
6757     bits<3> idx;
6758     bits<3> idx2;
6759     let Inst{20-18} = idx;
6760     let Inst{17-16} = 0b10;
6761     let Inst{14-12} = idx2;
6762     let Inst{11} = {?};
6763   }
6764   def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
6765     bits<2> idx;
6766     bits<2> idx2;
6767     let Inst{20-19} = idx;
6768     let Inst{18-16} = 0b100;
6769     let Inst{14-13} = idx2;
6770     let Inst{12-11} = {?,?};
6771   }
6772   def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
6773     bits<1> idx;
6774     bits<1> idx2;
6775     let Inst{20} = idx;
6776     let Inst{19-16} = 0b1000;
6777     let Inst{14} = idx2;
6778     let Inst{13-11} = {?,?,?};
6779   }
6780
6781   // For all forms of the INS instruction, the "mov" mnemonic is the
6782   // preferred alias. Why they didn't just call the instruction "mov" in
6783   // the first place is a very good question indeed...
6784   def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
6785                          GPR32, VectorIndexB>;
6786   def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
6787                          GPR32, VectorIndexH>;
6788   def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
6789                          GPR32, VectorIndexS>;
6790   def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
6791                          GPR64, VectorIndexD>;
6792
6793   def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
6794                          VectorIndexB>;
6795   def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
6796                          VectorIndexH>;
6797   def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
6798                          VectorIndexS>;
6799   def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
6800                          VectorIndexD>;
6801 }
6802
6803 //----------------------------------------------------------------------------
6804 // AdvSIMD TBL/TBX
6805 //----------------------------------------------------------------------------
6806
6807 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6808 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6809                           RegisterOperand listtype, string asm, string kind>
6810   : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
6811        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
6812     Sched<[WriteV]> {
6813   bits<5> Vd;
6814   bits<5> Vn;
6815   bits<5> Vm;
6816   let Inst{31}    = 0;
6817   let Inst{30}    = Q;
6818   let Inst{29-21} = 0b001110000;
6819   let Inst{20-16} = Vm;
6820   let Inst{15}    = 0;
6821   let Inst{14-13} = len;
6822   let Inst{12}    = op;
6823   let Inst{11-10} = 0b00;
6824   let Inst{9-5}   = Vn;
6825   let Inst{4-0}   = Vd;
6826 }
6827
6828 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6829 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6830                           RegisterOperand listtype, string asm, string kind>
6831   : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
6832        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
6833     Sched<[WriteV]> {
6834   bits<5> Vd;
6835   bits<5> Vn;
6836   bits<5> Vm;
6837   let Inst{31}    = 0;
6838   let Inst{30}    = Q;
6839   let Inst{29-21} = 0b001110000;
6840   let Inst{20-16} = Vm;
6841   let Inst{15}    = 0;
6842   let Inst{14-13} = len;
6843   let Inst{12}    = op;
6844   let Inst{11-10} = 0b00;
6845   let Inst{9-5}   = Vn;
6846   let Inst{4-0}   = Vd;
6847 }
6848
6849 class SIMDTableLookupAlias<string asm, Instruction inst,
6850                           RegisterOperand vectype, RegisterOperand listtype>
6851     : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
6852                 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
6853
6854 multiclass SIMDTableLookup<bit op, string asm> {
6855   def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
6856                                       asm, ".8b">;
6857   def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
6858                                       asm, ".8b">;
6859   def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
6860                                       asm, ".8b">;
6861   def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
6862                                       asm, ".8b">;
6863   def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
6864                                       asm, ".16b">;
6865   def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
6866                                       asm, ".16b">;
6867   def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
6868                                       asm, ".16b">;
6869   def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
6870                                       asm, ".16b">;
6871
6872   def : SIMDTableLookupAlias<asm # ".8b",
6873                          !cast<Instruction>(NAME#"v8i8One"),
6874                          V64, VecListOne128>;
6875   def : SIMDTableLookupAlias<asm # ".8b",
6876                          !cast<Instruction>(NAME#"v8i8Two"),
6877                          V64, VecListTwo128>;
6878   def : SIMDTableLookupAlias<asm # ".8b",
6879                          !cast<Instruction>(NAME#"v8i8Three"),
6880                          V64, VecListThree128>;
6881   def : SIMDTableLookupAlias<asm # ".8b",
6882                          !cast<Instruction>(NAME#"v8i8Four"),
6883                          V64, VecListFour128>;
6884   def : SIMDTableLookupAlias<asm # ".16b",
6885                          !cast<Instruction>(NAME#"v16i8One"),
6886                          V128, VecListOne128>;
6887   def : SIMDTableLookupAlias<asm # ".16b",
6888                          !cast<Instruction>(NAME#"v16i8Two"),
6889                          V128, VecListTwo128>;
6890   def : SIMDTableLookupAlias<asm # ".16b",
6891                          !cast<Instruction>(NAME#"v16i8Three"),
6892                          V128, VecListThree128>;
6893   def : SIMDTableLookupAlias<asm # ".16b",
6894                          !cast<Instruction>(NAME#"v16i8Four"),
6895                          V128, VecListFour128>;
6896 }
6897
6898 multiclass SIMDTableLookupTied<bit op, string asm> {
6899   def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
6900                                       asm, ".8b">;
6901   def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
6902                                       asm, ".8b">;
6903   def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
6904                                       asm, ".8b">;
6905   def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
6906                                       asm, ".8b">;
6907   def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
6908                                       asm, ".16b">;
6909   def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
6910                                       asm, ".16b">;
6911   def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
6912                                       asm, ".16b">;
6913   def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
6914                                       asm, ".16b">;
6915
6916   def : SIMDTableLookupAlias<asm # ".8b",
6917                          !cast<Instruction>(NAME#"v8i8One"),
6918                          V64, VecListOne128>;
6919   def : SIMDTableLookupAlias<asm # ".8b",
6920                          !cast<Instruction>(NAME#"v8i8Two"),
6921                          V64, VecListTwo128>;
6922   def : SIMDTableLookupAlias<asm # ".8b",
6923                          !cast<Instruction>(NAME#"v8i8Three"),
6924                          V64, VecListThree128>;
6925   def : SIMDTableLookupAlias<asm # ".8b",
6926                          !cast<Instruction>(NAME#"v8i8Four"),
6927                          V64, VecListFour128>;
6928   def : SIMDTableLookupAlias<asm # ".16b",
6929                          !cast<Instruction>(NAME#"v16i8One"),
6930                          V128, VecListOne128>;
6931   def : SIMDTableLookupAlias<asm # ".16b",
6932                          !cast<Instruction>(NAME#"v16i8Two"),
6933                          V128, VecListTwo128>;
6934   def : SIMDTableLookupAlias<asm # ".16b",
6935                          !cast<Instruction>(NAME#"v16i8Three"),
6936                          V128, VecListThree128>;
6937   def : SIMDTableLookupAlias<asm # ".16b",
6938                          !cast<Instruction>(NAME#"v16i8Four"),
6939                          V128, VecListFour128>;
6940 }
6941
6942
6943 //----------------------------------------------------------------------------
6944 // AdvSIMD scalar CPY
6945 //----------------------------------------------------------------------------
6946 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6947 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
6948                         string kind, Operand idxtype>
6949   : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
6950        "{\t$dst, $src" # kind # "$idx" #
6951        "|\t$dst, $src$idx}", "", []>,
6952     Sched<[WriteV]> {
6953   bits<5> dst;
6954   bits<5> src;
6955   let Inst{31-21} = 0b01011110000;
6956   let Inst{15-10} = 0b000001;
6957   let Inst{9-5}   = src;
6958   let Inst{4-0}   = dst;
6959 }
6960
6961 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
6962       RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
6963     : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
6964                     # "|\t$dst, $src$index}",
6965                 (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
6966
6967
6968 multiclass SIMDScalarCPY<string asm> {
6969   def i8  : BaseSIMDScalarCPY<FPR8,  V128, ".b", VectorIndexB> {
6970     bits<4> idx;
6971     let Inst{20-17} = idx;
6972     let Inst{16} = 1;
6973   }
6974   def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
6975     bits<3> idx;
6976     let Inst{20-18} = idx;
6977     let Inst{17-16} = 0b10;
6978   }
6979   def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
6980     bits<2> idx;
6981     let Inst{20-19} = idx;
6982     let Inst{18-16} = 0b100;
6983   }
6984   def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
6985     bits<1> idx;
6986     let Inst{20} = idx;
6987     let Inst{19-16} = 0b1000;
6988   }
6989
6990   def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
6991                                                           VectorIndexD:$idx)))),
6992             (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
6993
6994   // 'DUP' mnemonic aliases.
6995   def : SIMDScalarCPYAlias<"dup", ".b",
6996                            !cast<Instruction>(NAME#"i8"),
6997                            FPR8, V128, VectorIndexB>;
6998   def : SIMDScalarCPYAlias<"dup", ".h",
6999                            !cast<Instruction>(NAME#"i16"),
7000                            FPR16, V128, VectorIndexH>;
7001   def : SIMDScalarCPYAlias<"dup", ".s",
7002                            !cast<Instruction>(NAME#"i32"),
7003                            FPR32, V128, VectorIndexS>;
7004   def : SIMDScalarCPYAlias<"dup", ".d",
7005                            !cast<Instruction>(NAME#"i64"),
7006                            FPR64, V128, VectorIndexD>;
7007 }
7008
7009 //----------------------------------------------------------------------------
7010 // AdvSIMD modified immediate instructions
7011 //----------------------------------------------------------------------------
7012
7013 class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
7014                           string asm, string op_string,
7015                           string cstr, list<dag> pattern>
7016   : I<oops, iops, asm, op_string, cstr, pattern>,
7017     Sched<[WriteV]> {
7018   bits<5> Rd;
7019   bits<8> imm8;
7020   let Inst{31}    = 0;
7021   let Inst{30}    = Q;
7022   let Inst{29}    = op;
7023   let Inst{28-19} = 0b0111100000;
7024   let Inst{18-16} = imm8{7-5};
7025   let Inst{11} = op2;
7026   let Inst{10} = 1;
7027   let Inst{9-5}   = imm8{4-0};
7028   let Inst{4-0}   = Rd;
7029 }
7030
7031 class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
7032                                 Operand immtype, dag opt_shift_iop,
7033                                 string opt_shift, string asm, string kind,
7034                                 list<dag> pattern>
7035   : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
7036                         !con((ins immtype:$imm8), opt_shift_iop), asm,
7037                         "{\t$Rd" # kind # ", $imm8" # opt_shift #
7038                         "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7039                         "", pattern> {
7040   let DecoderMethod = "DecodeModImmInstruction";
7041 }
7042
7043 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
7044                                 Operand immtype, dag opt_shift_iop,
7045                                 string opt_shift, string asm, string kind,
7046                                 list<dag> pattern>
7047   : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
7048                         !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
7049                         asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
7050                              "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7051                         "$Rd = $dst", pattern> {
7052   let DecoderMethod = "DecodeModImmTiedInstruction";
7053 }
7054
7055 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
7056                                      RegisterOperand vectype, string asm,
7057                                      string kind, list<dag> pattern>
7058   : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7059                               (ins logical_vec_shift:$shift),
7060                               "$shift", asm, kind, pattern> {
7061   bits<2> shift;
7062   let Inst{15}    = b15_b12{1};
7063   let Inst{14-13} = shift;
7064   let Inst{12}    = b15_b12{0};
7065 }
7066
7067 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
7068                                      RegisterOperand vectype, string asm,
7069                                      string kind, list<dag> pattern>
7070   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7071                               (ins logical_vec_shift:$shift),
7072                               "$shift", asm, kind, pattern> {
7073   bits<2> shift;
7074   let Inst{15}    = b15_b12{1};
7075   let Inst{14-13} = shift;
7076   let Inst{12}    = b15_b12{0};
7077 }
7078
7079
7080 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
7081                                          RegisterOperand vectype, string asm,
7082                                          string kind, list<dag> pattern>
7083   : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7084                               (ins logical_vec_hw_shift:$shift),
7085                               "$shift", asm, kind, pattern> {
7086   bits<2> shift;
7087   let Inst{15} = b15_b12{1};
7088   let Inst{14} = 0;
7089   let Inst{13} = shift{0};
7090   let Inst{12} = b15_b12{0};
7091 }
7092
7093 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
7094                                          RegisterOperand vectype, string asm,
7095                                          string kind, list<dag> pattern>
7096   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7097                               (ins logical_vec_hw_shift:$shift),
7098                               "$shift", asm, kind, pattern> {
7099   bits<2> shift;
7100   let Inst{15} = b15_b12{1};
7101   let Inst{14} = 0;
7102   let Inst{13} = shift{0};
7103   let Inst{12} = b15_b12{0};
7104 }
7105
7106 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
7107                                       string asm> {
7108   def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
7109                                                  asm, ".4h", []>;
7110   def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
7111                                                  asm, ".8h", []>;
7112
7113   def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
7114                                              asm, ".2s", []>;
7115   def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
7116                                              asm, ".4s", []>;
7117 }
7118
7119 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
7120                                       bits<2> w_cmode, string asm,
7121                                       SDNode OpNode> {
7122   def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
7123                                                  asm, ".4h",
7124              [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
7125                                              imm0_255:$imm8,
7126                                              (i32 imm:$shift)))]>;
7127   def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
7128                                                  asm, ".8h",
7129              [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
7130                                               imm0_255:$imm8,
7131                                               (i32 imm:$shift)))]>;
7132
7133   def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
7134                                              asm, ".2s",
7135              [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
7136                                              imm0_255:$imm8,
7137                                              (i32 imm:$shift)))]>;
7138   def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
7139                                              asm, ".4s",
7140              [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
7141                                               imm0_255:$imm8,
7142                                               (i32 imm:$shift)))]>;
7143 }
7144
7145 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
7146                              RegisterOperand vectype, string asm,
7147                              string kind, list<dag> pattern>
7148   : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7149                               (ins move_vec_shift:$shift),
7150                               "$shift", asm, kind, pattern> {
7151   bits<1> shift;
7152   let Inst{15-13} = cmode{3-1};
7153   let Inst{12}    = shift;
7154 }
7155
7156 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
7157                                    RegisterOperand vectype,
7158                                    Operand imm_type, string asm,
7159                                    string kind, list<dag> pattern>
7160   : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
7161                               asm, kind, pattern> {
7162   let Inst{15-12} = cmode;
7163 }
7164
7165 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
7166                                    list<dag> pattern>
7167   : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
7168                         "\t$Rd, $imm8", "", pattern> {
7169   let Inst{15-12} = cmode;
7170   let DecoderMethod = "DecodeModImmInstruction";
7171 }
7172
7173 //----------------------------------------------------------------------------
7174 // AdvSIMD indexed element
7175 //----------------------------------------------------------------------------
7176
7177 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7178 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7179                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
7180                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
7181                       string apple_kind, string dst_kind, string lhs_kind,
7182                       string rhs_kind, list<dag> pattern>
7183   : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
7184       asm,
7185       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7186       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
7187     Sched<[WriteV]> {
7188   bits<5> Rd;
7189   bits<5> Rn;
7190   bits<5> Rm;
7191
7192   let Inst{31}    = 0;
7193   let Inst{30}    = Q;
7194   let Inst{29}    = U;
7195   let Inst{28}    = Scalar;
7196   let Inst{27-24} = 0b1111;
7197   let Inst{23-22} = size;
7198   // Bit 21 must be set by the derived class.
7199   let Inst{20-16} = Rm;
7200   let Inst{15-12} = opc;
7201   // Bit 11 must be set by the derived class.
7202   let Inst{10}    = 0;
7203   let Inst{9-5}   = Rn;
7204   let Inst{4-0}   = Rd;
7205 }
7206
7207 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7208 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7209                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
7210                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
7211                       string apple_kind, string dst_kind, string lhs_kind,
7212                       string rhs_kind, list<dag> pattern>
7213   : I<(outs dst_reg:$dst),
7214       (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
7215       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7216       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
7217     Sched<[WriteV]> {
7218   bits<5> Rd;
7219   bits<5> Rn;
7220   bits<5> Rm;
7221
7222   let Inst{31}    = 0;
7223   let Inst{30}    = Q;
7224   let Inst{29}    = U;
7225   let Inst{28}    = Scalar;
7226   let Inst{27-24} = 0b1111;
7227   let Inst{23-22} = size;
7228   // Bit 21 must be set by the derived class.
7229   let Inst{20-16} = Rm;
7230   let Inst{15-12} = opc;
7231   // Bit 11 must be set by the derived class.
7232   let Inst{10}    = 0;
7233   let Inst{9-5}   = Rn;
7234   let Inst{4-0}   = Rd;
7235 }
7236
7237 // ARMv8.2 Index Dot product instructions
7238 class BaseSIMDThreeSameVectorDotIndex<bit Q, bit U, string asm, string dst_kind,
7239                                       string lhs_kind, string rhs_kind,
7240                                       RegisterOperand RegType,
7241                                       ValueType AccumType, ValueType InputType,
7242                                       SDPatternOperator OpNode> :
7243         BaseSIMDIndexedTied<Q, U, 0b0, 0b10, 0b1110, RegType, RegType, V128,
7244                             VectorIndexS, asm, "", dst_kind, lhs_kind, rhs_kind,
7245         [(set (AccumType RegType:$dst),
7246               (AccumType (OpNode (AccumType RegType:$Rd),
7247                                  (InputType RegType:$Rn),
7248                                  (InputType (bitconvert (AccumType
7249                                     (AArch64duplane32 (v4i32 V128:$Rm),
7250                                         VectorIndexS:$idx)))))))]> {
7251   bits<2> idx;
7252   let Inst{21}    = idx{0};  // L
7253   let Inst{11}    = idx{1};  // H
7254 }
7255
7256 multiclass SIMDThreeSameVectorDotIndex<bit U, string asm,
7257                                        SDPatternOperator OpNode> {
7258   def v8i8  : BaseSIMDThreeSameVectorDotIndex<0, U, asm, ".2s", ".8b", ".4b", V64,
7259                                               v2i32, v8i8, OpNode>;
7260   def v16i8 : BaseSIMDThreeSameVectorDotIndex<1, U, asm, ".4s", ".16b", ".4b", V128,
7261                                               v4i32, v16i8, OpNode>;
7262 }
7263
7264 multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
7265                          SDPatternOperator OpNode> {
7266   let Predicates = [HasNEON, HasFullFP16] in {
7267   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
7268                                       V64, V64,
7269                                       V128_lo, VectorIndexH,
7270                                       asm, ".4h", ".4h", ".4h", ".h",
7271     [(set (v4f16 V64:$Rd),
7272         (OpNode (v4f16 V64:$Rn),
7273          (v4f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7274     bits<3> idx;
7275     let Inst{11} = idx{2};
7276     let Inst{21} = idx{1};
7277     let Inst{20} = idx{0};
7278   }
7279
7280   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
7281                                       V128, V128,
7282                                       V128_lo, VectorIndexH,
7283                                       asm, ".8h", ".8h", ".8h", ".h",
7284     [(set (v8f16 V128:$Rd),
7285         (OpNode (v8f16 V128:$Rn),
7286          (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7287     bits<3> idx;
7288     let Inst{11} = idx{2};
7289     let Inst{21} = idx{1};
7290     let Inst{20} = idx{0};
7291   }
7292   } // Predicates = [HasNEON, HasFullFP16]
7293
7294   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7295                                       V64, V64,
7296                                       V128, VectorIndexS,
7297                                       asm, ".2s", ".2s", ".2s", ".s",
7298     [(set (v2f32 V64:$Rd),
7299         (OpNode (v2f32 V64:$Rn),
7300          (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
7301     bits<2> idx;
7302     let Inst{11} = idx{1};
7303     let Inst{21} = idx{0};
7304   }
7305
7306   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7307                                       V128, V128,
7308                                       V128, VectorIndexS,
7309                                       asm, ".4s", ".4s", ".4s", ".s",
7310     [(set (v4f32 V128:$Rd),
7311         (OpNode (v4f32 V128:$Rn),
7312          (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
7313     bits<2> idx;
7314     let Inst{11} = idx{1};
7315     let Inst{21} = idx{0};
7316   }
7317
7318   def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
7319                                       V128, V128,
7320                                       V128, VectorIndexD,
7321                                       asm, ".2d", ".2d", ".2d", ".d",
7322     [(set (v2f64 V128:$Rd),
7323         (OpNode (v2f64 V128:$Rn),
7324          (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
7325     bits<1> idx;
7326     let Inst{11} = idx{0};
7327     let Inst{21} = 0;
7328   }
7329
7330   let Predicates = [HasNEON, HasFullFP16] in {
7331   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
7332                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7333                                       asm, ".h", "", "", ".h",
7334     [(set (f16 FPR16Op:$Rd),
7335           (OpNode (f16 FPR16Op:$Rn),
7336                   (f16 (vector_extract (v8f16 V128_lo:$Rm),
7337                                        VectorIndexH:$idx))))]> {
7338     bits<3> idx;
7339     let Inst{11} = idx{2};
7340     let Inst{21} = idx{1};
7341     let Inst{20} = idx{0};
7342   }
7343   } // Predicates = [HasNEON, HasFullFP16]
7344
7345   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7346                                       FPR32Op, FPR32Op, V128, VectorIndexS,
7347                                       asm, ".s", "", "", ".s",
7348     [(set (f32 FPR32Op:$Rd),
7349           (OpNode (f32 FPR32Op:$Rn),
7350                   (f32 (vector_extract (v4f32 V128:$Rm),
7351                                        VectorIndexS:$idx))))]> {
7352     bits<2> idx;
7353     let Inst{11} = idx{1};
7354     let Inst{21} = idx{0};
7355   }
7356
7357   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
7358                                       FPR64Op, FPR64Op, V128, VectorIndexD,
7359                                       asm, ".d", "", "", ".d",
7360     [(set (f64 FPR64Op:$Rd),
7361           (OpNode (f64 FPR64Op:$Rn),
7362                   (f64 (vector_extract (v2f64 V128:$Rm),
7363                                        VectorIndexD:$idx))))]> {
7364     bits<1> idx;
7365     let Inst{11} = idx{0};
7366     let Inst{21} = 0;
7367   }
7368 }
7369
7370 multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
7371   // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
7372   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
7373                            (AArch64duplane32 (v4f32 V128:$Rm),
7374                                            VectorIndexS:$idx))),
7375             (!cast<Instruction>(INST # v2i32_indexed)
7376                 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7377   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
7378                            (AArch64dup (f32 FPR32Op:$Rm)))),
7379             (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
7380                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
7381
7382
7383   // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
7384   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
7385                            (AArch64duplane32 (v4f32 V128:$Rm),
7386                                            VectorIndexS:$idx))),
7387             (!cast<Instruction>(INST # "v4i32_indexed")
7388                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7389   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
7390                            (AArch64dup (f32 FPR32Op:$Rm)))),
7391             (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
7392                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
7393
7394   // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
7395   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
7396                            (AArch64duplane64 (v2f64 V128:$Rm),
7397                                            VectorIndexD:$idx))),
7398             (!cast<Instruction>(INST # "v2i64_indexed")
7399                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7400   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
7401                            (AArch64dup (f64 FPR64Op:$Rm)))),
7402             (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
7403                 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
7404
7405   // 2 variants for 32-bit scalar version: extract from .2s or from .4s
7406   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
7407                          (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
7408             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
7409                 V128:$Rm, VectorIndexS:$idx)>;
7410   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
7411                          (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
7412             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
7413                 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
7414
7415   // 1 variant for 64-bit scalar version: extract from .1d or from .2d
7416   def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
7417                          (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
7418             (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
7419                 V128:$Rm, VectorIndexD:$idx)>;
7420 }
7421
7422 multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
7423   let Predicates = [HasNEON, HasFullFP16] in {
7424   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
7425                                           V128_lo, VectorIndexH,
7426                                           asm, ".4h", ".4h", ".4h", ".h", []> {
7427     bits<3> idx;
7428     let Inst{11} = idx{2};
7429     let Inst{21} = idx{1};
7430     let Inst{20} = idx{0};
7431   }
7432
7433   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
7434                                           V128, V128,
7435                                           V128_lo, VectorIndexH,
7436                                           asm, ".8h", ".8h", ".8h", ".h", []> {
7437     bits<3> idx;
7438     let Inst{11} = idx{2};
7439     let Inst{21} = idx{1};
7440     let Inst{20} = idx{0};
7441   }
7442   } // Predicates = [HasNEON, HasFullFP16]
7443
7444   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
7445                                           V128, VectorIndexS,
7446                                           asm, ".2s", ".2s", ".2s", ".s", []> {
7447     bits<2> idx;
7448     let Inst{11} = idx{1};
7449     let Inst{21} = idx{0};
7450   }
7451
7452   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7453                                       V128, V128,
7454                                       V128, VectorIndexS,
7455                                       asm, ".4s", ".4s", ".4s", ".s", []> {
7456     bits<2> idx;
7457     let Inst{11} = idx{1};
7458     let Inst{21} = idx{0};
7459   }
7460
7461   def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
7462                                       V128, V128,
7463                                       V128, VectorIndexD,
7464                                       asm, ".2d", ".2d", ".2d", ".d", []> {
7465     bits<1> idx;
7466     let Inst{11} = idx{0};
7467     let Inst{21} = 0;
7468   }
7469
7470   let Predicates = [HasNEON, HasFullFP16] in {
7471   def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
7472                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7473                                       asm, ".h", "", "", ".h", []> {
7474     bits<3> idx;
7475     let Inst{11} = idx{2};
7476     let Inst{21} = idx{1};
7477     let Inst{20} = idx{0};
7478   }
7479   } // Predicates = [HasNEON, HasFullFP16]
7480
7481   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
7482                                       FPR32Op, FPR32Op, V128, VectorIndexS,
7483                                       asm, ".s", "", "", ".s", []> {
7484     bits<2> idx;
7485     let Inst{11} = idx{1};
7486     let Inst{21} = idx{0};
7487   }
7488
7489   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
7490                                       FPR64Op, FPR64Op, V128, VectorIndexD,
7491                                       asm, ".d", "", "", ".d", []> {
7492     bits<1> idx;
7493     let Inst{11} = idx{0};
7494     let Inst{21} = 0;
7495   }
7496 }
7497
7498 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
7499                          SDPatternOperator OpNode> {
7500   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
7501                                       V128_lo, VectorIndexH,
7502                                       asm, ".4h", ".4h", ".4h", ".h",
7503     [(set (v4i16 V64:$Rd),
7504         (OpNode (v4i16 V64:$Rn),
7505          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7506     bits<3> idx;
7507     let Inst{11} = idx{2};
7508     let Inst{21} = idx{1};
7509     let Inst{20} = idx{0};
7510   }
7511
7512   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7513                                       V128, V128,
7514                                       V128_lo, VectorIndexH,
7515                                       asm, ".8h", ".8h", ".8h", ".h",
7516     [(set (v8i16 V128:$Rd),
7517        (OpNode (v8i16 V128:$Rn),
7518          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7519     bits<3> idx;
7520     let Inst{11} = idx{2};
7521     let Inst{21} = idx{1};
7522     let Inst{20} = idx{0};
7523   }
7524
7525   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7526                                       V64, V64,
7527                                       V128, VectorIndexS,
7528                                       asm, ".2s", ".2s", ".2s",  ".s",
7529     [(set (v2i32 V64:$Rd),
7530        (OpNode (v2i32 V64:$Rn),
7531           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7532     bits<2> idx;
7533     let Inst{11} = idx{1};
7534     let Inst{21} = idx{0};
7535   }
7536
7537   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7538                                       V128, V128,
7539                                       V128, VectorIndexS,
7540                                       asm, ".4s", ".4s", ".4s", ".s",
7541     [(set (v4i32 V128:$Rd),
7542        (OpNode (v4i32 V128:$Rn),
7543           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7544     bits<2> idx;
7545     let Inst{11} = idx{1};
7546     let Inst{21} = idx{0};
7547   }
7548
7549   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
7550                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7551                                       asm, ".h", "", "", ".h", []> {
7552     bits<3> idx;
7553     let Inst{11} = idx{2};
7554     let Inst{21} = idx{1};
7555     let Inst{20} = idx{0};
7556   }
7557
7558   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7559                                       FPR32Op, FPR32Op, V128, VectorIndexS,
7560                                       asm, ".s", "", "", ".s",
7561       [(set (i32 FPR32Op:$Rd),
7562             (OpNode FPR32Op:$Rn,
7563                     (i32 (vector_extract (v4i32 V128:$Rm),
7564                                          VectorIndexS:$idx))))]> {
7565     bits<2> idx;
7566     let Inst{11} = idx{1};
7567     let Inst{21} = idx{0};
7568   }
7569 }
7570
7571 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
7572                                SDPatternOperator OpNode> {
7573   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7574                                       V64, V64,
7575                                       V128_lo, VectorIndexH,
7576                                       asm, ".4h", ".4h", ".4h", ".h",
7577     [(set (v4i16 V64:$Rd),
7578         (OpNode (v4i16 V64:$Rn),
7579          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7580     bits<3> idx;
7581     let Inst{11} = idx{2};
7582     let Inst{21} = idx{1};
7583     let Inst{20} = idx{0};
7584   }
7585
7586   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7587                                       V128, V128,
7588                                       V128_lo, VectorIndexH,
7589                                       asm, ".8h", ".8h", ".8h", ".h",
7590     [(set (v8i16 V128:$Rd),
7591        (OpNode (v8i16 V128:$Rn),
7592          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7593     bits<3> idx;
7594     let Inst{11} = idx{2};
7595     let Inst{21} = idx{1};
7596     let Inst{20} = idx{0};
7597   }
7598
7599   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7600                                       V64, V64,
7601                                       V128, VectorIndexS,
7602                                       asm, ".2s", ".2s", ".2s", ".s",
7603     [(set (v2i32 V64:$Rd),
7604        (OpNode (v2i32 V64:$Rn),
7605           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7606     bits<2> idx;
7607     let Inst{11} = idx{1};
7608     let Inst{21} = idx{0};
7609   }
7610
7611   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7612                                       V128, V128,
7613                                       V128, VectorIndexS,
7614                                       asm, ".4s", ".4s", ".4s", ".s",
7615     [(set (v4i32 V128:$Rd),
7616        (OpNode (v4i32 V128:$Rn),
7617           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7618     bits<2> idx;
7619     let Inst{11} = idx{1};
7620     let Inst{21} = idx{0};
7621   }
7622 }
7623
7624 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
7625                                    SDPatternOperator OpNode> {
7626   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
7627                                           V128_lo, VectorIndexH,
7628                                           asm, ".4h", ".4h", ".4h", ".h",
7629     [(set (v4i16 V64:$dst),
7630         (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
7631          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7632     bits<3> idx;
7633     let Inst{11} = idx{2};
7634     let Inst{21} = idx{1};
7635     let Inst{20} = idx{0};
7636   }
7637
7638   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7639                                       V128, V128,
7640                                       V128_lo, VectorIndexH,
7641                                       asm, ".8h", ".8h", ".8h", ".h",
7642     [(set (v8i16 V128:$dst),
7643        (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7644          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7645     bits<3> idx;
7646     let Inst{11} = idx{2};
7647     let Inst{21} = idx{1};
7648     let Inst{20} = idx{0};
7649   }
7650
7651   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7652                                       V64, V64,
7653                                       V128, VectorIndexS,
7654                                       asm, ".2s", ".2s", ".2s", ".s",
7655     [(set (v2i32 V64:$dst),
7656        (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7657           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7658     bits<2> idx;
7659     let Inst{11} = idx{1};
7660     let Inst{21} = idx{0};
7661   }
7662
7663   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7664                                       V128, V128,
7665                                       V128, VectorIndexS,
7666                                       asm, ".4s", ".4s", ".4s", ".s",
7667     [(set (v4i32 V128:$dst),
7668        (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7669           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7670     bits<2> idx;
7671     let Inst{11} = idx{1};
7672     let Inst{21} = idx{0};
7673   }
7674 }
7675
7676 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
7677                              SDPatternOperator OpNode> {
7678   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7679                                       V128, V64,
7680                                       V128_lo, VectorIndexH,
7681                                       asm, ".4s", ".4s", ".4h", ".h",
7682     [(set (v4i32 V128:$Rd),
7683         (OpNode (v4i16 V64:$Rn),
7684          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7685     bits<3> idx;
7686     let Inst{11} = idx{2};
7687     let Inst{21} = idx{1};
7688     let Inst{20} = idx{0};
7689   }
7690
7691   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7692                                       V128, V128,
7693                                       V128_lo, VectorIndexH,
7694                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7695     [(set (v4i32 V128:$Rd),
7696           (OpNode (extract_high_v8i16 V128:$Rn),
7697                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7698                                                       VectorIndexH:$idx))))]> {
7699
7700     bits<3> idx;
7701     let Inst{11} = idx{2};
7702     let Inst{21} = idx{1};
7703     let Inst{20} = idx{0};
7704   }
7705
7706   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7707                                       V128, V64,
7708                                       V128, VectorIndexS,
7709                                       asm, ".2d", ".2d", ".2s", ".s",
7710     [(set (v2i64 V128:$Rd),
7711         (OpNode (v2i32 V64:$Rn),
7712          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7713     bits<2> idx;
7714     let Inst{11} = idx{1};
7715     let Inst{21} = idx{0};
7716   }
7717
7718   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7719                                       V128, V128,
7720                                       V128, VectorIndexS,
7721                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7722     [(set (v2i64 V128:$Rd),
7723           (OpNode (extract_high_v4i32 V128:$Rn),
7724                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7725                                                       VectorIndexS:$idx))))]> {
7726     bits<2> idx;
7727     let Inst{11} = idx{1};
7728     let Inst{21} = idx{0};
7729   }
7730
7731   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
7732                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
7733                                       asm, ".h", "", "", ".h", []> {
7734     bits<3> idx;
7735     let Inst{11} = idx{2};
7736     let Inst{21} = idx{1};
7737     let Inst{20} = idx{0};
7738   }
7739
7740   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7741                                       FPR64Op, FPR32Op, V128, VectorIndexS,
7742                                       asm, ".s", "", "", ".s", []> {
7743     bits<2> idx;
7744     let Inst{11} = idx{1};
7745     let Inst{21} = idx{0};
7746   }
7747 }
7748
7749 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
7750                                        SDPatternOperator Accum> {
7751   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
7752                                       V128, V64,
7753                                       V128_lo, VectorIndexH,
7754                                       asm, ".4s", ".4s", ".4h", ".h",
7755     [(set (v4i32 V128:$dst),
7756           (Accum (v4i32 V128:$Rd),
7757                  (v4i32 (int_aarch64_neon_sqdmull
7758                              (v4i16 V64:$Rn),
7759                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7760                                                     VectorIndexH:$idx))))))]> {
7761     bits<3> idx;
7762     let Inst{11} = idx{2};
7763     let Inst{21} = idx{1};
7764     let Inst{20} = idx{0};
7765   }
7766
7767   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
7768   // intermediate EXTRACT_SUBREG would be untyped.
7769   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
7770                 (i32 (vector_extract (v4i32
7771                          (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
7772                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7773                                                     VectorIndexH:$idx)))),
7774                          (i64 0))))),
7775             (EXTRACT_SUBREG
7776                 (!cast<Instruction>(NAME # v4i16_indexed)
7777                     (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
7778                     V128_lo:$Rm, VectorIndexH:$idx),
7779                 ssub)>;
7780
7781   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7782                                       V128, V128,
7783                                       V128_lo, VectorIndexH,
7784                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7785     [(set (v4i32 V128:$dst),
7786           (Accum (v4i32 V128:$Rd),
7787                  (v4i32 (int_aarch64_neon_sqdmull
7788                             (extract_high_v8i16 V128:$Rn),
7789                             (extract_high_v8i16
7790                                 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7791                                                 VectorIndexH:$idx))))))]> {
7792     bits<3> idx;
7793     let Inst{11} = idx{2};
7794     let Inst{21} = idx{1};
7795     let Inst{20} = idx{0};
7796   }
7797
7798   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7799                                       V128, V64,
7800                                       V128, VectorIndexS,
7801                                       asm, ".2d", ".2d", ".2s", ".s",
7802     [(set (v2i64 V128:$dst),
7803         (Accum (v2i64 V128:$Rd),
7804                (v2i64 (int_aarch64_neon_sqdmull
7805                           (v2i32 V64:$Rn),
7806                           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
7807                                                  VectorIndexS:$idx))))))]> {
7808     bits<2> idx;
7809     let Inst{11} = idx{1};
7810     let Inst{21} = idx{0};
7811   }
7812
7813   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7814                                       V128, V128,
7815                                       V128, VectorIndexS,
7816                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7817     [(set (v2i64 V128:$dst),
7818           (Accum (v2i64 V128:$Rd),
7819                  (v2i64 (int_aarch64_neon_sqdmull
7820                             (extract_high_v4i32 V128:$Rn),
7821                             (extract_high_v4i32
7822                                 (AArch64duplane32 (v4i32 V128:$Rm),
7823                                                 VectorIndexS:$idx))))))]> {
7824     bits<2> idx;
7825     let Inst{11} = idx{1};
7826     let Inst{21} = idx{0};
7827   }
7828
7829   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
7830                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
7831                                       asm, ".h", "", "", ".h", []> {
7832     bits<3> idx;
7833     let Inst{11} = idx{2};
7834     let Inst{21} = idx{1};
7835     let Inst{20} = idx{0};
7836   }
7837
7838
7839   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
7840                                       FPR64Op, FPR32Op, V128, VectorIndexS,
7841                                       asm, ".s", "", "", ".s",
7842     [(set (i64 FPR64Op:$dst),
7843           (Accum (i64 FPR64Op:$Rd),
7844                  (i64 (int_aarch64_neon_sqdmulls_scalar
7845                             (i32 FPR32Op:$Rn),
7846                             (i32 (vector_extract (v4i32 V128:$Rm),
7847                                                  VectorIndexS:$idx))))))]> {
7848
7849     bits<2> idx;
7850     let Inst{11} = idx{1};
7851     let Inst{21} = idx{0};
7852   }
7853 }
7854
7855 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
7856                                    SDPatternOperator OpNode> {
7857   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7858   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7859                                       V128, V64,
7860                                       V128_lo, VectorIndexH,
7861                                       asm, ".4s", ".4s", ".4h", ".h",
7862     [(set (v4i32 V128:$Rd),
7863         (OpNode (v4i16 V64:$Rn),
7864          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7865     bits<3> idx;
7866     let Inst{11} = idx{2};
7867     let Inst{21} = idx{1};
7868     let Inst{20} = idx{0};
7869   }
7870
7871   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7872                                       V128, V128,
7873                                       V128_lo, VectorIndexH,
7874                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7875     [(set (v4i32 V128:$Rd),
7876           (OpNode (extract_high_v8i16 V128:$Rn),
7877                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7878                                                       VectorIndexH:$idx))))]> {
7879
7880     bits<3> idx;
7881     let Inst{11} = idx{2};
7882     let Inst{21} = idx{1};
7883     let Inst{20} = idx{0};
7884   }
7885
7886   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7887                                       V128, V64,
7888                                       V128, VectorIndexS,
7889                                       asm, ".2d", ".2d", ".2s", ".s",
7890     [(set (v2i64 V128:$Rd),
7891         (OpNode (v2i32 V64:$Rn),
7892          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7893     bits<2> idx;
7894     let Inst{11} = idx{1};
7895     let Inst{21} = idx{0};
7896   }
7897
7898   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7899                                       V128, V128,
7900                                       V128, VectorIndexS,
7901                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7902     [(set (v2i64 V128:$Rd),
7903           (OpNode (extract_high_v4i32 V128:$Rn),
7904                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7905                                                       VectorIndexS:$idx))))]> {
7906     bits<2> idx;
7907     let Inst{11} = idx{1};
7908     let Inst{21} = idx{0};
7909   }
7910   }
7911 }
7912
7913 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
7914                                        SDPatternOperator OpNode> {
7915   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7916   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
7917                                       V128, V64,
7918                                       V128_lo, VectorIndexH,
7919                                       asm, ".4s", ".4s", ".4h", ".h",
7920     [(set (v4i32 V128:$dst),
7921         (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
7922          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7923     bits<3> idx;
7924     let Inst{11} = idx{2};
7925     let Inst{21} = idx{1};
7926     let Inst{20} = idx{0};
7927   }
7928
7929   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7930                                       V128, V128,
7931                                       V128_lo, VectorIndexH,
7932                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7933     [(set (v4i32 V128:$dst),
7934           (OpNode (v4i32 V128:$Rd),
7935                   (extract_high_v8i16 V128:$Rn),
7936                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7937                                                       VectorIndexH:$idx))))]> {
7938     bits<3> idx;
7939     let Inst{11} = idx{2};
7940     let Inst{21} = idx{1};
7941     let Inst{20} = idx{0};
7942   }
7943
7944   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7945                                       V128, V64,
7946                                       V128, VectorIndexS,
7947                                       asm, ".2d", ".2d", ".2s", ".s",
7948     [(set (v2i64 V128:$dst),
7949         (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
7950          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7951     bits<2> idx;
7952     let Inst{11} = idx{1};
7953     let Inst{21} = idx{0};
7954   }
7955
7956   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7957                                       V128, V128,
7958                                       V128, VectorIndexS,
7959                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7960     [(set (v2i64 V128:$dst),
7961           (OpNode (v2i64 V128:$Rd),
7962                   (extract_high_v4i32 V128:$Rn),
7963                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7964                                                       VectorIndexS:$idx))))]> {
7965     bits<2> idx;
7966     let Inst{11} = idx{1};
7967     let Inst{21} = idx{0};
7968   }
7969   }
7970 }
7971
7972 //----------------------------------------------------------------------------
7973 // AdvSIMD scalar shift by immediate
7974 //----------------------------------------------------------------------------
7975
7976 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7977 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
7978                      RegisterClass regtype1, RegisterClass regtype2,
7979                      Operand immtype, string asm, list<dag> pattern>
7980   : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
7981       asm, "\t$Rd, $Rn, $imm", "", pattern>,
7982     Sched<[WriteV]> {
7983   bits<5> Rd;
7984   bits<5> Rn;
7985   bits<7> imm;
7986   let Inst{31-30} = 0b01;
7987   let Inst{29}    = U;
7988   let Inst{28-23} = 0b111110;
7989   let Inst{22-16} = fixed_imm;
7990   let Inst{15-11} = opc;
7991   let Inst{10}    = 1;
7992   let Inst{9-5} = Rn;
7993   let Inst{4-0} = Rd;
7994 }
7995
7996 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7997 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
7998                      RegisterClass regtype1, RegisterClass regtype2,
7999                      Operand immtype, string asm, list<dag> pattern>
8000   : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
8001       asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
8002     Sched<[WriteV]> {
8003   bits<5> Rd;
8004   bits<5> Rn;
8005   bits<7> imm;
8006   let Inst{31-30} = 0b01;
8007   let Inst{29}    = U;
8008   let Inst{28-23} = 0b111110;
8009   let Inst{22-16} = fixed_imm;
8010   let Inst{15-11} = opc;
8011   let Inst{10}    = 1;
8012   let Inst{9-5} = Rn;
8013   let Inst{4-0} = Rd;
8014 }
8015
8016
8017 multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
8018   let Predicates = [HasNEON, HasFullFP16] in {
8019   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8020                               FPR16, FPR16, vecshiftR16, asm, []> {
8021     let Inst{19-16} = imm{3-0};
8022   }
8023   } // Predicates = [HasNEON, HasFullFP16]
8024   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8025                               FPR32, FPR32, vecshiftR32, asm, []> {
8026     let Inst{20-16} = imm{4-0};
8027   }
8028   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8029                               FPR64, FPR64, vecshiftR64, asm, []> {
8030     let Inst{21-16} = imm{5-0};
8031   }
8032 }
8033
8034 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
8035                              SDPatternOperator OpNode> {
8036   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8037                               FPR64, FPR64, vecshiftR64, asm,
8038   [(set (i64 FPR64:$Rd),
8039      (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
8040     let Inst{21-16} = imm{5-0};
8041   }
8042
8043   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
8044             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
8045 }
8046
8047 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
8048                                  SDPatternOperator OpNode = null_frag> {
8049   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8050                               FPR64, FPR64, vecshiftR64, asm,
8051   [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
8052                                                    (i32 vecshiftR64:$imm)))]> {
8053     let Inst{21-16} = imm{5-0};
8054   }
8055
8056   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
8057                            (i32 vecshiftR64:$imm))),
8058             (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
8059                                             vecshiftR64:$imm)>;
8060 }
8061
8062 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
8063                              SDPatternOperator OpNode> {
8064   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8065                               FPR64, FPR64, vecshiftL64, asm,
8066     [(set (v1i64 FPR64:$Rd),
8067        (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8068     let Inst{21-16} = imm{5-0};
8069   }
8070 }
8071
8072 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8073 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
8074   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8075                               FPR64, FPR64, vecshiftL64, asm, []> {
8076     let Inst{21-16} = imm{5-0};
8077   }
8078 }
8079
8080 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8081 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
8082                                SDPatternOperator OpNode = null_frag> {
8083   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8084                               FPR8, FPR16, vecshiftR8, asm, []> {
8085     let Inst{18-16} = imm{2-0};
8086   }
8087
8088   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8089                               FPR16, FPR32, vecshiftR16, asm, []> {
8090     let Inst{19-16} = imm{3-0};
8091   }
8092
8093   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8094                               FPR32, FPR64, vecshiftR32, asm,
8095     [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
8096     let Inst{20-16} = imm{4-0};
8097   }
8098 }
8099
8100 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
8101                                 SDPatternOperator OpNode> {
8102   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8103                               FPR8, FPR8, vecshiftL8, asm, []> {
8104     let Inst{18-16} = imm{2-0};
8105   }
8106
8107   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8108                               FPR16, FPR16, vecshiftL16, asm, []> {
8109     let Inst{19-16} = imm{3-0};
8110   }
8111
8112   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8113                               FPR32, FPR32, vecshiftL32, asm,
8114     [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
8115     let Inst{20-16} = imm{4-0};
8116   }
8117
8118   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8119                               FPR64, FPR64, vecshiftL64, asm,
8120     [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8121     let Inst{21-16} = imm{5-0};
8122   }
8123
8124   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
8125             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
8126 }
8127
8128 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
8129   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8130                               FPR8, FPR8, vecshiftR8, asm, []> {
8131     let Inst{18-16} = imm{2-0};
8132   }
8133
8134   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8135                               FPR16, FPR16, vecshiftR16, asm, []> {
8136     let Inst{19-16} = imm{3-0};
8137   }
8138
8139   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8140                               FPR32, FPR32, vecshiftR32, asm, []> {
8141     let Inst{20-16} = imm{4-0};
8142   }
8143
8144   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8145                               FPR64, FPR64, vecshiftR64, asm, []> {
8146     let Inst{21-16} = imm{5-0};
8147   }
8148 }
8149
8150 //----------------------------------------------------------------------------
8151 // AdvSIMD vector x indexed element
8152 //----------------------------------------------------------------------------
8153
8154 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8155 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
8156                      RegisterOperand dst_reg, RegisterOperand src_reg,
8157                      Operand immtype,
8158                      string asm, string dst_kind, string src_kind,
8159                      list<dag> pattern>
8160   : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
8161       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
8162            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
8163     Sched<[WriteV]> {
8164   bits<5> Rd;
8165   bits<5> Rn;
8166   let Inst{31}    = 0;
8167   let Inst{30}    = Q;
8168   let Inst{29}    = U;
8169   let Inst{28-23} = 0b011110;
8170   let Inst{22-16} = fixed_imm;
8171   let Inst{15-11} = opc;
8172   let Inst{10}    = 1;
8173   let Inst{9-5}   = Rn;
8174   let Inst{4-0}   = Rd;
8175 }
8176
8177 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8178 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
8179                      RegisterOperand vectype1, RegisterOperand vectype2,
8180                      Operand immtype,
8181                      string asm, string dst_kind, string src_kind,
8182                      list<dag> pattern>
8183   : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
8184       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
8185            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
8186     Sched<[WriteV]> {
8187   bits<5> Rd;
8188   bits<5> Rn;
8189   let Inst{31}    = 0;
8190   let Inst{30}    = Q;
8191   let Inst{29}    = U;
8192   let Inst{28-23} = 0b011110;
8193   let Inst{22-16} = fixed_imm;
8194   let Inst{15-11} = opc;
8195   let Inst{10}    = 1;
8196   let Inst{9-5}   = Rn;
8197   let Inst{4-0}   = Rd;
8198 }
8199
8200 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
8201                               Intrinsic OpNode> {
8202   let Predicates = [HasNEON, HasFullFP16] in {
8203   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8204                                   V64, V64, vecshiftR16,
8205                                   asm, ".4h", ".4h",
8206       [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
8207     bits<4> imm;
8208     let Inst{19-16} = imm;
8209   }
8210
8211   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8212                                   V128, V128, vecshiftR16,
8213                                   asm, ".8h", ".8h",
8214       [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
8215     bits<4> imm;
8216     let Inst{19-16} = imm;
8217   }
8218   } // Predicates = [HasNEON, HasFullFP16]
8219   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8220                                   V64, V64, vecshiftR32,
8221                                   asm, ".2s", ".2s",
8222       [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
8223     bits<5> imm;
8224     let Inst{20-16} = imm;
8225   }
8226
8227   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8228                                   V128, V128, vecshiftR32,
8229                                   asm, ".4s", ".4s",
8230       [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
8231     bits<5> imm;
8232     let Inst{20-16} = imm;
8233   }
8234
8235   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8236                                   V128, V128, vecshiftR64,
8237                                   asm, ".2d", ".2d",
8238       [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
8239     bits<6> imm;
8240     let Inst{21-16} = imm;
8241   }
8242 }
8243
8244 multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
8245                                   Intrinsic OpNode> {
8246   let Predicates = [HasNEON, HasFullFP16] in {
8247   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8248                                   V64, V64, vecshiftR16,
8249                                   asm, ".4h", ".4h",
8250       [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
8251     bits<4> imm;
8252     let Inst{19-16} = imm;
8253   }
8254
8255   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8256                                   V128, V128, vecshiftR16,
8257                                   asm, ".8h", ".8h",
8258       [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
8259     bits<4> imm;
8260     let Inst{19-16} = imm;
8261   }
8262   } // Predicates = [HasNEON, HasFullFP16]
8263
8264   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8265                                   V64, V64, vecshiftR32,
8266                                   asm, ".2s", ".2s",
8267       [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
8268     bits<5> imm;
8269     let Inst{20-16} = imm;
8270   }
8271
8272   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8273                                   V128, V128, vecshiftR32,
8274                                   asm, ".4s", ".4s",
8275       [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
8276     bits<5> imm;
8277     let Inst{20-16} = imm;
8278   }
8279
8280   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8281                                   V128, V128, vecshiftR64,
8282                                   asm, ".2d", ".2d",
8283       [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
8284     bits<6> imm;
8285     let Inst{21-16} = imm;
8286   }
8287 }
8288
8289 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
8290                                      SDPatternOperator OpNode> {
8291   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8292                                   V64, V128, vecshiftR16Narrow,
8293                                   asm, ".8b", ".8h",
8294       [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
8295     bits<3> imm;
8296     let Inst{18-16} = imm;
8297   }
8298
8299   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8300                                   V128, V128, vecshiftR16Narrow,
8301                                   asm#"2", ".16b", ".8h", []> {
8302     bits<3> imm;
8303     let Inst{18-16} = imm;
8304     let hasSideEffects = 0;
8305   }
8306
8307   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8308                                   V64, V128, vecshiftR32Narrow,
8309                                   asm, ".4h", ".4s",
8310       [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
8311     bits<4> imm;
8312     let Inst{19-16} = imm;
8313   }
8314
8315   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8316                                   V128, V128, vecshiftR32Narrow,
8317                                   asm#"2", ".8h", ".4s", []> {
8318     bits<4> imm;
8319     let Inst{19-16} = imm;
8320     let hasSideEffects = 0;
8321   }
8322
8323   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8324                                   V64, V128, vecshiftR64Narrow,
8325                                   asm, ".2s", ".2d",
8326       [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
8327     bits<5> imm;
8328     let Inst{20-16} = imm;
8329   }
8330
8331   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8332                                   V128, V128, vecshiftR64Narrow,
8333                                   asm#"2", ".4s", ".2d", []> {
8334     bits<5> imm;
8335     let Inst{20-16} = imm;
8336     let hasSideEffects = 0;
8337   }
8338
8339   // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
8340   // themselves, so put them here instead.
8341
8342   // Patterns involving what's effectively an insert high and a normal
8343   // intrinsic, represented by CONCAT_VECTORS.
8344   def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
8345                                                    vecshiftR16Narrow:$imm)),
8346             (!cast<Instruction>(NAME # "v16i8_shift")
8347                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8348                 V128:$Rn, vecshiftR16Narrow:$imm)>;
8349   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
8350                                                      vecshiftR32Narrow:$imm)),
8351             (!cast<Instruction>(NAME # "v8i16_shift")
8352                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8353                 V128:$Rn, vecshiftR32Narrow:$imm)>;
8354   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
8355                                                      vecshiftR64Narrow:$imm)),
8356             (!cast<Instruction>(NAME # "v4i32_shift")
8357                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8358                 V128:$Rn, vecshiftR64Narrow:$imm)>;
8359 }
8360
8361 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
8362                                 SDPatternOperator OpNode> {
8363   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8364                                   V64, V64, vecshiftL8,
8365                                   asm, ".8b", ".8b",
8366                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
8367                        (i32 vecshiftL8:$imm)))]> {
8368     bits<3> imm;
8369     let Inst{18-16} = imm;
8370   }
8371
8372   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8373                                   V128, V128, vecshiftL8,
8374                                   asm, ".16b", ".16b",
8375              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
8376                    (i32 vecshiftL8:$imm)))]> {
8377     bits<3> imm;
8378     let Inst{18-16} = imm;
8379   }
8380
8381   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8382                                   V64, V64, vecshiftL16,
8383                                   asm, ".4h", ".4h",
8384               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
8385                     (i32 vecshiftL16:$imm)))]> {
8386     bits<4> imm;
8387     let Inst{19-16} = imm;
8388   }
8389
8390   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8391                                   V128, V128, vecshiftL16,
8392                                   asm, ".8h", ".8h",
8393             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
8394                   (i32 vecshiftL16:$imm)))]> {
8395     bits<4> imm;
8396     let Inst{19-16} = imm;
8397   }
8398
8399   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8400                                   V64, V64, vecshiftL32,
8401                                   asm, ".2s", ".2s",
8402               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
8403                     (i32 vecshiftL32:$imm)))]> {
8404     bits<5> imm;
8405     let Inst{20-16} = imm;
8406   }
8407
8408   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8409                                   V128, V128, vecshiftL32,
8410                                   asm, ".4s", ".4s",
8411             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
8412                   (i32 vecshiftL32:$imm)))]> {
8413     bits<5> imm;
8414     let Inst{20-16} = imm;
8415   }
8416
8417   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8418                                   V128, V128, vecshiftL64,
8419                                   asm, ".2d", ".2d",
8420             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
8421                   (i32 vecshiftL64:$imm)))]> {
8422     bits<6> imm;
8423     let Inst{21-16} = imm;
8424   }
8425 }
8426
8427 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
8428                                 SDPatternOperator OpNode> {
8429   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8430                                   V64, V64, vecshiftR8,
8431                                   asm, ".8b", ".8b",
8432                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
8433                        (i32 vecshiftR8:$imm)))]> {
8434     bits<3> imm;
8435     let Inst{18-16} = imm;
8436   }
8437
8438   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8439                                   V128, V128, vecshiftR8,
8440                                   asm, ".16b", ".16b",
8441              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
8442                    (i32 vecshiftR8:$imm)))]> {
8443     bits<3> imm;
8444     let Inst{18-16} = imm;
8445   }
8446
8447   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8448                                   V64, V64, vecshiftR16,
8449                                   asm, ".4h", ".4h",
8450               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
8451                     (i32 vecshiftR16:$imm)))]> {
8452     bits<4> imm;
8453     let Inst{19-16} = imm;
8454   }
8455
8456   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8457                                   V128, V128, vecshiftR16,
8458                                   asm, ".8h", ".8h",
8459             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
8460                   (i32 vecshiftR16:$imm)))]> {
8461     bits<4> imm;
8462     let Inst{19-16} = imm;
8463   }
8464
8465   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8466                                   V64, V64, vecshiftR32,
8467                                   asm, ".2s", ".2s",
8468               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
8469                     (i32 vecshiftR32:$imm)))]> {
8470     bits<5> imm;
8471     let Inst{20-16} = imm;
8472   }
8473
8474   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8475                                   V128, V128, vecshiftR32,
8476                                   asm, ".4s", ".4s",
8477             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
8478                   (i32 vecshiftR32:$imm)))]> {
8479     bits<5> imm;
8480     let Inst{20-16} = imm;
8481   }
8482
8483   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8484                                   V128, V128, vecshiftR64,
8485                                   asm, ".2d", ".2d",
8486             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
8487                   (i32 vecshiftR64:$imm)))]> {
8488     bits<6> imm;
8489     let Inst{21-16} = imm;
8490   }
8491 }
8492
8493 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8494 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
8495                                     SDPatternOperator OpNode = null_frag> {
8496   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
8497                                   V64, V64, vecshiftR8, asm, ".8b", ".8b",
8498                  [(set (v8i8 V64:$dst),
8499                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
8500                            (i32 vecshiftR8:$imm)))]> {
8501     bits<3> imm;
8502     let Inst{18-16} = imm;
8503   }
8504
8505   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8506                                   V128, V128, vecshiftR8, asm, ".16b", ".16b",
8507              [(set (v16i8 V128:$dst),
8508                (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
8509                        (i32 vecshiftR8:$imm)))]> {
8510     bits<3> imm;
8511     let Inst{18-16} = imm;
8512   }
8513
8514   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
8515                                   V64, V64, vecshiftR16, asm, ".4h", ".4h",
8516               [(set (v4i16 V64:$dst),
8517                 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
8518                         (i32 vecshiftR16:$imm)))]> {
8519     bits<4> imm;
8520     let Inst{19-16} = imm;
8521   }
8522
8523   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8524                                   V128, V128, vecshiftR16, asm, ".8h", ".8h",
8525             [(set (v8i16 V128:$dst),
8526               (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8527                       (i32 vecshiftR16:$imm)))]> {
8528     bits<4> imm;
8529     let Inst{19-16} = imm;
8530   }
8531
8532   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
8533                                   V64, V64, vecshiftR32, asm, ".2s", ".2s",
8534               [(set (v2i32 V64:$dst),
8535                 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8536                         (i32 vecshiftR32:$imm)))]> {
8537     bits<5> imm;
8538     let Inst{20-16} = imm;
8539   }
8540
8541   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8542                                   V128, V128, vecshiftR32, asm, ".4s", ".4s",
8543             [(set (v4i32 V128:$dst),
8544               (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8545                       (i32 vecshiftR32:$imm)))]> {
8546     bits<5> imm;
8547     let Inst{20-16} = imm;
8548   }
8549
8550   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
8551                                   V128, V128, vecshiftR64,
8552                                   asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
8553               (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
8554                       (i32 vecshiftR64:$imm)))]> {
8555     bits<6> imm;
8556     let Inst{21-16} = imm;
8557   }
8558 }
8559
8560 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
8561                                     SDPatternOperator OpNode = null_frag> {
8562   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
8563                                   V64, V64, vecshiftL8,
8564                                   asm, ".8b", ".8b",
8565                     [(set (v8i8 V64:$dst),
8566                           (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
8567                                   (i32 vecshiftL8:$imm)))]> {
8568     bits<3> imm;
8569     let Inst{18-16} = imm;
8570   }
8571
8572   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8573                                   V128, V128, vecshiftL8,
8574                                   asm, ".16b", ".16b",
8575                     [(set (v16i8 V128:$dst),
8576                           (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
8577                                   (i32 vecshiftL8:$imm)))]> {
8578     bits<3> imm;
8579     let Inst{18-16} = imm;
8580   }
8581
8582   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
8583                                   V64, V64, vecshiftL16,
8584                                   asm, ".4h", ".4h",
8585                     [(set (v4i16 V64:$dst),
8586                            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
8587                                    (i32 vecshiftL16:$imm)))]> {
8588     bits<4> imm;
8589     let Inst{19-16} = imm;
8590   }
8591
8592   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8593                                   V128, V128, vecshiftL16,
8594                                   asm, ".8h", ".8h",
8595                     [(set (v8i16 V128:$dst),
8596                           (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8597                                   (i32 vecshiftL16:$imm)))]> {
8598     bits<4> imm;
8599     let Inst{19-16} = imm;
8600   }
8601
8602   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
8603                                   V64, V64, vecshiftL32,
8604                                   asm, ".2s", ".2s",
8605                     [(set (v2i32 V64:$dst),
8606                           (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8607                                   (i32 vecshiftL32:$imm)))]> {
8608     bits<5> imm;
8609     let Inst{20-16} = imm;
8610   }
8611
8612   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8613                                   V128, V128, vecshiftL32,
8614                                   asm, ".4s", ".4s",
8615                     [(set (v4i32 V128:$dst),
8616                           (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8617                                   (i32 vecshiftL32:$imm)))]> {
8618     bits<5> imm;
8619     let Inst{20-16} = imm;
8620   }
8621
8622   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
8623                                   V128, V128, vecshiftL64,
8624                                   asm, ".2d", ".2d",
8625                     [(set (v2i64 V128:$dst),
8626                           (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
8627                                   (i32 vecshiftL64:$imm)))]> {
8628     bits<6> imm;
8629     let Inst{21-16} = imm;
8630   }
8631 }
8632
8633 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
8634                                    SDPatternOperator OpNode> {
8635   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8636                                   V128, V64, vecshiftL8, asm, ".8h", ".8b",
8637       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
8638     bits<3> imm;
8639     let Inst{18-16} = imm;
8640   }
8641
8642   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8643                                   V128, V128, vecshiftL8,
8644                                   asm#"2", ".8h", ".16b",
8645       [(set (v8i16 V128:$Rd),
8646             (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
8647     bits<3> imm;
8648     let Inst{18-16} = imm;
8649   }
8650
8651   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8652                                   V128, V64, vecshiftL16, asm, ".4s", ".4h",
8653       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
8654     bits<4> imm;
8655     let Inst{19-16} = imm;
8656   }
8657
8658   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8659                                   V128, V128, vecshiftL16,
8660                                   asm#"2", ".4s", ".8h",
8661       [(set (v4i32 V128:$Rd),
8662             (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
8663
8664     bits<4> imm;
8665     let Inst{19-16} = imm;
8666   }
8667
8668   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8669                                   V128, V64, vecshiftL32, asm, ".2d", ".2s",
8670       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
8671     bits<5> imm;
8672     let Inst{20-16} = imm;
8673   }
8674
8675   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8676                                   V128, V128, vecshiftL32,
8677                                   asm#"2", ".2d", ".4s",
8678       [(set (v2i64 V128:$Rd),
8679             (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
8680     bits<5> imm;
8681     let Inst{20-16} = imm;
8682   }
8683 }
8684
8685
8686 //---
8687 // Vector load/store
8688 //---
8689 // SIMD ldX/stX no-index memory references don't allow the optional
8690 // ", #0" constant and handle post-indexing explicitly, so we use
8691 // a more specialized parse method for them. Otherwise, it's the same as
8692 // the general GPR64sp handling.
8693
8694 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
8695                    string asm, dag oops, dag iops, list<dag> pattern>
8696   : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
8697   bits<5> Vt;
8698   bits<5> Rn;
8699   let Inst{31} = 0;
8700   let Inst{30} = Q;
8701   let Inst{29-23} = 0b0011000;
8702   let Inst{22} = L;
8703   let Inst{21-16} = 0b000000;
8704   let Inst{15-12} = opcode;
8705   let Inst{11-10} = size;
8706   let Inst{9-5} = Rn;
8707   let Inst{4-0} = Vt;
8708 }
8709
8710 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
8711                        string asm, dag oops, dag iops>
8712   : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
8713   bits<5> Vt;
8714   bits<5> Rn;
8715   bits<5> Xm;
8716   let Inst{31} = 0;
8717   let Inst{30} = Q;
8718   let Inst{29-23} = 0b0011001;
8719   let Inst{22} = L;
8720   let Inst{21} = 0;
8721   let Inst{20-16} = Xm;
8722   let Inst{15-12} = opcode;
8723   let Inst{11-10} = size;
8724   let Inst{9-5} = Rn;
8725   let Inst{4-0} = Vt;
8726 }
8727
8728 // The immediate form of AdvSIMD post-indexed addressing is encoded with
8729 // register post-index addressing from the zero register.
8730 multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
8731                            int Offset, int Size> {
8732   // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
8733   //      "ld1\t$Vt, [$Rn], #16"
8734   // may get mapped to
8735   //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
8736   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
8737                   (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
8738                       GPR64sp:$Rn,
8739                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8740                       XZR), 1>;
8741
8742   // E.g. "ld1.8b { v0, v1 }, [x1], #16"
8743   //      "ld1.8b\t$Vt, [$Rn], #16"
8744   // may get mapped to
8745   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
8746   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
8747                   (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
8748                       GPR64sp:$Rn,
8749                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8750                       XZR), 0>;
8751
8752   // E.g. "ld1.8b { v0, v1 }, [x1]"
8753   //      "ld1\t$Vt, [$Rn]"
8754   // may get mapped to
8755   //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
8756   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
8757                   (!cast<Instruction>(BaseName # Count # "v" # layout)
8758                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8759                       GPR64sp:$Rn), 0>;
8760
8761   // E.g. "ld1.8b { v0, v1 }, [x1], x2"
8762   //      "ld1\t$Vt, [$Rn], $Xm"
8763   // may get mapped to
8764   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
8765   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
8766                   (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
8767                       GPR64sp:$Rn,
8768                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8769                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8770 }
8771
8772 multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
8773                        int Offset128, int Offset64, bits<4> opcode> {
8774   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
8775     def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
8776                            (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
8777                            (ins GPR64sp:$Rn), []>;
8778     def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
8779                            (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
8780                            (ins GPR64sp:$Rn), []>;
8781     def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
8782                            (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
8783                            (ins GPR64sp:$Rn), []>;
8784     def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
8785                            (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
8786                            (ins GPR64sp:$Rn), []>;
8787     def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
8788                            (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
8789                            (ins GPR64sp:$Rn), []>;
8790     def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
8791                            (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
8792                            (ins GPR64sp:$Rn), []>;
8793     def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
8794                            (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
8795                            (ins GPR64sp:$Rn), []>;
8796
8797
8798     def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
8799                        (outs GPR64sp:$wback,
8800                              !cast<RegisterOperand>(veclist # "16b"):$Vt),
8801                        (ins GPR64sp:$Rn,
8802                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8803     def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
8804                        (outs GPR64sp:$wback,
8805                              !cast<RegisterOperand>(veclist # "8h"):$Vt),
8806                        (ins GPR64sp:$Rn,
8807                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8808     def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
8809                        (outs GPR64sp:$wback,
8810                              !cast<RegisterOperand>(veclist # "4s"):$Vt),
8811                        (ins GPR64sp:$Rn,
8812                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8813     def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
8814                        (outs GPR64sp:$wback,
8815                              !cast<RegisterOperand>(veclist # "2d"):$Vt),
8816                        (ins GPR64sp:$Rn,
8817                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8818     def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
8819                        (outs GPR64sp:$wback,
8820                              !cast<RegisterOperand>(veclist # "8b"):$Vt),
8821                        (ins GPR64sp:$Rn,
8822                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8823     def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
8824                        (outs GPR64sp:$wback,
8825                              !cast<RegisterOperand>(veclist # "4h"):$Vt),
8826                        (ins GPR64sp:$Rn,
8827                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8828     def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
8829                        (outs GPR64sp:$wback,
8830                              !cast<RegisterOperand>(veclist # "2s"):$Vt),
8831                        (ins GPR64sp:$Rn,
8832                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8833   }
8834
8835   defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
8836   defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
8837   defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
8838   defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
8839   defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
8840   defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
8841   defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
8842 }
8843
8844 // Only ld1/st1 has a v1d version.
8845 multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
8846                        int Offset128, int Offset64, bits<4> opcode> {
8847   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
8848     def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
8849                             (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
8850                                  GPR64sp:$Rn), []>;
8851     def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
8852                            (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
8853                                 GPR64sp:$Rn), []>;
8854     def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
8855                            (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
8856                                 GPR64sp:$Rn), []>;
8857     def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
8858                            (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
8859                                 GPR64sp:$Rn), []>;
8860     def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
8861                            (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
8862                                 GPR64sp:$Rn), []>;
8863     def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
8864                            (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
8865                                 GPR64sp:$Rn), []>;
8866     def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
8867                            (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
8868                                 GPR64sp:$Rn), []>;
8869
8870     def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
8871                        (outs GPR64sp:$wback),
8872                        (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
8873                             GPR64sp:$Rn,
8874                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8875     def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
8876                        (outs GPR64sp:$wback),
8877                        (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
8878                             GPR64sp:$Rn,
8879                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8880     def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
8881                        (outs GPR64sp:$wback),
8882                        (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
8883                             GPR64sp:$Rn,
8884                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8885     def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
8886                        (outs GPR64sp:$wback),
8887                        (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
8888                             GPR64sp:$Rn,
8889                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8890     def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
8891                        (outs GPR64sp:$wback),
8892                        (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
8893                             GPR64sp:$Rn,
8894                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8895     def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
8896                        (outs GPR64sp:$wback),
8897                        (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
8898                             GPR64sp:$Rn,
8899                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8900     def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
8901                        (outs GPR64sp:$wback),
8902                        (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
8903                             GPR64sp:$Rn,
8904                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8905   }
8906
8907   defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
8908   defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
8909   defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
8910   defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
8911   defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
8912   defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
8913   defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
8914 }
8915
8916 multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
8917                        int Offset128, int Offset64, bits<4> opcode>
8918   : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
8919
8920   // LD1 instructions have extra "1d" variants.
8921   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
8922     def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
8923                            (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
8924                            (ins GPR64sp:$Rn), []>;
8925
8926     def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
8927                        (outs GPR64sp:$wback,
8928                              !cast<RegisterOperand>(veclist # "1d"):$Vt),
8929                        (ins GPR64sp:$Rn,
8930                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8931   }
8932
8933   defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
8934 }
8935
8936 multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
8937                        int Offset128, int Offset64, bits<4> opcode>
8938   : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
8939
8940   // ST1 instructions have extra "1d" variants.
8941   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
8942     def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
8943                            (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8944                                 GPR64sp:$Rn), []>;
8945
8946     def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
8947                        (outs GPR64sp:$wback),
8948                        (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8949                             GPR64sp:$Rn,
8950                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8951   }
8952
8953   defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
8954 }
8955
8956 multiclass SIMDLd1Multiple<string asm> {
8957   defm One   : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
8958   defm Two   : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
8959   defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
8960   defm Four  : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
8961 }
8962
8963 multiclass SIMDSt1Multiple<string asm> {
8964   defm One   : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
8965   defm Two   : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
8966   defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
8967   defm Four  : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
8968 }
8969
8970 multiclass SIMDLd2Multiple<string asm> {
8971   defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
8972 }
8973
8974 multiclass SIMDSt2Multiple<string asm> {
8975   defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
8976 }
8977
8978 multiclass SIMDLd3Multiple<string asm> {
8979   defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
8980 }
8981
8982 multiclass SIMDSt3Multiple<string asm> {
8983   defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
8984 }
8985
8986 multiclass SIMDLd4Multiple<string asm> {
8987   defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
8988 }
8989
8990 multiclass SIMDSt4Multiple<string asm> {
8991   defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
8992 }
8993
8994 //---
8995 // AdvSIMD Load/store single-element
8996 //---
8997
8998 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
8999                          string asm, string operands, string cst,
9000                          dag oops, dag iops, list<dag> pattern>
9001   : I<oops, iops, asm, operands, cst, pattern> {
9002   bits<5> Vt;
9003   bits<5> Rn;
9004   let Inst{31} = 0;
9005   let Inst{29-24} = 0b001101;
9006   let Inst{22} = L;
9007   let Inst{21} = R;
9008   let Inst{15-13} = opcode;
9009   let Inst{9-5} = Rn;
9010   let Inst{4-0} = Vt;
9011 }
9012
9013 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
9014                          string asm, string operands, string cst,
9015                          dag oops, dag iops, list<dag> pattern>
9016   : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
9017   bits<5> Vt;
9018   bits<5> Rn;
9019   let Inst{31} = 0;
9020   let Inst{29-24} = 0b001101;
9021   let Inst{22} = L;
9022   let Inst{21} = R;
9023   let Inst{15-13} = opcode;
9024   let Inst{9-5} = Rn;
9025   let Inst{4-0} = Vt;
9026 }
9027
9028
9029 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9030 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
9031                   DAGOperand listtype>
9032   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
9033                        (outs listtype:$Vt), (ins GPR64sp:$Rn),
9034                        []> {
9035   let Inst{30} = Q;
9036   let Inst{23} = 0;
9037   let Inst{20-16} = 0b00000;
9038   let Inst{12} = S;
9039   let Inst{11-10} = size;
9040 }
9041 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9042 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
9043                       string asm, DAGOperand listtype, DAGOperand GPR64pi>
9044   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
9045                        "$Rn = $wback",
9046                        (outs GPR64sp:$wback, listtype:$Vt),
9047                        (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
9048   bits<5> Xm;
9049   let Inst{30} = Q;
9050   let Inst{23} = 1;
9051   let Inst{20-16} = Xm;
9052   let Inst{12} = S;
9053   let Inst{11-10} = size;
9054 }
9055
9056 multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
9057                           int Offset, int Size> {
9058   // E.g. "ld1r { v0.8b }, [x1], #1"
9059   //      "ld1r.8b\t$Vt, [$Rn], #1"
9060   // may get mapped to
9061   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
9062   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9063                   (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9064                       GPR64sp:$Rn,
9065                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9066                       XZR), 1>;
9067
9068   // E.g. "ld1r.8b { v0 }, [x1], #1"
9069   //      "ld1r.8b\t$Vt, [$Rn], #1"
9070   // may get mapped to
9071   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9072   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9073                   (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9074                       GPR64sp:$Rn,
9075                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9076                       XZR), 0>;
9077
9078   // E.g. "ld1r.8b { v0 }, [x1]"
9079   //      "ld1r.8b\t$Vt, [$Rn]"
9080   // may get mapped to
9081   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9082   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9083                   (!cast<Instruction>(BaseName # "v" # layout)
9084                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9085                       GPR64sp:$Rn), 0>;
9086
9087   // E.g. "ld1r.8b { v0 }, [x1], x2"
9088   //      "ld1r.8b\t$Vt, [$Rn], $Xm"
9089   // may get mapped to
9090   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9091   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9092                   (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9093                       GPR64sp:$Rn,
9094                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9095                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9096 }
9097
9098 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
9099   int Offset1, int Offset2, int Offset4, int Offset8> {
9100   def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
9101                         !cast<DAGOperand>("VecList" # Count # "8b")>;
9102   def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
9103                         !cast<DAGOperand>("VecList" # Count #"16b")>;
9104   def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
9105                         !cast<DAGOperand>("VecList" # Count #"4h")>;
9106   def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
9107                         !cast<DAGOperand>("VecList" # Count #"8h")>;
9108   def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
9109                         !cast<DAGOperand>("VecList" # Count #"2s")>;
9110   def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
9111                         !cast<DAGOperand>("VecList" # Count #"4s")>;
9112   def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
9113                         !cast<DAGOperand>("VecList" # Count #"1d")>;
9114   def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
9115                         !cast<DAGOperand>("VecList" # Count #"2d")>;
9116
9117   def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
9118                                  !cast<DAGOperand>("VecList" # Count # "8b"),
9119                                  !cast<DAGOperand>("GPR64pi" # Offset1)>;
9120   def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
9121                                  !cast<DAGOperand>("VecList" # Count # "16b"),
9122                                  !cast<DAGOperand>("GPR64pi" # Offset1)>;
9123   def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
9124                                  !cast<DAGOperand>("VecList" # Count # "4h"),
9125                                  !cast<DAGOperand>("GPR64pi" # Offset2)>;
9126   def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
9127                                  !cast<DAGOperand>("VecList" # Count # "8h"),
9128                                  !cast<DAGOperand>("GPR64pi" # Offset2)>;
9129   def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
9130                                  !cast<DAGOperand>("VecList" # Count # "2s"),
9131                                  !cast<DAGOperand>("GPR64pi" # Offset4)>;
9132   def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
9133                                  !cast<DAGOperand>("VecList" # Count # "4s"),
9134                                  !cast<DAGOperand>("GPR64pi" # Offset4)>;
9135   def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
9136                                  !cast<DAGOperand>("VecList" # Count # "1d"),
9137                                  !cast<DAGOperand>("GPR64pi" # Offset8)>;
9138   def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
9139                                  !cast<DAGOperand>("VecList" # Count # "2d"),
9140                                  !cast<DAGOperand>("GPR64pi" # Offset8)>;
9141
9142   defm : SIMDLdrAliases<NAME, asm, "8b",  Count, Offset1,  64>;
9143   defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
9144   defm : SIMDLdrAliases<NAME, asm, "4h",  Count, Offset2,  64>;
9145   defm : SIMDLdrAliases<NAME, asm, "8h",  Count, Offset2, 128>;
9146   defm : SIMDLdrAliases<NAME, asm, "2s",  Count, Offset4,  64>;
9147   defm : SIMDLdrAliases<NAME, asm, "4s",  Count, Offset4, 128>;
9148   defm : SIMDLdrAliases<NAME, asm, "1d",  Count, Offset8,  64>;
9149   defm : SIMDLdrAliases<NAME, asm, "2d",  Count, Offset8, 128>;
9150 }
9151
9152 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
9153                       dag oops, dag iops, list<dag> pattern>
9154   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9155                        pattern> {
9156   // idx encoded in Q:S:size fields.
9157   bits<4> idx;
9158   let Inst{30} = idx{3};
9159   let Inst{23} = 0;
9160   let Inst{20-16} = 0b00000;
9161   let Inst{12} = idx{2};
9162   let Inst{11-10} = idx{1-0};
9163 }
9164 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
9165                       dag oops, dag iops, list<dag> pattern>
9166   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9167                            oops, iops, pattern> {
9168   // idx encoded in Q:S:size fields.
9169   bits<4> idx;
9170   let Inst{30} = idx{3};
9171   let Inst{23} = 0;
9172   let Inst{20-16} = 0b00000;
9173   let Inst{12} = idx{2};
9174   let Inst{11-10} = idx{1-0};
9175 }
9176 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
9177                           dag oops, dag iops>
9178   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9179                        "$Rn = $wback", oops, iops, []> {
9180   // idx encoded in Q:S:size fields.
9181   bits<4> idx;
9182   bits<5> Xm;
9183   let Inst{30} = idx{3};
9184   let Inst{23} = 1;
9185   let Inst{20-16} = Xm;
9186   let Inst{12} = idx{2};
9187   let Inst{11-10} = idx{1-0};
9188 }
9189 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
9190                           dag oops, dag iops>
9191   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9192                            "$Rn = $wback", oops, iops, []> {
9193   // idx encoded in Q:S:size fields.
9194   bits<4> idx;
9195   bits<5> Xm;
9196   let Inst{30} = idx{3};
9197   let Inst{23} = 1;
9198   let Inst{20-16} = Xm;
9199   let Inst{12} = idx{2};
9200   let Inst{11-10} = idx{1-0};
9201 }
9202
9203 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
9204                       dag oops, dag iops, list<dag> pattern>
9205   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9206                        pattern> {
9207   // idx encoded in Q:S:size<1> fields.
9208   bits<3> idx;
9209   let Inst{30} = idx{2};
9210   let Inst{23} = 0;
9211   let Inst{20-16} = 0b00000;
9212   let Inst{12} = idx{1};
9213   let Inst{11} = idx{0};
9214   let Inst{10} = size;
9215 }
9216 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
9217                       dag oops, dag iops, list<dag> pattern>
9218   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9219                            oops, iops, pattern> {
9220   // idx encoded in Q:S:size<1> fields.
9221   bits<3> idx;
9222   let Inst{30} = idx{2};
9223   let Inst{23} = 0;
9224   let Inst{20-16} = 0b00000;
9225   let Inst{12} = idx{1};
9226   let Inst{11} = idx{0};
9227   let Inst{10} = size;
9228 }
9229
9230 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
9231                           dag oops, dag iops>
9232   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9233                        "$Rn = $wback", oops, iops, []> {
9234   // idx encoded in Q:S:size<1> fields.
9235   bits<3> idx;
9236   bits<5> Xm;
9237   let Inst{30} = idx{2};
9238   let Inst{23} = 1;
9239   let Inst{20-16} = Xm;
9240   let Inst{12} = idx{1};
9241   let Inst{11} = idx{0};
9242   let Inst{10} = size;
9243 }
9244 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
9245                           dag oops, dag iops>
9246   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9247                            "$Rn = $wback", oops, iops, []> {
9248   // idx encoded in Q:S:size<1> fields.
9249   bits<3> idx;
9250   bits<5> Xm;
9251   let Inst{30} = idx{2};
9252   let Inst{23} = 1;
9253   let Inst{20-16} = Xm;
9254   let Inst{12} = idx{1};
9255   let Inst{11} = idx{0};
9256   let Inst{10} = size;
9257 }
9258 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9259                       dag oops, dag iops, list<dag> pattern>
9260   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9261                        pattern> {
9262   // idx encoded in Q:S fields.
9263   bits<2> idx;
9264   let Inst{30} = idx{1};
9265   let Inst{23} = 0;
9266   let Inst{20-16} = 0b00000;
9267   let Inst{12} = idx{0};
9268   let Inst{11-10} = size;
9269 }
9270 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9271                       dag oops, dag iops, list<dag> pattern>
9272   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9273                            oops, iops, pattern> {
9274   // idx encoded in Q:S fields.
9275   bits<2> idx;
9276   let Inst{30} = idx{1};
9277   let Inst{23} = 0;
9278   let Inst{20-16} = 0b00000;
9279   let Inst{12} = idx{0};
9280   let Inst{11-10} = size;
9281 }
9282 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
9283                           string asm, dag oops, dag iops>
9284   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9285                        "$Rn = $wback", oops, iops, []> {
9286   // idx encoded in Q:S fields.
9287   bits<2> idx;
9288   bits<5> Xm;
9289   let Inst{30} = idx{1};
9290   let Inst{23} = 1;
9291   let Inst{20-16} = Xm;
9292   let Inst{12} = idx{0};
9293   let Inst{11-10} = size;
9294 }
9295 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
9296                           string asm, dag oops, dag iops>
9297   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9298                            "$Rn = $wback", oops, iops, []> {
9299   // idx encoded in Q:S fields.
9300   bits<2> idx;
9301   bits<5> Xm;
9302   let Inst{30} = idx{1};
9303   let Inst{23} = 1;
9304   let Inst{20-16} = Xm;
9305   let Inst{12} = idx{0};
9306   let Inst{11-10} = size;
9307 }
9308 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9309                       dag oops, dag iops, list<dag> pattern>
9310   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9311                        pattern> {
9312   // idx encoded in Q field.
9313   bits<1> idx;
9314   let Inst{30} = idx;
9315   let Inst{23} = 0;
9316   let Inst{20-16} = 0b00000;
9317   let Inst{12} = 0;
9318   let Inst{11-10} = size;
9319 }
9320 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9321                       dag oops, dag iops, list<dag> pattern>
9322   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9323                            oops, iops, pattern> {
9324   // idx encoded in Q field.
9325   bits<1> idx;
9326   let Inst{30} = idx;
9327   let Inst{23} = 0;
9328   let Inst{20-16} = 0b00000;
9329   let Inst{12} = 0;
9330   let Inst{11-10} = size;
9331 }
9332 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
9333                           string asm, dag oops, dag iops>
9334   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9335                        "$Rn = $wback", oops, iops, []> {
9336   // idx encoded in Q field.
9337   bits<1> idx;
9338   bits<5> Xm;
9339   let Inst{30} = idx;
9340   let Inst{23} = 1;
9341   let Inst{20-16} = Xm;
9342   let Inst{12} = 0;
9343   let Inst{11-10} = size;
9344 }
9345 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
9346                           string asm, dag oops, dag iops>
9347   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9348                            "$Rn = $wback", oops, iops, []> {
9349   // idx encoded in Q field.
9350   bits<1> idx;
9351   bits<5> Xm;
9352   let Inst{30} = idx;
9353   let Inst{23} = 1;
9354   let Inst{20-16} = Xm;
9355   let Inst{12} = 0;
9356   let Inst{11-10} = size;
9357 }
9358
9359 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9360 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
9361                          RegisterOperand listtype,
9362                          RegisterOperand GPR64pi> {
9363   def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
9364                            (outs listtype:$dst),
9365                            (ins listtype:$Vt, VectorIndexB:$idx,
9366                                 GPR64sp:$Rn), []>;
9367
9368   def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
9369                             (outs GPR64sp:$wback, listtype:$dst),
9370                             (ins listtype:$Vt, VectorIndexB:$idx,
9371                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9372 }
9373 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9374 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
9375                          RegisterOperand listtype,
9376                          RegisterOperand GPR64pi> {
9377   def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
9378                             (outs listtype:$dst),
9379                             (ins listtype:$Vt, VectorIndexH:$idx,
9380                                  GPR64sp:$Rn), []>;
9381
9382   def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
9383                             (outs GPR64sp:$wback, listtype:$dst),
9384                             (ins listtype:$Vt, VectorIndexH:$idx,
9385                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9386 }
9387 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9388 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
9389                          RegisterOperand listtype,
9390                          RegisterOperand GPR64pi> {
9391   def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
9392                             (outs listtype:$dst),
9393                             (ins listtype:$Vt, VectorIndexS:$idx,
9394                                  GPR64sp:$Rn), []>;
9395
9396   def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
9397                             (outs GPR64sp:$wback, listtype:$dst),
9398                             (ins listtype:$Vt, VectorIndexS:$idx,
9399                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9400 }
9401 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9402 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
9403                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9404   def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
9405                             (outs listtype:$dst),
9406                             (ins listtype:$Vt, VectorIndexD:$idx,
9407                                  GPR64sp:$Rn), []>;
9408
9409   def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
9410                             (outs GPR64sp:$wback, listtype:$dst),
9411                             (ins listtype:$Vt, VectorIndexD:$idx,
9412                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9413 }
9414 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9415 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
9416                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9417   def i8 : SIMDLdStSingleB<0, R, opcode, asm,
9418                            (outs), (ins listtype:$Vt, VectorIndexB:$idx,
9419                                         GPR64sp:$Rn), []>;
9420
9421   def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
9422                                     (outs GPR64sp:$wback),
9423                                     (ins listtype:$Vt, VectorIndexB:$idx,
9424                                          GPR64sp:$Rn, GPR64pi:$Xm)>;
9425 }
9426 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9427 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
9428                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9429   def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
9430                             (outs), (ins listtype:$Vt, VectorIndexH:$idx,
9431                                          GPR64sp:$Rn), []>;
9432
9433   def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
9434                             (outs GPR64sp:$wback),
9435                             (ins listtype:$Vt, VectorIndexH:$idx,
9436                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9437 }
9438 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9439 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
9440                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9441   def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
9442                             (outs), (ins listtype:$Vt, VectorIndexS:$idx,
9443                                          GPR64sp:$Rn), []>;
9444
9445   def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
9446                             (outs GPR64sp:$wback),
9447                             (ins listtype:$Vt, VectorIndexS:$idx,
9448                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9449 }
9450 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9451 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
9452                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9453   def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
9454                             (outs), (ins listtype:$Vt, VectorIndexD:$idx,
9455                                          GPR64sp:$Rn), []>;
9456
9457   def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
9458                             (outs GPR64sp:$wback),
9459                             (ins listtype:$Vt, VectorIndexD:$idx,
9460                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9461 }
9462
9463 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
9464                                  string Count, int Offset, Operand idxtype> {
9465   // E.g. "ld1 { v0.8b }[0], [x1], #1"
9466   //      "ld1\t$Vt, [$Rn], #1"
9467   // may get mapped to
9468   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
9469   def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
9470                   (!cast<Instruction>(NAME # Type  # "_POST")
9471                       GPR64sp:$Rn,
9472                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9473                       idxtype:$idx, XZR), 1>;
9474
9475   // E.g. "ld1.8b { v0 }[0], [x1], #1"
9476   //      "ld1.8b\t$Vt, [$Rn], #1"
9477   // may get mapped to
9478   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9479   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
9480                   (!cast<Instruction>(NAME # Type # "_POST")
9481                       GPR64sp:$Rn,
9482                       !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9483                       idxtype:$idx, XZR), 0>;
9484
9485   // E.g. "ld1.8b { v0 }[0], [x1]"
9486   //      "ld1.8b\t$Vt, [$Rn]"
9487   // may get mapped to
9488   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9489   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
9490                       (!cast<Instruction>(NAME # Type)
9491                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9492                          idxtype:$idx, GPR64sp:$Rn), 0>;
9493
9494   // E.g. "ld1.8b { v0 }[0], [x1], x2"
9495   //      "ld1.8b\t$Vt, [$Rn], $Xm"
9496   // may get mapped to
9497   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9498   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
9499                       (!cast<Instruction>(NAME # Type # "_POST")
9500                          GPR64sp:$Rn,
9501                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9502                          idxtype:$idx,
9503                          !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9504 }
9505
9506 multiclass SIMDLdSt1SingleAliases<string asm> {
9507   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
9508   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
9509   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
9510   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
9511 }
9512
9513 multiclass SIMDLdSt2SingleAliases<string asm> {
9514   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
9515   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
9516   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
9517   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
9518 }
9519
9520 multiclass SIMDLdSt3SingleAliases<string asm> {
9521   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
9522   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
9523   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
9524   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
9525 }
9526
9527 multiclass SIMDLdSt4SingleAliases<string asm> {
9528   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
9529   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
9530   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
9531   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
9532 }
9533 } // end of 'let Predicates = [HasNEON]'
9534
9535 //----------------------------------------------------------------------------
9536 // AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
9537 //----------------------------------------------------------------------------
9538
9539 let Predicates = [HasNEON, HasRDM] in {
9540
9541 class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
9542                                     RegisterOperand regtype, string asm,
9543                                     string kind, list<dag> pattern>
9544   : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
9545                                 pattern> {
9546 }
9547 multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
9548                                              SDPatternOperator Accum> {
9549   def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
9550     [(set (v4i16 V64:$dst),
9551           (Accum (v4i16 V64:$Rd),
9552                  (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
9553                                                    (v4i16 V64:$Rm)))))]>;
9554   def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
9555     [(set (v8i16 V128:$dst),
9556           (Accum (v8i16 V128:$Rd),
9557                  (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
9558                                                    (v8i16 V128:$Rm)))))]>;
9559   def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
9560     [(set (v2i32 V64:$dst),
9561           (Accum (v2i32 V64:$Rd),
9562                  (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
9563                                                    (v2i32 V64:$Rm)))))]>;
9564   def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
9565     [(set (v4i32 V128:$dst),
9566           (Accum (v4i32 V128:$Rd),
9567                  (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
9568                                                    (v4i32 V128:$Rm)))))]>;
9569 }
9570
9571 multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
9572                                      SDPatternOperator Accum> {
9573   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
9574                                           V64, V64, V128_lo, VectorIndexH,
9575                                           asm, ".4h", ".4h", ".4h", ".h",
9576     [(set (v4i16 V64:$dst),
9577           (Accum (v4i16 V64:$Rd),
9578                  (v4i16 (int_aarch64_neon_sqrdmulh
9579                           (v4i16 V64:$Rn),
9580                           (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
9581                                                     VectorIndexH:$idx))))))]> {
9582     bits<3> idx;
9583     let Inst{11} = idx{2};
9584     let Inst{21} = idx{1};
9585     let Inst{20} = idx{0};
9586   }
9587
9588   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9589                                           V128, V128, V128_lo, VectorIndexH,
9590                                           asm, ".8h", ".8h", ".8h", ".h",
9591     [(set (v8i16 V128:$dst),
9592           (Accum (v8i16 V128:$Rd),
9593                  (v8i16 (int_aarch64_neon_sqrdmulh
9594                           (v8i16 V128:$Rn),
9595                           (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
9596                                                    VectorIndexH:$idx))))))]> {
9597     bits<3> idx;
9598     let Inst{11} = idx{2};
9599     let Inst{21} = idx{1};
9600     let Inst{20} = idx{0};
9601   }
9602
9603   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9604                                           V64, V64, V128, VectorIndexS,
9605                                           asm, ".2s", ".2s", ".2s", ".s",
9606     [(set (v2i32 V64:$dst),
9607         (Accum (v2i32 V64:$Rd),
9608                (v2i32 (int_aarch64_neon_sqrdmulh
9609                         (v2i32 V64:$Rn),
9610                         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
9611                                                  VectorIndexS:$idx))))))]> {
9612     bits<2> idx;
9613     let Inst{11} = idx{1};
9614     let Inst{21} = idx{0};
9615   }
9616
9617   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
9618   // an intermediate EXTRACT_SUBREG would be untyped.
9619   // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we
9620   // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
9621   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9622                        (i32 (vector_extract
9623                                (v4i32 (insert_subvector
9624                                        (undef),
9625                                         (v2i32 (int_aarch64_neon_sqrdmulh
9626                                                  (v2i32 V64:$Rn),
9627                                                  (v2i32 (AArch64duplane32
9628                                                           (v4i32 V128:$Rm),
9629                                                           VectorIndexS:$idx)))),
9630                                       (i32 0))),
9631                                (i64 0))))),
9632             (EXTRACT_SUBREG
9633                 (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
9634                           (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
9635                                                 FPR32Op:$Rd,
9636                                                 ssub)),
9637                           V64:$Rn,
9638                           V128:$Rm,
9639                           VectorIndexS:$idx)),
9640                 ssub)>;
9641
9642   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9643                                           V128, V128, V128, VectorIndexS,
9644                                           asm, ".4s", ".4s", ".4s", ".s",
9645     [(set (v4i32 V128:$dst),
9646           (Accum (v4i32 V128:$Rd),
9647                  (v4i32 (int_aarch64_neon_sqrdmulh
9648                           (v4i32 V128:$Rn),
9649                           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
9650                                                    VectorIndexS:$idx))))))]> {
9651     bits<2> idx;
9652     let Inst{11} = idx{1};
9653     let Inst{21} = idx{0};
9654   }
9655
9656   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
9657   // an intermediate EXTRACT_SUBREG would be untyped.
9658   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9659                         (i32 (vector_extract
9660                                (v4i32 (int_aarch64_neon_sqrdmulh
9661                                         (v4i32 V128:$Rn),
9662                                         (v4i32 (AArch64duplane32
9663                                                  (v4i32 V128:$Rm),
9664                                                  VectorIndexS:$idx)))),
9665                                (i64 0))))),
9666             (EXTRACT_SUBREG
9667                 (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
9668                          (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
9669                                                FPR32Op:$Rd,
9670                                                ssub)),
9671                          V128:$Rn,
9672                          V128:$Rm,
9673                          VectorIndexS:$idx)),
9674                 ssub)>;
9675
9676   def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
9677                                         FPR16Op, FPR16Op, V128_lo,
9678                                         VectorIndexH, asm, ".h", "", "", ".h",
9679                                         []> {
9680     bits<3> idx;
9681     let Inst{11} = idx{2};
9682     let Inst{21} = idx{1};
9683     let Inst{20} = idx{0};
9684   }
9685
9686   def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
9687                                         FPR32Op, FPR32Op, V128, VectorIndexS,
9688                                         asm, ".s", "", "", ".s",
9689     [(set (i32 FPR32Op:$dst),
9690           (Accum (i32 FPR32Op:$Rd),
9691                  (i32 (int_aarch64_neon_sqrdmulh
9692                         (i32 FPR32Op:$Rn),
9693                         (i32 (vector_extract (v4i32 V128:$Rm),
9694                                              VectorIndexS:$idx))))))]> {
9695     bits<2> idx;
9696     let Inst{11} = idx{1};
9697     let Inst{21} = idx{0};
9698   }
9699 }
9700 } // let Predicates = [HasNeon, HasRDM]
9701
9702 //----------------------------------------------------------------------------
9703 // ARMv8.3 Complex ADD/MLA instructions
9704 //----------------------------------------------------------------------------
9705
9706 class ComplexRotationOperand<int Angle, int Remainder, string Type>
9707   : AsmOperandClass {
9708   let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
9709   let DiagnosticType = "InvalidComplexRotation" # Type;
9710   let Name = "ComplexRotation" # Type;
9711 }
9712 def complexrotateop : Operand<i32> {
9713   let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
9714   let PrintMethod = "printComplexRotationOp<90, 0>";
9715 }
9716 def complexrotateopodd : Operand<i32> {
9717   let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
9718   let PrintMethod = "printComplexRotationOp<180, 90>";
9719 }
9720
9721 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9722 class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
9723                                      RegisterOperand regtype, Operand rottype,
9724                                      string asm, string kind, list<dag> pattern>
9725   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
9726       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
9727       "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
9728     Sched<[WriteV]> {
9729   bits<5> Rd;
9730   bits<5> Rn;
9731   bits<5> Rm;
9732   bits<1> rot;
9733   let Inst{31}    = 0;
9734   let Inst{30}    = Q;
9735   let Inst{29}    = U;
9736   let Inst{28-24} = 0b01110;
9737   let Inst{23-22} = size;
9738   let Inst{21}    = 0;
9739   let Inst{20-16} = Rm;
9740   let Inst{15-13} = opcode;
9741   // Non-tied version (FCADD) only has one rotation bit
9742   let Inst{12}    = rot;
9743   let Inst{11}    = 0;
9744   let Inst{10}    = 1;
9745   let Inst{9-5}   = Rn;
9746   let Inst{4-0}   = Rd;
9747 }
9748
9749 multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
9750                                           string asm, SDPatternOperator OpNode>{
9751   let Predicates = [HasV8_3a, HasNEON, HasFullFP16] in {
9752   def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
9753               asm, ".4h",
9754               [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
9755                                               (v4f16 V64:$Rn),
9756                                               (v4f16 V64:$Rm),
9757                                               (rottype i32:$rot)))]>;
9758
9759   def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
9760               asm, ".8h",
9761               [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
9762                                                (v8f16 V128:$Rn),
9763                                                (v8f16 V128:$Rm),
9764                                                (rottype i32:$rot)))]>;
9765   }
9766
9767   let Predicates = [HasV8_3a, HasNEON] in {
9768   def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
9769               asm, ".2s",
9770               [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
9771                                               (v2f32 V64:$Rn),
9772                                               (v2f32 V64:$Rm),
9773                                               (rottype i32:$rot)))]>;
9774
9775   def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
9776               asm, ".4s",
9777               [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
9778                                                (v4f32 V128:$Rn),
9779                                                (v4f32 V128:$Rm),
9780                                                (rottype i32:$rot)))]>;
9781
9782   def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
9783               asm, ".2d",
9784               [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
9785                                                (v2f64 V128:$Rn),
9786                                                (v2f64 V128:$Rm),
9787                                                (rottype i32:$rot)))]>;
9788   }
9789 }
9790
9791 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9792 class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
9793                                          bits<3> opcode,
9794                                          RegisterOperand regtype,
9795                                          Operand rottype, string asm,
9796                                          string kind, list<dag> pattern>
9797   : I<(outs regtype:$dst),
9798       (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
9799       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
9800       "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
9801     Sched<[WriteV]> {
9802   bits<5> Rd;
9803   bits<5> Rn;
9804   bits<5> Rm;
9805   bits<2> rot;
9806   let Inst{31}    = 0;
9807   let Inst{30}    = Q;
9808   let Inst{29}    = U;
9809   let Inst{28-24} = 0b01110;
9810   let Inst{23-22} = size;
9811   let Inst{21}    = 0;
9812   let Inst{20-16} = Rm;
9813   let Inst{15-13} = opcode;
9814   let Inst{12-11} = rot;
9815   let Inst{10}    = 1;
9816   let Inst{9-5}   = Rn;
9817   let Inst{4-0}   = Rd;
9818 }
9819
9820 multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
9821                                              Operand rottype, string asm,
9822                                              SDPatternOperator OpNode> {
9823   let Predicates = [HasV8_3a, HasNEON, HasFullFP16] in {
9824   def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
9825               rottype, asm, ".4h",
9826               [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
9827                                               (v4f16 V64:$Rn),
9828                                               (v4f16 V64:$Rm),
9829                                               (rottype i32:$rot)))]>;
9830
9831   def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
9832               rottype, asm, ".8h",
9833               [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
9834                                                (v8f16 V128:$Rn),
9835                                                (v8f16 V128:$Rm),
9836                                                (rottype i32:$rot)))]>;
9837   }
9838
9839   let Predicates = [HasV8_3a, HasNEON] in {
9840   def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
9841               rottype, asm, ".2s",
9842               [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
9843                                               (v2f32 V64:$Rn),
9844                                               (v2f32 V64:$Rm),
9845                                               (rottype i32:$rot)))]>;
9846
9847   def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
9848               rottype, asm, ".4s",
9849               [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
9850                                                (v4f32 V128:$Rn),
9851                                                (v4f32 V128:$Rm),
9852                                                (rottype i32:$rot)))]>;
9853
9854   def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
9855               rottype, asm, ".2d",
9856               [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
9857                                                (v2f64 V128:$Rn),
9858                                                (v2f64 V128:$Rm),
9859                                                (rottype i32:$rot)))]>;
9860   }
9861 }
9862
9863 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9864 class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
9865                                  bit opc1, bit opc2, RegisterOperand dst_reg,
9866                                  RegisterOperand lhs_reg,
9867                                  RegisterOperand rhs_reg, Operand vec_idx,
9868                                  Operand rottype, string asm, string apple_kind,
9869                                  string dst_kind, string lhs_kind,
9870                                  string rhs_kind, list<dag> pattern>
9871   : I<(outs dst_reg:$dst),
9872       (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
9873       asm,
9874       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
9875       "$idx, $rot" # "|" # apple_kind #
9876       "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
9877     Sched<[WriteV]> {
9878   bits<5> Rd;
9879   bits<5> Rn;
9880   bits<5> Rm;
9881   bits<2> rot;
9882
9883   let Inst{31}    = 0;
9884   let Inst{30}    = Q;
9885   let Inst{29}    = U;
9886   let Inst{28}    = Scalar;
9887   let Inst{27-24} = 0b1111;
9888   let Inst{23-22} = size;
9889   // Bit 21 must be set by the derived class.
9890   let Inst{20-16} = Rm;
9891   let Inst{15}    = opc1;
9892   let Inst{14-13} = rot;
9893   let Inst{12}    = opc2;
9894   // Bit 11 must be set by the derived class.
9895   let Inst{10}    = 0;
9896   let Inst{9-5}   = Rn;
9897   let Inst{4-0}   = Rd;
9898 }
9899
9900 // The complex instructions index by pairs of elements, so the VectorIndexes
9901 // don't match the lane types, and the index bits are different to the other
9902 // classes.
9903 multiclass SIMDIndexedTiedComplexHSD<bit U, bit opc1, bit opc2, Operand rottype,
9904                                      string asm, SDPatternOperator OpNode> {
9905   let Predicates = [HasV8_3a,HasNEON,HasFullFP16] in {
9906   def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
9907                       V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
9908                       ".4h", ".h", []> {
9909     bits<1> idx;
9910     let Inst{11} = 0;
9911     let Inst{21} = idx{0};
9912   }
9913
9914   def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
9915                       V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
9916                       ".8h", ".8h", ".h", []> {
9917     bits<2> idx;
9918     let Inst{11} = idx{1};
9919     let Inst{21} = idx{0};
9920   }
9921   } // Predicates = [HasV8_3a,HasNEON,HasFullFP16]
9922
9923   let Predicates = [HasV8_3a,HasNEON] in {
9924   def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
9925                       V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
9926                       ".4s", ".4s", ".s", []> {
9927     bits<1> idx;
9928     let Inst{11} = idx{0};
9929     let Inst{21} = 0;
9930   }
9931   } // Predicates = [HasV8_3a,HasNEON]
9932 }
9933
9934 //----------------------------------------------------------------------------
9935 // Crypto extensions
9936 //----------------------------------------------------------------------------
9937
9938 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9939 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
9940               list<dag> pat>
9941   : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
9942     Sched<[WriteV]>{
9943   bits<5> Rd;
9944   bits<5> Rn;
9945   let Inst{31-16} = 0b0100111000101000;
9946   let Inst{15-12} = opc;
9947   let Inst{11-10} = 0b10;
9948   let Inst{9-5}   = Rn;
9949   let Inst{4-0}   = Rd;
9950 }
9951
9952 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
9953   : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
9954             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
9955
9956 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
9957   : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
9958             "$Rd = $dst",
9959             [(set (v16i8 V128:$dst),
9960                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
9961
9962 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9963 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
9964                      dag oops, dag iops, list<dag> pat>
9965   : I<oops, iops, asm,
9966       "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
9967       "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
9968     Sched<[WriteV]>{
9969   bits<5> Rd;
9970   bits<5> Rn;
9971   bits<5> Rm;
9972   let Inst{31-21} = 0b01011110000;
9973   let Inst{20-16} = Rm;
9974   let Inst{15}    = 0;
9975   let Inst{14-12} = opc;
9976   let Inst{11-10} = 0b00;
9977   let Inst{9-5}   = Rn;
9978   let Inst{4-0}   = Rd;
9979 }
9980
9981 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
9982   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
9983                    (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
9984                    [(set (v4i32 FPR128:$dst),
9985                          (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
9986                                  (v4i32 V128:$Rm)))]>;
9987
9988 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
9989   : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
9990                    (ins V128:$Rd, V128:$Rn, V128:$Rm),
9991                    [(set (v4i32 V128:$dst),
9992                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9993                                  (v4i32 V128:$Rm)))]>;
9994
9995 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
9996   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
9997                    (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
9998                    [(set (v4i32 FPR128:$dst),
9999                          (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
10000                                  (v4i32 V128:$Rm)))]>;
10001
10002 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10003 class SHA2OpInst<bits<4> opc, string asm, string kind,
10004                  string cstr, dag oops, dag iops,
10005                  list<dag> pat>
10006   : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
10007                        "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
10008     Sched<[WriteV]>{
10009   bits<5> Rd;
10010   bits<5> Rn;
10011   let Inst{31-16} = 0b0101111000101000;
10012   let Inst{15-12} = opc;
10013   let Inst{11-10} = 0b10;
10014   let Inst{9-5}   = Rn;
10015   let Inst{4-0}   = Rd;
10016 }
10017
10018 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
10019   : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
10020                (ins V128:$Rd, V128:$Rn),
10021                [(set (v4i32 V128:$dst),
10022                      (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
10023
10024 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
10025   : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
10026                [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
10027
10028 // Armv8.2-A Crypto extensions
10029 class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
10030                     list<dag> pattern>
10031   : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteV]> {
10032   bits<5> Vd;
10033   bits<5> Vn;
10034   let Inst{31-25} = 0b1100111;
10035   let Inst{9-5}   = Vn;
10036   let Inst{4-0}   = Vd;
10037 }
10038
10039 class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
10040   : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm, asmops,
10041                   "$Vm = $Vd", []> {
10042   let Inst{31-25} = 0b1100111;
10043   let Inst{24-21} = 0b0110;
10044   let Inst{20-15} = 0b000001;
10045   let Inst{14}    = op0;
10046   let Inst{13-12} = 0b00;
10047   let Inst{11-10} = op1;
10048 }
10049 class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
10050   : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d}">;
10051 class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
10052   : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s}">;
10053
10054 class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
10055                 string asmops, string cst>
10056   : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
10057   bits<5> Vm;
10058   let Inst{24-21} = 0b0011;
10059   let Inst{20-16} = Vm;
10060   let Inst{15}    = 0b1;
10061   let Inst{14}    = op0;
10062   let Inst{13-12} = 0b00;
10063   let Inst{11-10} = op1;
10064 }
10065 class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
10066   : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10067               "{\t$Vd.2d, $Vn.2d, $Vm.2d}", "">;
10068 class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
10069   : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10070               "{\t$Vd.2d, $Vn.2d, $Vm.2d}", "$Vd = $Vdst">;
10071 class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
10072   : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10073               "{\t$Vd.4s, $Vn.4s, $Vm.4s}", "">;
10074 class CryptoRRRTied_4S<bits<1> op0, bits<2>op1, string asm>
10075   : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10076               "{\t$Vd.4s, $Vn.4s, $Vm.4s}", "$Vd = $Vdst">;
10077 class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
10078   : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
10079               asm, "{\t$Vd, $Vn, $Vm.2d}", "$Vd = $Vdst">;
10080
10081 class CryptoRRRR<bits<2>op0, string asm, string asmops>
10082   : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
10083                   asmops, "", []> {
10084   bits<5> Vm;
10085   bits<5> Va;
10086   let Inst{24-23} = 0b00;
10087   let Inst{22-21} = op0;
10088   let Inst{20-16} = Vm;
10089   let Inst{15}    = 0b0;
10090   let Inst{14-10} = Va;
10091 }
10092 class CryptoRRRR_16B<bits<2>op0, string asm>
10093  : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b}"> {
10094 }
10095 class CryptoRRRR_4S<bits<2>op0, string asm>
10096  : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s}"> {
10097 }
10098
10099 class CryptoRRRi6<string asm>
10100   : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
10101                   "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm}", "", []> {
10102   bits<6> imm;
10103   bits<5> Vm;
10104   let Inst{24-21} = 0b0100;
10105   let Inst{20-16} = Vm;
10106   let Inst{15-10} = imm;
10107   let Inst{9-5}   = Vn;
10108   let Inst{4-0}   = Vd;
10109 }
10110
10111 class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
10112   : BaseCryptoV82<(outs V128:$Vdst),
10113                   (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
10114                   asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm}", "$Vd = $Vdst", []> {
10115   bits<2> imm;
10116   bits<5> Vm;
10117   let Inst{24-21} = 0b0010;
10118   let Inst{20-16} = Vm;
10119   let Inst{15}    = 0b1;
10120   let Inst{14}    = op0;
10121   let Inst{13-12} = imm;
10122   let Inst{11-10} = op1;
10123 }
10124
10125 //----------------------------------------------------------------------------
10126 // v8.1 atomic instructions extension:
10127 // * CAS
10128 // * CASP
10129 // * SWP
10130 // * LDOPregister<OP>, and aliases STOPregister<OP>
10131
10132 // Instruction encodings:
10133 //
10134 //      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
10135 // CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
10136 // CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
10137 // SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
10138 // LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
10139 // ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
10140
10141 // Instruction syntax:
10142 //
10143 // CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10144 // CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
10145 // CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
10146 // CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
10147 // SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10148 // SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
10149 // LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10150 // LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
10151 // ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
10152 // ST<OP>{<order>} <Xs>, [<Xn|SP>]
10153
10154 let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
10155 class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
10156                       string cstr, list<dag> pattern>
10157       : I<oops, iops, asm, operands, cstr, pattern> {
10158   bits<2> Sz;
10159   bit NP;
10160   bit Acq;
10161   bit Rel;
10162   bits<5> Rs;
10163   bits<5> Rn;
10164   bits<5> Rt;
10165   let Inst{31-30} = Sz;
10166   let Inst{29-24} = 0b001000;
10167   let Inst{23} = NP;
10168   let Inst{22} = Acq;
10169   let Inst{21} = 0b1;
10170   let Inst{20-16} = Rs;
10171   let Inst{15} = Rel;
10172   let Inst{14-10} = 0b11111;
10173   let Inst{9-5} = Rn;
10174   let Inst{4-0} = Rt;
10175   let Predicates = [HasLSE];
10176 }
10177
10178 class BaseCAS<string order, string size, RegisterClass RC>
10179       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
10180                         "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
10181                         "$out = $Rs",[]>,
10182         Sched<[WriteAtomic]> {
10183   let NP = 1;
10184 }
10185
10186 multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
10187   let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
10188   let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
10189   let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
10190   let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
10191 }
10192
10193 class BaseCASP<string order, string size, RegisterOperand RC>
10194       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
10195                         "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
10196                         "$out = $Rs",[]>,
10197         Sched<[WriteAtomic]> {
10198   let NP = 0;
10199 }
10200
10201 multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
10202   let Sz = 0b00, Acq = Acq, Rel = Rel in
10203     def W : BaseCASP<order, "", WSeqPairClassOperand>;
10204   let Sz = 0b01, Acq = Acq, Rel = Rel in
10205     def X : BaseCASP<order, "", XSeqPairClassOperand>;
10206 }
10207
10208 let Predicates = [HasLSE] in
10209 class BaseSWP<string order, string size, RegisterClass RC>
10210       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
10211           "\t$Rs, $Rt, [$Rn]","",[]>,
10212         Sched<[WriteAtomic]> {
10213   bits<2> Sz;
10214   bit Acq;
10215   bit Rel;
10216   bits<5> Rs;
10217   bits<3> opc = 0b000;
10218   bits<5> Rn;
10219   bits<5> Rt;
10220   let Inst{31-30} = Sz;
10221   let Inst{29-24} = 0b111000;
10222   let Inst{23} = Acq;
10223   let Inst{22} = Rel;
10224   let Inst{21} = 0b1;
10225   let Inst{20-16} = Rs;
10226   let Inst{15} = 0b1;
10227   let Inst{14-12} = opc;
10228   let Inst{11-10} = 0b00;
10229   let Inst{9-5} = Rn;
10230   let Inst{4-0} = Rt;
10231   let Predicates = [HasLSE];
10232 }
10233
10234 multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
10235   let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
10236   let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
10237   let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
10238   let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
10239 }
10240
10241 let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
10242 class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
10243       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
10244           "\t$Rs, $Rt, [$Rn]","",[]>,
10245         Sched<[WriteAtomic]> {
10246   bits<2> Sz;
10247   bit Acq;
10248   bit Rel;
10249   bits<5> Rs;
10250   bits<3> opc;
10251   bits<5> Rn;
10252   bits<5> Rt;
10253   let Inst{31-30} = Sz;
10254   let Inst{29-24} = 0b111000;
10255   let Inst{23} = Acq;
10256   let Inst{22} = Rel;
10257   let Inst{21} = 0b1;
10258   let Inst{20-16} = Rs;
10259   let Inst{15} = 0b0;
10260   let Inst{14-12} = opc;
10261   let Inst{11-10} = 0b00;
10262   let Inst{9-5} = Rn;
10263   let Inst{4-0} = Rt;
10264   let Predicates = [HasLSE];
10265 }
10266
10267 multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
10268                         string order> {
10269   let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
10270     def B : BaseLDOPregister<op, order, "b", GPR32>;
10271   let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
10272     def H : BaseLDOPregister<op, order, "h", GPR32>;
10273   let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
10274     def W : BaseLDOPregister<op, order, "", GPR32>;
10275   let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
10276     def X : BaseLDOPregister<op, order, "", GPR64>;
10277 }
10278
10279 // Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
10280 // complex DAG for DstRHS.
10281 let Predicates = [HasLSE] in
10282 multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
10283                                          string size, dag SrcRHS, dag DstRHS> {
10284   def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
10285             (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
10286   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
10287             (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
10288   def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
10289             (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
10290   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
10291             (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
10292   def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
10293             (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
10294 }
10295
10296 multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
10297                                      string size, dag RHS> {
10298   defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, RHS, RHS>;
10299 }
10300
10301 multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
10302                                          string size, dag LHS, dag RHS> {
10303   defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, LHS, RHS>;
10304 }
10305
10306 multiclass LDOPregister_patterns<string inst, string op> {
10307   defm : LDOPregister_patterns_ord<inst, "X", op, "64", (i64 GPR64:$Rm)>;
10308   defm : LDOPregister_patterns_ord<inst, "W", op, "32", (i32 GPR32:$Rm)>;
10309   defm : LDOPregister_patterns_ord<inst, "H", op, "16", (i32 GPR32:$Rm)>;
10310   defm : LDOPregister_patterns_ord<inst, "B", op, "8",  (i32 GPR32:$Rm)>;
10311 }
10312
10313 multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
10314   defm : LDOPregister_patterns_ord_mod<inst, "X", op, "64",
10315                         (i64 GPR64:$Rm),
10316                         (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
10317   defm : LDOPregister_patterns_ord_mod<inst, "W", op, "32",
10318                         (i32 GPR32:$Rm),
10319                         (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10320   defm : LDOPregister_patterns_ord_mod<inst, "H", op, "16",
10321                         (i32 GPR32:$Rm),
10322                         (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10323   defm : LDOPregister_patterns_ord_mod<inst, "B", op, "8",
10324                         (i32 GPR32:$Rm),
10325                         (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10326 }
10327
10328 let Predicates = [HasLSE] in
10329 multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
10330                                         string size, dag OLD, dag NEW> {
10331   def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
10332             (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
10333   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
10334             (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10335   def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
10336             (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10337   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
10338             (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10339   def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
10340             (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10341 }
10342
10343 multiclass CASregister_patterns_ord<string inst, string suffix, string op,
10344                                     string size, dag OLD, dag NEW> {
10345   defm : CASregister_patterns_ord_dag<inst, suffix, op, size, OLD, NEW>;
10346 }
10347
10348 multiclass CASregister_patterns<string inst, string op> {
10349   defm : CASregister_patterns_ord<inst, "X", op, "64",
10350                         (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
10351   defm : CASregister_patterns_ord<inst, "W", op, "32",
10352                         (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10353   defm : CASregister_patterns_ord<inst, "H", op, "16",
10354                         (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10355   defm : CASregister_patterns_ord<inst, "B", op, "8",
10356                         (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10357 }
10358
10359 let Predicates = [HasLSE] in
10360 class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
10361                         Instruction inst> :
10362       InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
10363
10364 multiclass STOPregister<string asm, string instr> {
10365   def : BaseSTOPregister<asm # "lb", GPR32, WZR,
10366                     !cast<Instruction>(instr # "LB")>;
10367   def : BaseSTOPregister<asm # "lh", GPR32, WZR,
10368                     !cast<Instruction>(instr # "LH")>;
10369   def : BaseSTOPregister<asm # "l",  GPR32, WZR,
10370                     !cast<Instruction>(instr # "LW")>;
10371   def : BaseSTOPregister<asm # "l",  GPR64, XZR,
10372                     !cast<Instruction>(instr # "LX")>;
10373   def : BaseSTOPregister<asm # "b",  GPR32, WZR,
10374                     !cast<Instruction>(instr # "B")>;
10375   def : BaseSTOPregister<asm # "h",  GPR32, WZR,
10376                     !cast<Instruction>(instr # "H")>;
10377   def : BaseSTOPregister<asm,        GPR32, WZR,
10378                     !cast<Instruction>(instr # "W")>;
10379   def : BaseSTOPregister<asm,        GPR64, XZR,
10380                     !cast<Instruction>(instr # "X")>;
10381 }
10382
10383 //----------------------------------------------------------------------------
10384 // Allow the size specifier tokens to be upper case, not just lower.
10385 def : TokenAlias<".4B", ".4b">;  // Add dot product
10386 def : TokenAlias<".8B", ".8b">;
10387 def : TokenAlias<".4H", ".4h">;
10388 def : TokenAlias<".2S", ".2s">;
10389 def : TokenAlias<".1D", ".1d">;
10390 def : TokenAlias<".16B", ".16b">;
10391 def : TokenAlias<".8H", ".8h">;
10392 def : TokenAlias<".4S", ".4s">;
10393 def : TokenAlias<".2D", ".2d">;
10394 def : TokenAlias<".1Q", ".1q">;
10395 def : TokenAlias<".2H", ".2h">;
10396 def : TokenAlias<".B", ".b">;
10397 def : TokenAlias<".H", ".h">;
10398 def : TokenAlias<".S", ".s">;
10399 def : TokenAlias<".D", ".d">;
10400 def : TokenAlias<".Q", ".q">;